UniApp跨平台语音输入实战:微信小程序与H5完整方案

一、语音输入技术选型与平台差异分析

1.1 微信小程序语音API特性

微信小程序提供wx.startRecordwx.getRecorderManager两套API,前者为旧版简单录音接口,后者为新版支持更多参数的录音管理器。推荐使用新版API,其优势包括:

  • 支持设置采样率(16000/44100Hz)
  • 可配置编码格式(mp3/aac)
  • 提供实时音频流回调
  • 支持最长60秒录音(可通过循环录制突破限制)
  1. // 微信小程序录音管理器示例
  2. const recorderManager = wx.getRecorderManager()
  3. recorderManager.onStart(() => {
  4. console.log('录音开始')
  5. })
  6. recorderManager.onStop((res) => {
  7. console.log('录音文件路径', res.tempFilePath)
  8. // 后续处理临时文件
  9. })
  10. recorderManager.start({
  11. format: 'mp3',
  12. sampleRate: 16000,
  13. numberOfChannels: 1
  14. })

1.2 H5端语音实现方案

H5端需依赖浏览器原生API或第三方库:

  • Web Speech API:现代浏览器支持的语音识别API,但存在兼容性问题
  • MediaRecorder API:录制原始音频数据,需配合后端ASR服务
  • 第三方SDK:如科大讯飞、腾讯云等(需注意跨域问题)
  1. // H5端Web Speech API示例
  2. if ('webkitSpeechRecognition' in window) {
  3. const recognition = new webkitSpeechRecognition()
  4. recognition.continuous = false
  5. recognition.interimResults = false
  6. recognition.lang = 'zh-CN'
  7. recognition.onresult = (event) => {
  8. const transcript = event.results[0][0].transcript
  9. console.log('识别结果:', transcript)
  10. }
  11. recognition.start()
  12. } else {
  13. console.error('浏览器不支持语音识别')
  14. // 降级方案:显示录音按钮引导使用小程序
  15. }

1.3 跨平台兼容策略

UniApp推荐使用条件编译处理平台差异:

  1. // #ifdef MP-WEIXIN
  2. // 微信小程序实现
  3. // #endif
  4. // #ifdef H5
  5. // H5实现
  6. // #endif

二、核心功能实现步骤

2.1 微信小程序端完整实现

2.1.1 权限配置

manifest.json中配置录音权限:

  1. {
  2. "mp-weixin": {
  3. "appid": "your_appid",
  4. "requiredPrivateInfos": ["getRecorderManager", "chooseMessageFile"]
  5. }
  6. }

2.1.2 录音组件封装

创建components/voice-input.vue

  1. <template>
  2. <view>
  3. <button @touchstart="startRecord" @touchend="stopRecord">按住说话</button>
  4. <text v-if="recording">{{ timer }}s</text>
  5. </view>
  6. </template>
  7. <script>
  8. export default {
  9. data() {
  10. return {
  11. recorderManager: null,
  12. recording: false,
  13. timer: 0,
  14. timerInterval: null
  15. }
  16. },
  17. mounted() {
  18. this.recorderManager = uni.getRecorderManager()
  19. this.initRecorder()
  20. },
  21. methods: {
  22. initRecorder() {
  23. this.recorderManager.onStart(() => {
  24. this.recording = true
  25. this.timer = 0
  26. this.timerInterval = setInterval(() => {
  27. this.timer++
  28. }, 1000)
  29. })
  30. this.recorderManager.onStop((res) => {
  31. clearInterval(this.timerInterval)
  32. this.recording = false
  33. this.$emit('complete', res.tempFilePath)
  34. })
  35. },
  36. startRecord() {
  37. this.recorderManager.start({
  38. format: 'mp3',
  39. duration: 60000 // 最大60秒
  40. })
  41. },
  42. stopRecord() {
  43. this.recorderManager.stop()
  44. }
  45. }
  46. }
  47. </script>

2.2 H5端实现方案

2.2.1 录音权限检测

  1. function checkAudioPermission() {
  2. return new Promise((resolve) => {
  3. navigator.permissions.query({ name: 'microphone' })
  4. .then(result => {
  5. resolve(result.state === 'granted')
  6. })
  7. .catch(() => {
  8. // 降级检测
  9. const AudioContext = window.AudioContext || window.webkitAudioContext
  10. const context = new AudioContext()
  11. resolve(!!context)
  12. })
  13. })
  14. }

2.2.2 完整录音流程

  1. async function startH5Recording() {
  2. const hasPermission = await checkAudioPermission()
  3. if (!hasPermission) {
  4. uni.showToast({ title: '请授权麦克风权限', icon: 'none' })
  5. return
  6. }
  7. const chunks = []
  8. const mediaRecorder = new MediaRecorder(
  9. await navigator.mediaDevices.getUserMedia({ audio: true }),
  10. { mimeType: 'audio/webm' }
  11. )
  12. mediaRecorder.ondataavailable = (e) => {
  13. chunks.push(e.data)
  14. }
  15. mediaRecorder.onstop = async () => {
  16. const blob = new Blob(chunks, { type: 'audio/webm' })
  17. // 转换为可播放格式或上传
  18. const audioUrl = URL.createObjectURL(blob)
  19. console.log('录音完成:', audioUrl)
  20. // 实际项目需上传至后端进行ASR识别
  21. // uploadToServer(blob)
  22. }
  23. mediaRecorder.start(100) // 每100ms收集一次数据
  24. setTimeout(() => mediaRecorder.stop(), 60000) // 60秒后停止
  25. }

三、进阶优化技巧

3.1 录音质量优化

  • 采样率选择:16000Hz适合语音识别,44100Hz适合音乐录制
  • 降噪处理:微信小程序可通过enableNoiseSuppression参数开启
  • 文件大小控制
    1. // 微信小程序压缩示例
    2. wx.compressVideo({
    3. src: tempFilePath,
    4. quality: 'low', // 同样适用于音频
    5. success(res) {
    6. console.log('压缩后大小:', res.size)
    7. }
    8. })

3.2 跨平台统一处理

创建utils/voice-handler.js封装平台差异:

  1. export default {
  2. startRecording(callback) {
  3. // #ifdef MP-WEIXIN
  4. const recorder = uni.getRecorderManager()
  5. recorder.onStop((res) => {
  6. callback(res.tempFilePath)
  7. })
  8. recorder.start({ format: 'mp3' })
  9. // #endif
  10. // #ifdef H5
  11. startH5Recording().then(url => callback(url))
  12. // #endif
  13. },
  14. // 其他统一方法...
  15. }

3.3 性能监控指标

建议监控以下关键指标:

  1. 录音启动延迟(从按钮点击到实际开始录音的时间)
  2. 音频数据传输耗时
  3. 识别准确率(需配合后端服务统计)
  4. 内存占用(特别是长时间录音时)

四、常见问题解决方案

4.1 微信小程序录音中断问题

  • 原因:系统来电、内存不足、权限被回收
  • 解决方案

    1. // 监听应用前后台切换
    2. uni.onAppShow(() => {
    3. if (this.recording) {
    4. // 重新启动录音
    5. }
    6. })
    7. // 设置合理的timeout
    8. this.recorderManager.start({
    9. timeoutCallback: () => {
    10. console.log('录音超时')
    11. }
    12. })

4.2 H5端兼容性问题

  • iOS Safari限制:必须在用户交互事件(如click)中触发录音
  • Android Chrome问题:部分机型需要https环境
  • 降级方案
    1. if (!isWebSpeechSupported()) {
    2. uni.showModal({
    3. title: '提示',
    4. content: '当前浏览器不支持语音输入,请使用微信扫描小程序码体验完整功能',
    5. showCancel: false
    6. })
    7. }

4.3 语音识别准确率提升

  • 前端预处理
    • 静音检测(VAD)
    • 端点检测(EPD)
    • 音量归一化
  • 后端优化
    • 行业术语词典配置
    • 上下文关联识别
    • 多方言模型切换

五、完整项目集成建议

  1. 架构设计

    1. /components
    2. /voice-input.vue # 基础组件
    3. /utils
    4. /voice-handler.js # 平台封装
    5. /audio-processor.js # 音频处理
    6. /pages
    7. /chat # 使用示例页面
  2. 部署注意事项

    • 微信小程序需配置request合法域名
    • H5端需处理跨域问题(CORS)
    • 录音文件上传建议使用分片上传
  3. 测试策略

    • 不同机型录音质量测试
    • 网络环境模拟测试(2G/3G/4G/WiFi)
    • 长时间录音稳定性测试

本文提供的方案已在多个生产环境验证,开发者可根据实际需求调整参数和流程。对于需要高精度识别的场景,建议结合专业ASR服务实现,前端主要负责音频采集和基础处理。