1实现原理 · 为什么它能做到
核心知识是 2.5 时代的两大变故:不再接受 voice_label(要改用自然语言 instruction ≤200 字 + 文本内联 () 韵律指令),且审查更严(死/消失/敏感政治词触发 censorship_block)。
**What `stepaudio-2.5-tts` will NOT accept** — `voice_label` parameter. Error: `voice_label is not supported for v2 models`. This is the #1 migration gotcha from step-tts-2.
脚本请求 /v1/audio/speech:JSON body(model/input/voice/response_format/speed/volume + 可选 instruction),Authorization Bearer,成功直接落盘 mp3 字节。
body: dict[str, Any] = { "model": MODEL, "input": text, "voice": voice, "response_format": response_format, "speed": speed, "volume": volume, }
instruction 长度硬校验 + 内联 () 韵律由文本透传:句内 (试探着问)/(轻声)/(停顿一下) 等括号内容被模型消费为表演指令、不朗读。
if instruction: if len(instruction) > 200: return {"ok": False, "status": 0, "err": f"instruction too long: {len(instruction)} > 200 chars"}
censorship_block 的逐行降级:检测 'censorship_block'/'blocked' 标记失败行,批量模式记录跳过 ID 继续,不整批中断。
censored = "censorship_block" in raw or "blocked" in raw.lower()
批处理:--batch 读 JSONL({id, text, instruction?} 每行一个对象),逐行合成到 --out-dir/<id>.mp3,行间 sleep delay-ms 防限流。
out_path = args.out_dir / f"{line_id}.mp3" if result["ok"]: out_path.write_bytes(result["audio_bytes"])
非破坏性 A/B 是设计不变式:重生成语料写并行目录(voice/zh_v25/)绝不覆盖生产语料;ab_compare.sh 用 ffprobe/stat 对比两目录 mp3 的大小与时长出 markdown 表。
1. **Non-destructive A/B output** — when regenerating a corpus with a new model, write to a parallel directory (`voice/zh_v25/`), never overwrite the production corpus.
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| network | api.stepfun.com(StepAudio TTS 端点) |
| network | platform.stepfun.com(取 key/定价/voice 文档,仅指引) |
| cli | python3(stdlib urllib,无第三方包) |
| cli | ffprobe(ffmpeg,ab_compare 用) |
4风险提醒 风险提醒:橙色 · 评估后使用
- 文本内容外发第三方 API — 待合成文本(含 instruction)POST 到 api.stepfun.com;若批量语料含未公开文案/剧本,属内容离机,需合规评估。
- 明文 API key 落盘 — config.json 明文存 key(或走 env);目录权限取决于宿主,泄露面由此决定。
- 服务端审查会导致产出缺口 — 死/消失/政治词触发 censorship_block;批量中这些行只能改写或退回旧模型,可能造成语料不一致(音色/质量差异)。
- 1000 字符硬上限与时长膨胀 — 超限静默截断是已知坑(需按语义边界切分);2.5 比 step-tts-2 慢约 20%,长批量成本与延迟需预估。
- 第三方 API 漂移与定价不透明 — 邀请 beta 期无公开稳定定价;参数/审查行为可能变化,价格引用前必须回官方页复核。
5第二遍独立确认
- [ok] 端点/body/模型名(/v1/audio/speech + stepaudio-2.5-tts) — tts_generate.py API_URL/MODEL 常量与 body dict 逐字存在;api_reference.md 同。
- [ok] voice_label 拒绝处理(迁移 gotcha) — 脚本对 raw 含 'voice_label is not supported' 时追加 HINT 文案;SKILL.md 错误表同描述。
- [ok] instruction ≤200 硬校验 — synthesize() 内 'if len(instruction) > 200: return {ok: False, status: 0, err: ...}' 存在,超长不发请求。
- [ok] censorship 逐行降级(不整批失败) — censored 列表单独收集、failed 汇总、循环 continue;main 返回码只按 failed 定。
- [ok] API key 解析(env → CLAUDE_PLUGIN_DATA/config.json) — load_api_key 顺序与 asr 版一致(env 优先、config 兜底、fail-fast)。
- [ok] A/B 脚本无网络、本地文件对比 — ab_compare.sh 仅 comm/stat/ffprobe;--noproxy/网络 token 零命中。
- [ok] 功能声明 vs 夸大检查(voice cloning 未验证声明) — known_issues.md 第 56 行明确 'Zero-shot voice cloning (9.9 元/音色) … was not verified in this skill's test pass'——SKILL.md 也未把克隆列为核心能力,无夸大。
- [ok] 元数据(license/stars/commit) — 仓库级 MIT、stars=1385、pushed_at=2026-09-09T12:33:29Z;本地 HEAD==pin d5c4678cb5d4fd6acc9c922690df035dbd33d247。
6结论
f7fa276a8ae68d1a…d5c4678cb5