更新记录

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 息屏作业时用固定关键词唤起扫码、打印、盘点等操作
  • 陪伴类、教育类应用用关键词触发剧情分支或语音播报
  • 会议、录播场景的关键词打点(如说「开始记录」开始录音)

使用流程

  1. 宿主 App 的 manifest.json 中 app-plus -> distribute -> android -> minSdkVersion 必须 ≥ 24(推理引擎要求,低于 24 云打包会报 uses-sdk:minSdkVersion 23 cannot be smaller than version 24 declared in library [onnxruntime])
  2. 宿主申请录音权限 android.permission.RECORD_AUDIO(示例见 pages/onnx-wakeword/onnx-wakeword.vue 的 plus.android.requestPermissions)
  3. 调用 init({ modelDir }) 加载 model_info.json、梅尔频谱模型与各唤醒词模型
  4. 调用 start({ threshold, l5Enabled, jumpRatio, onDetect, onError }) 开始采集与推理
  5. 命中时在 onDetect 中拿到唤醒词与置信度,执行业务逻辑
  6. 页面卸载或退出前调用 stop({}) 停止监听,再调用 release({}) 释放模型
  7. 运行中如需调整灵敏度,调用 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 训练框架均可。

在线生成: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:模型文件名,相对于 modelDir
  • models[].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 唤醒,息屏后仍可识别

隐私、权限声明

1. 本插件需要申请的系统权限列表:

android.permission.RECORD_AUDIO android.permission.MODIFY_AUDIO_SETTINGS android.permission.WAKE_LOCK

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

麦克风音频仅在设备本地完成推理,不上传、不录音存盘;模型文件随插件内置,无需联网下载

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。