openWakeWord 无法唤醒、没有反应?按这个顺序排查召回率
模型一直没有反应,不一定是模型训练失败。麦克风采集、重采样、帧切分、特征提取、触发阈值,以及合成训练语音与真人声音之间的差异,都可能造成漏唤醒。正确做法是先定位管线,再决定是否重新训练。
最先做的事情:输出原始预测分数,不要只看“是否触发”。分数完全不变化,优先检查音频和模型加载;正确发音时分数会上升但达不到阈值,再检查阈值和训练覆盖。
1. 先用 WAV 文件确认模型确实加载
先不要接实时麦克风,找一段明确包含目标词的 16 kHz WAV,通过 predict_clip() 测试,并打印模型标签和分数。相对路径错误、加载了旧模型、ONNX 与 TFLite 文件混用,表现都会像“召回率为零”。
from openwakeword.model import Model
model = Model(wakeword_models=["my_wakeword.onnx"])
print(model.predict_clip("positive_test.wav"))
2. 核对音频格式
openWakeWord 使用 16-bit、16 kHz PCM 音频,官方建议按照 80 ms 的整数倍提供帧。双声道、浮点数据被当成整数、选错静音通道、重采样异常或者字节序错误,都会让分数起不来。
- 把运行时实际输入保存成 5 秒 WAV,亲自听一遍。
- 打印采样率、通道数、数据类型、帧长度、最大最小振幅。
- 排查期间暂时关闭系统自动增益、降噪和回声消除。
- 确认声音既没有削波,也不是接近全静音。
3. 记录分数分布,再调整阈值
官方预训练模型通常从 0.5 阈值开始,但 openWakeWord 也明确建议根据使用环境调节。至少记录 20 次正确发音的峰值,并同时录制几分钟普通对话作为负样本。降低阈值能减少漏唤醒,也会增加误唤醒,不能只看一边。
| 现象 | 优先检查 |
|---|---|
| 任何声音分数都接近零 | 模型路径、数据类型、采样率和特征流程 |
| 目标词峰值略低于阈值 | 用负样本验证更低阈值 |
| WAV 能识别,麦克风不能 | 采集、重采样、缓冲与帧边界 |
| 只有训练者能唤醒 | 真人说话人和口音覆盖 |
| 近距离正常,远距离失效 | 噪声、混响、麦克风增益和远场数据 |
4. 暂时关闭 VAD、冷却和连续帧判断
模型可能已经给出高分,但被 VAD 门控、冷却时间、防抖或“连续多帧达到阈值”的逻辑拦截。诊断时逐层关闭,并同时记录模型分数、VAD 分数、阈值结果和冷却状态,再一层层恢复。
5. 用真实设备建立独立测试集
纯净 TTS 主要覆盖标准发音和有限音色。应当用最终设备录制一组不参与训练的测试数据,覆盖不同说话人、语速、距离、房间和噪声。不要使用训练录音同时做测试,否则得到的召回率没有代表性。
6. 训练数据如何改善
- 使用多个 TTS 说话人,并变化语速、音高和音量。
- 加入接近真实场景的背景音、混响和远场模拟。
- 把相似发音、常见误触发词作为困难负样本。
- 特定用户或口音经常漏检时,加入切分正确的真人录音。
- 同时评价召回率和误触发率,不能只追求阈值越低越好。
听词如何减少召回波动
听词不会把某个测试数字当成所有设备上的保证。训练流程针对目标词生成多种合成语音,加入噪声、速度等变化,并提供真人录音增强版本,用选定的真实录音补充合成语音分布。这样做的目标是缩小“干净合成音”和“真实用户、真实麦克风”之间的差异。模型导出为 ONNX/TFLite 后,仍应在目标设备上验证并设置阈值。
怎么选择:如果问题来自音频或阈值,修复后可以继续使用 openWakeWord;如果困难在于长期维护语音生成、增强和验证流程,可以选择生成独立模型,再使用开源推理代码离线部署。
生成并测试离线模型