语音合成POST
把文字合成为语音,直接返回音频二进制。支持系统音色与通过音色复刻创建的专属音色。
POST https://api.tokentosea.com/v1/audio/speech
提交文字与音色,成功时直接返回音频文件的二进制内容。音频同时保存在私有存储中,可通过 /v1/results/{key} 再次获取下载链接(保留 30 天)。
前提:全能密钥或模型密钥,账户可用余额足以覆盖本次预留。Python 示例需要 pip install requests,Node.js 示例需要 Node.js 18+。
支持的型号#
截至 2026-10-21,17 个型号开放本接口,以 GET /v1/models 为准。
| 服务商 | 型号 | 音色 |
|---|---|---|
| MiniMax | speech-2.8-hd、speech-2.8-turbo、speech-2.6-hd、speech-2.6-turbo、speech-02-hd、speech-02-turbo、speech-01-hd、speech-01-turbo | 系统音色 male-qn-qingse |
| 千问 CosyVoice | cosyvoice-v3-flash、cosyvoice-v3-plus、cosyvoice-v2 | 系统音色,见各型号的 system_voices |
| 千问 CosyVoice | cosyvoice-v3.5-flash、cosyvoice-v3.5-plus | 无系统音色,先用 /v1/audio/voices 创建专属音色 |
| 千问 | qwen-audio-3.0-tts-flash、qwen-audio-3.0-tts-plus、qwen-audio-3.1-tts-flash | 系统音色,见各型号的 system_voices |
| 千问 | qwen-audio-3.1-tts-next | 不使用音色,用 text_prompt 描述说话方式 |
每个型号可用的系统音色完整列表在 GET /v1/models 的 system_voices 字段与模型页面中,例如 cosyvoice-v3-plus 提供 longanhuan、longanyang。只支持 JSON 请求与非流式响应。
请求体#
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | 必填 | 型号 ID |
input | string | 必填 | 要合成的文字(也可写作 text)。qwen-audio-3.1-tts-next 使用 text_prompt |
voice | string | 必填(qwen-audio-3.1-tts-next 除外) | 系统音色 ID,或 /v1/audio/voices 创建的 voice_tts_…(必须与创建时的型号一致) |
response_format | string | 可选 | wav、mp3、pcm、flac、opus、ogg、aac。千问默认 wav,MiniMax 默认 mp3 |
sample_rate | integer | 可选 | 千问:采样率,默认 24000 |
speed | number | 可选 | MiniMax:语速,默认 1 |
voice_setting | object | 可选 | MiniMax 原生音色设置,传入后替换平台默认值({ voice_id, speed, vol: 1, pitch: 0 }) |
audio_setting | object | 可选 | MiniMax 原生音频设置,传入后替换平台默认值({ format, sample_rate: 32000, channel: 1 }) |
text_prompt | string | 仅 qwen-audio-3.1-tts-next | 包含说话方式描述与正文的提示 |
parameters | object | 可选 | 千问:其他厂商原生参数 |
provider_options | object | 可选 | MiniMax:其他原生字段,并入上游请求体 |
音色校验:voice(以及 MiniMax voice_setting.voice_id)必须是该型号的系统音色,或用同一把密钥创建的 voice_tts_…,否则返回 422 voice_not_registered;voice_tts_… 属于其他型号时返回 422 voice_model_mismatch。不能直接填写厂商侧的音色 ID。
计费:按字符计价的型号预留时按文字字符数的 2 倍上限预留,结算以厂商返回的计费字符数为准。
长文本异步合成(先上传文本文件,再按文件合成)使用 /v1/invoke,目前对 speech-2.8-hd 开放。
响应#
成功时返回 200,响应体为音频二进制:
| 响应头 | 值 |
|---|---|
Content-Type | 与音频格式对应,例如 audio/wav、audio/mpeg(mp3)、audio/L16(pcm)、audio/flac、audio/ogg、audio/aac |
X-Request-Id | 本次调用的幂等键 |
如果音频尚未完成转存,接口返回 202 与 JSON 结果信封。请检查 Content-Type:是 JSON 时按结果信封处理,稍后用同一个键查询 /v1/results/{key},完成后 output.data[0] 中有音频的下载链接与 asset_id。
示例#
curl https://api.tokentosea.com/v1/audio/speech \
-H "Authorization: Bearer $TOKENTOSEA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"model": "cosyvoice-v3-plus",
"input": "你好,欢迎使用语音服务。",
"voice": "longanyang",
"response_format": "wav"
}' \
-o speech.wavimport os
import uuid
import requests
response = requests.post(
"https://api.tokentosea.com/v1/audio/speech",
headers={
"Authorization": "Bearer " + os.environ["TOKENTOSEA_API_KEY"],
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"model": "cosyvoice-v3-plus",
"input": "你好,欢迎使用语音服务。",
"voice": "longanyang",
"response_format": "wav",
},
timeout=300,
)
content_type = response.headers.get("Content-Type", "")
if response.status_code == 200 and content_type.startswith("audio/"):
with open("speech.wav", "wb") as file:
file.write(response.content)
print("saved speech.wav")
else:
# 202:音频仍在处理,用 X-Request-Id 查询 /v1/results/{key};其他状态为错误
print(response.status_code, response.headers.get("X-Request-Id"), response.text)import { randomUUID } from 'node:crypto';
import { writeFile } from 'node:fs/promises';
const response = await fetch('https://api.tokentosea.com/v1/audio/speech', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TOKENTOSEA_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': randomUUID(),
},
body: JSON.stringify({
model: 'cosyvoice-v3-plus',
input: '你好,欢迎使用语音服务。',
voice: 'longanyang',
response_format: 'wav',
}),
});
const type = response.headers.get('content-type') ?? '';
if (response.status === 200 && type.startsWith('audio/')) {
await writeFile('speech.wav', Buffer.from(await response.arrayBuffer()));
console.log('saved speech.wav');
} else {
// 202:音频仍在处理,用 X-Request-Id 查询 /v1/results/{key};其他状态为错误
console.log(response.status, response.headers.get('x-request-id'), await response.text());
}MiniMax 的请求体:
{
"model": "speech-2.8-turbo",
"input": "你好,欢迎使用语音服务。",
"voice": "male-qn-qingse",
"response_format": "mp3",
"speed": 1
}使用专属音色时,把 voice 换成 /v1/audio/voices 返回的 voice_tts_…,model 必须与创建音色时一致。
错误#
| 状态码 | code | 原因与处理 |
|---|---|---|
422 | voice_not_registered | 音色不是该型号的系统音色,也不是你创建的 voice_tts_… |
422 | voice_model_mismatch | voice_tts_… 是为其他型号创建的 |
422 | use_owned_platform_resource | voice_tts_… 格式不正确 |
404 | resource_not_found | voice_tts_… 不存在,或不是用当前密钥创建的(专属音色与创建它的密钥绑定) |
422 | audio_format_not_supported | response_format 不在支持列表中 |
422 | response_mode_not_verified | 本接口不支持流式 |
400 | main_wallet_authorization_failed | 文字过长,超出单次预留上限 |