Skip to content

Commit

Permalink
More blog updates (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
kixelated authored Oct 30, 2023
1 parent ff2447f commit 97390f6
Show file tree
Hide file tree
Showing 21 changed files with 56 additions and 52 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "moq-js",
"private": true,
"type": "module",
"private": true,
"workspaces": [
"lib",
"web"
Expand Down
2 changes: 2 additions & 0 deletions web/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ export default defineConfig({
},
},
},
// Don't add trailing slashes to paths
trailingSlash: "never",
})
Binary file added web/public/blog/kixelCat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
2 changes: 1 addition & 1 deletion web/src/components/issues.astro
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="my-4 flex flex-row items-center gap-4 rounded-md bg-slate-700 px-4 py-2">
<img src="/warning.svg" alt="Warning" class="h-12 m-0" />
<img src="/issues/warning.svg" alt="Warning" class="h-12 m-0" />
<div>
This is an proof-of-concept. Check out the numerous <a href="/issues">issues</a>.
</div>
Expand Down
12 changes: 6 additions & 6 deletions web/src/layouts/global.astro
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,28 @@ if (frontmatter && frontmatter.title) title = frontmatter.title
content="A new live media protocol in development. This website is a proof-of-concept demonstrating web support, utilizing moq-rs and moq-js."
/>
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" type="image/svg+xml" href="/layout/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<title>{title ? `${title} - ` : ""}Media over QUIC</title>
</head>
<body>
<div class="flex flex-col md:flex-row gap-8 md:p-8 p-4">
<nav class="flex flex-row items-center md:flex-col md:w-72 md:gap-12 gap-4 w-full">
<a href="/" class="w-1/2 md:w-auto">
<img src="/logo-small.svg" class="w-52" alt="Media over QUIC" />
<img src="/layout/logo.svg" class="w-52" alt="Media over QUIC" />
</a>
<div class="flex flex-row flex-wrap items-center justify-center gap-4 w-1/2">
<a href="/watch">
<img src="/watch.svg" class="w-28" alt="Watch" />
<img src="/layout/watch.svg" class="w-28" alt="Watch" />
</a>
<a href="/publish">
<img src="/publish.svg" class="w-28" alt="Publish" />
<img src="/layout/publish.svg" class="w-28" alt="Publish" />
</a>
<a href="/source">
<img src="/source.svg" class="w-28" alt="Source" />
<img src="/layout/source.svg" class="w-28" alt="Source" />
</a>
<a href="https://discord.gg/FCYF3p99mr">
<img src="/discord.svg" class="w-28" alt="Discord" />
<img src="/layout/discord.svg" class="w-28" alt="Discord" />
</a>
</div>
</nav>
Expand Down
82 changes: 42 additions & 40 deletions web/src/pages/blog/replacing-webrtc.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,20 @@ author: kixelated

# Replacing WebRTC

The long and winding path, searching for _something else_.
Written by [@kixelated](https://github.com/kixelated).
The long path to use _something else_ for real-time media.

## tl;dr

If you primarily use WebRTC for...

- **real-time media**: it will take a while to make something comparable; we're working on it.
- **real-time media**: it will take a while to replace WebRTC; we're working on it.
- **data channels**: WebTransport is amazing and _actually_ works.
- **peer-to-peer**: you're stuck with WebRTC for the forseeable future.

## Disclaimer

I spent over a year building/optimizing a full WebRTC stack @ Twitch using [pion](https://github.com/pion/webrtc).
We ultimately scrapped it and my use-case was quite custom so your millage will vary.
Also, some of these issues may have been addressed since then.
I spent almost two years building/optimizing a partial WebRTC stack @ Twitch using [pion](https://github.com/pion/webrtc).
Our use-case was quite custom and we ultimately scrapped it, but your millage may vary.

## Why WebRTC?

Expand Down Expand Up @@ -82,7 +80,7 @@ The problems start when you try to use it for anything else.
My final project at Twitch was to reduce latency by replacing HLS with WebRTC for delivery.
This seems like a no-brainer at first, but it quickly turned into [death by a thousand cuts](https://docs.google.com/document/d/1OTnJunbpSJchdj8XI3GU9Fo-RUUFBqLO1AhlaKk5Alo/edit?usp=sharing).
The biggest issue was that the user experience was just terrible.
Twitch doesn't need the same aggressive latency as Google Meet, but WebRTC is hard-wired to compromise on quality.
Twitch doesn't need the same aggressive latency as Google Meet, but WebRTC is hard-coded to compromise on quality.

In general, it's quite difficult to customize WebRTC outside of a few configurable modes.
It's a black box that you turn on, and if it works it works.
Expand All @@ -93,36 +91,30 @@ But you're ultimately bound by the browser implementation, unless you don't need

### Data

WebRTC also has a data channel API, which is particularly useful because [until recently](https://developer.mozilla.org/en-US/docs/Web/API/WebTransport), it's been the only way to send/receive unreliable messages from a browser.

WebRTC also has a data channel API, which is particularly useful because [until recently](#webtransport), it's been the only way to send/receive "unreliable" messages from a browser.
In fact, many companies use WebRTC data channels to avoid the WebRTC media stack (ex. Zoom).
I went down this path too, attempting to send each video frame as an unreliable message, but ultimately it didn't work due to fundamental flaws with [SCTP](https://www.rfc-editor.org/rfc/rfc9260.html).

I eventually hacked "datagram" support into SCTP by breaking frames into unreliable messages below the MTU size.
Finally! UDP in the browser, but at what cost:
I went down this path too, attempting to send each video frame as an unreliable message, but it didn't work due to fundamental flaws with [SCTP](https://www.rfc-editor.org/rfc/rfc9260.html).
I won't go into the detail in this post, but I eventually hacked "datagram" support into SCTP by breaking frames into unreliable messages below the MTU size.

Finally! UDP\* in the browser, but at what cost:

- a convoluted handshake that takes at least 10 (!) round trips.
- 2x the packets, because libsctp immediately ACKs every "datagram".
- a custom SCTP implementation, which means the browser can't send "datagrams".

Oof. Fortunately there's now a [better way](https://developer.mozilla.org/en-US/docs/Web/API/WebTransport/datagrams) to send datagrams.
Feel free to use my [Rust library](https://docs.rs/webtransport-quinn/latest/webtransport_quinn/).
Oof.

### P2P

The best and worst part about WebRTC is that it supports peer-to-peer.
The ICE handshake is extremely complicated:

- You need both peers to generate a SDP offer/answer.
- You need a public server (usually HTTPS/WebSocket) to exchange the offer/answer.
- Some networks use symmetric NATs, so you need a fallback TURN server.
- Some networks block UDP, so you need a fallback TCP TURN server.
- Some networks only support IPv4 or IPv6 internally, so you should support dual-stack.
- Some clients only support mDNS, so you have to figure that out too.
The [ICE handshake](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Connectivity) is extremely complicated, even from the [application's point of view](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Signaling_and_video_calling).
Without going into detail, there's an explosion of permutations cases that you need to handle based on the network topology.
Some networks block P2P (ex. symmetric NATs) while others outright block UDP, forcing you to use a TURN server a [non-insignificant amount of time](https://twitter.com/HCornflower/status/894600051506515968).

Most conferencing solutions these days are actually client-server for better QoS.
However, you're still forced to perform the complicated ICE handshake.
This has major architecture ramifications, but I'll save that for another blog post.
Most conferencing solutions are client-server anyway, relying on their own private network instead of public transit (aka a CDN).
However the server is still forced to perform the complicated ICE handshake which has major architecture ramifications, but I'll save that for another blog post.

Note that there are rumblings of [P2P WebTransport](https://w3c.github.io/p2p-webtransport/) and [P2P QUIC](https://datatracker.ietf.org/doc/draft-seemann-quic-nat-traversal/), but I wouldn't hold my breath.

Expand Down Expand Up @@ -181,21 +173,23 @@ In fact, you need to choose when to render each audio _sample_ via [AudioWorklet
The upside is that now your web application gets full control of how to render media.
It's now possible to implement WebRTC-like behavior, like temporarily freezing video and desyncing A/V.

[caniuse](https://caniuse.com/webcodecs)
Check [caniuse](https://caniuse.com/webcodecs) for current browser support.

## WebTransport

[WebTransport](https://developer.mozilla.org/en-US/docs/Web/API/WebCodecs_API) is a new API for transmitting data over the network.
Think of it like WebSockets, but with a few key differences:

- [QUIC](https://www.rfc-editor.org/rfc/rfc9000.html) not TCP.
- Provides independent streams that can be closed/prioritized.
- Provides datagrams that can be dropped.
- [Reliable streams](https://developer.mozilla.org/en-US/docs/Web/API/WebTransport_API#reliable_transmission_via_streams) that are delivered in order.
- **Semi-reliable streams** by closing a stream (with an error code) to drop the tail.
- [Unreliable datagrams](https://developer.mozilla.org/en-US/docs/Web/API/WebTransport/datagrams) that may be dropped during congestion.

QUIC has too many benefits to enumerate, but some highlights:

- Fully encrypted
- Congestion controlled (even datagrams)
- Independent streams (no head-of-line blocking)
- 1-RTT handshake
- Multiplexed over a single UDP port
- Transparent network migration (ex. switching from Wifi to LTE)
Expand All @@ -204,7 +198,8 @@ QUIC has too many benefits to enumerate, but some highlights:
That last one is surprisingly important: WebTransport will share all of the optimizations that HTTP/3 receives.
A HTTP/3 server can simultaneously serve multiple WebTransport sessions and HTTP requests over the same connection.

[caniuse](https://caniuse.com/webtransport)
Check [caniuse](https://caniuse.com/webtransport) for current browser support.
Use my [Rust library](https://docs.rs/webtransport-quinn/latest/webtransport_quinn/) for servers and native clients!

## But how?

Expand All @@ -213,18 +208,19 @@ Okay, so we have WebCodecs and WebTransport, but are they actually useful?
I alluded to the secret behind latency earlier: avoiding queues.
Queuing can occur at any point in the media pipeline.

| Capture | Encode | Send | Receive | Decode | Render |
| :-----: | :----: | :--: | :-----: | :----: | :----: |
| --> | --> | --> | --> | --> | --> |
| Capture/Encode | Send/Receive | Decode/Render |
| :------------: | :----------: | :-----------: |
| --> | --> | --> |

Let's start with the easy one.
[WebCodecs](#webcodecs) allows you to avoid queuing almost entirely.

| Capture | Encode | Send | Receive | Decode | Render |
| :-----------: | :-----------: | :--: | :-----: | :-----------: | :-----------: |
| **WebCodecs** | **WebCodecs** | ? | ? | **WebCodecs** | **WebCodecs** |
| Capture/Encode | Send/Receive | Decode/Render |
| :------------: | :----------: | :-----------: |
| **WebCodecs** | ? | **WebCodecs** |

The tricky part is the bit in the middle, the network.
It's not as simple as throwing your hands into the air and proclaiming "UDP has no queues!"

### The Internet of Queues

Expand All @@ -239,6 +235,7 @@ Every packet you send will fight with other packets on the internet.
- If those queues are full, **packets will be dropped**.

There can be random packet loss, but 99% of the time we care about loss due to queuing.
Note that even datagrams may be queued by the network; a firehose of packets is never the answer.

### Detecting Queuing

Expand Down Expand Up @@ -284,7 +281,7 @@ You can't put the toothpaste back in the tube.
However, there are actually quite a few ways of dropping media with [WebTransport](#webtransport):

1. Use datagrams and choose which packets to transmit. (like WebRTC)
2. Use QUIC streams and reset them to stop transmitting. (like [RUSH](https://www.ietf.org/archive/id/draft-kpugin-rush-00.html))
2. Use QUIC streams and close them to stop transmittions. (like [RUSH](https://www.ietf.org/archive/id/draft-kpugin-rush-00.html))
3. Use QUIC streams and prioritize them. (like [Warp](https://www.youtube.com/watch?v=PncdrMPVaNc))

I'm biased because I made the 3rd one.
Expand All @@ -304,13 +301,18 @@ It's going to take a lot of companies who are willing to bet on a new standard.<
And there are major flaws with both **WebCodecs** and **WebTransport** that still need to be addressed before we'll ever reach WebRTC parity.
To name a few:

- We need something like [transport-wide-cc](https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/transport-wide-cc-02/README.md) in QUIC.
- We need better [congestion control](https://www.w3.org/TR/webtransport/#dom-webtransportoptions-congestioncontrol) in browsers.
- We need echo cancellation in WebCodecs, which might be possible already?
- We need [FEC](https://datatracker.ietf.org/doc/draft-michel-quic-fec/) in QUIC, at least to experiment.
- We need more encoding options, like non-reference frames or SVC.
- We need something like [transport-wide-cc](https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/transport-wide-cc-02/README.md) in QUIC: [like this proposal](https://www.ietf.org/archive/id/draft-smith-quic-receive-ts-00.html)
- We need echo cancellation in [WebAudio](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API), which might be possible?
- We may need [FEC](https://en.wikipedia.org/wiki/Error_correction_code#Forward_error_correction) in QUIC: [like this proposal](https://datatracker.ietf.org/doc/draft-michel-quic-fec/)
- We may need more encoding options, like non-reference frames or SVC.
- Oh yeah and full browser support: [WebCodecs](https://caniuse.com/webcodecs) - [WebTransport](https://caniuse.com/webtransport)

## So yeah...

Hit us up on [Discord](https://discord.gg/FCYF3p99mr) if you want to help!
Written by [@kixelated](https://github.com/kixelated).
Hit me up on [Discord](https://discord.gg/FCYF3p99mr) if you want to help!

Tune in for next week's episode: **Replacing HLS/DASH** and **Replacing RTMP**.

<img src="/blog/kixelCat.png" class="inline w-16" />
6 changes: 3 additions & 3 deletions web/src/pages/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ layout: "@/layouts/global.astro"
---

<center>
<img src="logo-full.svg" className="h-32" alt="Media over QUIC Logo" />
<img src="/home/logo.svg" className="h-32" alt="Media over QUIC Logo" />
</center>

**Media over QUIC** is new live media protocol powered by [QUIC](https://quicwg.org/):
Expand Down Expand Up @@ -44,9 +44,9 @@ The standard is being produced by many individuals from companies such as Google

<center>
<a href="https://ietf.org" alt="IETF">
<img src="ietf.svg" className="m-4 inline h-12" alt="IETF Logo" />
<img src="/home/ietf.svg" className="m-4 inline h-12" alt="IETF Logo" />
</a>
<a href="https://quicwg.org/" alt="QUIC Working Group">
<img src="quic.svg" className="m-4 inline h-12" alt="QUIC Logo" />
<img src="/home/quic.svg" className="m-4 inline h-12" alt="QUIC Logo" />
</a>
</center>
2 changes: 1 addition & 1 deletion web/src/pages/watch/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ title: Watch
All **PUBLIC** broadcasts will be eventually listed here. Until then, enjoy:

<div class="grid grid-cols-[200px_1fr] items-center gap-6">
<a href="/watch/bbb"><img src="/bunny.png" alt="Big Buck Bunny" /></a>
<a href="/watch/bbb"><img src="/watch/bunny.png" alt="Big Buck Bunny" /></a>
<div>
<h3 class="m-0 mb-4">[Big Buck Bunny](/watch/bbb)</h3>
<p class="m-0 text-sm">_video_: h.264 1280x720 3.0Mb/s</p>
Expand Down

0 comments on commit 97390f6

Please sign in to comment.