微信小程序同声传译插件接入实战:语音识别功能完整实现指南

功能概述

微信小程序同声传译插件提供了强大的语音识别能力,可以将用户的实时语音转换为文字内容。这个功能特别适合用于聊天输入、语音搜索、语音笔记等场景。

核心实现步骤

1. 插件配置

首先需要在 manifest.json 中配置插件信息:

json 复制代码
{
  "mp-weixin": {
    "plugins": {
      "WechatSI": {
        "version": "插件的版本号",
        "provider": "插件的appId"
      }
    }
  }
}

2. 权限管理

语音功能需要用户授权,我们封装了权限检查方法:

javascript 复制代码
export function authorize(scope) {
  return new Promise((resolve, reject) => {
    uni.getSetting({
      success(res) {
        if (!res.authSetting[scope]) {
          uni.authorize({
            scope: scope,
            success(res) {
              resolve(res)
            },
            fail(err) {
              resolve(err)
              console.log(err.errMsg)
            }
          })
        } else {
          resolve(res)
        }
      }
    })
  })
}

3. 录音状态管理

使用 ref 管理录音的各个状态:

javascript 复制代码
const recordState = ref(-1) // -1 未授权 0 未录音 1 正在录音 2 解析录音
const startTime = ref(0)
const endTime = ref(0)

核心功能实现

初始化语音识别管理器

javascript 复制代码
const plugin = requirePlugin('WechatSI')
const manager = plugin.getRecordRecognitionManager()

// 开始识别回调
manager.onRecognize = function(res) {
  console.log("成功开始识别", res)
}

// 开始录音回调
manager.onStart = function(res) {
  console.log("成功开始录音", res)
}

错误处理机制

完善的错误处理是良好用户体验的关键:

javascript 复制代码
manager.onError = function(res) {
  console.error("error msg", res)
  let error = '微信异常或超时,请重试或手动输入~'
  
  if(recordState.value) {
    if(res.retcode == -30004) {
      error = '声音太小,请重试~'
    }
    if(res.retcode != -30012) {  
      wx.showModal({
        title: '提示',
        content: error,
        showCancel: false
      })
    }
    onMikeEnd()			
  }
  recordState.value = 0
}

录音结束处理

当用户停止录音时,获取识别结果:

javascript 复制代码
manager.onStop = function(res) {
  let text = res.result
  console.log('结束录音,语音内容: ' + text)

  if (!text || text.length == 0) {
    wx.showModal({
      title: '提示',
      content: '听不清楚,请重新说一遍!',
      showCancel: false
    })
    return
  }

  content.value += text
  recordState.value = 0
  
  // 自动发送逻辑
  if(roomStore.$audioAutoSend) {
    uni.$emit("SEND_MESSAGE", {
      speechInput: true
    })
  }
}

用户体验优化

防误触处理

通过时间判断避免用户误触:

javascript 复制代码
function onMikeStart(e) {
  startTime.value = new Date().getTime()
  recordState.value = 1

  setTimeout(function() {
    if (!recordState.value) {
      console.log("时间小于0.5秒,认为误点,不进行录音")
      return
    }
    
    manager.start({
      duration: 30000, // 最长30秒
      lang: 'zh_CN'    // 支持中文识别
    })
  }, 100)
}

录音时长控制

javascript 复制代码
function onMikeEnd() {
  endTime.value = new Date().getTime()
  let time = endTime.value - startTime.value
  
  // 时间太短不处理
  if (time < 500) {
    console.log("时间太短,不调用manager.stop()")
    return
  }
  
  recordState.value = 2
  manager.stop()
}

技术要点总结

  • 权限管理:必须先获取用户授权才能使用录音功能
  • 状态管理:清晰的状态机确保流程正确
  • 错误处理:针对不同错误码提供友好提示
  • 性能优化:防误触、超时控制等细节处理

完整代码

javascript 复制代码
export function useSpeech() {
  const plugin = requirePlugin('WechatSI')
  const manager = plugin.getRecordRecognitionManager()
  
  // 事件监听
  manager.onRecognize = function(res) {
    console.log("成功开始识别", res)
  }
  
  manager.onStart = function(res) {
    console.log("成功开始录音", res)
  }
  
  manager.onError = function(res) {
    console.error("error msg", res)
    let error = '微信异常或超时,请重试或手动输入~'
    if(recordState.value) {
      if(res.retcode == -30004) {
        error = '声音太小,请重试~'
      }
      if(res.retcode != -30012) {  
        wx.showModal({
          title: '提示',
          content: error,
          showCancel: false
        })
      }
      onMikeEnd()			
    }
    recordState.value = 0
  }
  
  manager.onStop = function(res) {
    let text = res.result
    console.log('结束录音,语音内容: ' + text)

    if (!text || text.length == 0) {
      wx.showModal({
        title: '提示',
        content: '听不清楚,请重新说一遍!',
        showCancel: false
      })
      return
    }

    content.value += text
    recordState.value = 0
    
    if(roomStore.$audioAutoSend) {
      uni.$emit("SEND_MESSAGE", {
        speechInput: true
      })
    }
  }

  const recordState = ref(-1)
  const startTime = ref(0)
  const endTime = ref(0)
  const startOver = ref(true)
  const endEnable = ref(true)

  function onMikeStart(e) {
    if (!startOver.value) {
      endEnable.value = false
      return
    } else {
      startOver.value = false
      endEnable.value = true
    }

    startTime.value = new Date().getTime()
    recordState.value = 1

    setTimeout(function() {
      if (!recordState.value) {
        console.log("时间小于0.5秒,认为误点,不进行录音")
        startOver.value = true
        return
      }

      manager.start({
        duration: 30000,
        lang: 'zh_CN'
      })

      startOver.value = true
    }, 100)
  }

  function onMikeEnd() {
    if (!endEnable.value || recordState.value == 2) {
      return
    }

    recordState.value = 2
    endTime.value = new Date().getTime()
    
    let time = endTime.value - startTime.value
    if (time < 500) {
      return
    }

    manager.stop()
  }
  
  return {
    getRecordAuth,
    recordState,
    onMikeStart,
    onMikeEnd
  }
}
相关推荐
Pedro2 分钟前
Flutter - 日志不再裸奔:pd_log 让打印有型、写盘有序
前端·flutter
申阳3 分钟前
Day 3:01. 基于Nuxt开发个人呢博客项目-初始化项目
前端·后端·程序员
三小河8 分钟前
解决 React + SSE 流式输出卡顿:Nginx 关键配置实战
前端·架构·前端框架
玖月晴空17 分钟前
Uniapp 速查文档
前端·微信小程序·uni-app
琉-璃19 分钟前
vue3+ts 任意组件间的通信 mitt的使用
前端·javascript·vue.js
FogLetter37 分钟前
React Fiber 机制:让渲染变得“有礼貌”的魔法
前端·react.js
不想说话的麋鹿44 分钟前
「项目前言」从配置程序员到动手造轮子:我用Vue3+NestJS复刻低代码平台的初衷
前端·程序员·全栈
JunpengHu1 小时前
esri-leaflet介绍
前端
zm4351 小时前
bpmn.js 自定义绘制流程图节点
前端·bpmn-js
小杨梅君1 小时前
探索现代 CSS 色彩:从 HSL 到 OKLCH,打造动态色阶
前端·javascript·css