500毫秒,这是人类对话中"自然感"的生死线。超过它,你会感觉对面是个机器人;低于它,用户几乎察觉不到延迟。谷歌Gemini 2.5 Flash Live API把语音交互压进了这个区间,但一位开发者花了500多场真实对话才发现——真正的杀手不是推理速度,是回声。
GoNoGo.team的创始人最初以为最难的是多智能体编排、40多个函数调用工具。结果上线后,AI面试代理频繁打断自己说话,像个人在空旷房间里听到回音后愣住。问题的根源:浏览器自带的回声消除(Acoustic Echo Cancellation,AEC)在新型语音架构里完全失效。
为什么传统方案会"失明"
传统语音AI走"语音→文字→语音"的拼接路线,延迟通常在1-3秒。Gemini Flash Live API是原生语音到语音(speech-to-speech),音频进、音频出,没有中间文本层。这意味着客户端处理的是原始PCM数据:16kHz麦克风输入,24kHz代理语音输出,Base64编码后走WebSocket传输。
浏览器端的AEC有个底层假设——"远端音频"必须通过``元素或Web Audio API播放,这样浏览器才能追踪参考信号。但GoNoGo的实现是手动解码WebSocket传来的24kHz PCM块,用AudioContext缓冲区调度播放。浏览器看不到这个音频流,自然无法消除它。
后果很荒诞:AI开口说话,笔记本扬声器出声,麦克风收进去,AI以为用户在打断自己。最优情况是它重复半句话;最差情况——作者说" constantly happened"——对话彻底崩掉。
500场对话磨出的野路子方案
开发者试过让AI忽略自己的声音,但语音活动检测(Voice Activity Detection,VAD)阈值调再高也拦不住物理层面的声波耦合。最终方案是在客户端建立"自引用消除":把即将播放的音频帧缓存为参考信号,与麦克风输入做实时对齐抵消。
这相当于在浏览器里重写半个AEC。对齐精度要控制在样本级别——24kHz意味着每帧约21微秒的偏差都会漏出残差。作者用512样本块(约32毫秒)处理,RMS能量检测阈值设在0.05,低于此值直接丢弃。
更麻烦的是采样率不匹配。输入16kHz,输出24kHz,重采样本身引入延迟。GoNoGo的做法是统一在客户端升到48kHz处理,再降回各自目标,把额外开销压到10毫秒以内。
被忽视的工程暗角
这个案例暴露了一个行业盲区:当语音AI从"文本中介"转向"端到端音频",大量浏览器层面的音频基础设施需要重建。AEC、噪声抑制、自动增益控制(AGC)这些曾经开箱即用的功能,在WebSocket+手动解码的架构里全部需要自研。
作者提到一个细节:测试时发现某些笔记本的扬声器-麦克风物理隔离太差,即使软件层面完美消除,机械振动仍会漏音。最终被迫在检测到AI说话时,动态压低麦克风增益——用信噪比换稳定性,这是硬件层面的妥协。
500毫秒延迟的目标达成了,但代价是团队把一半精力花在"让AI听不到自己"这种基础问题上。语音AI的竞赛正在从模型能力转向工程整合——谁能把端到端延迟、回声消除、网络抖动缓冲这些脏活累活打包好,谁才能让用户觉得"对面像个真人"。
GoNoGo现在每天处理数百场创始人面试,回声问题基本解决。但作者留下一个未回答的疑问:当多模态模型开始同时处理语音、视觉、实时环境音,现有的音频处理栈还有多少能复用?下一代开发者会不会在同样的坑里再栽一次?
热门跟贴