传统文本转语音的挑战
传统文本转语音API采用请求-响应模式。这要求您在发起合成请求之前收集完整的文本。某机构Polly虽然能在请求后增量式流式返回音频,但瓶颈在于输入端——您必须等到文本完全可用才能开始发送。在由大语言模型驱动的对话应用中,文本是逐令牌生成的,这意味着需要等待整个响应生成完毕才能开始合成。
新功能:双向流式传输
StartSpeechSynthesisStream API 引入了一种根本不同的方法:
- 增量发送文本:文本一旦可用即可流式传输给某机构Polly,无需等待完整句子或段落
- 即时接收音频:实时获取生成的合成音频字节
- 控制合成时机:使用flush配置触发对已缓冲文本的立即合成
- 真正的双工通信:通过单一连接同时发送和接收
关键组件
| 组件 | 方向 | 用途 |
|---|---|---|
| TextEvent | 客户端 → 某机构Polly | 发送待合成的文本 |
| CloseStreamEvent | 客户端 → 某机构Polly | 表示文本输入结束 |
| AudioEvent | 某机构Polly → 客户端 | 接收合成的音频块 |
| StreamClosedEvent | 某机构Polly → 客户端 | 确认流已完成 |
性能基准测试
使用相同输入(7,045个字符、970字的散文,Matthew声音+Generative引擎,MP3输出,24kHz,us-west-2区域)进行对比:
| 指标 | 传统SynthesizeSpeech | 双向流式 | 改进 |
|---|---|---|---|
| 总处理时间 | 115,226 ms (~115秒) | 70,071 ms (~70秒) | 快39% |
| API调用次数 | 27 | 1 | 减少27倍 |
| 发送的句子数 | 27(顺序) | 27(逐词流式) | — |
| 总音频字节 | 2,354,292 | 2,324,636 | — |
技术实现
创建异步Polly客户端
PollyAsyncClient pollyClient = PollyAsyncClient.builder()
.region(Region.US_WEST_2)
.credentialsProvider(DefaultCredentialsProvider.create())
.build();
StartSpeechSynthesisStreamRequest request = StartSpeechSynthesisStreamRequest.builder()
.voiceId(VoiceId.JOANNA)
.engine(Engine.GENERATIVE)
.outputFormat(OutputFormat.MP3)
.sampleRate("24000")
.build();
发送文本事件
TextEvent textEvent = TextEvent.builder()
.text("Hello, this is streaming text-to-speech!")
.build();
处理音频事件
StartSpeechSynthesisStreamResponseHandler responseHandler =
StartSpeechSynthesisStreamResponseHandler.builder()
.onResponse(response -> System.out.println("Stream connected"))
.onError(error -> handleError(error))
.subscriber(StartSpeechSynthesisStreamResponseHandler.Visitor.builder()
.onAudioEvent(audioEvent -> {
byte[] audioData = audioEvent.audioChunk().asByteArray();
playOrBufferAudio(audioData);
})
.onStreamClosedEvent(event -> {
System.out.println("Synthesis complete. Characters processed: "
+ event.requestCharacters());
})
.build())
.build();
LLM流式集成模式
// 启动Polly流
pollyStreamer.startStream(VoiceId.JOANNA, audioPlayer::playChunk);
// 当LLM生成令牌时...
llmClient.streamCompletion(prompt, token -> {
boolean isSentenceEnd = token.endsWith(".") || token.endsWith("!") || token.endsWith("?");
pollyStreamer.sendText(token, isSentenceEnd);
});
// LLM完成时
pollyStreamer.closeStream();
业务收益
改善用户体验:音频在LLM仍在生成时就开始播放,掩盖了后端处理时间。更快速、响应更及时的交互可提高用户留存率和满意度。
降低运营成本:
| 成本因素 | 传统分块方法 | 双向流式 |
|---|---|---|
| 基础设施 | WebSocket服务器、负载均衡器、分块中间件 | 客户端直连某机构Polly |
| 开发工作 | 自定义分块逻辑、音频重组、错误处理 | SDK处理复杂性 |
| 维护成本 | 多个组件需要监控和更新 | 单一集成点 |
| API调用 | 每个请求多次调用(每块一次) | 单个流会话 |
推荐使用场景
- 对话式AI助手 – 将LLM响应直接流式合成语音
- 实时翻译 – 在生成翻译文本的同时进行合成
- 交互式语音应答 – 动态响应的电话系统
- 无障碍工具 – 实时屏幕阅读器和文本转语音
- 游戏 – 动态NPC对话和旁白
- 实时字幕 – 实时转录系统的音频输出FINISHED