Vue.js集成AWS Polly文本转语音报错:无支持音源,求解决
修复Vue.js + AWS Polly文本转语音的音频播放错误
你遇到的DOMException: Failed to load because no supported source was found错误,核心原因是AWS SDK v3返回的AudioStream是ReadableStream类型,不是直接可用的二进制数据,直接将其传入Blob会生成损坏的音频文件,导致浏览器无法识别。
修复步骤:
转换ReadableStream为ArrayBuffer
AWS SDK v3的AudioStream提供了transformToByteArray()方法,可以直接将流转换为字节数组,这是最简便的处理方式。修正Blob创建与音频播放逻辑
使用转换后的字节数组创建Blob,同时处理浏览器自动播放限制(部分浏览器会阻止未触发用户交互的自动播放)。
完整修正代码:
<template> <div> <textarea v-model="textToSpeak" rows="4" cols="50"></textarea> <button @click="synthesizeSpeech">合成语音</button> <audio ref="audioPlayer" controls @ended="cleanUpAudio"></audio> </div> </template> <script> import { Polly, SynthesizeSpeechCommand } from "@aws-sdk/client-polly"; export default { data() { return { textToSpeak: "hello world", audioUrl: null }; }, methods: { async synthesizeSpeech() { const accessKeyId = "YOUR_ACCESS_KEY_ID"; const secretAccessKey = "YOUR_SECRET_ACCESS_KEY"; const region = "us-east-1"; const pollyClient = new Polly({ region: region, credentials: { accessKeyId: accessKeyId, secretAccessKey: secretAccessKey, }, }); try { const response = await pollyClient.send( new SynthesizeSpeechCommand({ OutputFormat: "mp3", Text: this.textToSpeak, VoiceId: "Joanna", }) ); // 关键修复:将ReadableStream转换为字节数组 const audioBytes = await response.AudioStream.transformToByteArray(); const audioBlob = new Blob([audioBytes], { type: "audio/mpeg" }); this.audioUrl = URL.createObjectURL(audioBlob); this.$refs.audioPlayer.src = this.audioUrl; // 处理自动播放限制:尝试播放,失败则让用户手动点击控件 try { await this.$refs.audioPlayer.play(); } catch (playError) { console.warn("自动播放被浏览器阻止,请手动点击播放按钮", playError); } } catch (error) { console.error("合成语音出错:", error); } }, cleanUpAudio() { // 清理URL对象,避免内存泄漏 if (this.audioUrl) { URL.revokeObjectURL(this.audioUrl); this.audioUrl = null; } } }, beforeUnmount() { // 组件卸载时清理资源 this.cleanUpAudio(); } }; </script>
额外注意事项:
- 不要硬编码密钥:生产环境中绝对不能直接写死AWS密钥,应该通过环境变量、后端代理或者AWS Cognito等方式安全传递凭证。
- 内存泄漏防护:每次生成音频URL后,在播放结束或组件卸载时调用
URL.revokeObjectURL()释放资源。 - 自动播放限制:现代浏览器大多限制无用户交互的自动播放,所以代码中添加了try-catch处理,提示用户手动播放。
内容的提问来源于stack exchange,提问作者DailyCodeer
相关产品推荐
相关产品推荐

