Media over QUIC Update 00

dabinat1 pts0 comments

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...

json relay stream from connect https

Related Articles