OpenAI 「实时语音」架构首次公开

PRODUCT


Realtime API 是 OpenAI 的实时语音交互接口,在 24 年的 DevDay 首次亮相,当时还是 beta,调用贵到离谱,音频输出 200 刀/百万 token:OpenAI 凌晨发布:Realtime 实时多模态 API,及其他

两个月后新加坡 DevDay,我在现场看了多语言混合输入输出的演示,情绪和语气都非常到位,比 Whisper 链路的效果好了一个量级


之后经历了 WebRTC 支持、SIP 电话接入、图片输入、多轮调价,到 2025 年 8 月正式 GA。现在这套系统服务数亿周活用户,语音 AI 这条线上,目前没有第二家能打的

Realtime API 这个东西,最牛逼的是延迟:从你对着手机说一句话开始,到听到 AI 返回声音为止,只需要不到 0.3 秒

在这个过程中,声音变成数据包,穿过 Wi-Fi、运营商的网络、横跨大半个互联网,到达 OpenAI 的服务器。然后,服务器跑完推理、生成语音,再原路返回。整个过程必须快到让你感觉不到延迟,就像跟一个真人在说话


对于这玩意儿是怎么实现的,OpenAI 今天发了个技术 Blog,来详细介绍了下

图片[1]-OpenAI 「实时语音」架构首次公开 - AI资源导航站-AI资源导航站

https://openai.com/index/delivering-low-latency-voice-ai-at-scale/

然后…第二作者,是麦当劳


核心信息包括:

 OpenAI 没有用行业默认方案,自己设计了 relay + transceiver 两层架构,前者只负责转发数据包,后者负责所有通话状态

 relay 极其轻量,不解密、不解码、不参与任何协商,只看数据包头部的一小段标记就知道往哪儿转

 全球各地部署了相同的 relay 入口,用户的数据包在离自己最近的地方进入 OpenAI 的网络

 relay 用 Go 语言写的,没有用更底层的高性能方案,因为够用了

 整套架构跑在 Kubernetes 上,对外只暴露少量固定端口


技术方案选型

OpenAI 用的实时通信协议叫 WebRTC,就是你平时微信视频通话、Google Meet 开会时底层跑的那套技术。它是一个开放标准,能在浏览器、手机和服务器之间传输低延迟的音频和视频

做 WebRTC 服务,行业里有一个默认选择叫 SFU(选择性转发单元)。简单说就是一个中转站,每个参与者跟它建一条连接,它负责把声音和画面转发给其他人。多人视频会议用这个方案很合适,音视频编解码、录制、策略控制都集中管理

图片[2]-OpenAI 「实时语音」架构首次公开 - AI资源导航站-AI资源导航站

SFU 方案:AI 作为 WebRTC 参与者加入,适合多方通话

OpenAI 的场景不一样。绝大多数会话是 1:1,一个用户对一个模型,每一轮对话都对延迟极度敏感。SFU 带来的多方通话基础设施,在这个场景里是多余的

他们还评估过另一个常规方案 TURN,这是 WebRTC 穿透防火墙时常用的中继方式。但 TURN 要求中继节点持有客户端的连接分配状态,不够轻量

最后选的方案叫 transceiver 模型:在网络边缘部署一个 WebRTC 服务,负责跟客户端完成连接建立、加密握手这些协议工作,然后把收到的音频转成更简单的内部协议,分别送给后面的推理、转录、语音合成服务。所有通话状态集中在 transceiver 一个地方,后端的 AI 服务可以当普通服务来扩展,完全不需要懂 WebRTC

图片[3]-OpenAI 「实时语音」架构首次公开 - AI资源导航站-AI资源导航站

transceiver 方案:在边缘终止 WebRTC,转换为后端协议


端口占用问题

选定 transceiver 方案之后,还有一个工程问题要解决:端口占用

传统 WebRTC 部署里,每个通话需要占用一个独立的网络端口。当同时通话的用户有几百万个的时候,端口会不够用。OpenAI 的基础设施跑在容器化平台 Kubernetes 上,没法给每个容器预留几千个公网端口

他们的做法是把数据包的「转发」和「处理」拆成两层

relay 是第一层,部署在面向公网的入口。它是一个极轻的 UDP 转发服务:不解密通话内容,不跑任何协议状态机,不参与编解码协商,不知道你在说什么。它只做一件事,读取数据包头部的一小段标记来判断这个包属于哪个会话,然后转发给对应的 transceiver

transceiver 是第二层,在 relay 后面。它拥有通话的全部协议状态,包括 ICE 连通性检查、DTLS 加密握手、SRTP 媒体解密,以及会话的整个生命周期。从用户的手机或浏览器来看,通话行为没有任何变化

图片[4]-OpenAI 「实时语音」架构首次公开 - AI资源导航站-AI资源导航站

relay 只做无状态转发,transceiver 持有完整会话状态

relay 持有的信息极其精简:一条内存中的转发映射(这个客户端的包往哪个 transceiver 送),加几个监控计数器和过期定时器。没有持久化,没有协议参与。如果 relay 重启了,下一个数据包到达时就能自动重建路由


解决首响应问题

Realtime API 最牛逼的地方,是在 0.3 秒内完成首响应,这就需要对首包进行路由管理。用户发出的第一个数据包到达 relay 时,relay 还没有任何关于这个用户的信息,但它必须立刻知道往哪里转发。在这一步中,如果停下来查数据库或者问别的服务都会增加延迟,是不行的

OpenAI 利用了 WebRTC 协议自带的一个机制:ICE ufrag(ICE 用户名片段)。这是在通话建立阶段双方交换的一个短标识符,之后客户端发的每个连通性检查包都会带上它。OpenAI 在服务端生成 ufrag 时,把路由需要的信息编码在了里面

具体流程:通话建立时,transceiver 分配好会话状态,在协商应答(SDP answer)里返回一个共享的 relay 虚拟 IP 和 UDP 端口。客户端看到的是一个固定的目标地址,比如 203.0.113.10:3478,背后其实是整个 relay 集群

客户端发出的第一个数据包通常是一个 STUN binding request。relay 只解析这个包头部的 ufrag 字段,解码出路由提示,把包转发给拥有该会话的 transceiver。之后这个客户端的所有后续包都走同一条已建立的路

图片[5]-OpenAI 「实时语音」架构首次公开 - AI资源导航站-AI资源导航站

从连接建立到媒体传输的完整时序:Client → LB → Relay → Transceiver

容灾方面,Redis 缓存了「客户端 IP:Port → transceiver IP:Port」的映射。relay 重启后可以在下一个 STUN 包到来之前就从 Redis 恢复转发路径,进一步缩短中断窗口


进行全球部署

如果用户在北京说一句话,如果数据包要跑到美国西海岸才开始处理,单程网络延迟就可能超过 150 毫秒,一来一回 300 毫秒。对话体验会明显卡顿。解决办法是让数据包尽早进入 OpenAI 自己的高速网络

relay 的公网暴露面缩到少量固定地址和端口之后,同一套转发逻辑就能在全球各地复制部署。OpenAI 把这个叫 Global Relay,一组地理分布式的 relay 入口点,都运行相同的包转发行为

图片[6]-OpenAI 「实时语音」架构首次公开 - AI资源导航站-AI资源导航站

Global Relay 接收全球客户端的数据包,转发给 transceiver 集群

用户的数据包在离自己最近的入口进入 OpenAI 网络,然后通过内部骨干网到达 transceiver。跟直接穿越公网相比,延迟更低,抖动更小,丢包更少

整套架构跑在 Kubernetes 上不需要暴露成千上万个 UDP 端口。更小且固定的暴露面更容易做安全策略和负载均衡,扩展时也不需要预留大段公网端口范围


底层是 Go 写的

做实时媒体转发,常规选择是 C/C++ 或者 Rust,有些追求极致的团队甚至会上 kernel bypass,绕过操作系统内核让程序直接操作网卡。OpenAI 的 relay 用 Go 写,这在行业里算非常规

他们在 Go 运行时层面做了几个针对性优化:

SO_REUSEPORT 让同一台机器上多个 relay 进程共享同一个 UDP 端口,操作系统内核在它们之间分配数据包,避免单一进程成为瓶颈

runtime.LockOSThread 把每个负责读 UDP 数据的 goroutine 钉在一个固定线程上,配合 SO_REUSEPORT,同一个通话的包倾向于落在同一个 CPU 核心,缓存命中率更高

 预分配内存缓冲区,最小化数据拷贝,避免在转发热路径上触发 Go 的垃圾回收

这套实现撑住了全球的实时媒体流量,relay 集群规模相对不大。所以他们没有进一步走 kernel bypass 路线

补充一个细节:OpenAI 使用了 Pion,一个 Go 语言的 WebRTC 开源库。Pion 的作者 Sean Der 在 Hacker News 上确认了这一点


三条设计原则

对于这个项目,OpenAI 在总结了三条原则,对任何做实时系统的团队都有参考价值:

硬性状态集中在一个地方 transceiver 拥有 ICE、DTLS、SRTP 和会话生命周期,relay 只转发。状态集中意味着出了问题只查一个地方

在已有信息上做路由 ICE ufrag 是协议自带的标识符,把路由信息编码在里面,首包到达时就能路由,不需要在热路径上加外部查询

够用就不换 Go 配合几个内核级优化对当前负载已经够用,就没有上 kernel bypass。先跑起来,再决定要不要换更重的方案

实时语音 AI 能跑起来,靠的是基础设施让延迟变得感知不到

OpenAI 改变的是 WebRTC 部署的内部形态,但没有改变客户端对 WebRTC 协议的预期

© 版权声明
THE END
喜欢就支持一下吧
点赞22 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片