
- A control plane (
Streams) that manages live inputs, signing keys, API keys, assets, and analytics. It is plain HTTPS — stateless request/response. - A data plane (
BroadcastPublisher+BroadcastViewer) that moves CMAF segments over the persistent MoQT connection.
Live broadcast
Push once, fan out to thousands. Sub-second glass-to-glass on a warm path.
VOD
Resumable uploads via TUS2, packaged to CMAF, played from the same catalog
the live path uses.
Four ingest protocols
RTMP, SRT, WHIP (WebRTC-HTTP ingest), and TUS2 — pick what your encoder or
browser already speaks.
Signed playback
Mint a JWT-bearing playback URL; the relay verifies it inside the subscribe
handler. The URL is the auth.
When to use it
Reach for streams when one producer feeds many consumers and you want adaptive, buffered media rather than a tight interactive loop:- Live events, sports, town halls, product launches, IRL streaming.
- Low-latency “watch parties” where every viewer needs the same timeline.
- VOD libraries built from the same packaging pipeline as your live streams.
- Embedding playback in a browser without a separate plugin — WebTransport is the playback path.
Ingest
The publish side accepts four ingest protocols. Each live input declares itsingest kind (rtmp, srt, whip, or fmp4); VOD uses TUS2.
- RTMP
- SRT
- WHIP
- TUS2 (VOD)
Classic encoder ingest (OBS, hardware encoders, mobile broadcasters). Point
the encoder at the RTMP endpoint and authenticate with the per-input stream
key. The engine ingests, transcodes, and CMAF-packages on the fly.
The browser
BroadcastPublisher in the SDK is a WHIP-style alternative: it
fragments a MediaStream to CMAF in the page and pushes each fragment as a MoQT
object. For server-class contribution, prefer RTMP/SRT/WHIP into the engine and
let the transcoder do the packaging.Wire model
The SDK connects over one of two URL paths, both of which resolve to the same MoQT namespace on the relay:/publish/… and /playback/… are URL paths, not namespaces — the relay’s
stream resolver maps them to stream/<org>/<id>. VOD reuses the same
stream/<org>/… namespace so live and on-demand playback are uniform.
The broadcast capability tag is media.broadcast. The relay writes a
per-broadcast analytics row keyed on that tag.
The catalog
Every stream carries a catalog (a subset ofdraft-ietf-moq-catalog) that
declares its tracks — name, RFC 6381 codec string, and (for VOD) the CMAF init
segment. A live input publishes the catalog in-band on the .catalog
track, so it can update mid-stream (a rendition added, a codec switched). VOD
ships the catalog as catalog.json over HTTPS. The viewer parses the catalog,
opens a MediaSource buffer per track, and feeds CMAF segments into it.
Lanes & QoS
Streams ride MoQT’s group/object model. Each CMAF fragment is one MoQT object; an init/keyframe fragment opens a new group (so a late joiner can start at a group boundary). Objects carry a priority: the init segment is highest priority (it must arrive before media decodes), media segments follow. Under loss, the relay drops by priority and group age rather than blocking the whole stream — buffered, adaptive delivery, not a frame-perfect interactive lane.| Property | Streams behavior |
|---|---|
| Delivery | Per-group, priority-ordered objects over MoQT |
| Late join | Starts at the most recent group boundary (keyframe) |
| ABR | One media track per rendition; the catalog enumerates them |
| Fallback | LL-HLS over HTTPS where WebTransport/MoQT is unavailable |
Codecs & packaging
- Video: H.264/AVC (
avc1.*) on the broad-compatibility path; the codec string is declared per track in the catalog. - Audio: Opus or AAC (
mp4a.40.2). - Container: CMAF / fragmented MP4 (fMP4) —
ftyp+moovinit segment, thenmoof+mdatmedia fragments, fed straight into the browser’sMediaSource. - Fallback: LL-HLS (Low-Latency HLS) over HTTPS for environments where WebTransport isn’t available. The CMAF segments are the same bytes; only the delivery framing changes.
Signed playback (JWT)
Playback is authorized by a short-lived JWT minted from one of the org’s signing keys (Ed25519 by default, RS256 optional). The control plane returns a playback URL with the token already attached as?tok=. The relay verifies
the JWT inside the SUBSCRIBE handler; a bad or expired token closes the session
with auth_failed. Tokens are server-clamped (30 s – 24 h, default 1 h) — re-mint
and re-open before expiry to keep long viewers alive.
Architecture
Related
- Realtime Tracks — the MoQT publish/subscribe primitive underneath every modality.
- Streams — SDK Methods
- Streams — Cookbook
- Streams — Recipes

