WebSocket合成

WebSocket 流式语音合成

服务概述

  • 通过 WebSocket 长连接进行流式语音合成,客户端发送 JSON 文本帧,服务端返回任务初始化、音频分片、任务完成或错误事件。
  • WebSocket 接口适用于需要在同一连接内连续发送多条合成请求、并按任务 ID 归并返回事件的实时语音场景。

服务申请

语音合成 API 采用全流程自助申请模式。在云上曲率官网(https://www.ilivedata.com/) 注册并激活账号后,在控制台创建语音合成项目,即可获得 appId 和服务密钥。

如需开通更多服务,可在管理控制台-总览页面开通其他服务。

接入流程

  1. 调用 Token 签发接口,使用 appId 和 secretKey 完成 auth 鉴权,获取 WebSocket Token。
  2. 使用返回的 wsUrl 拼接 token 参数建立 WebSocket 连接。
  3. 建连成功后,客户端通过 WebSocket 发送合成请求 JSON。
  4. 服务端通过 WebSocket 返回 initaudiodoneerror 事件。

获取 WebSocket Token

请求 URL

https://tts.ilivedata.com/api/v1/speech/synthesis/ws-token

HTTP 请求头

请求头 描述
X-AppId 例:81900001 项目或应用的唯一标识符
X-TimeStamp 例:2024-07-01T07:59:59Z 请求的 UTC 时间戳。需要把时间戳按 W3C 标准格式化
Authorization 例:Njl86M/jY6zZaZoGhZdGO+GI/8+yGFECusGH1yQHUFE= 签名值

请求方法:GET

请求签名

当用户请求 Token 签发接口时,使用 appId 和 secretKey 对请求做签名。当 API 收到带签名信息的请求之后,将使用相同的算法验证签名。如果发现签名不一致,API 将会返回鉴权失败。

签名计算方法

签名计算规则请参考帮助中心的请求签名。Token 签发接口为 GET 请求,通常没有请求体,按 GET 无请求体场景计算签名。HTTPRequestURI 是请求 URI 的绝对路径,不包含请求串。

签名示例

GET
tts.ilivedata.com
/api/v1/speech/synthesis/ws-token
X-AppId:81900001
X-TimeStamp:2024-11-01T07:59:59Z

请求示例

curl -X GET 'https://tts.ilivedata.com/api/v1/speech/synthesis/ws-token' \
  -H 'X-AppId: 81900001' \
  -H 'X-TimeStamp: 2024-11-01T07:59:59Z' \
  -H 'Authorization: {signature}'

响应示例

{
  "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresIn": 60,
  "expiresAt": 1782359144,
  "wsUrl": "wss://tts.ilivedata.com/api/v1/speech/synthesis/ws"
}

响应字段说明

字段名 类型 描述
token String WebSocket JWT,签名算法为 RS256
expiresIn Number Token 有效期,单位秒。Token 需要在有效期内用于建立 WebSocket 连接
expiresAt Number Token 过期时间,Unix 秒
wsUrl String TTS WebSocket 连接地址,不含 token 参数

建立 WebSocket 连接

WebSocket 连接地址

wss://tts.ilivedata.com/api/v1/speech/synthesis/ws?token={token}

Token 只用于 WebSocket 握手鉴权。连接建立成功后,当前连接不会因为 Token 到期自动断开;如果连接断开后需要重连,应重新获取 Token。

TTS 服务会校验 JWT 的签名、过期时间、audissscopepathappId。请求消息中的 appId 必须与 Token 中的 appId 一致。

WebSocket 请求参数

建连成功后,客户端通过 WebSocket 文本消息发送请求体 JSON。

顶层参数

参数 是否必需 类型 描述
appId 条件必需 Number request.appId 二选一;服务端优先取顶层 appId
sessionId 可选 String 业务会话 ID;不传时同一 WebSocket 连接内复用连接级默认 sessionId
request 必需 Object 合成请求体,结构与 SynthesisRequest 一致

request

参数 是否必需 类型 描述
appId 条件必需 Number 与顶层 appId 二选一
text 必需 String 合成文本,去除首尾空白后不能为空
language 可选 String 文本内容所属语种,推荐传入此语言参数;不传则使用自动语种检测结果。支持语种请参考语种列表
voice 可选 VoiceSetting 合成声音相关配置
output 可选 OutputSetting 输出音频相关配置

VoiceSetting

参数 必需 类型 描述
name 可选 String 预置音色库音色注册的音色名称
audio 可选 String 未指定音色名称时,可以通过此参数指定的音频文件进行音色克隆
emotion 可选 String 情感表达

OutputSetting

参数 必需 类型 描述
format 可选 String 选择输出合成音频格式,候选为 pcmwavmp3opus,默认为 wav

请求体示例

{
  "appId": 81900001,
  "request": {
    "appId": 81900001,
    "text": "您好,这是一个 WebSocket 流式语音合成示例。",
    "language": "zh-CN",
    "voice": {
      "name": "juvenile"
    },
    "output": {
      "format": "mp3"
    }
  }
}

如果客户端需要自定义业务会话,可显式传入 sessionId

{
  "appId": 81900001,
  "sessionId": "biz-session-001",
  "request": {
    "appId": 81900001,
    "text": "同一个业务会话内的第一条消息。",
    "voice": {
      "name": "juvenile"
    },
    "output": {
      "format": "mp3"
    }
  }
}

WebSocket 响应事件

init 事件

表示服务端已接受该任务,并返回任务标识信息。

字段名 类型 描述
event String 固定为 init
taskId String 任务 ID,由服务端生成
sessionId String 会话 ID;客户端未传时由服务端按连接生成
status String 固定为 init
taskStatus Number 任务状态
{
  "event": "init",
  "taskId": "bj_ws_1b3d21549d3841d3b4400829403a4fff",
  "sessionId": "bj_ws_5f45c8fa85814b159741c80620f705bf",
  "status": "init",
  "taskStatus": 1
}

audio 事件

表示一个音频分片。

字段名 类型 描述
event String 固定为 audio
taskId String 任务 ID
sessionId String 会话 ID
seq Number 音频分片序号
itemIndex Number 文本分片索引
itemDone Boolean 当前 itemIndex 是否完成
sampleRate Number 当前音频分片采样率
durationMs Number 当前音频分片时长,单位毫秒
audioBase64 String 音频二进制分片的 Base64 字符串
status String 固定为 streaming
{
  "event": "audio",
  "taskId": "bj_ws_1b3d21549d3841d3b4400829403a4fff",
  "sessionId": "bj_ws_5f45c8fa85814b159741c80620f705bf",
  "seq": 12,
  "itemIndex": 0,
  "itemDone": false,
  "sampleRate": 22050,
  "durationMs": 120,
  "audioBase64": "...",
  "status": "streaming"
}

done 事件

表示任务完成,服务端已上传完整音频文件。

字段名 类型 描述
event String 固定为 done
taskId String 任务 ID
sessionId String 会话 ID
status String 固定为 done
url String 上传后的音频文件访问地址
{
  "event": "done",
  "taskId": "bj_ws_1b3d21549d3841d3b4400829403a4fff",
  "sessionId": "bj_ws_5f45c8fa85814b159741c80620f705bf",
  "status": "done",
  "url": "https://xxx.cos.accelerate.myqcloud.com/tts/.../bj_ws_1b3d21549d3841d3b4400829403a4fff.mp3"
}

error 事件

表示任务失败。

字段名 类型 描述
event String 固定为 error
taskId String 任务 ID,若请求未进入任务初始化阶段可能为空
sessionId String 会话 ID,若请求未进入任务初始化阶段可能为空
status String 固定为 error
errorCode Number 错误码
errorMessage String 错误信息
{
  "event": "error",
  "taskId": "bj_ws_1b3d21549d3841d3b4400829403a4fff",
  "sessionId": "bj_ws_5f45c8fa85814b159741c80620f705bf",
  "status": "error",
  "errorCode": 3003,
  "errorMessage": "Invalid voice name."
}

taskId 与 sessionId 规则

  • 客户端不需要传 taskId。服务端会为每条消息生成新的唯一 taskId,并在 initaudiodoneerror 事件中返回。
  • 如果客户端传入 taskId,服务端会忽略该字段,仍然使用服务端生成的 taskId
  • 客户端不传 sessionId 时,服务端会在 WebSocket 建连时生成一个连接级默认 sessionId;同一连接内多条消息会返回相同 sessionId
  • 客户端显式传入 sessionId 时,服务端优先使用客户端传入的 sessionId

断线处理说明

  • WebSocket 断开后,客户端需要重新建立连接并重新发送合成请求。
  • 服务端不会使用客户端传入的 taskId 做任务级恢复。
  • 如果业务需要关联断线前后的请求,可由客户端传入同一个 sessionId 作为业务会话标识。

客户端处理建议

  • Token 有有效期,建议获取后立即建立 WebSocket 连接。
  • 收到 init 后可记录服务端返回的 taskIdsessionId,用于日志排查和业务侧事件归并。
  • audioBase64 需要 Base64 解码后再播放或缓存。
  • done 事件为准获取最终文件 URL。
  • 若连接断开,需要重新建立 WebSocket 连接并重新发送请求;新的请求会生成新的 taskId