IndexTTS-2.5 语音合成
选择音色,提交文字,下载配音。包含固定音色 ID、调用示例和语速说明。
输入文字和音色 ID,即可生成 WAV 配音。支持中文、英文、日文、西班牙文和阿拉伯文。 当前供团队内部使用,暂不扣零售余额;使用现有账号的 API Key。
选择音色
| 音色 | voice_id | 使用范围 |
|---|---|---|
| 王立群参考音色(AI 合成) | wangliqun | 可调用本模型的所有账号;内置已选试听配置 |
| 官方示例音色 01 | official-voice-01-v1 | 可调用本模型的账号 |
使用 wangliqun,只需传文稿和这个 ID,无需上传录音或重复填写参数。
它固定绑定 wangliqun-v1 参考录音、默认生成参数和最终音频停顿处理;显式传入的生成参数可以覆盖默认值。
普通官方或自建音色 ID 固定的是参考录音。
更换同一账号的 API Key 不会改变音色 ID;其他账号不能直接使用该账号的自建音色。
王立群参考音色的内容账号选项已保存为「王立群老师」。这是参考录音生成的 AI 音色,合成内容不是本人录音。 下面的示例可供其他有本模型权限的账号直接使用;原先个人账号保存的 UUID 仍保持原内容及账号范围。
先完成下文「设置 API Key」,再查询当前账号能使用的音色:
curl --fail-with-body --silent --show-error \
https://api.wildflow.cn/v1/voices \
-H "Authorization: Bearer $WILDFLOW_API_KEY"从响应的 data 中复制 voice_id。列表包含 11 个官方人声音色、2 个情绪参考、共享 wangliqun,以及当前账号的自建音色。
如果返回 next_cursor,用 ?after=next_cursor 查询下一页。
生成一段配音
下面的命令适用于 macOS / Linux,需要 Python 3 和 cURL。只需修改文稿;如果更换音色,再修改 voice_id。
1. 设置 API Key
export WILDFLOW_API_KEY="替换为控制台生成的密钥"
export WILDFLOW_IDEMPOTENCY_KEY="$(python3 -c 'import uuid; print(uuid.uuid4())')"每次生成新配音时创建一个新的幂等键。网络中断后重试同一次生成,保留原键。
2. 提交文稿
curl --fail-with-body --silent --show-error \
-X POST https://api.wildflow.cn/v1/jobs \
-H "Authorization: Bearer $WILDFLOW_API_KEY" \
-H "Idempotency-Key: $WILDFLOW_IDEMPOTENCY_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "IndexTTS-2.5",
"parameters": {
"text": "你好,欢迎使用野生流动。",
"voice_id": "wangliqun"
}
}' \
--output operation.json响应保存到 operation.json。首次提交通常返回 HTTP 202,表示任务已接收;还需要查询完成状态并下载文件。
3. 等待完成并下载
export RESULT_FILE="result.wav"
export RESULT_MEDIA_TYPE="audio/wav"下面的命令使用 Python 3,读取上一步保存的 operation.json,等待任务完成后下载结果。等待超过两小时会停止;再次执行本段会继续查询原任务,不会重新提交。
python3 - <<'PY'
import hashlib
import json
import os
import time
from datetime import datetime, timezone
from email.utils import parsedate_to_datetime
from pathlib import Path
from urllib.error import HTTPError
from urllib.parse import quote
from urllib.request import Request, urlopen
base = "https://api.wildflow.cn"
headers = {"Authorization": "Bearer " + os.environ["WILDFLOW_API_KEY"]}
operation = json.loads(Path("operation.json").read_text())
operation_id = operation["id"]
status_url = base + "/v1/jobs/" + quote(operation_id, safe="")
output = Path(os.environ["RESULT_FILE"])
expected_media_type = os.environ["RESULT_MEDIA_TYPE"]
deadline = time.monotonic() + 7200
def pause(value):
try:
seconds = float(value)
except (TypeError, ValueError):
try:
seconds = (parsedate_to_datetime(value) - datetime.now(timezone.utc)).total_seconds()
except (TypeError, ValueError, OverflowError):
seconds = 3
seconds = max(1, seconds)
if time.monotonic() + seconds >= deadline:
raise SystemExit("等待超时。保留 operation.json,稍后重新执行本段继续查询。")
time.sleep(seconds)
while time.monotonic() < deadline:
try:
with urlopen(Request(status_url, headers=headers), timeout=60) as response:
status = json.load(response)
retry_after = response.headers.get("Retry-After", "3")
except HTTPError as error:
if error.code in (429, 503):
pause(error.headers.get("Retry-After", "3"))
continue
raise SystemExit(f"查询失败:HTTP {error.code}。保留原任务,检查错误后继续查询。")
state = status["state"]
print("任务状态:", state, flush=True)
if state == "succeeded":
artifacts = status.get("artifacts", [])
if not artifacts:
raise SystemExit("任务成功但缺少结果文件,请保留任务 ID 并联系支持。")
artifact = artifacts[0]
if artifact["media_type"] != expected_media_type:
raise SystemExit("结果格式与预期不同,请检查任务和模型。")
download_url = base + "/v1/artifacts/" + quote(artifact["id"], safe="") + "/content"
temporary = output.with_name(output.name + ".part")
digest = hashlib.sha256()
size = 0
with urlopen(Request(download_url, headers=headers), timeout=60) as response:
with temporary.open("wb") as file:
while chunk := response.read(1024 * 1024):
file.write(chunk)
digest.update(chunk)
size += len(chunk)
if size != artifact["size_bytes"] or digest.hexdigest() != artifact["sha256"]:
raise SystemExit("文件校验失败,保留原任务并重新执行本段下载。")
temporary.replace(output)
print("已保存:", output)
break
if state not in ("queued", "running", "submitting"):
raise SystemExit(f"任务已停止:{state}。请保留任务 ID;不要换幂等键重复提交。")
pause(retry_after)
else:
raise SystemExit("等待超时。保留 operation.json,稍后继续查询原任务。")
PY网络中断时可重新执行本段。failed、cancelled、recovery_required 或未知状态会停止下载;需要帮助时查看任务恢复说明。
下载完成后,播放当前目录下的 result.wav。完整文件下载失败时可以重试下载,不需要重新生成。
调整语速和停顿
wangliqun 默认采用 duration_factor=1.1、interval_silence=350、
max_text_tokens_per_segment=80、use_random=false、use_emo_text=false。
这些默认值只作用于该说话人 ID;需要调整时在 parameters 中显式填写。
| 你想调整什么 | 参数 | 怎么调整 |
|---|---|---|
| 说话速度 | duration_factor | 1 为模型默认,1.1 稍慢,1.2 更慢。它是生成时长因子,不是播放器倍速,也不是音色相似度 |
| 模型分段之间额外加入的静音 | interval_silence | 单位毫秒;系统默认 200,上述试听使用 350。它不控制模型产生的所有字间、句间停顿 |
| 每次生成的文本段长度 | max_text_tokens_per_segment | 系统默认 120,上述试听使用 80;较短的段落会增加分段机会,需结合听感调整 |
同样的参数仍可能生成不同的节奏,最终时长不保证按时长因子线性变化。
wangliqun 的最终 WAV 已包含停顿处理。 仅将中间连续至少 450 毫秒、
所有声道低于约 -48 dB 的近静音段缩短至约 350 毫秒;保留其他 PCM 样本、首尾停顿,不做全局变速。
这是按音量判断的固定处理,并不理解停顿语义。返回的 voice_profile_version 为 wangliqun-v1,
pause_removed_ms 表示缩短的毫秒数。其他音色不启用此处理。
提交前可以在朗读稿中去掉不需要发声的排版符号,把数字写成希望听到的读法。
展示稿可以保留书名号,例如 《中华文化一千问》;朗读稿可以写成 中华文化一千问。
这些是文稿准备建议,不表示后台会自动改写输入。
上传自己的音色
已有可用的音色 ID 时跳过本节。首次保存音色时,准备 1–15 秒的 PCM16 WAV 录音,命名为 reference.wav。
支持 8–192 kHz、单声道或双声道,文件最大 12 MiB,无需填写参考文本。
curl --fail-with-body --silent --show-error \
https://api.wildflow.cn/v1/voices \
-H "Authorization: Bearer $WILDFLOW_API_KEY" \
-H "Content-Type: audio/wav" \
-H "X-WildFlow-Voice-Name: Book-account-v1" \
-H "X-WildFlow-Content-SHA256: $(shasum -a 256 reference.wav | cut -d ' ' -f 1)" \
--data-binary @reference.wav --output voice.json
export WILDFLOW_VOICE_ID="$(python3 -c 'import json; print(json.load(open("voice.json"))["voice_id"])')"
curl --fail-with-body --silent --show-error \
"https://api.wildflow.cn/v1/voices/$WILDFLOW_VOICE_ID" \
-H "Authorization: Bearer $WILDFLOW_API_KEY"
curl --fail-with-body --silent --show-error \
https://api.wildflow.cn/v1/voices \
-H "Authorization: Bearer $WILDFLOW_API_KEY"保存返回的 voice_id,以后每次合成直接传入。更换参考录音时创建新 ID,已有音色内容不能覆盖。
自建音色保存在当前账号下,目前没有自动过期时间;上传的录音应在你有权使用的范围内。
在网页中使用
在个人设置的「音色工作室」中选择音色、输入文稿并生成配音。自建音色也可以在这里上传和试听。
如果需要为多个内容账号保存不同音色,输入内容账号名称后保存选择。
脚本调用时仍需显式传 voice_id,以便确定每批内容使用哪个音色。
通过 API 保存某个内容账号的选择:
PUT /v1/voice-preference
Content-Type: application/json
Authorization: Bearer <你的 API Key>{
"content_account": "王立群老师",
"voice_id": "wangliqun"
}GET /v1/voice-preference 查看已保存的选择。省略或留空 content_account 时,PUT 保存通用默认音色。
哪些参数值得调整
没有显式传入的参数会使用默认值。例如 text_normalization=true、do_sample=true、top_p=0.8、
top_k=30、temperature=0.8、repetition_penalty=10 已经生效,不需要为了启用而重复填写。
| 你遇到的问题 | 优先尝试 | 如何判断 |
|---|---|---|
| 整体说得太快或太慢 | duration_factor | 同一文稿、同一音色,只改这个值对比。它也可能改变节奏,不保证只改变总时长 |
| 分段处额外空白偏长 | interval_silence | 可以把试听中的 350 改回默认 200 做对比;模型自身生成的停顿仍可能保留 |
| 切段频繁、衔接不顺 | max_text_tokens_per_segment | 先比较 80 与默认 120。段更长不保证一定更自然 |
| 需要明确的开心、悲伤等表达 | use_emo_text 与 emo_text | 单独做短句试听;不需要明显情绪的讲述可以保持关闭 |
| 已有满意的情绪参考录音 | emotion_voice_id 与 emo_alpha | 用参考录音控制表达,强度单独比较;它不替代说话人的 voice_id |
| 需要细调情绪构成 | emo_vector | 八维情绪组合需要试听,不能当作通用的音质提升参数 |
| 想比较生成表达的变化 | temperature、top_p、top_k、do_sample | 属于生成采样控制,调低或关闭采样不等于质量更高。先保留默认值,每次只改一项 |
| 输出出现明显重复 | repetition_penalty | 先检查文稿和切段;必要时单独测试,不因名称而一味调大 |
| 希望更早开始播放 | stream=true | 改变结果获取和播放方式,不是提高音色相似度或发音质量的开关 |
use_random=false 只关闭随机情绪风格,不等于关闭所有生成采样。
情绪参考、情绪向量和文本情绪互斥,不要把三种方式一起启用。
是否采用某组参数,应以同音色、同文稿的试听结果为准;参数表本身不能证明哪一组听感更好。
全部生成参数
所有合成参数位于 parameters,未知字段会被拒绝。下表是通用默认值;
wangliqun 的语速与分段默认值按上文覆盖。
| 参数 | 默认值 | 允许值与说明 |
|---|---|---|
text | 必填 | 1–8,192 个 UTF-8 字节,首尾不能含空白 |
stream | false | true 时保存原生生成片段,可边生成边听;完整 WAV 仍由最终 Artifact 下载 |
voice_id | 原服务端音色 | 共享 wangliqun、官方或自建音色 ID |
lang | zh | zh / en / ja / es / ar |
duration_factor | 1 | 0.5–2,越大越慢;控制生成时长,不是音色相似度,最终秒数不保证线性变化 |
emotion_voice_id | 无 | 参考音频的音色 ID,用于情绪而非说话人身份 |
emo_alpha | 1 | 0–1,情绪参考强度 |
emo_vector | 无 | 8 个 0–1 数字,依次为高兴、愤怒、悲伤、恐惧、厌恶、低落、惊讶、平静 |
use_emo_text | false | 从文稿自动判断情绪;传 emo_text 可明确描述 |
emo_text | 无 | 非空且不超过 2,048 UTF-8 字节,要求 use_emo_text=true |
use_random | false | 随机情绪风格,可能降低音色一致性 |
interval_silence | 200 | 分段静音间隔,整数 0–2000 毫秒 |
max_text_tokens_per_segment | 120 | 每段 Token 上限,整数 20–200 |
text_normalization | true | 文本规范化 |
do_sample | true | 语音 Token 采样 |
top_p / top_k | 0.8 / 30 | 0.01–1 / 整数 1–100 |
temperature | 0.8 | 0.1–2 |
repetition_penalty | 10 | 0.1–20 |
情绪音频、情绪向量和文本情绪三种方式互斥。发音标注可直接写进文稿,例如 <行|XING2>。
固定音色 ID 固定的是参考录音;随机采样和文本内容仍会影响每次声学输出,不能保证文件逐字节相同。
不要自行设置 input_artifact_ids 或传原始参考音频到 Job;服务端根据音色 ID 绑定输入。
边生成边听
提交 Job 时设置 parameters.stream=true。网页勾选「边生成边听」,提交后点击同名播放按钮,
即可连续播放已保存的片段;浏览器要求一次点击才能开启音频播放。
API 客户端可以每 0.5–1 秒查询 GET /v1/jobs/{operation_id}/audio-segments。返回 data 数组,
每项包含 segment_id、attempt_id、sequence、media_type、size_bytes 和 sha256。
按 sequence 顺序读取 GET /v1/jobs/{operation_id}/audio-segments/{segment_id}/content,
每段是独立可解码的 PCM16 WAV。片段在持久化且通过完整性校验后才可读取,访问仍使用原账号 API Key。
客户端对同一 segment_id 只播放一次;若恢复后的 attempt_id 改变,清空旧播放队列,避免混合两次生成。
任务终止后再查询一次片段列表,避免遗漏最后一段。片段包含模型原生分段静音,播放时无需另加间隔。
每段最多 16 MiB,每次尝试最多 1,024 段、合计 320 MiB;当前片段没有自动过期时间。
音频片段不表示任务已经成功,也不触发计费。生成中断时,已保存片段可继续读取,但可能不完整;
recovery_required 按任务恢复规则处理,不自动重新合成。
只有完整 WAV 持久化后才返回 succeeded,最终交付与视频制作应使用任务的完整 Artifact。
wangliqun 的流式片段是未经停顿处理的原生预览;最终 Artifact 包含停顿处理,时长可能更短,
请基于最终文件制作字幕。
错误与恢复
400 invalid_request:检查文本长度、参数范围、音色 ID 和情绪模式是否互斥;401/403:检查 API Key,并用GET /v1/models确认这把 Key 能看到IndexTTS-2.5;409 idempotency_conflict:同一幂等键已经绑定了不同请求;429/503:按Retry-After等待后有限重试;recovery_required:停止自动补发,保留 Operation ID 并联系平台恢复。
网络中断后使用相同请求正文和相同幂等键恢复原 Operation,不要换键重复创建任务。不要在日志、前端 代码或问题截图中记录完整 API Key,也不要记录不必要的敏感文本。
模型与兼容说明
模型来源为 IndexTeam/IndexTTS-2.5,目录版本为 indextts-2.5@0b328234。
当前 team_trial 内部计费金额为 ¥0,上传、查询和保存音色偏好也不收费。
公共渠道为单并发;批量任务通过 Job 队列提交并轮询。
旧调用如果只传 text,仍采用 server_fixed 原服务端音色,不会自动使用网页中保存的默认音色。
该旧录音的来源记录不完整;需要固定音色时请显式传入已保存的 voice_id。
官方示例来自 IndexTeam/IndexTTS-2-Demo。模型许可与参考录音的使用范围是两回事,示例音色不代表取得说话人的商业声音授权。
相关文档
获取 API Key · 价格与计费 · 常见问题