これは時雨堂が 2024 年 10 月 29 日 (火) 14:00-18:00 で開催を予定しているオンラインイベント WebRTC 入門 & WebRTC SFU Sora 入門 v2024-10 の 講師用 の資料であり、 参加者用の資料ではありません。
時雨堂 WebRTC 入門 & WebRTC SFU Sora 入門 オンラインイベント v2024-10
ChatGPT などがある今、学ぼうと思えば好きなだけ学べる時代がきています。 ただ「正しい情報」をなんとなく知っている事はとても重要だと考えています。
WebRTC & WebRTC SFU Sora 入門は参加者の雰囲気に合わせて話す内容を変更します。
資料表示用の画面と iPad を画面共有してホワイトボード的な使い方をしていきます。
是非 Discord にメモを残していってください。 後から振り返るとき、参加者の皆に有用だと思います。
コメントを見ながらどんな内容を話すかを決めていきますので、 是非コメントを積極的にしていってください。
Creative Commons — 表示 - 非営利 - 改変禁止 4.0 国際 — CC BY-NC-ND 4.0
この本を積極的に利用します。
O'Reilly Japan - ハイパフォーマンス ブラウザネットワーキング
少し古い本ですが大変お勧めです。
- WebRTC はブラウザだけで利用できる
- WebRTC はプロトコルスタックなので、ブラウザ外でも利用できる
- むしろ Discord や WhatsApp といった非ウェブアプリで利用されている
- WebRTC は P2P でしか利用できない
- WebRTC は P2P だけでなく、クライアント・サーバーモデルでも利用できる
- WebRTC は P2P だから超低遅延を実現している
- P2P といっても、いろいろなネットワークを経由して繋がる
- WebRTC が超低遅延なのは P2P だからではなく、WebRTC プロトコルスタックのおかげ
- WebRTC は UDP だから超低遅延を実現している
- インターネットは UDP だろうが TCP だろうが速度一緒なのを忘れている
- WebRTC が超低遅延なのは UDP だけでなく WebRTC プロトコルスタックのおかげ
WebRTC の歴史といっても、WebRTC ができた経緯とかではなく、 WebRTC 自体がどのように進化してきたかを話をしていきます。
ここで話すことは、基本的に役に立ちません。 ただ、歴史を知ることで、WebRTC がどのように進化してきたかを知ることができます。
もともと WebRTC では P2P での通信を想定していますが、ビジネスでは P2P だけではなく、SFU のようにサーバー経由でうまいことやりたくなってきました。 実際多くの WebRTC を使ったビジネスではサーバー経由である WebRTC SFU が採用されています。
この SFU を使った場合、必ず複数のストリームを送受信する必要があります。そこで登場したのがマルチストリームという概念です。 簡単に言えば複数の音声や映像を送信する仕組みです。マルチトラックとは異なります。
マルチトラックは 1 ストリームに複数の音声と映像を含む方式です。勘違いしやすいのでここは注意してください。
- WebRTC in Firefox 38: Multistream and renegotiation - Mozilla Hacks - the Web developer blog
- Firefox multistream and renegotiation for Jitsi Videobridge - Mozilla Hacks - the Web developer blog
- Multistream を勝手にまとめる. Firefox 38 で実装された WebRTC の Multistream… | by V | Medium
WebRTC は最初 H.264 には対応していませんでした。なぜなら H.264 コーデックにはパテントがあります。 ただこれを力業で解決したのが Cisco の OpenH264 です。MPEG-LA のライセンスを Cisco が負担するというものです。
これのおかげで WebRTC で H.264 を気軽に利用できるようになりました。
Cisco が提供している OpenH264 のバイナリを利用する限りは、無料で利用することができます。 ソースコードをコンパイルして使う場合は、ライセンスは自前で払う必要があります。
- cisco/openh264: Open Source H.264 Codec
- OpenH264
- Open-Sourced H.264 Removes Barriers to WebRTC
- archive です
- RFC 7742: WebRTC Video Processing and Codec Requirements
VP8 から始まった WebRTC のコーデックですが、 Chrome は早い段階で VP8 の次の VP9 に対応しました。 それに続き Firefox が対応し、今では Safari も対応しています。
ただ、Safari の VP9 対応はおまけ的なモノだと感じています。なぜなら Safari が VP9 に対応したのは YouTube のためです。 YouTube は VP9 に対応していないと 4K 以上の動画を再生できないからです。
WebRTC のサイマルキャストは 1 つの映像ソースを、複数の画質で配信する仕組みです。1080p / 720p / 360p などの画質を同時に配信することができます。基本的には 3 本の映像ソースを同時に配信することになります。
- simulcast.cc - Chromium Code Search
- RFC 8853: Using Simulcast in Session Description Protocol (SDP) and RTP Sessions
libwebrtc の場合は解像度毎に配信可能な本数と、要求ビットレートがハードコードされています。
// These tables describe from which resolution we can use how many
// simulcast layers at what bitrates (maximum, target, and minimum).
// Important!! Keep this table from high resolution to low resolution.
constexpr const SimulcastFormat kSimulcastFormats[] = {
{1920, 1080, 3, webrtc::DataRate::KilobitsPerSec(5000),
webrtc::DataRate::KilobitsPerSec(4000),
webrtc::DataRate::KilobitsPerSec(800)},
{1280, 720, 3, webrtc::DataRate::KilobitsPerSec(2500),
webrtc::DataRate::KilobitsPerSec(2500),
webrtc::DataRate::KilobitsPerSec(600)},
{960, 540, 3, webrtc::DataRate::KilobitsPerSec(1200),
webrtc::DataRate::KilobitsPerSec(1200),
webrtc::DataRate::KilobitsPerSec(350)},
{640, 360, 2, webrtc::DataRate::KilobitsPerSec(700),
webrtc::DataRate::KilobitsPerSec(500),
webrtc::DataRate::KilobitsPerSec(150)},
{480, 270, 2, webrtc::DataRate::KilobitsPerSec(450),
webrtc::DataRate::KilobitsPerSec(350),
webrtc::DataRate::KilobitsPerSec(150)},
{320, 180, 1, webrtc::DataRate::KilobitsPerSec(200),
webrtc::DataRate::KilobitsPerSec(150),
webrtc::DataRate::KilobitsPerSec(30)},
// As the resolution goes down, interpolate the target and max bitrates down
// towards zero. The min bitrate is still limited at 30 kbps and the target
// and the max will be capped from below accordingly.
{0, 0, 1, webrtc::DataRate::KilobitsPerSec(0),
webrtc::DataRate::KilobitsPerSec(0),
webrtc::DataRate::KilobitsPerSec(30)}};
ブラウザの場合は encodings の設定から自由に変更が可能です。
- https://w3c.github.io/webrtc-pc/#dom-rtcrtpencodingparameters
- https://w3c.github.io/webrtc-extensions/#rtcrtpencodingparameters
求めるレベルによりますが、 WebRTC は複雑な仕組みが多いので、深追いするとかなりの時間がかかります。 そのため、どこまで学ぶべきかを事前に決めるべきです。
利用するだけであれば P2P や SFU どちらかをつかい、ブラウザだけでなら読める必要はありません。 もしブラウザ以外から WebRTC を使う場合は必ず読めるようになった方がいいです。
基本的に必要ありません。ただ 知って損することはない です。 実際 W3C の資料を読む際にも RTP や SCTP の知識があると良いこともあります。
特にデータチャネルを利用する場合は SCTP を学んでおくことで、適切な利用ができます。
多くの場合で通信関連の不具合や問題が起きるのが TURN がらみです。 うまく繋がらないとか、詰まるとか、色々な問題が起きます。 そのため TURN については、少し深追いしておくのが良いです。
といってもプロトコルの話というよりは、どんな仕組みで動いているのかを理解すれば十分です。
WebRTC は多くの技術の組み合わせです。ここではできる限りは取り上げていきます。 理解して詳しくなるのではなく なんとなく聞いたことがある を重視します。
- WebRTC: Real-Time Communication in Browsers
- WebRTC API - Web APIs | MDN
- Real-Time Communication in WEB-browsers (rtcweb)
- Identifiers for WebRTC's Statistics API
W3C の WebRTC 関連の資料は本当に細かく、大量にありますが ぜひ読むべき です。 タダ、どこから読めばいいかわからない、何を読めばいいか解らないというと思うので、 ここではざっと W3C の紹介をしていこうと思います。
- Region Capture
- Screen Capture
- Scalable Video Coding (SVC) Extension for WebRTC
- WebRTC Encoded Transform
- 送信前、受信後の音声や映像のフレームを書き換える仕組み
- WebRTC RTP Transport
- Media Capture and Streams
- Audio Output Devices API
- Media Capabilities
- MediaStreamTrack Content Hints
- WebRTC Priority Control API
- MediaStreamTrack Insertable Media Processing using Streams
RFC 8834: Media Transport and Use of RTP in WebRTC
今まではメディアチャネルと呼んできましたが、RFC 的にメディアトランスポートと書かれていることもあり、 そちらにあわせることにします。
メディアトランスポートは音声と映像をリアルタイムでやりとりする仕組みです。 プロトコルには RTP が利用されており、通信の暗号化には DTLS-SRTP が利用されます。
よく WebRTC P2P での例はこのメディアトランスポートを利用して、ブラウザで音声や映像をやりとりしています。
メディアトランスポートが音声と映像専用ですが、データチャネルは なんでも です。 つまりバイナリやテキストをやりとりすることができます。
データチャネルは Data Channels over SCTP over DTLS over UDP というミルフィーユプロトコルです。
- RFC 8831: WebRTC Data Channels
- RFC 8832: WebRTC Data Channel Establishment Protocol
- RFC 8841: Session Description Protocol (SDP) Offer/Answer Procedures for Stream Control Transmission Protocol (SCTP) over Datagram Transport Layer Security (DTLS) Transport
- "sctp-port" Attribute は使われていません
SDP では m=application
で利用します。
この RFC 8864: Negotiation Data Channels Using the Session Description Protocol (SDP) の仕様は全て採用されていないので、忘れましょう。
- RFC 6083: Datagram Transport Layer Security (DTLS) for Stream Control Transmission Protocol (SCTP)
- RFC 6347: Datagram Transport Layer Security Version 1.2
DTLS はデータグラム向けの TLS です。TLS と何が違うの?って思うと思いますが、ハンドシェイク部分に再送機能が付いています。よく誤解されるのですがアプリケーションデータでは再送はしません。
アプリケーションデータというのは暗号化されたトンネル通信部分です。
データチャネルの再送や順番保証の仕組みは DTLS ではなく SCTP が行っています。 TLS の場合は TCP がやってくれています。
DTLS は 1.2 が利用されています。1.3 は今のところ対応される様子はありません。 ちなみに、OpenSSL はまだ DTLS 1.3 は実装中で、まだリリースされていません。
SCTP は TCP と UDP のいいところ取りをした第 3 のプロトコルです。しかし一般的に使われることはありません。 理由は簡単で世のルーターが SCTP をうまくハンドリングできないことがあるからです。
そこで WebRTC ではまず SCTP を DTLS で隠蔽し、かつ UDP に載せています。 これでルーターはただの UDP として SCTP を扱うことになります。
SCTP は本当に複雑なプロトコルです。 また勘違いされやすいのが、データチャネルは SCTP 上に構築された プロトコルです。
SCTP は信頼性の高いプロトコルです。ただし SCTP の拡張を利用することで信頼性を下げることができます。 これは受信者に ここまで受け取ったことにする ということができるので、データチャネルのような信頼性の低いプロトコルを実現することができます。
- RFC 3758: Stream Control Transmission Protocol (SCTP) Partial Reliability Extension
- RFC 6525: Stream Control Transmission Protocol (SCTP) Stream Reconfiguration
- RFC 7765: TCP and Stream Control Transmission Protocol (SCTP) RTO Restart
- RFC 8261: Datagram Transport Layer Security (DTLS) Encapsulation of SCTP Packets
- RFC 9260: Stream Control Transmission Protocol
SCTP は基本的には順番保証があり、かつ再送があります。これは TCP と同じです。しかし拡張する仕組みを追加することで、再送を諦める仕組みが入ります。データチャネルの最大再送信回数や最大パケットライフタイムはこの拡張の仕組みを使っています。
もともと SCTP は大きくても 64 KB 程度のメッセージを送信するための仕組みでした、 そのため SCTP 標準では大きなメッセージを送ることができませんでした。
そのために拡張機能を使い大きなメッセージを送れるようにしています。
- RFC 6096: Stream Control Transmission Protocol (SCTP) Chunk Flags Registration
- これは SCTP の最新の RFC では統合されています。
WebRTC は多くのプロトコルを利用しています。利用されているプロトコルは全て RFC になっています。
SDP は双方でやりとりをする際に、自分が利用可能な技術を教え合うプロトコルです。 ハンドシェイクのために Offer と Answer という 2 つのメッセージをやりとりします。
Offer に対して Answer を返します。
SDP は更新ができるプロトコルです。WebRTC の P2P ですと、一度 Offer/Answer のやりとりをすると終わりというイメージがあるため、 あまり知られていません。WebRTC SFU では Offer/Answer のやりとりを繰り返すことで、新たなピアを追加することができます。 この際の Offer/Answer は Re-Offer / Re-Answer と読んだりします。
v=0
o=- 3358184816123717626 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1
a=extmap-allow-mixed
a=msid-semantic: WMS
m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:xVwm
a=ice-pwd:hsi24iz/FODRl0rmMFHzAHAA
a=ice-options:trickle
a=fingerprint:sha-256 9A:2A:81:5E:F8:24:5D:CF:53:8C:90:71:B7:22:F1:49:8D:B2:BA:9A:B8:65:49:5B:33:D6:2A:38:77:6D:F7:F2
a=setup:actpass
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=recvonly
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:63 red/48000/2
a=fmtp:63 111/111
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:126 telephone-event/8000
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 35 36 37 38 102 103 104 105 106 107 108 109 127 125 39 40 41 42 43 44 45 46 47 48 112 113 114 115 116 117 118 49
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:xVwm
a=ice-pwd:hsi24iz/FODRl0rmMFHzAHAA
a=ice-options:trickle
a=fingerprint:sha-256 9A:2A:81:5E:F8:24:5D:CF:53:8C:90:71:B7:22:F1:49:8D:B2:BA:9A:B8:65:49:5B:33:D6:2A:38:77:6D:F7:F2
a=setup:actpass
a=mid:1
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:13 urn:3gpp:video-orientation
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=recvonly
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtpmap:98 VP9/90000
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=fmtp:98 profile-id=0
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtpmap:100 VP9/90000
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=fmtp:100 profile-id=2
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=rtpmap:35 VP9/90000
a=rtcp-fb:35 goog-remb
a=rtcp-fb:35 transport-cc
a=rtcp-fb:35 ccm fir
a=rtcp-fb:35 nack
a=rtcp-fb:35 nack pli
a=fmtp:35 profile-id=1
a=rtpmap:36 rtx/90000
a=fmtp:36 apt=35
a=rtpmap:37 VP9/90000
a=rtcp-fb:37 goog-remb
a=rtcp-fb:37 transport-cc
a=rtcp-fb:37 ccm fir
a=rtcp-fb:37 nack
a=rtcp-fb:37 nack pli
a=fmtp:37 profile-id=3
a=rtpmap:38 rtx/90000
a=fmtp:38 apt=37
a=rtpmap:102 H264/90000
a=rtcp-fb:102 goog-remb
a=rtcp-fb:102 transport-cc
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtpmap:103 rtx/90000
a=fmtp:103 apt=102
a=rtpmap:104 H264/90000
a=rtcp-fb:104 goog-remb
a=rtcp-fb:104 transport-cc
a=rtcp-fb:104 ccm fir
a=rtcp-fb:104 nack
a=rtcp-fb:104 nack pli
a=fmtp:104 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
a=rtpmap:105 rtx/90000
a=fmtp:105 apt=104
a=rtpmap:106 H264/90000
a=rtcp-fb:106 goog-remb
a=rtcp-fb:106 transport-cc
a=rtcp-fb:106 ccm fir
a=rtcp-fb:106 nack
a=rtcp-fb:106 nack pli
a=fmtp:106 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:107 rtx/90000
a=fmtp:107 apt=106
a=rtpmap:108 H264/90000
a=rtcp-fb:108 goog-remb
a=rtcp-fb:108 transport-cc
a=rtcp-fb:108 ccm fir
a=rtcp-fb:108 nack
a=rtcp-fb:108 nack pli
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
a=rtpmap:109 rtx/90000
a=fmtp:109 apt=108
a=rtpmap:127 H264/90000
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d001f
a=rtpmap:125 rtx/90000
a=fmtp:125 apt=127
a=rtpmap:39 H264/90000
a=rtcp-fb:39 goog-remb
a=rtcp-fb:39 transport-cc
a=rtcp-fb:39 ccm fir
a=rtcp-fb:39 nack
a=rtcp-fb:39 nack pli
a=fmtp:39 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=4d001f
a=rtpmap:40 rtx/90000
a=fmtp:40 apt=39
a=rtpmap:41 H264/90000
a=rtcp-fb:41 goog-remb
a=rtcp-fb:41 transport-cc
a=rtcp-fb:41 ccm fir
a=rtcp-fb:41 nack
a=rtcp-fb:41 nack pli
a=fmtp:41 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=f4001f
a=rtpmap:42 rtx/90000
a=fmtp:42 apt=41
a=rtpmap:43 H264/90000
a=rtcp-fb:43 goog-remb
a=rtcp-fb:43 transport-cc
a=rtcp-fb:43 ccm fir
a=rtcp-fb:43 nack
a=rtcp-fb:43 nack pli
a=fmtp:43 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=f4001f
a=rtpmap:44 rtx/90000
a=fmtp:44 apt=43
a=rtpmap:45 AV1/90000
a=rtcp-fb:45 goog-remb
a=rtcp-fb:45 transport-cc
a=rtcp-fb:45 ccm fir
a=rtcp-fb:45 nack
a=rtcp-fb:45 nack pli
a=rtpmap:46 rtx/90000
a=fmtp:46 apt=45
a=rtpmap:47 AV1/90000
a=rtcp-fb:47 goog-remb
a=rtcp-fb:47 transport-cc
a=rtcp-fb:47 ccm fir
a=rtcp-fb:47 nack
a=rtcp-fb:47 nack pli
a=fmtp:47 profile=1
a=rtpmap:48 rtx/90000
a=fmtp:48 apt=47
a=rtpmap:112 H264/90000
a=rtcp-fb:112 goog-remb
a=rtcp-fb:112 transport-cc
a=rtcp-fb:112 ccm fir
a=rtcp-fb:112 nack
a=rtcp-fb:112 nack pli
a=fmtp:112 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f
a=rtpmap:113 rtx/90000
a=fmtp:113 apt=112
a=rtpmap:114 H264/90000
a=rtcp-fb:114 goog-remb
a=rtcp-fb:114 transport-cc
a=rtcp-fb:114 ccm fir
a=rtcp-fb:114 nack
a=rtcp-fb:114 nack pli
a=fmtp:114 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=64001f
a=rtpmap:115 rtx/90000
a=fmtp:115 apt=114
a=rtpmap:116 red/90000
a=rtpmap:117 rtx/90000
a=fmtp:117 apt=116
a=rtpmap:118 ulpfec/90000
a=rtpmap:49 flexfec-03/90000
a=rtcp-fb:49 goog-remb
a=rtcp-fb:49 transport-cc
a=fmtp:49 repair-window=10000000
ICE は P2P での通信を確立するための仕組みです。実際に P2P でのデータをやりとりするのはまた別です。
ピアが利用可能な経路を収集(Gathering)して、その中から最適な経路を選択します。 最適な経路というのは優先度によって決められます。この優先度というのは、 ローカルネットワークが一番高く、リレー(TURN)が一番低くなります。
- RFC 8445: Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal
- RFC 8839: Session Description Protocol (SDP) Offer/Answer Procedures for Interactive Connectivity Establishment (ICE)
- ゲームでよくある「NAT タイプ」はどう判定しているの?
- How NAT traversal works · Tailscale
SDP と ICE はセットで利用されます。SDP に ice-uflag と ice-pwd が乗っかってきます。 この ice-uflag と ice-pwd は STUN パケットを送る際に Fingerprint や Message-Integrity に利用され、メッセージの認証メカニズムとして利用されます。
STUN は、NAT を経由するネットワーク上のデバイスが自分のパブリック IP アドレスとポートを発見することを支援しますためのプロトコルです。
グローバル環境にいる STUN サーバに STUN リクエストを飛ばして、自分の IP アドレスとポートを返してもらいます。 プロトコル自体はとてもシンプルなモノです。WebRTC で STUN を利用する場合は認証も暗号化も行いません。 STUN プロトコルは UDP を利用します。
TURN は NAT 越えができない場合にリレーするプロトコルです。 TURN があることで NAT 越えができない時に無理矢理サーバー経由で通信を行います。
TURN は通信の復号してしまうとよく勘違いされますが、 TURN はリレーサーバーなので、一切通信自体には手を加えません。
TURN には UDP / TCP / TLS over TCP / DTLS over UDP があり、さらに IPv4 / IPv6 も可能です。
-
RFC 6062: Traversal Using Relays around NAT (TURN) Extensions for TCP Allocations
-
Allocate-Request
-
Permission-Request
-
ChannelBind-Request
-
Send-Indication / Data-Indication
WebRTC で利用する TURN-TCP は TURN-UDP over TCP であって、TURN-TCP over TCP ではありません。
TURN には優先度という概念がありません。すべての TURN 経路に対して allocate-request を送信します。 allocate-request というのは TURN の経路を確保するためのリクエストです。
TURN Urls の払い出しに TURN-UDP と TURN-TCP と TURN-TLS を設定しているのであれば、 TURN-UDP と TURN-TCP と TURN-TLS のすべてに allocate-request を同時に送信します。 そして一番早く帰ってきた経路を利用します。
WebRTC で利用する TURN-TCP は厳密には TURN-TCP ではなく TURN-UDP over TCP です。 本来の TURN TCP 拡張の実装ではありません。TURN TCP 拡張はコントロールとデータにわけて TCP を張るのですが、WebRTC ではコントロールとデータを同じポートでやりとりします。つまり TCP 拡張は利用されていません。
RFC 6062 - Traversal Using Relays around NAT (TURN) Extensions for TCP Allocations
RTP は音声と映像をリアルタイムでやりとりするためのプロトコルです。基本的に UDP を想定しています。 RTP は暗号化の機能は持っておらず、暗号化する場合は SRTP を利用します。
プロトコル自体もシンプルで、ヘッダーにはシーケンス番号やタイムスタンプなどが入っており、あとはペイロード (実際の音声や映像がエンコードされたバイナリ) が含まれているだけです。
RTP は分割の機能を持っています、これは MTU に収まらない場合に分割して送信するための機能です。 4K の映像を送る場合とかは 15 Mbps 必要なので、かなり細かく分割する必要があります。
- RFC 3550 - RTP: A Transport Protocol for Real-Time Applications
- RFC 5761 - Multiplexing RTP Data and Control Packets on a Single Port
- RFC 8108 - Sending Multiple RTP Streams in a Single RTP Session
- RFC 8860 - Sending Multiple Types of Media in a Single RTP Session
WebRTC では多くの RTP ヘッダー拡張が採用されています。これは主に libwebrtc が勝手に定義してます。 libwebrtc というか Google が、です。
RTP ヘッダーは決められた値以外の値を入れる場所がないので拡張を利用します。 拡張は SDP でお互いが利用できる拡張をハンドシェイクします。 もし利用できない拡張が送られてきても無視する必要があります。
- RFC 6464 - A Real-time Transport Protocol (RTP) Header Extension for Client-to-Mixer Audio Level Indication
- RFC 6465 - A Real-time Transport Protocol (RTP) Header Extension for Mixer-to-Client Audio Level Indication
- docs/native-code/rtp-hdrext/abs-send-time - src - Git at Google
- docs/native-code/rtp-hdrext/abs-capture-time - src - Git at Google
- RFC 8852 - RTP Stream Identifier Source Description (SDES)
- https://www.rfc-editor.org/rfc/rfc5450.txt
- docs/native-code/rtp-hdrext/video-content-type - src - Git at Google
- docs/native-code/rtp-hdrext/video-timing - src - Git at Google
- docs/native-code/rtp-hdrext/video-layers-allocation00 - src - Git at Google
- RTP Payload Format For AV1
- docs/native-code/rtp-hdrext/video-frame-tracking-id - src - Git at Google
- WebRTC header extensions review
- Video BFrame RTP Header Extension
RTP はデータを運ぶプロトコル、RTCP はそれをコントロールするプロトコルです。 WebRTC では統計情報や状態の通知、全画面要求や再送要求、帯域推定などに利用されています。
- RFC 3550: RTP: A Transport Protocol for Real-Time Applications
- RFC 5506 - Support for Reduced-Size Real-Time Transport Control Protocol (RTCP): Opportunities and Consequences
- RFC 7022: Guidelines for Choosing RTP Control Protocol (RTCP) Canonical Names (CNAMEs)
RTP 拡張と RTCP を利用した輻輳制御の仕組みです。
WebRTC で利用されている音声や映像の暗号化は SRTP というプロトコルを利用しています。これは RTP のセキュア版です。 ただ暗号化ということはどうにかして双方で同じ鍵を持つ必要があります。WebRTC ではこの双方で同じ鍵を持つ方法に DTLS を利用しています。
メディアトランスポートでは SRTP 向けの暗号鍵生成用に DTLS のハンドシェイクを利用しています。 メディアトランスポートだけを利用する場合はアプリケーションデータは利用されません。
DTLS で取得した MasterSecret を利用して SRTP/SRTCP の鍵を生成します。
シグナリングというのは WebRTC を P2P で利用するにあたり SDP 情報を交換する手段です。 簡単に言うと Offer と Answer のやりとりします。
WebRTC でシグナリングの規格は定義されていません。
シグナリングなどの再標準化も意識的に行いませんでした。 これはすでに SIP やその他の IETF 以外の取り組みで解決されており、非常に政治的な問題になりかねないと考えたからです。最終的には、この空間に加えるべき価値があまりないと感じたのです
シグナリングを担当することをシグナリングサーバーと呼びます。クライアントから SDP を受け取ってもう一つのクライアントに SDP を渡し、その SDP に対応する SDP を受け取り、クライアントへ渡すという仕組みです。
sequenceDiagram
participant C1 as クライアント1
participant SS as シグナリングサーバー
participant C2 as クライアント2
C1->>SS: type: offer
SS->>C2: type: offer
C2->>SS: type: answer
SS->>C1: type: answer
note over C1,C2: ICE
note over C1,C2: DTLS
note over C1,C2: WebRTC 確立
シグナリングに通常の HTTP を使うやり方もあります。ただし、offer を通知する仕組みが必ず必要になるので、 SSE を使うなどする必要があります。
sequenceDiagram
participant C1 as クライアント1
participant SS as シグナリングサーバー
participant C2 as クライアント2
C1->>SS: type: offer
note right of SS: ここを SSE などでなんとかする必要がある
SS->>C2: type: offer
WebSocket が利用されるのかというと、双方向のやりとりがとても簡単だからです。とはいえ XHR と SSE でも困りません。
WebSocket を利用すると、WebRTC でよく使われるメッセージングを実装することができます。そのため WebSocket が利用されることが多いためと、考えています。
sequenceDiagram
participant C1 as クライアント1
participant SS as シグナリングサーバー
participant C2 as クライアント2
par
note over C1,SS: WebSocket 確立
and
note over SS,C2: WebSocket 確立
end
C1->>SS: type: offer
SS->>C2: type: offer
WebRTC ではシグナリングの規格が定義されていませんが、 これだと困る場合があります。それは 配信ツール を利用する場合です。
OBS というオープンソース (GPLv3) の配信ツールがあります。これから WebRTC を利用するにはシグナリングの規格が必要です。
そこで登場したのが WHIP です。WHIP はとてもシンプルな規格です。WHIP はマルチストリームには対応せず、あくまで音声トラックと映像トラックを 1 ずつの 1 ストリームを扱います。
sequenceDiagram
participant OBS as OBS
participant WE as WHIP Endpoint
participant MS as Media Server
participant WS as WHIP Resource
OBS->>+WE: HTTP POST (SDP Offer)
WE-->>-OBS: HTTP 201 Created (SDP Answer)
note over OBS,MS: ICE
note over OBS,MS: DTLS
note over OBS,MS: WebRTC 確立
OBS->>+WS: HTTP DELETE
WS-->>-OBS: HTTP 200 OK
WHIP 配信用のシグナリング規格ですが、 WHEP は視聴用のシグナリング規格です。
WebRTC を一度確立してしまえば、シグナリングにデータチャネルを使うこともできます。 一度確立したのにシグナリング使うのか?と思うかも知れません。これはマルチトラックやマルチストリームで再ハンドシェイクする必要があります。
マルチストリームを利用する場合は、再ハンドシェイクが必要になります。再ハンドシェイクは re-offer と re-answer と呼ばれています。
その際 SDP の m= の数を減らすことはできません。
WebRTC では様々なセキュリティの技術が利用されています。SRTP/SRTCP や DTLS 、さらには SDP を利用した証明書の Fingerprint チェック、STUN ice-ufrag / ice-pwd 、TURN の usrename / credential。
RFC 8826 - Security Considerations for WebRTC
- STUN と TURN
- Fingerprint
- Message-Integrity
- DTLS-SRTP
- SCTP over DTLS
現在の WebRTC のトレンドについて説明します。簡単に言えば、最近導入された技術です。
AV1 は Alliance for Open Media が開発しているコーデックで、VP9 よりも圧縮率が高いといわれています。
- Chrome 90 から WebRTC でも AV1 が利用できるようになり、 Chrome 113 からサイマルキャストで AV1 が利用可能になりました
- Edge 121 から WebRTC が AV1 が利用できるようになっています
- Safari は Technology Preview で AV1 が利用できるようになっています
- Firefox は対応していません
AV1 はリリース初期は負荷がとても高かったのですが今はほとんど VP9 と変わりません。
- Google Developers Japan: Chrome 90 ベータ版: WebRTC 用 AV1 エンコーダ、新しいオリジン トライアルなど
- RTP Payload Format For AV1
- Chrome M90 で WebRTC の AV1 が利用できるようになった
- Safari Technology Preview で WebRTC AV1 が利用可能になった
H.265 は H.264 の次のコーデックです。ただパテント周りが色々たいへんなことになっています。 ただ Apple の Safari 18 で対応しました。さらにブラウザ外では積極的に利用されています。 これは RTSP などの監視カメラ向けのコーデックがほぼ H.265 が採用されているためのようです。
libwebrtc でも H.265 の対応が進んでおり、 Chrome でもフィールドトライアル機能として既に試すことができます。
- Added HEVC parser for WebRTC
- RFC 7798: RTP Payload Format for High Efficiency Video Coding (HEVC)
- draft-aboba-avtcore-hevc-webrtc-01
少し時雨堂の宣伝が入ります
- サイマルキャストの複数のストリームは同じコーデックでしたが、それを異なるコーデックにする仕組みです
- 既に W3C に仕様は存在しますが libwebrtc には実装されていませんでした
- 現在、時雨堂が Google のサポート実装を進めています
SVC は 1 ストリームに複数画質を押し込める仕組みです。
- Scalable Video Coding (SVC) Extension for WebRTC
- WebRTC SVC 拡張と AV1 コーデック
- Mastering the AV1 SVC chains - Dolby.io
SFU と SVC の組み合わせにはパテントが存在するため、利用する場合は注意してください。
ICE Restart はネットワークインターフェースの変更、たとえば LTE から Wifi への切り替えなどで発生する際に、必要な機能です。通常 IP アドレスが変わると、WebRTC は切断されてしまいますが、ICE Restart を利用し ICE で新規にペアを発見することで新しい接続を行います。
ICE Restart が発生すると DTLS はやり直しが入ります。ただペアリングがすぐ終われば DTLS 自体の通信は一瞬です。 そのため、一瞬音声や映像が止まると感じることはあります。
TURN を利用していたとしてもこれは同じで、新しく Allocate Request を利用してコネクションを張り直します。
OBS Studio v30 で利用可能になります、 配信ツールへ WebRTC が利用される良いきっかけになると思っています。
まずは H.264 から始まり、今は AV1 への対応が進められています。サイマルキャストへの対応も予定されています。 AV1 への対応は OBS Studio v30.1 で利用可能になる予定です。現在 v30.1 beta が提供されています。
WHIP 自体は Twitch が対応し始めています。おそらくこれから多くの配信サービスで WHIP への対応が始まると思います。
WHIP とは逆の視聴用の仕組みです。
- WebRTC-HTTP Egress Protocol (WHEP)
- Example setup of a combined MPEG-DASH and WebRTC distribution | by Eyevinn Technology | Medium
- DASH and webRTC-based Streaming | webRTC
あまり興味がある人はいないと思いますが、簡単にだけ触れていこうと思います。
E2EE というのは End to End Encryption の略で、クライアント同士のみで暗号化をする仕組みです。WebRTC P2P は E2EE といって問題無いです。
SFU で E2EE を行う場合はクライアント側で WebRTC とは別に暗号化をする必要があります。
- RFC 9605 - Secure Frame (SFrame): Lightweight Authenticated Encryption for Real-Time Media
- RFC 9420 - The Messaging Layer Security (MLS) Protocol
WebRTC SFU と E2EE は多くのサービスで利用されています。WhatsApp や Signal や Facebook Messange。MS Teams や Google Meeting、 Facetime でも採用されています。
最近では Discord が WebRTC の E2EE を実装しています。
Meet DAVE: Discord’s New End-to-End Encryption for Audio & Video
WebRTC が複雑すぎたということで、 Media over QUIC (MoQ) というのが出てきています。今後はこちらが主流になっていくと思いますが、だからといって WebRTC が廃れることはありません。今後 10 年は WebRTC は続いていくと考えて問題ありません。
Opus は WebRTC の音声で利用されているプロトコルで、 1.5 により大幅な改善が行われました。
Opus の開発者は現在 Amazon にいます。
- Opus 1.5 Released
Opus Gets a Serious Machine Learning Upgrade
- Deep Audio Redundancy (DRED) Extension for the Opus Codec
- Extension Formatting for the Opus Codec
IoT 向けの仕様ですが、DTLS のハンドシェイクコストを減らすための仕組みです。 CID を利用する事でハンドシェイクをスキップします。
RFC 9146: Connection Identifier for DTLS 1.2
MOQT はパブリッシュ/サブスクライブモデルによる統合メディアストリーミングプロトコルです。 QUIC または WebTransport を利用します。
特徴としては規格にリレー機能を組み込む事で、 数百万人への配信といったような超大規模な配信を目的としています。
MOQT は libwebrtc に当たる実装は https://github.com/google/quiche/tree/main/quiche/quic/moqt にありますが、音声や映像コーデックの処理から帯域推定まで全て自前でやる必要があります。
また MOQT 自体はあくまで土管でしかないため、その上に配信用のプロトコルを実装する必要があります。
現時点では MOQT は片方向がメインです、双方ができないわけではありませんが、まだまだ先と考えて良いでしょう。
- QUIC
- HTTP/3
- HTTP/2 へのフォールバック
HTTP/3 上の WebTransport と HTTP/2 上の WebTransport を使用して、サーバーにデータを送信し、サーバーからデータを受信します。WebSocket と同様に使用できますが、複数のストリーム、一方向のストリーム、アウトオブオーダーデリバリー、信頼性のあるトランスポートと信頼性のないトランスポートをサポートしています。
MOQT ではコーデックのハンドリングは自前で行う飛鳥があるため、ブラウザの場合は WebCodecs という仕組みが提供されています。 音声、映像、画像の符号化・復号化のためのコーデックへのインタフェースを定義する仕様です。 WebCodecs はあくまでインターフェースです。
MOQT を利用するには WebCodecs と WebTransport を組み合わせ、さらにその上に MOQT を実装し、さらにその上に配信用のプロトコルを実装する必要があります。LOC や WARP などがそのプロトコルの一例です。
MOQT とは異なる戦略として WebTransport で双方向はすでに試されていますが、結果的には RTP を載せるという話になっています。
WebRTC SFU Sora 入門では時雨堂が開発する WebRTC SFU である、Sora についてお話をしていきます。
ここからは時雨堂製品の宣伝がメインになります。
WebRTC SFU は現時点で WebRTC をビジネスで利用する場合のデファクトスタンダードです。 WebRTC 本来の P2P の利用ではなく、クライアントサーバーモデルです。
- WebRTC SFU とは
- WebRTC SFU が出てきた背景
- クライアント側のスペックが上がった
- クライアント側の帯域が出るようになった
- サーバーマシンのスペックが上がった
- MCU が衰退した背景
- なぜ WebRTC SFU を採用するのか
- WebRTC SFU のユースケース
- WebRTC SFU における TURN
- 必要かどうかと言われると必要です
- TURN-TLS を使いたい場合は必要で す
WebRTC SFU に決められた仕様というのは存在しません。 そのため、世の中にある WebRTC SFU はそれぞれが独自の仕様を持っています。
時雨堂の Sora も完全に独自仕様です。
- ブラウザの WebRTC と繋がること
- WebRTC で扱っている音声、映像、データを転送できること
おそらくこれだけです。なので基本的に誰でも WebRTC SFU を名乗れます。
- 負荷
- PLI ストーム (勝手に命名)
- 帯域推定 / 輻輳制御
- 大規模
時雨堂が 1 から Erlang/OTP というマニアックな言語で開発している WebRTC SFU です。 依存ライブラリがとても少なく、WebRTC 関連のプロトコルは全て自前実装です。
https://sora-doc.shiguredo.jp/OSS_LICENSE
Sora は 2015 年 12 月に正式版をリリースしました。
WebRTC SFU はシンプルな機能になりがちなのですが、Sora は多くの機能を持っています。
今回はそれらの機能を色々と紹介していきます。
Sora はよくある WebRTC SFU のサービスとは異なり、自分で運用出来るパッケージ製品です。
WebRTC SFU はサーバ経由で音声や映像、データを転送するため、転送量がかかります。
自分たちで運用できるようにすることで、コストを削減できるようにしています。
- Sora JavaScript SDK
- Sora iOS SDK
- Sora Android SDK
- Sora Unity SDK
- Sora C++ SDK
- Sora C SDK
- libdatachannel 利用
- Sora Python SDK
- https://sora-doc.shiguredo.jp/
- 正式版ドキュメント
- https://sora-doc-canary.shiguredo.jp/
- 開発版ドキュメント
Sora は WebSocket を利用したシグナリングの他に、データチャネルを利用したシグナリングも利用できます。 WebSocket だけを利用する事もできますし、WebSocket とデータチャネルの併用、データチャネルだけを利用することもできます。
https://sora.shiguredo.jp/features#signaling
シグナリングは WebSocket からデータチャネルにシームレスに切り替わります。
SSE (Server Side Event) を採用するという方法もありましたが、 認証を考えると SDK 側が少しでもシンプルになると言うことを考えました。
WebSocket は 1 度張ってしまえば、その後は認証する必要がありません。
また、WebRTC は思った以上に SFU からの通知が必要です。 さらに切断されたタイミングを SFU が把握するには TCP があるととても便利です。
WebSocket は思った以上に切れやすいという問題がありました。 WebSocket が切れても DataChannel が接続できれば ... なんとでもなるという考えです。
Sora は後述しますが TURN を組み込んでいるため TCP しか繋がらないところでも問題無く DataChannel が利用できます。 そのため DataChannel をシグナリングに利用しても上手く動かないということはありません。
Sora ではシグナリングに利用する WebSocket / DataChannel を利用して、 他のクライアントの参加タイミングや切断タイミングを通知します。
それ以外にも色々な通知を Sora からリアルタイムで通知します。
そのため、他の仕組みを要する必要がありません。
Sora を利用する際は TURN サーバーを別途立てる必要がありません。 なぜなら Sora は TURN サーバーを内蔵しているからです。むしろ Sora は常 TURN プロトコルを利用します。
今皆さんが繋いでいるのは TURN サーバーであり Sora でもあります。
なぜ TURN 経由?
- SDP -> ICE -> DTLS -> SRTP
- TURN が無い場合
- SDP -> TURN -> DTLS -> SRTP
- TURN を強制する場合
強制的に TURN を利用する事で ICE のチャレンジを行う必要がありません。 さらに TURN には認証の仕組みが入っています。セキュリティ的にメリットがとても多いです。
W3C WebRTC API には TURN のみを使用する仕組みが用意されています。
https://www.w3.org/TR/webrtc/#dom-rtcicetransportpolicy-relay
Sora は 1 接続で複数の音声や映像を送受信することができます。 送信は音声、映像一つずつのみですが、受信はいくらでも増やすことができます。
動的にストリームを管理することで実現しています。これは WebRTC API の機能の一つです。
https://sora.shiguredo.jp/features#multistream
Sora は複数画質を同時に配信することができます。WebRTC では SFU で映像を変換をしていたら間に合わないので、 クライアントが最初から複数画質を配信することが一般的です。 視聴者は複数の画質から「選択する」というのは HLS などのライブストリーミングと同様です。
https://sora.shiguredo.jp/features#simulcast
ちなみに、最近では Twitch が OBS からの複数画質配信に対応する支援を行っています。
時雨堂は Twitch のテクノロジーパートナーです。
高画質は H.265 で低画質は AV1 で配信というようなことができる仕組みです。 現時点ではまだ libwebrtc には入っておりません。 現在、時雨堂が Google から支援を受けつつ実装を進めています。
- https://webrtc.googlesource.com/src.git/+/bcb19c00ba8ab1788ba3c08f28ee1b23e0cc77b9
- https://webrtc.googlesource.com/src.git/+/c42162cacb762b3a343a0b7bd398ce77dd4ff69e
- https://webrtc.googlesource.com/src.git/+/e68cb78ee72bb61efa50d03f304e1da159f23be5
Sora は独自の機能としてスポットライト機能というアクティブな話者のストリームだけを配信する仕組みを持っています。 10 人参加している会議で話をする人は多くても 2-3 名です。
なのに他の人の映像をリアルタイムに配信していたら、帯域や CPU が無駄になります。 これが 50 人規模ならなおさらです。
Sora ではアクティブな話者だけ高画質&音声配信、 それ以外はストリーミング自体を Sora から止めてしまうという仕組みを持っています。これは全て自動で行われます。
https://sora.shiguredo.jp/features#spotlight
Sora では WebRTC の音声や映像を SFU 側で録画する仕組みを持っています。 さらにこの録画機能は無変換で行うため、SFU 側の負荷は発生しません。
WebRTC から WebM や MP4 (2024 年 12 月対応) に無変換で保存します。
https://sora.shiguredo.jp/features#recording
Sora は認証の仕組みは持っていますが、認証を判断する仕組みは持っていません。 ウェブフック送信先からの戻り値を見て認証を行います。
ウェブフックからの戻り値が {"allowed": true}
であれば、そのクライアントは接続を許可します。
そのため、Sora からデータベースへ接続に行ったり、Sora に六十区を組み込む必要がありません。
それ以外も全ての情報はウェブフックによって送信されます。
Sora 自体へのアクションは全て HTTP API を利用します。
ウェブフックと HTTP API を利用して、Sora は他のシステムと連携します。
Sora では常時接続しているシグナリング用の経路を利用して、HTTP API 経由でクライアントにプッシュ通知を送信することができます。 プッシュ通知と言ってもただの JSON メッセージが送れるだけです。
http POST 127.0.0.1:3000/ \
x-sora-target:Sora_20160711.PushChannel \
channel_id=sora \
data:="{\"spam\": \"egg\"}" \
-vvv
Sora は単体(シングルノード)でも動作しますが、クラスター機能を利用することで、大規模な配信ができるようになり、冗長構成が取れるようになります。
Sora のクラスターは Raft ベース分散システムを構築しています。Raft に付いては簡単に口頭で説明します。 詳しく知りたい人は以下の資料を読むことをオススメします。
最低 3 ノード、推奨は 5 ノードのレギュラーノード(投票権を持つノード) で構成します。 5 ノードであれば 3 ノードが同時に障害が発生しない限り、クラスターは動作します。
https://sora.shiguredo.jp/cluster
Sora には投票権を持たないテンポラリーノードが存在します。 投票権を持たないため、スケールイン時に気軽にクラスターから離脱させられます。ただサーバーを落とすだけで良いです。
そのため、基本はレギュラーノードを 5 ノードで、あとのノードは全てテンポラリーノードで構成します。 テンポラリーノードを利用する事で、スケールアウトとスケールインがしやすい構成になります。
Sora のクラスターにはアフィニティ機能と呼ばれる 寄せ を行う仕組みが搭載されています。 これは同じチャネル(ルームのようなもの)の接続を同じノードに寄せる機能です。
当たり前ですが WebRTC は遅延を抑えることが最優先なので、 できるだけ同一ノードに参加する方が遅延が減るためです。
アフィニティには cluster_affinity_threshold というパラメータがあり、これは同一ノードに寄せる接続数を指定できます。 この値が 3 であれば最大 3 接続までは同一ノードに寄せますが、4 からは別ノードを利用するようになります。
Sora のクラスター機能はロードバランス機能も持っています。空いているノードにリダイレクトして接続を促します。 もちろん 1 チャネルの接続数に影響はしますが、100 接続がある場合、5 ノードの場合は 20 接続ずつになるように調整します。
ロードバランス機能とアフィニティ機能とテンポラリーノードを組み合わせることで好きなだけスケールできる WebRTC SFU が実現できます。
Sora はメディア配信ワーカーという機能をもっています。これは単に Sora が配信する際の内部的なワーカー数を調整できるという仕組みです。 通常は 1 ワーカーで配信を行うのですが、これを増やしたり減らしたりできます。スレッドプールのスレッド数が調整できるようなものです。
このおかげで、1 ノードでも高ビットレートかつ大規模な配信が可能になります。
Sora はログ出力時にセンシティブなデータを "REDACTED"
という文字列に変更して出力する仕組みを持っています。
これは時雨堂がサポートでログを受け取るときに不必要な情報を受け取らないようにするためです。
去年 OBS が WebRTC に対応しました。Sora はこの OBS が対応している WHIP/WHEP にも対応しています。
Sora では WebRTC の音声ストリームを外部サービスに送信する仕組みを持っています。 これは主にリアルタイムな文字起こしを行うための仕組みです。
Sora は音声や映像を特定の条件にだけ転送するというフィルター機能を搭載しています。 これは FW の仕組みにインスパイアされた仕組みです。
実際にシステムに組み込まれるパッケージの場合は細かい転送制御を行いたい場合があります。
{
"action": "block",
"rules": [
// チャネルに接続しているすべてのクライアントへ connection_id "S8YEN0TSE13JDC2991NG4XZ150" からの音声と映像をブロックし転送しない
// また
// チャネルに接続しているすべてのクライアントへ client_id が "screen-share" の音声をブロックし転送しない
[
{
"field": "connection_id",
"operator": "is_in",
"values": ["S8YEN0TSE13JDC2991NG4XZ150"]
}
],
[
{
"field": "client_id",
"operator": "is_in",
"values": ["screen-share"]
},
{
"field": "kind",
"operator": "is_in",
"values": ["audio"]
}
]
]
}
https://sora-cloud.shiguredo.jp/
- Sora のクラウド版
- Sora ほぼ全ての機能が利用できる
- サポート込み
- 申し込んでからすぐ使える
- 月額基本料 5,000 円
- 10 同時接続単位で 15,000 円
- 100 Mbps 帯域単位で 30,000 円
- 接続時間での 課金なし
- 転送量での 課金なし
- 接続回数での 課金なし
- 録画機能利用時の 追加料金なし
- 録画ファイルの S3 や S3 互換のオブジェクトストレージへのアップロード時の 追加料金なし
- 録画合成機能利用時の 追加料金金なし
- TURN 利用での 追加料金なし
- クラスター構成
- 冗長化対応
- スケールアウト対応
- Akamai Connected Cloud
- 低レイテンシーなネットワーク
- 充実したセキュリティ
- 120 ミリ秒程度の遅延で 4K 120fps での配信を 50 人へ問題無くできた
- クラスターのノードを増やすことで数万人への配信でも問題無いと判断できた