音色复刻POST
用一段参考音频为 CosyVoice 型号创建专属音色,获得 voice_tts_… 后在语音合成中使用。
POST https://api.tokentosea.com/v1/audio/voices
GET https://api.tokentosea.com/v1/audio/voices/{id}
提交一段公网可访问的参考音频,由厂商创建专属音色。平台返回音色 ID voice_tts_…,在 语音合成 中作为 voice 使用。创建音色本身不扣费(响应中 creation_charge_cny 为 "0"),合成时按字符计费。
前提:全能密钥或模型密钥,且密钥的调用范围包含对应型号;一段你有权使用的参考音频,放在厂商可公网访问的 https:// 地址。Python 示例需要 pip install requests,Node.js 示例需要 Node.js 18+。
音色与密钥、型号绑定
音色只能由创建它的那把密钥使用,并且只能用于创建时指定的 model。
支持的型号#
| 型号 | 说明 |
|---|---|
cosyvoice-v3.5-plus、cosyvoice-v3.5-flash | 这两个型号没有系统音色,必须先创建专属音色 |
截至 2026-10-21,以 GET /v1/models 的 resource_endpoints 包含 /v1/audio/voices 为准。
创建音色#
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | 必填 | 使用该音色的语音合成型号 |
audio_url | string | 必填 | 参考音频的 https:// 地址,厂商需能公网访问 |
language_hints | string[] | 可选 | 语言提示,默认 ["zh"] |
| 请求头 | 说明 |
|---|---|
Idempotency-Key | 建议提供。同一个键、同一参数重复提交返回同一个音色;参数不同返回 409 idempotency_conflict;前一次仍在处理时返回 409 voice_creation_already_accepted |
请只上传你有权使用的声音。
响应#
响应示例
{
"id": "voice_tts_7d90…(64 位十六进制)",
"object": "voice",
"model": "cosyvoice-v3.5-plus",
"purpose": "voice-clone",
"created_at": 1792483200,
"availability": "provider-managed",
"voice": "voice_tts_7d90…",
"creation_charge_cny": "0",
"provider_request_id": "…"
}| 字段 | 说明 |
|---|---|
id / voice | 音色 ID,在语音合成中作为 voice 传入 |
availability | provider-managed:音色由厂商保存,平台不设过期时间;厂商侧的保留规则以其文档为准 |
creation_charge_cny | 创建费用,当前为 "0" |
GET /v1/audio/voices/{id} 返回同样的对象(不含 voice、creation_charge_cny、provider_request_id)。
示例#
# 1. 创建音色
curl https://api.tokentosea.com/v1/audio/voices \
-H "Authorization: Bearer $TOKENTOSEA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"model": "cosyvoice-v3.5-plus", "audio_url": "https://example.com/my-voice.wav", "language_hints": ["zh"]}'
# 2. 用返回的 voice 合成语音
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.5-plus", "input": "你好,欢迎使用语音服务。", "voice": "voice_tts_…", "response_format": "wav"}' \
-o speech.wavimport os
import uuid
import requests
API = "https://api.tokentosea.com/v1"
HEADERS = {"Authorization": "Bearer " + os.environ["TOKENTOSEA_API_KEY"]}
created = requests.post(
API + "/audio/voices",
headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
json={"model": "cosyvoice-v3.5-plus", "audio_url": "https://example.com/my-voice.wav", "language_hints": ["zh"]},
timeout=180,
)
created.raise_for_status()
voice = created.json()["voice"]
speech = requests.post(
API + "/audio/speech",
headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
json={"model": "cosyvoice-v3.5-plus", "input": "你好,欢迎使用语音服务。", "voice": voice, "response_format": "wav"},
timeout=300,
)
speech.raise_for_status()
with open("speech.wav", "wb") as file:
file.write(speech.content)import { randomUUID } from 'node:crypto';
import { writeFile } from 'node:fs/promises';
const API = 'https://api.tokentosea.com/v1';
const headers = { Authorization: `Bearer ${process.env.TOKENTOSEA_API_KEY}`, 'Content-Type': 'application/json' };
const created = await fetch(`${API}/audio/voices`, {
method: 'POST',
headers: { ...headers, 'Idempotency-Key': randomUUID() },
body: JSON.stringify({ model: 'cosyvoice-v3.5-plus', audio_url: 'https://example.com/my-voice.wav', language_hints: ['zh'] }),
});
if (!created.ok) throw new Error(await created.text());
const { voice } = await created.json();
const speech = await fetch(`${API}/audio/speech`, {
method: 'POST',
headers: { ...headers, 'Idempotency-Key': randomUUID() },
body: JSON.stringify({ model: 'cosyvoice-v3.5-plus', input: '你好,欢迎使用语音服务。', voice, response_format: 'wav' }),
});
if (!speech.ok) throw new Error(await speech.text());
await writeFile('speech.wav', Buffer.from(await speech.arrayBuffer()));配额与错误#
每个账号每个 UTC 自然日最多创建 20 个音色(北京时间每天 08:00 重置),失败的创建同样计数。
| 状态码 | code | 原因与处理 |
|---|---|---|
422 | audio_url_required | audio_url 缺失或不是 https:// 地址 |
422 | voice_creation_not_supported | 该型号不支持创建音色 |
422 | endpoint_not_verified | 型号未开放音色接口 |
403 | model_not_allowed | 型号不在密钥的调用范围内 |
409 | idempotency_conflict、voice_creation_already_accepted | 同一幂等键对应不同参数,或创建仍在进行 |
429 | resource_daily_limit | 今日创建次数已用完 |
502 | provider_voice_creation_failed | 厂商未能创建音色(例如音频质量不足),请更换参考音频 |
404 | resource_not_found | 查询的音色不存在,或不是用当前密钥创建的 |