本章聚焦于语音实时对话的核心管道设计。与传统的“ASR(识别)→ NLP(理解)→ TTS(合成)”级联式架构不同,OpenAI Realtime API 提供了一个端到端的、流式的多模态交互环境。在车载场景下,这意味着更低的延迟、更自然的打断(Barge-in)以及听觉与视觉的并发处理。
本章学习目标:
在车载环境中,直接从车机端(Client)连接 OpenAI 存在安全隐患(API Key 泄露)和逻辑编排困难。因此,推荐采用 BFF (Backend for Frontend) Relay 模式。
我们主要通过 WebSocket 或 WebRTC 进行连接。
Rule-of-Thumb: 在车端与云端网关之间使用成熟的私有协议或 WebSocket,在云端网关(Relay Server)与 OpenAI 之间使用官方推荐的 WebSocket 链接。 除非对延迟有极致要求(<300ms 端到端)且网络环境极其优越,否则避免车端直连。
+--------+ (1) Audio/Events +---------+ (2) Signed WS +----------+
| Vehicle | <========================> | Relay | <====================> | OpenAI |
| (Client)| (Custom/WS) | (Server)| | Realtime |
+--------+ +---------+ +----------+
| | |
| [Mic Input] -> DSP(AEC/NS) -> Enc | [Auth & Session Mgmt] | [Model]
| [Spk Output] <- Dec <- Buffer | [Tool Execution (Car Ctrl)] | [Audio In/Out]
| [Screen/Cam] -> Base64/Binary | [RAG / Knowledge Fetch] | [Function Call]
+ + +
OPENAI_API_KEY,该 Key 永不下发到车端。Session ID,连接断开即销毁上下文(除非使用了持久化记忆机制,见 Chapter 5)。Realtime API 是有状态的。管理好“连接—配置—交互—销毁”的闭环至关重要。
连接建立后的第一件事是发送 session.update 事件。
alloy 或 shimmer 等清晰音色)。server_vad 模式,让模型决定用户何时说完,但也需允许车端强制发送“截断信号”。Realtime API 完全由事件驱动。Relay Server 需维护一个事件泵。
input_audio_buffer.append: 持续发送音频块(Base64 PCM)。input_audio_buffer.commit: 强制提交(当车端 VAD 判定说话结束时)。conversation.item.create: 注入非语音消息(如:系统提示“前方路况拥堵”或 RAG 检索到的文本)。response.audio.delta: 音频流片段(需即时转发给车端播放)。response.audio_transcript.done: 文本实录(用于在屏幕显示字幕)。response.function_call_arguments.done: 工具调用请求。场景:车辆驶入隧道,网络中断 5 秒。 策略:
response.cancel 重置状态,避免播放过时的回复。车载环境最大的痛点是噪声和回声。Realtime API 的“全双工”特性要求极高的音频处理量。
如果车机播放 AI 的声音被麦克风录入并传回 OpenAI,模型会听到自己说话,导致死循环或“鬼畜”。
input_audio_buffer 发回给 OpenAI。用户在 AI 说话时插嘴,AI 必须立即停止。
流程设计:
input_audio_buffer.clear 事件给 Relay。response.cancel 事件。ASCII 流程图:打断
Time | User (Car) | Relay Server | OpenAI
-----+-------------------------+-----------------------+----------------
t0 | [Listening] | | [Generates Audio A...]
t1 | <Plays Audio A part 1> | <Fwd Audio A part 2> |
t2 | "Hey wait!" (Talks) | |
t3 | [Stop Playback!] | -> input_audio.append |
t4 | -> VAD Triggered | -> response.cancel | [Stop Generation]
t5 | -> input_audio.append | -> input_audio.commit | [Process New Audio]
Realtime API 支持图像输入。车载场景下,摄像头(DMS/OMS)和屏幕内容是关键上下文。
不要发送视频流!带宽和 Token 消耗都扛不住。
使用 conversation.item.create 消息,类型为 message,内容包含 type: "image_url" (Base64)。
图像预处理 Rule-of-Thumb:
当 Realtime 模型决定调用工具(如 set_seat_heater)时,音频流会发生什么?
function_call。function_call_output 发回模型。工具执行的结果(JSON)需要转化为自然语言反馈。
function_call_output item 提交,然后触发 response.create,模型会自动将 JSON 结果总结为语音回复。| 陷阱类型 | 描述 | 解决方案 |
|---|---|---|
| 自激啸叫 (Audio Loop) | 模型听到了自己刚才说的话,误以为是用户在重复,导致无限复读。 | 严格检查 AEC 效果;在客户端实现“AI 说话时麦克风静音”作为保底(但这会牺牲打断体验,仅作降级)。 |
| VAD 过于敏感 | 风噪、胎噪被误认为是人声,导致模型频繁被打断或胡言乱语。 | 调高 VAD 阈值;在车端做本地预处理(RNNoise);在 System Prompt 强调“忽略背景噪音”。 |
| 工死锁 | 模型调用工具后,Relay 迟迟不返回 Output,导致会话卡死。 | 设置工具执行超时(如 3s);超时后自动返回 “Status: Timeout” 给模型,让模型以此回复用户。 |
| Token 爆炸 | 长期会话积累了大量历史音频和文本,导致延迟增加、费用飙升。 | 实现 Context Window 滚动机制;每隔 N 轮对话,将旧的历史项从 session 中剔除或总结。 |
本章构建了车舱语音助手的“实时传输层”。核心要点包括: