有关app、小程序录音功能替代方案之面对面录音(2)

45 阅读3分钟

面对面录音代码设计以及实现

在上篇中我们介绍了为何当时业务上用到了面对面录音,在实际开发场景中,不同的框架下实现录音功能有着不同的差异与限制。 我们以微信小程序举例,并结合实际项目开发难度、限制等提出了面对面录音需求。接下来看项目具体实现这个业务需求。 效果图如下 在这里插入图片描述

小程序业务代码分析

1、开始录音

<!-- 录音按钮组件 -->
<view class="fun_box" bind:tap="faceToFaceAudioRecord">
  <view class="fun_box_pic">
    <image src="../../images/audio_icon.png" class="aspectFit_icon" mode="aspectFit"/>
  </view>
  <view class="fun_box_tit">录音</view>
</view>

开始录音:faceToFaceAudioRecord函数

  • 首先检查用户权限和算力包是否足够,不足则提示并返回。

  • 设置屏幕常亮。

  • 初始化录音相关的数据,包括状态、临时文件路径、计时等。

  • 设置录音参数,如时长10分钟、采样率16kHz、单声道、比特率48kbps、mp3格式。

const options = {
  duration: 600000, // 10分钟最大时长
  sampleRate: 16000, // 采样率
  numberOfChannels: 1, // 单声道
  encodeBitRate: 48000, // 编码比特率
  format: 'mp3' // 音频格式
}
  • 启动录音管理器,开始计时,并更新界面状态。

2、计时功能

计时功能:startCounting函数

startCounting() {
  this.data.record_timer = setInterval(() => {
    if (this.data.record_times_nums < 14400) { // 4小时限制
      this.setData({
        record_times_nums: this.data.record_times_nums + 1,
        record_times_number: util.toHoursMinutesSeconds(this.data.record_times_nums)
      })
      // 3小时55分时显示提示
      if (this.data.record_times_nums === 14100) {
        this.setData({ show_record_tipstext: true })
      }
    } else {
      this.playUploadAction() // 自动停止录制
    }
  }, 1000)
}
  • 使用setInterval每秒更新计时器。

  • 最多录制4小时(14400秒),在达到3小时55分(14100秒)时显示提示。

  • 达到4小时自动停止录制。

3、停止录音并上传:playUploadAction函数

  • 关闭屏幕常亮。

  • 清除计时器。

  • 监听录音停止事件,将临时文件路径保存到recorder_temp_filepath数组中。

  • 停止录音管理器。

  • 更新状态,然后延迟800毫秒调用uploadRecording函数。

4、上传录音:uploadRecording函数

  • 显示上传中提示。

  • 调用接口获取临时密钥(COS上传所需)。

api.post('xxxxxx', {
  data: { secure: true }
}).then((result) => {
  // 获取COS临时密钥
  const COS = require('./lib/cos-wx-sdk-v5.min.js')
})
  • 使用COS SDK将每个录音临时文件上传到腾讯云对象存储。
cos.uploadFile({
  Bucket: result.bucket,
  Region: result.region,
  Key: FilePath, // 随机生成的文件路径
  FilePath: itempath, // 临时文件路径
  SliceSize: 1024 * 1024 * 5, // 5MB分块大小
  onProgress: function(progressData) {
    console.log('上传进度:', progressData.percent)
  }
})
  • 每个文件上传成功后,获取文件的临时URL。

  • 所有文件上传完成后,使用云函数发起一个音频合并任务(Concat)。

const body = COS.util.json2xml({
  Request: {
    Tag: 'Concat',
    Input: { Object: upload_flie_path[0].fileKey },
    Operation: {
      ConcatTemplate: {
        Container: { Format: 'mp3' },
        ConcatFragment: concatFragment, // 需要合并的片段
        DirectConcat: 'false'
      },
      Output: {
        Region: config.Region,
        Bucket: config.Bucket,
        Object: result.path + '/' + path_name
      }
    }
  }
})
  • 查询合并任务的状态,直到完成或超时。

  • 合并完成后,调用后端接口记录录音文件信息。

5、轮询查询任务状态:catchJobsAction函数

  • 定期查询合并任务的状态,直到任务完成(Success)或失败(Failed)或超时(5分钟)。
catchJobsAction(keyname, pathname, startTime = Date.now()) {
  const MAX_WAIT_TIME = 5 * 60 * 1000 // 5分钟超时限制
  
  // 超时检测
  if (Date.now() - startTime > MAX_WAIT_TIME) {
    console.warn('任务处理超时')
    return
  }
  
  // 5秒后再次检查
  that.data.jobCheckTimer = setTimeout(() => {
    that.catchJobsAction(keyname, pathname, startTime)
  }, 5000)
}
  • 任务成功完成后,调用后端接口记录录音文件,并更新界面状态。

最后,由于项目周期紧张,功能开发完经过测试发布上线,但仍需优化

// 1. 提取常量
const RECORD_CONFIG = {
  MAX_DURATION: 600000, // 10分钟
  SAMPLE_RATE: 16000,
  MAX_WAIT_TIME: 5 * 60 * 1000 // 5分钟
}

// 2. 改进错误处理
async uploadRecording() {
  try {
    // 上传逻辑
  } catch (error) {
    console.error('上传失败:', error)
    app.msg('上传失败,请重试')
    this.resetRecordState()
  }
}

// 3. 添加状态枚举
const RECORD_STATE = {
  IDLE: 'idle',
  RECORDING: 'recording',
  UPLOADING: 'uploading',
  PROCESSING: 'processing'
}

以上就是关于面对面录音从设计到开发再到上线的全部历程,感谢!