语音助手"像不像人",常常不取决于声音多自然,而取决于它何时开始、何时停下。通俗地说,VAD像门口的感应灯:检测到你开口就点亮,沉默一段时间才熄灭。学会它,你就能理解语音Agent为什么会抢话、吞字,以及用户打断时为何必须同时停止生成和清空播放队列。
最新事件与真实问题
Google在9月15日正式发布Gemini 3.8 Live和Extended Thinking,面向低延迟音频对音频应用,支持异步工具调用和会话中的增量内容更新。官方Live API文档建议把麦克风音频切成20至100毫秒的小块发送,并说明用户插话时,服务器会取消正在生成的内容。
来源:Google发布公告、Live API能力文档、最佳实践。最新事件是模型发布;VAD和实时打断则是长期通用概念。
这个概念解决什么问题
VAD是Voice Activity Detection,即语音活动检测。它回答的不是"用户说了什么",而是"当前音频里是否有人声、这一轮是否开始或结束"。如果开始判断太迟,开头几个字会被截掉;结束判断太快,句中短暂停顿会被误认为说完;判断太慢,助手又会让人等。
生活类比可以把它想成对讲机的自动按键:听见人声就占用通道,持续安静才交还通道。类比的边界是,真实VAD面对噪声、多人说话和回声时不是简单开关,而会结合能量、频谱或神经网络概率,并设置起始阈值、结束阈值和静音等待。
准确地说,实时语音客户端持续发送音频帧;VAD从连续帧估计说话状态,产生activityStart和activityEnd等事件;会话控制器据此提交一轮输入、取消旧输出或启动新响应。Barge-in是用户在模型说话时插话,中文可理解为"抢话式打断"。
一轮对话其实有三条同时流动的数据:麦克风上传的原始音频、服务器下发的模型音频、本地扬声器尚未播放的缓冲。用户一开口,服务器可能已经取消后续生成,但客户端队列里仍存着几百毫秒旧声音;若不清空,助手就会表现成"明明听见了还要说完"。因此打断是分布式状态一致性问题,不是一个静音按钮。
最小实践
下面不用麦克风和API,只用分贝序列模拟VAD与打断,便于看清状态。无需安装依赖,保存为vad_demo.py后运行python vad_demo.py。
python
frames_db = [-50, -22, -18, -46, -47, -49]
threshold_db = -35
silence_needed = 2
speaking = False
silent_frames = 0
model_speaking = True
playback_queue = ["旧回答片段1", "旧回答片段2"]
for index, level in enumerate(frames_db):
voice = level > threshold_db
if voice and not speaking:
speaking = True
silent_frames = 0
print(index, "ACTIVITY_START")
if model_speaking:
model_speaking = False
playback_queue.clear()
print(index, "INTERRUPT_AND_CLEAR_PLAYBACK")
elif voice:
silent_frames = 0
elif speaking:
silent_frames += 1
if silent_frames >= silence_needed:
speaking = False
print(index, "ACTIVITY_END")
print("queued_chunks =", len(playback_queue))
本次任务已在Python 3中实际运行,输出依次出现索引1的ACTIVITY_START与INTERRUPT_AND_CLEAR_PLAYBACK、索引4的ACTIVITY_END,最后队列长度为0。关键有三段:阈值把帧分成人声与静音;连续静音计数避免一句话中间停顿就结束;插话时同时标记模型停止并清空尚未播放的旧音频。生产环境应换成真正VAD,并处理回声消除。
真实接入还要处理采样率与连接生命周期。官方建议把常见的44.1kHz或48kHz麦克风输入重采样到16kHz,再发送小块音频。持续WebSocket连接可能被服务器轮换,因此客户端要保存会话恢复令牌、处理即将断开的通知,并给重复发送的工具结果设置幂等标识。否则一次网络抖动就可能让助手忘记上下文或重复执行动作。
三个常见误区
第一,VAD不是语音识别,它不知道内容。第二,服务器停止生成不等于扬声器立即停止;客户端若不清播放缓冲,用户仍会听到旧回答。第三,阈值越敏感不一定越好,键盘声、电视声会造成误触发。第四,音频块越大虽然请求更少,却会增加察觉插话的延迟。
还有一个容易忽略的误区:把"端到端语音模型"理解为不需要客户端工程。模型可以减少语音识别、语言模型和语音合成之间的级联等待,但采集、降噪、回声消除、播放、重连与权限提示仍然属于应用责任。浏览器和手机对麦克风切后台的行为也不同。
适用与不适用
VAD与打断适合客服、陪练、车载和会议助手等自然轮流说话的场景。录音转写、法律取证或必须保留完整原声的流程,不应因检测结果丢弃音频;多人会议还需要说话人分离。弱网下也要设计重连、会话恢复和去重,不能只优化模型延迟。
长会话还会不断累积音频Token。官方文档建议启用上下文窗口压缩,以滑动窗口保留近期信息;但压缩会丢掉部分早期细节。预约、金额、地址等关键事实应写入结构化业务状态,而不是期待模型永远记住整段声音。
我的判断与练习
我的判断是:实时语音的核心指标应是"可被自然打断的时间",而非只看首个音频包多快。一个200毫秒开口却要两秒才停下的助手,仍然令人挫败。
5分钟实践题:把silence_needed分别改为1和3,再加入一帧-20的键盘噪声,观察轮次如何变化;然后写下你愿意接受的误打断与等待时间。你更能接受语音助手偶尔抢话,还是偶尔多等半秒?
关注「蜗牛聊AI」,一起看懂技术变化背后的真正机会。
本文首发于 java4u.cn,转载请注明出处。