面对面录音代码设计以及实现
在上篇中我们介绍了为何当时业务上用到了面对面录音,在实际开发场景中,不同的框架下实现录音功能有着不同的差异与限制。
我们以微信小程序举例,并结合实际项目开发难度、限制等提出了面对面录音需求。接下来看项目具体实现这个业务需求。
效果图如下
小程序业务代码分析
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'
}
以上就是关于面对面录音从设计到开发再到上线的全部历程,感谢!