語音 AI 的最後一哩路:當架構決定體驗
如果你用過 ChatGPT 的語音模式,大概已經體驗過那種「它聽得懂你何時插話」的驚喜感。但你有沒有想過,背後是怎麼做到的?
想像你正在跟 ChatGPT 對話,你講到一半突然糾正自己:「不,我是說…」,然後它瞬間理解了你的打斷,繼續接話。這種自然到幾乎不被察覺的互動,背後藏著一套極度複雜的網路基礎建設。
OpenAI 最近公開了他們如何重新設計 WebRTC(網頁即時通訊)架構來支援超過 9 億的每週活躍用戶,確保語音對話的延遲夠低、體驗夠順暢。對台灣的開發者和創業者來說,這不只是 OpenAI 的內部技術故事——它揭示了即時語音 AI 產品在規模化時會遇到的真實瓶頸,以及怎麼繞過它們。
語音 AI 的低延遲需求:三個不能妥協的條件
當一個語音 AI 系統要服務 9 億用戶時,延遲不再只是「快不快」的問題,而是「能不能用」的問題。OpenAI 的團隊列出了三個硬需求:
第一,全球覆蓋。 用戶遍布世界各地,從美國到台灣,每個人打開 ChatGPT 語音都應該能在幾秒內開始對話。這意味著你的網路入口點必須夠分散,讓使用者的封包不用繞半個地球。
第二,快速連線建立。 使用者按下語音按鈕後,到真正能開始說話的時間應該趨近於零。傳統的 WebRTC 連線建立需要 ICE(互動式連線建立)握手、DTLS(資料包傳輸層安全協議)加密協商,這些來回溝通在一般場景下沒問題,但對即時語音來說,每一次往返都在消耗用戶的耐心。
第三,穩定且低的媒體往返時間。 不只是快,還要穩定。延遲的抖動(jitter)和封包遺失會讓語音聽起來斷斷續續。想像你在跟人講電話,對方每隔幾秒就飄一句「你說什麼?」——這就是抖動太高的結果。根據 OpenAI 的數據,這些問題在規模化之前可能不明顯,但當同時連線數達到數百萬時,每個小問題都會被無限放大。
WebRTC 為什麼是語音 AI 的基礎
你可能聽過 WebRTC 這個詞——它是 Google 主導開發的開放標準,專門用來讓瀏覽器和行動裝置之間進行低延遲的音視訊通訊。原本的設計場景是視訊會議,但 OpenAI 發現它同樣適合做語音 AI 的傳輸層。
為什麼不自己建一套協定?因為 WebRTC 已經解決了即時通訊中最棘手的問題:
- NAT 穿透: 解決了「你的電腦在路由器後面,伺服器如何找到你」的問題
- 加密傳輸: DTLS 和 SRTP 保證語音內容不會被竊聽
- 編解碼協商: 自動決定用哪種壓縮格式來傳送語音
- 品質控制: RTCP 回報網路品質,讓系統動態調整
更重要的,這些功能在 Chrome、Safari、行動裝置上已經內建實作。對 OpenAI 來說,選擇 WebRTC 意味著他們只需要專注在建構背後的基礎設施,不需要從頭打造傳輸層。
有趣的是,OpenAI 現在還挖來了 WebRTC 的原創架構師 Justin Uberti 和 Pion(Go 語言的 WebRTC 實作)的創作者 Sean DuBois,讓他們加入團隊共同優化即時語音的底層架構。
選擇架構:為什麼捨棄 SFU 改用收發器模式
在 WebRTC 的世界裡,處理多人通訊最常見的模式是 SFU(選擇性轉發單元)。它就像一個會議主持人,接收每個參與者的串流,然後選擇性地轉發給其他人。如果你用過 Zoom 或 Google Meet,你用的就是 SFU。
SFU 的優點很明顯:一群人開會時非常適合。但它有一個根本問題——它假設場景是多對多的。而 OpenAI 的場景是「一個人對一個 AI 模型」,也就是一對一。
在 SFU 模式中,AI 模型會被當作另一個「與會者」加入會議。這代表每個串流都要經過一次轉發,增加了不必要的延遲。對於需要即時反應的語音 AI,這個延遲是不能接受的。
OpenAI 選擇了收發器(transceiver)模式。簡單來說,收發器是一個邊緣服務,由它來終止客戶端的 WebRTC 連線,然後把媒體和事件轉換成更簡單的內部協定,傳送給後端的模型推論、語音轉文字、語音生成等服務。
這種設計的關鍵優勢在於:收發器是唯一擁有完整 WebRTC 連線狀態的服務。ICE 連線檢查、DTLS 握手、SRTP 加密金鑰、連線生命週期,全部集中在一個地方。這讓後端服務可以像普通的 HTTP 服務一樣擴展,不需要理解 WebRTC 的複雜細節。
單埠模型:解決 Kubernetes 上的 UDP 噩夢
當 OpenAI 把收發器部署到 Kubernetes 上時,馬上遇到了一個大問題。
傳統的 WebRTC 伺服器使用「一個連線一個 UDP 埠」的模式。意思是每一條語音連線都需要一個獨立的 UDP 埠號。當同時連線數達到數十萬甚至上百萬時,問題出現了:
- Kubernetes 的負載平衡器不是為管理數萬個 UDP 埠設計的
- 大量的 UDP 埠擴大了攻擊面,維運和資安政策難以管控
- Pod 在 Kubernetes 上會頻繁新增、移除、重新排程,每個 Pod 都需要保留一大段穩定的埠號範圍,這讓自動擴展變得非常困難
為了解決這個問題,許多 WebRTC 系統轉向了「單埠」模式——每台伺服器只暴露一個 UDP 埠,在應用層做多工分流。
但單埠模式引發了第二個問題:連線所有權的歸屬。ICE 和 DTLS 是有狀態的協定。建立連線的那個程序必須持續接收同一個連線的封包,才能驗證連線正確性、完成 DTLS 握手、解密 SRTP。如果同一個連線的封包落到不同的程序上,連線就會中斷,媒體也會出問題。
核心解法:中繼器 + 收發器的分離架構
OpenAI 的解法是把封包路由和協定終止分開,形成「中繼器 + 收發器」的雙層架構。
中繼器(relay) 是一個非常輕量的 UDP 轉發層,暴露一個小而穩定的 UDP 埠範圍。它不解密媒體、不執行 ICE 狀態機、不參與編解碼協商。它只做一件事:讀取足夠的封包中繼資料來決定要把封包轉發到哪裡。
收發器(transceiver) 是後端真正的 WebRTC 端點。它擁有所有的協定狀態,從客戶端的角度來看,WebRTC 連線完全正常——只是封包在中間多跳了一次。
關鍵的技術巧思在於「第一封包路由」:當中繼器收到來自客戶端的第一個封包時,它怎麼知道要把封包送給哪個收發器?
答案是 ICE ufrag(使用者名稱片段)。每個 WebRTC 連線在建立時都會交換一個簡短的識別碼,叫 ICE ufrag。OpenAI 在生成伺服器端的 ufrag 時,刻意在裡面編入了路由資訊——哪個叢集、哪個收發器負責這個連線。
中繼器解析第一個 STUN(Session Traversal Utilities for NAT)封包,讀取伺服器 ufrag,解碼路由提示,然後把封包轉發給對應的收發器。後續的 DTLS、RTP、RTCP 封包就可以在同一個連線中流動,不需要重新解碼 ufrag。
為了進一步提升可靠性,OpenAI 還用 Redis 快取了 <客戶端IP+埠, 收發器IP+埠> 的對應關係。這樣即使中繼器重啟導致連線狀態丟失,Redis 可以更快地恢復路由,不需要等到下一個 STUN 封包到來。
全球中繼:讓語音封包不再繞遠路
一旦把公開 UDP 埠縮減到少數穩定的位置和埠號,OpenAI 就能部署「全球中繼」——分布在世界各地的中繼器,全部實作同樣的封包轉發行為。
你可以想像成 OpenAI 在全球各地設立了「語音閘道」。當台灣的使用者打開 ChatGPT 語音時,封包會進入最近的中繼點(可能是東京或新加坡),而不是穿過整個網際網路到達美國西岸。
為了做到這一點,OpenAI 使用 Cloudflare 的地理位置和鄰近性導向來分配信令流量。初始的 HTTP 或 WebSocket 請求會到達離使用者最近的收發器叢集。這個請求的上下文決定了連線的位置,以及要給客戶端的全球中繼位址。
SDP 應答(Session Description Protocol 的回應)提供全球中繼位址,而 ufrag 包含足夠的資訊讓全球中繼能把媒體路由到指定的叢集,再由該叢集的本地中繼路由到目標收發器。
這個設計的結果是:信令和媒體都在離使用者最近的位置進入 OpenAI 的骨幹網路,大幅縮短了第一跳的延遲,也減少了網際網路長距離傳輸帶來的抖動和封包遺失。
實作細節:Go 語言打造的輕量級中繼
OpenAI 用 Go 語言實作了中繼服務,刻意保持功能範圍狹窄。
在 Linux 上,核心的網路堆疊會從網路介面接收 UDP 封包,並傳遞給綁定了對應 IP:Port 的 socket(作業系統端點)。中繼運行在使用者空間,一個普通的 Go 程序從 socket 讀取封包標頭,更新少量的串流狀態,然後轉發封包。
有趣的是,OpenAI 團隊特別提到他們不需要任何核心繞過(kernel-bypass)技術——像 DPDK 或 XDP 那樣繞過作業系統核心直接操作網路硬體。因為中繼做的事情太少了,使用 Go 和使用者空間 socket 就足以達到效能要求。這降低了實作複雜度和維運成本。
對台灣開發者的啟示
OpenAI 這篇文章對台灣開發者至少有三層意義:
第一,語音 AI 的基礎架構問題是真實存在的。 如果你正在開發語音代理人、客服機器人或任何需要即時語音互動的產品,千萬不要低估網路層的挑戰。當語音串流的延遲超過 300 毫秒時,使用者就會明顯感覺到不自然。這不是單純加幾台伺服器就能解決的問題。
第二,開放標準是最好的起點。 OpenAI 選擇 WebRTC 而不是自己發明協定,說明了在即時通訊領域,站在開放標準的肩膀上發展是更明智的策略。台灣的開發者做語音產品時,也可以直接採用 WebRTC,專注在應用層的創新,而不是重複造輪子。
第三,架構選擇會決定規模化的天花板。 OpenAI 捨棄 SFU 選擇收發器模式,不是因為 SFU 不好,而是因為場景不同。台灣創業者在做技術選型時,最重要的是釐清自己的使用場景——是多對多的群組對話,還是一對一的 AI 互動?這會直接影響你需要哪種架構。
此外,還有一個非常實用的技術細節值得關注:OpenAI 用 ICE ufrag 內嵌路由資訊的手法。這是一個典型的「用既有的協定資料解決新問題」的思維,不需要新增任何額外的協定或欄位,就能搞定第一封包路由。這種思考方式對任何在做系統設計的工程師都有啟發。
真正的挑戰:當語音 AI 從驚喜變成一種期待
看完 OpenAI 的技術分享,你可能會覺得這是大公司的奢侈煩惱——畢竟不是每家公司都有 9 億用戶的語音流量。
但其實這篇文章透露了一個更深層的信號:語音 AI 正在從「酷炫功能」變成「基本要求」。當 OpenAI 願意花這麼多力氣去優化一個連線建立時間減少幾百毫秒的架構,代表他們意識到使用者對語音延遲的容忍度正在趨近於零。
五年後回看,我們可能會發現 OpenAI 這套架構的設計哲學——把協定終止和封包路由分離、用標準協定嵌入路由資訊、地理分散的邊緣入口——已經成為語音 AI 基礎設施的事實標準。
而對於正在讀這篇文章的開發者來說,最好的時間點永遠是現在。語音 AI 的基礎建設正在成型,趁著標準還沒固化之前,找到自己的切入點,比等到一切底定後再追趕更有機會。
畢竟,OpenAI 可以為了語音體驗重新設計 WebRTC 架構。但你不需要。
你只需要知道這些架構思考的背後,代表的是使用者對語音 AI 的期待已經變了——他們不再接受「能說話就好」,而是要求「像真人對話一樣流暢」。這個期待,是所有語音產品開發者面對的新常態。