如何让Flutter的just_audio兼容Amazon Polly驱动的Spring Boot服务?
问题:Flutter just_audio无法播放Spring Boot生成的Polly音频
我正在开发一款Flutter应用,使用just_audio库播放短语音提示。手动通过AWS控制台用Amazon Polly生成MP3并上传到S3后,just_audio可以正常播放,代码如下:
final AudioPlayer audioPlayer = AudioPlayer(); audioPlayer.setUrl('https://bucketname.s3.eu-west-2.amazonaws.com/say_someting.mp3'); audioPlayer.play();
但需要根据运行时动态文本实时生成语音,因此搭建了Java Spring Boot微服务调用Polly并暴露接口。音频时长3秒内、大小约15KB,服务代码如下:
@GetMapping(path = "/mp3", produces = "audio/mpeg") public byte[] getAudio() { // 运行时动态文本 final String whatToSay = "The time is now " + System.currentTimeMillis(); // 构造Polly语音合成请求 final SynthesizeSpeechRequest synthesizeSpeechRequest = new SynthesizeSpeechRequest() .withOutputFormat(OutputFormat.Mp3) .withVoiceId(VoiceId.Amy) .withText(whatToSay); // 可启用SSML控制语调 // synthesizeSpeechRequest.setTextType(TextType.Ssml); final SynthesizeSpeechResult synthesizeSpeechResult = amazonPolly.synthesizeSpeech(synthesizeSpeechRequest); // 将音频流转为字节数组返回 final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); IOUtils.copy(synthesizeSpeechResult.getAudioStream(), outputStream); return outputStream.toByteArray(); }
服务部署到Elastic Beanstalk后,浏览器访问接口能正常播放,下载的MP3也能在Quicktime播放,但just_audio调用时抛出source error异常,代码如下:
final AudioPlayer audioPlayer = AudioPlayer(); audioPlayer.setUrl('https://my-domain/mp3'); audioPlayer.play();
已尝试的排查动作:
- 调试just_audio源码,但异步Future的错误无法追踪
- 尝试设置空请求头调用接口
- 试用flutter_tts但无法控制语调
- 改为流式输出Polly音频,问题仍存在
测试接口响应头:
HTTP/1.1 200 Server: nginx Date: Thu, 08 Feb 2024 07:59:14 GMT Content-Type: audio/mpeg Content-Length: 50043 Connection: keep-alive
解决方案
1. 直接转发Polly原始音频流
just_audio对音频格式校验严格,字节流转换可能丢失关键文件头信息。修改Spring Boot接口,直接将Polly的原始音频流写入响应输出流:
@GetMapping(path = "/mp3", produces = "audio/mpeg") public void getAudio(HttpServletResponse response) throws IOException { String whatToSay = "The time is now " + System.currentTimeMillis(); SynthesizeSpeechRequest request = new SynthesizeSpeechRequest() .withOutputFormat(OutputFormat.Mp3) .withVoiceId(VoiceId.Amy) .withText(whatToSay); SynthesizeSpeechResult result = amazonPolly.synthesizeSpeech(request); InputStream audioStream = result.getAudioStream(); response.setContentType("audio/mpeg"); response.setContentLength((int) result.getContentLength()); IOUtils.copy(audioStream, response.getOutputStream()); response.getOutputStream().flush(); }
2. 为just_audio添加请求头并等待异步操作
部分服务器会限制缺少特定头的请求,且需确保音频加载完成后再播放:
final AudioPlayer audioPlayer = AudioPlayer(); await audioPlayer.setUrl( 'https://my-domain/mp3', headers: { 'Accept': 'audio/mpeg', }, ); await audioPlayer.play();
3. 配置跨域(CORS)
Flutter应用可能存在跨域限制,在Spring Boot中添加CORS配置:
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "POST") .allowedHeaders("*"); } }
也可直接在Controller方法上添加@CrossOrigin(origins = "*")注解。
4. 验证音频格式标准性
下载Spring Boot接口返回的音频,用ffmpeg检查格式是否符合just_audio兼容的MP3标准:
ffmpeg -i downloaded.mp3 -v info
若存在格式问题,可在服务端添加简单转码步骤确保格式合规。
内容的提问来源于stack exchange,提问作者Paul Wells
相关产品推荐
相关产品推荐

