如何在 Amazon SageMaker AI 上用 Kokoro TTS 为 AI 智能体流式输出低延迟语音
发生了什么
AWS 机器学习博客发布一篇实施教程,针对语音智能体的一个具体延迟来源:文本转语音集成通常等智能体把整段回答生成完才开始合成,用户在这段时间里听不到任何声音。
方案是把智能体逐句产出的文本立即送入托管在 Amazon SageMaker AI 实时端点上的 Kokoro-82M 语音合成模型。该模型有 8200 万参数,运行在 ml.g5.xlarge GPU 实例的自定义容器中,容器暴露两个路由:POST /invocations 处理单次完整输入,WS /invocations-bidirectional-stream 在一条连接上双向收发多条消息。
教程按步骤给出实现要点:容器需显式接受二进制 WebSocket 帧,否则 receive_text() 会抛 KeyError;一条消息合成完成后不要关闭会话,只在客户端发送 close 消息时关闭;客户端用 IncrementalSentenceChunker 把完整字符串或流式 token 统一切成完整句子。作者说明这不是并发合成,双向处理是严格串行循环,收益仅在于第一句一出现就开始合成。
实测数据
作者在实时端点上用同一段 267 字符、四句话的文本做五轮对照:整段发送与只发首句相比,首音频字节平均时间从 329.3 毫秒降到 156.7 毫秒,相对改善 52.4%,这一组只隔离语音合成传输本身。
端到端测试用同一提示词分别走双向与批量两条路径,同一 Bedrock 模型和端点,唯一变量是合成启动时机。双向模式首音频时间在本地容器上比批量模式快 2.4 倍,部署到 AgentCore 运行时后快 3.5 倍。作者解释,部署环境多一跳网络后差距反而扩大,因为双向模式把网络开销藏进生成与合成的重叠里,批量模式只能串行等待。
两种音频回传方式
面向浏览器的回传,文章比较了两条路。沿用现有 SSE 管道时,音频需 base64 编码后包进 JSON 事件,作者在 24 段音频上测得载荷增大约 33%,并用 Amazon Transcribe 确认不同编码下质量无差异;此外 SSE 事件以空行分隔、音频以 MP3 帧分隔,两套边界不一定对齐,实测一次响应中四个逻辑 MP3 帧被拆成六个传输块,其中两个在帧中间断开,消费端必须缓冲到分隔符出现再处理。
另一条路是在同一条双向会话上多路复用原始二进制音频与 JSON 控制帧,靠整块能否解析为 JSON 对象来区分,作者指出原始 PCM 音频可能以 0x7b 开头,但整块解析成功的概率极低。文章的建议是:已有 SSE 文本管道就从 base64 起步,新建语音链路或延迟优先则用统一传输。
编辑部观察
这篇教程的价值在于把延迟拆成可分别测量的两段:合成启动时机和音频回传编码,并各自给出对照数字。需要注意适用条件:作者明确说明双向处理是串行循环,句子之间没有并发合成,收益取决于首句与末句之间真实的生成间隔;2.4 倍与 3.5 倍是同一提示词、同一模型下的相对值,不是绝对延迟承诺。
实践建议
准备复用的团队可以先核查三点:容器是否显式处理二进制帧,否则会出现端点显示 InService 但每个请求都报错的假象;会话是否在单条消息后被提前关闭;流式文本结尾没有标点时是否调用了 flush 释放残余句子。另外原文提示示例容器固定了较旧版本的 PyTorch,存在已知安全公告 PYSEC-2026-2286,在非验证性用途前应先升级。清理资源时,agent-infra destroy 与 speech-infra destroy 不会清空缓存模型权重的 S3 桶,也不会删除存放容器镜像的 ECR 仓库,需要手动处理。

