☰
Open-XiaoAI 小爱音箱自定义唤醒词实战:基于 sherpa-onnx 的 KWS 配置、调优与开机自启
2026/10/14 16:42:43 网站建设 项目流程
  • 人工智能
  • 大模型
  • AI 应用
  • AI Agent
  • 语音
  • 智能硬件
  • 固件

【免费下载链接】open-xiaoai

🔊 让小爱音箱「听见你的声音」,解锁无限可能。

项目地址:https://gitcode.com/gh_mirrors/op/open-xiaoai
点击查看免费下载

本文基于 open-xiaoai 仓库中的 examples/kws/README.md 展开,讲解如何在小爱音箱端(Client 端)部署 sherpa-onnx 关键词唤醒服务(KWS),实现自定义唤醒词与自定义欢迎语。读完后你可以独立完成唤醒词拼音 token 的生成、keywords.txt/reply.txt配置、init.sh/boot.sh启动与开机自启,并借助debug.sh调试脚本按 ASR 输出校准唤醒词拼音,同时理解唤醒事件从模型输出到语音提示、再到ubus唤醒通知的完整链路。

方案概述与适用前提

该演示方案的核心思路是:由于小爱音箱端算力与存储有限,选择把 sherpa-onnx 的一个小型 zipformer2 关键词识别模型(约 5MB)直接跑在音箱 Client 端,本地完成唤醒词检测;配合一个monitor常驻进程,负责播放自定义欢迎语并向系统派发唤醒事件。

先明确适用前提,避免踩坑:

  • 适用机型:仅适用于小爱音箱 Pro(LX06)和 Xiaomi 智能音箱 Pro(OH2P)两款机型,其他型号的小爱音箱请勿直接使用。这一点与 刷机教程 的适用范围一致;
  • 内存限制:只有带 DTS 功能的旧款小爱音箱 Pro(256MB 内存)和新款 OH2P 经过测试可正常运行。部分不带 DTS 的新版 Pro 只有 128MB 内存,无法加载模型(详见后文“启动失败显示 Killed”一节);
  • 前置条件:需要先将小爱音箱刷入补丁固件,然后 SSH 连接到小爱音箱,完整步骤见 小爱音箱 Pro 刷机教程。刷机成功后补丁固件默认开启 SSH,默认密码为open-xiaoai:
ssh -o HostKeyAlgorithms=+ssh-rsa root@你的小爱音箱局域网IP地址 # 比如:ssh -o HostKeyAlgorithms=+ssh-rsa root@192.168.31.227

另外需要说明:根据仓库根目录 README.md 的声明,open-xiaoai 项目目前已停止维护,不再提供更新与支持,本文以仓库当前代码为准。

快速开始:三分钟部署唤醒词服务

SSH 登录后,按以下步骤操作(完整命令可直接复制执行):

# 创建 open-xiaoai/kws 文件夹 mkdir -p /data/open-xiaoai/kws # 设置自定义唤醒词 cat <<EOF > /data/open-xiaoai/kws/keywords.txt t iān m āo j īng l íng @天猫精灵 x iǎo d ù x iǎo d ù @小度小度 d òu b āo d òu b āo @豆包豆包 n ǐ h ǎo x iǎo zh ì @你好小智 EOF # 设置唤醒提示语(可选) cat <<EOF > /data/open-xiaoai/kws/reply.txt 主人你好,请问有什么吩咐? EOF # 运行启动脚本 init.sh curl -sSfL https://gitee.com/idootop/artifacts/releases/download/open-xiaoai-kws/init.sh | sh

keywords.txt每一行的格式是「拼音 token 序列 +@+ 原始唤醒词」:t iān对应“天”,m āo对应“猫”,以此类推;@之后的中文用于唤醒成功后的日志展示与事件上报。@之前的拼音 token 不是随意写的,必须与模型词表 tokens.txt 严格对应,生成方法见下文“设置唤醒词”一节。

如果想让服务在音箱开机后自动运行,执行以下命令将boot.sh下载为/data/init.sh(开机自启动入口),然后重启即可:

# 下载 boot.sh 到 /data/init.sh 开机时自启动 curl -L -o /data/init.sh https://gitee.com/idootop/artifacts/releases/download/open-xiaoai-kws/boot.sh # 重启小爱音箱 reboot

启动脚本内部机制:init.sh 与 boot.sh 源码解读

仓库中的 examples/kws/init.sh 就是上面curl | sh实际执行的脚本,读懂它有助于排错。其执行流程如下:

  1. 磁盘空间检查:要求至少 32MB 可用空间。优先使用/data分区,若不足则回退到/tmp,两者都不满足时直接报错退出(见 init.sh#L16-L37)。
  2. 下载模型与二进制:若$WORK_DIR/models/encoder.onnx不存在,则从制品仓库下载kws.tar.gz(包含kws推理二进制与models/下的encoder.onnx、decoder.onnx、joiner.onnx、tokens.txt),解压后赋予执行权限(见 init.sh#L47-L54)。
  3. 写入默认唤醒词:若/data/open-xiaoai/kws/keywords.txt不存在,自动写入「你好小智 / 豆包豆包 / 天猫精灵 / 小度小度」四个默认唤醒词(见 init.sh#L63-L69)。因此快速开始中如果先创建了自定义keywords.txt,脚本不会覆盖它。
  4. 启动 monitor 守护进程:除非传入--no-monitor参数,否则下载并后台启动monitor二进制,它负责播放欢迎语和派发唤醒事件(见 init.sh#L71-L80),其实现细节见下文“唤醒事件的底层链路”。
  5. 启动 KWS 推理主进程:核心启动命令如下(见 init.sh#L86-L96):
"$KWS_BIN" \ --model-type=zipformer2 \ --tokens="$WORK_DIR/models/tokens.txt" \ --encoder="$WORK_DIR/models/encoder.onnx" \ --decoder="$WORK_DIR/models/decoder.onnx" \ --joiner="$WORK_DIR/models/joiner.onnx" \ --keywords-file="/data/open-xiaoai/kws/keywords.txt" \ --provider=cpu \ --num-threads=1 \ --chunk-size=1024 \ noop

各参数含义:--model-type=zipformer2指定 sherpa-onnx 的 zipformer2 关键词识别模型结构;--encoder/--decoder/--joiner是 Transformer 编码器、解码器与 joiner 三件套 ONNX 文件;--keywords-file指向设备上的唤醒词配置(注意这里固定指向/data/open-xiaoai/kws/keywords.txt,即使模型因空间不足被放到了/tmp);--provider=cpu --num-threads=1表明纯 CPU 单线程推理,这是受音箱算力限制的取舍;--chunk-size=1024控制音频分块大小;最后的noop为 sherpa-onnx 程序要求的占位模式参数。

examples/kws/boot.sh 与init.sh基本一致,额外做了两处“开机场景”适配:开头exec > /dev/null 2>&1静默所有输出;并在启动前循环ping baidu.com等待网络可用(见 boot.sh#L16-L22),保证断网重启时模型下载不会被跳过。

部署完成后,音箱上的典型目录结构为:

/data/open-xiaoai/kws/ ├── kws # 唤醒词推理二进制(CPU 端) ├── monitor # 欢迎语播放 + 唤醒事件派发进程 ├── models/ │ ├── encoder.onnx │ ├── decoder.onnx │ ├── joiner.onnx │ └── tokens.txt # 模型词表(拼音 token → 词元 id) ├── keywords.txt # 唤醒词配置(拼音 token + @原始词) └── reply.txt # 唤醒提示语(可选)

设置唤醒词:从中文到拼音 token

keywords.txt里的拼音 token 需要与模型词表精确匹配,手工编写容易出错。仓库提供了 examples/kws/keywords.py 脚本自动完成转换。注意:仅支持中文唤醒词,支持多个唤醒词,每行一个。

操作方式:在电脑上克隆本项目,修改 examples/kws/my-keywords.txt(默认内容为“天猫精灵 / 小度小度 / 豆包豆包 / 你好小智”,每行一个中文唤醒词),然后运行:

# 你可能需要先安装 uv uv run keywords.py --tokens tokens.txt --output keywords.txt --text my-keywords.txt

脚本会生成keywords.txt,把它复制到小爱音箱的/data/open-xiaoai/kws/keywords.txt即可。如果你不方便复制文件,也可以直接在小爱音箱上运行以下命令(记得修改成自己的唤醒词):

cat <<EOF > /data/open-xiaoai/kws/keywords.txt t iān m āo j īng l íng @天猫精灵 x iǎo d ù x iǎo d ù @小度小度 d òu b āo d òu b āo @豆包豆包 n ǐ h ǎo x iǎo zh ì @你好小智 EOF

修改完毕后,记得重启脚本或小爱音箱使新配置生效。

keywords.py 的转换原理

从源码结构看,转换分两步(见 keywords.py#L76-L125):

  1. 中文拆拼音:借助pypinyin将每个汉字转为拼音,再用to_initials/to_finals_tone拆成「声母 + 带声调韵母」两个 token。例如“天”→t+iān,“猫”→m+āo,与仓库中现成的 keywords.txt 输出一致;
  2. 词表校验:每个 token 都必须在 tokens.txt(共 227 个词元,如zh 10、ān 28、iǔ 33)中存在。任何拼音 token 查不到(OOV)时,脚本打印告警并整行跳过该唤醒词——这意味着若某个字的多音字拼音或特殊读音不在词表内,该唤醒词会静默失效,这是“时好时坏”的一个潜在原因,可用下文debug.sh排查。

keywords.py还支持在每个唤醒词后附加元信息(见 keywords.py#L31-L42 的参数说明,转换时会原样保留到输出):

后缀含义示例
:分数boosting score,提高该词触发权重小爱同学 :2.0
#阈值触发阈值(仅关键词识别任务生效)小艺小艺 #0.6
@原文原始短语,用于展示你好小智 @你好小智

例如输入你好小智 :2.5 #0.5 @你好小智,输出即为n ǐ h ǎo x iǎo zh ì :2.5 #0.5 @你好小智。

设置欢迎语:reply.txt 配置与播放逻辑

唤醒成功后音箱会播放提示语。你可以新建reply.txt自定义提示语,内容格式如下:

主人你好,请问有什么吩咐? https://example.com/music.wav file:///usr/share/sound-vendor/AiNiRobot/wakeup_ei_01.wav

配置规则:

  • 每行一句欢迎语;
  • 支持文字(TTS 合成)和音频链接(http(s)://或file://);
  • 多条欢迎语会随机选择一句播放;
  • 默认欢迎语与小爱同学一致:“哎”、“在”。

同样有两种部署方式:把电脑上的reply.txt复制到/data/open-xiaoai/kws/reply.txt,或直接在音箱上执行:

cat <<EOF > /data/open-xiaoai/kws/reply.txt 主人你好,请问有什么吩咐? https://example.com/music.wav file:///usr/share/sound-vendor/AiNiRobot/wakeup_ei_01.wav EOF

修改完毕后,记得重启脚本或小爱音箱使新配置生效。

播放逻辑的源码佐证

提示语的播放由monitor进程实现,仓库内的 Rust 源码 packages/client-rust/src/bin/monitor.rs 可以印证上述行为(见 monitor.rs#L17-L48):

  • 若reply.txt存在且非空,则完全替换默认提示音(默认的wakeup_ei_01.wav/wakeup_zai_01.wav即“哎/在”两个 wav 文件),与“默认欢迎语与小爱同学一致”的说明吻合;
  • 通过pick_one从候选列表随机取一条,与“多条欢迎语随机选择”一致;
  • 内容包含://(即音频链接)时用miplayer -f '<url>'播放文件/远程音频,否则走系统自带的/usr/sbin/tts_play.sh做文字转语音。

唤醒事件的底层链路:从 kws.log 到 ubus 唤醒通知

从源码结构看,kws推理进程与monitor进程之间通过日志文件解耦:KWS 服务把识别结果写入/tmp/open-xiaoai/kws.log,monitor侧由KwsMonitor监听该文件(路径常量定义见 kws.rs#L11)。

事件流如下:

  1. 文件轮询:底层FileMonitor每 10ms 轮询一次文件长度,发现新行就触发NewLine事件;若文件被重建(长度变小)则触发NewFile事件(见 file.rs#L70-L100);
  2. 事件解析:KwsMonitor按时间戳@关键词格式拆行,用AtomicU64记录上次时间戳做去重,防止同一唤醒事件被重复处理;关键词为__STARTED__时映射为Started事件,其余映射为Keyword事件(见 kws.rs#L50-L64);
  3. 响应动作:
    • Started:通过tts_play.sh播报“自定义唤醒词已开启”(欢迎语可通过 monitor 的第一个命令行参数覆盖);
    • Keyword:按上文规则播放欢迎语,随后执行ubus call pnshelper event_notify '{"src":1,"event":0}'向系统派发唤醒事件(见 monitor.rs#L47),从而唤醒音箱进入对话状态。

这条链路也解释了为什么“自定义唤醒词触发后能否关灯、打电话”默认做不到——monitor的响应动作是固定的(提示音 + 唤醒事件),要挂接任意动作需要像仓库中其他演示(如 examples/xiaozhi)那样在 Server 端接收唤醒词事件后再做业务处理。

常见问题

Q:为什么唤醒词识别不是很灵敏,时好时坏?

由于小爱音箱 client 端算力和存储空间有限,默认只使用了一个较小的语音识别模型,所以识别效果并不是很完美,需要多多尝试。

你可以在小爱音箱上运行以下调试脚本,根据语音识别结果,动态调整唤醒词拼音:

# 运行调试脚本 curl -sSfL https://gitee.com/idootop/artifacts/releases/download/open-xiaoai-kws/debug.sh | sh # 🐢 模型加载较慢,请在提示 Started! Please speak 后,再使用自定义唤醒词 # Started! Please speak # 0:tiānmāojīnglián 👈 天猫精灵 # 1:xiǎodùxiǎodù 👈 小度小度 # 2:dōubāodùba 👈 豆包豆包 # 3:nǐhǎoxiǎozhī 👈 你好小智

debug.sh 会下载并运行kws-debug二进制,使用与init.sh完全相同的模型参数(--model-type=zipformer2、CPU、单线程等,见 debug.sh#L66-L75),但不加载keywords-file,而是实时打印原始识别假设。对照假设与目标唤醒词的拼音差异(例如“天猫精灵”被识别为tiānmāojīnglián),回到keywords.py或手动修正keywords.txt中的拼音 token 即可改善命中率。

如果你想要更完美的唤醒词识别效果,可以在 server 端运行更大规模、更先进的 AI 模型来做唤醒词识别,推荐使用 FunASR 和 Sherpa-ONNX,可以参考 xiaozhi-esp32-server 项目。

Q:能不能设置英文/方言作为唤醒词?比如:Siri

默认使用的小型语音识别模型只支持中文(普通话)作为唤醒词。

如果你想要使用英文唤醒词(比如 siri),或者更灵敏的唤醒词识别效果,可以参考仓库内的 xiaozhi Server 端演示,其 Server 端同样基于 sherpa-onnx 的 KeywordSpotter(参数示例见 sherpa.py#L9-L21),配置中同时包含中文词与hi siri等英文词;其词表文件 keywords.txt 中也能看到英文词对应的 BPE token(如▁HI ▁S I RI)。

如果你需要更多语言的唤醒词,比如日语、韩语或方言等,可以在 server 端运行更大规模、更先进的 AI 模型来进行唤醒词识别,推荐使用 FunASR 和 Sherpa-ONNX,可以参考 xiaozhi-esp32-server 项目。

Q:是否支持说话人(声纹)识别?

由于小爱音箱 client 端算力和存储空间有限,默认只使用了一个较小的语音识别模型,并不支持说话人识别等高阶功能。

如果你需要声纹识别、连续对话等高阶功能,可以在 server 端运行更大规模、更先进的 AI 模型来进行语音识别和对话管理,推荐使用 FunASR 和 Sherpa-ONNX,可以参考 xiaozhi-esp32-server 项目。

Q:能否自定义唤醒词的响应动作?比如:关灯

该脚本默认不支持自定义唤醒词触发后执行的动作(默认行为即上文分析的“播放欢迎语 + 派发唤醒事件”)。

如果你想要自定义唤醒词的触发动作,可以参考 open-xiaoai 里的其他演示程序,根据 server 端接收到的小爱音箱上的唤醒词事件,实时触发任意自定义操作(比如打电话、订外卖等)。

Q:我不是小爱音箱 Pro 能不能用?

由于小爱音箱 client 端算力和存储空间有限,默认只使用了一个较小的语音识别模型(5MB 左右),需要占用大约 20MB 的存储空间。其他型号的小爱音箱存储空间和算力可能不足以运行该模型,请自行测试。

你也可以参考 open-xiaoai 里的演示程序,在 server 端运行更大规模、更先进的 AI 模型来进行唤醒词识别,达到相同目的。推荐使用 FunASR 和 Sherpa-ONNX,可以参考 xiaozhi-esp32-server 项目。

Q:我是小爱音箱 Pro(LX06)为什么启动失败显示 Killed?

目前只在新款小米智能音箱 Pro(OH2P)和旧款带 DTS 功能的小爱音箱 Pro(256 MB 内存)上测试可以正常运行。

有些新版的小爱音箱 Pro(不带 DTS 版本)内存仅为 128MB,无法提供充足的内存来加载模型文件,故无法在 Client 端运行该 KWS 服务,进程会被系统直接Killed。建议参考 xiaozhi 演示,在 Server 端运行 KWS 服务。

小结

本方案的工程取舍很清晰:用 5MB 级 zipformer2 小模型换取纯 Client 端、无需 Server 依赖的唤醒能力,用日志文件 + 轮询的monitor进程把“识别”和“响应”解耦,从而在 128~256MB 内存的音箱硬件上稳定运行。需要重点记住的三个配置入口是:keywords.txt(用 keywords.py 生成,拼音 token 必须匹配 tokens.txt)、reply.txt(文字或音频、多条随机播放)、/data/init.sh(开机自启开关)。当识别灵敏度或语言覆盖不满足需求时,正确的升级路径是把 KWS 移到 Server 端(如 xiaozhi 演示),而不是继续压缩 Client 端模型。

  • 人工智能
  • 大模型
  • AI 应用
  • AI Agent
  • 语音
  • 智能硬件
  • 固件

【免费下载链接】open-xiaoai

🔊 让小爱音箱「听见你的声音」,解锁无限可能。

项目地址:https://gitcode.com/gh_mirrors/op/open-xiaoai
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询