场景需求:
点击录音按钮:
- 如没有检测到录音设备,提示:“无法找到麦克风设备,请检查设备连接”。
- 如录音设备连接正常:录音按钮变成录制状态,开始录制声音,同时输入框禁止键盘输入。
再次点击录音按钮或录音时长达到上限(30秒):
录音按钮变成未录音状态,停止录制声音,同时将音频转换成文本,并添加到输入框中,输入框恢复键盘输入功能。(将语音数据以二进制文件form-data格式发送给后端)
代码如下:
isRecording: false, //是否正在录制
mediaRecorder: null,
audioChunks: [],
recordingTimeout: null,
// 点击录音按钮
async toggleRecording() {
if (this.isRecording) {
// 停止录音
this.stopRecording();
} else {
try {
// 请求麦克风访问权限
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
});
// 创建 MediaRecorder 实例
this.mediaRecorder = new MediaRecorder(stream);
this.mediaRecorder.start();
this.isRecording = true;
// 绑定 ondataavailable 事件以收集录音数据
this.mediaRecorder.ondataavailable = (event) => {
if (event.data.size > 0) {
this.audioChunks.push(event.data);
}
};
// 绑定 onstop 事件以在录音停止后收集数据
this.mediaRecorder.onstop = () => {
this.processRecording();
};
// 设置录音时长上限为 30 秒
this.recordingTimeout = setTimeout(() => {
this.stopRecording();
}, 30000);
} catch (e) {
this.$message.error('无法找到麦克风设备,请检查设备连接');
}
}
},
// 点击暂停录音按钮
stopRecording() {
if (this.isRecording) {
this.mediaRecorder.stop();
this.isRecording = false;
clearTimeout(this.recordingTimeout);
}
},
// 处理数据
async processRecording() {
// 停止录音后,将 audioChunks 转换为音频 Blob
const audioBlob = new Blob(this.audioChunks, {
type: 'audio/mp4',
});
let file = new File([audioBlob], 'video.mp4', { type: 'video/mp4' });
const formData = new FormData();
formData.append('file', file);
try {
const response = await axios.post(
`${process.env.VUE_APP_VIDEO}/asr`,
formData,
{
headers: {
'Content-Type': 'multipart/form-data',
},
}
);
//console.log('Upload successful: ' + response.data.result);
this.searchContent = response.data.result;
} catch (error) {
console.log('Upload failed: ' + error.message);
}
// 重置 audioChunks 以备下次使用
this.audioChunks = [];
},
效果图:
遇到的一些坑:
1、在HTTP下navigator.mediaDevices为undefined或媒体设备下的方法报错
需要确保在HTTPS下运行服务,因为大多数现代浏览器要求媒体流只能在安全上下文中使
在vite.config.js中设置https:true
2、服务是在HTTPS下运行的,且设备有麦克风功能,但是还是无法进行语音录制时,需要检查浏览器是否允许该网站使用麦克风功能
3、进行录音后生成的文件大小是0kb,是因为在stopRecording函数中调用处理数据processRecording函数时,此时没有拿到audioChunks,
解决办法:
给mediaRecorder绑定onstop事件,在这个事件中去处理录音数据audioChunks,在这一阶段可以获取到录音数据audioChunks