小程序中使用onFrameRecorded实时显示波形

本文介绍在小程序环境中使用MP3格式进行录音,并通过js-mp3库解码MP3帧为PCM数据,进而计算音频分贝大小的过程。讨论了遇到的问题,如帧缓冲区设置不当、采样率问题及计算效率低下等,并提供了代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

onFrameRecorded 传过来的是MP3帧,但是,这个帧有的时候是不完整的帧,好像是小程序的性能问题或者之类的其他问题。

使用js-mp3,把MP3帧解码成PCM数据,然后再按照pcm数据,来计算分贝数。

踩坑的地方:

1.famebuffer设置的太小,造成传过来的arrayBuffer里面没有一个完整的mp3帧,结果就是Decode失败。以为是小程序的黑箱问题。

2.js-mp3声称自己不支持mpeg2,感觉心里凉了半截,后来“高坚果”给了一个表格:

原来是采样率设置问题,修改为44.1khz采样率,搞定。

3.“高坚果”提供的Recoder里面的源码是使用getChannelData来计算的,里面返回的是一个Float16Array,但是js-mp3解码出来的pcm,如果转换成Float16Array,会有很多NaN,所以没有使用Recoder里面计算分贝大小的方法。但是这个计算方法是仓促写出来的,所以问题多多,已知问题:会出现突然100的情况;并不是对所有声音都敏感。

4.效率很差。因为中间经过了mp3压缩,然后再解码,再判断分贝大小,所以,效率真的很差。

代码摘抄如下:

recordTest: function () {
    var ctx = wx.createCanvasContext("firstCanvas")
    ctx.draw();
    var curr_index = 0;
    var reclength = 30; //录音30秒
    var step = reclength / app.globalData.windowWidth;
    var startTime = new Date();
    var powerArr = [];
    var ctx_height = 200;

    var rm = wx.getRecorderManager()
    rm.onFrameRecorded((res) => {
      const { frameBuffer } = res
      var decoder = Mp3.newDecoder(frameBuffer)
      if (decoder != null) {
        var pcmArrayBuffer = decoder.decode()
        var pcmArr = new Int16Array(pcmArrayBuffer)
        var size = pcmArr.length

        var sum = 0;
        for (var i = 0; i < size; i++) {
          sum += Math.abs(pcmArr[i]);
        }
        var powerLevel = sum * 500.0 / (size * 16383);
        if (powerLevel >= 100) {
          powerLevel = 100
        }
        if (powerLevel <= 5) {
          powerLevel = 2
        }

        powerLevel = parseInt(powerLevel)
        if(powerArr[curr_index] * 2 < powerLevel && powerLevel == 100)
        {
          powerLevel = powerArr[curr_index]
        }
        var bufferDuration = (new Date() - startTime) / 1000; //计算开始了多少秒了
        while (bufferDuration > curr_index * step)  //每次循环进来不止前进一次
        {
          powerArr[curr_index] = powerLevel
          curr_index++
          ctx.setFillStyle("#6E6FAC")
          var curr_height = powerLevel / 100 * ctx_height
          var curr_y = (ctx_height - curr_height) / 2
          ctx.fillRect(curr_index, curr_y, 1, curr_height)
          ctx.draw(true)
        }
      }
    })
    rm.onStart(() => {
      console.log('recorder start')
      this.setData({buttonText: "录音中"})
    })
    rm.onPause(() => {
      console.log('recorder pause')
      console.log(farms);
    })
    rm.onStop((res) => {
      this.setData({buttonText: "录音结束"})
      console.log('recorder stop', res)
      console.log("curr_index:" + curr_index)
      const { tempFilePath } = res

      const fs = wx.getFileSystemManager()
      // // 从临时文件中读取音频
      fs.readFile({
        filePath: tempFilePath,
        success(res) {
          var decoder = Mp3.newDecoder(res.data)
          if (decoder == null) {
            console.log("decoder error")
          }
          else {
            console.log("decode ok")
            var pcmArrayBuffer = decoder.decode()
            console.log(pcmArrayBuffer)
          }
        },
        fail(e) {
          console.log('read fail')
          console.log(e)
        }
      })

    })
    const options = {
      duration: 30000,
      sampleRate: 44100,
      numberOfChannels: 1,
      encodeBitRate: 64000,
      format: 'mp3',
      frameSize: 1
    }
    rm.start(options)
  }

 

pcm计算分贝大小:https://www.jianshu.com/p/d3745dd23056

js-mp3:https://github.com/soundbus-technologies/js-mp3

<think>好的,我现在需要帮助用户解决在微信小程序中实现实时语音转文字的问题。首先,我需要回顾用户提供的引用内容,看看有什么已有的信息可以利用。 用户提到了引用[1]中的配置权限和录音组件,引用[2]中的录音结束回调获取临时路径,以及引用[3]中的音频格式转换步骤。用户现在想要实时转换,而不仅仅是录音结束后处理。这可能意味着需要边录音边转换,而不是等整个录音完成。 微信小程序的录音API是否支持实时获取音频流呢?根据现有的资料,微信的录音组件通常是录制完成后触发回调,所以可能不支持实时的流式处理。不过,我需要确认这一点。如果API不支持实时流,可能需要采用其他方法,比如分片录音,然后分段上传和处理。 接下来,用户需要将音频转换为文字。微信的语音识别API是否支持实时流式识别?根据现有的信息,微信的语音识别可能需要在录音结束后上传整个文件。这时候可能需要第三方服务,比如腾讯云或阿里云的实时语音识别服务,这些服务通常支持流式传输,可以实时返回识别结果。 然后,考虑音频格式的问题。引用[3]中提到需要将PCM文件转换为特定格式,比如16000采样率。实时处理中,可能需要在录音的同时进行格式转换,或者使用支持不同格式的API。 另外,权限配置和录音组件的使用是基础,用户已经知道如何配置,但实时处理可能需要更频繁地调用API,或者使用不同的组件。例如,分片录音,每次录制一小段,然后立即处理,再继续下一段,以实现“实时”的效果。 还需要考虑性能问题,频繁的录音和处理可能会影响小程序运行,需要优化代码,避免卡顿。同时,网络延迟也是一个问题,如果使用云端API,实时性可能受网络状况影响。 总结步骤可能包括:配置权限,使用录音组件分片录制,实时或分段上传音频到识别服务,处理返回的文字,并显示在界面上。如果使用腾讯云,需要集成其SDK,处理鉴权和数据传输。 最后,需要提醒用户注意隐私和合规问题,确保获得用户授权,并遵守相关法律法规。</think>要在微信小程序中实现实时语音转文字功能,可以结合微信原生API和第三方云服务实现。以下是分步解决方案: ### 一、基础配置 1. 添加录音权限 在`app.json`中配置: ```json "permission": { "recorder": { "desc": "用于实时语音输入" } } ``` 2. 创建录音管理器 ```javascript const recorderManager = wx.getRecorderManager(); const innerAudioContext = wx.createInnerAudioContext(); ``` ### 二、实时录音处理 ```javascript // 开始录音时设置分片参数 recorderManager.start({ format: 'PCM', sampleRate: 16000, // 必须与识别接口要求一致[^3] numberOfChannels: 1, frameSize: 1280 // 每帧数据大小 }); // 实时获取音频帧 recorderManager.onFrameRecorded((res) => { const { frameBuffer } = res; // 此处发送帧数据到识别服务[^2] wx.request({ url: '第三方识别API地址', data: frameBuffer, success: (res) => { console.log('识别结果:', res.data.text) } }); }); ``` ### 三、推荐实现方案 1. **微信原生方案**(非完全实时): - 使用`RecorderManager`分段录音 - 每次录制1-2秒后自动提交识别 - 通过`onRecordEnd`获取完整录音文件[^1] 2. **腾讯云实时ASR**(推荐真实时): ```javascript // 初始化WebSocket连接 const socket = wx.connectSocket({ url: 'wss://asr.cloud.tencent.com/stream/asr' }); // 发送音频流 recorderManager.onFrameRecorded((res) => { wx.sendSocketMessage({ data: res.frameBuffer }); }); // 接收识别结果 socket.onMessage((res) => { console.log('实时结果:', JSON.parse(res.data).result); }); ``` ### 四、音频格式处理 实时转换需注意: 1. 采样率必须保持16000Hz 2. 单声道录制 3. PCM编码建议使用16bit位深 4. 需要Base64编码传输 ### 五、注意事项 1. 实时识别延迟应控制在300ms以内 2. 需处理网络中断重连机制 3. 必须添加麦克风使用说明 4. 建议添加可视化波形反馈
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值