🆕 New in v0.14: MoQ Transport draft-18 — plus in-band CTA-608 captions and AV1 video

Now Streaming LOCMAF
Low Overhead CMAF for MOQT

moqlivemock and MOQ Player v0.14 stream LOCMAF, a compact wire format for streaming CMAF over MoQ Transport — including DRM-protected content — with delta moofs as small as 2 bytes and a moof-header compression ratio of ~45:1.

The same service continues to stream live, wall-clock synchronized multi-bitrate video and audio over MoQ Transport draft-18, across the CMAF, LOCMAF, LOC and moq-mi packaging modes — all from a single publisher.

New: in-band CTA-608 captions and AV1 video. Every video track now carries a CTA-608 CC1 caption inside the elementary stream itself — an SEI NAL unit for AVC and HEVC, a metadata_itu_t_t35 OBU for AV1 — in all packagings and in the encrypted namespaces, where the captions ride inside the ciphertext. MOQ Player decodes and renders them on both engines, MSE (CMAF and LOCMAF) and WebCodecs (LOC), on the true 32×15 grid with colours, background boxes and the pop-on / roll-up / paint-on screen model. AV1 renditions play on the WebCodecs pipeline but are not yet captioned there — the player reads captions from SEI, not from the AV1 metadata OBU.
MSF / CMSF draft-01 catalogs. The catalog syntax now follows the released MSF and CMSF draft-01 specifications — content protection signaling, init-data references (initDataList / initRef), and string version signaling. With shared init references, the CMAF and LOCMAF packagings of each rendition now live in a single unified catalog at almost no extra cost — the two variants point at the same init data instead of duplicating it. These catalogs are no longer compatible with draft-00.
What is LOCMAF? LOCMAF observes that consecutive CMAF moof headers are almost identical and delta-encodes them on the wire, then reconstructs functionally lossless CMAF chunks at the receiver. Unlike LOC, it preserves the per-sample encryption metadata that the browser EME / CDM pipeline needs, so DRM-protected live streams (Widevine, PlayReady, FairPlay, ClearKey) work end-to-end. Full spec and measurements at locmaf.dev.
💬 In-band CTA-608 captions
🎞️ AVC, HEVC and AV1 video
Unified CMAF + LOCMAF v0.3 catalog
📦 CMAF, LOCMAF, LOC, moq-mi
🔒 DRM end-to-end over MoQ
🚀 MoQ Transport draft-18
🌐 WebTransport Ready
📺 Multi-bitrate, wall-clock synced
Try MOQ Player Now or read the LOCMAF site · IETF draft · reference codec · slides
LOCMAF

Low Overhead CMAF for MoQ

A new wire format for CMAF over MoQ — including DRM — with the overhead of LOC

✨ Why LOCMAF

CMAF carries the metadata that DRM needs (per-sample IVs, subsample maps, tenc defaults). LOC is compact but strips this away. LOCMAF keeps the CMAF structure intact and compresses the redundant moof bytes out of the wire — so the standard MSE / EME path on the receiver plays protected content as if it had arrived as plain CMAF.

  • Sample-level objects (one frame per MoQ object)
  • Delta moof as small as 2 bytes
  • Functionally lossless reconstruction
  • Works with Widevine, PlayReady, FairPlay, ClearKey

📊 Measured Compression

On a 250-fragment AVC group from the moqlivemock test asset:

  • CMAF moof total: 26 040 B
  • LOCMAF object total: 592 B
  • moof-header ratio: 45 : 1
  • 128 kbps AAC wire bitrate: 171.5 → 131.9 kbps (−23 %)
  • 128 kbps AAC under cbcs DRM: 191.4 → 131.9 kbps (−31 %)

LOCMAF saves more relative to CMAF under DRM than in clear, because senc / saio / saiz make the CMAF moof grow while LOCMAF only emits what it needs.

See it yourself: after connecting MOQ Player to the server, click the Show catalog toggle to inspect each track's total wire bitrate (framing included) and compare a CMAF track to its LOCMAF counterpart — both renditions live in the same cmsf/* catalog.

🔗 LOCMAF Resources

Everything you need to understand and implement LOCMAF:

Catalog signal: "packaging": "locmaf" with "locmafVersion": "0.3" in the CMSF Track entry. The matching "packaging": "cmaf" rendition shares the same init data through an initRef, so both variants sit side by side in one draft-01 catalog.

Try LOCMAF Live

Both the publisher and the browser player have shipped LOCMAF since v0.13. Open MOQ Player, connect to a cmsf/* namespace and pick a LOCMAF track from the catalog, and the receiver will rebuild the CMAF chunks and feed them to MSE / EME for you — clear, ClearKey/ECCP, and commercial DRM all work side by side.

Open MOQ Player

In-band CTA-608 Captions

Captions carried inside the video elementary stream — through every packaging, and inside the ciphertext

💬 What is Carried

The publisher injects one self-contained CTA-608 CC1 caption per MoQ group, generated with Eyevinn/go-608. Row 13 carries the UTC clock, row 14 the group number, so what you read on screen is directly checkable against the burnt-in overlay.

  • AVC and HEVC — an SEI NAL unit before the first VCL NALU
  • AV1 — a metadata_itu_t_t35 OBU before the first frame OBU
  • Present in CMAF, LOCMAF, LOC and moq-mi
  • Spliced in before encryption, so captions ride inside the ciphertext
  • Each group is independent — a caption comes from that group's samples alone

🎛️ Presentation Modes

mlmpub -cc608mode selects how a caption reaches the screen, covering all three CTA-608 presentation styles. Measured at 25 fps in a 25-frame group:

  • paint-on (default) — grows two characters per frame; first characters on frame 4, complete on frame 17, so the caption is displayed over the second it names
  • roll-up2 / roll-up3 / roll-up4 — types the same way but scrolls the window up before each line, finishing two frames later
  • pop-on — builds invisibly and flips on whole at frame 18

The roll-up sizes differ in the RU2/RU3/RU4 mode code on the wire but display identically here, since a group holds one cue and the window is reset per group — which is exactly what makes them useful for exercising a decoder.

▶️ Rendering in MOQ Player

MOQ Player decodes the captions from the in-band SEI on both render engines — MSE (CMAF and LOCMAF) and WebCodecs (LOC) — and paints them on the true 32×15 grid inside the CTA-608 safe area, with colours, background boxes and the full pop-on / roll-up / paint-on screen model.

  • CC toggle enabled only when the track advertises urn:scte:dash:cc:cea-608:2015 and its codec can carry CTA-608
  • Encrypted namespaces work without a key — the caption SEI sits in the clear subsample leader
  • Built on a general timed-text overlay seam that WebVTT, IMSC-1 and ograf renderers can reuse

Not yet on AV1: AV1 renditions play on the WebCodecs pipeline, but their captions travel in a metadata OBU rather than an SEI NAL unit, so the player does not render them — the CC toggle stays struck through on those tracks.

See the Captions

Captions are enabled on this demo service. Open MOQ Player, pick an AVC or HEVC video track in any cmsf/* or msf/clear namespace — clear or encrypted — and switch the CC toggle on.

Open MOQ Player

Why Use MoqLiveMock?

Test your MoQ client implementations against a reliable, always-available server speaking MoQ Transport draft-18. MoqLiveMock simulates a true live MoQ streaming service with UTC-aligned content delivery — all clients receive synchronized streams regardless of join time. Stream 10-second loops of synchronized multi-bitrate AVC, HEVC and AV1 content across CMAF, LOCMAF, LOC, and moq-mi packaging modes, with clear and DRM-protected variants of each, and in-band CTA-608 captions in every video track.

Available Streams

Specially prepared relatively low-bitrate content for testing

🎥 Video Tracks

H.264 (AVC), HEVC and AV1 encoded video streams at multiple bitrates for adaptive streaming, each carrying in-band CTA-608 captions

  • 400 kbps AVC
  • 600 kbps AVC
  • 900 kbps AVC
  • 400 kbps HEVC
  • 600 kbps HEVC
  • 900 kbps HEVC
  • 400 kbps AV1
  • 600 kbps AV1
  • 900 kbps AV1

All three codecs are served in the cmsf/* namespaces (CMAF and LOCMAF) and in LOC; moq-mi/clear video is AVC only. The AV1 assets are encoded in low-delay CBR mode (I/P only, no reordering) so they match the AVC/HEVC structure.

🎵 Audio Tracks

Easily discernable audio tracks in AAC, Opus, and AC-3 with synchronized second beeps

  • Monotonic AAC (128 kbps)
  • Scale AAC (128 kbps)
  • Monotonic Opus (128 kbps)
  • Scale Opus (128 kbps)
  • Monotonic AC-3 (192 kbps)
  • Scale AC-3 (192 kbps)

📝 Text Tracks

Out-of-band subtitle tracks in CMAF-compatible formats, plus captions carried inside the video itself

  • WVTT (WebVTT in CMAF)
  • STPP (TTML in CMAF)
  • CTA-608 CC1, in-band in every video track

The CTA-608 captions are signaled per video track with an accessibility descriptor (urn:scte:dash:cc:cea-608:2015, CC1=eng) in the MSF / CMSF catalog; catalogless moq-mi signals nothing and is in-band only. See the captions section.

🔒 Content Protection

Multiple content protection modes served as separate namespaces, each catalog carrying both CMAF and LOCMAF packaging

  • cmsf/clear — unencrypted
  • cmsf/drm-cbcs — Widevine, PlayReady, FairPlay
  • cmsf/eccp-cbcs — ClearKey (ECCP)

Each namespace has its own CMSF draft-01 catalog, with every rendition in both CMAF and LOCMAF packaging. LOCMAF carries the same per-sample encryption metadata as CMAF, so the same EME / CDM path works for either.

Signaling follows the released CMSF draft-01 specification, also supported by Shaka Player.

📦 Packaging Modes

Side-by-side packaging modes so clients can compare wire-cost and pipelines

  • cmsf/*CMAF and LOCMAF (v0.3) in one catalog, sharing init data via initRef
  • msf/clearLOC, raw codec frames per object
  • moq-mi/clearmoq-mi, catalogless interop

LOCMAF gives near-LOC overhead while keeping CMAF's metadata path, so DRM survives the round-trip. LOC and moq-mi carry raw codec frames played via WebCodecs.

⚡ Technical Specs

Modern streaming protocols and formats

  • MoQ Transport draft-18
  • ALPN-based version selection (moqt-18)
  • AVC, HEVC and AV1 video; AAC, Opus and AC-3 audio
  • CMAF chunks, LOCMAF delta moofs, LOC raw frames
  • In-band CTA-608 CC1 captions (SEI for AVC/HEVC, T.35 OBU for AV1)
  • MSE / EME and WebCodecs render pipelines in MOQ Player
  • 10-second loops, wall-clock synchronized
  • MSF / CMSF catalog per namespace
  • moq-mi catalogless namespace
  • Multiple namespaces announced from one publisher

Live Streaming Simulation

UTC-aligned streaming for consistent playback across all clients

🕐 Wall-clock Alignment

MoqLiveMock simulates a live MOQ streaming service with precise UTC time alignment. This ensures all subscribers receive synchronized content regardless of when they join or when the publisher was started.

Two-Level Time Alignment

1.
10-Second Asset Loop is aligned to UTC modulo 10 seconds
The first sample of the clip maps to epoch times where seconds % 10 == 0. This ensures every subscriber joining at the same wall-clock time receives the same content.
2.
MoQ Groups are aligned to full UTC seconds
Each group number equals Unix_epoch_ms / 1000, so group boundaries fall on exact second boundaries.
💡 No Drift: Audio is typically not compatible with integral seconds, so minimal displacement is applied without accumulated drift over time.

How to Use

Multiple ways to connect and stream content

🌐 Browser Player (Recommended)

Use MOQ Player (warp-player v0.14) for instant playback in Chrome, Edge, Firefox, or Safari 26.4+. No installation required. It speaks MoQ Transport draft-18 and ships an MSE / EME engine that plays both CMAF and LOCMAF tracks (the LOCMAF decoder reconstructs CMAF chunks before they reach MSE) plus a WebCodecs engine for LOC and moq-mi tracks — selectable from the UI. The CC toggle renders in-band CTA-608 captions on either engine for AVC and HEVC tracks.

Open MOQ Player

💻 Command Line Client

For developers and advanced users, use mlmsub to stream from the terminal:

# Install the client
go install github.com/Eyevinn/moqlivemock/cmd/mlmsub@latest

# Stream clear CMAF (default namespace: cmsf/clear)
mlmsub -addr moqlivemock.demo.osaas.io -videoname _avc -audioname _aac -muxout - | ffplay -

# Dump the unified cmsf/clear catalog — each rendition appears as a CMAF track
# and a LOCMAF track (the '_locmaf' suffix), sharing init data via initRef
mlmsub -addr moqlivemock.demo.osaas.io -namespace cmsf/clear -catalogout -

# Stream the LOCMAF variant — chunks are reconstructed into CMAF on the receiver
mlmsub -addr moqlivemock.demo.osaas.io -namespace cmsf/clear -videoname _avc_locmaf -audioname _aac_locmaf -muxout - | ffplay -

# Stream the AV1 rendition (CMAF packaging, AV1 + AAC)
mlmsub -addr moqlivemock.demo.osaas.io -videoname _av1 -audioname _aac -muxout - | ffplay -

# Stream LOCMAF under ClearKey/ECCP (cbcs)
mlmsub -addr moqlivemock.demo.osaas.io -namespace cmsf/eccp-cbcs -videoname _eccp_locmaf -audioname _eccp_locmaf -muxout - | ffplay -

# Stream LOC-packaged content (raw frames, AVC + AAC) and write to files
mlmsub -addr moqlivemock.demo.osaas.io -namespace msf/clear -videoout video.h264 -audioout audio.aac

# Discover announced namespaces on a relay
mlmsub -addr moqlivemock.demo.osaas.io -discover

# Stream with WebTransport (selected by the https:// scheme) and debug logging
mlmsub -addr https://moqlivemock.demo.osaas.io:443 -loglevel debug -muxout - | ffplay -

The cmd/locmaf tool in moqlivemock includes a roundtrip subcommand that encodes a fragmented MP4 through the LOCMAF encoder/decoder and verifies sample-level fidelity — handy for running the LOCMAF wire-cost measurements yourself.

🔧 Run Your Own Server

Clone the repository and run your own MoqLiveMock instance:

# Clone and build
git clone https://github.com/Eyevinn/moqlivemock
cd moqlivemock
go build ./cmd/mlmpub

# Option 1: Using mkcert (recommended for development)
mkcert -key-file key.pem -cert-file cert.pem localhost 127.0.0.1 ::1
mkcert -install
./mlmpub -cert cert.pem -key key.pem -addr localhost:4443

# Option 2: Using fingerprint (no cert installation needed)
./mlmpub -sideport 8081

# With in-band CTA-608 captions (this demo runs with -cc608)
./mlmpub -sideport 8081 -cc608

# Pick the CTA-608 presentation style (default: paint-on)
./mlmpub -sideport 8081 -cc608 -cc608mode roll-up2

# With ClearKey/ECCP encryption
./mlmpub -sideport 8081 \
  -kid 00112233445566778899aabbccddeeff \
  -iv 00000000000000000000000000000001 \
  -scheme cbcs -laurl http://localhost:8081/clearkey

When using fingerprint mode, connect with MOQ Player using:
• Server URL: https://localhost:4443/moq
• Fingerprint URL: http://localhost:8081/fingerprint
The -sideport enables an HTTP server for both /fingerprint and /clearkey endpoints.

Part of the Eyevinn Open Source Ecosystem