熙瑾会悟 ASR 实战:静音场景为什么会出现“幻觉识别”?从 VAD 到解码策略,系统解决语音识别误报问题
一、先说一个实际遇到的问题:明明没人说话,ASR 却“说了一大段”
做熙瑾会悟的 ASR 能力时,有一个问题一开始其实挺容易被忽略:
录音没有人说话,模型却识别出了文字。
例如会议开始前,设备已经开始录音,但现场还没有人讲话。
原始音频可能是:
00:00 - 00:08 静音
00:08 - 00:15 空调声
00:15 - 00:20 轻微键盘声
00:20 - 00:25 静音
正常情况下,这几秒应该直接被过滤掉。
但实际测试的时候,ASR 可能返回类似:
“今天我们主要讨论一下项目的整体情况……” 甚至有时候还能连续生成好几句话。
第一次遇到这个现象,很多人的第一反应可能是:
“是不是 ASR 模型识别能力不行?”
实际上不完全是。
这个问题通常不是简单的“模型准确率低”,而是一个由音频输入、VAD、模型解码机制、上下文信息以及后处理策略共同造成的问题。
尤其是基于 Attention/Encoder-Decoder 架构的语音识别模型,在面对低质量、低能量甚至接近纯静音的音频时,有可能根据训练过程中学到的语言模式“猜”出一段看起来合理的文本。
所以这里出现了一个很有意思的现象:
模型不是听到了这句话,而是在没有足够语音信息的时候,生成了一句“它认为可能存在的话”。
这也是我们在会议 ASR 场景里重点处理的问题之一。
二、所谓“幻觉识别”到底是什么?
这里先把概念说清楚。
ASR 中所谓的“幻觉识别”,并不是模型真的产生了类似大语言模型那种完整意义上的幻觉,而是工程上经常用来描述:
输入音频缺少有效语音信息,但 ASR 模型仍然输出了具有语言结构的文本。
例如:
真实音频:
——————————————
静音
——————————————
ASR输出: “感谢大家今天参加本次会议。” 或者:
真实音频: 空调声 + 鼠标声 + 轻微背景噪声 ASR输出: “下面我们开始讨论第二个问题……” 对于普通语音 Demo 来说,这个问题可能不明显。
但对于会议产品影响非常大。
因为会议系统后面还有一层:

一旦 ASR 在静音阶段生成了一段“假文字”,后面的 LLM 可能还会一本正经地把它总结进去。
最终就会变成:
录音里没人说话,但是会议纪要里出现了不存在的内容。
这就不是一个简单的识别误差了。
三、问题排查:到底是谁把“静音”变成了文字?
我们把整个 ASR 链路拆开以后,可以发现问题一般出现在几个地方。

真正需要重点关注的是:

如果只盯着 ASR 模型本身,很容易陷入一个误区:
“换个更大的模型是不是就好了?”
实际上不一定。
很多时候,让模型少吃一点无效音频,比单纯换一个更大的模型更有效。
四、第一个问题:VAD 没有把静音过滤干净
VAD,也就是:
Voice Activity Detection,语音活动检测。
它主要负责判断:
这一段音频到底有没有人在讲话?
这是解决静音幻觉最直接的一道防线。
假设原始音频是:
0s ───────────────────────── 60s
讲话 静音 讲话
████ ---- ████
VAD 之后:
[05s - 18s] [39s - 55s] ASR 实际收到的就不是完整的 60 秒,而是两段有效语音。
这样可以直接减少:
静音输入
背景噪声输入
空白音频
无效推理
幻觉文本
五、VAD 为什么还会误判?
问题又来了。
VAD 也不是万能的。
会议环境里经常出现:
键盘声 鼠标声 敲桌子 翻纸 空调 椅子移动 远处说话 手机震动 有些声音的能量并不低。
如果只使用简单的音量阈值:
if RMS > threshold: 有人说话 很容易把噪声当成人声。
所以在实际工程里,VAD 最好不要只依赖一个指标。
可以组合:
最终形成一个更加稳定的语音活动判断。
六、第二个问题:不能只依赖 VAD,ASR 前面还需要一道“静音门”
这是实际工程中比较值得做的一层。
即使 VAD 判断“可能存在语音”,也可以在真正送进 ASR 前再做一次检查。
例如计算:
RMS(Root Mean Square)能量。
简单来说,就是判断当前音频整体能量水平。
伪代码可以理解成:
energy = calculate_rms(audio)
if energy < silence_threshold:
return empty_result
当然,生产环境不能简单写死一个阈值。
因为不同设备:
会议室麦克风 笔记本麦克风 USB麦克风 录音笔 手机 底噪完全不一样。
所以更合理的做法是:
动态估计噪声底,再判断当前音频是否明显高于噪声水平。
例如:
两者之间需要建立一个合理的判定区间。
七、第三个问题:ASR 模型本身为什么会“编”出文字?
这个问题就涉及 ASR 模型内部机制了。
以 Encoder-Decoder 类模型为例:

当输入语音足够清晰时:

能够共同帮助模型生成正确文本。
但如果输入的是:
静音 或者:
极低能量噪声 那么有效声学信息非常少。
这时候 Decoder 仍然可能根据已经生成的 token 和训练过程中学到的语言概率继续往下生成。
简单理解就是:

所以会出现:

这种看起来非常离谱,但模型概率上又可能说得通的结果。
八、Whisper 类模型为什么尤其需要关注这个问题?
在实际工程中,Whisper 是一个很常见的选择。
它的优点非常明显:
多语言能力较强
模型生态成熟
工程资料丰富
对复杂音频有一定鲁棒性
社区使用广泛
但在实际应用中,静音、噪声、重复音频、异常片段等场景仍然需要额外处理。
因此不能简单地:
result = whisper.transcribe(audio)
然后把所有输出直接当成最终结果。
更合理的思路是建立:
Whisper + VAD + no_speech判断 + log probability + compression ratio + 后处理 多层过滤机制。
九、Whisper 场景下可以关注哪些指标?
如果使用 Whisper 或类似模型,可以重点观察模型提供的相关评分信息。
例如:
1. no_speech probability
可以理解为:
模型认为这一段没有说话的概率。
如果:
no_speech_prob 很高 那么可以考虑直接丢弃该 Segment。
当然,不能简单理解为:
no_speech_prob > 0.5 就一定删除。
具体阈值还是应该根据自己的会议数据进行测试。
2. Average Log Probability
如果生成文本时平均 log probability 很低,说明模型对当前结果其实没有那么有把握。
可以把它作为一个过滤指标。
例如:

共同判断。
3. Compression Ratio
这个指标在检测异常重复文本时也有一定参考价值。
比如输入异常音频后出现:
“大家好大家好大家好大家好大家好……” 或者:
“谢谢谢谢谢谢谢谢……” 这种明显异常的重复结果,就可以进一步过滤。
十、第四个问题:音频切得太长,也容易放大幻觉
假设一个会议录音:
00:00 ───────────────── 10:00
中间可能只有:
讲话 → 静音 → 讲话 → 静音 → 噪声 → 讲话
如果直接把 10 分钟音频交给模型:
10分钟音频 ↓ ASR
模型需要在大量无效音频中寻找语音。
这时候风险自然会上升。
所以更合理的处理方式是:

例如:
Segment 01:00:02 - 00:18
Segment 02:00:24 - 00:43
Segment 03:01:05 - 01:31
十一、Segment 不能切得太碎
但是这里又存在另一个坑。
如果切得过碎:
“今天我们主要讨论项目进度” 可能变成:
“今天我们” “主要讨论” “项目进度” 上下文被切断后,识别准确率反而会下降。
所以实际项目里需要做一个折中:
最小语音长度 + 最大Segment长度 + 静音间隔 + 前后上下文 共同决定切分策略。
这也是为什么 VAD 参数不能照着网上的一组数字直接抄。
会议、访谈、电话、直播、课堂,参数都可能不一样。
十二、第五个问题:会议环境的“静音”其实不一定是真静音
这一点非常重要。
实际录音里面很少存在真正意义上的:
绝对 0 声音 更多的是:
低频空调声 + 麦克风底噪 + 电流声 + 远处人声 + 桌面振动 所以:
静音检测实际上是在做“语音与非语音”的分类。
这也是为什么音频预处理很重要。
十三、音频预处理可以做什么?
比较常见的处理包括:
1. 重采样
统一采样率。
例如:
48kHz ↓ 16kHz 具体采样率根据模型要求决定。
2. 单声道转换
如果业务模型主要使用 Mono:
Stereo ↓ Mono
3. 音量归一化
避免不同设备录音音量差异太大。
4. 降噪
可以使用:
- RNNoise
- WebRTC Audio Processing
- DeepFilterNet
- 企业自己的降噪模块
但降噪也不能过度。
如果把人声高频部分一起削掉,ASR 反而可能更差。
十四、第六个问题:不要把“静音过滤”全部交给模型
这是整个问题排查过程中比较重要的一点。
如果架构变成:

其实已经晚了一步。
更好的方式是:

也就是说:
前面过滤一次,模型结果出来以后再过滤一次。
形成双保险。
十五、第七个问题:ASR 输出之后还需要做“幻觉文本过滤”
这是我们实际工程里比较值得增加的一层。
假设 ASR 输出:
“谢谢大家的观看。” 但原始音频:
静音 6 秒 这时候即使 ASR 自己认为这句话概率不错,我们仍然可以通过上下文判断:
音频能量 ≈ 0 VAD = 无语音 文本 = 非空 最终:
文本 → 丢弃
十六、可以设计一个简单的多指标判定策略
例如:
VoiceScore =
α × VADScore
+ β × EnergyScore
+ γ × ASRConfidence
+ δ × NoSpeechScore
不一定非要真的采用这个公式,但这个思路比较重要。
不要:
只看一个指标。
而是把多个信号综合起来。
例如:
|
条件 |
判断 |
|
VAD 无语音 |
高概率丢弃 |
|
音频能量极低 |
倾向丢弃 |
|
no_speech_prob 高 |
倾向丢弃 |
|
ASR 置信度低 |
倾向丢弃 |
|
出现大量重复文本 |
丢弃 |
|
Segment 极短 |
根据业务判断 |
|
多项指标同时异常 |
直接丢弃 |
十七、Paraformer 场景应该怎么处理?
如果使用 Paraformer 等非自回归 ASR 模型,处理思路有所不同。
Paraformer 的特点之一就是推理效率较好,在中文语音识别、实时场景中比较适合。
但模型快并不意味着:
静音就一定不会识别出文本。
因此同样建议:

如果部署的是 FunASR 相关模型组合,也可以结合:

形成完整处理链。
十八、SenseVoice 场景也建议采用前后双层过滤
SenseVoice 这类模型除了语音识别,还可以用于语音相关任务。
但在企业会议场景里,不管使用什么模型,都不建议把:
模型输出 直接等同于:
最终文本 统一增加:

会更加稳妥。
十九、一个比较实用的 ASR 防幻觉架构
最终我们可以把这套方案整理成下面这样:
这个架构的关键就在于:
ASR 不是唯一的判断者。
二十、异常结果可以考虑“重新识别”
还有一个比较实用的方法。
如果第一轮识别结果异常:
VAD正常 但是 ASR置信度很低 不要马上把结果返回给用户。
可以尝试:

比如第一次:
0s - 15s
第二次改成:
2s - 13s
或者:
增加上下文 再识别一次。
这种方式虽然增加一点计算量,但对于离线会议转写非常实用。
二十一、对于实时 ASR,还要处理“尾部静音”
实时会议里经常有这种情况:
用户: “我们先讨论一下这个问题……” 然后停了两秒。
ASR 需要判断:
是不是一句话结束了?
如果 Endpointing 做得不好,就可能把:
讲话 + 2秒静音 + 后面的噪声 一起送进模型。
所以实时 ASR 中通常需要处理:

这里的静音时长是非常重要的参数。
太短:
用户一句话还没说完就被截断。
太长:
用户说完了,文字迟迟不出来。
因此实时会议需要在:
准确率和延迟之间做平衡。
二十二、为什么“规则过滤”不能做得太狠?
看到这里,有人可能会想:
“既然静音容易产生幻觉,那我把所有短文本都过滤掉。”
这个方法看起来简单,但很容易误伤。
比如:
“好。” “可以。” “对。” “嗯。” 这些都是非常短的语句。
如果简单按照:
文本长度 < 3 直接删除,那么正常会议内容也会丢失。
所以过滤规则最好结合:

综合判断。
二十三、还可以建立一个“幻觉文本黑名单”
在真实业务中,如果长期积累数据,会发现一些固定模式。
例如某些模型在无语音情况下容易生成:
“谢谢大家。” “感谢观看。” “请大家关注。” “字幕由……” 这些文本在特定会议场景下本身就比较可疑。
可以建立:
hallucination_patterns:
- "感谢大家"
- "谢谢观看"
- "欢迎订阅"
- "请关注"
但这里必须强调:
黑名单只能作为辅助规则,不能作为主要解决方案。
否则换一个业务场景,很容易误删真实内容。
二十四、如何验证优化到底有没有效果?
不能凭感觉。
建议建立一套专门的“静音测试集”。
例如:
然后比较优化前后:
|
指标 |
优化前 |
优化后 |
|
静音误识别率 |
较高 |
明显下降 |
|
正常语音召回率 |
基准 |
保持稳定 |
|
幻觉文本数量 |
较多 |
减少 |
|
平均推理量 |
较高 |
降低 |
|
无效 ASR 请求 |
较多 |
减少 |
真正需要关注的是:
不能为了降低幻觉,把正常语音一起过滤掉。
所以测试的时候至少要同时看:
误报率 + 漏报率。
二十五、最终落地的一套解决方案
结合熙瑾会悟会议场景,这个问题最后可以归纳成五层。
第一层:音频层
重采样 降噪 音量归一化 声道处理
第二层:VAD 层
VAD模型 + 动态能量阈值 + 最小语音时长 + 静音持续时间
第三层:ASR 层
Paraformer SenseVoice Whisper 根据场景选择。
第四层:模型结果层
no_speech probability 平均log probability 文本重复度 置信度 Segment长度 进行二次判断。
第五层:业务层
术语纠错 文本规范化 上下文判断 异常文本过滤 会议纪要校验 这样才能真正形成完整的防幻觉体系。
二十六、实际项目中我比较推荐的处理链路
如果让我重新设计这部分,我会采用:
这里有一个核心原则:
不要试图让 ASR 模型一个人解决所有问题。
让:
VAD 负责判断有没有声音,ASR 负责判断说了什么,声纹负责判断是谁说的,后处理负责把文字整理干净,大模型负责理解会议内容。
每一层负责自己的事情,整个系统反而更加稳定。
二十七、这次问题给 ASR 部署带来的一个经验
以前做 ASR,很容易把注意力放在:
模型准确率 但是实际进入生产以后,会发现:
异常输入处理能力,同样重要。
真实世界不是一个干净的数据集。
用户会:
- 录到空白
- 录到噪声
- 录到远处说话
- 录到设备碰撞
- 录到会议暂停
- 录到突然关麦
- 录到很长的静音
这些都属于正常情况。
如果系统没有设计异常输入处理机制,那么再好的模型也可能出现奇怪结果。
所以一个真正稳定的企业级 ASR 系统,应该具备:
正常语音 → 正常识别
静音 → 不输出
噪声 → 尽量过滤
弱语音 → 谨慎判断
异常结果 → 二次校验
低置信度 → 重识别
长时间静音 → 自动结束Segment
这次熙瑾会悟 ASR 的“静音幻觉识别”问题,看起来只是一个小 Bug,但实际往下追,会发现它涉及整个语音识别链路。
真正解决它,并不是简单地换一个模型。
更有效的方式是把问题拆开:

前面负责减少无效输入,中间负责提高识别质量,后面负责拦截异常结果。
对于熙瑾会悟这种企业级会议系统来说,这套思路尤其重要。
因为会议录音不像实验室数据,环境永远是变化的。有人说话的时候要准确识别,没人说话的时候也要**“保持安静”**。
从这个角度看,ASR 的准确率不应该只理解成:
“说话的时候识别得有多准。”
还应该包括:
“没说话的时候,系统能不能忍住不乱说。”
这其实也是企业级语音识别系统和简单 Demo 之间非常明显的区别。
更多推荐


所有评论(0)