OpenAI 低延迟语音 AI 架构揭秘:WebRTC Relay + Transceiver 设计

2026 年 5 月 4 日 OpenAI 工程团队发布了一篇深度技术博文 详细介绍了他们如何为 9 亿+ 周活跃用户提供低延迟实时语音 AI 体验 这篇文章在 Hacker News 迅速登顶 引发了大量讨论

核心问题是 当语音对话的规模达到十亿级别 传统的 WebRTC 架构会遇到哪些瓶颈 OpenAI 给出的答案是 Relay + Transceiver 分离架构

为什么语音 AI 比文字实时更难

语音 AI 只有达到"语速"级别的响应才让人觉得自然 网络延迟造成的尴尬停顿 被截断的插话 延迟的 barge-in(打断)都会立刻破坏用户体验

对于 OpenAI 来说 这意味着三个硬性要求

  • 全球覆盖 - 为 9 亿+ 用户提供一致的语音体验
  • 快速建连 - 用户点击麦克风到能说话的时间必须极短
  • 低且稳定的媒体 RTT - 低抖动和低丢包 保证连麦感觉流畅

这也是 ChatGPT Voice、Realtime API(WebRTC 端点)以及各类交互式 AI Agent 的底层基础设施需求

为什么选 WebRTC

WebRTC 是一套开放标准 为浏览器和移动端提供了端到端的低延迟音视频传输能力 它对 AI 场景的核心价值在于

  • ICE - 连接建立和 NAT 穿透
  • DTLS + SRTP - 加密传输
  • Codec 协商 - 压缩和解码音频
  • RTCP - 质量控制
  • 客户端特性 - 回音消除、抖动缓冲等

没有 WebRTC 的话 每个客户端都需要自己解决 NAT 穿透、加密传输和网络自适应问题 而 WebRTC 已经在浏览器和移动平台上广泛实现了这些 团队只需专注于把实时媒体连接到 AI 模型

值得一提的是 WebRTC 的原始架构师之一 Justin Uberti 和 Pion(Go WebRTC 库)的作者 Sean DuBois 现在都是 OpenAI 的同事 他们正在推动 WebRTC 和实时 AI 更紧密的结合

AI 语音的独特需求:流式音频

对于 AI 来说 最重要的是音频以连续流的方式到达 语音 Agent 可以在用户还在说话时就开始转写、推理、调用工具或生成语音 而不需要等完整上传

这就是"对话式"和"按键通话"之间的本质区别

架构选型:SFU vs Transceiver

确定使用 WebRTC 后 下一个问题是 "在哪里终止 WebRTC 连接"

SFU(Selective Forwarding Unit)

传统方案是 SFU 每个参与者和 SFU 建立独立的 WebRTC 连接 AI 也作为一个参与者加入会话 这对多方通话(群组通话、教室、协作会议)很合适

但 OpenAI 的场景大部分是 1:1 —— 一个用户对一个模型 且延迟敏感度极高

Transceiver 模型

因此 OpenAI 选择了 Transceiver 方案

  • WebRTC 边缘服务(Transceiver)终止客户端连接
  • 然后将媒体和事件转换为简单的内部协议
  • 发送给模型推理、转写、语音生成、工具调用和编排等后端服务

在这个设计中 Transceiver 是唯一拥有 WebRTC 会话状态的服务 包括 ICE 连通性检查、DTLS 握手、SRTP 加密密钥和会话生命周期 这让后端服务可以像普通服务一样伸缩 而不是作为 WebRTC 对等端存在

Kubernetes 上的 WebRTC 难题

OpenAI 的 Transceiver 用 Go + Pion 实现 运行在 Kubernetes 上 但传统的 "一个 WebRTC 会话占一个 UDP 端口" 模型在 K8s 环境遇到了两个大问题

问题一:端口爆炸

高并发场景下 每个会话一个端口意味着需要暴露和管理数万个 UDP 端口

  • 云负载均衡器和 K8s Service 不是为每个服务开几万个 UDP 端口设计的
  • 大 UDP 端口范围很难审计安全策略
  • K8s 自动扩缩容时 Pod 不断增删 每个 Pod 需要预留和公告大块稳定端口范围 弹性变得很脆弱

问题二:会话粘性

ICE 和 DTLS 是有状态的协议 一个会话的初始化过程和后续数据必须落在同一个进程上 如果在负载均衡层面跨 Pod 路由 会话可能会建立失败或媒体中断

解决方案:Relay + Transceiver 分离架构

OpenAI 的方案是将 包路由(Relay)协议终止(Transceiver) 分离

架构总览

  • Relay - 轻量级 UDP 转发层 暴露极小的公网端口
  • Transceiver - 有状态的 WebRTC 端点 部署在 Relay 后面

Relay 不解密媒体、不运行 ICE 状态机、不参与 Codec 协商 它只读取足够的数据包元数据来决定转发目标 然后将包转发给拥有该会话的 Transceiver

从客户端角度看 WebRTC 会话一切正常 没有任何变化

关键设计:ICE ufrag 路由

第一个数据包的路由是最关键的一步 Relay 必须在没有现成会话的情况下路由第一个包 而不是去查外部服务

OpenAI 利用 WebRTC 协议自带的钩子:ICE username fragment(ufrag)

每一端在 ICE 协商时都有自己的 ufrag Relay 生成的 ufrag 中编码了足够的路由元数据 让 Relay 可以推断出目标集群和拥有该会话的 Transceiver

  1. 信令阶段 Transceiver 分配会话状态 返回共享的 Relay VIP 和 UDP 端口
  2. 客户端发起 STUN 连接请求
  3. Relay 解析 ufrag 识别目标 Transceiver
  4. 转发数据包到正确的 Transceiver 实例

客户端看到的只是一个稳定的目标地址(如 203.0.113.10:3478)背后有多个 Relay 实例

方案对比

  • 每会话独立 IP:端口 - 直接客户端到服务器 但需要大量端口 不适合 K8s
  • 每服务器共用端口 - 端口占用小 但跨负载均衡集群时首包可能落在错误的实例
  • TURN 中继 - 可集中策略 但增加建连轮次 分配迁移困难
  • 💡 Relay + Transceiver(OpenAI 方案) - 公网端口占用极小 + 保持 WebRTC 会话完整性 + 原生支持 K8s 弹性

工程实现细节

单端口复用

Relay 暴露一小段固定的 UDP 端口 单端口内部通过应用层多路复用(demultiplex)区分成千上万的并发会话

无状态转发

Relay 本身无需维持会话状态 它只读取 STUN Binding Request 中的 ufrag 做一次哈希或查找 然后转发 即使 Relay 实例重启或扩容 已有会话不受影响

Transceiver 的职责

  • 信令:SDP 协商、Codec 选择、ICE 凭证、会话建立
  • 媒体:终止下游 WebRTC 连接、维护到后端服务的上游连接(推理、编排等)

Transceiver 完全拥有 WebRTC 会话状态 可以像普通微服务一样部署在 K8s 上

对 AI 开发者的价值

这篇文章对 AI 应用开发者有三个重要启示

1. WebRTC 是构建实时语音 AI 的最佳基础

OpenAI 的选择验证了 WebRTC 的成熟度 如果你在构建语音 Agent 或实时对话式 AI 直接用 WebRTC 比拼凑自定义 UDP 协议更可靠

2. 架构分离提高可伸缩性

Relay 和 Transceiver 的分离解耦让两者可以独立扩缩 如果流量突增 只需要增加 Relay 实例(无状态、轻量)或 Transceiver 实例(有状态、计算密集)各自调整

3. Pion(Go WebRTC)的生产力

OpenAI 用 Go + Pion 实现了整个 Transceiver 服务 这说明 Pion 已经足够成熟支撑十亿级实时通信负载 对于中小团队来说 用 Pion 自建 WebRTC 服务的门槛远低于 C++ 原生方案

总结

OpenAI 这篇博文是近年来最有价值的实时媒体基础设施分享之一 它展示了一个经过十亿用户验证的 WebRTC 大规模部署方案

核心思路其实很清晰

  1. 不要改变客户端和服务器之间的 WebRTC 协议
  2. 在集群内部做包路由和应用层协议的分离
  3. 利用协议自带的元数据(ufrag)做智能路由
  4. 让每个组件只做一件事

这套架构不仅适用于语音 AI 对话 也可以用于任何需要大规模实时媒体的场景 包括视频会议、实时翻译、语音客服等

对于普通开发者而言 即使不直接做基础设施 理解这套设计思路也能帮助你在构建实时系统时做出更好的架构决策