GPT-SoVITS 本地声音工作流
把这份 Skill 当作一条可审计的 Windows 本地工作流。目标是让一个没有当前对话记忆的 agent,也能从零完成部署、准备本人声音素材、微调、试听和本地 API 交付;每一步都用本机代码、日志、文件和端口验证,不用经验替代证据。
0. 先确认边界
开始前确认:
- 请求者拥有录音和声音的使用权,或已取得明确同意。只处理授权的声音,不把克隆用于冒充、欺诈、绕过身份验证或隐瞒合成身份。
- 这是本地部署;API 默认只绑定
127.0.0.1。除非用户明确授权并完成认证、访问控制和风险评估,不公开端口、不建立隧道、不安装系统服务。 - 原始录音永远先保留只读副本。训练实验使用独立的
training/<experiment>目录,模型输出使用独立的版本目录,不覆盖官方预训练模型。 - “训练命令返回”不等于“声音训练完成”。完成必须同时满足:数据标注匹配、训练进程成功退出、目标权重存在且大小合理、API 能加载自定义权重、实际生成 WAV 且通过格式和非静音检查。
1. 安装前必须询问和探测
1.1 在下载前询问安装位置
如果用户没有给出安装目录,先询问,不下载、不克隆、不解压。至少询问:
- GPT-SoVITS 项目放在哪个绝对路径、是否允许创建该目录;
- 模型和缓存是否也放在该盘,目标盘剩余空间是否足够;
- 是否已有项目或旧版本,是否需要保留;
- 用户要使用集成 Windows 包,还是源码/运行时目录。
把用户确认的路径保存为任务变量,例如 $gptRoot、$voiceToolsRoot、$experimentRoot;不要把 $HOME、$PID 或其他系统变量当作自定义变量。
1.2 下载前收集硬件和完整依赖证据
在网络操作前运行只读探测,并记录输出:
Get-CimInstance Win32_OperatingSystem | Select-Object Caption,Version,OSArchitecture
nvidia-smi --query-gpu=name,memory.total,driver_version --format=csv,noheader
Get-Command 7z.exe,7zz.exe -ErrorAction SilentlyContinue | Select-Object Name,Source
Get-Command ffmpeg.exe,ffprobe.exe -ErrorAction SilentlyContinue | Select-Object Name,Source
若命令不在 PATH,再检查用户明确安装的路径、注册表卸载信息或项目配置;不能据此断言工具不存在。若用户说已有 7-Zip 或 FFmpeg,验证它的真实可执行文件和版本,并优先复用。不要额外安装 Docker、WSL、系统 CUDA 或第二套 Python,除非用户另行授权且兼容性证据要求这样做。
同时探测现有 Python/运行时、PyTorch、CUDA 和 GPU:
& "$gptRoot\runtime\python.exe" --version
& "$gptRoot\runtime\python.exe" -c "import torch,sys; print(sys.version.split()[0]); print(torch.__version__); print(torch.cuda.is_available()); print(torch.version.cuda); print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'no-cuda')"
将“官方 README 的测试环境”和“本机实际环境”分开记录。版本不一致时优先检查项目自带 runtime、install.ps1、requirements.txt、模型文件和实际启动日志,不要盲目升级。
在下载、安装或修改 PATH 前,先做完整依赖盘点。依赖不是一张对所有机器都相同的固定清单;先根据用户选择的“集成包/源码”“GPU/CPU”“是否自动 ASR”“是否做人声分离”确定分支,再逐项标记为“已满足、缺失、版本不兼容、无需或待确认”。至少检查:
| 类别 | 何时必需 | 核验对象 |
|---|---|---|
| Windows/架构/PowerShell | 所有 Windows 部署 | Windows 版本、64 位、PowerShell、权限、目标盘空间 |
| Python 运行时与 pip | 所有运行方式 | 集成包自带 runtime\python.exe,或项目要求的 Conda/venv、pip 版本 |
| Conda | 源码方式执行官方 install.ps1 时 |
当前 shell 可调用的 conda、目标环境和 conda info;集成包不因源码脚本而额外安装 Conda |
| Git | 仅源码克隆、更新或固定 commit | git.exe 版本;已有压缩包时不因为没有 Git 就安装 |
| 解压能力 | 安装包/模型为压缩包时 | 7-Zip/7z.exe/7zz.exe、Windows tar 或 Expand-Archive 至少一种 |
| FFmpeg 与 ffprobe | 音频转换、切分、格式和试听验证 | 两个真实可执行文件及版本;不能只检查 PATH 名称 |
| HTTP/诊断工具 | API 试听或下载诊断时 | curl.exe、PowerShell Web 请求能力;先复用 Windows 自带版本 |
| NVIDIA 驱动与 GPU | GPU 推理/训练时 | nvidia-smi、设备管理器证据、显存;不能把系统 CUDA Toolkit 当成 PyTorch CUDA runtime |
| PyTorch 系列 | 当前 GPT-SoVITS 分支运行时 | 项目 Python 中的 torch、torchaudio、torchcodec(若当前代码/依赖要求),CUDA 可用性 |
| Windows 原生运行库 | 某些 Python 原生包导入或启动报 DLL 错误时 | VC++ Redistributable 和实际 DLL/导入错误;没有证据时不预装 |
| 项目 Python 包 | 运行 WebUI、训练或 API 的分支 | 读取实际 requirements.txt、extra-req.txt,在项目 Python 中逐包导入并运行 pip check |
| 预训练模型与文本/内容模型 | 推理、特征提取、SoVITS/GPT 微调时 | 从当前代码配置和 README 得到的权重、BERT/CNHuBERT、G2PW 等实际文件 |
| ASR 模型与数据 | 选择自动转写时 | FunASR/Whisper 分支的包、模型缓存和语言模型;手工文字稿可不安装 ASR |
| NLTK/Open JTalk/UVR5 资源 | 仅对应文本前端、日语或人声分离分支 | 代码实际导入、模型目录和首次运行日志;未走该分支标记为可选 |
| 网络、证书、下载源 | 需要下载源码、包或模型时 | GitHub/Hugging Face 可达性、代理/证书、缓存和模型落盘路径 |
用项目自己的运行时检查包,而不是用系统 Python 代替:
$pythonExe = Join-Path $gptRoot 'runtime\python.exe' # 源码/Conda 时改为已确认的解释器
& $pythonExe --version
& $pythonExe -m pip --version
& $pythonExe -m pip check
& $pythonExe -c "import importlib.util as u, torch; print('torch=', torch.__version__); print('cuda=', torch.cuda.is_available(), 'torch_cuda=', torch.version.cuda); print('torchaudio=', u.find_spec('torchaudio') is not None); print('torchcodec=', u.find_spec('torchcodec') is not None)"
然后读取实际项目的 requirements.txt、extra-req.txt、install.ps1、pyproject.toml/setup.py(存在才读),把每个声明包与导入结果对照;不要用“能打开 WebUI”替代依赖检查。对外部程序分别验证真实路径和版本:
Get-Command git.exe,tar.exe,curl.exe,ffmpeg.exe,ffprobe.exe,7z.exe,7zz.exe -ErrorAction SilentlyContinue |
Select-Object Name,Source,Version
Get-Command 找不到 7-Zip 或 FFmpeg 时,只能说“当前 PATH 未发现”。继续检查用户提供的路径、常见安装目录、卸载注册表和项目配置;找到后用绝对路径执行 --version。同理,nvidia-smi 失败只能说明该命令没有给出证据,不能直接断言没有 NVIDIA GPU 或驱动。
1.3 缺失依赖必须先询问,不得擅自安装
把缺失项按“运行必需、训练必需、ASR/文本前端条件必需、可选工具”分组,向用户逐项报告。每一项在安装前都询问:
- 是否允许安装或下载;
- 安装到哪个绝对路径(项目/runtime、Git、7-Zip、FFmpeg、缓存/模型、训练输出分别询问,不能用一个模糊的“默认位置”代替);
- 是否允许加入 PATH;
- 选择哪个下载源/代理,是否允许联网;
- 已有旧版本是否保留,是否只复用现有版本;
- 是否允许创建目录、下载模型和占用目标盘空间。
可直接使用下面的询问格式:
依赖门禁发现以下项目尚未得到满足:
- [类别/名称]:已观察证据……;影响……;当前可替代方案……
请确认:
1. 是否允许安装/下载这些缺失项?(不允许则停在诊断或改走可用替代方案)
2. 每项安装或保存到哪个绝对路径?项目运行时、外部工具、模型/缓存、训练输出分开填写。
3. 是否允许修改 PATH?如果不允许,我会在启动脚本中使用绝对路径。
4. 使用哪个下载源,是否允许联网?
5. 是否保留已有版本,不覆盖现有安装?
用户确认前只做只读探测和报告,不下载、不安装、不改 PATH、不替换已有版本。用户确认后也要一类一类安装,记录安装器、版本、绝对路径、退出码和验证命令;失败时保留日志并回到门禁,不自动升级整个环境。VC++ Redistributable 通常由系统安装器写入系统组件位置,未必支持自定义运行库目录;遇到这一项时要明确询问“是否允许系统级安装”,另问“安装器下载/保留在哪个绝对路径”,不能虚构一个可选的运行库目录。
若用户已经有某个依赖但不在 PATH,优先让用户提供或确认它的绝对路径;若项目可用绝对路径运行,就不要为了 PATH 再安装一份。若选择源码方式而没有 Git,可在用户同意后选择官方压缩包作为替代,不把 Git 强行列为所有安装的必需项。
1.4 选择安装来源和版本
先读取 官方 README 与教程综合参考,再读取官方 README、安装脚本和本机包结构,确认当前版本支持的 Windows 方式、预训练模型、Python/PyTorch/CUDA 组合及 FFmpeg 要求。官方说明、当前本机代码和运行结果冲突时:
- 官方文档说明“应该怎样”;
- 本机代码和
--help说明“这份安装实际接受什么”; - 运行日志说明“这台机器实际做到什么”。
未解决的版本冲突标记为未知,先做最小探测,不要用最新版本覆盖可用环境。
2. 部署与启动语义
2.1 最小部署顺序
- 创建用户确认的项目目录和独立工具目录。
- 下载或解压到明确的临时目录;核对顶层是否包含
GPT_SoVITS、runtime、webui.py、api_v2.py等实际文件。 - 对官方
.7z集成包优先复用已验证的 7-Zip;解压后检查是否多了一层嵌套目录和文件数量。官方教程特别提醒某些通用解压器可能漏文件,不要用它们替代已验证的 7-Zip。 - 验证预训练模型、BERT/CNHuBERT、G2PW(中文需要时)、ASR 模型(需要自动标注时)和 FFmpeg/ffprobe 的实际路径;训练/数据路径优先使用无空格、无中文的 ASCII 路径,若当前脚本支持中文路径也以实际代码为准。
- 用项目自带 Python 启动一次 WebUI,保存 stdout/stderr、版本、端口和退出码。
不要因为某个集成包的 go-webui.bat 与当前目录不同,就凭经验改名或补文件。先读启动脚本;若脚本失败,保留窗口输出或从 PowerShell 运行以获取真实错误。
2.2 WebUI 与 API 是两个进程
按照本机启动脚本验证端口,不先假设端口号。常见本地包装中:
- WebUI 在
127.0.0.1:9874,用于切分、ASR、特征提取、训练和手工推理; api_v2.py在127.0.0.1:9880,用于 HTTP TTS。- 集成包常见推理 WebUI 为
9872、UVR5 WebUI 为9873;这些只是包装脚本的常见值,必须从本机脚本和 listener 重新确认。
WebUI 不需要 API 才能打开;API 也不是训练的前置条件。API 只在需要程序化生成或验证 HTTP 集成时启动。检查端口和接口:
Get-NetTCPConnection -LocalAddress 127.0.0.1 -State Listen
Invoke-WebRequest http://127.0.0.1:9874/ -UseBasicParsing -TimeoutSec 5
Invoke-WebRequest http://127.0.0.1:9880/openapi.json -UseBasicParsing -TimeoutSec 5
关闭时关闭对应的前台窗口或使用项目自己的退出接口;不要误杀整台机器的所有 Python 进程。
2.3 部署完成后主动交付素材说明
安装成功后,不要等用户问“接下来给什么”。主动告诉用户:
- 需要本人、单人、清晰、无背景音乐和强混响的录音;
- 需要与录音逐字对应的文字稿,ASR 只能作为草稿,用户校对后的文字才是标注真值;
- 录音格式优先 WAV、单声道、16-bit PCM,项目会统一到 32 kHz;M4A/AAC 可以先保留原件再用 FFmpeg 转换;
- 先做流程验证可用约 1–3 分钟;想要更稳定的第一版,建议准备约 10–20 分钟干净语音、覆盖不同音素和正常语速;更高覆盖度可以准备 20–60 分钟。以上是操作建议,不是官方硬性最低值;质量取决于录音、文字准确度、切片和训练设置;
- 单段通常以约 2–12 秒为目标,过长或含多句的段落应切分;
- 说话人、语言、录音环境和文本必须记录;不要混入其他人、音乐、回声、剪辑爆音或错误文字。
3. 数据准备:先保留原件,再生成训练副本
推荐实验布局:
<voice-tools-root>\training\<experiment>\
original\ # 原始 M4A/WAV,只读保留
raw\ # 统一采样率后的 WAV
slices\ # 自动切分片段
labels\ # 原文、ASR 草稿、人工修正版
reports\ # 数量、时长、字符匹配、错误报告
requests\ # 可选的 API JSON 请求,不放密钥
使用绝对路径和显式 UTF-8。先检查音频,再转换;不要直接覆盖原始 M4A:
& "$ffmpegExe" -i "$inputAudio" -ar 32000 -ac 1 -sample_fmt s16 "$rawWav"
& "$ffprobeExe" -v error -show_entries format=duration:stream=sample_rate,channels -of default=noprint_wrappers=1 "$rawWav"
3.1 切分、ASR 和校对
优先使用当前 WebUI 的“切分音频→ASR→校对”流程;CLI 入口以本机代码为准。官方当前 README 的常见入口是 audio_slicer.py、tools/asr/funasr_asr.py -i <input> -o <output> -l <language> 和 tools/asr/fasterwhisper_asr.py -i <input> -o <output> -l <language> -p <precision>;旧版本参数可能不同,先读 -h/WebUI 实际命令。每一步都保存输入、输出和退出码。
ASR 校对规则:
- 逐段试听,不只看 ASR 文本;
- 用用户提供的实际发音改写文字稿;例如原文写“窠巢”,但录音实际读成“巢穴”,训练标注应写“巢穴”;
- 保留语义必要的中文标点,但不要添加录音中没有的词;
- 对每一行执行“音频文件存在、文本非空、说话人和语言合法、音频顺序可追踪”的检查;
- 去除标点后比较标注与用户确认全文,报告字符数和第一个不匹配位置;不匹配时先修正,不进入训练。
3.2 .list 与特征文件的契约
官方 TTS 标注格式是:
audio_path|speaker_name|language|text
语言值按本机版本支持情况使用 zh、ja、en、ko、yue 等。中文训练使用对应的文本前端和 BERT/CNHuBERT。完成数据预处理后,按语言和当前分支检查本机实验目录是否出现并且数量一致:
2-name2text.txt
3-bert/
4-cnhubert/
5-wav32k/
6-name2semantic.tsv
7-sv_cn/
6-name2semantic.tsv 的表头必须是一个真实的 Tab 分隔:item_name<TAB>semantic_audio;不要把两个字符 \t 当作表头。中文分支才强制核对 BERT 目录;英语、日语、粤语或韩语分支出现空的 3-bert 可能是官方教程所述的正常情况。其余当前分支实际要求的 phoneme、CNHuBERT、semantic、SV 特征必须按同一个文件名集合匹配,任何缺失、重复或错位都停止训练。
4. 微调顺序与训练验证
4.1 先 SoVITS,再 GPT
V2/V2Pro 等版本通常先训练 SoVITS,再训练 GPT;具体脚本和参数以当前 webui.py 的实际分支为准。常见本机入口是:
GPT_SoVITS/s2_train.py
GPT_SoVITS/s1_train.py --config_file <yaml>
WebUI 的训练函数会动态写临时 JSON/YAML、设置实验名、预训练 G/D 或 S1 权重、输出目录和 GPU。优先使用 WebUI 让它创建目录和配置;手动运行前必须复制同样的配置并预创建输出目录。
4.2 关键资源和参数
- 根据实测显存选择 batch size、半精度、gradient checkpoint 和 epoch;不能把某台 RTX 2060 的设置当成通用默认。
- V2Pro 需要匹配的
s2Gv2Pro.pth与s2Dv2Pro.pth,GPT 使用版本匹配的 S1 预训练权重;先验证文件存在和加载日志中的All keys matched successfully或同等证据。 - 为每次实验使用新名字和独立
logs/<experiment>;保留每 epoch 的可推理权重,除非用户明确要求清理。 - 小数据集上的
top_3_acc=1.0只说明训练集拟合得很好,不能证明自然度、泛化或声音像本人;必须让用户听不同文本,并把小数据集结果标为“流程验证/可能过拟合”。
4.3 每个训练阶段的完成条件
SoVITS 完成必须看到:数据集数量、skipped_phone/skipped_dur、预训练权重加载、每个目标 epoch 的保存成功、训练进程退出码 0 或项目明确的 training done;同时检查 logs_s2_<version> 和版本化 SoVITS 权重。
GPT 完成必须看到:semantic_data_len 与 phoneme_data_len 一致、数据集进入训练、每个目标 epoch 的 GPT 权重、checkpoint 和 Trainer.fit 的正常结束;同时检查版本化 GPT 权重。
不要把只有日志、只有 checkpoint 或只有 WebUI“完成”提示当作完成。缺一个可加载的目标权重就回到故障定位。
5. API 加载、试听和交付
API 初次启动的配置通常仍指向官方预训练权重。训练出的自定义权重必须显式加载,并且必须通过一次真实 /tts 生成验证。官方 api_v2.py 常见接口为:
GET /set_gpt_weights?weights_path=<absolute-or-project-relative-path>
GET /set_sovits_weights?weights_path=<absolute-or-project-relative-path>
POST /tts
GET /control?command=exit
加载接口返回 success 只证明加载函数接受请求;随后还要生成 WAV、用 ffprobe 检查采样率/声道/时长,并用 FFmpeg 音量分析或人工试听确认不是静音。
/tts 至少提供:text、text_lang、ref_audio_path、prompt_lang、prompt_text。参考音频的实际内容必须与 prompt_text 一致;优先选择清晰、约几秒到十几秒的单段,而不是把整段长录音直接当参考。
当前版本还可能要求或接受 batch_threshold、split_bucket、fragment_interval、seed、parallel_infer、overlap_length、min_chunk_length、sample_steps、super_sampling 等字段;这些字段和 media_type/streaming_mode 的可选值必须读取目标 api_v2.py/openapi.json。注意 /set_refer_audio 使用 refer_audio_path,不是 /tts 的 ref_audio_path;完整字段表见 故障与 API 参考。
在 Windows 上不要假定 PowerShell Invoke-WebRequest -OutFile 能可靠保存二进制响应;若出现空引用或无法解析 WAV,用显式 UTF-8 JSON 文件配合 curl.exe --data-binary @request.json --output result.wav,再检查 HTTP 状态和文件头。不要把错误 JSON 当成 WAV 交付。
交付时报告:
- 实际使用的 GPT/SoVITS 权重完整路径和实验名;
- API 地址、启动方式和“重启后是否需要重新加载自定义权重”;
- 试听文件路径、时长、格式和已执行的验证;
- 数据量、训练设置、过拟合风险和未验证事项;
- 如果用户要求清理,精确列出删除的模型文件,确认原始录音是否保留。
6. 故障恢复顺序
遇到失败时使用:复现 → 保存日志 → 定位边界 → 一次只改一个变量 → 最小修复 → 重跑原场景 → 独立验证。
优先查阅 故障与 API 参考,不要凭错误猜测安装或重装。
常见关键点:
.bat窗口闪退:从 PowerShell 运行对应.ps1,记录真实 stdout/stderr 和退出码;不能把“窗口消失”当成 API 失败。- WebUI 可访问但 API 没开:这是正常的两个进程状态,分别按端口和
/openapi.json验证。 - 首次保存 checkpoint 报错:检查日志写入的目标,例如
logs_s2_v2Pro\G_*.pth;手工配置可能没有创建logs_s2_v2Pro,而 WebUI 会创建。补齐精确目录后重跑,不改模型文件。 - PyTorch Windows 分布式出现
kubernetes.docker.internal地址警告:只有在随后完成 barrier、进入训练并正常保存时才能判为非致命;若进程退出,继续读取 traceback 和退出码。 - PowerShell 将原生 Python stderr 标成
NativeCommandError:这是管道呈现方式,不等于 Python 失败;以日志内容和$LASTEXITCODE为准。 - 训练结束但没有权重:检查版本分支、保存目录、权限、磁盘空间、是否使用了正确的
s1_train.py/s2_train.py,并对目标目录做独立Get-ChildItem验证。 - API 返回 200 但试听文件坏:检查请求 JSON 编码、HTTP 响应头、文件大小和 WAV 头;用
curl.exe保存并用ffprobe验证。 - 目录或中文文件名乱码:先判断终端显示编码、文件 BOM 和实际解码方式,使用显式 UTF-8;不要把乱码写回标注。
7. 不要提前做的事
不要在用户尚未确认安装路径和硬件前下载;不要因为已有 7-Zip/FFmpeg 就断言它不存在;不要自动把新权重覆盖预训练目录;不要为了“方便”公开 9880;不要把 ASR 草稿直接当真值;不要删除原始录音;不要在小数据集达到高训练准确率后宣称声音质量已验证;不要创建或交付 Skill 之后继续偷偷训练、上传或推送数据。
参考资料路由
- 安装、版本、模型和数据格式:读取 Windows 部署与数据参考。
- 官方 README、版本分支、教程经验值和官方指南故障线索:读取 官方 README 与教程综合参考。
- 训练配置、真实文件契约、试听和排错:读取 故障与 API 参考。
- 官方来源、本机代码证据和时效边界:读取 来源账本。
完成任一任务后,在最终回复中区分“已观察事实”“采取的动作”“仍未知/未验证”,并给出用户可以直接打开或执行的完整路径和命令。