流式文本语音合成

最近更新时间:2024-07-11 19:52:09

说明:

此接口为 API 2.0 版本,在参数风格、错误码等方面有区别于 API 3.0 版本,请知悉。

本接口服务采用 websocket 协议,将请求文本合成为音频,同步返回合成音频数据及相关文本信息,达到“边合成边播放”的效果。区别于实时语音合成,本接口支持流式文本输入,适用于大语言模型的逐字输入场景,极大地提升了交互体验。


在使用该接口前,需要 开通语音合成服务,并进入 API 密钥管理页面 新建密钥,生成 AppID、SecretID 和 SecretKey,用于 API 调用时生成签名,签名将用来进行接口鉴权。

接口要求

集成实时语音合成 API 时,需按照以下要求。

内容 说明
音色种类 支持 中文音色(暂不支持英文、日语),音色 ID 详见 音色列表页。可通过接口参数 VoiceType 设置对应音色 ID
支持场景 通用、客服、情感、阅读、新闻等,详见 音色列表页
音频属性 采样率:8000Hz、16000Hz、24000Hz(部分支持,详见音色列表页)
采样精度:16bits
声道:单声道(mono)
音频格式 pcm、mp3
请求协议 wss 协议
请求地址 wss://tts.cloud.tencent.com/stream_wsv2?{请求参数}
接口鉴权 签名鉴权机制,详见 签名生成
响应格式 音频信息通过 binary 类型帧,返回原始二进制数据,可以边接收边播放;
文本信息通过 text 类型帧,返回 JSON 格式数据(如状态码、时间戳、服务器事件等)
并发限制 默认单账号限制并发连接数为20路(与实时语音合成接口共用),如您有提高并发限制的需求,请联系商务经理咨询或 购买并发
调用限制 1. 同一个流式会话中,总合成字数不超过 10000字
2. 输入流可持续发送合成文本,若超过 10分钟 没有文本发送,服务端将把已缓存文本正常合成完毕后关闭连接
3. 仅支持在输入流开启前,设置语速、音量、情感等参数
文本限制 1. 流式合成文本 不支持 SSML标记
2. 服务侧收到流式合成文本后缓存,并按照句子分割后合成,分割标点包括全角符号 。 ; ? ! 半角符号 ; ? ! 与换行符
3. 文本合成依赖句子的完整性,确保合成文本包含正确标点(尤其是文本末尾标点),否则文本可能长时间缓存而未合成

接口调用流程

接口调用流程分为三个阶段:签名握手阶段、合成阶段和结束阶段。三个阶段后台均会返回文本消息 text message(包括合成文本时间戳、服务器事件等),内容为 json 序列化字符串,以下是格式说明:

字段名 类型 描述
code Integer 状态码,0代表正常,非0值表示发生错误
message String 错误说明,发生错误时显示这个错误发生的具体原因,随着业务发展或体验优化,此文本可能会经常保持变更或更新
session_id String 本次会话唯一 id,由客户端在握手阶段生成并赋值在调用参数中
request_id String 本次会话唯一 id,由服务端自动生成,并随文本消息返回
message_id String 本 message 唯一 id
result Result 语音合成文本时间戳
ready Integer READY 事件:该字段返回1时表示服务端已初始化,客户端可以开始发送文本合成请求
final Integer FINAL 事件:该字段返回1时表示文本全部合成结束,客户端收到后需主动关闭 websocket 连接
heartbeat Integer HEARTBEAT 事件:该字段返回1时表示心跳报文,客户端收到后可忽略

其中合成结果 Result 结构体格式为:

字段名 类型 描述
subtitles Subtitle Array 当前一段话的词列表,Subtitle 结构体格式为:
Text: String 类型,该字的内容。
BeginTime: Integer 类型,该字在整个音频流中的起始时间。
EndTime: Integer 类型,该字在整个音频流中的结束时间。
BeginIndex: Integer 类型,该字在整个文本中的开始位置,从0开始。
EndIndex: Integer 类型,该字在整个文本中的结束位置,从0开始。
Phoneme: String 类型,该字的音素(注意:此字段可能返回 null,表示取不到有效值)。

握手阶段

请求格式

握手阶段,客户端主动发起 websocket 连接请求,请求 URL 格式为:

wss://tts.cloud.tencent.com/stream_wsv2?{请求参数}

其中<appid>需替换为腾讯云注册账号的 AppID,可通过 API 密钥管理页面 获取,{请求参数}格式为

key1=value2&key2=value2...(key 和 value 都需要进行 urlencode)

参数说明:

参数名称 必填 类型 描述
Action String 调用接口名,取值为:TextToStreamAudioWSv2(注意大小写)
AppId Integer 账号 AppId(请确保该字段数据类型为整型 int)
SecretId String 腾讯云注册账号的密钥 SecretId,可通过 API 密钥管理页面 获取
Timestamp Integer 当前 UNIX 时间戳,可记录发起 API 请求的时间。例如1529223702,如果与当前时间相差过大,会引起签名过期错误
Expired Integer 签名的有效期,是一个符合 UNIX Epoch 时间戳规范的数值,单位为秒;Expired 必须大于 Timestamp 且 Expired-Timestamp 小于90天
SessionId String 语音合成全局唯一标识,一个 websocket 连接对应一个,用户自己生成(推荐使用 uuid),最长128位。
VoiceType Integer 音色 ID,仅支持中文音色,暂不支持英语、日语
包括标准音色与精品音色,精品音色拟真度更高,价格不同于标准音色,请参见 购买指南。完整的音色 ID 列表请参见 音色列表
Volume Float 音量大小,范围[-10,10],对应音量大小。
默认为0,代表正常音量,值越大音量越高。
Speed Float 语速,范围:[-2,6],分别对应不同语速:
-2: 代表0.6倍
-1: 代表0.8倍
0: 代表1.0倍(默认)
1: 代表1.2倍
2: 代表1.5倍
6: 代表2.5倍
如果需要更细化的语速,可以保留小数点后 2 位,例如0.5/1.25/2.81等。
参数值与实际语速转换,可参考 代码示例
SampleRate Integer 音频采样率:
  • 24000:24k(部分音色支持,请参见 音色列表
  • 16000:16k(默认)
  • 8000:8k
  • Codec String 返回音频格式:
    pcm: 返回二进制 pcm 音频(默认)
    mp3: 返回二进制 mp3 音频
    EnableSubtitle Boolean 是否开启时间戳功能,默认为false。
    EmotionCategory String 控制合成音频的情感,仅支持多情感音色使用。取值: neutral(中性)、sad(悲伤)、happy(高兴)、angry(生气)、fear(恐惧)、news(新闻)、story(故事)、radio(广播)、poetry(诗歌)、call(客服)、撒娇(sajiao)、厌恶(disgusted)、震惊(amaze)、平静(peaceful)、兴奋(exciting)、傲娇(aojiao)、解说(jieshuo)
    示例值:neutral
    EmotionIntensity Integer 控制合成音频情感程度,取值范围为 [50,200],默认为 100;只有 EmotionCategory 不为空时生效。
    SegmentRate Integer 断句敏感阈值,取值范围:[0,1,2],默认值:0
    该值越大越不容易断句,模型会更倾向于仅按照标点符号断句。此参数建议不要随意调整,可能会影响合成效果
    Signature String 接口签名参数

    一、签名阶段

    Signature 签名生成

    1. 对除 Signature 之外的所有参数按字典序进行排序,拼接后得到请求参数为

    Action=TextToStreamAudioWSv2&AppId=130046****&Codec=pcm&EnableSubtitle=True&Expired=1688697305&SampleRate=16000&SecretId=*****XcaKs2w4vZw5zTCrHRM7dOwre9*****&SessionId=b78ae3ba-1ba5-11ee-a106-768645a5c72a&Speed=0&Timestamp=1688610905&VoiceType=101001&Volume=0

    再拼接请求方法、域名地址,得到签名原文(注意大小写)。签名原文格式为

    请求方法(GET) + 域名地址(tts.cloud.tencent.com/stream_wsv2) + 请求参数(?Action=TextToStreamAudioWSv2&其他参数...)

    最终,得到的签名原文为:

    GETtts.cloud.tencent.com/stream_wsv2?Action=TextToStreamAudioWSv2&AppId=130046****&Codec=pcm&EnableSubtitle=True&Expired=1688697305&SampleRate=16000&SecretId=*****XcaKs2w4vZw5zTCrHRM7dOwre9*****&SessionId=b78ae3ba-1ba5-11ee-a106-768645a5c72a&Speed=0&Timestamp=1688610905&VoiceType=101001&Volume=0

    1. 对签名原文使用 SecretKey 进行 HmacSha1 加密,之后再进行 base64 编码。例如对上一步的签名原文, SecretKey=*****SkqpeHgqmSz*****,使用 HmacSha1 算法进行加密并做 base64 编码处理:

    Base64Encode(HmacSha1("GETtts.cloud.tencent.com/stream_wsv2?Action=TextToStreamAudioWSv2&AppId=130046****&Codec=pcm&EnableSubtitle=True&Expired=1688697305&SampleRate=16000&SecretId=*****XcaKs2w4vZw5zTCrHRM7dOwre9*****&SessionId=b78ae3ba-1ba5-11ee-a106-768645a5c72a&Speed=0&Timestamp=1688610905&VoiceType=101001&Volume=0", "*****SkqpeHgqmSz*****"))

    得到 Signature 签名值为:

    4Lv+k6y6v5VRT/iBFPU+Gyfeiy0=

    1. 将 Signature 值进行 urlencode(必须进行 URL 编码,否则将导致鉴权失败偶现 )后拼接得到 URL 为:

    wss://tts.cloud.tencent.com/stream_wsv2?Action=TextToStreamAudioWSv2&AppId=130046****&Codec=pcm&EnableSubtitle=True&Expired=1688697305&SampleRate=16000&SecretId=*****XcaKs2w4vZw5zTCrHRM7dOwre9*****&SessionId=b78ae3ba-1ba5-11ee-a106-768645a5c72a&Speed=0&Timestamp=1688610905&VoiceType=101001&Volume=0&Signature=4Lv%2Bk6y6v5VRT/iBFPU%2BGyfeiy0%3D

    请求响应

    客户端发起连接请求后,后台建立连接并进行签名校验,校验成功则返回 code 值为 0 的确认消息表示握手成功;如果校验失败,后台返回 code 为非 0 值的消息并断开连接。

    {"code":0,"message":"success","session_id":"e042008c-1019-11ee-8b49-6c92bf65e6fe","request_id":"b028dfe6-d7af-4d25-b61d-dcae685aa81f","message_id":"f81c0771-5606-478e-9560-555a5717ea25","final":0,"result":{"subtitles":null}}

    二、合成阶段

    2.1 接收 READY 事件

    握手成功之后,等待服务端发送 READY 事件(ready=1),即可进入合成阶段。客户端根据需要发送合成文本,服务端缓存文本,并根据标点符号判断,确定接收到完整句子后,调用合成引擎。

    {"code":0,"message":"success","session_id":"da916680-31f8-11ef-997c-52540037edd7","request_id":"1bc1bab3-170d-4443-8685-238ce6bb6420","message_id":"b211e1d5-a742-4f65-8a11-af1f0757383e","final":0,"ready":1,"heartbeat":0,"result":{"subtitles":null}}

    2.2 发送合成指令与合成文本

    客户端根据需要发送合成指令(ACTION_SYNTHESIS)与合成文本,服务端缓存文本,并根据标点符号判断,确定接收到完整句子后,调用合成引擎。

    {"session_id": "381665d8-31f6-11ef-894a-52540037edd7", "message_id": "3b46df26-31f6-11ef-894a-52540037edd7", "action": "ACTION_SYNTHESIS", "data": "\u5355\u662f\u5468\u56f4\u77ed\u77ed\u7684\u6ce5\u5899\u6839\u4e00\u5e26\uff0c\u5c31\u6709\u65e0\u9650\u8da3\u5473\u3002"}

    2.3 接收合成结果

    合成结果:客户端需要同步接收后台返回的二进制音频数据与文本数据。文本数据示例如下:

    {"code":0,"message":"success","session_id":"659f1260-101a-11ee-959d-6c92bf65e6fe","request_id":"20ebf801-53ee-4a58-96ab-c63e0f16044a","message_id":"8d4a2f2b-3b15-445c-933b-74b6b44cd882","final":0,"result":{"subtitles":[{"Text":"欢","BeginTime":250,"EndTime":570,"BeginIndex":0,"EndIndex":1,"Phoneme":"huan1"},{"Text":"迎","BeginTime":570,"EndTime":770,"BeginIndex":1,"EndIndex":2,"Phoneme":"ying2"},{"Text":"使","BeginTime":770,"EndTime":1020,"BeginIndex":2,"EndIndex":3,"Phoneme":"shi3"},{"Text":"用","BeginTime":1020,"EndTime":1270,"BeginIndex":3,"EndIndex":4,"Phoneme":"yong4"}]}}

    返回错误:合成过程中如果出现错误,后台返回 code 为非 0 值的消息并断开连接。

    {"code":10001,"message":"参数不合法(Please check your parameter VoiceType)","session_id":"b6b10dc0-101a-11ee-9e72-6c92bf65e6fe","request_id":"a2edbe4f-c12f-48e6-8810-fda7a0992f79","message_id":"da63be2f-d44e-4f3b-a2d7-0b19a3748d23","final":0,"result":{"subtitles":null}}

    心跳消息:合成过程中,服务端会定时发送 HEARTBEAT 事件(heartbeat=1),用于保持长连接,客户端收到后不用处理

    {"code":0,"message":"success","session_id":"da916680-31f8-11ef-997c-52540037edd7","request_id":"1bc1bab3-170d-4443-8685-238ce6bb6420","message_id":"a985e1d5-a742-4f65-8a11-af1f07574237","final":0,"ready":0,"heartbeat":1,"result":{"subtitles":null}}

    三、结束阶段

    3.1 发送结束指令

    全部文本发送完后,发送 结束指令(ACTION_COMPLETE),通知服务器所有文本已发送完成。

    {"session_id": "da916680-31f8-11ef-997c-52540037edd7", "message_id": "de674bee-31f8-11ef-997c-52540037edd7", "action": "ACTION_COMPLETE", "data": ""}

    3.2 接收 FINAL 事件

    服务器:合成完所有请求文本之后,最终返回 FINAL 事件(final=1)

    客户端:收到合成完成消息后,需主动关闭 websocket 连接

    合成完成消息示例

    {"code":0,"message":"success","session_id":"dbb8417e-101a-11ee-840e-6c92bf65e6fe","request_id":"99207183-3bda-42de-a1f4-6d8838122ad3","message_id":"d56a3fed-0dd6-4dc6-b434-416ae1b69f0f","final":1,"ready":0,"heartbeat":0,"result":{"subtitles":null}}

    3.3 关闭 websocket 连接

    客户端收到 FINAL 事件后,关闭 websocket 连接,实时合成结束

    四、调用流程示意图

    实时合成 wsv2 流程图

    五、指令、事件与格式

    5.1 客户端指令

    客户端根据场景需要,发送指令到服务端

    指令类型
    指令 名称 data 描述
    ACTION_SYNTHESIS 合成文本指令 合成文本 客户端收到 READY 事件后,可持续调用该指令发送合成文本。
    两次合成指令发送间隔不超过 10 分钟
    若发送超时,服务端将返回超时报错(错误码 10009,仅做通知,可忽略),并在将缓存文本正常合成完毕后通知客户端关闭连接。
    ACTION_COMPLETE 合成结束指令 空字符串 客户端发送完所有文本后,发送该指令通知服务端文本发送完成
    指令格式

    {
        "session_id": "dbb8417e-101a-11ee-840e-6c92bf65e6fe", // 会话唯一id,客户端建立连接时传入
        "message_id": "3b46df26-31f6-11ef-894a-52540037edd7", // 本次消息唯一id
        "action": "ACTION_SYNTHESIS", // 指令类型
        "data": "" // 指令数据
    }

    5.2 服务端事件

    服务端将合成文本结果(如时间戳)、错误消息、服务器事件,通过文本消息方式返回客户端。

    事件类型

    final, ready, heartbeat 等,详情参见上面返回参数列表(该字段未来可能会扩展更多类型)

    事件格式

    {
        "code": 0, // 错误码
        "message": "success", // 错误信息
        "session_id": "dbb8417e-101a-11ee-840e-6c92bf65e6fe", // 会话唯一id,客户端建立连接时传入
        "request_id": "99207183-3bda-42de-a1f4-6d8838122ad3", // 会话唯一id,服务器生成,随消息返回
        "message_id": "d56a3fed-0dd6-4dc6-b434-416ae1b69f0f", // 本次消息唯一id
        "final": 1, // 事件类型
        "ready": 0,
        "heartbeat": 0,
        "result": { // 服务器事件,该字段可忽略
            "subtitles": null
        }
    }

    开发者资源

    SDK

    SDK 调用示例

    错误码

    客户端错误

    数值 说明
    10001 参数不合法,具体详情参考 message 字段
    10002 账号当前调用并发超限
    10003 鉴权失败
    10004 客户端数据上传超时
    10005 客户端连接断开
    10006 流式输入文本包含SSML
    10007 流式输入文本超过最大长度限制
    10008 流式输入文本通道已关闭
    10009 流式输入文本超时未发送,服务端合成完毕后将正常关闭连接

    服务端错误

    数值 说明
    20000 后台错误
    20001 后台服务处理失败
    20002 后台引擎合成失败
    20003 后台引擎合成超时