01

總覽與定位

WebRTC 不是「另一個即時聊天協定」——它是瀏覽器原生的即時媒體與 P2P 資料通道:信令走你自己的通道,媒體走 ICE + DTLS-SRTP。

WebSocket 那篇處理的是應用訊息的全雙工通道;SSE 那篇處理的是單向事件串流。兩者都還在「文字/JSON/位元組訊息」的世界。本篇要進的是另一個世界:音訊、視訊、以及低延遲的二進位 DataChannel——而且經常要直接連到對端 peer,中間沒有你的應用伺服器當轉發站。

信令平面
Signaling · SDP · 你自己挑通道
交換 Offer/Answer 與 ICE candidate。常見用 WebSocket/HTTPS;協定本身不規定信令怎麼傳。
媒體/資料平面
ICE · DTLS-SRTP · RTP/SCTP
真正的影音與 DataChannel 流量走 UDP(必要時 TURN 中繼)。這條路與信令連線不是同一條 TCP。
架構取捨
P2P · SFU · MCU · TURN 成本
兩人通話可直連;多人會議幾乎一定上 SFU。TURN 是「打不通時的保底」,也是帳單上最容易爆炸的一項。

這三塊的差別不在技術棧,而在失敗模式與帳單:信令斷了可以重連補送,媒體抖了只能靠緩衝與碼率適配——而最右邊那塊是唯一會按流量計費的,架構討論最後多半卡在它。

座標與 WS/WebTransport/NAT 文怎麼切

聊天與信令走 WebSocket(或 HTTPS):房間加入、誰上線、SDP 交換。媒體走 WebRTC:麥克風、鏡頭、螢幕分享、遊戲狀態的 DataChannel。
NAT/STUN/TURN 的類型表與映射語意已在 NAT 與 Port Forwarding 那篇定調——本篇引用結論(Symmetric 多半要 TURN;host/srflx/relay 三類候選),不重做類型表,改從端到端 ICE 狀態機與媒體拓撲切入。
WebTransport datagram 不是 WebRTC:前者是瀏覽器↔伺服器的 QUIC 應用通道;後者是 peer 連線 + 媒體協定棧。面試若把兩者混成「都是 UDP 所以一樣」,會直接失分。

一句話答法WebRTC = 自選信令通道交換 SDP/ICE + 瀏覽器內建的 ICE/DTLS-SRTP 媒體平面;聊天走 WS,影音走 WebRTC,不要把 WebTransport 當成它的別名。
02

信令與媒體分離

規格故意把「怎麼找到對方、怎麼談條件」和「談完之後封包怎麼飛」拆成兩個平面——這是整套設計的第一性原理。

Signaling plane
可靠、有序即可 · 延遲不敏感
  • SDP Offer/Answer
  • ICE candidate trickle
  • 房間/身分/權限
  • 掛斷、重協商(renegotiation)
Media / data plane
低延遲、可丟包 · 對 jitter 敏感
  • RTP/RTCP 影音
  • SCTP over DTLS(DataChannel)
  • ICE 打洞或 TURN 中繼
  • NACK/PLI/Simulcast 適配

左右兩欄要的東西正好相反:左邊要「一定要到」,右邊要「晚到不如不到」。把右欄的需求丟進左欄的通道,就會寫出用 WebSocket 推視訊幀的設計。

為什麼要分離?因為兩者的失敗模式完全不同。信令斷了,你可以重連 WebSocket、補發最後一則 SDP;媒體抖了,你要的是 jitter buffer 與碼率適配,而不是把整段視訊塞進一條可靠的 TCP 聊天通道。把視訊幀當 WebSocket binary frame 硬推,短期能 demo、長期會在 NAT、擁塞與瀏覽器功耗上翻車——這也是為什麼「用 WS 傳音訊」幾乎永遠是面試裡的錯誤答案。

控制面
Peer A
瀏覽器
──WS──▸
Signaling server
轉送 SDP 與 candidate
──WS──▸
Peer B
瀏覽器
媒體面
Peer A
RTP/SRTP 送收
◂──直連 UDP(首選)──▸
Peer B
RTP/SRTP 送收
Peer A
同一組 track
──UDP──▸
TURN relay
保底:打不通才繞
──UDP──▸
Peer B
同一組 track

控制面一定經過伺服器,媒體面盡量不經過:兩條路徑的端點相同、走法卻完全不同。伺服器完全不碰媒體封包正是 P2P 通話省頻寬的來源,TURN 只在直連打不通時才把媒體拉回中繼。

陷阱信令伺服器 ≠ 媒體伺服器

很多架構圖把「WebRTC server」畫成一個方塊。實務上至少拆成:信令(常與既有後端同進程)、STUN/TURN(coturn 之類)、以及(多人時)SFU。把它們綁成單體,會讓水平擴充與計費邊界糊成一團。

一句話答法WebRTC 把可控、可重試的信令與對延遲敏感的媒體平面拆開;信令常用 WS,媒體走 ICE 選出的 UDP 路徑,兩者失敗與擴充策略各自獨立。
03

SDP Offer/Answer

SDP 是雙方對「我能播什麼、我要聽什麼、用哪組編解碼」的文字契約;Offer/Answer 是交換這份契約的狀態機。

1 · 最小交握節奏

sequenceDiagram
    participant A as Peer A
    participant S as 信令伺服器
    participant B as Peer B
    A->>A: createOffer
    A->>A: setLocalDescription
    A->>S: offer SDP
    S->>B: offer SDP
    B->>B: setRemoteDescription
    B->>B: createAnswer
    B->>B: setLocalDescription
    B-->>S: answer SDP
    S-->>A: answer SDP
    A->>A: setRemoteDescription
    Note over A,B: 之後 candidate 經同一條信令陸續補送
  

看兩端的對稱性:A 與 B 各做一次「產生描述 → setLocalDescription → 經信令送出 → 對端 setRemoteDescription」,圖的下半段就是 Answer 的回程。信令伺服器只負責轉送、不解讀 SDP 內容——這也是它能與既有後端同進程的原因。

順序不能亂:本地先 setLocalDescription,對端才能 setRemoteDescription。現代瀏覽器多半搭配 Trickle ICE——SDP 先送出,candidate 稍後陸續經信令補上,不必等蒐集完才通話。

2 · SDP 裡面試真正會問的欄位

區塊/語意你在協商什麼實務影響
m= lines音訊/視訊/application 媒體列有沒有 DataChannel、幾路 track
codec/fmtpVP8/VP9/H.264/AV1、opus互通性、硬解、CPU/電池
ICE ufrag/pwd連線認證材料與 candidate 綁定;重協商會換
fingerprintDTLS 憑證指紋防中間人;與信令通道信任綁在一起
a=setup/actpass誰當 DTLS clientAnswer 端通常定角色
關鍵SDP 是契約,不是「連線本身」

交換完 Offer/Answer,只代表雙方同意能力集合;封包能不能通,還要看 ICE。反過來說:ICE 已連上但 SDP 沒談妥 codec,仍然沒有可用的視訊 track。面試答案要拆成「協商成功」與「連線成功」兩層。

一句話答法SDP Offer/Answer 協商媒體能力與 DTLS/ICE 材料;Trickle ICE 讓你先送 SDP 再補 candidate,但「談妥」≠「已經能通」。
04

ICE:host/srflx/relay 與連線狀態機

ICE 的工作是:蒐集所有可能的位址、兩兩配對探測,挑一條「打得通且夠好」的路徑——打不通就降級到 TURN。

1 · 三類 candidate(引用 NAT 篇結論)

host
本機網卡位址
同一 LAN/VPN 內最快。跨網時幾乎沒用,但仍會被蒐集並參與排序。
srflx
server-reflexive · 經 STUN
「我在公網上長怎樣」。對應 NAT 篇:Full Cone/大部分家用 NAT 常靠它打洞;Symmetric NAT 上 STUN 映射對 peer 常失效。
relay
經 TURN 中繼
保底路徑。媒體比特率 × 通話時長直接進你的雲帳單;成功率最高,延遲與成本也最高。

三張卡由左至右就是 ICE 的偏好順序(type preference 126 / 100 / 0):host 最快但適用面最窄,relay 一定通但最貴——中間那張的 Symmetric 但書,正是 relay 必須存在的理由。

2 · 連線狀態(你要會講的那幾個)

stateDiagram-v2
    [*] --> new
    new --> checking: 開始配對探測
    checking --> connected: 找到可用 pair
    checking --> failed: 全部 pair 皆失敗
    connected --> completed: 探測收斂
    connected --> disconnected: 網路抖動
    completed --> disconnected: 網路抖動
    disconnected --> connected: 自行恢復
    disconnected --> failed: 逾時仍未恢復
    failed --> [*]
  

這張圖的重點在分支與回邊,不在那條直線:checking 有兩條出路,而 disconnected 有一條回到 connected 的回邊——有沒有這條回邊,正是它與 failed 的本質差別。

connected 表示已有一對可用 candidate;completed 表示探測收斂。disconnected 常是短暫網路抖動(ICE 會繼續救),failed 才是「這條 PeerConnection 救不回來、該重談或換 TURN」。產品埋點應分開這兩種,不然 on-call 會被誤報淹爆。

陷阱「有 STUN 就等於能 P2P」

STUN 只告訴你反射位址;能不能打洞取決於雙方 NAT 行為。企業網、電信 CGNAT、Symmetric 組合失敗率不低。正式產品的預設心智模型應是:P2P 是優化,TURN 是 SLA——並在儀表板同時看「直連率」與「每分鐘 TURN GB」。

一句話答法ICE 蒐集 host/srflx/relay 並探測配對;srflx 打洞失敗就上 relay。狀態上要分清 connected/completed 與 disconnected/failed。
05

DTLS-SRTP 與 DataChannel

媒體加密不是「再包一層 TLS over TCP」——WebRTC 在 UDP 上做 DTLS,再把金鑰導給 SRTP;資料通道則跑在 DTLS 上的 SCTP。

1 · 為什麼是 DTLS-SRTP

影音是 RTP 封包流,需要的是逐包加解密與可接受的丟包,而不是像 HTTPS 那樣的可靠位元流。流程簡化為:ICE 通了 → 雙方做 DTLS 握手(憑證指紋已在 SDP 對過)→ 匯出金鑰給 SRTP/SRTCP。面試關鍵句:信任錨在信令通道——若攻擊者能竄改你的 SDP fingerprint,媒體加密也守不住。

2 · DataChannel:可靠/不可靠是你選的

模式底層語意典型用途
ordered + reliable近似 TCP檔案、白板快照、控制訊息
unordered + partial reliability可丟、可不排序游標、遊戲狀態、感測器
與 WS 對照WS 永遠可靠有序聊天/信令仍偏 WS;高頻狀態可 DataChannel
關鍵DataChannel 仍掛在同一條 PeerConnection

它不是「免費多一條 TCP」。NAT 穿透、TURN 費用、連線生命週期都與媒體共用。把所有後端 API 搬進 DataChannel 通常得不償失;它擅長的是peer 之間的低延遲資料,不是取代你的 REST/gRPC。

一句話答法DTLS 握手後金鑰餵給 SRTP 保護 RTP;DataChannel 走 DTLS 上的 SCTP,可選可靠/不可靠,但仍受同一條 ICE 路徑與 TURN 成本約束。
06

媒體架構:P2P、SFU、MCU 與適配

兩人可以直連;三人以上,拓撲選擇決定的是 CPU、頻寬帳單與誰來做轉碼。

P2P(mesh)
每對 peer 一條 PC
N 人要 N(N-1)/2 條連線;上行要扇出多路編碼。兩人通話理想,五人以上通常不可行。
SFU
Selective Forwarding Unit
客戶端編碼一次上行;伺服器不轉碼,按訂閱轉發。現代會議/直播連線的預設答案。
MCU
混流/轉碼
伺服器合成單一畫面再下行。相容舊客戶端、統一佈局,但 CPU 成本極高,已非主流首選。

看中間那張:SFU 之所以是預設答案,是因為它把客戶端上行固定成一路,又不像 MCU 那樣把轉碼成本全攬到伺服器上。

Simulcast/SVC
同一來源多品質層
  • 客戶端同時送高低碼率層
  • SFU 依訂閱者網路挑層轉發
  • 換來的是上行成本與編碼複雜度
Jitter buffer
延遲 ↔ 流暢的緩衝
  • 吸收網路抖動,換取可播放連續性
  • 太大 → 口型不同步、互動感差
  • 太小 → 卡頓、PLC 頻繁

兩者都在同一條軸上滑動:Simulcast 用上行成本換下行的品質彈性,jitter buffer 用延遲換播放連續性——動任何一個之前,先確認你要犧牲哪一邊。

關鍵TURN 成本要放進架構圖,不是維運備註

SFU 已經讓媒體經過你的資料中心;若 peer↔SFU 還大量走 TURN relay(雙重中繼),帳單與延遲會疊加。部署上常把 TURN 與 SFU 放同一區域、優化 ICE 優先順序,並監控 relay 比例當成 SLO。

一句話答法兩人 P2P、多人 SFU;MCU 只在需要伺服器混流時考慮。Simulcast 讓 SFU 可選層轉發,jitter buffer 則在延遲與流暢之間滑動。
07

互動 · ICE 候選配對空間

ICE 不是走一條固定的狀態序列,而是在「A 的候選 × B 的候選」這張平面上,依優先度由高到低找第一個能通的座標。

第 4 節的狀態機只交代了結果——checking 之後是 connected 還是 failed——沒交代那個結果是怎麼來的。 實際發生的事是:兩端各自蒐集一批候選,兩批做外積形成一張 checklist,每一格是一對 candidate pair; ICE 依 RFC 8445 的優先度公式把所有格子排序,由高到低逐格送 STUN Binding Request,第一個通的就被提名,其餘取消。 所以「為什麼這通電話走了 TURN」這個問題,答案永遠是一個座標,不是一個狀態。

候選優先度 = 224 × type preference + 28 × local preference + 255 | 配對優先度 = 232 × min(G, D) + 2 × max(G, D) + (G > D ? 1 : 0)

下面的平面把整個過程攤開。設定兩端的 NAT 型別、網卡數、是否同一 LAN、TURN 是否可用, 平面的尺寸、每一格的優先度與可穿透性、掃描軌跡、被提名的那一格,以及探測次數、收斂時間與 TURN 曝險量,全部由這些輸入算出來。

互動 · ICE 候選配對空間 改任一設定,整張平面重新排序與重新判定
被提名的 pair 探測過但打不通 已取消(更高優先的先成功了) 底色深淺=pair priority
改任一設定即可重算。

四個值得停下來看的座標(以預設的兩端 Port-Restricted、不同 LAN、TURN 開啟、A 兩張網卡為起點, 此時平面是 4 × 3 = 12 格,掃到第 6 格的 srflx ↔ srflx 才通,RTT 40 ms、收斂 160 ms): (1) 把 Peer A 改成 Symmetric,第 6 格當場轉紅,軌跡繼續往下走到第 7 格的 host #1 ↔ relay—— 注意被提名的不是 srflx ↔ relay,因為 host 的 type preference 比 srflx 高;RTT 跳到 76 ms、收斂 216 ms。 (2) 但 Symmetric 不等於一定要 TURN:把 Peer B 改成 Full Cone 或 Address-Restricted,srflx ↔ srflx 又通了—— 只有「Symmetric 對上 Symmetric」或「Symmetric 對上 Port-Restricted」才真的打不通。 (3) 在 Symmetric 對 Port-Restricted 的狀態下關掉 TURN,平面縮成 3 × 2 = 6 格且全部轉紅,狀態落到 failed。 (4) 勾選「同一個 LAN」,左上角那格(優先度最高的 host #1 ↔ host #1)直接轉綠,探測次數從 6 降到 1,收斂時間 160 → 22 ms。 兩點簡化要說明:本模擬省略了 peer-reflexive 候選,所以「私網 host 對上公網 srflx」一律判為不通; 另外 relay 一端被視為必定可達,實務上仍可能被防火牆的 UDP 封鎖擋掉。

一句話答法ICE 做的是空間搜尋:兩端候選做外積、依 RFC 8445 的優先度排序、由高到低逐格探測,第一個通的就被提名;connected 與 failed 只是這場搜尋有沒有找到座標的結果,而 relay 之所以貴又慢,是因為它是這張平面上優先度最低、卻也是唯一保證有解的那一列。
08

面試折衷與邊界

把選型壓成可答的判準:什麼時候 WebRTC、什麼時候不要、成本與安全邊界在哪。

問題優先選項別做的事
瀏覽器即時音視訊WebRTC +(多人)SFU用 WebSocket 推 raw frame
聊天/信令/房間狀態WebSocket 或 HTTPS為每則聊天開 PeerConnection
瀏覽器↔自有後端的不可靠datagramWebTransport(若棧支援)把 WebTransport 說成 WebRTC
企業網/高失敗率 NAT預設備妥 TURN,監控 relay %假設 STUN 萬能
錄製、轉碼、統一佈局SFU + 旁路錄製/必要時 MCU在每個客戶端各自混流當唯一方案
陷阱安全邊界常被低估

媒體加密不代表「信令可信」。SDP、房間權杖、TURN 認證(時間限額憑證)都要當敏感面。另外:螢幕分享與裝置權限是瀏覽器 UX/隱私問題,不是 ICE 能解決的;權限被拒時要有降級路徑(純語音、純 DataChannel)。

關鍵一句架構口訣

信令可控、媒體可丟、TURN 可買、SFU 可擴。 先畫這四塊的責任與帳單,再談 codec 與 Simulcast 細節。

一句話答法即時影音用 WebRTC;信令/聊天用 WS;多人上 SFU並把 TURN 當 SLA 成本。別用 WS 傳視訊,也別把 WebTransport datagram 誤認成 WebRTC。