プロトコル

WebRTCとは?P2Pの仕組み・ICE/STUN/TURNからSFU選定・実装・運用判断まで実装者向けに解説

会員管理システム開発とは

ビデオ通話、遠隔作業支援、ライブ配信、画面共有つきのサポート窓口。映像と音声を「今すぐ」相手へ届ける機能を任されたとき、実装者が最初に検討するのがWebRTCです。ところが着手すると、公式仕様にシグナリングサーバーの作り方は書かれておらず、社内から繋がらない、3人までは動くのに5人で音が途切れる、といった壁が続きます。本記事では、接続確立の手順を仕様の粒度で分解し、TURNの費用計算、SFUを挟む分岐、実装コードと品質計測、採否の判断までを2026年7月時点の一次情報で整理します。

まとめ:WebRTCの仕組みと実装・採用判断の結論

WebRTCは、ブラウザやアプリの間で映像・音声・任意のデータを、サーバーを経由せずに直接やり取りするための通信規格です。W3CのAPI仕様「WebRTC: Real-Time Communication in Browsers」は勧告に達し、公開版は2025年3月13日付。プロトコル側はIETFのRFC群が担い、概観がRFC 8825、Offer/Answerの手順がRFC 9429、NAT越えがRFC 8445(ICE)・RFC 8489(STUN)・RFC 8656(TURN)です。

実装で最初に理解すべき点は「WebRTCは通信の中身だけを定め、相手を見つける手順を定めていない」ことです。互いのSDP(通信条件)とICE候補(到達可能な経路)を交換する経路=シグナリングは、開発者が自分で作ります(多くの現場ではWebSocket)。

NAT配下の端末同士を繋ぐには、自分のグローバル側のアドレスをSTUNで知り、直接届かない相手にはTURNサーバーで中継させます。中継は課金対象の帯域を通るため、設計時の見積もりが要ります。

人数が増えれば構成も変わります。全員が全員へ送るmesh方式は5人前後で上り帯域が破綻するため、実務ではSFU(受け取った映像を選んで転送するサーバー)を挟む形になるでしょう。採否の判断軸は「映像音声そのものを運ぶか」と「遅延要求が1秒を切るか」の2点です。数秒の遅れが許されるならHLSでCDN配信したほうが安く、テキストや数値の双方向ならWebSocketで足ります。

WebRTCとは何か|ブラウザ標準のリアルタイム通信スタック

HTTPを介した往復モデルと比べたときの構造上の決定的な違い

HTTPやWebSocketで映像を運ぶ場合、データはいったんサーバーへ上がり、そこから相手へ降ります。経路が2本になるため遅延は加算され、サーバーは全利用者分の帯域を負担する構造。TCPを使う以上、パケットが1つ欠けると再送待ちで後続も渡せず、映像では「一瞬止まる」形で現れます。

WebRTCはこの構造を変えます。相手を見つけるまではサーバーを使いますが、確立後のメディアは端末同士が直接、UDP上のSRTPで運びます。届かなかったパケットは状況に応じて捨てて先へ進む。音声や映像では、完全性より時間軸の連続性が体験を決めるためです。実装者から見ると、扱う対象が「リクエストとレスポンス」から「途切れる前提のストリームと品質指標」へ移ります。

W3C勧告とIETF RFC群の位置づけと参照範囲を押さえる

WebRTCは単一の仕様ではなく、API仕様とプロトコル仕様の組み合わせです。

主な仕様 定めている範囲
API W3C WebRTC勧告(2025年3月) RTCPeerConnection等の挙動
接続手順 RFC 9429(JSEP) Offer/Answerの状態遷移
NAT越え RFC 8445 / 8489 / 8656 ICE・STUN・TURN
データ RFC 8831 / 8832 SCTP over DTLSのチャネル
安全性 RFC 8826 / 8827 脅威モデルと必須の暗号化

コーデックの要件も仕様で決まっています。映像はRFC 7742がVP8とH.264 Constrained Baselineの実装を必須と定め、音声側の要件仕様ではOpusとG.711が必須。どのブラウザ同士でも最低1つは共通のコーデックがある状態が保証され、VP9やAV1は追加の選択肢という位置づけです。

getUserMedia・RTCPeerConnection・データチャネルの役割分担

触るAPIは3つだけです。getUserMedia()がカメラとマイクからMediaStreamを取得し、RTCPeerConnectionが接続と送受信を担い、RTCDataChannelが映像以外の任意データを運びます。

3つ目を見落とすと設計を損ないます。データチャネルはSCTPをDTLSの上で動かす仕組みで、ファイル転送や共同編集のカーソル、IoT機器の制御値まで運べます。順序保証と再送回数を自分で選べるため、TCPとUDPの中間の性質を要件に合わせて作れる。SSE・WebSocket・WebTransportまで含めた性能の横並び比較はSSEとWebSocketの違いと使い分けにあります。本記事は比較ではなく、WebRTCを選んだ後に要る仕様と実装を担当します。

接続確立の手順①|シグナリングは仕様の外側にあり自分で設計する

シグナリングでSDPとICE候補の交換に何を流すかを自分で決める

WebRTCの仕様は、接続確立に要る情報の「中身」を定めますが、どう運ぶかは定めていません。ここが最初の分岐点で、用いる技術も認証の方式も部屋の概念も開発者が設計します。

交換するものは2種類です。1つはSDPで、使えるコーデック、解像度、鍵情報の指紋などが並んだテキスト。もう1つはICE候補で、自分に到達できる可能性のあるIPアドレスとポートの一覧です。SDPは呼び出す側がOffer、受ける側がAnswerを返す1往復。ICE候補は見つかった順に何度も飛びます。

シグナリングの実装はWebSocketが定番でしょう。双方向で、サーバーから任意のタイミングで押し出せる性質が要求と一致するためです。プロトコルそのものの仕様と実装はWebSocketの仕組みと実装・運用の判断で扱っています。要件が「1対1の発信を通知するだけ」なら、HTTPのポーリングでも成立します。

Perfect Negotiationでglareと状態エラーを避ける

同時に双方がOfferを投げると状態機械が衝突します。glareと呼ばれる古典的な問題で、素朴な実装ではInvalidStateErrorが出て接続が止まる。W3C側が推奨する回避策がPerfect Negotiationです。

考え方は単純で、2者に非対称な役割を先に割り振ります。譲る側(polite)は、自分がOfferを作りかけていても相手のOfferを受け入れて自分の作業を巻き戻す。譲らない側(impolite)は相手のOfferを無視して自分のを通す。役割は参加順で決めても構いません。

const pc = new RTCPeerConnection({ iceServers });
let makingOffer = false, ignoreOffer = false;

pc.onnegotiationneeded = async () => {
  makingOffer = true;
  await pc.setLocalDescription();          // 引数なしで種別を自動判定
  signal({ description: pc.localDescription });
  makingOffer = false;
};

async function onSignal({ description, candidate }) {
  if (description) {
    const collision = description.type === 'offer' &&
      (makingOffer || pc.signalingState !== 'stable');
    ignoreOffer = !polite && collision;    // 譲らない側は相手を無視
    if (ignoreOffer) return;
    await pc.setRemoteDescription(description);
    if (description.type === 'offer') {
      await pc.setLocalDescription();
      signal({ description: pc.localDescription });
    }
  } else if (candidate && !ignoreOffer) {
    await pc.addIceCandidate(candidate);
  }
}

引数なしのsetLocalDescription()は、現在の状態からOfferとAnswerのどちらを作るべきかをブラウザが判断します。自前で分岐を書く旧来のコードより短く、状態エラーも起きにくいでしょう。

接続確立の手順②|ICE候補とSTUN・TURNでNATを越える

host・srflx・relayという3種類の候補が意味するもの

家庭や社内の端末は私設アドレスを持ち、NATの内側にいます。相手から見える形のアドレスを自分では知らないため、候補を集める工程が入る。集まる候補は3種類です。

hostはNICが持つアドレスそのままで、同じLAN内なら最短経路。srflx(server reflexive)はSTUNサーバーへ問い合わせて判明したNATの外側のアドレスとポート。relayはTURNサーバーが自分の代わりに用意した中継先です。ICEはこれらを総当たりで組み合わせ、実際にパケットが通る組を選びます。優先度は原則host、srflx、relayの順。

候補が揃うのを待って一括で送ると待ち時間が積み上がります。RFC 8838のTrickle ICEは、見つかった候補を即座に相手へ流し、並行して接続確認を進める手法です。実装上はonicecandidateの候補をそのままシグナリングへ流し、nullが来たら収集完了と判断します。NATとNAPTそのものの動作はNATの仕組みとNAPT(IPマスカレード)との違いで整理しています。

STUNだけで足りるケースと、TURNが要るネットワークの条件

STUNは「自分の外側の姿を教えてもらう」だけの軽い問い合わせで、メディアは通しません。多くのNATは内側から外へ出た通信の穴を一定時間保持するため、双方がSTUNで得たアドレスへ同時に送ると穴が開通します。ここまでで済めばサーバー費用はほぼゼロ。

成立しない条件が3つあります。第1に、宛先ごとに別のポートを割り当てる形のNAT(対称NAT)が片方にあると、事前に知ったポートへは届きません。第2に、ファイアウォールがUDPを外向きに一切通さない場合。第3に、内側から外への通信でも宛先を検査するプロキシ環境です。

こうした相手にはTURNで中継します。中継サーバーは両者から受けて両者へ送るため、メディアの全量がそこを通る。実装はcoturnのようなOSSか、SaaSのTURNを契約する形が一般的です。UDPが塞がれた環境まで拾うなら、TURN側でTCP 443番も受けTLSで包む構成が要ります。この1点で「社内から使えない」という報告の大半は消えます。

TURN中継で発生する帯域と転送量課金を設計前に計算しておく

TURNは費用が読みにくいので、先に掛け算します。1対1のビデオ通話で片方向1.5Mbpsを想定すると、中継サーバーは1セッションでA向きとB向きの両方を送出するため、下り方向の合計は約3Mbps。1時間なら3Mbps×3,600秒=10.8Gbit、およそ1.3GBです。クラウドの転送量課金は下り方向にかかるため、この量が請求の対象になります。

同時100セッションのピークなら瞬間帯域は300Mbps規模。確かめるのは3点です。全セッション中どれくらいが中継に落ちるか(環境依存のため実際の利用者層で測ります)、サーバーのNICと台数が瞬間帯域に耐えるか、月間の転送量課金が事業として成立するか。P2Pで直結できた分は費用がかからないため、STUNで済む比率を上げる施策が費用に直結します。

多人数接続の設計|mesh・SFU・MCUの分岐点と選び分け

mesh方式が破綻する参加人数を上り帯域の掛け算から見積もる

P2Pのまま人数を増やすと、各端末は自分以外の全員へ同じ映像を送ります。参加者N人なら上りはN-1本。片方向1.5Mbpsとして、3人なら3Mbps、5人なら6Mbps、8人なら10.5Mbpsの上りが各端末に要ります。家庭やモバイルの上り回線はここで頭打ち。端末は相手ごとに独立したエンコードとDTLSセッションを持つため、CPUと発熱も人数に比例します。

実務上の目安は3人、条件が良くて4人です。「最大何人」が要件に書かれないまま着手し、デモの3人では動いたのに本番の6人で崩れる経路は避けたいところ。

SFUの仕組みと、simulcast・SVCで解像度を選ぶ設計

SFU(Selective Forwarding Unit)は、各端末から1本だけ受け取り、必要な相手へ複製して転送するサーバーです。端末の上りは常に1本で済み、参加者が増えても伸びるのは下りだけ。映像を復号しないため、サーバーのCPU負荷はMCUよりはるかに軽い構造です。

実装上の要点がsimulcastです。同じ映像を高・中・低の複数解像度で同時に送出し、SFUが受信側の回線に応じて配る層を選びます。SDP上のシグナリングはRFC 8853が定め、送信側はaddTransceiversendEncodingsで層を宣言します。

pc.addTransceiver(videoTrack, {
  direction: 'sendonly',
  sendEncodings: [
    { rid: 'h', maxBitrate: 1500000 },
    { rid: 'm', maxBitrate: 500000, scaleResolutionDownBy: 2 },
    { rid: 'l', maxBitrate: 150000, scaleResolutionDownBy: 4 }
  ]
});

AV1やVP9では、1本のストリームに階層を埋め込むSVCという方式も選べます。上り帯域はsimulcastより節約できるものの、エンコード負荷と対応状況を実機で確かめる前提でしょう。自前で組むかSaaSに寄せるかは別の判断で、OSSのSFU製品の機能と料金はLiveKitの特徴・料金・使い方で扱っています。

MCUを選ぶべき場面と、WHIPで外部の配信基盤へ流し込む選択

MCU(Multipoint Control Unit)は、サーバー側で全員の映像を復号して1枚に合成し、参加者へは1本だけ返す方式です。再符号化を伴うためCPU費用は重い。それでも選ぶ理由は3つ。参加端末が低スペックで下り1本しか扱えない場合、合成済みの録画ファイルが成果物として要る場合、電話網や既存のテレビ会議設備と繋ぐ場合です。

視聴者が数千人規模になると、WebRTCで配り切る前提自体を見直します。2025年3月にStandards TrackのRFC 9725として発行されたWHIP(WebRTC-HTTP Ingestion Protocol)は、HTTP POSTでSDPを1往復させるだけで配信基盤へ送出できる仕組みで、配信側だけWebRTC・視聴側はHLSという構成を組みやすくする。視聴側もHTTPで受けるWHEPは、2026年7月時点でdraft段階です。

実装と運用|最小コード・データチャネル・品質計測とセキュリティ

RTCPeerConnectionで映像を送受信する最小の骨格

接続部分のコードは、Perfect Negotiationを前提にすると短く済みます。要点は、トラックを追加した時点でnegotiationneededが発火する流れに任せることです。

const pc = new RTCPeerConnection({
  iceServers: [
    { urls: 'stun:stun.example.com:3478' },
    { urls: 'turns:turn.example.com:443?transport=tcp',
      username: 'u', credential: shortLivedSecret }   // 短命の資格情報
  ]
});

const local = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
for (const track of local.getTracks()) pc.addTrack(track, local);

pc.ontrack = (ev) => { remoteVideo.srcObject = ev.streams[0]; };
pc.onicecandidate = (ev) => { if (ev.candidate) signal({ candidate: ev.candidate }); };
pc.oniceconnectionstatechange = () => {
  if (pc.iceConnectionState === 'failed') pc.restartIce();   // 経路の張り直し
};

TURNの資格情報を静的に埋め込む実装は避けてください。取り出して他人の中継に使われると帯域がそのまま課金されるため、有効期限つきの値を都度発行する形にします。failedからの復帰はrestartIce()で、モバイル回線からWi-Fiへ切り替わった場面に効きます。

データチャネルの順序保証と再送回数の設定を要件ごとに合わせる

データチャネルは既定でTCPに近い性質(順序保証つき・欠落は再送)ですが、生成時のオプションで緩められます。カーソル座標のように「古い値に価値がない」データでは、後続を待たせないほうが体験が良くなる。

// 確実に届けたい: 設定変更・チャット
const reliable = pc.createDataChannel('control');

// 遅れたら捨てたい: カーソル・センサー値
const fast = pc.createDataChannel('cursor', {
  ordered: false,
  maxRetransmits: 0
});

大きなデータは分割が必要です。1メッセージの上限は実装依存で、相互接続を考えるなら16KiB程度に区切るのが無難でしょう。送信バッファの詰まりはbufferedAmountで判定し、しきい値を超えたら送出を止める背圧の制御を自分で書きます。

getStatsで見るべき4つの指標と、品質劣化時の切り分け

WebRTCの運用は「繋がったか」では終わらず、繋がった状態の良し悪しを数値で持つ必要があります。pc.getStats()が返すレポートのうち、実務で見る指標は4つに絞れます。

指標 読み取れること
packetsLost / jitter 経路の混雑と揺らぎ
roundTripTime 往復遅延の実測値
availableOutgoingBitrate 送出に使える帯域の推定
qualityLimitationReason 制限の主因(cpu / bandwidth)

4つ目が切り分けの鍵です。値がbandwidthなら回線側、cpuなら端末側の処理能力が上限。前者は解像度とフレームレートの上限を下げる方向、後者はsimulcastの層を減らす方向へ手を打ちます。数値を蓄積しておけば、「たまに途切れる」という報告を経路と端末のどちらの問題かで分けられます。

セキュリティ面で先に押さえたいのは、暗号化が選択肢ではない点です。WebRTCはDTLSで鍵を交換しSRTPでメディアを暗号化する構成が必須で、平文で流す設定は存在しません。鍵の指紋はSDPに載るため、シグナリング経路をTLSで守らないと中間者に差し替えられる余地が残ります。ICE候補にはローカルのアドレスが載るため、主要ブラウザは既定でmDNS名へ置き換える設計です。SFU経由ではサーバーが復号できる位置に立つので、運用者にも中身を見せない要件があるならEncoded Transformでフレーム単位に暗号を重ねます。

WebRTCを採用してよい3つの条件と、見送るべき3つの場面

WebRTCを採用してよい3つの条件を、費用構造から言い切る

第1に、運ぶ対象が映像・音声・画面共有そのものであること。テキストや数値ならTCP上のWebSocketで組んだほうが軽く済みます。カメラ映像やマイク音声を扱う要件で初めて、UDPと欠落許容という性質が価値になる。

第2に、遅延要求が1秒を切ること。WebRTCの伝送遅延は条件が良ければ数百ミリ秒以下に収まり、会話が成立します。対してHLSは数秒から十数秒。オークションの入札、遠隔での作業指示、医療や教育での対話のように、返答が噛み合う用途が対象です。「見るだけ」で数秒遅れても困らないなら、この条件は満たしません。

第3に、TURNとSFUを持てる体制があること。WebRTCはP2Pという言葉から「サーバー不要」と誤解されますが、実運用ではシグナリング、STUN、TURN、多人数ならSFUの4種が動きます。中継帯域の課金と監視の担当を確保できるかを先に確認する。SaaSのSFUに寄せる判断も、この観点では正解でしょう。

WebRTCを見送るべき3つの場面と、代わりに選ぶ手段の指針

1つ目は、1対多の片方向配信で数秒の遅延が許される場面です。セミナー配信や商品紹介なら、HLSでCDNに載せたほうが安価に数万人へ届きます。WebRTCで同じ人数を配ると、SFUの台数と帯域が線形に増えてしまう。

2つ目は、双方向でもデータがテキストや数値である場面です。共同編集やチャット、ダッシュボード更新にWebRTCを持ち込むと、ICEとTURNの運用の重さだけが増えます。

3つ目は、要件が既製のSaaSで満たせる場面です。Web会議の機能一式を内製すると、録画、画面共有、参加者管理、モバイル対応、回線品質への追従が積み上がります。自社画面へ通話機能を埋め込む程度なら、SDKを提供するプラットフォームに寄せ、差別化する部分だけを自前で書く判断が現実的でしょう。

リアルタイム映像の開発を外部に委ねるとき見積書で確かめる5項目

発注する場合、見積書の粒度で品質の差が出ます。確かめるのは5項目です。第1に同時接続数と1部屋の最大人数が数値で書かれているか。第2にTURN中継の想定比率と月間転送量の見積もりが入っているか(抜けた見積もりは公開後に通信費で破綻します)。第3にmesh・SFU・MCUのどれを採るかとその根拠。第4に品質計測の指標と劣化時の切り分け手順が成果物に含まれるか。第5に対象ブラウザと端末の範囲、UDP遮断環境での挙動をどう扱うかです。

いずれも後から追加すると構成の作り直しになりやすい項目。配信方式の選定から相談したい場合は、動画配信システム開発で受け付けています。WebRTCで組む範囲とHLSに任せる範囲の線引きから設計します。

よくある質問

WebRTCとWebSocketの違いは何ですか?

WebSocketはサーバー経由でTCPでデータを運び、メッセージを確実に届けます。WebRTCは端末同士が直接、UDP上で映像・音声・任意データを運ぶ規格で、欠落を許して遅延を詰める。実務では併用が普通で、SDPとICE候補の交換をWebSocketで行う構成が定番です。

WebRTCはサーバーなしで使えるのですか?

メディアの経路はサーバーを介さずに済みますが、サーバーが不要になるわけではありません。シグナリングサーバーは必須で、NAT配下ではSTUN、直接繋がらない相手にはTURNが要ります。多人数ならSFUも加わる構成です。公開STUNだけで検証を済ませ本番でTURNを用意しないと、特定の利用者だけ繋がらない事象になります。

WebRTCの遅延はどれくらいですか?

条件が良ければ片方向で数百ミリ秒以下に収まり、対話が成立する水準です。数秒から十数秒のHLSやDASHとは桁で違います。ただしTURN中継が入る、経路が遠い、端末のCPUが不足する条件で伸びるため、想定利用者の環境でroundTripTimeを実測してください。

WebRTCで多人数の会議を作るにはどうしますか?

3〜4人を超えるならSFUを挟みます。mesh方式では各端末の上り帯域が参加者数に比例して増え、5人で6Mbps前後、8人で10Mbps超が要求されるためです。SFUなら上りは常に1本。自前構築はmediasoupなどのOSS、運用を委ねるならSaaSという選択です。

WebRTCのセキュリティは大丈夫ですか?

メディアの暗号化はDTLS-SRTPで必須化されており、平文で流す設定はありません。注意すべきは周辺です。シグナリング経路をTLSで守る、TURNの資格情報を短命にする、運用者にも中身を見せない要件があればEncoded Transformで暗号を重ねる。この3点を設計に含めます。

関連記事

資料請求

RELATED POSTS 関連記事