DEEP DIVE: WEBRTC

WebRTC:ブラウザ間をサーバーレスでつなぐリアルタイム通信

ビデオ会議アプリを開くと、映像も音声もチャットメッセージも、多くの場合サーバーを経由せずブラウザ同士で直接やり取りされています。それを実現するのがWebRTC(Web Real-Time Communication)です。シグナリング・NAT越え・暗号化・データ転送という複数の技術を束ね、ブラウザという最も普及したプラットフォームの上にP2P通信を持ち込んだ仕組みを詳説します。

WebRTCとは何か

WebRTCは、ブラウザやモバイルアプリがサーバーを経由せず直接音声・映像・任意のデータをやり取りするためのAPI群とプロトコル群の総称です。2011年にGoogleがオープンソースプロジェクトとして公開し、その後W3C(ブラウザ向けJavaScript API)とIETF(下回りのプロトコル)の双方で標準化が進められ、2021年にW3CのWebRTC 1.0勧告と、IETFのRFC 8825(概要)をはじめとする一連のRFC群として結実しました。それ以前は音声・映像のリアルタイム通信にFlashやネイティブアプリのSDK、あるいは専用プラグインが必要でしたが、WebRTCによって「ブラウザを開くだけ」でP2Pのリアルタイム通信が可能になりました。

WebRTCの核心は、ブラウザという制約の多い環境の中に、シグナリング・NAT越え・暗号化・輻輳制御・メディアコーデックといった、本来なら個別に実装が必要な要素をひとまとめにして「標準API」として提供した点にあります。開発者はRTCPeerConnectionという1つのオブジェクトを操作するだけで、その裏側で動くICE・STUN/TURN・DTLS・SRTP・SCTPといった複雑なプロトコルスタックの詳細を意識せずに済みます。

構成要素

RTCPeerConnection
WebRTCの中心となるAPI。1対のピア間の接続を表し、メディアトラックやデータチャネルの追加、ICE候補の収集、SDPのオファー/アンサーの生成・適用など、接続確立に必要なほぼすべての操作をこのオブジェクトを通じて行う。
MediaStream(getUserMedia)
navigator.mediaDevices.getUserMedia()によってカメラ・マイクなどのデバイスから取得する音声・映像ストリーム。取得したトラックをRTCPeerConnectionに追加することで、相手ピアへ直接送信できるようになる。画面共有用のgetDisplayMedia()も同系統のAPI。
RTCDataChannel
メディア以外の任意データをやり取りするための双方向チャネル。内部的にはSCTP(Stream Control Transmission Protocol)をDTLSの上で運ぶ(SCTP over DTLS)構成になっており、TCPのような信頼性・順序保証のあるモードだけでなく、UDPに近い低遅延・順序不問のモードもorderedmaxRetransmitsといったオプションで選択できる。
ICE(Interactive Connectivity Establishment)
2つのピアの間で実際に通信可能な経路を見つけ出すためのフレームワーク(RFC 8445)。双方が持ちうる複数の候補経路を収集・交換し、実際に疎通確認(コネクティビティチェック)を行った上で最良の経路を選択する。
SDP(Session Description Protocol)
これから確立するメディアセッションの内容(使用するコーデック、メディアの種類、暗号化のパラメータ、ICE候補など)を記述するテキスト形式のフォーマット(RFC 8866)。WebRTCでは「オファー」と「アンサー」という1往復のSDP交換によってセッションの合意を形成する。

接続確立の流れ

  1. シグナリング: 2つのピアがSDPのオファー/アンサーとICE候補を交換する段階。ここで重要なのは、WebRTCの仕様書自体はシグナリングの手段を一切規定していないという点である。SDPさえ届けばよいので、実装は通常WebSocketサーバーやメッセージングサービスを介して行われる。つまりWebRTCの通信自体はP2Pでも、接続の「仲人役」としてサーバーが必要になる。シグナリングの具体的な方式については次節で扱う。
  2. ICE候補収集: 各ピアが自分に到達可能な経路の候補を集める。ローカルのネットワークインターフェースのアドレスであるhost候補、STUNサーバーに問い合わせて判明する公衆網から見た自分のアドレスであるserver reflexive候補、STUN/ICEだけでは直接疎通できない場合の中継点となるrelay候補(TURNサーバー経由)の3種類に大別される。
  3. STUN/TURNによるNAT越え: STUNサーバーは「自分が外からどう見えているか」を教えてくれるだけの軽量なサーバーで、多くのNAT環境ではこれとUDPホールパンチングの組み合わせで直接経路が開通する。対称型NATなど直接接続がどうしても成立しない場合には、TURNサーバーが両者の間でパケットを中継する「最後の手段」として機能する。
  4. DTLSハンドシェイク: 実際の経路が確定すると、その経路上でDTLS(Datagram TLS)によるハンドシェイクを行い、鍵交換と相互認証を済ませる。
  5. メディア/データの送受信: 確立した暗号化経路の上で、音声・映像はSRTP(Secure RTP)、任意データはSCTPが流れ始める。以降の実データはすべてこの暗号化されたトンネルの中を通る。

ここで押さえておきたいのは、「WebRTCはP2Pだが、サーバーレスではない」という点です。シグナリングには必ず何らかのサーバー(あるいは既存の通信チャネル)が必要で、多くの実装ではSTUNサーバーも、直接疎通が失敗した場合の保険としてTURNサーバーも用意されています。さらに、対称型NATやシンメトリックなファイアウォールの組み合わせなど、直接経路がそもそも開通しないケースは実運用上珍しくなく、その場合TURNリレー経由の通信は実質的に「サーバー経由」と変わりません。WebRTCが提供するのは「可能な限り直接接続を試み、ダメならリレーにフォールバックする」という設計であって、サーバーを完全に排除する仕組みではないのです。

シグナリングの詳細

WebRTCのネゴシエーションは、JSEP(JavaScript Session Establishment Protocol、RFC 8829)と呼ばれるモデルに基づいています。JSEPが要求するのは「オファー/アンサーのSDPとICE候補を相手に届けること」だけであり、その運搬手段(WebSocketなのかHTTPなのか、あるいはメールやQRコード、手動のコピー&ペーストであってもよい)を仕様は意図的に規定していません。この自由度がシグナリング実装の多様性を生む一方で、「ICE候補をいつ・どのように交換するか」という設計次第で、接続確立にかかる速度や実装の複雑さは大きく変わってきます。

Non-Trickle ICE(Vanilla ICE)

最も素朴な方式が、Non-Trickle ICE(Vanilla ICEとも呼ばれる)です。setLocalDescription()を呼び出した後、ICE候補の収集がすべて完了するのを待ってから、全候補を書き込んだ完全なSDPを一度だけ交換します。利点は、シグナリングが「オファー1通・アンサー1通」の1往復だけで完結することです。HTTPの単発リクエストやQRコード、手動のコピペのような、リアルタイム性を持たないチャネルでも成立します。一方で欠点もあります。候補収集には複数のネットワークインターフェースの列挙、STUNサーバーへの問い合わせ、TURNサーバーへの割り当て要求(NAT越えを参照)などが含まれ、応答のないサーバーのタイムアウト待ちも発生しうるため、収集完了までに数秒かかることも珍しくありません。その間ユーザーは接続が始まらないまま待たされることになり、接続確立の体感速度が重要な用途にはあまり向きません。

Trickle ICE

Trickle ICE(RFC 8838)は、候補収集の完了を待たずにシグナリングを開始する方式です。まず候補ゼロ(または収集済みの一部)のSDPを即座に送信し、その後見つかった候補をonicecandidateイベントが発火するたびに1つずつ「滴らせる(trickle)」ように逐次送信していきます。受信側はaddIceCandidate()で到着した候補をその都度追加でき、届いた候補から順に疎通確認(コネクティビティチェック)を始められます。SDPの交換・候補収集・疎通確認が並行して進むため、接続確立にかかる時間は大幅に短縮されます。実際、ブラウザのWebRTC実装はデフォルトでTrickle ICEを前提に動作します。ただしこの方式には、候補を随時送受信できる双方向・低遅延のシグナリングチャネル(WebSocketなど)が前提条件として必要です。両端がTrickleに対応していることが望ましいものの、非対応の相手に対してはNon-Trickleとして振る舞う(=全候補が揃ってから送る)ことで後方互換性は保たれます。

WHIP / WHEP:HTTPベースの標準シグナリング

シグナリングの手段が自由であることは、裏を返せばサービスごとに独自プロトコルが乱立し、配信機材やソフトウェア間の相互運用性が失われることを意味します。この問題に対してIETFが標準化したのが、HTTPの1往復だけでSDPを交換するWHIP(WebRTC-HTTP Ingestion Protocol、RFC 9725)です。OBS Studioのようなエンコーダーがメディアサーバーへ映像を「押し込む」取り込み(ingest)用の仕様で、SDPオファーをHTTPのPOSTリクエストとして送信し、レスポンスとしてアンサーを受け取るだけで接続が確立します。視聴側(egress)に対応する仕様がWHEP(WebRTC-HTTP Egress Protocol)で、こちらも標準化が進められています。背景にあるのは、長らくライブ配信の取り込みを担ってきたRTMPを、サブ秒遅延を実現できるWebRTCで置き換えたいという動機です。基本形は1往復で完結するNon-Trickle的な設計ですが、HTTPのPATCHメソッドを使ったTrickle ICEやICE restartもオプションとして規定されています。OBS StudioをはじめとするエンコーダーソフトウェアやCDN、メディアサーバーの多くが対応を進めており、WHIPは「WebRTC版RTMP」とも呼べる地位を確立しつつあります。

以上3方式の違いを整理すると、次のようになります。

観点Non-Trickle(Vanilla)Trickle ICEWHIP/WHEP
SDP交換の回数・形態オファー/アンサーを1往復(全候補を含む完全なSDP)最小限のSDPを先行送信し、候補は逐次追加HTTPのPOST/PATCHによる1往復(拡張でTrickleも可)
候補の送り方収集完了後にまとめて送信onicecandidateごとに逐次送信基本は一括、PATCH併用時は逐次
接続確立の速さ収集完了まで待つため遅い(数秒かかることも)収集と並行して疎通確認が進むため速い1往復で完結するため速い
必要なチャネルリアルタイム性不要(HTTP単発、QRコード、コピペ等)双方向・低遅延(WebSocket等)HTTPクライアント/サーバー
主な用途簡易な1対1接続、非対話的なチャネル経由の接続一般的なブラウザ間のWebRTC接続ライブ配信の取り込み(ingest)・配信(egress)

メッシュシグナリング:サーバーレスへの道

一度P2Pメッシュがある程度育てば、確立済みのP2P接続そのものを、新規接続のシグナリング経路として再利用できます。すでにメッシュへ参加しているノードが仲介者となり、新しいピアとのSDP/ICE候補の交換を、既存のデータチャネル越しに中継するという発想です。シグナリングサーバーが処理する負荷は下がり、サーバー障害への耐性も上がります。

ただし鶏と卵の制約は残ります。まだ1本も接続を持たない新規参加者にとっての「最初の1本」だけは、必ず何らかの外部ブートストラップ(シグナリングサーバー、リレー、あるいは既存の通信チャネル)が要ります。P2Pシグナリングが有効になるのは、あくまでネットワークがある程度育った後の話です。

発展形として、専用のシグナリングサーバーの代わりにNostrのような汎用pub/subリレーをシグナリングの搬送路に使う構成もあります。この場合のプライバシー設計の定石は、シグナリング専用の使い捨ての一時鍵を発行してアプリの永続的なアイデンティティから分離し、本来のIDはリレー運営者にも見えないよう暗号化されたペイロードの中にのみ含めることです。

セキュリティ

WebRTCでは、メディアもデータチャネルも暗号化が必須です。仕様上、暗号化なしの通信という選択肢自体が存在しません。DTLSでセッション鍵を交換し、音声・映像はSRTP、データチャネルはDTLS上のSCTPによって、常に暗号化された状態で送受信されます。

  • IPアドレス漏洩の懸念: ICE候補の収集過程では、ブラウザがローカルネットワークのプライベートIPアドレスや、STUNサーバーへの問い合わせによって判明する公衆網上のグローバルIPアドレスを候補として生成する。VPNを利用していても、この候補生成の仕組みによって本来のIPアドレスが露出してしまう「WebRTC IPリーク」がかつて問題視された。
  • mDNS候補による緩和: 現在の主要ブラウザでは、ローカルのhost候補をそのままのIPアドレスで公開する代わりに、ランダムな.localホスト名(mDNS)に置き換えて共有する仕組みが標準で有効になっており、同一ローカルネットワーク内の接続確立は保ちつつ、無関係な第三者へのプライベートIPアドレスの漏洩を抑えている。

トポロジの限界:フルメッシュから SFU/MCU へ

1対1の通話であれば、2つのピアが直接接続するフルメッシュ構成で何の問題もありません。しかし参加者がn人になるビデオ会議で全員がフルメッシュを組もうとすると、各ピアはn-1本の接続を維持し、n-1本分の映像・音声を送信し続ける必要があります。接続数はO(n²)で増加し、各クライアントの上り帯域と処理能力が数人規模でも簡単に頭打ちになるため、この方式は少人数の通話にしか通用しません。

この限界に対する現実解が、SFU(Selective Forwarding Unit)MCU(Multipoint Control Unit)という中央集約型のサーバーの再導入です。SFUは各参加者から受け取ったメディアストリームをデコードせずにそのまま他の参加者へ転送するだけのルーターで、各クライアントは1本のアップロードと(n-1)本相当のダウンロードだけで済むようになります。MCUはさらに一歩進んで、サーバー側で全員分の映像・音声をミックス・合成してから1本のストリームとして配信するため、クライアント側の負荷はさらに軽くなりますが、サーバーの計算コストは大きくなります。Google MeetやDiscord、Zoomのようなビデオ会議サービスの多くはSFU方式を採用しています。これは「P2Pの理想」と「多人数への現実的なスケーラビリティ」との間のトレードオフであり、P2Pとメタバースで扱う多人数同時接続の課題とも通じるテーマです。

応用

  • ビデオ会議・音声通話: Google Meet、Discord、Zoomのブラウザ版など、多くのビデオ会議サービスがWebRTCをメディア伝送の基盤に用いている。
  • ファイル転送: RTCDataChannelを使えば、サーバーにファイルをアップロードすることなくブラウザ間で直接ファイルを送受信できる。
  • ブラウザ上のP2Pネットワーク: RTCDataChannelはメディア専用ではなく、任意のバイナリデータを運べる汎用のP2Pパイプでもある。これを土台に、WebTorrentはブラウザからBitTorrent的なスウォームへ直接参加できるようにし、IPFSのブラウザノードやlibp2pのWebRTCトランスポートは、専用アプリのインストールなしにブラウザをP2Pネットワークの正式な参加者にする。従来「サーバーからのダウンロード」しかできなかったブラウザが、ピアとしてアップロードもできるようになった意義は大きい。

比較: WebSocket / WebTransport / WebRTC DataChannel

観点WebSocketWebTransportWebRTC DataChannel
接続形態クライアント–サーバー(常に1対1、サーバー必須)クライアント–サーバー(常に1対1、サーバー必須)ピア–ピア(サーバーはシグナリングとNAT越えの補助のみ)
トランスポートTCPQUIC(UDPベース)SCTP over DTLS(UDPベース)
信頼性・順序性TCPに固定(常に信頼性あり・順序保証あり)ストリーム単位で選択可能、データグラムは信頼性なしストリームごとにorderedmaxRetransmits等で柔軟に選択可能
シグナリング要否不要(URLへの接続のみ)不要(URLへの接続のみ)必要(SDP/ICE候補の事前交換が必須)
主な用途サーバーとのリアルタイム双方向通信全般(チャット、通知など)低遅延なサーバー通信、メディアストリーミング、多重データグラム転送ビデオ会議の映像・音声・チャット、P2Pファイル転送、ブラウザP2Pネットワーク

関連ページ

WebRTCが直接接続を試みるための土台はNAT越えのSTUN/TURN/ICEそのものであり、シグナリングの実装ではWebSocketがよく使われます。多人数接続で顕在化するスケーラビリティの課題はP2Pとメタバースで扱う同時接続数の問題と地続きで、RTCDataChannelを土台にしたWebTorrentのようなブラウザP2PネットワークはBitTorrentのスウォームの仕組みをそのまま受け継いでいます。サーバーとの単純な双方向通信であればWebRTCの複雑さは不要で、その場合の選択肢はWebSocketWebTransportを参照してください。SFU/MCUによる中央集約とはまた違う、中継ノードのカスケードで1対多のリアルタイム配信を成立させる仕組みはP2Pライブ配信で詳しく扱っています。

トップページへ戻る