IOS录音末尾被截断 / 录音API 在IOS和Android的不同表现及解决方法
发布于 4 年前 作者 leixiang 2528 次浏览 来自 分享

前言

最近项目有一个录音功能 之前就有人反馈录音的结尾总是被截断 但是当时开发周期比较紧张 现在回过头来详细测试了几个机型的实际情况 在两个平台上 确实有表现不一直的地方 导致录音结尾被截断

现象

测试机型:
安卓端:MI 8 SE/ MI 9
IOS端:iphone7/iphone8P

录音相关API:RecorderManager
https://developers.weixin.qq.com/miniprogram/dev/api/media/recorder/RecorderManager.html

假如我们需要录一段固定5秒时长的音频

wxml代码:


<button ontap="record">{{str}}button>

<view style=“height:30rpx;width:100%;”>view> <button ontap=“play”>播放录音button>

js代码

const app = getApp()
const recorderManager = wx.getRecorderManager();
const InnerAudioContext = wx.createInnerAudioContext();
InnerAudioContext.autoplay = false;
var gettimestamp = function(){
  return Math.ceil(new Date().getTime());//获取当前时间戳
}
Page({
  data: {
    str:"开始录音",
    src:false,
  },
  record(){
    if(this.lock){
      console.log('recording')
      return;
    }
    this.lock = true;
    recorderManager.onStart(()=>{
      this.timestamp2 = gettimestamp();//recorderManager系统提供的开始录音时间点
      this.setData({
        str:"正在录音..."
      })
      //业务及页面表现相关代码
    })
    recorderManager.onStop((res)=>{
      //业务及页面表现相关代码
      this.lock = false;
      this.setData({
        str:"录音完毕 重新录音"
      })
      InnerAudioContext.src=res.tempFilePath;
      console.log( '从点击录音按钮的时间点到现在经过时间:', gettimestamp() - this.timestamp1 )
      console.log( '从开始录音回调事件时间点到现在经过时间:', gettimestamp() - this.timestamp2 )
    })

    this.timestamp1 = gettimestamp();//点击录音按钮的时间点
    recorderManager.start({
      format: "wav",
      duration: 5*1000,
    })

  },
  play(){
    if(!this.data.src){
      wx.showToast({
        icon:"none",
        title: '还未录音',
      })
      return;
    }
    InnerAudioContext.play();
  }
})

代码片段:https://developers.weixin.qq.com/s/EXMrulmW7Rji

这时候运行代码 我们看到控制台打印结果 从点击录音按钮的时间点到现在经过时间从开始录音回调事件时间点到现在经过时间 不同 这一点在IOS上和安卓上有明显差异
IOS上的时间差 要比 安卓上大得多!而且从 从开始录音回调事件时间点到现在经过时间 与 我们设置的5秒并不是完全一致的 这个时间间隔总会大于5秒 而且视设备而定 性能越差的设备 多出的时间间隔越长
另外 我们可以刻意在开头和结尾说不同的内容 会发现安卓和IOS的表现不一致 IOS的结尾被截断了 按钮的文字变化也要慢一些 其实在文字变成 录音结束之前 设备录音就已经结束了
也就是说 在IOS设备上 使用 recorderManager.start()duration 属性 会截断一部分录音 实际录音文件会小于5秒 那怎么办呢?

对IOS兼容

我们开始根据平台改良我们的代码 不设置 recorderManager.start()duration 字段 使其为默认值 在 recorderManager.onStart() 通过延时5秒使用 recorderManager.stop() 来结束音频录音
这时候 recorderManager.onStop() 会捕获结束音频事件

改造后的record方法:

record(){
    if(this.lock){
      console.log('recording')
      return;
    }
    this.lock = true;
    recorderManager.onStart(()=>{
      //业务及页面表现相关代码
      this.timestamp2 = gettimestamp();//recorderManager系统提供的开始录音时间点
      this.setData({
        str:"正在录音..."
      })
      this.settimeout = setTimeout(()=>{
        let stopaction = setTimeout(() => { 
          recorderManager.stop();
          clearTimeout(stopaction)
        }, 5*1000)
      })
    })
    recorderManager.onStop((res)=>{
      //业务及页面表现相关代码
      this.lock = false;
      this.setData({
        str:"录音完毕 重新录音"
      })
      InnerAudioContext.src=res.tempFilePath;
      console.log( '从点击录音按钮的时间点到现在经过时间:', gettimestamp() - this.timestamp1 )
      console.log( '开始录音回调事件时间点到现在经过时间:', gettimestamp() - this.timestamp2 )
    })

    this.timestamp1 = gettimestamp();//点击录音按钮的时间点
    
    recorderManager.start({
      format: "wav",
    })

  },

代码片段:https://developers.weixin.qq.com/s/Z8NI1lmz7Sjx

测试改造后的代码 在IOS好了 顺利的录到了结尾
但是! 可但是! 但可是!IOS的结尾补上了 安卓这边又出问题了 安卓这边明显多出了那段时间间隔 这段时间和IOS那边补上的正好相同 真是拆了东墙补西墙

没办法只能上终极手段了 通过判断平台 对两个平台做兼容

最终解决方案

通过 wx.getSystemInfoSync() 获取设备所属的平台 改造record方法

record(){
    let systemparams = wx.getSystemInfoSync();
    if(this.lock){
      console.log('recording')
      return;
    }
    this.lock = true;
    recorderManager.onStart(()=>{
      //业务及页面表现相关代码
      this.timestamp2 = gettimestamp();//recorderManager系统提供的开始录音时间点
      this.setData({
        str:"正在录音..."
      })
      if (systemparams.platform == 'ios') {
        let stopaction = setTimeout(() => { 
          recorderManager.stop();
          clearTimeout(stopaction)
        }, 5*1000)
      }
    })
    recorderManager.onStop((res)=>{
      //业务及页面表现相关代码
      this.lock = false;
      this.setData({
        str:"录音完毕 重新录音"
      })
      InnerAudioContext.src=res.tempFilePath;
      console.log( '从点击录音按钮的时间点到现在经过时间:', gettimestamp() - this.timestamp1 )
      console.log( '开始录音回调事件时间点到现在经过时间:', gettimestamp() - this.timestamp2 )
    })

    this.timestamp1 = gettimestamp();//点击录音按钮的时间点
    
    if (systemparams.platform == 'ios') {
      recorderManager.start({
        format: "wav",
      });
    } else { 
      recorderManager.start({
        format: "wav",
        duration: 1000 * 5
      });
    }
  },

代码片段:https://developers.weixin.qq.com/s/XNOizlm87pj8

注意

上面是录一段定长的音频 如果是要录制不定时长的需求 只需兼容安卓端的情况即可 倘若不在乎安卓端结尾多出的部分 其实也不影响实际效果

结语

归根结底 两个平台上出现差异的原因主要是两个平台行对API的封装方法不同 也可能因为两个平台提供的API存在限制不能达到一致的效果
如果有其他建议 或 demo中出现问题 欢迎指正
以上是关于录音功能在两个平台的差异及解决方法 觉得不错点个赞吧

回到顶部