Skip to content

feat: 新增消息语音播放功能 #108

Description

@juzi050

背景

现有 Chat 仅支持文本回复,希望为 assistant 消息增加语音播放能力,使用户可以直接播放回复内容。

预期交互效果如下:

消息语音播放示意

即在 assistant 消息操作区增加语音播放入口,用户点击后即可播放当前回复内容。

核心功能

  • assistant 回复支持点击播放语音,并可随时停止
  • 全局同一时间仅播放一条消息,新播放自动停止上一条
  • TTS 边合成边下发、边接收边播放,无需等待全文合成完成
  • 支持主动取消及异常中断后的资源释放

实现方案

计划通过一个 PR 完成消息语音播放的完整链路。

后端通过 WebSocket 连接池承载流式 TTS 合成,消息文本按句分块后依次合成,并通过 SSE 持续向前端下发音频数据;前端边接收边播放。TTS 支持多候选模型 fallback,语音合成任务使用独立线程池,与 Chat 主链路隔离。

按依赖顺序实现:

  1. WebSocket 连接池

    • 提供可复用的 WebSocket 连接模板
    • 单条物理连接同一时间最多执行一个 TTS 任务
    • 按模型维护独立连接池并负责任务调度
    • 区分连接池容量不足与模型建连失败,避免容量问题影响模型健康状态
  2. 流式 TTS

    • 封装阿里云 CosyVoice WebSocket 流式合成协议
    • 支持文本增量输入与音频流式输出
    • 首个音频分片到达后确认合成成功
    • 提供可取消的 TTS 任务句柄
  3. 候选模型路由

    • 支持多个 TTS 候选模型
    • 根据模型健康状态选择可用模型
    • 当前模型合成失败时自动 fallback 至下一候选
    • 连接池容量不足等非模型故障不计入模型异常
  4. 消息语音播放

    • 根据 messageId 查询 assistant 消息内容
    • 长文本按句切分,单个合成分块不超过 80 字符
    • 分块完成后立即进行流式 TTS 合成
    • 通过 SSE 持续下发音频元数据及音频分片
    • 前端边接收边播放
    • 使用全局单实例播放器控制播放状态,新播放自动停止旧播放
    • 语音任务通过独立线程池执行,不阻塞 Chat 请求
  5. 取消与资源回收

    • 用户停止播放时立即取消当前 TTS 任务
    • 中断后的 WebSocket 连接不再复用并及时释放
    • 长文本连续合成时正确处理任务结束与分块衔接,避免音频提前结束

预期效果

完成后,assistant 消息可以直接点击播放语音,并具备流式播放、主动停止、播放互斥和异常 fallback 能力,同时语音合成链路不会影响现有 Chat 请求。

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions