JavaScript中MediaRecorder调用stop后未触发dataavailable事件的问题求助
JavaScript中MediaRecorder调用stop后未触发dataavailable事件的问题求助
我看到你遇到了MediaRecorder的dataavailable事件在调用stop()后没有触发(或触发后数据丢失)的问题,让我帮你分析代码里的问题并给出修复方案。
代码核心问题分析
dataavailable事件内的逻辑颠倒:你在事件回调第一行就执行audioChunks = [],这会导致每次事件触发时先清空数组,再push新数据,完全破坏了音频片段的积累逻辑。- stop按钮的同步清空操作:
media_recorder.stop()是异步触发dataavailable事件的,但你在调用stop()后立刻执行audioChunks = [],这会把事件里刚push的音频数据直接清空,让你误以为事件没触发。 - 日志输出可读性差:你的
demo.innerHTML拼接没有换行,所有内容挤在一起,很难直观跟踪代码执行流程。
修复后的完整代码
var demo = document.getElementById("demo") const startButton = document.getElementById('start'); const stopButton = document.getElementById('stop'); let media_recorder let audioChunks = [] navigator.mediaDevices.getUserMedia({ audio: true }) .then(stream => { demo.innerHTML += "已获取麦克风权限<br>"; media_recorder = new MediaRecorder(stream); // 修正dataavailable事件逻辑:只积累音频数据,不在此清空数组 media_recorder.addEventListener('dataavailable', e => { audioChunks.push(e.data); demo.innerHTML += "dataavailable事件已触发,已收集音频片段<br>"; // 当MediaRecorder状态变为inactive时,说明录制完全停止,可处理音频 if (media_recorder.state === 'inactive') { const audioBlob = new Blob(audioChunks, { type: 'audio/webm' }); const audioUrl = URL.createObjectURL(audioBlob); // 这里可添加播放、上传等业务逻辑 const audioPlayer = new Audio(audioUrl); audioPlayer.play(); demo.innerHTML += "录制完成!正在播放音频...<br>"; // 播放结束后释放URL,避免内存泄漏 audioPlayer.onended = () => { URL.revokeObjectURL(audioUrl); demo.innerHTML += "音频播放完毕,已释放资源<br>"; }; } }); startButton.addEventListener('click', () => { audioChunks = []; // 开始新录制前清空数组 media_recorder.start(); demo.innerHTML += 'Recording started! Speak now.<br>'; }); stopButton.onclick = () => { media_recorder.stop(); demo.innerHTML += "已发送停止录制请求<br>"; demo.innerHTML += "Recording stopped!<br>"; // 移除此处的audioChunks = [],避免清空异步收集的音频数据 }; }).catch (err => { demo.innerHTML += `获取麦克风权限失败:${err.message}<br>`; })
关键修复点说明
- 调整
dataavailable事件逻辑:移除事件内的数组清空操作,只负责积累音频片段;通过media_recorder.state === 'inactive'判断录制完全结束,此时再执行音频播放、上传等后续逻辑。 - 数组清空时机迁移:将
audioChunks = []移到start按钮的点击事件中,确保每次新录制都从空数组开始积累数据。 - 移除stop事件内的数组清空:
stop()触发的dataavailable是异步事件,同步清空会直接丢失刚收集到的音频数据,这是你误以为事件没触发的核心原因。 - 优化日志可读性:添加
<br>标签让日志内容换行,方便你清晰跟踪代码执行和事件触发流程。
现在你可以测试修复后的代码,点击开始录制后说话,再点击停止,就能看到dataavailable事件触发的日志,并且正常播放录制的音频了。
备注:内容来源于stack exchange,提问作者marco
相关产品推荐
相关产品推荐

