双向流式API为用户提供文本转语音能力,支持多语种、多方言,支持WebSocket协议流式调用,同时支持一包发送请求数据或者边发边收数据的流式交互方式。
该接口会处理碎片化的文本或者过长的文本,整理为长度合适的句子。因此最大的优势是平衡延迟和合成效果。
在对接大文本模型时,推荐将流式输出的文本直接输入该接口,而不要额外增加切句或者攒句的逻辑。同样的文本调用一次该接口与多次调用合成接口相比,前者会更为自然,情绪更饱满。
该接口每次使用均需要建立websocket连接,发送start connection,发送start session,通过task request发送文本,同时接收音频。在没有文本可以发送后,需立即发送finish session。多数情况下此时音频还未完全返回完毕,具体流程可参考该页交互示例。
Key | 说明 | 是否必须 | Value 示例 |
---|---|---|---|
X-Api-App-Key | 使用火山引擎控制台获取的APP ID,可参考 控制台使用FAQ-Q1 | Yes | 123456789 |
X-Api-Access-Key | 使用火山引擎控制台获取的Access Token,可参考 控制台使用FAQ-Q1 | Yes | your-access-key |
X-Api-Resource-Id | 表示调用服务的资源信息 ID
| Yes |
(不支持声音复刻1.0) |
X-Api-Connect-Id | 用于追踪当前连接情况的标志 ID | 67ee89ba-7050-4c04-a3d7-ac61a63499b3 |
Key | 说明 | Value 示例 |
---|---|---|
X-Tt-Logid | 服务端返回的 logid,建议用户获取和打印方便定位问题 | 202407261553070FACFE6D19421815D605 |
WebSocket 使用二进制协议传输数据。
协议的组成由至少 4 个字节的可变 header、payload size 和 payload 三部分组成,其中
需注意:协议中整数类型的字段都使用大端表示。
Byte | Left 4-bit | Right 4-bit | 说明 |
---|---|---|---|
0 - Left half | Protocol version | 目前只有v1,始终填 | |
0 - Right half | Header size (4x) | 目前只有4字节,始终填 | |
1 | Message type | Message type specific flags | 下文详细说明 |
2 - Left half | Serialization method |
| |
2 - Right half | Compression method |
| |
3 | Reserved | 留空( | |
[4 ~ 7] | [Optional field,like event number,...] | 取决于Message type specific flags,可能有、也可能没有 | |
... | Payload | 可能是音频数据、文本数据、音频文本混合数据 |
Message type & specific flags是重点扩展的部分,详细说明如下:
Message type | 含义 | Message type specific flags | 是否包含Event number | 备注 |
---|---|---|---|---|
0b0001 | Full-client request | 0b0100 | 是 | 完整请求体,用于触发服务端session初始化 |
0b1001 | Full-server response | 0b0100 | 是 | TTS:前端信息、文本音频混合数据等(Serialization=JSON) |
0b1011 | Audio-only response | 0b0100 | 是 | |
0b1111 | Error information | None | 否 |
TTS服务参数具体如下,大部分设置仅在StartSession生效,每次发送的文本可在TaskRequest中生效
字段 | 描述 | 是否必须 | 类型 | 默认值 |
---|---|---|---|---|
user | 用户信息 | |||
user.uid | 用户uid | |||
event | 请求的事件 | √ | ||
namespace | 请求方法 | string | BidirectionalTTS | |
req_params.text | required,输入文本,与ssml字段至少一个非空,若ssml非空则按照ssml字段 | √ | string | |
req_params.speaker | 发音人,具体见发音人列表 | √ | string | |
req_params.audio_params | 音频参数,便于服务节省音频解码耗时 | √ | object | |
req_params.audio_params.format | 音频编码格式,mp3/ogg_opus/pcm | string | mp3 | |
req_params.audio_params.sample_rate | 音频采样率,可选值 [8000,16000,22050,24000,32000,44100,48000] | number | 24000 | |
req_params.audio_params.speech_rate | 语速,取值范围[-50,100],100代表2.0倍速,-50代表0.5倍数 | number | 0 | |
req_params.audio_params.pitch_rate | 音调,取值范围[-12,12] | number | 0 | |
req_params.audio_params.enable_timestamp | 是否选择同时返回字与音素时间戳 | bool | false | |
req_params.additions | 用户自定义参数 | jsonstring | ||
req_params.additions.enable_language_detector | 自动识别语种 | bool | false | |
req_params.additions.disable_markdown_filter | 是否关闭markdown过滤,true为不过滤,false为过滤 | bool | true | |
req_params.additions.enable_latex_tn | 是否可以播报latex公式,需将disable_markdown_filter设为true | bool | false | |
req_params.additions.max_length_to_filter_parenthesis | 是否过滤括号内的部分,0为不过滤,100为过滤 | int | 100 |
示例:
{ "user": { "uid": "12345" }, "event": 100, "req_params": { "text": "明朝开国皇帝朱元璋也称这本书为,万物之根", "speaker": "zh_female_shuangkuaisisi_moon_bigtts", "audio_params": { "format": "mp3", "sample_rate": 24000 }, } } }
主要关注建连阶段 HTTP Response 的状态码和 Body
Byte | Left 4-bit | Right 4-bit | 说明 |
---|---|---|---|
0 - Left half | Protocol version | 目前只有v1,始终填 | |
0 - Right half | Header size (4x) | 目前只有4字节,始终填 | |
1 | Message type | Message type specific flags | 下文详细说明 |
2 - Left half | Serialization method |
| |
2 - Right half | Compression method |
| |
3 | Reserved | 留空( | |
[4 ~ 7] | [Optional field,like event number,...] | 取决于Message type specific flags,可能有、也可能没有 | |
... | Payload | 可能是音频数据、文本数据、音频文本混合数据 |
字段 | 描述 | 类型 | 默认值 |
---|---|---|---|
data | 返回的二进制数据包 | []byte | |
event | 返回的事件类型 | number | |
res_params.text | 经文本分句后的句子 | string | |
res_params.duration | 该句文本的音频时长 | number |
Byte | Left 4-bit | Right 4-bit | 说明 |
---|---|---|---|
0 - Left half | Protocol version | 目前只有v1,始终填 | |
0 - Right half | Header size (4x) | 目前只有4字节,始终填 | |
1 | Message type | Message type specific flags | 固定为 |
2 - Left half | Serialization method |
| |
2 - Right half | Compression method |
| |
3 | Reserved | 留空( | |
[4 ~ 7] | Error code | 错误码 | |
... | Payload | 错误消息对象 |
在 TTS 场景中,Event 是正常数据帧(包括上行和下行)的必要字段,事件定义了请求过程中必要的状态转移。具体的使用过程详见交互示例部分
Event code | 含义 | 事件类型 | 应用阶段:上行/下行 |
---|---|---|---|
1 | StartConnection,Websocket 阶段申明创建连接 | Connect 类 | 上行 |
2 | FinishConnection,结束连接 | Connect 类 | 下行 |
50 | ConnectionStarted,成功建连 | Connect 类 | 下行 |
51 | ConnectionFailed,建连失败 | Connect 类 | 下行 |
52 | ConnectionFinished 结束连接成功 | Connect 类 | 下行 |
100 | StartSession,Websocket 阶段申明创建会话 | Connect 类 | 上行 |
102 | FinishSession,声明结束会话(上行) | Session 类 | 上行 |
150 | SessionStarted,成功开始会话 | Session 类 | 下行 |
151 | SessionCanceled,已取消会话 | Session 类 | 下行 |
152 | SessionFinished,会话已结束(上行&下行) | Session 类 | 下行 |
153 | SessionFailed,会话失败 | Session 类 | 下行 |
200 | TaskRequest,传输请求内容 | 数据类 | 上行 |
350 | TTSSentenceStart,TTS 返回句内容开始 | 数据类 | 下行 |
351 | TTSSentenceEnd,TTS 返回句内容结束 | 数据类 | 下行 |
352 | TTSResponse,TTS 返回句的音频内容 | 数据类 | 下行 |
Connection 类:
StartConnection
包(RequestMeta):Byte | Left 4-bit | Right 4-bit | 备注 | |
---|---|---|---|---|
0 | 0001 | 0001 | v1 | 4-byte header |
1 | 0001 | 0100 | Full-client request | with event number |
2 | 0001 | 0000 | JSON | no compression |
3 | 0000 | 0000 | ||
4 - 7 | int32( | event type | ||
8 - 11 | uint32( | len( | ||
12 - 93 |
|
|
FinishConnection
包(RequestMeta):Byte | Left 4-bit | Right 4-bit | 备注 | |
---|---|---|---|---|
0 | 0001 | 0001 | v1 | 4-byte header |
1 | 0001 | 0100 | Full-client request | with event number |
2 | 0001 | 0000 | JSON | no compression |
3 | 0000 | 0000 | ||
4 - 7 | int32( | event type | ||
8-11 | uint32( | len( | ||
12-13 |
|
|
ConnectionStarted
包:Byte | Left 4-bit | Right 4-bit | 备注 | |
---|---|---|---|---|
0 | 0001 | 0001 | v1 | 4-byte header |
1 | 1001 | 0100 | Full-server response | with event number |
2 | 0001 | 0000 | JSON | no compression |
3 | 0000 | 0000 | ||
4 - 7 | int32( | event type | ||
8 - 11 | uint32( | len( | ||
12 - 18 |
| connection_id | ||
19 - 22 | uint32( | len( | ||
23 - 24 |
|
|
允许客户端不填connection_id
,由网关下发一个唯一的ID
ConnectionFailed
包(ResponseMeta):Byte | Left 4-bit | Right 4-bit | 备注 | |
---|---|---|---|---|
0 | 0001 | 0001 | v1 | 4-byte header |
1 | 1001 | 0100 | Full-server response | with event number |
2 | 0001 | 0000 | JSON | no compression |
3 | 0000 | 0000 | ||
4 - 7 | int32( | event type | ||
8 - 11 | uint32( | len( | ||
12 - 15 | uint32( | len( | ||
16 - 73 |
| response_meta_json
|
Session 类:
StartSession
包(RequestMeta):Byte | Left 4-bit | Right 4-bit | 备注 | |
---|---|---|---|---|
0 | 0001 | 0001 | v1 | 4-byte header |
1 | 0001 | 0100 | Full-client request | with event number |
2 | 0001 | 0000 | JSON | no compression |
3 | 0000 | 0000 | ||
4 - 7 | int32( | event type | ||
8 - 11 | uint32( | len( | ||
12 - 23 |
| session_id | ||
24 - 27 | uint32( | len( | ||
28 - ... |
| tts_session_meta |
不允许客户端不填session_id
FinishSession
包(RequestMeta):Byte | Left 4-bit | Right 4-bit | 备注 | |
---|---|---|---|---|
0 | 0001 | 0001 | v1 | 4-byte header |
1 | 0001 | 0100 | Full-client request | with event number |
2 | 0001 | 0000 | JSON | no compression |
3 | 0000 | 0000 | ||
4 - 7 | int32( | event type | ||
8 - 11 | int32( | len( | ||
12 - 23 |
| session_id | ||
24 - 27 | uint32( | len( | ||
28 - 29 |
|
|
SessionStarted
包(ResponseMeta):Byte | Left 4-bit | Right 4-bit | 备注 | |
---|---|---|---|---|
0 | 0001 | 0001 | v1 | 4-byte header |
1 | 1001 | 0100 | Full-server response | with event number |
2 | 0001 | 0000 | JSON | no compression |
3 | 0000 | 0000 | ||
4 - 7 | int32( | event type | ||
8 - 11 | uint32( | len( | ||
12 - 23 |
| session_id | ||
24 - 27 | uint32( | len( | ||
28 - 29 |
|
|
SessionFinished
包(ResponseMeta):Byte | Left 4-bit | Right 4-bit | 备注 | |
---|---|---|---|---|
0 | 0001 | 0001 | v1 | 4-byte header |
1 | 1001 | 0100 | Full-server response | with event number |
2 | 0001 | 0000 | JSON | no compression |
3 | 0000 | 0000 | ||
4 - 7 | int32(Event_SessionFinished) | event type | ||
8 - 11 | uint32( | len( | ||
12 - 23 |
| session_id | ||
24 - 27 | uint32(48) | len( | ||
28 - 75 |
| response_meta_json
|
SessionFailed
包(ResponseMeta):与SessionFinished
类似SessionCanceled
包(ResponseMeta):与SessionFinished
类似数据类:
Event_TaskRequest
事件为例):Byte | Left 4-bit | Right 4-bit | 备注 | |
---|---|---|---|---|
0 | 0001 | 0001 | v1 | 4-byte header |
1 | 0010 | 0100 | Audio-only request | with event number |
2 | 0000 | 0000 | raw | no compression |
3 | 0000 | 0000 | ||
4 - 7 | int32( | event type | ||
8 - 11 | uint32( | len( | ||
12 - 23 |
| session_id | ||
24 - 27 | uint32( | len( | ||
28 - ... |
| audio_binary |
Byte | Left 4-bit | Right 4-bit | 备注 | |
---|---|---|---|---|
0 | 0001 | 0001 | v1 | 4-byte header |
1 | 0010 | 0000 | Audio-only request | no event number |
2 | 0000 | 0000 | raw | no compression |
3 | 0000 | 0000 | ||
8 - 11 | uint32( | len( | ||
12 - 23 |
| session_id | ||
24 - 27 | uint32( | len( | ||
28 - ... |
| audio_binary |
Event_TaskRequest
事件为例):Byte | Left 4-bit | Right 4-bit | 备注 | |
---|---|---|---|---|
0 | 0001 | 0001 | v1 | 4-byte header |
1 | 0001 | 0100 | Full-client request | with event number |
2 | 0001 | 0000 | JSON | no compression |
3 | 0000 | 0000 | ||
4 - 7 | int32( | event type | ||
8 - 11 | uint32( | len( | ||
12 - 23 |
| session_id | ||
24 - 27 | uint32( | len( | ||
28 - ... |
|
|
CodeOK Code = 20000000 //成功 CodeClientError Code = 45000000 //客户端通用错误 CodeServerError Code = 55000000 //服务端通用错误 CodeSessionError Code = 55000001 //服务端session错误 CodeInvalidReqError Code = 45000001 //客户端请求参数错误
将下面两行替换为控制台获取的APP ID和Access Token
appKey = flag.String("app_key", "your_app_key", "VolcEngine app ID") accessKey = flag.String("access_key", "your_access_key", "Access Token for authorization")