跳到正文
meng shao· @shao__meng · X·· 2026-05-05AI 评分55
AI 导读

为实现语音AI的自然对话感,OpenAI采用WebRTC支持音频流式处理。针对1:1场景,采用Transceiver模型集中管理WebRTC状态,使后端可横向扩展。为解决WebRTC与K8s的端口和状态粘性问题,设计了Relay+Transceiver架构:轻量Relay层收敛公网UDP入口,并利用ICE ufrag字段编码路由信息,实现首包精准转发至对应Transceiver。该设计保留了协议语义,状态集中,并通过全球部署Relay优化路径,最终在K8s上实现了低延迟、高可扩展的语音交互系统。

正文 · 原文

OpenAI 如何实现规模化的低延迟语音 AI

语音交互的"自然感"完全建立在毫秒级响应之上。一旦网络抖动、首包慢、丢包,用户立刻感知为停顿、被打断或抢话失败。OpenAI 面对的约束有三条:
· 全球可达:服务 9 亿+ 周活用户
· 首连快:会话建立后用户能立刻开口
· 媒体 RTT 低且稳:低抖动、低丢包,让对话节奏紧凑

为什么选 WebRTC?
WebRTC 把实时音视频里最难的部分(NAT 穿透、加密传输、编解码协商、抖动缓冲、回声消除等)做成了浏览器与移动端原生支持的标准栈。对 AI 产品而言,最关键的特性是 音频以连续流的形式到达——模型可以在用户还在说话时就开始转写、推理、调用工具乃至生成回答,这是"对讲机"和"对话感"的分水岭。

媒体架构选择:放弃 SFU,采用 Transceiver 模型
· SFU(选择性转发单元):适合多方会议,把所有参与者的音视频汇聚后选择性转发。
· OpenAI 的实际负载:绝大多数会话是 1:1(一个用户对一个模型),对每一轮延迟都极敏感。

因此选择了 Transceiver 模型:边缘的 transceiver 服务终结 WebRTC 连接,再把媒体和事件转换为更简单的内部协议送往后端推理服务。所有 WebRTC 状态(ICE、DTLS 握手、SRTP 密钥、生命周期)只集中在 transceiver 一处,后端服务因此能像普通服务一样横向扩展,而不必充当 WebRTC 对端。

核心矛盾:WebRTC 与 Kubernetes 不兼容
最初版本是基于 Pion 的单 Go 服务,同时承担信令与媒体终结。但传统 WebRTC 的 "一会话一端口" 模型在 K8s 上水土不服:
· 端口耗尽:高并发意味着上万个公网 UDP 端口;云负载均衡和 K8s Service 都不擅长管理这种大端口段。
· 安全面扩张:庞大端口范围难以审计与加固。
· 弹性差:Pod 频繁创建销毁与端口预留冲突。
· 状态粘性问题:转向"单端口 + 应用层多路复用"后,又出现新问题——ICE 和 DTLS 是有状态协议,同一会话的后续包必须回到创建它的进程,否则握手与解密都会失败。

目标因此被精确定义为:对外暴露极小且固定的 UDP 表面,同时保证每个包都能精准回到拥有该会话的 transceiver。

解决方案:Relay + Transceiver 的拆分架构
把 包路由 和 协议终结 分离:
· Relay:轻量 UDP 转发层,公网入口很小;不解密、不跑 ICE、不参与编解码协商,只读取必要包头后转发。
· Transceiver:保持完整 WebRTC 状态机,对客户端而言完全是标准 WebRTC 行为。

关键技巧:用 ICE ufrag 做首包路由
WebRTC 在握手时本就交换一个短标识 ufrag(ICE username fragment)。OpenAI 在服务端生成 ufrag 时,把"目标集群 + 目标 transceiver"的路由信息编码进去:
· 信令阶段,transceiver 分配会话状态,并在 SDP answer 中返回 relay 的 VIP+端口(如 203.0.113.10:3478)。
· 客户端首个媒体包通常是 STUN binding request,relay 解析其中的 server ufrag,解码出路由提示,把包送到正确的 transceiver。
· 后续的 DTLS、RTP、RTCP 包基于已建立的会话表直接转发,不再重复解析。

Relay 只维护极小的内存态(地址映射 + 计数器 + 过期清理)。即使 relay 重启丢失会话,下一个 STUN 包就能依据 ufrag 重建路由。同时配 Redis 缓存使恢复更快。

Global Relay 与就近信令
公网 UDP 表面收敛后,可以把同一套 relay 模式部署到全球各地:
· 用 Cloudflare 地理与就近导向 把信令请求送到最近的 transceiver 集群。
· 该集群在 SDP answer 中通告就近的 Global Relay 入口。
ufrag 中携带的路由信息确保媒体包既能进入就近入口,又能锚定到唯一的 transceiver。

效果:信令与首个 ICE 探测都走最短路径,直接缩短了用户开口前等待的时间。

Relay 实现细节
Go 编写,运行在用户态,不引入内核旁路(kernel bypass),靠以下手段就能扛全球流量:
· SO_REUSEPORT:多 worker 绑同一 UDP 端口,内核分发,避免单读循环瓶颈。
· runtime.LockOSThread:goroutine 钉到固定 OS 线程,让同一 flow 落在同一 CPU 核,提升缓存局部性。
· 预分配缓冲 + 零拷贝解析:减少 Go GC 压力。
· 设计要点:不做协议终结、状态短时可丢、可水平扩展、重启对流量影响极小。

效果与可迁移的经验
· 在 K8s 上跑 WebRTC 媒体不再需要暴露上万 UDP 端口;安全面更小、负载均衡更稳、扩缩容更顺。
· 验证了对 1:1 的 AI 语音场景,SFU-less 是更合适的默认选择。

四条更普适的工程结论:
· 在边缘保留协议语义:客户端依旧说标准 WebRTC,浏览器与移动端不做任何特殊适配。
· 硬状态集中一处:ICE/DTLS/SRTP/会话生命周期全部归 transceiver。
· 路由用协议本身已有的字段:ufrag 提供了无需额外热路径查询的首包路由钩子。
· 先把常规路径打磨干净:用 SO_REUSEPORT、线程绑核、低分配解析就够用,不必上来就追求 kernel bypass。

原文地址
https://openai.com/index/delivering-low-latency-voice-ai-at-scale/

引用OpenAI Developers@OpenAIDevs
🎙️ Voice AI only feels natural when conversation keeps pace with speech. Here’s how we rebuilt our WebRTC stack with a thin relay and stateful transceiver to keep real-time media fast for ChatGPT voice, the Realtime API, and more. https://openai.com/index/delivering-low-latency-voice-ai-at-scale/
在 X 查看被引用的帖子

来源:meng shao · x.com