Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/CeeblueTV/wrts-client/llms.txt

Use this file to discover all available pages before exploring further.

HTTPAdaptiveSource is the default streaming source in the @ceeblue/wrts-client library. It uses HTTP/2 pull-based delivery and implements a full adaptive bitrate (MBR) algorithm across multiple parallel download channels — automatically switching video renditions up or down based on measured bandwidth. It is automatically selected by the Player whenever the endpoint URL starts with https:// or http://.

Import

import { HTTPAdaptiveSource } from '@ceeblue/wrts-client';

Registration

HTTPAdaptiveSource is registered via the @Source.registerClass('https', 'http') decorator. The Player calls Source.getClass(protocol) at startup and selects this implementation automatically for any https:// or http:// endpoint — no explicit configuration is required.
// HTTPAdaptiveSource is used automatically
const player = new Player(videoElement);
player.start({ endPoint: 'https://example.com/wrts/out+<id>/index.json' });

Constructor

constructor(playing: IPlaying, params: Connect.Params)
Creates a new HTTPAdaptiveSource for the given playback context. Internally calls super(playing, 'https', params) with the default Connect.Type.WRTS connection type. Three AbortController instances are provisioned immediately — _reliableController, _skippableController, and _alterableController — for the three channel types used during download. All controllers are wired to playing.signal so they abort automatically when playback stops.
playing
IPlaying
required
The playback context providing buffer state, stall events, resolution limits, and the stop signal.
params
Connect.Params
required
Connection parameters including endPoint, streamName, mediaExt, and optional query parameters.

How It Works

Manifest Fetch

On startup, HTTPAdaptiveSource fetches index.json from the server. If the URL path does not already end in .json, the source rewrites it — stripping the existing extension and appending /index.json. The manifest provides:
  • Sequence pattern (sequence.pattern) — a URL template used to construct per-sequence download URLs, e.g. {trackIds}/{sequenceId}.rts.
  • Track separator (sequence.trackSeparator) — character used to join multiple track IDs in a combined URL (default: -).
  • Current sequence ID and time (sequence.current.id, sequence.current.time) — used to compute how many sequences to pre-load into the buffer before live playback begins.
  • Live time (metadata.liveTime) — corrected immediately using half the measured RTT of the manifest request.
The manifest endpoint must be a .json URL. If you provide a non-JSON path (e.g. /wrts/out+<id>/stream.rts), the source automatically rewrites it to /wrts/out+<id>/stream/index.json.

Download Channel Model

After the manifest is parsed, HTTPAdaptiveSource enters a sequence-download loop. Each iteration dispatches up to three parallel download channels, each managed by its own AbortController:
ChannelControllerAssigned tracksAbort behavior
alterable_alterableControllerVideo in the lowest available renditionAborted on stall or buffer loss; supports key-frame-only fallback
skippable_skippableControllerAudio and video in non-lowest renditionsAborted on stall; sequence is skipped on abort
reliable_reliableControllerAll tracks when reliable=trueNever aborted; retried until successful
Track assignment per channel depends on the reliable flag and the rendition level:
  • When reliable=true — all audio and video tracks go to the reliable channel.
  • When reliable=false and the video track has a lower rendition available — video goes to skippable.
  • When reliable=false and the video is already at the lowest rendition — video goes to alterable.
By default, tracks are combined into a single request per channel to minimise connection overhead. Set player.tracksCombinable = false if you need audio and video to be fetched in separate requests — for example, when using passthrough CMAF mode.

Adaptive Bitrate Algorithm

HTTPAdaptiveSource measures bandwidth continuously via recvByteRate and adjusts the video rendition each sequence iteration:
  • Downgrade: triggered when a stall occurs (playing.onStall), when the alterable controller is aborted, or when BufferState.LOW is reached without a bandwidth measurement. The source walks the videoTrack.down chain until bandwidth consumption fits within the measured rate, then calls adaptiveRetry.raise() to back off UP attempts.
  • Upgrade (UP emulation): when adaptiveRetry.try() returns true, a speculative GET request is fired in parallel against the next higher rendition (videoTrack.up) using _upController. If the download completes without being aborted, the track switches UP on the next iteration. If it is aborted (e.g. by a stall), adaptiveRetry.raise() is called and the delay before the next UP attempt increases.
  • Screen resolution cap: after any rendition decision, the source also walks videoTrack.down while Media.overScreenSize(videoTrack.resolution, playing.maximumResolution) is true — ensuring the selected rendition never exceeds the display’s physical resolution.

Sequence Skipping

When reliable=false, BufferState is LOW, and playing.buffering is true (i.e. a stall has occurred and the buffer is refilling), the source calculates how many sequences to skip in order to catch up to live. The calculation uses the max-sequence-duration header returned by sequence responses. If the header is absent, skip recovery is disabled and an error is logged. For each candidate skip target, a HEAD request is issued to verify the sequence exists. On success, the source logs the skip range and advances the sequence counter.

Key-Frame-Only Download (Alterable Channel)

When the buffer is LOW and not yet buffering (i.e. currently draining), and the alterable channel is active, HTTPAdaptiveSource issues a HEAD request for the current sequence to read the first-sample-length response header. If present, it then fetches only that many bytes (Range: bytes=0-N) — delivering only the key frame. Once the key frame is received, the transfer is intentionally left open but no further data is processed, and the sample’s duration is stretched to cover the full sequence duration using skipVideo().

CMCD Support

HTTPAdaptiveSource is the only source implementation that supports CMCD (Common Media Client Data) telemetry. CMCD data is attached to every fetchMedia() call.
cmcd
CMCD
Controls the level of CMCD telemetry included with each media request. Inherited from ICMCD.
ValueDescription
CMCD.NONECMCD disabled (default)
CMCD.SHORTCore metrics only (bl, br, mtp, rtp, tb)
CMCD.FULLAll CMCD fields including cid, dl, ot, st
cmcdMode
CMCDMode
Delivery method for CMCD data. CMCDMode.HEADER (default) sends data in HTTP request headers; CMCDMode.QUERY appends it as a query-string parameter.
cmcdSid
string
Optional CMCD session ID string. Passed through in every CMCD payload.
import { Player, HTTPAdaptiveSource, CMCD, CMCDMode } from '@ceeblue/wrts-client';

const player = new Player(videoElement, HTTPAdaptiveSource);
player.cmcd = CMCD.FULL;
player.cmcdMode = CMCDMode.QUERY;
player.cmcdSid = 'session-abc-123';
player.start({ endPoint: 'https://example.com/wrts/out+<id>/index.json' });

Track Selection

HTTPAdaptiveSource overrides setTracks() to allow dynamic track selection. Track changes are applied internally within the play() loop — the source checks videoSelected and audioSelected at the start of each sequence iteration to determine the requested tracks. The trackSelectable property inherited from Source returns true for this class, meaning callers can safely invoke player.videoTrack = id or player.audioTrack = id at runtime.

Inherited Properties

Key properties inherited from Source relevant to HTTPAdaptiveSource:
reliable
boolean
When true, all tracks are assigned to the reliable channel and no sequences are ever skipped. Defaults to false. Calling setReliability() on HTTPAdaptiveSource is a no-op — reliability is changed by setting player.reliable before or during playback.
trackSelectable
boolean
Always true for HTTPAdaptiveSource — the source supports setTracks().
recvByteRate
ByteRate
Running average of total bytes received per second, sampled per GOP. Used by the MBR algorithm to determine safe rendition levels.
videoTrack
number | undefined
Index of the currently active video track. undefined on startup; -1 if video is disabled.
videoSelected
number | undefined
Index of the manually selected video track. When undefined, automatic MBR selection is active.

Usage Example

import { Player, HTTPAdaptiveSource } from '@ceeblue/wrts-client';

// Explicit class — identical to the default when using an https:// endpoint
const player = new Player(videoElement, HTTPAdaptiveSource);

player.onMetadata = (metadata) => {
  console.log('Available video tracks:', metadata.videoTracks);
  // Optionally return initial track selection
  return { video: metadata.videoTracks[0].id };
};

player.start({ endPoint: 'https://example.com/wrts/out+<id>/index.json' });
import { Player, HTTPAdaptiveSource, CMCD } from '@ceeblue/wrts-client';

const player = new Player(videoElement, HTTPAdaptiveSource);
player.cmcd = CMCD.FULL;
player.start({ endPoint: 'https://example.com/wrts/out+<id>/index.json' });

Build docs developers (and LLMs) love