AWS Predictions语音转文本:浏览器录音后续音频解码失败
问题分析与解决方案
核心问题
- 重复创建AudioContext:每次调用
convertAudio都新建AudioContext实例,浏览器对这类音频上下文实例的数量有限制,多次创建会导致后续解码失败。 - MediaRecorder片段无完整文件头:调用
recorder.start(500)会每隔500ms触发ondataavailable,但这些片段是不完整的音频数据(缺少文件头信息),decodeAudioData无法解析这类片段。 - 媒体流未正确管理:每次录制未释放之前的媒体流轨道,可能导致资源泄漏;同时
device.value存储的是Promise而非媒体流对象,代码逻辑存在冗余。 - 编码格式不匹配:MediaRecorder默认编码格式可能不被AWS Transcription或
decodeAudioData兼容,需要指定明确的、双方支持的格式。
修复后的代码
// initialize refs const isRecording = ref(false) const mediaStream = ref(null) const recorder = ref(null) const audioChunks = ref([]) // 复用单个AudioContext实例 const audioContext = ref(new AudioContext()) async function recordAudio() { if (isRecording.value) return isRecording.value = true audioChunks.value = [] // 正确获取媒体流并存储 mediaStream.value = await navigator.mediaDevices.getUserMedia({ audio: true }) // 指定兼容的编码格式,优先选择AWS支持的wav/mp3 const mimeType = 'audio/wav' // 或尝试 'audio/mp3'(需浏览器支持) recorder.value = new MediaRecorder(mediaStream.value, { mimeType }) recorder.value.ondataavailable = (e) => { if (e.data.size > 0) { audioChunks.value.push(e.data) } } // 录制结束后统一处理音频 recorder.value.onstop = async () => { await convertAudio(audioChunks.value) // 释放媒体流轨道 mediaStream.value.getTracks().forEach(track => track.stop()) mediaStream.value = null } recorder.value.start() } // called on stop-button click async function stop() { if (!isRecording.value || !recorder.value) return recorder.value.stop() isRecording.value = false } async function convertAudio(chunks) { const audioBlob = new Blob(chunks, { type: recorder.value.mimeType }) const audioBuffer = await audioBlob.arrayBuffer() try { // 使用Promise形式的decodeAudioData,便于错误捕获 const res = await audioContext.value.decodeAudioData(audioBuffer) const output = res.getChannelData(0) const result = await Predictions.convert({ transcription: { source: { bytes: output }, language: 'de-DE' } }) console.log({ fullText: result.transcription.fullText }) } catch (err) { console.error('音频解码或转录失败:', err) } }
关键修改说明
- 复用AudioContext:全局创建一个
audioContext实例,避免重复创建导致的浏览器限制问题。 - 收集完整音频片段:在
ondataavailable中收集所有音频块,直到录制停止后再统一处理,确保音频数据完整(带文件头)。 - 指定编码格式:明确设置
MediaRecorder的mimeType为AWS Transcription支持的格式(如audio/wav),保证解码和转录兼容性。 - 正确管理媒体流:录制停止后主动停止媒体流的所有轨道,释放资源;同时修正媒体流的存储方式,直接存储流对象而非Promise。
- Promise化解码逻辑:使用
await audioContext.value.decodeAudioData(audioBuffer)替代回调,更直观处理错误。
内容的提问来源于stack exchange,提问作者DontEatMyCookies
相关产品推荐
相关产品推荐

