WebRTC リアルタイム通信実践 2026:ピア接続、SFU、本番パターン
WebRTC が今もリアルタイム通信の基盤である理由
ビデオ会議、オンライン教育、ライブ配信のマイク接続、クラウドゲーム、IoT 遠隔制御の裏側で、WebRTC はブラウザネイティブ・低遅延・端末間暗号化の事実上の標準です。2026 年、Plan B が標準から削除され Unified Plan が完全定着、さらに insertable streams(挿入可能メディア)による端末間暗号化のカスタマイズが可能になり、本番環境での成熟度が増しています。
| 能力 | WebRTC | 従来の RTMP/HLS |
|---|---|---|
| 遅延 | 100ms ~ 500ms | 2s ~ 30s |
| 暗号化 | 既定 DTLS-SRTP | 別途設定要 |
| ブラウザネイティブ | ✅ プラグイン不要 | ❌ プレーヤ要 |
| 双方向 | ✅ 天然支援 | ❌ 単方向主体 |
コア概念の全体像
- Signaling(シグナリング):SDP と ICE 候補を交換するチャネル。WebRTC は規定せず、通常 WebSocket を使う。
- SDP:メディア能力(コーデック、解像度、伝送アドレス)のセッション記述。
- ICE / STUN / TURN:到達可能な経路を発見し NAT を越える。
- PeerConnection:メディアトラックとデータ伝送を管理する中心オブジェクト。
ステップ1:ピア接続を確立する
最小の 1:1 通話骨架(シグナリングは WebSocket):
// クライアント A
const pc = new RTCPeerConnection({
iceServers: [
{ urls: "stun:stun.l.google.com:19302" },
{ urls: "turn:turn.example.com:3478", username: "user", credential: "pass" }
]
});
// ローカル音声・映像を取得
const localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
localStream.getTracks().forEach(track => pc.addTrack(track, localStream));
// リモートトラック到着時に描画
pc.ontrack = (e) => {
remoteVideo.srcObject = e.streams[0];
};
// Offer を生成してシグナリングサーバへ
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
signaling.send(JSON.stringify({ type: "offer", sdp: pc.localDescription }));
シグナリングサーバ(Node + ws)は転送のみ、メディアには関与しません:
import { WebSocketServer } from "ws";
const wss = new WebSocketServer({ port: 8080 });
const peers = new Map();
wss.on("connection", (ws) => {
ws.on("message", (msg) => {
const data = JSON.parse(msg);
// 単純なルーム転送:offer/answer/candidate を同室のもう一人へ
const target = peers.get(data.room)?.find(p => p !== ws);
target?.send(msg);
});
});
NAT 越え:STUN と TURN の役割分担
接続失敗の多くは NAT が根因です。3 つのシナリオを理解します:
| シナリオ | 解決策 | 説明 |
|---|---|---|
| 双方が公網/錐型 NAT | STUN | 公網マッピングを発見すれば直結 |
| 対称型 NAT | TURN | リレー必須 |
| 厳格な企業 FW | TURN + TLS | 443 ポートでリレー |
// 優先直結(p2p)、失敗時は TURN リレーへ自動退避
const pc = new RTCPeerConnection({
iceServers: [
{ urls: "stun:stun.example.com" },
{ urls: "turn:turn.example.com:3478?transport=tcp", username: "u", credential: "c" }
]
});
pc.oniceconnectionstatechange = () => {
if (pc.iceConnectionState === "disconnected") {
console.warn("ICE 切断、再接続を試行…");
}
};
接続調査では、まず URL 解析 ツールでシグナリング/TURN アドレス形式を確認し、HTTP ステータスコード でシグナリング健全性を照合します。
トポロジ選択:Mesh / SFU / MCU
| トポロジ | 原理 | 長所 | 短所 | 用途 |
|---|---|---|---|---|
| Mesh | 全ペア直結 | 中継サーバ経費なし | 帯域が人数の二乗で増大 | 4人以下の小部屋 |
| SFU | サーバ転送・トランスコードなし | 客側は1上り・多下り | サーバ帯域が大 | 会議の主流 |
| MCU | サーバ混入 | 客側は1受信 | サーバ CPU 高・遅延大 | 弱網/電話接入 |
2026 年、大半のビデオ会議は SFU を採用。客側は1上り(Simulcast 多段)し、他者の多下りを購読します。
// Simulcast:同一映像を3段で同時送信、SFU が購読者の網に応じ選択
const sender = pc.getSenders().find(s => s.track.kind === "video");
await sender.setParameters({
encodings: [
{ rid: "low", maxBitrate: 150_000, scaleResolutionDownBy: 4 },
{ rid: "mid", maxBitrate: 500_000, scaleResolutionDownBy: 2 },
{ rid: "high", maxBitrate: 1_500_000 }
]
});
データチャネル:音声・映像だけではない
WebRTC の RTCDataChannel は低遅延・順序有無選択可能な P2P データ伝送を提供し、ゲーム状態同期、ファイル転送、ホワイトボード協調に最適です。
const dc = pc.createDataChannel("whiteboard", { ordered: false, maxRetransmits: 0 });
dc.onopen = () => dc.send(JSON.stringify({ type: "stroke", points: [...] }));
dc.onmessage = (e) => renderStroke(JSON.parse(e.data));
構造化メッセージを送る際は、先に JSON フォーマッター でペイロードを検証し、解析例外でデータチャネルが崩壊するのを防ぎます。
セキュリティ:既定暗号化も境界は守る
WebRTC メディアは既定で DTLS-SRTP 端末間暗号化ですが、「安全そのもの」ではありません:
- シグナリングは HTTPS/WSS 必須。さもないと SDP が中間者に改ざんされる。
- メディアサーバは認可を。SFU は
track加入時に room token を検証すべき。 - E2EE カスタム:
insertable streams(RTCRtpScriptTransform)でアプリ層鍵を注入し、サーバも平文を見えない真の端末間暗号化を実現。
// パケット単位メディア暗号化(略示)
const encoder = new RTCRtpScriptTransform(pc, "https://cdn/encrypt-worker.js");
sender.transform = encoder;
本番スケールパターン
カスケード SFU(Cascading SFU)
大規模クロスリージョン会議は複数 SFU をカスケードし、近接接入・内部転送で国際遅延を下げます。
帯域推定と輻輳制御
WebRTC は GCC(Google Congestion Control)を内蔵しますが、協調が必要です:
pc.getStats()のgoogAvailableSendBandwidthを監視し動的降段;- 弱網では不要なデータチャネルを閉じる;
adaptivePtimeで音声パケット化時間を調整。
自動購読管理
「話している/フォーカス中」のリモート流のみ購読し、下り帯域を削減します。
function subscribeTo(userId, quality) {
signaling.send(JSON.stringify({ type: "subscribe", userId, quality }));
}
よくある質問 FAQ
Q1:なぜ「接続中」で止まりがち?
90% は NAT/ファイアウォール起因の ICE 失敗。TURN が使えるか、シグナリングが candidate を転送しているか確認を。
Q2:Mesh と SFU はどちら?
4人以下の小部屋は Mesh でコスト節約。4人超や録画/混入が必要なら SFU 必須。
Q3:モバイルをバックグラウンドにすると切れますか?
切れます。iOS/Android はバックグラウンドで getUserMedia を凍結。 visibilitychange を監視し再接続か公開停止を。
Q4:WebRTC でライブ配信できますか?
低遅延インタラクティブ配信(マイク接続)に最適。単方向の大規模配信は SFU 出力を HLS/CMAF へ再パッケージを。
Q5:Simulcast は必須ですか?
多段 Simulcast は弱網体験を大きく改善しますが、上り帯域を約10%-20%増やします。場面で权衡を。
推奨ツール
WebRTC 開発・調査には、以下の ToolsKu ツールが役立ちます:
- URL 解析 — STUN/TURN/シグナリング アドレス形式の確認
- HTTP ステータスコード — シグナリングと TURN REST API 応答の照合
- JSON フォーマッター — シグナリング SDP ラップとデータチャネル ペイロードの検証
WebRTC の壁は「接続確立」と「NAT 越え」。この二つを越えれば、ブラウザの中にミリ秒遅延のリアルタイム世界を構築できます。
ブラウザローカルツールを無料で試す →