Skip to main content
WSS

/ws/v1/t2a_v2 的区别

本接口面向文本流式输入场景:把大模型的流式输出直接逐 token 转成语音。 task_start 的音色、音频、发音字典等参数与 /ws/v1/t2a_v2 完全一致,已有接入可直接复用。

事件流程

  1. 建立连接,收到 connected_success
  2. 发送 task_start,收到 task_started
  3. 发送 task_continue可按任意粒度,包括单个字符),服务端攒句后开始合成
    • 每句合成开始返回 sentence_start
    • 音频通过 task_continued 分块返回
    • 该句结束返回 sentence_end
  4. 需要打断时发送 task_cancel,收到 task_canceled 后可继续发送 task_continue
  5. 一轮说完、希望立刻拿到尾句音频时发送 task_flush,收到 task_flushed 后会话继续
  6. 发送 task_finish,服务端合成完残留文本后返回 task_finished 并关闭连接
三层结束语义不要混用:is_final 表示本次请求的音频结束,sentence_end 表示当前句结束,task_finished 表示整个会话结束。
一条连接同时只能有一个合成会话。任务已开始后重复发送 task_start 会返回 2206(事件顺序非法)并关闭连接。

攒句与延迟

服务端按标点判断句子边界,因此你发送的文本中的标点会直接影响音频的自然度
最后一条对多轮对话场景有实际影响。如果一轮说完时残留的文本既很短、又不带句末标点,它不会被那个短静默窗口立刻送出,而要等一个更长的兜底窗口。有两个办法避免这段等待:给最后一片文本补上句末标点,或者发送 task_flush 主动催出。注意不能用 task_finish 代替——它会关闭连接,在一条连接上跑多轮对话时用不了。
如果你的程序在转发大模型输出前会清洗文本,请保留原始标点。缺少标点会让服务端退化为按长度机械切分,停顿位置与语义不符,音频明显不自然。
上游(如大模型)出现较长停顿时,音频中会出现相应的空白,这无法避免。服务端不会为了填补空白而把攒了一半的句子提前送出——那样只会让听众先听到半个词再等待。

连接保活

连接空闲超过约 120 秒会被服务端关闭并返回 2201。「空闲」指服务端既没有收到上行事件,也没有在下发音频。
服务端不会主动发送 WebSocket ping 帧。如果你的会话存在较长静默期(例如等待用户说话),请由客户端定期发送 ping —— 服务端会回复 pong 并刷新活跃时间。仅靠 TCP 连接存活不足以避免 2201

发送速率与重试

收到 2205 表示服务端排队待合成的文本过多,通常是发送速度超过了合成速度。
2205 不是配额限流,也是软失败:连接和会话都不会关闭。稍后重新发送该条 task_continue 即可,不需要重连、也不需要重新 task_start
单条 task_continue 文本超过 10,000 字符会返回 2204,该条被跳过,连接与会话同样保持。
任务开始
type:object

发送任务开始事件则正式开始合成任务,当服务端返回的 task_started 事件时,标志着任务已成功开始。 只有在接收到该事件后,才能向服务器发送 task_continue 事件或 task_finish 事件。

任务继续
type:object

当收到服务端返回的 task_started 事件后,任务正式开始,可通过发送 task_continue 事件发送要合成的文本。

/ws/v1/t2a_v2 的关键区别:本接口的文本不会一条一次合成,而是进入服务端的攒句缓冲,按下列规则成句后才送去合成,因此可以安全地按逐字/逐 token 粒度发送:

  • 遇到句末标点(。!?…;!?. 及换行)立即合成
  • 遇到次级标点(,、:,;:)且已攒够长度时合成
  • 累计长度达到上限时强制切分
  • 停止发送超过一定时间后,自动合成缓冲区中的残留文本

纯空白文本会被静默丢弃,不会返回错误。 当最后一次收到服务端返回结果后超过 120s 没有发送新事件时,WebSocket 连接自动断开。

打断合成
type:object

发送 task_cancel 事件可立即打断当前合成:服务端会丢弃攒句缓冲区中尚未合成的文本、中断正在进行的合成,并返回 task_canceled 事件。

已经发送给客户端的音频不会撤回。

打断后会话回到 task_started 状态,可以继续发送 task_continue 继续合成,无需重建连接。适用于实时对话中用户插话打断的场景。

催出残留(不结束会话)
type:object

发送 task_flush 事件,让服务端立即把攒句缓冲区里剩余的文本送去合成,但不结束会话、不关闭连接。合成完毕后返回 task_flushed

适用场景:一轮说完了,而最后一片文本很短又不带句末标点。这种残留不会被静默窗口立刻送出(那是为了避免在词中间切开),需要等一个更长的兜底窗口。发 task_flush 可以立刻拿到这段音频。

task_finish 的区别:task_finish 会关闭连接,因此在一条连接上进行多轮对话时无法用它催出某一轮的尾句;task_flush 之后会话仍处于 task_started 状态,可以继续发送 task_continue

缓冲区恰好为空时也会正常返回 task_flushed,不算错误。

任务结束
type:object

服务端收到 task_finish 事件后,会先把攒句缓冲区中剩余的文本送去合成,等全部音频返回后才回复 task_finished 并关闭连接。

因此最后一句不完整的文本也不会丢失,无需客户端在结束前补一个标点。

建连成功
type:object

成功建立连接后会返回 connected_success 事件

任务开始
type:object

服务端返回 task_started 事件,标志着任务已成功开始

分句开始合成
type:object

服务端攒够一个句子并开始合成时返回 sentence_start 事件。随后该句的音频通过 task_continued 事件分块返回,直到 sentence_end

可用它统计服务端实际把文本攒成了多少句

任务继续
type:object

服务端返回 task_continued 事件,标志着任务已成功继续

分句合成结束
type:object

服务端返回 sentence_end 事件,表示当前句子的音频已全部返回。

注意三层结束语义的区别:is_final 表示本次请求的音频结束,sentence_end 表示当前句结束,task_finished 表示整个会话结束

打断成功
type:object

服务端返回 task_canceled 事件,表示打断已生效。此后可继续发送 task_continue

残留已送出
type:object

服务端返回 task_flushed,表示本次 task_flush 请求的音频已全部下发完毕。该事件排在本次 flush 产生的音频帧之后,收到它即可认为这一轮的音频结束。此后可继续发送 task_continue

任务结束
type:object

服务端返回 task_finished 事件,标志着任务已成功结束

任务失败
type:object

如果接收到 task_failed 事件,表示任务失败。此时需要关闭 WebSocket 连接并处理错误。