端侧唤醒词检测实战:给语音助手装上离线守门员
目录
为什么语音助手需要一个守门员
智能音箱、车载助手、会议耳机——只要涉及语音交互,第一个问题都是:怎么知道用户开始说话了?
最笨的方案是全时跑 ASR。但上一篇里那个 24MB 的 int8 识别模型,全时转写依然会吃掉可观的 CPU 和电量。更聪明的做法是三级接力:
- 唤醒词(KWS):常驻运行,只监听几个关键词,功耗极低
- VAD(语音活动检测):唤醒后检测人声边界,截断有效音频
- ASR + TTS:完整识别与回复,唤醒后才启动
唤醒词就是这条流水线的第一道门。本文用 sherpa-onnx 的开源词表 KWS 完整跑一遍,10 分钟给应用装上离线唤醒能力,和之前写的 ASR、TTS 文章正好组成闭环。
开源词表 KWS 是什么
传统唤醒词方案(如固定训练的 Hey Siri)要针对每个词准备大量音频重新训练。sherpa-onnx 的 open vocabulary KWS 换了个思路:模型本质是一个微型 ASR(Zipformer,仅 3.3M 参数),解码时只允许输出你指定的关键词——换唤醒词不用重新训练,改一行文本即可。
每个关键词带两个旋钮(官方文档定义):
- boosting score(如
:2.0):beam search 中给包含该词的路径加分,越大越容易触发 - trigger threshold(如
#0.6):解码序列的最低声学概率,取值 0-1,越小越容易触发
| 方案 | 特点 | 适用场景 |
|---|---|---|
| sherpa-onnx KWS (k2-fsa) | 开源词表,免训练换词,Python/C++/iOS/Android 全 API | 生产级端侧语音助手,本文主角 |
| openWakeWord (dscripka) | PyTorch 训练自己的专属唤醒词 | 需要完全自定义、可解释的唤醒词 |
| Porcupine(Picovoice) | 精度高、多语言,闭源 SDK | 商用快速集成,注意授权费用 |
三分钟跑通中文唤醒
安装并下载官方中文模型(wenetspeech 训练,3.3M 参数,int8 版本仅数 MB):
|
|
编写关键词文件(: 后是 boosting score,# 后是触发阈值,注意两者与数值之间不能有空格):
|
|
用官方测试音频验证(模型目录自带 test_wavs):
|
|
Python 集成:流式监听
|
|
调参实战:误唤醒与漏唤醒
- 触发阈值:
#0.25起步。误唤醒多就往上调,漏唤醒多就往下调,用带噪音的回归音频反复测 - boosting score:唤醒词和日常对话里相似发音冲突时(如「小爱同学」vs「小爱通知」),适当降低 score 减少抢词
- 先跑官方 demo 再换词:模型自带
keywords.txt和测试音频,先用默认词验证环境,再逐步换成自己的词
端到端闭环
唤醒命中后,接 VAD 截断人声,送进 sherpa-onnx ASR 识别,再用 Piper TTS 回复,一条完全离线的语音链路就通了。三个模型加起来不到 50MB,普通手机 CPU 即可实时运行,全程音频不出设备。
踩坑记录
- token 类型选错:中文模型必须用
cjkchar,英文模型用bpe,混用会解码出乱码 - 音频格式:输入必须是 16kHz 单声道,麦克风采集时记得先重采样
- 关键词文件格式:
:和#与数值之间不能有空格,否则解析失败;中文关键词建议加@原文,便于日志排查