Update 00 - Media over QUIC<br>published 6/24/2026<br>Update 00
sup nerds.<br>We now doing low-energy progress reports.
Here’s a summary of stuff that changed in the last 4? months.<br>IDK my brain is so fried from talking to Claude all day.
Hop-based Routing
Now you can now arbitrarily connect moq-relay instances to each other to form a cluster.<br>They’ll gossip available broadcasts to each other and proxy any subscriptions automatically via the shortest path.
For example, I can host a relay at https://denver.moq.dev and configure it with:
moq-relay --cluster-connect "https://chicago.moq.dev" --cluster-connect "https://seattle.moq.dev" ...<br>Imagine relays are also configured to connect to their nearest neighbors.<br>A subscription from a user in Europe, subscribing to a broadcast in Denver, might travel:
Frankfurt -> London -> New York -> Chicago -> Denver
At each hop, we deduplicate subscriptions.<br>Which means at most only one copy of a track will ever be transmitted between two relays.
SPOILER : an upcoming marketing image
For context, the previous architecture was a mesh.<br>Every relay would connect to every other relay, which would have resulted in:
Frankfurt -> Denver (oof)
Oh yeah and<br>Your local relay (snug behind a firewall) can proxy all broadcasts to/from a public CDN:
moq-relay --cluster-connect "https://cdn.moq.dev" ...<br>It’ll work with any other MoQ CDN… once they implement enough of the moq-transport spec (Cloudflare pls).<br>But you’ll need moq-lite-03+ to establish multiple connections, otherwise a cycle will ruin your day.
Standards
Speaking of standards, the IETF keeps marching forward, so I have to “support” every new draft version:
moq-transport drafts 14-18.
qmux drafts 00-01
msf drafts 00-01
loc draft 01
We don’t support every single feature because some of them are dumb and it takes forever to litigate every single addition/change in the IETF.<br>I’m starting to publish extensions for stuff we add on top, but it’s such a drain on my time.
Instead the moq.dev libraries prefer to negotiate :
moq-lite drafts 01-04
hang drafts 00-01
moq-lite-05 is coming SOON with more stuff.
Muxing
My philosophy is that we should not transmit arbitrary media formats over MoQ.<br>It’s possible to transmit TS over MoQ verbatim, but then every player/subscriber needs to decode Transport Streams (gross).
Instead, moq-mux is our transmuxing layer.<br>We can import/export other formats without re-encoding, preserving the intent but not the original structure.
Here’s the codecs we support:
H.264/H.265
AV1
VP8/VP9
Opus
AAC
And the containers we support:
fMP4/CMAF
FLV/RTMP
Matroska/WebM
HLS
LOC
MPEG-TS
Going back to Transport Streams (gross) as an example.<br>When you import a TS stream with moq-mux, we’ll split A/V into MoQ tracks, but we’ll also preserve “unknown” tracks with a special “ts” section.<br>If you export the same stream to TS with moq-mux, we’ll re-assemble the TS stream and reinsert the unknown tracks.
This is a REALLY BIG DEAL for broadcast TV.<br>Your precious SCTE35 markers are preserved AND you’re not wasting 5% of your bandwidth on 188-byte packets.
ur welcome
CLI
Note that moq-mux is available as both a library and a CLI via moq-cli.
# Publish: pipe in a MPEG-TS file<br>ffmpeg -re -i input.ts -f mpegts - | \<br>moq-cli publish --url https://cdn.moq.dev/anon --broadcast my-stream ts
# Subscribe: pull MPEG-TS back out and play it<br>moq-cli subscribe --url https://cdn.moq.dev/anon --broadcast my-stream --format ts | \<br>ffplay -<br>You can download all of the moq binaries (moq-relay, moq-token, etc) from your favorite package manager:
Homebrew
Docker
Nix
winget
.deb/.rpm
For specific commands, see the CLI docs.<br>Cool I guess?
JSON
JSON isn’t known for its efficiency.
moq-json (Rust) and @moq/json (Typescript) publish arbitrary JSON over MoQ tracks.<br>The first frame in each group is a full snapshot, then subsequent frames are JSON Merge Patch deltas.<br>We periodically make new groups so late joiners can catch up without having to download the entire stream.
We also stack moq-flate (Rust) and @moq/flate (Typescript) to add DEFLATE compression on top.<br>Normally you would compress each frame individually, like a gzip file, but it turns out we can do significantly better by using Z_SYNC_FLUSH.<br>Each subsequent frame within the same group can reuse the previous frames as a compression window, instead of starting from scratch.
Claude ran a benchmark over a synthetic stream of JSON sensor snapshots.<br>The type of output you’d expect from a drone.
Bitrate savings for different configurations:
No DEFLATEDEFLATE per frameDEFLATE per groupNo deltas0%39%89%JSON Merge Patch58%72%91%<br>I was surprised to see how important Z_SYNC_FLUSH is given it’s not supported by the browser implementation and is bugged in the most popular Javascript implementation.<br>At this point, the main benefit of JSON Merge Patch is to save some CPU cycles.
Backends
We’ve used Quinn for the longest time, but now you can use other QUIC...