WebRTC SFU と WebTransport

V
8 min readApr 17, 2021

自社製品の WebRTC SFU へ Erlang での DataChannel の実装が一段落して、これからがっつりリリースまではテストしつつバグ探しという状態へと代わり、さて今後 WebRTC SFU をどう成長させていくかと考えるターンになりました。そこでここ数日ほどは QUIC サーバを作って止まっていた知識をアップデートするという状況になりました。

HTTP/2 や QUIC や HTTP/3 については偉大な先人たちがいることもあり、焦って調べてこなかったというのもありますが、本当にたくさんの情報があり大変ありがたいです。ただ WebTransport は用途がマニアックということもあり、ここだけは自分でしっかり調べていかないとなと思っている状況です。

そんな中、自社の WebRTC SFU をどうやっていくかというのがぼんやり見えてきたので、雑にまとめていこうと思います。

まとめ

  • WebTransport のフォールバック方針早く決着して欲しい
  • 実装が大変そうでつらい
  • 学ぶ事が多すぎてつらい

WebTransport (UDP) と WebSocket (TCP) の併用

今回 DataChannel を実装してわかったのは、UDP プロトコルだけではリアルタイムな音声や映像の切断検知には厳しいということでした。

UDP 上で実装されている DataChannel では切断を検知する場合「丁寧な切断」以外は気付くことができません。例えば突然ブラウザやブラウザタブを落とされると WebRTC SFU 側には何のパケットも送られてきません。これはなかなか厳しいです。ICE の State は disconnect から connected に復帰することもあるので、信頼もできません。

これを検知するには SFU 側の SCTP レイヤーまたは DataChanel レイヤーで何かしらの仕組みが必要になるわけです。ただそれでも気付くまでは 15–30 秒必要になるわけです。TCP であればシステム側がクローズ通知を飛ばしてくれることもありすぐに気付くことができます。

もちろんパケットを細かく飛ばしてタイムアウト検知をシビアにするといいのかも知れませんが、RFC 8085 — UDP Usage Guidelines を読む限りは キープアライブは 30 秒間隔程度にしておけみたいな話が書いてあります。

つまり音声や映像、メッセージングをリアルタイムに扱い、切断検知を可能な限り早く知りたい場合は TCP と UDP の併用というのが良いというのが結論になります。実際 Google Meet などは切断検知のために裏でポーリングしてます。

そこで次のプロトコルでも WebTransport 一択というわけにはいかなさそうです。

WebSocket over HTTP/2

まず今利用してる WebSocket は HTTP/1.1 ベース (以降 WebSocket1 と表記)ですが、Chrome M91 では HTTP/2 ベースが入ります(以降 WebSocket2 と表記)。WebSocket1 では Upgrade を利用して新しい TCP を張るという仕組みでしたが、RFC 8441 — Bootstrapping WebSockets with HTTP/2 によると WebSocket2 では CONNECT メソッド拡張を利用して HTTP/2 のストリームの一つとして WebSokcet の通信を行うようになります。

もともと WebSocket はコントロール用でリアルタイムな大量のデータを送ったりは向いていないので無難な判断だと思います。

WebRTC SFU の初回接続のために接続や切断検知やつまりまず HTTP/2 ありきにしていくというのが良さそうです。

HTTP/2 は HTTPS であれば TLS 上で ALPN で h2 を指定することで対応可能です。このあたりは TLS 1.3 縛りにして WebSocket over HTTP/2 over TLS 1.3 over TCP という仕組みを採用しようと考えています。

WebTransport over HTTP/3 のフォールバック

懸念しているのは WebTransport over HTTP/3 (以降 WebTransport と表記) です。そもそも UDP が潰されている可能性を考えるとフォールバックが必要になります。もちろん 443 の TCP は必ず空いている前提です。

ただ WebTransport のフォールバックについてはまだ具体的な話は決まっていません。WebTransport using HTTP/2 を見ると、WebSocket2 同様 CONNECT メソッド拡張を利用して HTTP/2 上に WebTransport を HTTP/2 のストリームの一つとして張るという方向性が出されていますが、どうなるかはわかりません。

WebRTC SFU 的には HTTP/2 は WebSocket2 のために張りっぱなしにしているので、WebTransport over HTTP/2 へのフォールバックは歓迎していところです。WebTransport は HTTP/2 の ALTSVC フレームで h3=“:443” あたりを返して 443 へ QUIC 接続を試みて、その中の ALPN で h3 を指定することで HTTP/3 を接続するという流れになると認識しています。ただサーバは良いのですがクライアントが HTTP/3 を張れないとあきらめて WebTransport over HTTP/2 へのフォールバックを判断するタイミングがまだわかっていない(または決まっていない)のでここは追って調べていく予定です。

WebTransport の上に載せるプロトコル

DataChannel の代替としての WebTransport は問題ないのですが、問題となるのは音声や映像を載せるプロトコルである RTP/RTCP の役割をするプロトコルがまだ出てきていないということです。一番良くないパターンとしては SRTP/SRTCP を捨てて RTP/RTCP を WebTransport に載せてしまうという方向性だと思っていますが、現実はまずはこの方向性に行ってしまいそうで怖いです。独自で定義は一番良くないパターンだと思っています。

RTP/RTCP はレガシーすぎるプロトコルなので、早めに捨ててほしいのですが、このあたりの議論は RIPT でなされるとみていたのですが、あまり進んでいるようには思えません。

独自定義の可能性も実はあって、ブラウザは WebCodecs というエンコード/デコード部分を自前でやる低めの API を提供し始めており、あとはそこをなんとかうまい WebTransport に載せたらいいのでは?なんて話も出得てきそうです。これだと独自で頑張れる大きい会社だけが使えるプロトコルになってしまって嬉しくないなと感じています。

WebTransport 自体の実装の複雑さ

WebTransport は over QUIC は行わず、over HTTP/3 で 対応するという方針になっています。その上で QUIC DatagramHTTP/3 上で使い双方向に寄せたのが WebTransport というのが現状です。

HTTP/3 自体が QUIC ベースであり、さらにその上で WebTransport という状況になり、ブラウザ自体は綺麗に対応してくれると思うのですが、それ以外で独立して使おうとなるとなかなか大変になりそうです。

とはいえ、すでに XFLAG は Elixir (+Rust の QUIC 実装) を組み合わせて ReQUIem という WebTransport (over QUIC) 実装を進めています(おそらくこれは over HTTP/3 に切り替わっていくはずですが)。

将来を見据えている企業は自前での実装を進め始めています。Twitch も配信や視聴を WebTransport 化していくようです。おそらく Google や Apple 、Facebook などもそうでしょう。

WebRTC SFU における WebTransport

音声や映像をどう配信するかが決まっていない以上は自前で行う必要がでてくるようになります。おそらく WebRTC SFU はより「メディアルーター」としての機能が強くなり、クライアント側は WebCodecs + WebAssembly という仕組みでのプロトコル組み立て、そこからの WebRTC SFU 経由での配信になるのではないでしょうか。

ただ WebTransport (QUIC レイヤー) の暗号自体はサーバ側で一度ほどく必要がでてくることになりそうです。

Zoom が採用している鍵を配布してサーバ側では必要が出てくるまで復号しないというのが WebTransport を採用した場合はやりにくくなるというのはあります。

WebTransport と E2EE

WebTransport を利用した場合クライアント側で AES-GCM あたりで暗号化して、さらに WebTransport レイヤーで暗号化することになるため、ここは多重暗号化になり改善されなさそうです。

今後の E2EE は SFrame-MLS というのが Google や Apple や Cisco や Wire の方針のようなので、これで行くのは間違いなさそうです。これを WebTransport に載せて WebRTC SFU で動くようにしていくという必要があります。

--

--