- 人工智能
- 大模型
- AI 应用
- AI Agent
- 语音
- 智能硬件
- 固件
【免费下载链接】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 | shkeywords.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实际执行的脚本,读懂它有助于排错。其执行流程如下:
- 磁盘空间检查:要求至少 32MB 可用空间。优先使用
/data分区,若不足则回退到/tmp,两者都不满足时直接报错退出(见 init.sh#L16-L37)。 - 下载模型与二进制:若
$WORK_DIR/models/encoder.onnx不存在,则从制品仓库下载kws.tar.gz(包含kws推理二进制与models/下的encoder.onnx、decoder.onnx、joiner.onnx、tokens.txt),解压后赋予执行权限(见 init.sh#L47-L54)。 - 写入默认唤醒词:若
/data/open-xiaoai/kws/keywords.txt不存在,自动写入「你好小智 / 豆包豆包 / 天猫精灵 / 小度小度」四个默认唤醒词(见 init.sh#L63-L69)。因此快速开始中如果先创建了自定义keywords.txt,脚本不会覆盖它。 - 启动 monitor 守护进程:除非传入
--no-monitor参数,否则下载并后台启动monitor二进制,它负责播放欢迎语和派发唤醒事件(见 init.sh#L71-L80),其实现细节见下文“唤醒事件的底层链路”。 - 启动 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):
- 中文拆拼音:借助
pypinyin将每个汉字转为拼音,再用to_initials/to_finals_tone拆成「声母 + 带声调韵母」两个 token。例如“天”→t+iān,“猫”→m+āo,与仓库中现成的 keywords.txt 输出一致; - 词表校验:每个 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)。
事件流如下:
- 文件轮询:底层
FileMonitor每 10ms 轮询一次文件长度,发现新行就触发NewLine事件;若文件被重建(长度变小)则触发NewFile事件(见 file.rs#L70-L100); - 事件解析:
KwsMonitor按时间戳@关键词格式拆行,用AtomicU64记录上次时间戳做去重,防止同一唤醒事件被重复处理;关键词为__STARTED__时映射为Started事件,其余映射为Keyword事件(见 kws.rs#L50-L64); - 响应动作:
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
🔊 让小爱音箱「听见你的声音」,解锁无限可能。
相关推荐
PaddleSpeech 关键词识别(KWS)实战:基于 MDTC 的"Hey Snips"唤醒词检测
PaddleSpeech 关键词识别(KWS)实战:基于 MDTC 的"Hey Snips"唤醒词检测 关键词识别(Keyword Spotting,KWS)用
人工智能语音音频xiaozhi-esp32唤醒词:自定义唤醒词训练与部署
xiaozhi esp32唤醒词:自定义唤醒词训练与部署 痛点:千篇一律的唤醒词无法满足个性化需求 你是否厌倦了每次都要用"你好小智"来唤醒你的AI助手?想要为
人工智能AI 应用语音智能硬件物联网open-xiaoai 接入 Gemini Live API 实战:让小爱音箱实现自动 VAD 连续语音对话
open xiaoai 接入 Gemini Live API 实战:让小爱音箱实现自动 VAD 连续语音对话 本文基于 open xiaoai 仓库中 exam
人工智能大模型AI 应用AI Agent语音智能硬件固件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考