实时语音的打断:barge-in 怎么做对
约五分之一的语音通话里,用户会在 AI 还没说完时开口插话。 这个数字来自 PolyAI 对生产环境通话的统计,我自己看线上日志,感受也差不多。更值得注意的是后半句:会打断的用户,往往是意图最强的那批人。 他们听够了想直接说事,或者发现 AI 理解错了要赶紧纠正。换句话说,打断处理得烂的那一小撮通话,直接决定了你整个产品体验的天花板——因为最在乎、最着急的用户,恰好都撞在这里。 所以"能被打断"不是锦上添花的功能。它和延迟一样,是语音 Agent 的及格线。但和延迟不同,打断的难点不在毫秒,在于它是一个并发控制问题:一个事件要同时掐断好几条正在跑的流,还不能掐错。 为什么打断比想象中难 很多人第一次做打断,以为就是"检测到用户说话,调一下 audioPlayer.stop()"。上线一周就会发现到处是坑。 难在三个地方。 第一,打断是个分布式的取消操作。用户开口的那一刻,你的系统里可能同时有:扬声器在播第 3 句的音频、TTS 服务还在合成第 5 句、LLM 还在流式生成第 8 句的 token。这三样东西跑在不同进程甚至不同机器上。你要在几十毫秒内把它们一起叫停,任何一个漏网,AI 就会出现"我已经打断它了,它怎么还在自说自话"的灵异现象。 第二,判断"这算不算打断"本身就难。背景里有人说话、电视开着、用户自己"嗯"“对啊"地随口附和——这些都会让一个朴素的 VAD 兴奋地触发打断。误打断比"打断慢了"更伤体验:AI 说到一半被一声咳嗽打断,僵在那里,用户一脸问号。 第三,打断之后,对话状态是脏的。AI 那句话只说了一半就被掐了,LLM 的上下文里到底该记成"我说了整句"还是"我只说了半句”?记错了,下一轮 AI 要么重复已经说过的内容,要么基于"它以为自己说了但其实没说出口"的信息往下接。 这三件事,后面一件件拆。 怎么知道用户在打断 打断检测的第一关,是 VAD(语音活动检测)。它干一件很窄的事:判断这一小段音频里有没有人声。现代 VAD(比如 Silero)能在几十毫秒内给出"有声/无声"的概率,这一层基本算解决了。 但 VAD 只够回答"有没有声音",回答不了"这声音算不算一次真正的打断"。2026 年成熟的做法,是在 VAD 上面叠一层判断,通常叫语义化的轮次检测。 这里要分清两个相关但不同的问题: 端点检测(turn detection):用户这一轮说完了没?——决定 AI 什么时候开口。 打断检测(barge-in):AI 正在说话时,用户这声插话,要不要让 AI 闭嘴?——决定 AI 什么时候停下。 它们共用 VAD 这个底座,但上层逻辑不一样。打断检测要额外回答的问题是:这声音是"我要说话了你停下",还是"嗯哼,我在听"。 主流框架的处理方式,可以摆在一起看: 方案 核心信号 特点 朴素 VAD 音频能量 / 人声概率 最快,但把附和、噪音全当打断 转写流启发式 VAD + ASR 部分转写文本 看用户说出的字是不是"有内容" 模型化打断判定 专门小模型读音频+文本 区分真打断 / 附和 / 噪音,准但有计算开销 LiveKit 在 2026 年走的是模型路线:它的自适应打断(adaptive interruption)用真实对话音频训练了一个小模型,AI 说话期间检测到人声,不会无脑停,而是让模型先判断"这次该不该让出话权"。Pipecat 的 Smart Turn、Deepgram 的 Flux、VideoSDK 开源的 Namo,思路都类似——从"听到声音就停"升级到"听懂这是不是打断再停"。 ...