Readonly
announcedTrack namespaces this client has successfully announced (received ANNOUNCE_OK). Source of truth for deciding what to UNANNOUNCE on teardown or targeted withdrawal.(future optimization: prefix trie).
Outgoing / incoming control message bidirectional stream wrapper.
Optional
controlTimeout (ms) for control stream read operations; undefined => no explicit timeout.
Optional
dataTimeout (ms) applied to reading incoming data streams; undefined => no explicit timeout.
Optional
maxOptional highest request id allowed (enforced externally / via configuration).
Optional
onInvoked for each decoded data object/header arriving on a uni stream (fetch or subgroup). Use to process or display incoming media/data. Informational event.
Optional
onInvoked after enqueuing each outbound data object/header. Reserved for future use. Informational event.
Optional
onGeneral-purpose error callback for surfaced exceptions not thrown to caller synchronously. Use to log or display errors. Error handler.
Optional
onFired on GOAWAY reception signaling graceful session wind-down. Use to prepare for disconnect or cleanup. Lifecycle handler.
Optional
onInvoked upon receiving each inbound control message before handling. Use for logging or debugging. Informational event.
Optional
onInvoked after each outbound control message is sent. Use for logging or analytics. Informational event.
Optional
onFired exactly once when the client transitions to terminated (disconnect). Use to clean up resources or notify user. Lifecycle handler.
Optional
onFired when an ANNOUNCE control message is processed for a track namespace. Use to update UI or trigger discovery logic. Discovery event.
Optional
onFired when an UNANNOUNCE control message is processed for a namespace. Use to remove tracks from UI or stop discovery. Discovery event.
Optional
onFired if the underlying WebTransport session fails (ready → closed prematurely). Use to log or alert on transport errors. Lifecycle/error handler.
Readonly
peerNamespace prefixes (tuples) the peer has requested announce notifications for via SUBSCRIBE_ANNOUNCES. Used to decide which locally issued ANNOUNCE messages should be forwarded (future optimization: prefix trie).
Readonly
publicationsActive publications (SUBSCRIBE or FETCH) keyed by requestId to manage object stream controllers and lifecycle.
Subset / specialization view of requests
.
Readonly
requestsAll in‑flight request objects keyed by requestId (SUBSCRIBE, FETCH, ANNOUNCE, etc). Facilitates lookup when responses / data arrive. Entries are removed on completion or error.
Readonly
subscribedNamespace prefixes this client has subscribed to (issued SUBSCRIBE_ANNOUNCES). Enables automatic filtering of incoming ANNOUNCE / UNANNOUNCE. Maintained locally; no dedupe of overlapping / shadowing prefixes yet.
Readonly
subscriptionsActive SUBSCRIBE request wrappers keyed by track alias for rapid alias -> subscription resolution during incoming unidirectional data handling.
Readonly
trackBidirectional alias <-> full track name mapping to reconstruct metadata for incoming objects that reference aliases only.
Readonly
trackLocally registered track definitions keyed by full track name string. Populated via addOrUpdateTrack. Does not imply the track has been announced or has active publications.
Underlying WebTransport session (set after successful construction in MOQtailClient.new).
Gets the current server setup configuration.
The ServerSetup instance associated with this client.
Registers or updates a Track definition for local publishing or serving.
A Track describes a logical media/data stream, identified by a unique name and namespace.
trackSource.live
is present, the track can be served to subscribers in real-time.trackSource.past
is present, the track can be fetched for historical data.The Track instance to add or update. See TrackSource for live/past source options.
void
: MOQtailError If the client has been destroyed.
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const videoTrack = stream.getVideoTracks()[0];
// Convert video frames to MoqtObject instances using your chosen scheme (e.g. WARP, CMAF, etc.)
// This part is application-specific and not provided by MOQtail:
const liveReadableStream: ReadableStream<MoqtObject> = ...
// Register the track for live subscription
client.addOrUpdateTrack({
fullTrackName: { namespace: ["camera"], name: "main" },
forwardingPreference: ObjectForwardingPreference.Latest,
trackSource: { live: liveReadableStream },
publisherPriority: 0 // highest priority
});
// For a hybrid track (live + past):
import { MemoryObjectCache } from './track/object_cache';
const cache = new MemoryObjectCache(); // Caches are not yet fully supported
client.addOrUpdateTrack({
fullTrackName: { namespace: ["camera"], name: "main" },
forwardingPreference: ObjectForwardingPreference.Latest,
trackSource: { live: liveReadableStream, past: cache },
publisherPriority: 8
});
Declare (publish) a track namespace to the peer so subscribers using matching prefixes (via MOQtailClient.subscribeAnnounces) can discover and begin subscribing/fetching its tracks.
Typical flow (publisher side):
announce(namespace)
once per namespace prefix to expose those tracks.Parameter semantics:
Returns: AnnounceOk on success (namespace added to announcedNamespaces
) or AnnounceError explaining refusal.
Use cases:
Optional
parameters: VersionSpecificParametersInternalError Transport/control failure while sending or awaiting response (client disconnects first).
announcedNamespaces
; manual removal occurs via MOQtailClient.unannounce.Send an AnnounceCancel to abort a previously issued ANNOUNCE before (or after) the peer fully processes it.
Use when an announce was sent prematurely (e.g. validation failed locally, namespace no longer needed) and you want to retract it without waiting for normal announce lifecycle or before publishing any objects.
Parameter semantics:
Behavior:
announcedNamespaces
(call MOQtailClient.unannounce for local bookkeeping removal).InternalError Wrapped transport/control send failure (client disconnects first) then rethrows.
Use in tandem with internal tracking if you want to prevent subsequent object publication until a new announce is issued.
const announceResp = await client.announce(["camera","temp"]) // wrong namespace
// Assume you kept the original announce requestId (e.g. from AnnounceRequest)
const cancelMsg = new AnnounceCancel(announceResp.requestId as bigint)
await client.announceCancel(cancelMsg)
Gracefully terminates this MOQtailClient session and releases underlying WebTransport resources.
Optional
reason: unknownOptional application-level reason (string or error) recorded and wrapped in an InternalError passed to the onSessionTerminated callback.
Promise that resolves once shutdown logic completes. Subsequent calls are safe no-ops.
One-shot retrieval of a bounded object span, optionally anchored to an existing subscription, returning a stream of MoqtObjects.
Choose a fetch type via typeAndProps.type
:
Field highlights (in FetchOptions):
Returns either a FetchError (refusal / invalid request at protocol level) or { requestId, stream }
whose stream
ends naturally after the bounded range completes (no explicit cancel needed for normal completion).
Use cases:
ProtocolViolationError Priority out of [0-255] or missing/invalid joining subscription id for Relative/Absolute.
InternalError Transport/control failure (the client disconnects first) then rethrows original error.
joiningRequestId
; if not found a ProtocolViolationError is thrown.const r = await client.fetch({
priority: 64,
groupOrder: GroupOrder.Original,
typeAndProps: {
type: FetchType.StandAlone,
props: { fullTrackName, startLocation, endLocation }
}
})
if (!(r instanceof FetchError)) {
for await (const obj of r.stream as any) {
// consume objects then stream ends automatically
}
}
const sub = await client.subscribe({ fullTrackName, filterType: FilterType.LatestObject, forward: true, groupOrder: GroupOrder.Original, priority: 0 })
if (!(sub instanceof SubscribeError)) {
const slice = await client.fetch({
priority: 32,
groupOrder: GroupOrder.Original,
typeAndProps: { type: FetchType.Relative, props: { joiningRequestId: sub.requestId, joiningStart: 0n } }
})
}
Request early termination of an in‑flight FETCH identified by its requestId
.
Use when the consumer no longer needs the remaining objects (user scrubbed away, UI panel closed, replaced by a new fetch). Sends a FetchCancel control frame if the id currently maps to an active fetch; otherwise silent no-op (idempotent).
Parameter semantics:
Current behavior / limitations:
Follow-up improvement planned: actively close associated readable stream controller immediately upon acknowledgment.
const r = await client.fetch({ priority: 32, groupOrder: GroupOrder.Original, typeAndProps: { type: FetchType.StandAlone, props: { fullTrackName, startLocation, endLocation } } })
if (!(r instanceof FetchError)) {
// user navigated away
await client.fetchCancel(r.requestId)
}
Removes a previously registered Track from this client's local catalog.
This deletes the in-memory entry inserted via MOQtailClient.addOrUpdateTrack, so future lookups by its Track.fullTrackName will fail. Does not automatically:
If the track was not present, the call is a silent no-op (idempotent removal).
: MOQtailError If the client has been destroyed.
Subscribes to a track and returns a stream of MoqtObjects matching the requested window and relay forwarding mode.
forward: true
tells the relay to forward objects to this subscriber as they arrive.forward: false
means the relay subscribes upstream but buffers objects locally, not forwarding them to you.filterType: AbsoluteStart
lets you specify a start position in the future; the stream waits for that object. If the start location is < the latest object
observed at the publisher then it behaves as filterType: LatestObject
filterType: AbsoluteRange
lets you specify a start and end group, both of should be in the future; the stream waits for those objects. If the start location is < the latest object
observed at the publisher then it behaves as filterType: LatestObject
.The method returns either a SubscribeError (on refusal) or an object with the subscription requestId
and a ReadableStream
of MoqtObjects.
Use the requestId
for MOQtailClient.unsubscribe or MOQtailClient.subscribeUpdate. Use the stream
to decode and display objects.
SubscribeOptions describing the subscription window and relay forwarding behavior.
Either a SubscribeError or { requestId, stream }
for consuming objects.
: MOQtailError If the client is destroyed.
: ProtocolViolationError If required fields are missing or inconsistent.
: InternalError On transport/protocol failure (disconnect is triggered before rethrow).
const result = await client.subscribe({
fullTrackName,
filterType: FilterType.LatestObject,
forward: true,
groupOrder: GroupOrder.Original,
priority: 32
});
if (!(result instanceof SubscribeError)) {
for await (const obj of result.stream) {
// decode and display obj
}
}
Narrows or updates an active subscription window and/or relay forwarding behavior.
Use this to:
forward: false
stops forwarding new objects, true
resumes).Only narrowing is allowed: you cannot move the start earlier or the end group later than the original subscription. Forwarding and priority can be changed at any time.
SubscribeUpdateOptions referencing the original subscription requestId
and new bounds.
Promise that resolves when the update control frame is sent.
:MOQtailError If the client is destroyed.
:ProtocolViolationError If the update would widen the window (earlier start, later end group, or invalid ordering).
:InternalError On transport/control failure (disconnect is triggered before rethrow).
priority
) leaves the previous value unchanged.forward: false
stops relay forwarding new objects after the current window drains.await client.subscribeUpdate({ requestId, startLocation: laterLoc, endGroup, forward: true, priority });
Optional
parameters: VersionSpecificParametersWithdraw a previously announced namespace so new subscribers no longer discover its tracks.
Use when shutting down publishing for a logical scope (camera offline, room closed, session ended).
Removes the namespace from announcedNamespaces
locally and sends an Unannounce control frame.
Parameter semantics:
Behavior:
trackSources
).(rethrows original error) Any lower-level failure while sending results in a disconnect (unwrapped TODO: future wrap with InternalError for consistency).
Peers that issued MOQtailClient.subscribeAnnounces for a matching prefix should receive the resulting Unannounce. Consider calling this before MOQtailClient.disconnect to give consumers prompt notice.
Stops an active subscription identified by its original SUBSCRIBE requestId
.
Sends an Unsubscribe control frame if the subscription is still active. If the id is unknown or already cleaned up, the call is a silent no-op (hence multiple calls are idempotent).
Use this when you no longer want incoming objects for a track (e.g. user navigated away, switching quality). Canceling the consumer stream reader does not auto-unsubscribe; call this explicitly for prompt cleanup.
The id returned from MOQtailClient.subscribe.
Promise that resolves when the unsubscribe control frame is sent.
:MOQtailError If the client is destroyed.
:InternalError Wrapped lower-level failure while attempting to send (session will be disconnected first).
Static
newEstablishes a new MOQtailClient session over WebTransport and performs the MOQT setup handshake.
Promise resolving to a ready MOQtailClient instance.
:ProtocolViolationError If the server sends an unexpected or invalid message during setup.
const client = await MOQtailClient.new({
url: 'https://relay.example.com/transport',
supportedVersions: [0xff00000b]
});
const client = await MOQtailClient.new({
url,
supportedVersions: [0xff00000b],
setupParameters: new SetupParameters().addMaxRequestId(1000),
transportOptions: { congestionControl: 'default' },
dataStreamTimeoutMs: 5000,
controlStreamTimeoutMs: 2000,
callbacks: {
onMessageSent: msg => console.log('Sent:', msg),
onMessageReceived: msg => console.log('Received:', msg),
onSessionTerminated: reason => console.warn('Session ended:', reason)
}
});
Represents a Media Over QUIC Transport (MOQT) client session.
Use MOQtailClient.new to establish a connection and perform MOQT operations such as subscribing to tracks, fetching historical data, announcing tracks for publication, and managing session lifecycle.
Once initialized, the client provides high-level methods for MOQT requests and publishing. If a protocol violation occurs, the client will terminate and must be re-initialized.
Usage
Connect and Subscribe to a Track
Announce a Track for Publishing
Graceful Shutdown