更新记录

1.0.0(2026-10-03)

百度语音唤醒


平台兼容性

uni-app(5.26)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
√ √ × × √ √ 10.0 13 16
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × × × ×

uni-app x(5.26)

Chrome Safari Android iOS 鸿蒙 微信小程序
× × 10.0 13 16 ×

其他

多语言 暗黑模式 宽屏模式 蒸汽模式
× × × √

yao-baidu-speech

百度云语音技术 SDK UTS 插件,提供在线语音识别(ASR)与语音唤醒(Wakeup)能力。

平台 语音识别 语音唤醒 备注
Android ✅ ✅ bdasr_V3 经典方案
iOS ✅ ✅ ASR_iOS_v3.0.13 经典 BDSEventManager 方案
HarmonyOS ✅ ❌(SDK 未开放) 需 HarmonyOS 5.0.4(API 16)及以上

三端 API 与回调事件格式完全一致,页面代码无需按平台做任何区分。

准备工作

  1. 前往 百度智能云控制台 创建语音技术应用,获取 appId / apiKey / secretKey 三件套。
  2. 唤醒功能要求应用的包名与百度控制台登记的包名一致(首次联网自动下载唤醒授权)。
  3. 麦克风权限由插件内部自动申请,无需页面处理。

快速开始

不想手写界面?直接复制文末 完整示例页面 到 pages/index/index.vue 即可跑起来。

1. 导入插件

import * as baiduSpeech from '@/uni_modules/yao-baidu-speech'

2. 初始化(只需一次)

baiduSpeech.initSpeech('你的appId', '你的apiKey', '你的secretKey')

3. 语音识别

// 开始识别
baiduSpeech.startAsr({ longSpeech: true }, (event) => {
  switch (event.name) {
    case 'asr.partial': // 中间/最终结果(用 result_type 区分)
      if (event.result_type === 'final_result') {
        console.log('最终结果: ' + event.result)
      } else {
        console.log('中间结果: ' + event.result)
      }
      break
    case 'asr.finish': // 识别结束
      if (event.error !== 0) {
        console.log('识别出错: ' + event.error + ' ' + event.desc)
      }
      break
    case 'asr.volume':
      // 音量事件(event.volume / event.volume_percent),高频回调
      break
  }
})

// 停止录音,等待剩余识别结果(长语音模式下点此才出最终结果)
baiduSpeech.stopAsr()

// 取消本次识别
baiduSpeech.cancelAsr()

// 释放识别状态
baiduSpeech.releaseAsr()

startAsr options 参数:

键 类型 说明
longSpeech boolean true 时走长语音模式:录音不会因静音自动关闭,点 stopAsr 才出最终结果。默认 false(单句短语音,静音自动断句结束)
其余键值对 any 原样透传给百度 SDK 原生参数(Android 见 SpeechConstant,iOS 见 BDSASRParameters.h)

4. 语音唤醒

// 开始唤醒。不传 kwsFile 时使用默认唤醒词文件("小度你好/百度一下")
baiduSpeech.startWakeup({}, (event) => {
  switch (event.name) {
    case 'wp.ready':
      console.log('唤醒引擎就绪')
      break
    case 'wp.data': // 唤醒成功
      if (event.error_code === 0) {
        console.log('唤醒成功: ' + event.word)
      }
      break
    case 'wp.error':
      console.log('唤醒出错: ' + event.error_code + ' ' + event.desc)
      break
  }
})

// 停止唤醒
baiduSpeech.stopWakeup()

// 释放唤醒引擎
baiduSpeech.releaseWakeup()

startWakeup options 参数:

键 类型 说明
kwsFile string 自定义唤醒词文件路径,支持 assets:///MyWake.bin、绝对路径、file:// 等(iOS 端常用 plus.io.convertLocalFileSystemURL('/static/WakeUp.bin'))。不传时使用默认唤醒词文件。自定义唤醒词请到百度智能云控制台导出 bin 文件
kwsDatFile string 仅 iOS:唤醒引擎模型 bds_easr_basic_model.dat 路径。不传时插件自动从主 bundle / www/static 探测(该 dat 文件需放在项目 static/ 目录)
其余键值对 any 原样透传给百度 SDK 原生参数

鸿蒙端暂不支持语音唤醒,调用 startWakeup 会回调 wp.error(百度鸿蒙 SDK 未开放唤醒能力)。

自定义唤醒词前,可先到百度官方唤醒词评估页面在线体验并评估唤醒词效果(支持在线创建/测试唤醒词),确认效果后再到百度智能云控制台导出对应 bin 文件使用。

回调事件

回调事件对象(UTSJSONObject)公共字段:

字段 类型 说明
name string 事件名,见下表
result string 识别文本(results[0] 快捷方式)
results string[] 识别文本数组
result_type string partial_result / final_result
error number 错误码(asr.finish 中 0 表示正常结束)
sub_error number 子错误码
desc string 错误/描述信息
sn string 识别请求唯一标识(排查日志时提供给百度)
volume / volume_percent number 音量(asr.volume)
data_length number 音频块字节数(asr.audio)
word string 命中的唤醒词(wp.data)
error_code number 唤醒错误码(0 成功)
raw string SDK 原始数据,排查问题时查看

识别事件:

事件名 说明
asr.ready 引擎就绪,可以开始说话
asr.begin 检测到用户开始说话
asr.partial 中间/最终识别结果(result_type 区分;最终结果的文本是累计全量)
asr.end 检测到用户停止说话(VAD 断句,长语音模式下录音继续)
asr.finish 识别结束(error 为 0 正常,非 0 出错)
asr.volume 录音音量
asr.audio 原始音频块
asr.error 识别错误
asr.cancel 识别被取消
asr.exit 识别退出

唤醒事件:wp.ready(引擎就绪)/ wp.data(唤醒成功)/ wp.error(唤醒出错)/ wp.exit(唤醒停止)。

插件层错误统一以 plugin.error 事件回调(如未初始化就调用、平台不支持等),看 desc 字段。

平台差异说明

事项 Android iOS HarmonyOS
默认唤醒词文件 插件内置 assets:///WakeUp.bin 自动从 www/static / 主 bundle 探测 —
唤醒模型 dat so 内置,无需关心 需放项目 static/(插件自动探测) —
麦克风权限 插件自动申请 插件自动申请(info.plist 已配置描述) 插件自动申请
系统要求 minSdkVersion 23,建议 targetSdkVersion ≥ 33(避免 Android 15"旧版应用"弹窗) iOS 12+ HarmonyOS 5.0.4(API 16)+

完整示例页面

以下为完整可运行的测试页(初始化 + 语音识别 + 语音唤醒 + 日志面板),直接复制到 pages/index/index.vue 即可使用(默认模板已注册该页面)。填写自己的三件套后先点 initSpeech,再点「开始识别」/「开始唤醒」。

<template>
    <view class="content">
        <view class="card">
            <text class="title">百度语音识别 + 唤醒测试</text>
            <view class="row">
                <input class="ipt" v-model="appId" placeholder="appId" />
            </view>
            <view class="row">
                <input class="ipt" v-model="apiKey" placeholder="apiKey" />
            </view>
            <view class="row">
                <input class="ipt" v-model="secretKey" placeholder="secretKey" />
            </view>
            <button type="primary" size="mini" @click="onInit">initSpeech</button>
        </view>

        <view class="card">
            <text class="title">语音识别 ASR</text>
            <view class="btns">
                <button type="primary" size="mini" @click="onStartAsr">开始识别</button>
                <button type="warn" size="mini" @click="onStopAsr">停止</button>
                <button size="mini" @click="onCancelAsr">取消</button>
                <button size="mini" @click="onReleaseAsr">释放</button>
            </view>
            <text class="result">{{ asrText || '识别结果' }}</text>
        </view>

        <view class="card">
            <text class="title">语音唤醒 Wakeup</text>
            <view class="row">
                <input class="ipt" v-model="kwsFile" placeholder="唤醒词文件路径(留空用默认WakeUp.bin)" />
            </view>
            <view class="btns">
                <button type="primary" size="mini" @click="onStartWakeup">开始唤醒</button>
                <button type="warn" size="mini" @click="onStopWakeup">停止</button>
                <button size="mini" @click="onReleaseWakeup">释放</button>
            </view>
            <text class="result">{{ wakeupText || '唤醒状态' }}</text>
        </view>

        <scroll-view class="log" scroll-y>
            <text class="logline">{{ logText }}</text>
        </scroll-view>
    </view>
</template>

<script>
    import * as baiduSpeech from '@/uni_modules/yao-baidu-speech'

    export default {
        data() {
            return {
                appId: '',
                apiKey: '',
                secretKey: '',
                // #ifdef APP-PLUS
                kwsFile: plus.io.convertLocalFileSystemURL("/static/WakeUp.bin"),
                // #endif
                // #ifndef APP-PLUS
                kwsFile: '',
                // #endif
                asrText: '',
                wakeupText: '',
                logText: ''
            }
        },
        methods: {
            appendLog(msg) {
                const time = new Date().toLocaleTimeString()
                this.logText = `[${time}] ${msg}\n` + this.logText
            },
            onInit() {
                if (!this.appId || !this.apiKey || !this.secretKey) {
                    uni.showToast({ title: '请填写三件套', icon: 'none' })
                    return
                }
                baiduSpeech.initSpeech(this.appId, this.apiKey, this.secretKey)
                this.appendLog('initSpeech 完成')
            },
            onStartAsr() {
                this.asrText = ''
                // longSpeech: 长语音模式,录音不会因静音自动关闭,点"停止"才出最终结果
                baiduSpeech.startAsr({ longSpeech: true }, (event) => {
                    this.handleAsrEvent(event)
                })
                this.appendLog('startAsr 已调用')
            },
            handleAsrEvent(event) {
                const name = event.name
                if (name === 'asr.partial') {
                    const rt = event.result_type
                    if (rt === 'final_result') {
                        this.asrText = event.result
                        this.appendLog('最终结果: ' + event.result)
                    } else if (rt === 'partial_result') {
                        this.asrText = event.result + '...'
                    }
                } else if (name === 'asr.finish') {
                    if (event.error && event.error !== 0) {
                        this.appendLog(`识别出错: error=${event.error} sub=${event.sub_error} ${event.desc} sn=${event.sn}`)
                    } else {
                        if (event.result) {
                            this.asrText = event.result
                        }
                        this.appendLog('识别结束' + (event.result ? ': ' + event.result : ''))
                    }
                } else if (name === 'asr.volume') {
                    // 音量事件刷屏,不打日志
                } else if (name === 'plugin.error') {
                    this.appendLog('插件错误: ' + event.desc)
                } else {
                    this.appendLog('asr event: ' + name)
                }
            },
            onStopAsr() {
                baiduSpeech.stopAsr()
                this.appendLog('stopAsr 已调用')
            },
            onCancelAsr() {
                baiduSpeech.cancelAsr()
                this.appendLog('cancelAsr 已调用')
            },
            onReleaseAsr() {
                baiduSpeech.releaseAsr()
                this.appendLog('releaseAsr 已调用')
            },
            onStartWakeup() {
                this.wakeupText = '等待唤醒...'
                // 唤醒词文件留空用默认 WakeUp.bin;
                // iOS 端唤醒模型 bds_easr_basic_model.dat 由插件自动从 static/ 探测,无需页面传
                let opts = {}
                const kws = (this.kwsFile || '').trim()
                if (kws) {
                    opts.kwsFile = kws
                    this.appendLog('使用自定义唤醒词文件: ' + kws)
                }
                baiduSpeech.startWakeup(opts, (event) => {
                    this.handleWakeupEvent(event)
                })
                this.appendLog('startWakeup 已调用')
            },
            handleWakeupEvent(event) {
                const name = event.name
                if (name === 'wp.data') {
                    if (event.error_code && event.error_code !== 0) {
                        this.appendLog(`唤醒出错: ${event.error_code} ${event.desc}`)
                    } else {
                        this.wakeupText = '唤醒成功: ' + event.word
                        this.appendLog('唤醒成功: ' + event.word)
                    }
                } else if (name === 'wp.error') {
                    this.appendLog(`唤醒error: ${event.error_code} ${event.desc}`)
                } else if (name === 'wp.ready') {
                    this.wakeupText = '唤醒引擎就绪'
                    this.appendLog('wp.ready 唤醒引擎就绪')
                } else if (name === 'wp.exit') {
                    this.appendLog('wp.exit 唤醒停止')
                } else if (name === 'plugin.error') {
                    this.appendLog('插件错误: ' + event.desc)
                } else {
                    this.appendLog('wakeup event: ' + name)
                }
            },
            onStopWakeup() {
                baiduSpeech.stopWakeup()
                this.appendLog('stopWakeup 已调用')
            },
            onReleaseWakeup() {
                baiduSpeech.releaseWakeup()
                this.appendLog('releaseWakeup 已调用')
            }
        }
    }
</script>

<style>
    .content {
        padding: 20rpx;
    }

    .card {
        background-color: #fff;
        border-radius: 12rpx;
        padding: 20rpx;
        margin-bottom: 20rpx;
    }

    .title {
        font-size: 32rpx;
        font-weight: bold;
        margin-bottom: 16rpx;
        display: block;
    }

    .row {
        margin-bottom: 12rpx;
    }

    .ipt {
        border: 1px solid #e0e0e0;
        border-radius: 8rpx;
        padding: 12rpx;
        font-size: 26rpx;
    }

    .btns {
        display: flex;
        gap: 12rpx;
        flex-wrap: wrap;
        margin-bottom: 12rpx;
    }

    .result {
        font-size: 30rpx;
        color: #007aff;
        min-height: 44rpx;
        display: block;
    }

    .log {
        background-color: #1e1e1e;
        border-radius: 12rpx;
        height: 500rpx;
        padding: 16rpx;
        width: 100%;
        box-sizing: border-box;
    }

    .logline {
        color: #d4d4d4;
        font-size: 22rpx;
        white-space: pre-wrap;
    }
</style>

隐私、权限声明

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

需要麦克风权限

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

插件不采集任何数据

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

无

暂无用户评论。