このページの目次

WebRTC

ブラウザ間での直接オーディオ・ビデオ転送——WebRTCはSDPでメディアパラメータを交渉し、ICEでNATトラバーサルを行い、DTLS-SRTPで暗号化転送を行います。P2Pの「サーバーを経由しない」ことは性能上の利点であると同時に、デバッグの悪夢でもあります。

概要

WebRTC(2011年)はブラウザに組み込まれたリアルタイム通信の標準規格であり、プラグインなしでビデオ通話、画面共有、P2Pデータ転送を実現します。複数のプロトコルを組み合わせています:SDPによるメディア交渉、ICEによるNAT透過、DTLS-SRTPによるメディア暗号化、SCTPによるデータチャネル。WebRTCの接続確立は非同期で行われ、candidateが一つずつ到着し、一つずつ検証されます。Trickle ICEにより接続時間が大幅に短縮されます。

アーキテクチャスタック

WebRTC アーキテクチャスタック: ブラウザAPIから下層トランスポートプロトコルへ Browser JS API(RTCPeerConnection, RTCDataChannel) WebRTC C++ stack(libwebrtc, Google) SDP メディア交渉 (offer/answer) ICE NAT透過 (STUN + TURN) DTLS 鍵交換 → SRTP鍵を派生 SRTP 暗号化された RTPストリーム SCTP データチャネル UDP(優先) TCP(フォールバック) 5つのプロトコルが「トランスポート層」を構成する——SDP/ICEは接続確立の交渉を担当し、DTLS/SRTPはメディアのセキュリティを管理し、 SCTPはデータチャネルを管理する。すべてはUDP上で動作し、接続できない場合にのみTCPにフォールバックする。

シグナリング: 意図的に空白とされた一环

WebRTC はシグナリングを規定していません⁠——両端がSDPとICE candidateをどのように交換するかは標準では一切規定されず、WebSocket/HTTP/任意のチャネルを使って自分で実装する必要があります。これは意図的な設計です:メディアパスはP2Pである必要がありますが、「まだ接続していない2者が最初にどのように接触するか」には、双方から到達可能なサードパーティが必要です。

シグナリングは紹介役を担当し、メディア/データはP2P直結で通信する シグナリングサーバー(自前構築、任意プロトコル) SDP offer/answer + ICE candidateの交換 Peer A Peer B (交渉完了後) SRTPメディア / SCTPデータ —— P2P直結 シグナリングは「両端がどのように互いを見つけるか」だけを担い、プロトコルは限定されない(WebSocket/HTTPどちらでも可、標準は介入しない)。 一度offer/answerとcandidateの交換が完了すると、メディアとデータはサーバーを完全に迂回して直結する。

まずシグナリングによってoffer/answerが渡され、初めてICEが接続可能なcandidateを持てる——これがWebRTCにおける「鶏が先か卵が先か」の問題である。

SDP 交渉

Caller → Callee (Offer):
  v=0
  o=- 1234567890 2 IN IP4 192.168.1.100
  s=-
  t=0 0
  a=group:BUNDLE audio video data     ← 同一トランスポートパスでのマルチプレクス
  m=audio 49170 UDP/TLS/RTP/SAVPF 111 103
  c=IN IP4 192.168.1.100
  a=rtpmap:111 opus/48000/2
  a=rtcp-mux                           ← RTPとRTCPを同一ポートで共有
  a=ice-ufrag:8sdf7g
  a=ice-pwd:asd88fg
  a=fingerprint:sha-256 AB:CD:...      ← DTLS証明書ハッシュ

Callee → Caller (Answer):
  m=audio 49180 UDP/TLS/RTP/SAVPF 111  ← 選択されたポート + コーデック
  ...

  → 双方の交渉完了 → ICEによる接続チェック開始

ICE

各peerは3種類のcandidateを収集する:

  1. host: ローカルIP:port
  2. srflx (server reflexive): STUNサーバーから返されるパブリックIP:port
  3. relay (relayed): TURNサーバーが割り当てる中継アドレス

各(local candidate + remote candidate)のペアに対して接続チェック(STUN binding)を実行し → 最適な利用可能なペアを選択する(優先度は host > srflx > relay、つまり「直結可能なら中継を使わない」)。

STUNとTURNの役割分担⁠:STUNは単に「自分のパブリックマッピングを問い合わせているだけ」であり、メディアを転送せず、ほぼコストゼロです。しかし、両端が対称型NATの背後にあり、NATトラバーサルが失敗した場合、TURN中継にフォールバックする必要があります——すべてのメディアがそれを介して転送され、帯域幅のコストが高くなります。これはデプロイにおいて唯一避けられないサーバーコストです。本番環境での経験則:接続の約10〜20%が最終的にTURNに到達します。

Trickle ICE:すべてのcandidateの収集が完了するのを待ってからofferを送信する必要はありません。candidateは発見次第シグナリングを通じて相手側に送信され、接続チェックが行われます。これにより、接続確立時間が「最も遅いcandidateを待つ」状態から「最初の利用可能なペアが準備できるまで」に短縮され——これがWebRTCの高速接続確立の鍵です。

DTLS-SRTP

DTLSハンドシェイク(TLS 1.2をUDP上で動作させるもの) → ハンドシェイク完了後、双方はDTLSからSRTP鍵を派生する(追加の交換は行わない):

DTLS ハンドシェイク: ClientHelloからSRTP鍵の派生へ ClientHello ServerHello Certificate ServerKey- Exchange ClientKey- Exchange ChangeCipher- Spec Finished DTLS-SRTP拡張: どのSRTP暗号スイートを使用するかを交渉 双方はDTLS master_secretからSRTP鍵を派生する SRTP keys = SRTP_KDF(DTLS master_secret) SRTP鍵は個別に転送されない——今回のDTLSハンドシェイクで生成されたmaster secretから直接派生され、 このハンドシェイクと自然に紐付けられ、追加の鍵交換ラウンドを省略する。

Data Channel

DTLS上に覆いかぶさるSCTP (Stream Control Transmission Protocol):

TCPと比較して:
  - マルチストリーム (HOLブロッキングなし)
  - メッセージ境界を保持
  - 設定可能:信頼性あり (reliable) / 部分的信頼性 (timed reliability)

適した用途:ファイル転送、ゲームステート、チャット

輻輳制御とSimulcast

リアルタイムメディアはTCPのようにパケット損失と再送に頼ることができない——フレームのデッドラインはわずか十数ミリ秒であり、再送を待つと必ずタイムアウトする。WebRTCはGCC (Google Congestion Control)⁠を使用する:RTPパケットの到着に基づくレイテンシ勾配で輻輳を予測する(キューが増加中 → 早期にビットレートを低下)、実際にパケットが損失するのを待つのではなく、送信側はこれに基づいてエンコードビットレートを動的に調整する。

Simulcast / SVC は、マルチユーザー会議における異種帯域幅の問題を解決する:同じカメラ入力から複数の品質レベル⁠(例:180p/360p/720p)を同時にエンコードし、ミドルウェアサーバーが各受信者のネットワーク状況に応じて適切な品質レベルを個別に配信する——これが以下のSFUが「視聴者ごとに品質を選択できる」前提である。

SFU / MCU / Mesh — マルチユーザートポロジー

WebRTCは本来P2Pであるが、マルチユーザーの場合P2Pはスケーラビリティに欠けるため、サーバーの導入が必須となる。3つのトポロジー(ストリーミングプロトコルにおける配信のトレードオフと同根):

マルチユーザートポロジーの選択: Mesh / SFU / MCU Mesh N人が両者間で直結 → 各ユーザーがN-1本のアップストリーム 3〜4人のみ利用可能、サーバー不要 SFU 選択的転送: サーバーはデコードせず転送のみ、各ユーザーはアップストリーム1本、必要に応じて配信(simulcastと連携) → 主流の解決策、スケーラブル、サーバーCPU負荷が軽い(トランスコード不要) MCU ミキシング: サーバーがすべてのストリームをデコード + 1つのストリームに合成して配信 → 受信側のダウンストリーム/計算リソースを節約できるが、サーバーCPUコストが極めて高い SFUは転送のみでデコードしないため、スケーラビリティとサーバーコストのバランスが取れており、マルチユーザー会議の主流ソリューションである。 Meshは超小規模な場合にのみ適しており、MCUはサーバーの計算リソースでクライアントの軽量さを引き換えるが、コストが最も高くなる。

なぜWebRTCはHLSのようにCDNで展開しにくいのか⁠:各接続には状態がある(ICE/DTLS/SRTPのコンテキスト + リアルタイムの輻輳制御フィードバック)ため、キャッシュ可能なファイルではない。大規模展開はエッジキャッシュではなくSFUのカスケードによってのみ可能——これは「サブ秒のリアルタイム性」がもたらす根本的な代償である。

参考

  • webrtc.org: webrtc.googlesource.com
  • ツール⁠: chrome://webrtc-internals

Keywords: WebRTC, signaling, SDP, ICE, Trickle ICE, STUN, TURN, DTLS-SRTP, SCTP, Data Channel, GCC, simulcast, SVC, SFU, MCU, mesh, Opus