更新记录
1.0.0(2026-11-03)
- 首个版本:Android 端离线唤醒词识别(ONNX 模型端侧推理,不联网)
- 支持 dscnn / nww / tcn / multi 四种模型类型与多唤醒词同时识别
- 内置示例模型:曼波、你好电脑,安装即可运行
- 五层防误触(L1 连续帧 / L2 峰值背景比 / L3 冷却 / L4 突发抑制 / L5 能量跃变)
- 接口:init / start / stop / setConfig / getStatus / release
- 支持运行期参数热更新、麦克风被占用回调、采集线程看门狗、息屏保活
平台兼容性
uni-app(4.72)
| Vue2 | Vue3 | Vue3插件版本 | Chrome | Safari | app-vue | app-vue插件版本 | app-nvue | app-nvue插件版本 | Android | Android插件版本 | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | √ | 1.0.0 | × | × | √ | 1.0.0 | √ | 1.0.0 | 7.0 | 1.0.0 | × | × |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | - | × | × | × | × | - | × | × |
uni-app x(4.72)
| Chrome | Safari | Android | Android插件版本 | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|---|
| × | × | 7.0 | 1.0.0 | × | × | × |
插件介绍
支持 uni-app 与 uni-app x 的 Android 离线唤醒词 / 关键词识别(KWS)插件,麦克风音频在设备本地完成推理,全程不联网、不上传音频。Android 端由 UTS + Kotlin 原生混编实现,推理引擎在打包时由云端仓库自动引入、示例模型随插件内置,无需手动放置 SDK 文件,最低支持 Android 7.0(minSdkVersion 24)。
使用场景
- 语音助手类 App 的免按键唤醒:用户说「曼波」直接进入对话,无需点击按钮
- 工业手持机 / PDA 息屏作业时用固定关键词唤起扫码、打印、盘点等操作
- 陪伴类、教育类应用用关键词触发剧情分支或语音播报
- 会议、录播场景的关键词打点(如说「开始记录」开始录音)
使用流程
- 宿主 App 的
manifest.json中app-plus -> distribute -> android -> minSdkVersion必须 ≥ 24(推理引擎要求,低于 24 云打包会报uses-sdk:minSdkVersion 23 cannot be smaller than version 24 declared in library [onnxruntime]) - 宿主申请录音权限
android.permission.RECORD_AUDIO(示例见pages/onnx-wakeword/onnx-wakeword.vue的plus.android.requestPermissions) - 调用
init({ modelDir })加载model_info.json、梅尔频谱模型与各唤醒词模型 - 调用
start({ threshold, l5Enabled, jumpRatio, onDetect, onError })开始采集与推理 - 命中时在
onDetect中拿到唤醒词与置信度,执行业务逻辑 - 页面卸载或退出前调用
stop({})停止监听,再调用release({})释放模型 - 运行中如需调整灵敏度,调用
setConfig({ threshold }),无需重启监听
用法
import { init, start, stop, setConfig, getStatus, release } from '@/uni_modules/zy-onnx-wakeword'
加载模型
init({
success: (res) => {
// res.wakeWords: ['曼波', '你好电脑']
console.log(res.wakeWords, res.modelCount, res.modelType)
},
fail: (err) => {
console.error(err.errCode, err.errMsg)
}
})
开始与停止监听
start({
threshold: 0.5,
l5Enabled: true,
jumpRatio: 5.0,
onDetect: (res) => {
console.log('命中', res.wakeWord, res.probability, '第', res.count, '次')
},
onError: (err) => {
console.warn('运行异常', err.errCode, err.errMsg)
},
success: () => {
console.log('已开始监听')
}
})
// 停止(保留模型,可再次 start)
stop({})
动态调参
setConfig({
threshold: 0.6,
l5Enabled: false,
jumpRatio: 3.0,
inferenceInterval: 60,
onDetect: (res) => {
console.log('新的命中回调', res.wakeWord)
}
})
读取状态
getStatus({
success: (res) => {
console.log(res.running, res.threshold, res.count, res.lastWakeWord)
}
})
释放资源
release({
success: () => {
console.log('已释放')
}
})
自定义唤醒词模型
获取 ONNX 模型
可以自己训练,也可以使用在线服务生成。
自己训练:以下工具都能导出 ONNX 唤醒词模型,任何能导出 ONNX 的 KWS 训练框架均可。
- OpenWakeWord — 开源,家居场景,支持多唤醒词
- MicroWakeWord — 专为 ESP32 等 MCU 设计
- NanoWakeWord — 11 种架构可选,模型极小(40KB)
在线生成:voicute.com 输入中文唤醒词即可自动生成 ONNX 模型,首次免费。
需要的模型文件
无论用哪个工具训练,最终需要以下文件:
| 文件 | 说明 |
|---|---|
melspectrogram.onnx |
音频 → 梅尔频谱,通用模块,插件已内置,一般无需替换 |
你的模型.onnx |
唤醒词推理模型,训练或在线生成获取 |
model_info.json |
模型配置,描述模型类型与唤醒词清单(需自行编写) |
放置模型
模型默认从插件内置的 assets 子目录 wakeword 加载。替换方式二选一:
- 直接替换
uni_modules/zy-onnx-wakeword/utssdk/app-android/assets/wakeword/下的模型文件与model_info.json - 把模型放到 App 可访问的目录(如
plus.io转换出的绝对路径),调用init({ modelDir: '/sdcard/xxx/wakeword' })
模型配置
单个唤醒词:
{
"model_type": "dscnn",
"mel_time": 98,
"multi_model": true,
"models": [
{ "wake_word": "曼波", "model_file": "manbo.onnx", "cons_frames": 2 }
]
}
多个唤醒词:
{
"model_type": "dscnn",
"mel_time": 98,
"multi_model": true,
"models": [
{ "wake_word": "打开灯光", "model_file": "dakaidengguang.onnx", "cons_frames": 2 },
{ "wake_word": "你好电脑", "model_file": "nihaodiannao.onnx", "cons_frames": 2 }
]
}
字段说明:
model_type:支持dscnn(默认,端到端 mel → sigmoid)、nww、tcn、multi四种mel_time:dscnn 单次推理使用的梅尔帧数,必须与训练时一致multi_model:是否多模型并列(多个唤醒词各一个.onnx)models[].wake_word:命中时回调返回的唤醒词文本models[].model_file:模型文件名,相对于modelDirmodels[].emb_frames:特征帧数,nww / tcn 模型必填且必须与训练时一致,dscnn 可不写models[].cons_frames:建议连续命中帧数,越大误触越低、响应越钝
mel_time / emb_frames 填错会导致完全识别不出来,请以训练输出中的 config.json 为准。
插件方法
| 方法 | 说明 | 回调 |
|---|---|---|
init(options?) |
加载模型清单与全部 ONNX 模型 | success / fail / complete |
start(options?) |
开始麦克风采集与推理 | success / fail / complete,事件 onDetect / onError |
stop(options?) |
停止采集与推理,保留已加载模型 | success / fail / complete |
setConfig(options?) |
运行中调整阈值 / L5 / 跃变倍数 / 连续帧数 / 推理间隔,可替换 onDetect、onError |
success / fail / complete |
getStatus(options?) |
读取初始化状态、监听状态、当前参数与累计命中次数 | success / fail / complete |
release(options?) |
停止监听并释放全部模型资源 | success / fail / complete |
init 参数与返回
init({
modelDir: 'wakeword', // 模型目录:assets 子目录名;以 / 开头为绝对路径;'.' 表示 assets 根目录,缺省 'wakeword'
modelInfoFile: 'model_info.json', // 模型清单文件名,缺省 'model_info.json'
melModelFile: 'melspectrogram.onnx', // 梅尔频谱模型文件名,缺省 'melspectrogram.onnx'
success: (res) => {
// res.wakeWords : string[] 已加载的唤醒词
// res.modelCount : number 唤醒词模型数量
// res.modelType : string 模型类型 'dscnn' | 'nww' | 'tcn' | 'multi'
// res.sampleRate : number 固定 16000
// res.melFramesNeeded : number 单次推理所需梅尔帧数
// res.audioSamplesNeeded : number 单次推理所需 PCM 采样点数
// res.modelDir : string 实际使用的模型目录
// res.models : object[] [{ wakeWord, modelFile, embFrames, consFrames }]
}
})
start 参数
start({
threshold: 0.5, // 命中阈值 0~1,缺省 0.5,越高越难触发
l5Enabled: true, // 是否启用 L5 能量跃变检测,缺省 true
jumpRatio: 5.0, // 能量跃变倍数 2.0~8.0,缺省 5.0,越大越严格
consFrames: 0, // 额外要求的连续命中帧数,缺省 0(与模型 cons_frames 取较大值)
inferenceInterval: 30, // 推理间隔毫秒,缺省 30(约 33fps),调大更省电
skipStartupMs: 3000, // 启动后跳过多少毫秒才允许命中,缺省 3000
rmsGate: 30 // RMS 门限,低于该能量跳过推理,缺省 30
})
onDetect 命中结果
onDetect: (res) => {
// res.wakeWord : string 命中的唤醒词
// res.probability : number 置信度 0~1(已做 softmax 归一化)
// res.background : number 背景(非唤醒词)概率 0~1
// res.rms : number 命中时音频 RMS(静音约 20,正常说话 500~2000)
// res.count : number 本次 start 以来累计命中次数
// res.timestamp : number 命中时间戳(毫秒)
}
onError 运行异常
onError: (err) => {
// err.errSubject : string 固定 'zy-onnx-wakeword'
// err.errCode : number 9260 段错误码,见下方错误码表
// err.errMsg : string 错误描述
}
getStatus / stop / setConfig 返回
success: (res) => {
// res.initialized : boolean 模型是否已加载
// res.running : boolean 是否正在监听
// res.threshold : number 当前阈值
// res.l5Enabled : boolean 是否启用 L5
// res.jumpRatio : number 当前跃变倍数
// res.consFrames : number 额外连续帧数
// res.inferenceInterval : number 推理间隔毫秒
// res.count : number 累计命中次数
// res.lastWakeWord : string 最近一次唤醒词(无则空字符串)
// res.lastProbability : number 最近一次置信度
}
错误码
| 错误码 | 说明 |
|---|---|
| 9260001 | 参数错误 |
| 9260002 | 模型未初始化,请先调用 init |
| 9260003 | 模型加载失败 |
| 9260004 | 模型文件不存在 |
| 9260005 | 缺少录音权限 |
| 9260006 | 麦克风初始化失败 |
| 9260007 | 麦克风被占用 |
| 9260008 | 已在监听中 |
| 9260009 | 当前未在监听 |
| 9260010 | 启动监听失败 |
| 9260011 | 推理失败 |
| 9260012 | 停止监听失败 |
| 9260013 | 释放资源失败 |
| 9260014 | ONNX Runtime 初始化失败 |
权限说明
| 权限 | 用途 |
|---|---|
android.permission.RECORD_AUDIO |
采集麦克风 PCM 音频用于唤醒词推理(必需) |
android.permission.MODIFY_AUDIO_SETTINGS |
启用系统降噪(NoiseSuppressor)改善识别率 |
android.permission.WAKE_LOCK |
监听期间保持 CPU 唤醒,息屏后仍可识别 |

收藏人数:
购买源码授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)
下载 66
赞赏 0
下载 12737590
赞赏 1959
赞赏
京公网安备:11010802035340号