seed-tts-2.0 语音合成

将文本转换为语音,适用于内容播报、配音和语音交互。本文使用 MaiToken 原生 HTTP 单向流式接口:一次提交文本,连续接收音频数据。

POST/api/v3/tts/unidirectional

接入准备

  1. 在 MaiToken 控制台 创建 API Key。
  2. 确保 API Key 所选分组允许使用 seed-tts-2.0,并有足够可用余额。
  3. 准备文本和该模型支持的音色 ID。

示例使用占位 API Key,请替换成自己的正式环境 Key。后台登录 Token 不能作为模型调用 Key。

接口地址

POST https://{BASE_URL}/api/v3/tts/unidirectional

这里使用完整的原生接口路径,不要在地址前追加 /v1。

请求头

字段 必填 说明
X-Api-Key 是 MaiToken API Key,直接填写 Key,不加 Bearer
X-Api-Resource-Id 是 固定为 seed-tts-2.0
Content-Type 是 application/json; charset=utf-8

请求体

{  "req_params": {    "text": "你好,欢迎使用 MaiToken 语音合成。",    "speaker": "zh_female_vv_uranus_bigtts",    "audio_params": {      "format": "mp3",      "sample_rate": 24000    }  }}
参数 类型 说明
req_params.text string 待合成文本,必须包含可朗读内容,使用 UTF-8 编码
req_params.speaker string 音色 ID,必须与模型版本匹配;示例音色为 zh_female_vv_uranus_bigtts
req_params.audio_params.format string 示例显式指定 mp3
req_params.audio_params.sample_rate integer 示例显式指定采样率 24000 Hz

本接口通过请求头选择模型,不需要在请求体顶层额外添加 model。音色可用性受当前接入资源授权影响。

Bash / cURL 示例

以下示例适用于 Bash、Git Bash。测试文本使用 JSON Unicode 转义表示“你好”,避免终端中文编码影响测试结果。

export MAITOKEN_API_KEY='替换为你的正式环境 API Key' curl --fail-with-body --silent --show-error --no-buffer \  'https://{BASE_URL}/api/v3/tts/unidirectional' \  -H "X-Api-Key: ${MAITOKEN_API_KEY}" \  -H 'X-Api-Resource-Id: seed-tts-2.0' \  -H 'Content-Type: application/json; charset=utf-8' \  --data-binary '{"req_params":{"text":"\u4f60\u597d","speaker":"zh_female_vv_uranus_bigtts","audio_params":{"format":"mp3","sample_rate":24000}}}' \  --output tts-response.jsonstream

每行末尾的反斜杠 \ 后不要添加空格。响应文件是 JSON 数据流,不能直接改名为 MP3 播放。

响应与音频还原

HTTP 响应体由多个 JSON 对象组成。音频对象的 data 是 Base64 数据,需要依次解码并拼接。JSON 对象可能按行分隔,也可能直接连续出现;不要假定一个网络数据块就是一个完整 JSON 对象。

以下为结构示意,<Base64音频片段> 不是可播放数据:

{"code":0,"message":"","data":"<Base64音频片段>"}{"code":0,"message":"","data":"<Base64音频片段>"}{"code":20000000,"message":"ok","data":null,"usage":{"text_words":2}}

code=0 表示普通成功数据帧;code=20000000 表示合成成功结束。usage.text_words 为上游报告的用量,可能只在末尾出现。即使 HTTP 状态为 200,也应检查响应中的业务错误码。响应协议参考上游 HTTP 单向流式说明。

Python 完整示例:请求并保存 MP3

此示例仅使用 Python 标准库,不需要安装 SDK。它在接收完整响应后解析连续 JSON、检查业务状态,再写入音频文件;适合接入验证,不是实时播放示例。

将代码保存为 seed_tts.py:

import base64import jsonimport osfrom pathlib import Pathfrom urllib.error import HTTPErrorfrom urllib.request import Request, urlopen  def decode_audio(raw):    decoder = json.JSONDecoder()    offset = 0    audio = bytearray()    usage = None    finished = False     while offset < len(raw):        if raw[offset].isspace():            offset += 1            continue        frame, offset = decoder.raw_decode(raw, offset)        if not isinstance(frame, dict):            raise RuntimeError("响应帧不是 JSON 对象")        code = frame.get("code")        if code not in (0, 20000000):            raise RuntimeError(f"合成失败:{code},{frame.get('message', frame)}")        if frame.get("data"):            audio.extend(base64.b64decode(frame["data"], validate=True))        if isinstance(frame.get("usage"), dict):            usage = frame["usage"]        if code == 20000000:            finished = True     if not finished:        raise RuntimeError("未收到合成成功结束帧,请检查连接是否中断")    if not audio:        raise RuntimeError("响应中没有音频数据")    return bytes(audio), usage  def main():    payload = {        "req_params": {            "text": "你好,欢迎使用 MaiToken 语音合成。",            "speaker": "zh_female_vv_uranus_bigtts",            "audio_params": {"format": "mp3", "sample_rate": 24000},        }    }    request = Request(        "https://{BASE_URL}/api/v3/tts/unidirectional",        data=json.dumps(payload, ensure_ascii=False).encode("utf-8"),        headers={            "X-Api-Key": os.environ["MAITOKEN_API_KEY"],            "X-Api-Resource-Id": "seed-tts-2.0",            "Content-Type": "application/json; charset=utf-8",        },        method="POST",    )    try:        with urlopen(request, timeout=120) as response:            raw = response.read().decode("utf-8")    except HTTPError as exc:        detail = exc.read().decode("utf-8", errors="replace")        raise RuntimeError(f"HTTP {exc.code}: {detail}") from exc     audio, usage = decode_audio(raw)    Path("speech.mp3").write_bytes(audio)    print(f"已保存 speech.mp3,共 {len(audio)} 字节;用量:{usage}")  if __name__ == "__main__":    main()

运行:

export MAITOKEN_API_KEY='替换为你的正式环境 API Key'python seed_tts.py

如果已通过上面的 cURL 保存响应,可复用解析函数还原音频,无需再次调用接口:

python -c 'from pathlib import Path; from seed_tts import decode_audio; audio, usage = decode_audio(Path("tts-response.jsonstream").read_text(encoding="utf-8")); Path("speech.mp3").write_bytes(audio); print(usage)'

用量与计费

该模型按字符用量计费,价格单位统一为“每万字符”。具体销售单价以 MaiToken 当前模型价格及账号分组为准。

消费金额 = 计费字符数 ÷ 10,000 × 每万字符销售单价 × 分组倍率 × 用户倍率

例如,假设单价为 0.08 积分/万字符、计费字符数为 1,000、分组和用户倍率均为 1,则消费为 0.008 积分。这里的价格仅用于演示公式,不是正式环境报价。

请求开始时可能冻结预估费用,最终根据用量结算并处理差额。预扣金额与最终扣款应分别查看;实际用量以调用日志中的结算记录为准,不要简单按 UTF-8 字节数计算字符数。

常见问题

现象 排查方式
curl: (3) URL rejected 检查 URL 引号、不可见字符和续行反斜杠;必要时将命令合成一行
unsupported_endpoint 确认完整路径为 /api/v3/tts/unidirectional,没有漏掉 /api/v3 或额外添加 /v1
No readable text! 确认文本在 req_params.text 中,非空且有可朗读内容;用示例的 Unicode 转义文本排除编码问题
HTTP 401 检查是否使用有效的 MaiToken API Key,而不是管理后台登录 Token
余额不足 检查可用余额和进行中请求的冻结占用
音色权限错误 检查 speaker 是否属于当前模型支持且已授权的音色
HTTP 429 / 并发限制 降低并发,结合接口返回信息采用退避重试
文件无法播放 确认已对每个 data 片段做 Base64 解码并按顺序拼接,没有把 JSON 响应直接保存成 MP3
连接中断 / 缺少结束帧 不将部分音频视为完整成功;先核对调用状态与账单,再决定是否重新发起请求

文档依据

核对日期:2026-09-24。