OpenAI Realtime API 通过 WebSocket 或 WebRTC 连接客户端。对于服务器侧连接,你可以从任何有网络的机器直接访问 OpenAI。对于客户端侧连接——也就是你真正想用它构建的大部分东西——浏览器需要一个安全源,你的后端需要签发临时令牌。两者都能通过隧道工作。有些细节值得了解。
两种连接方式,两个穿隧道的理由
Realtime API 支持服务器侧连接(你的后端向 OpenAI 打开一个 WebSocket)和客户端侧连接(浏览器使用你后端签发的临时令牌打开一个 WebRTC 对等连接或 WebSocket)。服务器侧路径不需要隧道。客户端侧几乎总是需要。
为什么客户端侧需要 HTTPS:
- 浏览器麦克风权限需要安全源。
- WebRTC 的
getUserMedia和 ICE 处理在 HTTPS 上效果最好。 - Service Worker(如果有)需要它。
- 如果你调用后端的
/session端点来获取临时令牌,那么当你的前端是 HTTPS 时,那个后端也必须是 HTTPS。
第一点你可以用浏览器标志绕过。别这么做。用一个 隧道,活在真实世界里。
开发中的 Realtime 应用的形态
一个最小的 realtime 应用有三个部分:
- 一个捕获麦克风输入并渲染音频输出的前端。
- 一个后端路由,用你真正的 API key 调用 OpenAI 的
/v1/realtime/sessions端点来签发临时令牌。 - 一个从浏览器到 OpenAI 的、使用临时令牌的直接 WebRTC 或 WebSocket 连接。
你的隧道暴露前端 + 后端(多数设置下同一个域名)。真正的 realtime 流量走浏览器到 OpenAI,而不经过你的隧道——那个连接是通过 HTTPS/WSS 直连的。
用 PortPreview 快速搭建
- 在 3000 或 5173 端口启动你的开发服务器(Next.js、Vite,随便什么)。
- 运行
npx portpreview 3000。 - 在浏览器中打开 HTTPS URL。麦克风权限提示正常工作。
- 调用你的令牌签发端点,拿到临时令牌,打开 realtime 连接。
- 说话,收到流式响应。
如果你用 Vite,你会需要 Vite + 隧道 里的 allowedHosts 和 HMR 配置。如果你在 Next.js 的某处用了 edge runtime,要当心需要 Node crypto 的路由上的 runtime 配置。
WebSocket 升级穿过隧道
Realtime 连接是 WebSocket(或者 WebRTC,它大多绕过隧道)。你用的任何隧道都必须正确转发 HTTP 的 Upgrade 请求。大多数都会——PortPreview、Cloudflare quick tunnels、ngrok 都处理 WebSocket 升级。如果你的不会,连接会在浏览器里悄悄失败,只有一条通用的 WebSocket closed before connected 消息,没有有用的细节。
如果不确定,用 wscat 测试升级。连接到 wss://your-tunnel.portpreview.dev/anything,观察握手。
真正有用的开发技巧
检查令牌签发请求
你的前端调用一个调用 OpenAI 的后端路由。这里最常见的开发 bug 是发往 /v1/realtime/sessions 的请求配置错误——模型名错、voice 错、modalities 错。你的隧道捕获前端到后端的请求,但捕获不到后端到 OpenAI 这一跳。在服务器侧记录那个请求,或者把两层都跑在本地,通过隧道代理它。
音频格式不匹配
Realtime API 默认使用可配置采样率的 PCM16。如果你灌入另一种格式的音频,模型要么拒绝,要么产生幻觉。浏览器 MediaRecorder 通常给你 Opus 或 WebM——你需要处理转换,或者用替你处理它的 WebRTC 路径。
长会话中的令牌过期
临时令牌寿命很短。如果你测试的会话比令牌 TTL 长,就按计划刷新。Realtime SDK 有相应的辅助工具;自己实现意味着监听 session.expired 事件,并在旧令牌死掉之前签发一个新的。
这在生产中是什么样
从开发到生产唯一真正的改动是 URL:把隧道主机名换成你真正的域名。令牌签发端点留在你的后端。从浏览器到 OpenAI 的 WebRTC/WebSocket 连接是同一条代码路径。我们见过有团队把这个想复杂了,试图把 realtime 流量代理过他们的后端——别这么干,它会增加延迟,并破坏 OpenAI 的 SDK 所假定的模型。
关于 Anthropic 的并行产品(它更接近一个工具调用循环,而非流式 WebSocket),参见 在本地使用 Anthropic tool use 和 Webhook。加入 PortPreview 等候名单,获得默认处理 WebSocket 升级的隧道。