|
| 1 | +--- |
| 2 | +layout: "@/layouts/global.astro" |
| 3 | +title: On a Boat |
| 4 | +author: kixelated |
| 5 | +description: I'm on a boat. |
| 6 | +cover: "/blog/on-a-boat/boat.png" |
| 7 | +date: 2026-02-26 |
| 8 | +--- |
| 9 | + |
| 10 | +# On a Boat |
| 11 | +[Saronic](https://www.saronic.com/) posted a [blog](https://medium.com/saronic-technologies/the-ground-moves-building-on-early-open-source-without-getting-burned-ba2af78beb78) about how they've been using MoQ for years. |
| 12 | +Go read it. |
| 13 | + |
| 14 | +I'm stoked because I can *finally* talk about nautical nonsense. |
| 15 | + |
| 16 | +## Bandwidth Constrained |
| 17 | +Imagine this: |
| 18 | + |
| 19 | +- You're on a boat, man. |
| 20 | +- You're going fast, man. |
| 21 | +- You've got 9 cameras and StarLink is expensive, man. |
| 22 | + |
| 23 | +<figure> |
| 24 | +  |
| 25 | + <figcaption>[obligatory](https://www.youtube.com/watch?v=R7yfISlGLNU)</figcaption> |
| 26 | +</figure> |
| 27 | + |
| 28 | +It's not sustainable to constantly transmit a full HD stream from every camera. |
| 29 | +Even if you can afford it, ship happens. |
| 30 | +Your bandwidth will fluctuate and camera feeds will drop out. |
| 31 | + |
| 32 | +Existing contribution protocols (ex. WebRTC, SRT, RTSP, RTMP) are push-based. |
| 33 | +A publisher, like a security camera on a boat, constantly transmits *everything* to a server. |
| 34 | +Not good when you're on a boat. |
| 35 | + |
| 36 | +But **MoQ is pull-based**\*. |
| 37 | +We are the ugly duckling of the media publishing world. |
| 38 | + |
| 39 | +\* Well technically, the IETF nerds added an (optional) `PUBLISH` message to [moq-transport](https://datatracker.ietf.org/doc/draft-ietf-moq-transport/), so it can do both. |
| 40 | +But I *strongly* discourage you from using it, and here's why: |
| 41 | + |
| 42 | +## LIKE, COMMENT, SUBSCRIBE |
| 43 | +But first the basics. |
| 44 | + |
| 45 | +A MoQ broadcast is split into live streams called "tracks". |
| 46 | +It's completely up to your application to decide how to split stuff into tracks. |
| 47 | +For example, [hang.live](https://hang.live) uses: |
| 48 | +- `1080p` |
| 49 | +- `360p` |
| 50 | +- `audio` |
| 51 | +- `captions` |
| 52 | +- `chat` |
| 53 | +- etc |
| 54 | + |
| 55 | +Every MoQ viewer has to explicitly `SUBSCRIBE` to each track, otherwise it won't be transmitted. |
| 56 | + |
| 57 | +This is fantastic because now tracks are optional. |
| 58 | +Window minimized? Codec unsupported? Screen too small? Don't `SUBSCRIBE 1080p`. |
| 59 | + |
| 60 | +What if 100 viewers `SUBSCRIBE 1080p`? |
| 61 | +[moq-relay](https://doc.moq.dev/app/relay/) is the champ that merges them into a single *upstream* `SUBSCRIBE 1080p`. |
| 62 | +Your boat is safe from the flood and serves *at most* one copy of each track. |
| 63 | + |
| 64 | +What if 100,000 viewers `SUBSCRIBE 1080p`? |
| 65 | +Run a [cluster](https://doc.moq.dev/app/relay/cluster) of relays. |
| 66 | +Sprinkle them around the world and suddenly you have a global CDN. |
| 67 | + |
| 68 | +It's the exact same concept as HTTP CDNs, but for live streams. |
| 69 | +MoQ is being standardized specifically so you can use a [CDN like Cloudflare](/blog/first-cdn) to scale world-wide. |
| 70 | +Or you could self-host [moq-relay](https://doc.moq.dev/app/relay/) (like Saronic) and keep everything in your network. |
| 71 | + |
| 72 | + |
| 73 | +## Enter, Renditions |
| 74 | +**Mr Skeptic Strawman** says: |
| 75 | +> I have a single viewer, why should I care about mass fanout? |
| 76 | +
|
| 77 | +Well **Mr Skeptic Strawman**, let's talk about renditions. |
| 78 | + |
| 79 | +In new reality land, you don't want a *human* viewer. |
| 80 | +You instead throw an AI model at that shit. |
| 81 | +The AI will subscribe to the 360p stream from every camera and try to detect anomalies. |
| 82 | +Like a kraken is attacking or something. |
| 83 | + |
| 84 | +idk I don't sail. |
| 85 | + |
| 86 | +By default, only the 360p stream for each camera is being transmitted. |
| 87 | +If AI detects a kraken on the starboard bow, then it subscribes to the 1080p stream. |
| 88 | + |
| 89 | +<figure> |
| 90 | +  |
| 91 | + <figcaption>Arr, there be a kraken on the starboard bow.</figcaption> |
| 92 | +</figure> |
| 93 | + |
| 94 | +But what happens during congestion if we can't transmit everything? |
| 95 | +**Answer**: it's your choice buddy. |
| 96 | + |
| 97 | +All MoQ subscriptions contain a priority, so they can cooperate while sharing a connection. |
| 98 | +- **Do you want the kraken cam?** Probably, set the priority to 10. |
| 99 | +- **Do you want to crash the boat?** Probably not, set the front-facing cameras to 5. |
| 100 | +- **Do you want audio?** Idk I don't sail, maybe set it to 15. |
| 101 | + |
| 102 | +The QUIC library will transmit packets based on the specified priorities. |
| 103 | +In this example: audio, then the kraken, then front cameras, then anything else. |
| 104 | +This is all best-effort, so your sloppy-seconds might get queued/dropped if the bandwidth is too low. |
| 105 | + |
| 106 | +**Something** has to be queued/dropped, but we do our best to make sure the most important stuff gets transmitted. |
| 107 | +Hopefully it's the kraken. |
| 108 | + |
| 109 | + |
| 110 | +## Backfill that Boat |
| 111 | +Another MoQ difference is that we don't drop frames, we prioritize/queue. |
| 112 | + |
| 113 | +**Mr Skeptic Strawman** says: |
| 114 | +> huh? |
| 115 | +
|
| 116 | +So lets say the kraken is consuming our crew, and our available bandwidth. |
| 117 | +We get an alert that the kraken is attacking. |
| 118 | + |
| 119 | +A human wants to see that shit in real-time and configures a maximum latency of 100ms. |
| 120 | +If a frame takes longer than that, then we skip ahead. |
| 121 | +We don't want a spinny boye getting in the way of the action. |
| 122 | + |
| 123 | +But let's say there's also a VOD worker recording the footage for the post-mortem. |
| 124 | +It can tolerate higher delays, configuring a maximum latency of 30 seconds. |
| 125 | + |
| 126 | +Normally, a WebRTC publisher would have dropped that frame after 100ms, but MoQ doesn't. |
| 127 | +We instead deprioritize it, sending newer frames instead but keeping old frames in RAM. |
| 128 | + |
| 129 | +**We know the kraken will eventually be satiated**. |
| 130 | +Once we recover, we might have enough spare bandwidth to backfill the VOD before the 30s deadline. |
| 131 | + |
| 132 | +The end result is a lossy live stream AND a pristine VOD. |
| 133 | +Just because one viewer wants real-time latency doesn't mean the rest of the world has to suffer. |
| 134 | + |
| 135 | +Literally huge. |
| 136 | + |
| 137 | +## Bonded Pairs |
| 138 | +What if you're near the coast? |
| 139 | +Can we use a cellular connection in addition to the satellite connection? |
| 140 | + |
| 141 | +Why of course, rhetorical question. |
| 142 | +QUIC supports path migration, seamlessly switching between multiple paths (active-backup). |
| 143 | +You can switch from Wifi to cellular to satellite without severing the QUIC connection (unlike TCP). |
| 144 | + |
| 145 | +There's also a [multi-path extension](https://datatracker.ietf.org/doc/draft-ietf-quic-multipath/) that can use multiple paths at the same time (active-active). |
| 146 | +If you want to give it a spin, the [iroh](https://iroh.computer/) folks just released their [Quinn fork](https://github.com/n0-computer/noq). |
| 147 | +It's gated [behind a feature flag](https://github.com/moq-dev/moq/blob/main/rs/moq-native/Cargo.toml) if you want to try it with MoQ. |
| 148 | + |
| 149 | +<figure> |
| 150 | +  |
| 151 | + <figcaption>Like kittens, these pairs are bonded.</figcaption> |
| 152 | +</figure> |
| 153 | + |
| 154 | +And that's only at the QUIC level. |
| 155 | +Another option is to establish multiple MoQ connections, advertising the broadcast as available on all of them. |
| 156 | +The viewer will automatically route subscriptions to the "best" connection. |
| 157 | +For example, via a P2P connection (via [iroh](https://iroh.computer/)) otherwise via CDN connection. |
| 158 | + |
| 159 | +And remember, MoQ won't transmit a track until there's a `SUBSCRIBE` for it. |
| 160 | +You can establish multiple connections, possibly to different CDNs, and nothing will flow. |
| 161 | +The moment a viewer (on that CDN?) needs a track, then it will be transmitted. |
| 162 | + |
| 163 | +Push-based protocols can't do this. |
| 164 | +**Pull-based is based.** |
| 165 | + |
| 166 | +## The Wake not Taken |
| 167 | +You need pretty huge buoys to be an early adopter. |
| 168 | +Saronic has been using my [moq.dev](https://github.com/moq-dev/moq) libraries for maybe ~2 years now... even before I was a professional vagrant. |
| 169 | + |
| 170 | +I want to thank them for their patience and support. |
| 171 | +They put up with bugs, overzealous renaming, and other shenanigans. |
| 172 | +They've got a pretty nice solution now and [are hiring](https://jobs.lever.co/saronic). |
| 173 | + |
| 174 | +And there's a few other cant-be-named companies evaluating MoQ for *security purposes*. |
| 175 | +I can't say that was the plan... but it makes perfect sense. |
| 176 | +Hit me up if you want to chat about your use-case and how I can help. |
| 177 | +Even if I have to sign an NDA. |
| 178 | + |
| 179 | +I'm just happy to see MoQ being used in the wild. |
| 180 | +[Dave Gullo](https://github.com/davegullo) earns a shoutout for doing just that with [ooda.video](https://ooda.video/). |
| 181 | +He's using the dope [MoQ OBS plugin](/blog/moqbs) we built in [Montevideo](/blog/monte-video) to do all of the kraken detection stuff. |
| 182 | + |
| 183 | +## Conclusion |
| 184 | +MoQ is great for boats. |
| 185 | +And other vehicles. |
| 186 | +And stationary objects. |
| 187 | + |
| 188 | +Want to learn more? |
| 189 | +I'm working on [more documentation](https://doc.moq.dev), including other non-boat [use-cases](https://doc.moq.dev/concept/use-case/). |
| 190 | + |
| 191 | +Until next time sailor. |
| 192 | + |
0 commit comments