ReadonlyannouncedTrack namespaces this client has successfully announced (received ANNOUNCE_OK). Source of truth for deciding what to PUBLISH_NAMESPACE_DONE on teardown or targeted withdrawal.(future optimization: prefix trie).
Outgoing / incoming control message bidirectional stream wrapper.
OptionalcontrolTimeout (ms) for control stream read operations; undefined => no explicit timeout.
OptionaldataTimeout (ms) applied to reading incoming data streams; undefined => no explicit timeout.
OptionalmaxOptional highest request id allowed (enforced externally / via configuration).
OptionalonInvoked for each decoded data object/header arriving on a uni stream (fetch or subgroup). Use to process or display incoming media/data. Informational event.
OptionalonInvoked after enqueuing each outbound data object/header. Reserved for future use. Informational event.
OptionalonGeneral-purpose error callback for surfaced exceptions not thrown to caller synchronously. Use to log or display errors. Error handler.
OptionalonFired on GOAWAY reception signaling graceful session wind-down. Use to prepare for disconnect or cleanup. Lifecycle handler.
OptionalonInvoked upon receiving each inbound control message before handling. Use for logging or debugging. Informational event.
OptionalonInvoked after each outbound control message is sent. Use for logging or analytics. Informational event.
OptionalonFired when an PUBLISH_NAMESPACE_DONE control message is processed for a namespace. Use to remove tracks from UI or stop discovery. Discovery event.
OptionalonTODO: onNamespaceAnnounced may be a better name Fired when an PUBLISH_NAMESPACE control message is processed for a track namespace. Use to update UI or trigger discovery logic. Discovery event.
OptionalonFired exactly once when the client transitions to terminated (disconnect). Use to clean up resources or notify user. Lifecycle handler.
OptionalonFired if the underlying WebTransport session fails (ready → closed prematurely). Use to log or alert on transport errors. Lifecycle/error handler.
ReadonlypeerNamespace prefixes (tuples) the peer has requested announce notifications for via SUBSCRIBE_NAMESPACE. Used to decide which locally issued ANNOUNCE messages should be forwarded (future optimization: prefix trie).
ReadonlypublicationsActive publications (SUBSCRIBE or FETCH) keyed by requestId to manage object stream controllers and lifecycle.
Subset / specialization view of requests.
ReadonlyrequestBidirectional requestId <-> full track name mapping to reconstruct metadata for incoming objects.
ReadonlyrequestsAll in‑flight request objects keyed by requestId (SUBSCRIBE, FETCH, ANNOUNCE, etc). Facilitates lookup when responses / data arrive. Entries are removed on completion or error.
ReadonlysubscribedNamespace prefixes this client has subscribed to (issued SUBSCRIBE_NAMESPACE). Enables automatic filtering of incoming PUBLISH_NAMESPACE / PUBLISH_NAMESPACE_DONE. Maintained locally; no dedupe of overlapping / shadowing prefixes yet.
ReadonlysubscriptionBidirectional track alias <-> subscription requestId mapping
ReadonlysubscriptionsActive SUBSCRIBE request wrappers keyed by track alias for rapid alias -> subscription resolution during incoming unidirectional data handling.
ReadonlytrackLocally 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
});
Gracefully terminates this MOQtailClient session and releases underlying WebTransport resources.
Optionalreason: 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)
}
Declare (publish) a track namespace to the peer so subscribers using matching prefixes (via MOQtailClient.subscribeNamespace) can discover and begin subscribing/fetching its tracks.
Typical flow (publisher side):
publishNamespace(namespace) once per namespace prefix to expose those tracks.Parameter semantics:
Returns: PublishNamespaceOk on success (namespace added to announcedNamespaces) or PublishNamespaceError explaining refusal.
Use cases:
Optionalparameters: VersionSpecificParametersInternalError Transport/control failure while sending or awaiting response (client disconnects first).
announcedNamespaces; manual removal occurs via MOQtailClient.publishNamespaceDone.Send an PublishNamespaceCancel 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.publishNamespaceDone 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 publishNamespaceResp = await client.publishNamespace(["camera","temp"]) // wrong namespace
// Assume you kept the original announce requestId (e.g. from PublishNamespaceRequest)
const cancelMsg = new PublishNamespaceCancel(publishNamespaceResp.requestId as bigint)
await client.publishNamespaceCancel(cancelMsg)
Withdraw 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 PublishNamespaceDone 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.subscribeNamespace for a matching prefix should receive the resulting PublishNamespaceDone. Consider calling this before MOQtailClient.disconnect to give consumers prompt notice.
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: LatestObjectfilterType: 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 });
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).
StaticnewEstablishes 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
Publish a namespace for Publishing
Graceful Shutdown