作者註: 這是一篇在 2015 年開了頭卻未能完成的草稿,於 2026 年藉由 AI 協作補齊內容,並保留了 2015 年當時的技術生態與時空視角。

以往在瀏覽器中要做到即時音訊或視訊對話,通常必須依賴 Flash 外掛程式、Java applets,或是要求使用者安裝像 Skype 這樣的獨立桌面通訊軟體。這不僅帶來使用者體驗上的門檻,在安全性、效能與跨平台上也一直為人詬病。

自從 Google 在 2011 年開源 WebRTC(Web Real-Time Communication)專案,並與 W3C 和 IETF 攜手推動標準化以來,現代瀏覽器(Chrome 與 Firefox)已經原生具備了點對點(P2P)的即時音訊、視訊與資料傳輸能力。特別是今年 4 月 27 日,Facebook Messenger 正式宣布跨平台(iOS 與 Android)上線免費視訊通話功能,背後正是由 WebRTC 提供技術支援;此外 Ericsson 開源了基於 GStreamer 的 OpenWebRTC,Matrix.org 也在推廣去中心化通訊架構。

最近花了一些時間研讀 Ilya Grigorik 的著作《High Performance Browser Networking》(作者在 hpbn.co 提供免費線上閱讀版)中關於 WebRTC 的章節,以及社群裡探討底層實作的文章。這篇筆記嘗試整理 WebRTC 的核心架構、連線建立過程,以及最容易被忽略但極為關鍵的網路擁塞控制(congestion control)機制。

WebRTC 的三大核心 API

對前端開發者來說,W3C 將複雜的底層網路與媒體處理封裝成三個主要的 JavaScript API:

MediaStream (getUserMedia)

MediaStream 負責存取使用者裝置的攝影機與麥克風。透過 navigator.getUserMedia(),網頁可以向使用者請求授權,取得包含音訊軌(audio tracks)與視訊軌(video tracks)的串流物件。

這個 API 的重點在於本機端的音視訊採集、同步與本機預覽(例如直接指定給 <video> 標籤的 src)。它只處理本機媒體流的擷取,並不涉及網路傳輸。

RTCPeerConnection

RTCPeerConnection 是 WebRTC 的靈魂核心。它負責管理整個 P2P 呼叫的完整生命週期,包含:

  • 影音編解碼器(codecs)的協商(透過 SDP 內容協商,由瀏覽器底層媒體引擎負責編解碼,如音訊 Opus、視訊 VP8 / H.264)
  • 網路封包的發送與接收
  • 聲學回音消除(AEC)、降噪(NS)與自動增益控制(AGC)
  • NAT 穿透與候選位址收集
  • 即時網路頻寬估算與品質監控

所有端對端的影音串流傳輸,都是透過這個物件來建立與維護。

RTCDataChannel

除了影音傳輸之外,WebRTC 另一個極具潛力的功能是 RTCDataChannel。它允許兩個瀏覽器之間直接建立雙向、低延遲的任意二進位或文字資料傳輸通道。

RTCDataChannel 的 API 設計刻意模仿了 WebSocket,但最大的差異在於它是真正的 P2P 傳輸(不需經過中間伺服器繞行),而且底層採用了 SCTP 協定,讓開發者可以在「可靠傳送(reliable)」與「不可靠傳送(unreliable)」、「依序到達(ordered)」與「不依序到達(unordered)」之間彈性選擇。這對於網頁即時多人遊戲、P2P 檔案分享或是協同編輯工具來說非常實用。

網路傳輸架構與協定疊構

WebRTC 之所以強大且複雜,是因為它不是跑在傳統的 HTTP 或單純的 TCP 協定之上,而是在 UDP 之上整合了多種既有的網際網路標準協定:

flowchart TD Sig["<div style='width:580px; max-width:100%; font-size:15px; font-weight:normal; line-height:1.6; padding:4px 0;'><span style='font-weight:bold;'>信令與連線協商 (Signaling and Session Control)</span><br/><span style='font-weight:normal;'>帶外信令交換 SDP(RFC 7116 / JSEP 草案)與 ICE 候選位址</span></div>"] style Sig width:580px; ICE["<div style='width:580px; max-width:100%; font-size:15px; font-weight:normal; line-height:1.6; padding:4px 0;'><span style='font-weight:bold;'>連線建立與 NAT 穿透 (ICE Framework)</span><br/><span style='font-weight:normal;'>STUN 探測公網位址 · TURN 中繼轉發 · 連線優先級檢測與提名</span></div>"] style ICE width:580px; subgraph DataPlane ["<div style='font-size:14px; font-weight:bold; padding:2px 0;'>端對端資料傳輸 (P2P Data Plane)</div>"] direction LR Media["<div style='width:270px; max-width:100%; font-size:14px; font-weight:normal; line-height:1.5; padding:4px;'><span style='font-weight:bold;'>影音媒體串流</span><br/><span style='font-weight:normal;'>SRTP / RTCP(音訊 Opus · 視訊 VP8 / H.264)<br/>金鑰由 DTLS-SRTP 交握導出<br/>擁塞控制:GCC 雙控制器 + REMB</span></div>"] Data["<div style='width:270px; max-width:100%; font-size:14px; font-weight:normal; line-height:1.5; padding:4px;'><span style='font-weight:bold;'>資料通道 (RTCDataChannel)</span><br/><span style='font-weight:normal;'>SCTP 多串流傳輸<br/>DTLS 傳輸加密與認證<br/>可自訂可靠度與有序性</span></div>"] end style DataPlane fill:#f8fafc,stroke:#cbd5e1,stroke-width:1px; Network["<div style='width:580px; max-width:100%; font-size:15px; font-weight:normal; line-height:1.6; padding:4px 0;'><span style='font-weight:bold;'>底層傳輸與網路層 (Transport and Network)</span><br/><span style='font-weight:normal;'>UDP (User Datagram Protocol) over IPv4 / IPv6</span></div>"] style Network width:580px; Sig --> ICE ICE --> DataPlane Media --> Network Data --> Network

為什麼選擇 UDP 而非 TCP?

在網頁開發的世界裡,我們習慣了 TCP 帶來的可靠性。但在即時音訊與視訊通話的場景下,延遲(latency)是第一要務,封包遺失反而退居其次:

  • 避免隊頭阻塞 (Head-of-Line Blocking):TCP 必須嚴格按序遞送所有資料。一旦中間有封包遺失,TCP 會停止後續資料遞送並等待重傳,直到遺失的封包補齊為止。這在網頁載入檔案時很理想,但在視訊對話中,幾百毫秒前的畫面如果遺失,重傳回來早已毫無意義,使用者只會感受到嚴重的畫面凍結與語音延遲。
  • 即時性優於完整性:UDP 沒有重傳機制與按序保證,任何封包抵達就立即交給解碼器處理。即使遺失少數封包,音訊可以透過 PLC(Packet Loss Concealment)做波形補償,視訊則可容忍輕微馬賽克,整體對話依然能保持即時流暢。

因此,WebRTC 的影音傳輸採用了建立在 UDP 之上的 SRTP(Secure Real-time Transport Protocol),搭配 RTCP 傳遞控制資訊;而加密方面,雙方透過 DTLS 交握交換身分憑證並導出 SRTP 金鑰(DTLS-SRTP),資料通道則由 DTLS 直接進行傳輸加密,兼顧傳輸效率與安全性。

P2P 連線建立:Signaling、NAT 穿透與 ICE

建立 P2P 連線的最大難題在於真實世界的網路環境。絕大多數終端裝置都沒有獨立的公開 IP 位址,而是隱藏在路由器 NAT(Network Address Translation)與防火牆後方。

兩個瀏覽器要建立直接通訊,必須經歷以下連線建立流程:

信令機制 (Signaling)

WebRTC 規範刻意不定義信令協定(signaling protocol)。開發者可以自由選擇任何現有機制(例如 WebSocket、SIP、XMPP 甚至是 HTTP POST)來讓雙方交換連線意向。

雙方需要交換的連線資訊包含:

  • SDP (Session Description Protocol):透過 Offer / Answer 模型交換雙方支援的影音編解碼格式、加密方式與傳輸參數。2015 年當時的規範依據為 RFC 7116,而負責將其抽象為 JavaScript 操作的 JSEP 當時仍為 IETF 草案。
  • ICE 參數與候選位址:在標準流程中,ICE 的認證資訊(a=ice-ufrag、a=ice-pwd)與候選位址(a=candidate)會直接寫在 SDP 內。若採用 Trickle ICE(當時仍為 IETF 草案),雙方可先交換初期 SDP,待候選位址蒐集完成後再增量傳送,能大幅縮短通話建立的等待時間。

NAT 穿透三部曲:STUN、TURN 與 ICE

當雙方交換了 SDP 後,需要透過以下三種機制打通連線:

  • STUN (Session Traversal Utilities for NAT):客戶端向公開網路上的 STUN 伺服器發送請求,STUN 伺服器會將看到的來源公開 IP 與 Port 回傳。這樣客戶端就能得知自己在公網上的反射位址(reflexive candidate)。對於大多數錐型 NAT,只要雙方互相向對方的公開位址發送封包,就能成功穿透連線。不過若遇到對稱型(symmetric)NAT、NAT 不支援回送繞路(hairpinning),或是企業防火牆直接阻擋 UDP 流量,STUN 就無法穿透。
  • TURN (Traversal Using Relays around NAT):若直接穿透失敗,連線會退回到 TURN 伺服器,由 TURN 伺服器作為第三方中繼節點轉發所有媒體與資料封包(必要時甚至可透過 TCP 443 埠繞過嚴格的防火牆)。雖然走 TURN 會增加伺服器頻寬負擔並稍微增加延遲,但它保證了通話的成功率。
  • ICE (Interactive Connectivity Establishment):ICE 是一個整合框架(當時依循 RFC 5245 規範)。它會收集本機位址(host candidate)、STUN 反射位址(srflx candidate)以及 TURN 中繼位址(relay candidate),將兩端的候選位址配對,並依 candidate pair 的優先級(priority)排序逐組發送 STUN 連線檢查請求,第一組通過檢查的組合即被提名(nomination)為使用中的路徑;連線建立後,仍會持續發送 STUN binding request 作為 keepalive 探測。

關鍵挑戰:網路擁塞控制 (Congestion Control)

在研讀 WebRTC 時,最讓我感到精妙的是它的網路擁塞控制機制。

為什麼 UDP 也需要擁塞控制?

TCP 內建流量控制(接收視窗 rwnd)與壅塞控制(壅塞視窗 cwnd)兩套機制;後者從慢啟動(slow start,指數增加)起步,當偵測到網路丟包時改以 AIMD(加法增大、乘法遞減)收斂發送速率,避免網路發生擁塞崩潰(congestion collapse)。

但原生 UDP 完全沒有任何頻寬調節機制。如果 WebRTC 視訊以固定的高碼率(例如 2 Mbps)持續發送 UDP 封包,一旦途經網路瓶頸(例如家用 Wi-Fi 訊號減弱或行動網路切換基地台),發送端若毫無警覺繼續硬塞,封包就會在路由器佇列中堆積,導致延遲劇增、嚴重丟包,甚至將同一網路環境下的其他連線一併拖垮。

因此,如何在沒有 TCP 內建機制的 UDP 上,實現靈敏且平滑的動態擁塞控制,是 WebRTC 能夠實用的關鍵。

媒體串流的動態頻寬估算:GCC 雙控制器架構與 REMB

WebRTC(特別是 Google 的開放原始碼實作)採用了 Google Congestion Control(GCC)演算法(記錄於 IETF draft-ietf-rmcat-gcc 草案中)。GCC 的核心是「延遲型控制器」與「遺失型控制器」的分工協作:

  • 延遲型控制器 (Delay-based Controller):分析連續封包抵達時間間隔的變化趨勢,做為路徑排隊延遲的過載偵測器(over-use detector)。當路由器佇列開始積壓時,封包排隊延遲會逐漸上升。延遲型控制器能在實際丟包發生之前,就預先偵測到網路負載過重。此控制器可部署於接收端(透過 REMB 回傳估算上限),亦可部署於發送端。
  • REMB (Receiver Estimated Maximum Bitrate):在接收端架構下,接收端依據延遲型控制器推估出這條路徑目前能承載的位元率上限,並透過 RTCP REMB 訊息回報給發送端。它是一個純粹的頻寬上限估計值,兩大訊號的共識融合主要在發送端完成。
  • RTCP 統計回報與 RTT 計算:發送端定期發送 RTCP Sender Report(SR)記錄發送時間戳;接收端則回傳 Receiver Report(RR)提供遺失率(fraction lost)與抖動(jitter),並夾帶前次 SR 的時間戳(LSR)與收受後的延遲(DLSR)。發送端收到 RR 後,即可計算出目前的 RTT(Round-Trip Time)。
  • 遺失型控制器 (Loss-based Controller):執行於發送端,綜合考量封包遺失率、RTT 以及 REMB 所提供的頻寬上限,計算出最終建議的發送碼率。在早期 WebRTC 實作中,發送端速率還會受到 TFRC(TCP-Friendly Rate Control, RFC 3448)公式的調節與約束。
  • 動態編碼調整:發送端在確定目標發送碼率後,會即時通知本機的視訊編碼器(如 VP8 或 H.264)。當頻寬吃緊時,編碼器會調高量化參數(QP)、降低輸出碼率、調降幀率,甚至在極端情況下降低解析度;當網路恢復暢通時,再逐步向上探測可用頻寬。

這種結合了「延遲偵測」與「遺失率回饋」的雙重控制,讓視訊對話既能充分利用可用頻寬,又不會因為網路波動而頻繁斷訊。

資料通道的擁塞控制:SCTP over DTLS

在 RTCDataChannel 方面,WebRTC 並沒有自己從頭發明一套協議,而是選擇將 SCTP(Stream Control Transmission Protocol)架構在 DTLS/UDP 之上,並由 DTLS 直接提供傳輸層加密。

SCTP 本身就定義了完整的流量控制(flow control)與類似 TCP 的擁塞控制(具備 slow start 與 congestion avoidance),但它比 TCP 更具彈性:

  • 支援多串流(multi-streaming),不同串流之間不會相互卡住。
  • 可透過參數設定是否需要可靠傳送(maxRetransmits、maxPacketLifeTime)與是否嚴格保證順序(ordered: false)。

這使得 DataChannel 既能享有標準的網路擁塞防護,不至於癱瘓網路,又能保有 UDP 敏捷彈性的傳輸特質。

2015 年的 WebRTC 生態觀察

回顧目前的發展,WebRTC 的影響力已經從單純的瀏覽器實驗走向大規模商業應用:

  • 主流社交軟體的採用:Facebook Messenger 在今年 4 月 27 日正式跨平台(iOS 與 Android)上線視訊通話功能(5 月底推廣至全球),並選擇 WebRTC 作為核心底層,證明了這套架構在大規模跨平台行動通訊中的穩定度。
  • 原生客戶端的新選擇:除了 Google 主導的 libwebrtc 程式庫之外,Ericsson 推出了開源的 OpenWebRTC。它以 GStreamer 為基底,架構簡潔且容易自訂擴充,為 iOS 與 Android 開發者提供了另一個不錯的選擇。
  • 去中心化通訊架構:Matrix.org 正推動開放且去中心化的聯邦通訊標準,將 WebRTC 作為即時語音與視訊傳輸的協定層。今年 4 月他們首度展示了透過 OpenWebRTC 實現 iOS App 與網頁客戶端的互通,不過完整的 WebRTC 與 TURN 整合仍在積極完善中。
  • 尚未定案的 SDP 格式之爭:多串流(multistream)該採用 Chrome 的 Plan B 還是標準化的 Unified Plan,是當前社群最大的分歧之一。Firefox 在今年 6 月剛完成 Unified Plan 的初步實作,而 Chrome 仍維持 Plan B,Jitsi 等團隊甚至必須自製 sdp-interop 來跨瀏覽器轉譯。這段標準過渡期考驗著開發者的相容性處理。
  • 瀏覽器支援與規範演進:Chrome 與 Firefox 已經提供相當成熟的原生支援;微軟在 2015 年 4 月的 Build 大會宣布 Windows 10 與全新的 Edge 瀏覽器將支援 ORTC(Object RTC);Apple Safari 目前尚未跟進。需要強調的是,當前的 WebRTC 規範仍處於不斷修訂的編者草案(Editor’s Draft)階段,各項 API 與底層實作依舊處於「建構中(under active construction)」的演進狀態。

結論

WebRTC 不只是讓瀏覽器多了幾個 API,它本質上是將過去電信與 VoIP 領域累積數十年的複雜網路技術(NAT 穿透、SRTP 加密、SCTP 多串流、GCC 擁塞控制)進行了高度整合與標準化。

理解這些底層運作機制後,在除錯通話品質不佳、連線建立失敗或頻寬震盪時,才能有清楚的方向。

參考資料