Skip to content

使用方法

介绍

安卓百度语音识别UTS原生插件集成了短语音识别、离线自定义命令词识别、语音唤醒,SDK内部均为采用流式协议,即用户边说边处理,插件支持uniapp和uniapp x

插件使用注意事项

  • 如果您在使用插件的过程中有任何问题,可以联系作者,作者将全力协助您使用插件
  • 本文档同时提供了uniapp的用法示例和uniappx的用法示例,插件市场导入的示例项目仅为uniapp的用法示例,如果您需要uniappx的示例项目可以通过下方的链接下载示例

https://pan.baidu.com/s/1uwjyWwSQCLSyWNiqkz8Ifg?pwd=xqji

官方文档

https://ai.baidu.com/ai-doc/SPEECH/3ltwvtg6u

联系作者

关注微信公众号可联系作者

插件地址

https://ext.dcloud.net.cn/plugin?id=29753

用法

在需要使用插件的页面加载以下代码

js
import * as module from "@/uni_modules/leven-uts-bdSpeech"
js
import * as module from "@/uni_modules/leven-uts-bdSpeech"

页面内容

uniapp

vue
<template>
  <view>
    <uni-card title="功能示例">
      <button type="primary" @click="toPage('onlineRecog')">在线识别</button>
      <button type="primary" @click="toPage('offlineRecog')">离线命令词</button>
      <button type="primary" @click="toPage('wakeup')">唤醒词</button>
      <button type="primary" @click="toPage('wakeUpRecog')">唤醒后识别</button>
    </uni-card>
  </view>
</template>

<script>
  import * as module from "@/uni_modules/leven-uts-bdSpeech"
  export default {
    data() {
      return {
        title: 'Hello'
      }
    },
    mounted() {
      this.$nextTick(() => {
        //申请插件所需权限
        this.requestPermissions();
      })
    },
    methods: {
      toPage(type) {
        switch (type) {
          case "onlineRecog":
            uni.navigateTo({
              url: "/pages/index/onlineRecog"
            })
            break
          case "offlineRecog":
            uni.navigateTo({
              url: "/pages/index/offlineRecog"
            })
            break
          case "wakeup":
            uni.navigateTo({
              url: "/pages/index/wakeup"
            })
            break
          case "wakeUpRecog":
            uni.navigateTo({
              url: "/pages/index/wakeUpRecog"
            })
            break
        }
      },
      showMessage(message) {
        uni.showToast({
          title: message,
          icon: "none"
        })
      },
      toAllFilesPermissionPage() {
        module.toAllFilesPermissionPage({
          complete: (res) => {
            if (res.code == 0) {
              let data = res.data;
              if (!data.status) {
                this.showMessage("所有文件访问权限未打开")
              } else {
                this.showMessage("权限申请完成")
              }
            } else {
              this.showMessage(res.message)
            }
          }
        })
      },
      checkAllFilesPermission() {
        module.checkAllFilesPermission({
          complete: (res) => {
            if (res.code == 0) {
              let data = res.data;
              if (!data.status) {
                this.toAllFilesPermissionPage();
              } else {
                this.showMessage("权限申请完成")
              }
            } else {
              this.showMessage(res.message)
            }
          }
        })
      },
      //申请插件所需权限
      requestPermissions() {
        module.requestPermissions({
          params: {
            permissions: [
              "android.permission.READ_EXTERNAL_STORAGE",
              "android.permission.WRITE_EXTERNAL_STORAGE",
              "android.permission.RECORD_AUDIO"
            ]
          },
          complete: (res) => {
            if (res.code == 0) {
              //判断是否有所有文件访问权限
              this.checkAllFilesPermission();
            } else {
              this.showMessage(res.message)
            }
          }
        })
      },
    }
  }
</script>

<style>
</style>
vue
<template>
  <view>
    <uni-card title="在线普通识别功能(含长语音)">
      <view>普通识别测试方法:</view>
      <view>请保持设备联网,对着麦克风说出日常用语即可。</view>
      <view>普通录音限制60s。使用长语音无此限制。</view>
    </uni-card>
    <uni-card title="设置">
      <uni-section title="PID,语种">
        <uni-data-checkbox v-model="settingParams.language" :localdata="languageItems"></uni-data-checkbox>
      </uni-section>
      <uni-section title="LMID,自训练平台ID,请选PID=8002生效">
        <uni-data-checkbox v-model="settingParams.lm_id" :localdata="lmIdItems"></uni-data-checkbox>
      </uni-section>
      <uni-section title="长语音" sub-title="长语音参数,优先级高于vad_endpoint_timeout">
        <radio-group @change="changeLongSpeech">
          <radio :value="false" style="transform:scale(0.7)" :checked="longSpeechIndex == 0"></radio>否
          <radio :value="true" style="transform:scale(0.7)" :checked="longSpeechIndex == 1"></radio>是
        </radio-group>
      </uni-section>
      <uni-section title="VAD时长设置">
        <uni-data-checkbox v-model="settingParams['vad.endpoint-timeout']"
          :localdata="vadEndpointTimeoutItems"></uni-data-checkbox>
      </uni-section>
      <uni-section title="VAD是否开启">
        <uni-data-checkbox v-model="settingParams.vad" :localdata="vadItems"></uni-data-checkbox>
      </uni-section>
      <uni-section title="外部音频">
        <uni-data-checkbox v-model="settingParams.infile" :localdata="infileItems"></uni-data-checkbox>
      </uni-section>
      <uni-section title="保存录音">
        <radio-group @change="changeSaveAudio">
          <radio :value="false" style="transform:scale(0.7)" :checked="saveAudioIndex == 0"></radio>否
          <radio :value="true" style="transform:scale(0.7)" :checked="saveAudioIndex == 1"></radio>是
        </radio-group>
      </uni-section>
      <uni-section title="开启代码中音频回调事件" sub-title="不需要音频二进制数据的回调,请勿开启,否则影响性能">
        <radio-group @change="changeAcceptAudioData">
          <radio :value="false" style="transform:scale(0.7)" :checked="acceptAudioDataIndex == 0"></radio>否
          <radio :value="true" style="transform:scale(0.7)" :checked="acceptAudioDataIndex == 1"></radio>是
        </radio-group>
      </uni-section>
      <uni-section title="禁用标点" sub-title="在选择输入法模型的前提下生效">
        <radio-group @change="changeDisablePunctuation">
          <radio :value="false" style="transform:scale(0.7)" :checked="disablePunctuationIndex == 0"></radio>否
          <radio :value="true" style="transform:scale(0.7)" :checked="disablePunctuationIndex == 1"></radio>是
        </radio-group>
      </uni-section>
      <uni-section title="提示音">
        <radio-group @change="changeTipsSound">
          <radio :value="false" style="transform:scale(0.7)" :checked="tipsSoundIndex == 0"></radio>否
          <radio :value="true" style="transform:scale(0.7)" :checked="tipsSoundIndex == 1"></radio>是
        </radio-group>
      </uni-section>
      <uni-section title="开启代码中音量回调事件" sub-title="是否需要音频的音量回调。正常使用请勿开启">
        <radio-group @change="changeAcceptAudioVolume">
          <radio :value="false" style="transform:scale(0.7)" :checked="acceptAudioVolumeIndex == 0"></radio>否
          <radio :value="true" style="transform:scale(0.7)" :checked="acceptAudioVolumeIndex == 1"></radio>是
        </radio-group>
      </uni-section>
    </uni-card>
    <button type="primary" @click="toggle">{{isStart ? "停止" : "开始"}}</button>
    <uni-card title="日志">
      <view v-for="(item, index) in logs" :key="index">{{item}}</view>
    </uni-card>
  </view>
</template>

<script>
  import * as module from "@/uni_modules/leven-uts-bdSpeech"
  import {
    SpeechConstant
  } from "@/utils/SpeechConstant.js"
  import {
    KeyUtils
  } from "@/utils/KeyUtils.js"
  export default {
    data() {
      return {
        isStart: false,
        //设置参数
        settingParams: {
          //语种
          language: "",
          //自训练平台ID
          lm_id: "",
          //长语音
          "enable.long.speech": false,
          //长语音时长设置
          "vad.endpoint-timeout": "",
          //vad是否开启
          vad: "",
          //外部音频
          infile: "",
          //开启代码中音频回调事件
          "accept-audio-data": false,
          //禁用标点
          "disable-punctuation": false,
          //开启代码中音量回调事件
          "accept-audio-volume": false
        },
        //语种列表
        languageItems: [{
          "value": "",
          "text": "默认"
        }, {
          "value": "cmn-Hans-CN",
          "text": "普通话"
        }, {
          "value": "en-GB",
          "text": "英语"
        }, {
          "value": "yue-Hans-CN",
          "text": "粤语"
        }, {
          "value": "sichuan-Hans-CN",
          "text": "四川话"
        }],
        //平台id列表
        lmIdItems: [{
          "value": "",
          "text": "默认"
        }, {
          "value": 1068,
          "text": "自训练平台上线的id,和账号维度绑定"
        }],
        //长语音默认选择
        longSpeechIndex: 0,
        //平台id列表
        vadEndpointTimeoutItems: [{
          "value": "",
          "text": "默认"
        }, {
          "value": 0,
          "text": "开启长语音(离线不支持)。建议pid选择15372"
        }, {
          "value": 800,
          "text": "800毫秒,静音800ms后断句,适用于输入短语"
        }, {
          "value": 2000,
          "text": "2000毫秒,静音2000ms后断句,适用于输入长句"
        }, {
          "value": 2230,
          "text": "2230, 毫秒,请修改代码中的VAD_ENDPOINT_TIMEOUT,自定义时长(建议800ms-3000ms之间)"
        }],
        //vad是否开启配置
        vadItems: [{
          "value": "",
          "text": "不设置"
        }, {
          "value": "dnn",
          "text": "默认,推荐模型"
        }, {
          "value": "touch",
          "text": "关闭静音断句功能。用戶手动停止录音"
        }],
        //外部音频列表
        infileItems: [{
          "value": "",
          "text": "不设置"
        }, {
          "value": "assets:///com/baidu/android/voicedemo/16k_test.pcm",
          "text": "16k采样的测试音频"
        }, {
          "value": "assets:///com/baidu/android/voicedemo/offline_input.pcm",
          "text": "测试离线命令词"
        }],
        //是否保存录音文件
        saveAudioIndex: 0,
        //录音文件保存路径,为空则默认为项目私有目录
        audioPath: "/storage/emulated/0/levenBdSpeech/1234.pcm",
        //开启代码中音频回调事件索引
        acceptAudioDataIndex: 0,
        //禁用标点索引
        disablePunctuationIndex: 0,
        //提示音
        tipsSoundIndex: 0,
        //开启代码中音量回调事件
        acceptAudioVolumeIndex: 0,
        //日志
        logs: []
      }
    },
    mounted() {
      this.$nextTick(() => {
        //初始化后注册监听
        this.initSdk();
      })
    },
    onUnload() {
      //页面卸载
      this.release();
    },
    methods: {
      toggle() {
        if (this.isStart) {
          this.stop()
        } else {
          this.start()
        }
      },
      showMessage(message) {
        uni.showToast({
          title: message,
          icon: "none"
        })
      },
      initSdk() {
        module.init({
          params: {
            appId: KeyUtils.APPID,
            apiKey: KeyUtils.APIKEY,
            secretKey: KeyUtils.SECRETKEY
          },
          complete: (res) => {
            if (res.code == 0) {
              this.addLog("初始化成功")

              //注册监听
              this.registerListener();
            } else {
              this.addLog(res.message)
            }
          }
        })
      },
      start() {
        let sendParams = this.settingParams;
        if (this.saveAudioIndex == 1) {
          // 目前必须开启此回掉才嫩保存音频
          sendParams["accept-audio-data"] = true;
          sendParams["outfile"] = this.audioPath;
        }
        if (this.tipsSoundIndex == 1) {
          //请将声音文件放到到raw下面,传递时不需要带扩展名只传入文件名即可
          sendParams['sound_start'] = "bdspeech_recognition_start";
          sendParams['sound_end'] = "bdspeech_speech_end";
          sendParams['sound_success'] = "bdspeech_recognition_success";
          sendParams['sound_error'] = "bdspeech_recognition_error";
          sendParams['sound_cancel'] = "bdspeech_recognition_cancel";
        }
        module.send({
          params: {
            //命令
            cmd: SpeechConstant.ASR_START,
            //执行参数
            params: sendParams
          },
          complete: (res) => {
            if (res.code == 0) {
              this.showMessage("发送成功")
            } else {
              this.showMessage(res.message)
            }
          }
        })
      },
      stop() {
        module.send({
          params: {
            cmd: SpeechConstant.ASR_STOP,
          },
          complete: (res) => {
            console.log(res)
          }
        })
      },
      registerListener() {
        module.registerListener({
          complete: (res) => {
            let data = res.data;
            if (data.type == "onRegisterSuccess") {
              //注册监听成功
              this.addLog("注册监听成功")
            } else if (data.type == "onEvent") {
              //识别回调事件
              let name = data.name;
              let params = data.params || "{}"
              switch (name) {
                case SpeechConstant.CALLBACK_EVENT_ASR_READY:
                  //引擎准备就绪,可以开始说话
                  this.addLog("引擎准备完成,可以开始说话")
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_BEGIN:
                  //检测到用户的已经开始说话
                  this.addLog("检测到用户的已经开始说话")
                  this.isStart = true;
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_END:
                  //检测到用户的已经停止说话,或者ASR_STOP 输入事件调用后
                  this.addLog("检测到用户的已经停止说话")
                  this.isStart = false;
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL:
                  //识别结果,识别过程
                  this.addLog("识别过程:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_FINISH:
                  //识别结束
                  this.addLog("识别结束:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_LONG_SPEECH:
                  //长语音识别结束
                  this.addLog("长语音识别结束:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_VOLUME:
                  //音量的回调
                  this.addLog("音量的回调:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_AUDIO:
                  //语音的二进制数据,dataValue pcm格式,16bits 16000采样率
                  let dataValue = data.data || [];
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_EXIT:
                  //引擎完成整个识别,空闲中
                  this.addLog("引擎完成整个识别,空闲中")
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_LOADED:
                  //离线命令词资源加载成功
                  this.addLog("离线命令词资源加载成功")
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_UNLOADED:
                  //离线命令词资源释放成功
                  this.addLog("离线命令词资源释放成功")
                  break
              }
            }
          }
        })
      },
      addLog(message) {
        this.logs.push(message)
      },
      release() {
        //取消识别
        module.send({
          params: {
            cmd: SpeechConstant.ASR_CANCEL
          },
          complete: (res) => {
            console.log(res)
          }
        })
        //取消监听
        module.unRegisterListener({
          complete: (res) => {
            console.log(res)
          }
        })
        //释放资源
        module.release({
          complete: (res) => {
            console.log(res)
          }
        })
      },
      changeSaveAudio(event) {
        if (event.detail.value) {
          this.saveAudioIndex = 1
        } else {
          this.saveAudioIndex = 0;
        }
      },
      changeTipsSound(event) {
        if (event.detail.value) {
          this.tipsSoundIndex = 1
        } else {
          this.tipsSoundIndex = 0;
        }
      },
      changeLongSpeech(event) {
        this.settingParams['enable.long.speech'] = event.detail.value
      },
      changeAcceptAudioData(event) {
        this.settingParams['accept-audio-data'] = event.detail.value
      },
      changeDisablePunctuation(event) {
        this.settingParams['disable-punctuation'] = event.detail.value
      },
      changeAcceptAudioVolume(event) {
        this.settingParams['accept-audio-volume'] = event.detail.value
      }
    }
  }
</script>

<style>

</style>
vue
<template>
  <view>
    <uni-card title="离线命令词识别(含长语音)">
      <view>根据bsg文件里预定义的固定语法进行离线命令词识别:</view>
      <view>SDK没有以下功能:</view>
      <view>1.没有任意词离线识别。</view>
      <view>2.没有纯离线,第一次使用必须联网。</view>
      <view>3.离线效果远差于在线的。</view>
      <view>离线命令词测试方法:</view>
      <view>1. 首次使用,联网任意识别一句话。这一步可以测试之前的“在线识别”界面。</view>
      <view>2. 断网, 大声说“打电话给妈妈”。遇见10012 Offline engine recognize fail ,表示您说的不够清晰或者语速过快。</view>
      <view>集成注意事项:</view>
      <view>1. demo中测试的“打电话给妈妈”, 其中 ”打电话给name”是bsg文件中定义的,"妈妈"是使用SLOT_DATA参数,覆盖bsg文件name词条的定义。</view>
      <view>2. demo的bsg文件是放在core的模块里的assets目录下。需要自定义bsg文件,可以在http://yuyin.baidu.com/asr 下载</view>
      <view>3. 首次联网SDK会自动下载授权文件。自动下载的前提是您填写的appId,appKey,secretKey及包名,同网页上填写的一致</view>
    </uni-card>
    <uni-card title="设置">
      <uni-section title="VAD时长设置">
        <uni-data-checkbox v-model="settingParams['vad.endpoint-timeout']"
          :localdata="vadEndpointTimeoutItems"></uni-data-checkbox>
      </uni-section>
      <uni-section title="VAD是否开启">
        <uni-data-checkbox v-model="settingParams.vad" :localdata="vadItems"></uni-data-checkbox>
      </uni-section>
      <uni-section title="外部音频">
        <uni-data-checkbox v-model="settingParams.infile" :localdata="infileItems"></uni-data-checkbox>
      </uni-section>
      <uni-section title="保存录音">
        <radio-group @change="changeSaveAudio">
          <radio :value="false" style="transform:scale(0.7)" :checked="saveAudioIndex == 0"></radio>否
          <radio :value="true" style="transform:scale(0.7)" :checked="saveAudioIndex == 1"></radio>是
        </radio-group>
      </uni-section>
      <uni-section title="开启代码中音频回调事件" sub-title="不需要音频二进制数据的回调,请勿开启,否则影响性能">
        <radio-group @change="changeAcceptAudioData">
          <radio :value="false" style="transform:scale(0.7)" :checked="acceptAudioDataIndex == 0"></radio>否
          <radio :value="true" style="transform:scale(0.7)" :checked="acceptAudioDataIndex == 1"></radio>是
        </radio-group>
      </uni-section>
      <uni-section title="提示音">
        <radio-group @change="changeTipsSound">
          <radio :value="false" style="transform:scale(0.7)" :checked="tipsSoundIndex == 0"></radio>否
          <radio :value="true" style="transform:scale(0.7)" :checked="tipsSoundIndex == 1"></radio>是
        </radio-group>
      </uni-section>
      <uni-section title="开启代码中音量回调事件" sub-title="是否需要音频的音量回调。正常使用请勿开启">
        <radio-group @change="changeAcceptAudioVolume">
          <radio :value="false" style="transform:scale(0.7)" :checked="acceptAudioVolumeIndex == 0"></radio>否
          <radio :value="true" style="transform:scale(0.7)" :checked="acceptAudioVolumeIndex == 1"></radio>是
        </radio-group>
      </uni-section>
    </uni-card>
    <button type="primary" @click="toggle">{{isStart ? "停止" : "开始"}}</button>
    <uni-card title="日志">
      <view v-for="(item, index) in logs" :key="index">{{item}}</view>
    </uni-card>
  </view>
</template>

<script>
  import * as module from "@/uni_modules/leven-uts-bdSpeech"
  import {
    SpeechConstant
  } from "@/utils/SpeechConstant.js"
  import {
    KeyUtils
  } from "@/utils/KeyUtils.js"
  export default {
    data() {
      return {
        isStart: false,
        //设置参数
        settingParams: {
          //离线解析
          decoder: 2,
          //长语音时长设置
          "vad.endpoint-timeout": "",
          //vad是否开启
          vad: "",
          //外部音频
          infile: "",
          //开启代码中音频回调事件
          "accept-audio-data": false,
          //开启代码中音量回调事件
          "accept-audio-volume": false
        },
        //平台id列表
        vadEndpointTimeoutItems: [{
          "value": "",
          "text": "默认"
        }, {
          "value": 0,
          "text": "开启长语音(离线不支持)。建议pid选择15372"
        }, {
          "value": 800,
          "text": "800毫秒,静音800ms后断句,适用于输入短语"
        }, {
          "value": 2000,
          "text": "2000毫秒,静音2000ms后断句,适用于输入长句"
        }, {
          "value": 2230,
          "text": "2230, 毫秒,请修改代码中的VAD_ENDPOINT_TIMEOUT,自定义时长(建议800ms-3000ms之间)"
        }],
        //vad是否开启配置
        vadItems: [{
          "value": "",
          "text": "不设置"
        }, {
          "value": "dnn",
          "text": "默认,推荐模型"
        }, {
          "value": "touch",
          "text": "关闭静音断句功能。用戶手动停止录音"
        }],
        //外部音频列表
        infileItems: [{
          "value": "",
          "text": "不设置"
        }, {
          "value": "assets:///com/baidu/android/voicedemo/16k_test.pcm",
          "text": "16k采样的测试音频"
        }, {
          "value": "assets:///com/baidu/android/voicedemo/offline_input.pcm",
          "text": "测试离线命令词"
        }],
        //是否保存录音文件
        saveAudioIndex: 0,
        //录音文件保存路径,为空则默认为项目私有目录
        audioPath: "/storage/emulated/0/levenBdSpeech/1234.pcm",
        //开启代码中音频回调事件索引
        acceptAudioDataIndex: 0,
        //提示音
        tipsSoundIndex: 0,
        //开启代码中音量回调事件
        acceptAudioVolumeIndex: 0,
        //日志
        logs: []
      }
    },
    mounted() {
      this.$nextTick(() => {
        //初始化
        //初始化后注册监听
        this.initSdk();
      })
    },
    onUnload() {
      //页面卸载
      this.release();
    },
    methods: {
      toggle() {
        if (this.isStart) {
          this.stop()
        } else {
          this.start()
        }
      },
      showMessage(message) {
        uni.showToast({
          title: message,
          icon: "none"
        })
      },
      initSdk() {
        module.init({
          params: {
            appId: KeyUtils.APPID,
            apiKey: KeyUtils.APIKEY,
            secretKey: KeyUtils.SECRETKEY
          },
          complete: (res) => {
            if (res.code == 0) {
              this.addLog("初始化成功")

              //注册监听
              this.registerListener();
              //加载离线命令词,如果要在这里加载离线命令词需要使用代码同步,保证在registerListener之后加载,这样才会有registerListener的命令词加载状态的回调
              // this.loadOfflineEngine()
            } else {
              this.addLog(res.message)
            }
          }
        })
      },
      start() {
        let sendParams = this.settingParams;
        if (this.saveAudioIndex == 1) {
          // 目前必须开启此回掉才嫩保存音频
          sendParams["accept-audio-data"] = true;
          sendParams["outfile"] = this.audioPath;
        }
        if (this.tipsSoundIndex == 1) {
          //请将声音文件放到到raw下面,传递时不需要带扩展名只传入文件名即可
          sendParams['sound_start'] = "bdspeech_recognition_start";
          sendParams['sound_end'] = "bdspeech_speech_end";
          sendParams['sound_success'] = "bdspeech_recognition_success";
          sendParams['sound_error'] = "bdspeech_recognition_error";
          sendParams['sound_cancel'] = "bdspeech_recognition_cancel";
        }
        module.send({
          params: {
            //命令
            cmd: SpeechConstant.ASR_START,
            //执行参数
            params: sendParams
          },
          complete: (res) => {
            if (res.code == 0) {
              this.showMessage("发送成功")
            } else {
              this.showMessage(res.message)
            }
          }
        })
      },
      stop() {
        module.send({
          params: {
            cmd: SpeechConstant.ASR_STOP,
          },
          complete: (res) => {
            console.log(res)
          }
        })
      },
      registerListener() {
        module.registerListener({
          complete: (res) => {
            let data = res.data;
            if (data.type == "onRegisterSuccess") {
              //注册监听成功
              this.addLog("注册监听成功")
              //这里可以加载离线命令词
              this.loadOfflineEngine();
            } else if (data.type == "onEvent") {
              //识别回调事件
              let name = data.name;
              let params = data.params || "{}"
              switch (name) {
                case SpeechConstant.CALLBACK_EVENT_ASR_READY:
                  //引擎准备就绪,可以开始说话
                  this.addLog("引擎准备完成,可以开始说话")
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_BEGIN:
                  //检测到用户的已经开始说话
                  this.addLog("检测到用户的已经开始说话")
                  this.isStart = true;
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_END:
                  //检测到用户的已经停止说话,或者ASR_STOP 输入事件调用后
                  this.addLog("检测到用户的已经停止说话")
                  this.isStart = false;
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL:
                  //识别结果,识别过程
                  this.addLog("识别过程:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_FINISH:
                  //识别结束
                  this.addLog("识别结束:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_LONG_SPEECH:
                  //长语音识别结束
                  this.addLog("长语音识别结束:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_VOLUME:
                  //音量的回调
                  this.addLog("音量的回调:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_AUDIO:
                  //语音的二进制数据,dataValue pcm格式,16bits 16000采样率
                  let dataValue = data.data || [];
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_EXIT:
                  //引擎完成整个识别,空闲中
                  this.addLog("引擎完成整个识别,空闲中")
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_LOADED:
                  //离线命令词资源加载成功
                  this.addLog("离线命令词资源加载成功")
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_UNLOADED:
                  //离线命令词资源释放成功
                  this.addLog("离线命令词资源释放成功")
                  break
              }
            }
          }
        })
      },
      loadOfflineEngine() {
        module.send({
          params: {
            //执行的命令
            cmd: SpeechConstant.ASR_KWS_LOAD_ENGINE,
            params: {
              decoder: 2,
              grammar: "assets:///baidu_speech_grammar.bsg",
              "slot-data": {
                name: ['妈妈', '李四'],
                appname: ['手百', '度秘']
              }
            }
          },
          complete: (res) => {
            console.log(res);
          }
        })
      },
      addLog(message) {
        this.logs.push(message)
      },
      release() {
        //取消识别
        module.send({
          params: {
            cmd: SpeechConstant.ASR_CANCEL
          },
          complete: (res) => {
            console.log(res)
          }
        })
        //卸载离线资源
        module.send({
          params: {
            cmd: SpeechConstant.ASR_KWS_UNLOAD_ENGINE
          },
          complete: (res) => {
            console.log(res)
          }
        })
        //取消监听
        module.unRegisterListener({
          complete: (res) => {
            console.log(res)
          }
        })
        //释放资源
        module.release({
          complete: (res) => {
            console.log(res)
          }
        })
      },
      changeSaveAudio(event) {
        if (event.detail.value) {
          this.saveAudioIndex = 1
        } else {
          this.saveAudioIndex = 0;
        }
      },
      changeTipsSound(event) {
        if (event.detail.value) {
          this.tipsSoundIndex = 1
        } else {
          this.tipsSoundIndex = 0;
        }
      },
      changeLongSpeech(event) {
        this.settingParams['enable.long.speech'] = event.detail.value
      },
      changeAcceptAudioData(event) {
        this.settingParams['accept-audio-data'] = event.detail.value
      },
      changeDisablePunctuation(event) {
        this.settingParams['disable-punctuation'] = event.detail.value
      },
      changeAcceptAudioVolume(event) {
        this.settingParams['accept-audio-volume'] = event.detail.value
      }
    }
  }
</script>

<style>

</style>
vue
<template>
  <view>
    <uni-card title="功能说明">
      <view>唤醒词功能即SDK识别唤醒词,或者认为是SDK识别出用户一大段话中的“关键词”,与Android系统自身的锁屏唤醒无关</view>
      <view>测试方法:</view>
      <view>1.第一次使用需要联网使用</view>
      <view>2. 请说“小度你好”或者 “百度一下”</view>
      <view>唤醒词是本地功能,需要获取正式授权文件(与离线命令词的正式授权文件是同一个)。 第一次联网使用唤醒词功能自动获取正式授权文件。之后可以断网测试。</view>
      <view>集成指南:</view>
      <view>1.demo的wakeUp.bin文件是放在core的模块里的assets目录下。需要自定义bsg文件,可以在http://yuyin.baidu.com/asr 下载</view>
      <view>2.首次联网SDK会自动下载授权文件。自动下载的前提是您填写的appId,appKey,secretKey及包名,同网页上填写的一致。</view>
    </uni-card>
    <button type="primary" @click="toggle">{{isStart ? "停止" : "开始"}}</button>
    <uni-card title="日志">
      <view v-for="(item, index) in logs" :key="index">{{item}}</view>
    </uni-card>
  </view>
</template>

<script>
  import * as module from "@/uni_modules/leven-uts-bdSpeech"
  import {
    SpeechConstant
  } from "@/utils/SpeechConstant.js"
  import {
    KeyUtils
  } from "@/utils/KeyUtils.js"
  export default {
    data() {
      return {
        isStart: false,
        //日志
        logs: []
      }
    },
    mounted() {
      this.$nextTick(() => {
        //初始化后注册监听
        this.initSdk();
      })
    },
    onUnload() {
      //页面卸载
      this.release();
    },
    methods: {
      toggle() {
        if (this.isStart) {
          this.stop()
        } else {
          this.start()
        }
      },
      showMessage(message) {
        uni.showToast({
          title: message,
          icon: "none"
        })
      },
      initSdk() {
        module.init({
          params: {
            appId: KeyUtils.APPID,
            apiKey: KeyUtils.APIKEY,
            secretKey: KeyUtils.SECRETKEY,
            type: "wp"
          },
          complete: (res) => {
            if (res.code == 0) {
              this.addLog("初始化成功")
              //注册监听
              this.registerListener();
            } else {
              this.addLog(res.message)
            }
          }
        })
      },
      start() {
        module.send({
          params: {
            //命令
            cmd: SpeechConstant.WAKEUP_START,
            //执行参数
            params: {
              'kws-file': "assets:///WakeUp.bin",
              // 'accept-audio-data':true,
              // 'infile':"assets:///com/baidu/android/voicedemo/wakeup.pcm"
            }
          },
          complete: (res) => {
            if (res.code == 0) {
              this.showMessage("发送成功")
              this.isStart = true;
            } else {
              this.showMessage(res.message)
            }
          }
        })
      },
      stop() {
        module.send({
          params: {
            cmd: SpeechConstant.WAKEUP_STOP,
          },
          complete: (res) => {
            console.log(res)
            this.isStart = false
          }
        })
      },
      registerListener() {
        module.registerListener({
          complete: (res) => {
            let data = res.data;
            if (data.type == "onRegisterSuccess") {
              //注册监听成功
              this.addLog("注册监听成功")
            } else if (data.type == "onEvent") {
              //识别回调事件
              let name = data.name;
              let params = data.params || "{}"
              switch (name) {
                case SpeechConstant.CALLBACK_EVENT_WAKEUP_SUCCESS:
                  //识别唤醒词成功
                  this.addLog("识别唤醒词成功:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_WAKEUP_ERROR:
                  //识别唤醒词报错
                  this.addLog("识别唤醒词报错:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_WAKEUP_STOPED:
                  //关闭唤醒词
                  this.addLog("关闭唤醒词")
                  this.isStart = false;
                  break
                case SpeechConstant.CALLBACK_EVENT_WAKEUP_AUDIO:
                  //音频回调
                  this.addLog("音频回调:" + params)
                  break
              }
            }
          }
        })
      },
      addLog(message) {
        this.logs.push(message)
      },
      release() {
        //取消识别
        module.send({
          params: {
            cmd: SpeechConstant.WAKEUP_STOP
          },
          complete: (res) => {
            console.log(res)
          }
        })
        //取消监听
        module.unRegisterListener({
          complete: (res) => {
            console.log(res)
          }
        })
      },
      changeSaveAudio(event) {
        if (event.detail.value) {
          this.saveAudioIndex = 1
        } else {
          this.saveAudioIndex = 0;
        }
      },
      changeTipsSound(event) {
        if (event.detail.value) {
          this.tipsSoundIndex = 1
        } else {
          this.tipsSoundIndex = 0;
        }
      },
      changeLongSpeech(event) {
        this.settingParams['enable.long.speech'] = event.detail.value
      },
      changeAcceptAudioData(event) {
        this.settingParams['accept-audio-data'] = event.detail.value
      },
      changeDisablePunctuation(event) {
        this.settingParams['disable-punctuation'] = event.detail.value
      },
      changeAcceptAudioVolume(event) {
        this.settingParams['accept-audio-volume'] = event.detail.value
      }
    }
  }
</script>

<style>

</style>
vue
<template>
  <view>
    <uni-card title="功能说明">
      <view>请先单独测试唤醒词功能和在线识别功能</view>
      <view>唤醒后识别,即唤醒词识别成功后,立即在线识别。</view>
      <view>根据用户说唤醒词之后有无停顿。共2种实现方式:</view>
      <view>1. 您的场景需要唤醒词之后无停顿,用户一下子说出。那么可以使用录音回溯功能:连同唤醒词一起整句识别。</view>
      <view>2. 您的场景为唤醒词之后UI引导有短暂停顿。那么不做回溯,识别出唤醒词停顿后的句子。</view>
      <view>两个方案的优劣 :</view>
      <view>方案1 中,整句回溯时间是经验值1.5s。 此外由于整句识别,可能唤醒词会识别成别的结果。</view>
      <view>方案2中, 如果用户不停顿,将可能造成首字或者首词的识别错误。</view>
      <view>测试方法:</view>
      <view>测试请说:百度一下【此处可以停顿】,今天天气真好</view>
      <view>集成指南:</view>
      <view>代码中通过backTrackInMs成员变量可以选择测试方案1还是方案2。</view>
    </uni-card>
    <button type="primary" @click="toggle">{{isStart ? "停止" : "开始"}}</button>
    <uni-card title="日志">
      <view v-for="(item, index) in logs" :key="index">{{item}}</view>
    </uni-card>
  </view>
</template>

<script>
  import * as module from "@/uni_modules/leven-uts-bdSpeech"
  import {
    SpeechConstant
  } from "@/utils/SpeechConstant.js"
  import {
    KeyUtils
  } from "@/utils/KeyUtils.js"
  import {
    compile
  } from "vue"
  export default {
    data() {
      return {
        isStart: false,
        /**
         * 0: 方案1, backTrackInMs > 0,唤醒词说完后,直接接句子,中间没有停顿。
         *              开启回溯,连同唤醒词一起整句识别。推荐4个字 1500ms
         *          backTrackInMs 最大 15000,即15s
         *
         * >0 : 方案2:backTrackInMs = 0,唤醒词说完后,中间有停顿。
         *       不开启回溯。唤醒词识别回调后,正常开启识别。
         *
         */
        backTrackInMs: 1500,
        //日志
        logs: []
      }
    },
    mounted() {
      this.$nextTick(() => {
        //初始化后注册监听
        this.initSdk();
      })
    },
    onUnload() {
      //页面卸载
      this.release();
    },
    methods: {
      toggle() {
        if (this.isStart) {
          this.stop()
        } else {
          this.start()
        }
      },
      showMessage(message) {
        uni.showToast({
          title: message,
          icon: "none"
        })
      },
      initSdk() {
        //先初始化命令词
        module.init({
          params: {
            appId: KeyUtils.APPID,
            apiKey: KeyUtils.APIKEY,
            secretKey: KeyUtils.SECRETKEY,
            type: "wp"
          },
          complete: (res) => {
            if (res.code == 0) {
              this.addLog("初始化命令词成功")
              //初始化识别
              this.initRecog()
            } else {
              this.addLog(res.message)
            }
          }
        })
      },
      initRecog() {
        module.init({
          params: {
            appId: KeyUtils.APPID,
            apiKey: KeyUtils.APIKEY,
            secretKey: KeyUtils.SECRETKEY
          },
          complete: (res) => {
            if (res.code == 0) {
              this.addLog("初始化识别成功")
              //注册监听
              this.registerListener();
            } else {
              this.addLog(res.message)
            }
          }
        })
      },
      start() {
        module.send({
          params: {
            //命令
            cmd: SpeechConstant.WAKEUP_START,
            //执行参数
            params: {
              'kws-file': "assets:///WakeUp.bin",
              // 'accept-audio-data':true,
              // 'infile':"assets:///com/baidu/android/voicedemo/wakeup.pcm"
            }
          },
          complete: (res) => {
            if (res.code == 0) {
              this.showMessage("发送成功")
              this.isStart = true;
            } else {
              this.showMessage(res.message)
            }
          }
        })
      },
      stop() {
        module.send({
          params: {
            cmd: SpeechConstant.WAKEUP_STOP,
          },
          complete: (res) => {
            console.log(res)
            this.isStart = false
          }
        })
      },
      recog() {
        module.send({
          params: {
            cmd: SpeechConstant.ASR_CANCEL
          },
          complete: (res) => {
            let sendParams = {
              'accept-audio-volume': false,
              'vad': SpeechConstant.VAD_DNN
            }
            if (this.backTrackInMs > 0) {
              let timeTamp = Date.parse(new Date());
              // 方案1  唤醒词说完后,直接接句子,中间没有停顿。开启回溯,连同唤醒词一起整句识别。
              // timeTamp - backTrackInMs ,  表示识别从backTrackInMs毫秒前开始
              sendParams['audio.mills'] = timeTamp - this.backTrackInMs;
            }
            module.send({
              params: {
                cmd: SpeechConstant.ASR_START,
                params: sendParams
              },
              complete: (resStart) => {
                console.log(resStart)
              }
            })
          }
        })
      },
      registerListener() {
        module.registerListener({
          complete: (res) => {
            let data = res.data;
            if (data.type == "onRegisterSuccess") {
              //注册监听成功
              this.addLog("注册监听成功")
            } else if (data.type == "onEvent") {
              //识别回调事件
              let name = data.name;
              let params = data.params || "{}"
              switch (name) {
                case SpeechConstant.CALLBACK_EVENT_WAKEUP_SUCCESS:
                  //识别唤醒词成功
                  this.addLog("识别唤醒词成功:" + params)
                  // 此处 开始正常识别流程
                  this.recog();
                  break
                case SpeechConstant.CALLBACK_EVENT_WAKEUP_ERROR:
                  //识别唤醒词报错
                  this.addLog("识别唤醒词报错:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_WAKEUP_STOPED:
                  //关闭唤醒词
                  this.addLog("关闭唤醒词")
                  this.isStart = false;
                  break
                case SpeechConstant.CALLBACK_EVENT_WAKEUP_AUDIO:
                  //音频回调
                  this.addLog("音频回调:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_READY:
                  //引擎准备就绪,可以开始说话
                  this.addLog("引擎准备完成,可以开始说话")
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_BEGIN:
                  //检测到用户的已经开始说话
                  this.addLog("检测到用户的已经开始说话")
                  this.isStart = true;
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_END:
                  //检测到用户的已经停止说话,或者ASR_STOP 输入事件调用后
                  this.addLog("检测到用户的已经停止说话")
                  this.isStart = false;
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL:
                  //识别结果,识别过程
                  this.addLog("识别过程:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_FINISH:
                  //识别结束
                  this.addLog("识别结束:" + params)
                  break
                case SpeechConstant.CALLBACK_EVENT_ASR_EXIT:
                  //引擎完成整个识别,空闲中
                  this.addLog("引擎完成整个识别,空闲中")
                  break
              }
            }
          }
        })
      },
      addLog(message) {
        this.logs.push(message)
      },
      release() {
        //取消识别
        module.send({
          params: {
            cmd: SpeechConstant.WAKEUP_STOP
          },
          complete: (res) => {
            console.log(res)
          }
        })
        //取消识别
        module.send({
          params: {
            cmd: SpeechConstant.ASR_STOP
          },
          complete: (res) => {
            console.log(res)
          }
        })
        //取消监听
        module.unRegisterListener({
          complete: (res) => {
            console.log(res)
          }
        })
      },
      changeSaveAudio(event) {
        if (event.detail.value) {
          this.saveAudioIndex = 1
        } else {
          this.saveAudioIndex = 0;
        }
      },
      changeTipsSound(event) {
        if (event.detail.value) {
          this.tipsSoundIndex = 1
        } else {
          this.tipsSoundIndex = 0;
        }
      },
      changeLongSpeech(event) {
        this.settingParams['enable.long.speech'] = event.detail.value
      },
      changeAcceptAudioData(event) {
        this.settingParams['accept-audio-data'] = event.detail.value
      },
      changeDisablePunctuation(event) {
        this.settingParams['disable-punctuation'] = event.detail.value
      },
      changeAcceptAudioVolume(event) {
        this.settingParams['accept-audio-volume'] = event.detail.value
      }
    }
  }
</script>

<style>

</style>

uniapp x

vue
<template>
  <!-- #ifdef APP -->
  <scroll-view style="flex:1">
  <!-- #endif -->
    <rice-cell-group border>
      <rice-cell title="在线识别" arrow clickable @click="toPage('onlineRecog')"></rice-cell>
      <rice-cell title="离线命令词" arrow clickable @click="toPage('offlineRecog')"></rice-cell>
      <rice-cell title="唤醒词" arrow clickable @click="toPage('wakeup')"></rice-cell>
      <rice-cell title="唤醒后识别" arrow clickable @click="toPage('wakeUpRecog')"></rice-cell>
    </rice-cell-group>
  <!-- #ifdef APP -->
  </scroll-view>
  <!-- #endif -->
</template>

<script lang="uts" setup>
  import * as module from "@/uni_modules/leven-uts-bdSpeech"
  import { LevenResult, LevenOptions } from "@/uni_modules/leven-uts-bdSpeech"

  function toPage(type : string) {
    switch (type) {
      case "onlineRecog":
        uni.navigateTo({
          url: "/pages/bdSpeech/onlineRecog"
        })
        break
      case "offlineRecog":
        uni.navigateTo({
          url: "/pages/bdSpeech/offlineRecog"
        })
        break
      case "wakeup":
        uni.navigateTo({
          url: "/pages/bdSpeech/wakeup"
        })
        break
      case "wakeUpRecog":
        uni.navigateTo({
          url: "/pages/bdSpeech/wakeUpRecog"
        })
        break
    }
  }

  //显示消息
  function showMessage(message : string) {
    uni.showToast({
      title: message,
      icon: "none"
    })
  }

  //跳转到所有文件访问权限页面
  function toAllFilesPermissionPage() {
    module.toAllFilesPermissionPage({
      complete: (res : LevenResult) => {
        if (res.code == 0) {
          let data = res.data;
          let status : boolean = data.getBoolean("status")!
          if (!status) {
            showMessage("所有文件访问权限未打开")
          } else {
            showMessage("权限授权完成,欢迎使用")
          }
        } else {
          showMessage("跳转到所有文件访问权限页面失败")
        }
      }
    } as LevenOptions)
  }

  //检测是否有所有文件访问权限
  function checkAllFilesPermission() {
    module.checkAllFilesPermission({
      complete: (res : LevenResult) => {
        if (res.code == 0) {
          let data = res.data;
          let status : boolean = data.getBoolean("status")!
          if (!status) {
            toAllFilesPermissionPage();
          } else {
            showMessage("权限授权完成,欢迎使用")
          }
        } else {
          showMessage("查询文件权限失败")
        }
      }
    } as LevenOptions)
  }

  //申请权限
  function requestPermissions() {
    module.requestPermissions({
      params: {
        permissions: [
          'android.permission.READ_EXTERNAL_STORAGE',
          'android.permission.WRITE_EXTERNAL_STORAGE',
          'android.permission.RECORD_AUDIO'
        ]
      },
      complete: (res : LevenResult) => {
        console.log(res)
        if (res.code == 0) {
          checkAllFilesPermission()
        } else {
          showMessage("权限申请未通过")
        }
      }
    } as LevenOptions)
  }

  //页面加载
  onMounted(() => {
    //申请权限
    requestPermissions();
  })
</script>

<style>

</style>
vue
<template>
  <!-- #ifdef APP -->
  <scroll-view style="flex:1">
  <!-- #endif -->
    <lux-card title="在线普通识别功能(含长语音)">
      <view><text>普通识别测试方法:</text></view>
      <view><text>请保持设备联网,对着麦克风说出日常用语即可。</text></view>
      <view><text>普通录音限制60s。使用长语音无此限制。</text></view>
    </lux-card>
    <lux-card title="设置">
      <lux-section text="PID,语种">
        <rice-radio-group v-model="language" direction="row">
          <rice-radio value="" label="默认" :customStyle="radioStyle"></rice-radio>
          <rice-radio value="cmn-Hans-CN" label="普通话" :customStyle="radioStyle"></rice-radio>
          <rice-radio value="en-GB" label="英语" :customStyle="radioStyle"></rice-radio>
          <rice-radio value="yue-Hans-CN" label="粤语" :customStyle="radioStyle"></rice-radio>
          <rice-radio value="sichuan-Hans-CN" label="四川话" :customStyle="radioStyle"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="LMID,自训练平台ID,请选PID=8002生效">
        <rice-radio-group v-model="lm_id">
          <rice-radio value="" label="默认" :customStyle="radioStyle"></rice-radio>
          <rice-radio value="1068" label="自训练平台上线的id,和账号维度绑定"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="长语音" subText="长语音参数,优先级高于vad_endpoint_timeout">
        <rice-radio-group v-model="enableLongSpeech" direction="row">
          <rice-radio :value="false" label="否"></rice-radio>
          <rice-radio :value="true" label="是"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="VAD时长设置">
        <rice-radio-group v-model="vadEndpointTimeout">
          <rice-radio value="" label="默认"></rice-radio>
          <rice-radio :value="0" label="开启长语音(离线不支持)。建议pid选择15372" :customStyle="radioStyle"></rice-radio>
          <rice-radio :value="800" label="800毫秒,静音800ms后断句,适用于输入短语" :customStyle="radioStyle"></rice-radio>
          <rice-radio :value="2000" label="2000毫秒,静音2000ms后断句,适用于输入长句" :customStyle="radioStyle"></rice-radio>
          <rice-radio :value="2230" label="2230, 毫秒,请修改代码中的VAD_ENDPOINT_TIMEOUT,自定义时长(建议800ms-3000ms之间)"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="VAD是否开启">
        <rice-radio-group v-model="vad">
          <rice-radio value="" label="不设置" :customStyle="radioStyle"></rice-radio>
          <rice-radio value="dnn" label="默认,推荐模" :customStyle="radioStyle"></rice-radio>
          <rice-radio value="touch" label="关闭静音断句功能。用戶手动停止录音"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="外部音频">
        <rice-radio-group v-model="infile">
          <rice-radio value="" label="不设置" :customStyle="radioStyle"></rice-radio>
          <rice-radio value="assets:///com/baidu/android/voicedemo/16k_test.pcm" label="16k采样的测试音频"
            :customStyle="radioStyle"></rice-radio>
          <rice-radio value="assets:///com/baidu/android/voicedemo/offline_input.pcm" label="测试离线命令词"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="保存录音">
        <rice-radio-group v-model="saveAudioData" direction="row">
          <rice-radio :value="false" label="否"></rice-radio>
          <rice-radio :value="true" label="是"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="开启代码中音频回调事件" subText="不需要音频二进制数据的回调,请勿开启,否则影响性能">
        <rice-radio-group v-model="acceptAudioData" direction="row">
          <rice-radio :value="false" label="否"></rice-radio>
          <rice-radio :value="true" label="是"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="禁用标点" subText="在选择输入法模型的前提下生效">
        <rice-radio-group v-model="disablePunctuation" direction="row">
          <rice-radio :value="false" label="否"></rice-radio>
          <rice-radio :value="true" label="是"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="提示音">
        <rice-radio-group v-model="tipsSound" direction="row">
          <rice-radio :value="false" label="否"></rice-radio>
          <rice-radio :value="true" label="是"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="开启代码中音量回调事件" subText="是否需要音频的音量回调。正常使用请勿开启">
        <rice-radio-group v-model="acceptAudioVolume" direction="row">
          <rice-radio :value="false" label="否"></rice-radio>
          <rice-radio :value="true" label="是"></rice-radio>
        </rice-radio-group>
      </lux-section>
    </lux-card>
    <button type="primary" @click="toggle">{{isStart ? "停止" : "开始"}}</button>
    <lux-card title="日志">
      <view v-for="(item, index) in logs" :key="index"><text>{{item}}</text></view>
    </lux-card>
  <!-- #ifdef APP -->
  </scroll-view>
  <!-- #endif -->
</template>

<script lang="uts" setup>
  import * as module from "@/uni_modules/leven-uts-bdSpeech"
  import { LevenResult, LevenOptions } from "@/uni_modules/leven-uts-bdSpeech"
  import {
    SpeechConstant
  } from "@/utils/bdSpeech/SpeechConstant.uts"
  import {
    KeyUtils
  } from "@/utils/bdSpeech/KeyUtils.uts"

  //radio样式
  const radioStyle = {
    marginBottom: '8px'
  }

  //设置参数
  //语种
  const language = ref("")
  //自训练平台ID
  const lm_id = ref("")
  //长语音
  const enableLongSpeech = ref(false)
  //VAD时长
  const vadEndpointTimeout = ref<number | string>("")
  //vad是否开启
  const vad = ref("")
  //外部音频
  const infile = ref("")
  //保存录音
  const saveAudioData = ref(false)
  //开启代码中音频回调事件
  const acceptAudioData = ref(false)
  //禁用标点
  const disablePunctuation = ref(false)
  //提示音
  const tipsSound = ref(false)
  //开启代码中音量回调事件
  const acceptAudioVolume = ref(false)
  //是否开始识别
  const isStart = ref(false)
  //日志
  const logs = ref<string[]>([])

  function addLog(message : string) {
    logs.value.push(message)
  }

  function showMessage(message : string) {
    uni.showToast({
      title: message,
      icon: "none"
    })
  }

  function start() {
    let sendParams = {
      //语种
      language: language.value,
      //自训练平台ID
      lm_id: lm_id.value,
      //长语音
      "enable.long.speech": enableLongSpeech.value,
      //长语音时长设置
      "vad.endpoint-timeout": vadEndpointTimeout.value,
      //vad是否开启
      vad: vad.value,
      //外部音频
      infile: infile.value,
      //开启代码中音频回调事件
      "accept-audio-data": acceptAudioData.value,
      //禁用标点
      "disable-punctuation": disablePunctuation.value,
      //开启代码中音量回调事件
      "accept-audio-volume": acceptAudioVolume.value
    };
    if (saveAudioData.value) {
      // 目前必须开启此回掉才嫩保存音频
      sendParams["accept-audio-data"] = true;
      sendParams["outfile"] = "/storage/emulated/0/levenBdSpeech/1234.pcm";
    }
    if (tipsSound.value) {
      //请将声音文件放到到raw下面,传递时不需要带扩展名只传入文件名即可
      sendParams['sound_start'] = "bdspeech_recognition_start";
      sendParams['sound_end'] = "bdspeech_speech_end";
      sendParams['sound_success'] = "bdspeech_recognition_success";
      sendParams['sound_error'] = "bdspeech_recognition_error";
      sendParams['sound_cancel'] = "bdspeech_recognition_cancel";
    }
    module.send({
      params: {
        //命令
        cmd: SpeechConstant.ASR_START,
        //执行参数
        params: sendParams
      },
      complete: (res : LevenResult) => {
        if (res.code == 0) {
          showMessage("发送成功")
        } else {
          showMessage(res.message)
        }
      }
    } as LevenOptions)
  }

  function stop() {
    module.send({
      params: {
        cmd: SpeechConstant.ASR_STOP,
      },
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
  }

  function release() {
    //取消识别
    module.send({
      params: {
        cmd: SpeechConstant.ASR_CANCEL
      },
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
    //取消监听
    module.unRegisterListener({
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
    //释放资源
    module.release({
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
  }

  function registerListener() {
    module.registerListener({
      complete: (res : LevenResult) => {
        let data = res.data;
        let type = data.getString("type")
        if (type == "onRegisterSuccess") {
          //注册监听成功
          addLog("注册监听成功")
        } else if (type == "onEvent") {
          //识别回调事件
          let name = data.getString("name");
          let params = data.getString("params") ?? "{}"
          switch (name) {
            case SpeechConstant.CALLBACK_EVENT_ASR_READY:
              //引擎准备就绪,可以开始说话
              addLog("引擎准备完成,可以开始说话")
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_BEGIN:
              //检测到用户的已经开始说话
              addLog("检测到用户的已经开始说话")
              isStart.value = true;
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_END:
              //检测到用户的已经停止说话,或者ASR_STOP 输入事件调用后
              addLog("检测到用户的已经停止说话")
              isStart.value = false;
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL:
              //识别结果,识别过程
              addLog("识别过程:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_FINISH:
              //识别结束
              addLog("识别结束:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_LONG_SPEECH:
              //长语音识别结束
              addLog("长语音识别结束:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_VOLUME:
              //音量的回调
              addLog("音量的回调:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_AUDIO:
              //语音的二进制数据,dataValue pcm格式,16bits 16000采样率
              // let dataValue = data.getArray("data") || [];
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_EXIT:
              //引擎完成整个识别,空闲中
              addLog("引擎完成整个识别,空闲中")
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_LOADED:
              //离线命令词资源加载成功
              addLog("离线命令词资源加载成功")
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_UNLOADED:
              //离线命令词资源释放成功
              addLog("离线命令词资源释放成功")
              break
          }
        }
      }
    } as LevenOptions)
  }

  function initSdk() {
    module.init({
      params: {
        appId: KeyUtils.APPID,
        apiKey: KeyUtils.APIKEY,
        secretKey: KeyUtils.SECRETKEY
      },
      complete: (res : LevenResult) => {
        if (res.code == 0) {
          addLog("初始化成功")

          //注册监听
          registerListener();
        } else {
          addLog(res.message)
        }
      }
    } as LevenOptions)
  }

  function toggle() {
    if (isStart.value) {
      stop()
    } else {
      start()
    }
  }

  onMounted(() => {
    nextTick(() => {
      //初始化后注册监听
      initSdk()
    })
  })

  onUnload(() => {
    //页面卸载
    release();
  })
</script>

<style>

</style>
vue
<template>
  <!-- #ifdef APP -->
  <scroll-view style="flex:1">
  <!-- #endif -->
    <lux-card title="离线命令词识别(含长语音)">
      <view><text>根据bsg文件里预定义的固定语法进行离线命令词识别:</text></view>
      <view><text>SDK没有以下功能:</text></view>
      <view><text>1.没有任意词离线识别。</text></view>
      <view><text>2.没有纯离线,第一次使用必须联网。</text></view>
      <view><text>3.离线效果远差于在线的。</text></view>
      <view><text>离线命令词测试方法:</text></view>
      <view><text>1. 首次使用,联网任意识别一句话。这一步可以测试之前的“在线识别”界面。</text></view>
      <view><text>2. 断网, 大声说“打电话给妈妈”。遇见10012 Offline engine recognize fail ,表示您说的不够清晰或者语速过快。</text></view>
      <view><text>集成注意事项:</text></view>
      <view><text>1. demo中测试的“打电话给妈妈”, 其中 ”打电话给name”是bsg文件中定义的,"妈妈"是使用SLOT_DATA参数,覆盖bsg文件name词条的定义。</text></view>
      <view><text>2. demo的bsg文件是放在core的模块里的assets目录下。需要自定义bsg文件,可以在http://yuyin.baidu.com/asr 下载</text></view>
      <view><text>3. 首次联网SDK会自动下载授权文件。自动下载的前提是您填写的appId,appKey,secretKey及包名,同网页上填写的一致</text></view>
    </lux-card>
    <lux-card title="设置">
      <lux-section text="VAD时长设置">
        <rice-radio-group v-model="vadEndpointTimeout">
          <rice-radio value="" label="默认"></rice-radio>
          <rice-radio :value="0" label="开启长语音(离线不支持)。建议pid选择15372" :customStyle="radioStyle"></rice-radio>
          <rice-radio :value="800" label="800毫秒,静音800ms后断句,适用于输入短语" :customStyle="radioStyle"></rice-radio>
          <rice-radio :value="2000" label="2000毫秒,静音2000ms后断句,适用于输入长句" :customStyle="radioStyle"></rice-radio>
          <rice-radio :value="2230" label="2230, 毫秒,请修改代码中的VAD_ENDPOINT_TIMEOUT,自定义时长(建议800ms-3000ms之间)"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="VAD是否开启">
        <rice-radio-group v-model="vad">
          <rice-radio value="" label="不设置" :customStyle="radioStyle"></rice-radio>
          <rice-radio value="dnn" label="默认,推荐模" :customStyle="radioStyle"></rice-radio>
          <rice-radio value="touch" label="关闭静音断句功能。用戶手动停止录音"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="外部音频">
        <rice-radio-group v-model="infile">
          <rice-radio value="" label="不设置" :customStyle="radioStyle"></rice-radio>
          <rice-radio value="assets:///com/baidu/android/voicedemo/16k_test.pcm" label="16k采样的测试音频"
            :customStyle="radioStyle"></rice-radio>
          <rice-radio value="assets:///com/baidu/android/voicedemo/offline_input.pcm" label="测试离线命令词"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="保存录音">
        <rice-radio-group v-model="saveAudioData" direction="row">
          <rice-radio :value="false" label="否"></rice-radio>
          <rice-radio :value="true" label="是"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="开启代码中音频回调事件" subText="不需要音频二进制数据的回调,请勿开启,否则影响性能">
        <rice-radio-group v-model="acceptAudioData" direction="row">
          <rice-radio :value="false" label="否"></rice-radio>
          <rice-radio :value="true" label="是"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="提示音">
        <rice-radio-group v-model="tipsSound" direction="row">
          <rice-radio :value="false" label="否"></rice-radio>
          <rice-radio :value="true" label="是"></rice-radio>
        </rice-radio-group>
      </lux-section>
      <lux-section text="开启代码中音量回调事件" subText="是否需要音频的音量回调。正常使用请勿开启">
        <rice-radio-group v-model="acceptAudioVolume" direction="row">
          <rice-radio :value="false" label="否"></rice-radio>
          <rice-radio :value="true" label="是"></rice-radio>
        </rice-radio-group>
      </lux-section>
    </lux-card>
    <button type="primary" @click="toggle">{{isStart ? "停止" : "开始"}}</button>
    <lux-card title="日志">
      <view v-for="(item, index) in logs" :key="index"><text>{{item}}</text></view>
    </lux-card>
  <!-- #ifdef APP -->
  </scroll-view>
  <!-- #endif -->
</template>

<script lang="uts" setup>
  import * as module from "@/uni_modules/leven-uts-bdSpeech"
  import { LevenResult, LevenOptions } from "@/uni_modules/leven-uts-bdSpeech"
  import {
    SpeechConstant
  } from "@/utils/bdSpeech/SpeechConstant.uts"
  import {
    KeyUtils
  } from "@/utils/bdSpeech/KeyUtils.uts"

  //radio样式
  const radioStyle = {
    marginBottom: '8px'
  }

  //设置参数
  //VAD时长
  const vadEndpointTimeout = ref<number | string>("")
  //vad是否开启
  const vad = ref("")
  //外部音频
  const infile = ref("")
  //保存录音
  const saveAudioData = ref(false)
  //开启代码中音频回调事件
  const acceptAudioData = ref(false)
  //提示音
  const tipsSound = ref(false)
  //开启代码中音量回调事件
  const acceptAudioVolume = ref(false)
  //是否开始识别
  const isStart = ref(false)
  //日志
  const logs = ref<string[]>([])

  function addLog(message : string) {
    logs.value.push(message)
  }

  function showMessage(message : string) {
    uni.showToast({
      title: message,
      icon: "none"
    })
  }

  function start() {
    let sendParams = {
      //长语音时长设置
      "vad.endpoint-timeout": vadEndpointTimeout.value,
      //vad是否开启
      vad: vad.value,
      //外部音频
      infile: infile.value,
      //开启代码中音频回调事件
      "accept-audio-data": acceptAudioData.value,
      //开启代码中音量回调事件
      "accept-audio-volume": acceptAudioVolume.value
    };
    if (saveAudioData.value) {
      // 目前必须开启此回掉才嫩保存音频
      sendParams["accept-audio-data"] = true;
      sendParams["outfile"] = "/storage/emulated/0/levenBdSpeech/1234.pcm";
    }
    if (tipsSound.value) {
      //请将声音文件放到到raw下面,传递时不需要带扩展名只传入文件名即可
      sendParams['sound_start'] = "bdspeech_recognition_start";
      sendParams['sound_end'] = "bdspeech_speech_end";
      sendParams['sound_success'] = "bdspeech_recognition_success";
      sendParams['sound_error'] = "bdspeech_recognition_error";
      sendParams['sound_cancel'] = "bdspeech_recognition_cancel";
    }
    module.send({
      params: {
        //命令
        cmd: SpeechConstant.ASR_START,
        //执行参数
        params: sendParams
      },
      complete: (res : LevenResult) => {
        if (res.code == 0) {
          showMessage("发送成功")
        } else {
          showMessage(res.message)
        }
      }
    } as LevenOptions)
  }

  function stop() {
    module.send({
      params: {
        cmd: SpeechConstant.ASR_STOP,
      },
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
  }

  function release() {
    //取消识别
    module.send({
      params: {
        cmd: SpeechConstant.ASR_CANCEL
      },
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
    //卸载离线资源
    module.send({
      params: {
        cmd: SpeechConstant.ASR_KWS_UNLOAD_ENGINE
      },
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
    //取消监听
    module.unRegisterListener({
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
    //释放资源
    module.release({
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
  }

  function loadOfflineEngine() {
    module.send({
      params: {
        //执行的命令
        cmd: SpeechConstant.ASR_KWS_LOAD_ENGINE,
        params: {
          decoder: 2,
          grammar: "assets:///baidu_speech_grammar.bsg",
          "slot-data": {
            name: ['妈妈', '李四'],
            appname: ['手百', '度秘']
          }
        }
      },
      complete: (res : LevenResult) => {
        console.log(res);
      }
    } as LevenOptions)
  }

  function registerListener() {
    module.registerListener({
      complete: (res : LevenResult) => {
        let data = res.data;
        let type = data.getString("type")
        if (type == "onRegisterSuccess") {
          //注册监听成功
          addLog("注册监听成功")
          //这里可以加载离线命令词
          loadOfflineEngine();
        } else if (type == "onEvent") {
          //识别回调事件
          let name = data.getString("name");
          let params = data.getString("params") ?? "{}"
          switch (name) {
            case SpeechConstant.CALLBACK_EVENT_ASR_READY:
              //引擎准备就绪,可以开始说话
              addLog("引擎准备完成,可以开始说话")
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_BEGIN:
              //检测到用户的已经开始说话
              addLog("检测到用户的已经开始说话")
              isStart.value = true;
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_END:
              //检测到用户的已经停止说话,或者ASR_STOP 输入事件调用后
              addLog("检测到用户的已经停止说话")
              isStart.value = false;
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL:
              //识别结果,识别过程
              addLog("识别过程:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_FINISH:
              //识别结束
              addLog("识别结束:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_LONG_SPEECH:
              //长语音识别结束
              addLog("长语音识别结束:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_VOLUME:
              //音量的回调
              addLog("音量的回调:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_AUDIO:
              //语音的二进制数据,dataValue pcm格式,16bits 16000采样率
              // let dataValue = data.getArray("data") || [];
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_EXIT:
              //引擎完成整个识别,空闲中
              addLog("引擎完成整个识别,空闲中")
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_LOADED:
              //离线命令词资源加载成功
              addLog("离线命令词资源加载成功")
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_UNLOADED:
              //离线命令词资源释放成功
              addLog("离线命令词资源释放成功")
              break
          }
        }
      }
    } as LevenOptions)
  }

  function initSdk() {
    module.init({
      params: {
        appId: KeyUtils.APPID,
        apiKey: KeyUtils.APIKEY,
        secretKey: KeyUtils.SECRETKEY
      },
      complete: (res : LevenResult) => {
        if (res.code == 0) {
          addLog("初始化成功")

          //加载离线命令词,如果要在这里加载离线命令词需要使用代码同步,保证在registerListener之后加载,这样才会有registerListener的命令词加载状态的回调
          // loadOfflineEngine()

          //注册监听
          registerListener();
        } else {
          addLog(res.message)
        }
      }
    } as LevenOptions)
  }

  function toggle() {
    if (isStart.value) {
      stop()
    } else {
      start()
    }
  }

  onMounted(() => {
    nextTick(() => {
      //初始化后注册监听
      initSdk()
    })
  })

  onUnload(() => {
    //页面卸载
    release();
  })
</script>

<style>

</style>
vue
<template>
  <!-- #ifdef APP -->
  <scroll-view style="flex:1">
  <!-- #endif -->
    <lux-card title="功能说明">
      <view><text>唤醒词功能即SDK识别唤醒词,或者认为是SDK识别出用户一大段话中的“关键词”,与Android系统自身的锁屏唤醒无关</text></view>
      <view><text>测试方法:</text></view>
      <view><text>1.第一次使用需要联网使用</text></view>
      <view><text>2. 请说“小度你好”或者 “百度一下”</text></view>
      <view><text>唤醒词是本地功能,需要获取正式授权文件(与离线命令词的正式授权文件是同一个)。 第一次联网使用唤醒词功能自动获取正式授权文件。之后可以断网测试。</text></view>
      <view><text>集成指南:</text></view>
      <view><text>1.demo的wakeUp.bin文件是放在core的模块里的assets目录下。需要自定义bsg文件,可以在http://yuyin.baidu.com/asr 下载</text></view>
      <view><text>2.首次联网SDK会自动下载授权文件。自动下载的前提是您填写的appId,appKey,secretKey及包名,同网页上填写的一致。</text></view>
    </lux-card>
    <button type="primary" @click="toggle">{{isStart ? "停止" : "开始"}}</button>
    <lux-card title="日志">
      <view v-for="(item, index) in logs" :key="index"><text>{{item}}</text></view>
    </lux-card>
  <!-- #ifdef APP -->
  </scroll-view>
  <!-- #endif -->
</template>

<script lang="uts" setup>
  import * as module from "@/uni_modules/leven-uts-bdSpeech"
  import { LevenResult, LevenOptions } from "@/uni_modules/leven-uts-bdSpeech"
  import {
    SpeechConstant
  } from "@/utils/bdSpeech/SpeechConstant.uts"
  import {
    KeyUtils
  } from "@/utils/bdSpeech/KeyUtils.uts"

  //是否开始识别
  const isStart = ref(false)
  //日志
  const logs = ref<string[]>([])

  function addLog(message : string) {
    logs.value.push(message)
  }

  function showMessage(message : string) {
    uni.showToast({
      title: message,
      icon: "none"
    })
  }

  function start() {
    module.send({
      params: {
        //命令
        //命令
        cmd: SpeechConstant.WAKEUP_START,
        //执行参数
        params: {
          'kws-file': "assets:///WakeUp.bin",
          // 'accept-audio-data':true,
          // 'infile':"assets:///com/baidu/android/voicedemo/wakeup.pcm"
        }
      },
      complete: (res : LevenResult) => {
        if (res.code == 0) {
          showMessage("发送成功")
          isStart.value = true
        } else {
          showMessage(res.message)
        }
      }
    } as LevenOptions)
  }

  function stop() {
    module.send({
      params: {
        cmd: SpeechConstant.WAKEUP_STOP,
      },
      complete: (res : LevenResult) => {
        console.log(res)
        isStart.value = false
      }
    } as LevenOptions)
  }

  function release() {
    //取消识别
    module.send({
      params: {
        cmd: SpeechConstant.WAKEUP_STOP
      },
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
    //取消监听
    module.unRegisterListener({
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
    //释放资源
    module.release({
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
  }

  function registerListener() {
    module.registerListener({
      complete: (res : LevenResult) => {
        let data = res.data;
        let type = data.getString("type")
        if (type == "onRegisterSuccess") {
          //注册监听成功
          addLog("注册监听成功")
        } else if (type == "onEvent") {
          //识别回调事件
          let name = data.getString("name");
          let params = data.getString("params") ?? "{}"
          switch (name) {
            case SpeechConstant.CALLBACK_EVENT_WAKEUP_SUCCESS:
              //识别唤醒词成功
              addLog("识别唤醒词成功:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_WAKEUP_ERROR:
              //识别唤醒词报错
              addLog("识别唤醒词报错:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_WAKEUP_STOPED:
              //关闭唤醒词
              addLog("关闭唤醒词")
              isStart.value = false;
              break
            case SpeechConstant.CALLBACK_EVENT_WAKEUP_AUDIO:
              //音频回调
              addLog("音频回调:" + params)
              break
          }
        }
      }
    } as LevenOptions)
  }

  function initSdk() {
    module.init({
      params: {
        appId: KeyUtils.APPID,
        apiKey: KeyUtils.APIKEY,
        secretKey: KeyUtils.SECRETKEY,
        type: "wp"
      },
      complete: (res : LevenResult) => {
        if (res.code == 0) {
          addLog("初始化成功")

          //注册监听
          registerListener();
        } else {
          addLog(res.message)
        }
      }
    } as LevenOptions)
  }

  function toggle() {
    if (isStart.value) {
      stop()
    } else {
      start()
    }
  }

  onMounted(() => {
    nextTick(() => {
      //初始化后注册监听
      initSdk()
    })
  })

  onUnload(() => {
    //页面卸载
    release();
  })
</script>

<style>

</style>
vue
<template>
  <!-- #ifdef APP -->
  <scroll-view style="flex:1">
  <!-- #endif -->
    <lux-card title="功能说明">
      <view><text>请先单独测试唤醒词功能和在线识别功能</text></view>
      <view><text>唤醒后识别,即唤醒词识别成功后,立即在线识别。</text></view>
      <view><text>根据用户说唤醒词之后有无停顿。共2种实现方式:</text></view>
      <view><text>1. 您的场景需要唤醒词之后无停顿,用户一下子说出。那么可以使用录音回溯功能:连同唤醒词一起整句识别。</text></view>
      <view><text>2. 您的场景为唤醒词之后UI引导有短暂停顿。那么不做回溯,识别出唤醒词停顿后的句子。</text></view>
      <view><text>两个方案的优劣 :</text></view>
      <view><text>方案1 中,整句回溯时间是经验值1.5s。 此外由于整句识别,可能唤醒词会识别成别的结果。</text></view>
      <view><text>方案2中, 如果用户不停顿,将可能造成首字或者首词的识别错误。</text></view>
      <view><text>测试方法:</text></view>
      <view><text>测试请说:百度一下【此处可以停顿】,今天天气真好</text></view>
      <view><text>集成指南:</text></view>
      <view><text>代码中通过backTrackInMs成员变量可以选择测试方案1还是方案2。</text></view>
    </lux-card>
    <button type="primary" @click="toggle">{{isStart ? "停止" : "开始"}}</button>
    <lux-card title="日志">
      <view v-for="(item, index) in logs" :key="index"><text>{{item}}</text></view>
    </lux-card>
  <!-- #ifdef APP -->
  </scroll-view>
  <!-- #endif -->
</template>

<script lang="uts" setup>
  import * as module from "@/uni_modules/leven-uts-bdSpeech"
  import { LevenResult, LevenOptions } from "@/uni_modules/leven-uts-bdSpeech"
  import {
    SpeechConstant
  } from "@/utils/bdSpeech/SpeechConstant.uts"
  import {
    KeyUtils
  } from "@/utils/bdSpeech/KeyUtils.uts"
  import { dateuts } from '@/uni_modules/rice-ui';

  //是否开始识别
  const isStart = ref(false)
  /**
   * 0: 方案1, backTrackInMs > 0,唤醒词说完后,直接接句子,中间没有停顿。
   *              开启回溯,连同唤醒词一起整句识别。推荐4个字 1500ms
   *          backTrackInMs 最大 15000,即15s
   *
   * >0 : 方案2:backTrackInMs = 0,唤醒词说完后,中间有停顿。
   *       不开启回溯。唤醒词识别回调后,正常开启识别。
   *
   */
  const backTrackInMs = ref(1500)
  //日志
  const logs = ref<string[]>([])

  function addLog(message : string) {
    logs.value.push(message)
  }

  function showMessage(message : string) {
    uni.showToast({
      title: message,
      icon: "none"
    })
  }

  function start() {
    module.send({
      params: {
        //命令
        //命令
        cmd: SpeechConstant.WAKEUP_START,
        //执行参数
        params: {
          'kws-file': "assets:///WakeUp.bin",
          // 'accept-audio-data':true,
          // 'infile':"assets:///com/baidu/android/voicedemo/wakeup.pcm"
        }
      },
      complete: (res : LevenResult) => {
        if (res.code == 0) {
          showMessage("发送成功")
          isStart.value = true
        } else {
          showMessage(res.message)
        }
      }
    } as LevenOptions)
  }

  function stop() {
    module.send({
      params: {
        cmd: SpeechConstant.WAKEUP_STOP,
      },
      complete: (res : LevenResult) => {
        console.log(res)
        isStart.value = false
      }
    } as LevenOptions)
  }

  function release() {
    //取消识别
    module.send({
      params: {
        cmd: SpeechConstant.WAKEUP_STOP
      },
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
    //取消识别
    module.send({
      params: {
        cmd: SpeechConstant.ASR_STOP
      },
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
    //取消监听
    module.unRegisterListener({
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
    //释放资源
    module.release({
      complete: (res : LevenResult) => {
        console.log(res)
      }
    } as LevenOptions)
  }

  function recog() {
    module.send({
      params: {
        cmd: SpeechConstant.ASR_CANCEL
      },
      complete: (res : LevenResult) => {
        let sendParams = {
          'accept-audio-volume': false,
          'vad': SpeechConstant.VAD_DNN
        }
        if (backTrackInMs.value > 0) {
          let timeTamp = dateuts().valueOf();
          // 方案1  唤醒词说完后,直接接句子,中间没有停顿。开启回溯,连同唤醒词一起整句识别。
          // timeTamp - backTrackInMs ,  表示识别从backTrackInMs毫秒前开始
          sendParams['audio.mills'] = timeTamp - backTrackInMs.value;
        }
        module.send({
          params: {
            cmd: SpeechConstant.ASR_START,
            params: sendParams
          },
          complete: (resStart) => {
            console.log(resStart)
          }
        })
      }
    } as LevenOptions)
  }

  function registerListener() {
    module.registerListener({
      complete: (res : LevenResult) => {
        let data = res.data;
        let type = data.getString("type")
        if (type == "onRegisterSuccess") {
          //注册监听成功
          addLog("注册监听成功")
        } else if (type == "onEvent") {
          //识别回调事件
          let name = data.getString("name");
          let params = data.getString("params") ?? "{}"
          switch (name) {
            case SpeechConstant.CALLBACK_EVENT_WAKEUP_SUCCESS:
              //识别唤醒词成功
              addLog("识别唤醒词成功:" + params)
              // 此处 开始正常识别流程
              recog();
              break
            case SpeechConstant.CALLBACK_EVENT_WAKEUP_ERROR:
              //识别唤醒词报错
              addLog("识别唤醒词报错:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_WAKEUP_STOPED:
              //关闭唤醒词
              addLog("关闭唤醒词")
              isStart.value = false;
              break
            case SpeechConstant.CALLBACK_EVENT_WAKEUP_AUDIO:
              //音频回调
              addLog("音频回调:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_READY:
              //引擎准备就绪,可以开始说话
              addLog("引擎准备完成,可以开始说话")
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_BEGIN:
              //检测到用户的已经开始说话
              addLog("检测到用户的已经开始说话")
              isStart.value = true;
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_END:
              //检测到用户的已经停止说话,或者ASR_STOP 输入事件调用后
              addLog("检测到用户的已经停止说话")
              isStart.value = false;
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL:
              //识别结果,识别过程
              addLog("识别过程:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_FINISH:
              //识别结束
              addLog("识别结束:" + params)
              break
            case SpeechConstant.CALLBACK_EVENT_ASR_EXIT:
              //引擎完成整个识别,空闲中
              addLog("引擎完成整个识别,空闲中")
              break
          }
        }
      }
    } as LevenOptions)
  }

  function initRecog() {
    module.init({
      params: {
        appId: KeyUtils.APPID,
        apiKey: KeyUtils.APIKEY,
        secretKey: KeyUtils.SECRETKEY
      },
      complete: (res : LevenResult) => {
        if (res.code == 0) {
          addLog("初始化识别成功")
          //注册监听
          registerListener();
        } else {
          addLog(res.message)
        }
      }
    } as LevenOptions)
  }

  function initSdk() {
    //先初始化命令词
    module.init({
      params: {
        appId: KeyUtils.APPID,
        apiKey: KeyUtils.APIKEY,
        secretKey: KeyUtils.SECRETKEY,
        type: "wp"
      },
      complete: (res : LevenResult) => {
        if (res.code == 0) {
          addLog("初始化命令词成功")
          //初始化识别
          initRecog()
        } else {
          addLog(res.message)
        }
      }
    } as LevenOptions)
  }

  function toggle() {
    if (isStart.value) {
      stop()
    } else {
      start()
    }
  }

  onMounted(() => {
    nextTick(() => {
      //初始化后注册监听
      initSdk()
      console.log(dateuts().valueOf())
    })
  })

  onUnload(() => {
    //页面卸载
    release();
  })
</script>

<style>

</style>
<script setup>

</script>

<style>

</style>

示例项目用到的全局变量

uniapp

js
export const SpeechConstant = {
  VERSION_NAME: "3.4.4.113",
  ASR_START: "asr.start",
  ASR_STOP: "asr.stop",
  ASR_CANCEL: "asr.cancel",
  ASR_CONFIG: "asr.config",
  ASR_KWS_LOAD_ENGINE: "asr.kws.load",
  ASR_KWS_UNLOAD_ENGINE: "asr.kws.unload",
  ASR_UPLOAD_WORDS: "asr.upload.words",
  ASR_UPLOAD_CANCEL: "asr.upload.cancel",
  WAKEUP_START: "wp.start",
  WAKEUP_STOP: "wp.stop",
  WAKEUP_LOAD_ENGINE: "wp.load",
  WAKEUP_UNLOAD_ENGINE: "wp.unload",
  ASR_UPLOAD_CONTRACT: "asr.upload.contract",
  UPLOADER_START: "uploader.start",
  UPLOADER_CANCEL: "uploader.cancel",
  CALLBACK_EVENT_ASR_READY: "asr.ready",
  CALLBACK_EVENT_ASR_BEGIN: "asr.begin",
  CALLBACK_EVENT_ASR_AUDIO: "asr.audio",
  CALLBACK_EVENT_ASR_VOLUME: "asr.volume",
  CALLBACK_EVENT_ASR_END: "asr.end",
  CALLBACK_EVENT_ASR_PARTIAL: "asr.partial",
  CALLBACK_EVENT_ASR_FINISH: "asr.finish",
  CALLBACK_EVENT_ASR_EXIT: "asr.exit",
  CALLBACK_EVENT_ASR_CANCEL: "asr.cancel",
  CALLBACK_EVENT_ASR_ERROR: "asr.error",
  CALLBACK_EVENT_ASR_LOADED: "asr.loaded",
  CALLBACK_EVENT_ASR_UNLOADED: "asr.unloaded",
  CALLBACK_EVENT_ASR_SERIALNUMBER: "asr.sn",
  CALLBACK_EVENT_ASR_LOG: "asr.log",
  CALLBACK_EVENT_UPLOAD_COMPLETE: "asr.upload.complete",
  CALLBACK_EVENT_ASR_LONG_SPEECH: "asr.long-speech.finish",
  ASR_CALLBACk_NAME: "ASR.callback",
  WAKEUP_CALLBACK_NAME: "WAKEUP.callback",
  UPLOAD_CALLBACK_NAME: "UPLOAD.callback",
  CALLBACK_ASR_STATUS: "cb.asr.status.int",
  strCALLBACK_ASR_LEVEL: "cb.asr.level.int",
  CALLBACK_ASR_RESULT: "cb.asr.result.string",
  CALLBACK_WAK_STATUS: "cb.wak.status.int",
  CALLBACK_WAK_RESULT: "cb.wak.result.string",
  CALLBACK_ERROR_DOMAIN: "cb.error.domain.int16_t",
  CALLBACK_ERROR_CODE: "cb.error.code.int16_t",
  CALLBACK_ERROR_DESC: "cb.error.desc.string",
  CALLBACK_EVENT_UNIT_FINISH: "unit.finish",
  SOUND_START: "sound_start",
  SOUND_END: "sound_end",
  SOUND_SUCCESS: "sound_success",
  SOUND_ERROR: "sound_error",
  SOUND_CANCEL: "sound_cancel",
  CALLBACK_EVENT_WAKEUP_STARTED: "wp.enter",
  CALLBACK_EVENT_WAKEUP_READY: "wp.ready",
  CALLBACK_EVENT_WAKEUP_STOPED: "wp.exit",
  CALLBACK_EVENT_WAKEUP_LOADED: "wp.loaded",
  CALLBACK_EVENT_WAKEUP_UNLOADED: "wp.unloaded",
  CALLBACK_EVENT_WAKEUP_ERROR: "wp.error",
  CALLBACK_EVENT_WAKEUP_SUCCESS: "wp.data",
  CALLBACK_EVENT_WAKEUP_AUDIO: "wp.audio",
  CALLBACK_EVENT_UPLOAD_FINISH: "uploader.finish",
  LOG_LEVEL: "log_level",
  LANGUAGE: "language",
  CONTACT: "contact",
  VAD: "vad",
  VAD_MFE: "mfe",
  VAD_MODEL: "model-vad",
  VAD_DNN: "dnn",
  VAD_TOUCH: "touch",
  SAMPLE_RATE: "sample",
  PAM: "decoder-server.pam",
  NLU: "nlu",
  PROP: "prop",
  PUBLIC_DECODER: false,
  IN_FILE: "infile",
  AUDIO_MILLS: "audio.mills",
  AUDIO_SOURCE: "audio.source",
  OUT_FILE: "outfile",
  ACCEPT_AUDIO_DATA: "accept-audio-data",
  ACCEPT_AUDIO_VOLUME: "accept-audio-volume",
  APP_KEY: "key",
  API_KEY: "apikey",
  SECRET: "secret",
  IAM_APIKEY: "iam_apikey",
  ACCESS_TOKEN: "access_token",
  URL: "decoder-server.url",
  PID: "pid",
  LMID: "lm_id",
  APP_NAME: "decoder-server.app",
  URL_NEW: "https://vse.baidu.com/v2",
  URL_OLD: "https://vse.baidu.com/echo.fcgi",
  DEC_TYPE: "dec-type",
  DECODER: "decoder",
  ASR_VAD_RES_FILE_PATH: "vad.res-file",
  VAD_ENDPOINT_TIMEOUT: "vad.endpoint-timeout",
  BDS_ASR_ENABLE_LONG_SPEECH: "enable.long.speech",
  ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH: "grammar",
  ASR_OFFLINE_ENGINE_DAT_FILE_PATH: "asr-base-file-path",
  ASR_OFFLINE_ENGINE_LICENSE_FILE_PATH: "license-file-path",
  SLOT_DATA: "slot-data",
  DISABLE_PUNCTUATION: "disable-punctuation",
  KWS_TYPE: "kws-type",
  APP_ID: "appid",
  APP_SN: "appsn",
  DEV: "dev",
  WP_DAT_FILEPATH: "wakeup_dat_filepath",
  WP_WORDS_FILE: "kws-file",
  WP_WORDS: "words",
  ENABLE_HTTPDNS: "enable-httpdns",
  WP_VAD_ENABLE: "wp.vad_enable",
  WP_ENGINE_LICENSE_FILE_PATH: "license-file-path",
  BOT_SESSION_LIST: "bot_session_list",
  BOT_ID: "bot_id",
  BOT_SESSION: "bot_session",
  BOT_SESSION_ID: "bot_session_id",
  ASR_ENABLE_NUMBERFORMAT: "enable.numberformat",
  ASR_PUNCTUATION_MODE: "punctuation-mode"
}
js
export const KeyUtils = {
  APPID: "120626545",
  SECRETKEY: "7azxFEumSZCUTR7dU0Bv0YnZwyuGIhKA",
  APIKEY: "Jeva58gMRCWfCFu3iQX0Qkfu"
}

uniapp x

js
export const SpeechConstant = {
  VERSION_NAME: "3.4.4.113",
  ASR_START: "asr.start",
  ASR_STOP: "asr.stop",
  ASR_CANCEL: "asr.cancel",
  ASR_CONFIG: "asr.config",
  ASR_KWS_LOAD_ENGINE: "asr.kws.load",
  ASR_KWS_UNLOAD_ENGINE: "asr.kws.unload",
  ASR_UPLOAD_WORDS: "asr.upload.words",
  ASR_UPLOAD_CANCEL: "asr.upload.cancel",
  WAKEUP_START: "wp.start",
  WAKEUP_STOP: "wp.stop",
  WAKEUP_LOAD_ENGINE: "wp.load",
  WAKEUP_UNLOAD_ENGINE: "wp.unload",
  ASR_UPLOAD_CONTRACT: "asr.upload.contract",
  UPLOADER_START: "uploader.start",
  UPLOADER_CANCEL: "uploader.cancel",
  CALLBACK_EVENT_ASR_READY: "asr.ready",
  CALLBACK_EVENT_ASR_BEGIN: "asr.begin",
  CALLBACK_EVENT_ASR_AUDIO: "asr.audio",
  CALLBACK_EVENT_ASR_VOLUME: "asr.volume",
  CALLBACK_EVENT_ASR_END: "asr.end",
  CALLBACK_EVENT_ASR_PARTIAL: "asr.partial",
  CALLBACK_EVENT_ASR_FINISH: "asr.finish",
  CALLBACK_EVENT_ASR_EXIT: "asr.exit",
  CALLBACK_EVENT_ASR_CANCEL: "asr.cancel",
  CALLBACK_EVENT_ASR_ERROR: "asr.error",
  CALLBACK_EVENT_ASR_LOADED: "asr.loaded",
  CALLBACK_EVENT_ASR_UNLOADED: "asr.unloaded",
  CALLBACK_EVENT_ASR_SERIALNUMBER: "asr.sn",
  CALLBACK_EVENT_ASR_LOG: "asr.log",
  CALLBACK_EVENT_UPLOAD_COMPLETE: "asr.upload.complete",
  CALLBACK_EVENT_ASR_LONG_SPEECH: "asr.long-speech.finish",
  ASR_CALLBACk_NAME: "ASR.callback",
  WAKEUP_CALLBACK_NAME: "WAKEUP.callback",
  UPLOAD_CALLBACK_NAME: "UPLOAD.callback",
  CALLBACK_ASR_STATUS: "cb.asr.status.int",
  strCALLBACK_ASR_LEVEL: "cb.asr.level.int",
  CALLBACK_ASR_RESULT: "cb.asr.result.string",
  CALLBACK_WAK_STATUS: "cb.wak.status.int",
  CALLBACK_WAK_RESULT: "cb.wak.result.string",
  CALLBACK_ERROR_DOMAIN: "cb.error.domain.int16_t",
  CALLBACK_ERROR_CODE: "cb.error.code.int16_t",
  CALLBACK_ERROR_DESC: "cb.error.desc.string",
  CALLBACK_EVENT_UNIT_FINISH: "unit.finish",
  SOUND_START: "sound_start",
  SOUND_END: "sound_end",
  SOUND_SUCCESS: "sound_success",
  SOUND_ERROR: "sound_error",
  SOUND_CANCEL: "sound_cancel",
  CALLBACK_EVENT_WAKEUP_STARTED: "wp.enter",
  CALLBACK_EVENT_WAKEUP_READY: "wp.ready",
  CALLBACK_EVENT_WAKEUP_STOPED: "wp.exit",
  CALLBACK_EVENT_WAKEUP_LOADED: "wp.loaded",
  CALLBACK_EVENT_WAKEUP_UNLOADED: "wp.unloaded",
  CALLBACK_EVENT_WAKEUP_ERROR: "wp.error",
  CALLBACK_EVENT_WAKEUP_SUCCESS: "wp.data",
  CALLBACK_EVENT_WAKEUP_AUDIO: "wp.audio",
  CALLBACK_EVENT_UPLOAD_FINISH: "uploader.finish",
  LOG_LEVEL: "log_level",
  LANGUAGE: "language",
  CONTACT: "contact",
  VAD: "vad",
  VAD_MFE: "mfe",
  VAD_MODEL: "model-vad",
  VAD_DNN: "dnn",
  VAD_TOUCH: "touch",
  SAMPLE_RATE: "sample",
  PAM: "decoder-server.pam",
  NLU: "nlu",
  PROP: "prop",
  PUBLIC_DECODER: false,
  IN_FILE: "infile",
  AUDIO_MILLS: "audio.mills",
  AUDIO_SOURCE: "audio.source",
  OUT_FILE: "outfile",
  ACCEPT_AUDIO_DATA: "accept-audio-data",
  ACCEPT_AUDIO_VOLUME: "accept-audio-volume",
  APP_KEY: "key",
  API_KEY: "apikey",
  SECRET: "secret",
  IAM_APIKEY: "iam_apikey",
  ACCESS_TOKEN: "access_token",
  URL: "decoder-server.url",
  PID: "pid",
  LMID: "lm_id",
  APP_NAME: "decoder-server.app",
  URL_NEW: "https://vse.baidu.com/v2",
  URL_OLD: "https://vse.baidu.com/echo.fcgi",
  DEC_TYPE: "dec-type",
  DECODER: "decoder",
  ASR_VAD_RES_FILE_PATH: "vad.res-file",
  VAD_ENDPOINT_TIMEOUT: "vad.endpoint-timeout",
  BDS_ASR_ENABLE_LONG_SPEECH: "enable.long.speech",
  ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH: "grammar",
  ASR_OFFLINE_ENGINE_DAT_FILE_PATH: "asr-base-file-path",
  ASR_OFFLINE_ENGINE_LICENSE_FILE_PATH: "license-file-path",
  SLOT_DATA: "slot-data",
  DISABLE_PUNCTUATION: "disable-punctuation",
  KWS_TYPE: "kws-type",
  APP_ID: "appid",
  APP_SN: "appsn",
  DEV: "dev",
  WP_DAT_FILEPATH: "wakeup_dat_filepath",
  WP_WORDS_FILE: "kws-file",
  WP_WORDS: "words",
  ENABLE_HTTPDNS: "enable-httpdns",
  WP_VAD_ENABLE: "wp.vad_enable",
  WP_ENGINE_LICENSE_FILE_PATH: "license-file-path",
  BOT_SESSION_LIST: "bot_session_list",
  BOT_ID: "bot_id",
  BOT_SESSION: "bot_session",
  BOT_SESSION_ID: "bot_session_id",
  ASR_ENABLE_NUMBERFORMAT: "enable.numberformat",
  ASR_PUNCTUATION_MODE: "punctuation-mode"
}
js
export const KeyUtils = {
  APPID: "120626545",
  SECRETKEY: "7azxFEumSZCUTR7dU0Bv0YnZwyuGIhKA",
  APIKEY: "Jeva58gMRCWfCFu3iQX0Qkfu"
}