You need to enable JavaScript to run this app.
文档中心
豆包语音

豆包语音

复制全文
下载 pdf
同步语音合成
双向流式语音合成(WebSocket)
复制全文
下载 pdf
双向流式语音合成(WebSocket)
基于 WebSocket 的双向流式 TTS 接口,支持文本流式输入、音频流式输出,低时延,适用于实时交互场景,覆盖多语种与多方言​
​
运行依赖文件​
​
​
TTS Websocket Bidirection protocols.zip
​
​
​​
WSSwss://openspeech.bytedance.com/api/v3/tts/bidirection​
请求头​
X-Api-Key string 必选​
API Key 可从 控制台>API Key管理 获取​
说明​
同时支持旧版控制台的鉴权方式,详见旧版控制台鉴权参考​
​
X-Api-Resource-Id string 必选​
请求的模型版本,可选值:​
  • seed-icl-2.0:豆包声音复刻大模型2.0,支持使用声音复刻接口克隆的音色,具体音色详见控制台>音色库​
​
X-Api-Connect-Id string ​
用于追踪当前连接情况的标志 ID​
​
X-Control-Require-Usage-Tokens-Return string​
若设置为*,会返回计费的字符数​
​
​
事件​
建立连接​
EventType string​
请求事件类型。建立连接时,字段固定为StartConnection​
​
​
创建会话​
EventType string​
请求事件类型。创建会话时,字段固定为StartSession​
​
session_id string​
合成会话id,由客户端生成​
​
req_params object 必选​
model string​
指定模型版本,默认值为seed-tts-2.0-standard​
说明​
仅当speaker参数为复刻音色时需指定此参数,且指定后不支持使用语音指令context_texts​
​
textstring​
输入待合成的文本​
​
speaker string 必选​
指定音色 ID,具体的音色ID可从控制台 > 音色库获取​
​
audio_params object 必选​
音频参数​
format string​
指定音频格式,默认值为mp3,支持 mp3 / pcm / ogg_opus / wav​
说明​
流式场景推荐使用pcm,不建议使用wav​
​
sample_rate int​
指定输出音频的采样率,单位为Hz,不同音频格式支持的比特率不同,详细如下:​
  • wav/pcm/mp3默认值为24000,取值范围为[8000,16000,22050,24000,32000,44100,48000]​
  • ogg_opus仅支持48000​
​
bit_rate int​
指定音频比特率,单位 bps,不同音频格式对比特率支持的情况不同,详细如下:​
  • mp3:默认为64000 ,可选值[64000,160000]​
  • ogg_opus:可选值[64000,160000]​
  • wav/pcm:不支持指定比特率​
说明​
当设置disable_default_bit_rate为true后,可选值[16000,32000,64000,160000]​
​
speech_rate int​
指定音频的语速,取值范围 [-50, 100]。其中,取值100代表2.0倍速,-50代表0.5倍速​
​
loudness_rate int​
指定音频的音量,取值范围 [-50, 100]。其中,取值100代表2.0倍音量,-50代表0.5倍音量​
​
enable_subtitle bool​
启用字幕服务,开启后将返回字级别的时间戳,默认值为false​
说明​
仅支持中文和英文语种​
​
​
additions string ​
max_length_to_filter_parenthesis int​
指定过滤括号内文本的长度,单位为字符,默认为0(即不过滤),推荐取值范围0~100​
说明​
  • 该参数用于过滤文本中括号内的注释、补充说明等无需朗读的内容​
  • 当括号内文本字符数超过设定值时,该括号的过滤功能将失效,括号内内容会被正常朗读。若存在较长的括号文本需要过滤,建议客户端在送入合成前自行完成前置过滤,以避免过滤失效及不必要的时延​
​
disable_markdown_filterbool​
Markdown解析过滤参数,默认值为false​
  • true:启用后,系统会解析并去除Markdown语法,例如" **你好** "朗读为 "你好"​
  • false:停用后,系统会保留原始字符,例如 " **你好** " 朗读为 "星星你好星星"​
​
disable_emoji_filter bool​
Emoji解析过滤参数,默认值为false​
  • true:启用后,系统会解析并去除文本中的Emoji符号​
  • false:停用后,系统会保留文本中的Emoji符号​
​
latex_parser string​
启用Latex文本朗读能力功能。可取值:v2​
说明​
  • 该参数适用于教育场景,启用后,会增加一定的时延。​
  • 启用该参数时,需同时将disable_markdown_filter设置为true​
​
explicit_language string​
指定朗读语种。开启后,仅朗读指定语种的文本,其他语种的内容会被跳过或合成失败,支持的语种如下:​
  • zh-cn:中文为主,支持中英混读​
  • en:英语​
  • ja:日语​
  • es-mx:墨西哥西语​
  • id:印度尼西亚语​
  • pt-br:巴西葡萄牙语​
  • pt:葡萄牙语​
  • ko:韩语​
  • it:意大利语​
  • de:德语​
  • fr:法语​
  • th:泰语​
  • vi:越南语​
  • ru:俄语​
  • fil:菲律宾语​
  • ms:马来语​
  • ar:阿拉伯语​
  • pl:波兰语​
  • tr:土耳其语​
  • sv:瑞典语​
  • nl: 荷兰语​
  • no: 挪威​
  • uk: 乌克兰语​
  • fi: 芬兰​
  • da: 丹麦​
  • cs: 捷克​
  • hu: 匈牙利​
  • el: 希腊​
  • ro: 罗马尼亚​
  • hi: 印度​
  • es-es: 西班牙西语​
说明​
  • 输入文本语种须与 explicit_language 指定的语种一致,不一致时合成效果不予保证​
​
enable_auto_language_recognitionbool​
开启自动多语种识别,默认为false,开启后,系统将根据首句文本自动识别语种,并使用对应语种进行朗读​
说明​
  • 支持的语种与 explicit_language 一致(pt与es-es除外)​
  • 指定语种的优先级高于自动多语种识别,当同时指定了explicit_language时,自动多语种识别不生效​
  • 自动识别语种时,葡萄牙语文本默认输出 pt-br(巴西口音),西班牙语文本默认输出 es-mx(墨西哥口音)。如需使用欧洲葡萄牙语pt或西班牙西班牙语es-es,须通过 explicit_language 参数显式指定​
  • 中英模型(中文、英文)与小语种模型(日、韩、法语、西语等小语种)相互独立,各自仅对对应语种合成效果最佳​
​
explicit_dialect string​
指定方言​
  • beijing:北京话​
  • dongbei:东北话​
  • henan:河南话​
  • shaanxi:陕西话​
  • shanghai:上海话​
  • sichuan:四川话​
  • tianjin:天津话​
  • yue:粤语​
说明​
使用该参数时,speaker需设置支持方言的音色,音色的详细情况请参见:音色列表​
​
aigc_watermark bool​
启用AIGC生成标识,默认值:false。开启后,将在音频合成结尾添加节奏标识​
​
aigc_metadata object​
在合成音频中添加meta水印,支持音频格式 mp3 / wav / ogg_opus​
enable bool​
启用meta隐式水印,默认值:false​
​
content_producerstring​
指定合成服务提供者的名称或编码​
​
produce_id string​
指定自定义的内容制作编号​
​
content_propagatorstring​
指定内容传播服务提供者的名称或编码​
​
propagate_id string​
指定自定义的内容传播编号​
​
​
post_process object​
后处理相关配置​
pitch int​
指定音调,默认值为0,默认不调整音调,取值范围:[-12,12]​
取值越大,音调越高(声音越尖锐、越明亮);取值越小,音调越低(声音越低沉,越厚重)​
​
​
context_texts array​
配置语音指令​
示例:​
​
"context_texts":[ "你可以用特别特别痛心的语气说话吗?"]​
​
说明​
  • 该字段文字不参与计费​
​
section_id string​
多轮会话 ID 用于关联同一上下文中的多次串行语音合成请求。服务端通过该 ID 在一次语音合成结束后保存对话历史,并在后续语音合成请求中,使用相同的 ID 读取对应的历史记录。​
取值示例:如在一通电话中的多次 TTS 请求,建议为该通电话使用 UUID 生成一个唯一的 section_id,并在所有 TTS 请求中传递相同的 section_id。​
示例:section_id="bf5b5771-31cd-4f7a-b30c-f4ddcbf2f9da"​
说明​
  • 服务端对历史上下文有相应的轮数限制和超时时间。​
​
pronunciation_dictobject​
配置发音词典,修正指定文本的发音​
toneobject​
配置发音规则数组,支持发音修正与文本转写两类规则​
  • 发音修正:原词/(拼音音节),用于指定词汇的具体发音​
  • 文本转写:原词/目标文本,用于将原词替换为目标文本后再合成​
示例:​
​
"req_params": {​
"text": "我在北京用 mobile 说 omg",​
"speaker": "zh_female_vv_uranus_bigtts",​
"audio_params": {​
"format": "mp3",​
"sample_rate": 24000​
},​
"additions": "{\"pronunciation_dict\":{\"tone\":[\"北京/(bei3)(jing1)\",\"omg/oh my god\"]}}" ​
}​
​
说明​
  • tone 中每条规则采用 原词/修正内容 格式,以/分隔。服务端按文本从左到右进行贪心最长匹配,存在多个可匹配词条时,优先匹配更长的原词​
  • 最多支持配置 5000 个词条;每个原词长度不超过 9 个字符,不能为空、不能包含空格、不可重复​
  • 仅豆包语音合成大模型2.0、豆包语音复刻大模型2.0对应的中英文音色支持​
  • 命中发音字典规则的文本片段不支持 SSML 标签,同时使用时 SSML 标签将失效,建议二者择一​
​
​
​
​
​
发送请求​
EventType string​
请求事件类型。发送请求时,字段固定为TaskRequest​
​
session_id string​
合成会话ID​
​
text string 必选​
待合成的输入文本​
​
​
取消会话​
EventType string​
请求事件类型。取消会话时,字段固定为CancelSession​
​
​
结束会话​
EventType string​
请求事件类型。结束会话时,字段固定为FinishSession​
​
​
结束连接​
EventType string​
请求事件类型。结束连接时,字段固定为FinishConnection​
​
​
​
响应​
EventType string​
响应事件类型。包含以下几种事件:​
  • ConnectionStarted:建连成功​
  • SessionStarted:会话开始​
  • TTSSentenceStart:开始合成音频​
  • TTSResponse:音频合成内容​
  • TTSSentenceEnd:音频合成结束​
  • TTSSubtitle:返回音频合成字幕​
  • SessionFinished:会话结束​
  • ConnectionFinished:连接结束​
  • SessionCanceled:会话取消​
  • ConnectionFailed:建连失败​
  • SessionFailed:会话失败​
​
MsgType string​
消息类型。响应消息类型有以下两种​
  • FullServerResponse:全量服务端响应​
  • AudioOnlyServer:仅音频服务端响应​
​
SessioId string​
会话 ID,用于标识一次合成会话​
​
PayloadSize int​
返回的音频片段大小,单位是字节​
​
ConnectId string​
连接 ID,用于标识当前 WebSocket 连接​
​
Payload object​
当前事件携带的响应内容​
phonemes object​
音素相关时间戳​
​
text string​
合成音频文本​
​
words object​
字级别时间戳​
confidence float​
时间戳置信度,范围 0~1​
​
startTime float​
开始时间(秒)​
​
endTime float​
结束时间(秒)​
​
word string​
字​
​
​
usage object​
本次请求的资源消耗统计​
text_words int​
本次请求计费的文本字数(含标点)​
​
​
​
​
​
​
​

输入示例

import asyncio
import copy
import json
import logging
import sys
import uuid
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[2]))

import websockets

from protocols import (
    EventType,
    MsgType,
    finish_connection,
    finish_session,
    receive_message,
    start_connection,
    start_session,
    task_request,
    wait_for_event,
)

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

URL = "wss://openspeech.bytedance.com/api/v3/tts/bidirection"
TEXT = "你好,欢迎使用语音合成服务"

async def main():
    # Connect to server.
    headers = {
        "X-Api-Key": "your_api_key",
        "X-Api-Resource-Id": "seed-tts-2.0",
        "X-Api-Connect-Id": str(uuid.uuid4()),
        "X-Control-Require-Usage-Tokens-Return": "*",
    }

    logger.info(f"Connecting to {URL}")
    websocket = await websockets.connect(
        URL, additional_headers=headers, max_size=10 * 1024 * 1024
    )
    logger.info(
        f"Connected to WebSocket server, Logid: {websocket.response.headers['x-tt-logid']}",
    )

    try:
        # Start connection.
        await start_connection(websocket)
        await wait_for_event(
            websocket, MsgType.FullServerResponse, EventType.ConnectionStarted
        )

        audio_received = False

        # Session-level parameters. Subtitle/timestamp is not enabled by default.
        base_request = {
            "req_params": {
                "speaker": "zh_female_gaolengyujie_uranus_bigtts",
                "audio_params": {
                    "format": "mp3",
                    "sample_rate": 24000,
                    # "enable_subtitle": True,
                },
            },
        }

        # Start session.
        start_session_request = copy.deepcopy(base_request)
        start_session_request["event"] = EventType.StartSession
        session_id = str(uuid.uuid4())
        await start_session(
            websocket, json.dumps(start_session_request).encode(), session_id
        )
        await wait_for_event(
            websocket, MsgType.FullServerResponse, EventType.SessionStarted
        )

        # Send characters one by one.
        async def send_chars():
            for char in TEXT:
                synthesis_request = copy.deepcopy(base_request)
                synthesis_request["event"] = EventType.TaskRequest
                synthesis_request["req_params"]["text"] = char
                await task_request(
                    websocket, json.dumps(synthesis_request).encode(), session_id
                )
                await asyncio.sleep(0.005)  # 5ms delay between characters.

            await finish_session(websocket, session_id)

        send_task = asyncio.create_task(send_chars())

        # Receive audio data.
        audio_data = bytearray()
        while True:
            msg = await receive_message(websocket)

            if msg.type == MsgType.FullServerResponse:
                if msg.event == EventType.SessionFinished:
                    break
            elif msg.type == MsgType.AudioOnlyServer:
                audio_received = True
                audio_data.extend(msg.payload)
            else:
                raise RuntimeError(f"TTS conversion failed: {msg}")

        await send_task

        if audio_data:
            audio_format = base_request["req_params"]["audio_params"]["format"]
            filename = f"bidirectional_session_0.{audio_format}"
            with open(filename, "wb") as f:
                f.write(audio_data)
            logger.info(f"Audio received: {len(audio_data)}, saved to {filename}")

        if not audio_received:
            raise RuntimeError("No audio data received")

    finally:
        # Finish connection.
        await finish_connection(websocket)
        await wait_for_event(
            websocket, MsgType.FullServerResponse, EventType.ConnectionFinished
        )
        await websocket.close()
        logger.info("Connection closed")

if __name__ == "__main__":
    asyncio.run(main())

输出示例

[
  {
    "MsgType": "FullServerResponse",
    "EventType": "ConnectionStarted",
    "ConnectId": "926b8fad-e2ef-453a-8f47-0497a88e7140",
    "Payload": {}
  },
  {
    "MsgType": "FullServerResponse",
    "EventType": "SessionStarted",
    "SessionId": "a61af389-4042-4a77-9958-0ff2ce8af537",
    "Payload": {}
  },
  {
    "MsgType": "FullServerResponse",
    "EventType": "TTSSentenceStart",
    "SessionId": "a61af389-4042-4a77-9958-0ff2ce8af537",
    "Payload": {
      "phonemes": [],
      "text": "",
      "words": []
    }
  },
  {
    "MsgType": "AudioOnlyServer",
    "EventType": "TTSResponse",
    "SessionId": "a61af389-4042-4a77-9958-0ff2ce8af537",
    "PayloadSize": 2349
  },
  {
    "MsgType": "AudioOnlyServer",
    "EventType": "TTSResponse",
    "SessionId": "a61af389-4042-4a77-9958-0ff2ce8af537",
    "PayloadSize": 3264
  },
  {
    "MsgType": "FullServerResponse",
    "EventType": "TTSSentenceEnd",
    "SessionId": "a61af389-4042-4a77-9958-0ff2ce8af537",
    "Payload": {
      "phonemes": [],
      "text": "你好,欢迎使用语音合成服务",
      "words": []
    }
  },
  {
    "MsgType": "FullServerResponse",
    "EventType": "SessionFinished",
    "SessionId": "a61af389-4042-4a77-9958-0ff2ce8af537",
    "Payload": {
      "usage": {
        "text_words": 13
      }
    }
  },
  {
    "MsgType": "FullServerResponse",
    "EventType": "ConnectionFinished",
    "ConnectId": "926b8fad-e2ef-453a-8f47-0497a88e7140",
    "Payload": {}
  }
]
最近更新时间:2026.09.28 19:13:15
这个页面对您有帮助吗?
有用
有用
无用
无用