GPT-SoVITS TTS 执行手册(主 session 专用)
⚠️ 核心规则:你不能 exec TTS!你要 spawn 子 session!
❌ 绝对禁止: exec 跑 tts_call.py
✅ 唯一方式: sessions_spawn(mode="run")
TTS 推理会杀 llama-server(腾显存)。你用的是 local/qwen3.6-35b——llama 一死你也会死。 如果你 exec TTS,你会立刻 503,连结果都看不到。别做。
时序窗口保证(纯本地链路)
- Python 脚本内部:stop_llama → TTS 推理 → start_llama → 三阶段检测(端口+health+completion)
- Python 脚本 stdout 只输出纯路径,stderr 不走 stdout(不走
2>&1) - PS 脚本:只读 stdout 路径 → Copy-Item → 写 flag → 等 llama /health → 输出 DONE
- 子 session exec 返回时本地 llama 已完全就绪 → announce 不会 503
子 session 用本地 qwen3.6-35b(独立运行),deepseek 仅作 fallback
执行步骤
⛔ 第一步:别 exec!
在你做任何事之前,停下来问自己:
"我接下来要调用的是 exec 还是 sessions_spawn?"
- 如果你要 exec → 停手。别做。 你会 503,然后发不出语音。
- 如果你要 sessions_spawn → ✅ 继续。
你只能 spawn,不能 exec。没有例外。
STEP 1: 组装参数(你负责写文本、选情绪、选语言)
根据上下文写好要合成的文本。
选语言(默认 ja=日文)。
选情绪模式(casual/tsundere/romantic/long),不指定则自动匹配。
STEP 2: 用 sessions_spawn 创建子 session
用下面这个命令,把 $text、$lang、$mood 替换好后 传给子 session:
sessions_spawn({
task: `你的任务:只做一件事——用 exec 运行下面这条命令。
命令(复制粘贴,一个字都不许改):
powershell -ExecutionPolicy Bypass -File "{{WORKSPACE}}\skills\tts\run_tts.ps1" -text "$text" -lang "$lang" -mood "$mood"
执行完毕后:
- 如果成功,输出"DONE: 然后是DONE后面的路径"
- 如果失败,输出"FAILED"
- 不要做任何其他操作!不要重新执行!不要写文件!不要检查!
- 你的唯一工作是运行这一条命令然后报告结果`,
taskName: "tts",
mode: "run",
model: "local/qwen3.6-35b",
fallbacks: ["deepseek/deepseek-v4-flash"],
runTimeoutSeconds: 540
})
STEP 3: 回复用户
sessions_spawn 后直接回复用户:"正在合成语音,稍等哦~ 🎤"
然后正常结束当前 turn。别 sessions_yield。
STEP 4: 收到 announce 后(重要!)
子 session 跑完会自动 announce 回来。announce 里会有 "DONE: <path>"。
⚠️ announce 可能包含两段文本:
1) 子 session 总结的长日志(模型信息、耗时等)—— 忽略它,不要转发!
2) "DONE: <path>" —— 只有这行有用!
你必须:
1. 从 announce 文本中提取 "DONE: " 后面的完整文件路径
2. 同时输出 MEDIA: 和 <qqmedia> 两种格式
3. 不要转发子 session 的日志文本
📦 同时输出两种格式(WebChat + QQ 频道都能收到语音):
MEDIA:C:\path\to\tts_yyyyMMddHHmmss.wav
<qqmedia>C:\path\to\tts_yyyyMMddHHmmss.wav</qqmedia>
⚠️ 关键:你必须用 DONE 后面的真实路径替换上面的示例路径。
两个标签各占一行,路径是同一个完整绝对路径。
MEDIA: 在行首,不在代码块里;<qqmedia> 标签也单独一行。
可以先说一句话,再用 MEDIA 和 <qqmedia> 发语音。
❌ 只输出 MEDIA: 不输出 <qqmedia> → QQ 频道收不到语音!
❌ 只输出 <qqmedia> 不输出 MEDIA: → WebChat 收不到语音!
参数速查
| 参数 | 说明 |
|---|---|
| text | 要合成的文本 |
| text_language | ja=日文, zh=中文, en=英文 |
| mood | casual=日常温柔, tsundere=傲娇, romantic=深情, long=长句 |
| 默认值 | lang=ja, mood=自动匹配 |
你的职责 vs 子 session 的职责
| 你(主 session) | 子 session(local qwen,deepseek fallback) |
|---|---|
| ✅ 写好待合成的文本 | ✅ 执行 exec 命令 |
| ✅ 选语言和情绪模式 | ✅ 复制 wav 到 media/qqbot/audio |
| ✅ sessions_spawn 子 session | ✅ 写 .task_flags |
| ✅ 回复用户"正在合成" | ✅ 等 llama /health + announce |
| ❌ 不要 exec Python 脚本! |
.task_flags 文件
- 路径:
{{TASK_FLAGS}}\ - 格式:
{"status":"ok","file":"<path>","type":"tts"}或{"status":"fail"} - 由 Windows Task Scheduler
cleanup-orphans每小时自动清理
故障排查
Q: 子 session announce 时 llama 503?
A: Python 脚本内部三阶段检测 + PS 脚本末尾 /health 双重确认。若仍超时,检查 /completion 阶段是否卡住。
Q: 子进程被 gateway 杀掉/孤儿进程?
A: tts_call.py 已内置 TimeoutGuard(HARD_TIMEOUT=420s) + atexit 清理。
Q: 并发调用导致两个 TTS 同时跑?
A: tts_call.py 有文件锁 (.tts_running.lock),会跳过重复调用。