DuolinGal 是一套面向 KiriKiri Z galgame 的本地优先研究工具链。这套工作流可以让你玩上英语或中文配音的 galgame。
这套工作流已经在《千恋*万花》上跑通了从资源提取、台词对齐、角色数据集导出,到 GPT-SoVITS 训练、批量推理、游戏补丁回灌的全流程。
我将这套工作流生成的《千恋*万花》英文配音补丁已经发布在了 GitHub Releases。下载并放入游戏目录即可玩。
这套工作流里,主要调用了如下核心工具,它们非常优秀,为它们的仓库点个 star 吧:
- GARbro 负责解包。
- GPT-SoVITS 负责角色语音克隆、角色训练、角色推理,是整条语音生成链的核心。
- FreeMote
负责反编译和重建
.scn、.psb、.psb.m等 KiriKiri 常见资源。 - KirikiriTools
负责
patch2.xp3打包;游戏运行补丁version.dll。 - FFmpeg
负责音频裁切、重采样、格式转换和
wav -> ogg转码。 - KrkrDump 负责解包。
- KrkrExtract 负责解包或重打包 XP3 资源。
注:在我本次进行千恋万花的英文生成时,使用的解包工具为
GARbro。虽然代码里预留了KrkrDump和KrkrExtract的接口,但我暂时没有使用过它们复现工作流。
视频 demo:
demo.mp4
更长的 demo 在 bilibili
DuolinGal 是一套面向 KiriKiri Z galgame 的本地优先研究工具链。
它把“资源提取 -> 台词对齐 -> 角色数据集导出 -> GPT-SoVITS 训练/量产 -> 游戏补丁回灌”串成了一条可复现的工程工作流,适合做:
- 英文配音补丁
- 中文配音补丁
- 角色级 TTS 研究与批量验证
当前项目已经在《千恋*万花》上跑通:
- 资源提取与脚本反编译
- 台词与语音对齐
- 角色数据集导出
- GPT-SoVITS 单角色训练
- 多角色夜量产
- 批量
wav -> ogg回灌 - 游戏内
unencrypted/覆盖与patch-build重建 - 最终
.xp3补丁打包并发布
DuolinGal 是一条已经工程化的工作流。它解决的核心问题是:
- 把 galgame 里的文本、语音、角色拆成可训练数据
- 让 GPT-SoVITS 在 Windows 单卡环境下稳定训练与批量推理
- 把生成结果重新整理成游戏可直接覆盖的语音树
- 为最终的目标语言语音补丁打包
- 分析游戏目录,识别 KiriKiri Z 常见特征
- 初始化可复现的项目工作区
- 解包(需要手动操作)
- 调用外部工具反编译
.scn/.psb - 构建
lines.csv与脚本节点索引 - 导出角色级 TTS 训练数据集
- 生成 GPT-SoVITS 训练清单与多语言预览
- 生成单角色 GPT-SoVITS 训练工作区
- 生成并执行可恢复的多角色 GPT-SoVITS 量产队列
- 批量把生成语音转成游戏覆盖用
.ogg - 重建项目级
patch-build - 打包
.xp3补丁
在开始之前,请先确认下面几样东西已经可用:
GARbro当前已验证的主线是手动解包scn.xp3和voice.xp3FreeMote用于反编译脚本资源FFmpeg用于音频格式转换KirikiriTools用于最终patch2.xp3打包- 本地
GPT-SoVITS仓库 GPTSoVitsconda 环境
当前真正复现成功的路径是:手动解包 + DuolinGal 构建项目 + 本地 GPT-SoVITS 训练/量产。
prepare-krkrdump/KrkrExtract相关入口仍然保留,但未复现。
pip install -e .复制:
为:
configs/toolchain.local.json
然后只编辑本地副本。
目前没有成功复现自动解包,总是显示 Steam Error Application load error,因此可以不填写解包工具路径(krkrdump krkrextract),直接手动解包游戏资源到指定目录即可。
$env:PYTHONPATH='src'
python -m duolingal analyze "<GAME_DIR>"
python -m duolingal init-project "<GAME_DIR>" --project-id senren-banka
# 由于自动化解包我没有复现成功,这里不用命令,用 GARbro 或其他解包工具做:
# 1. 把 scn.xp3 解到 "<PROJECT_ROOT>\extracted_script"
# 2. 把 voice.xp3 解到 "<PROJECT_ROOT>\extracted_voice"
python -m duolingal preflight "<PROJECT_ROOT>" --config configs/toolchain.local.json
python -m duolingal decompile-scripts "<PROJECT_ROOT>" --config configs/toolchain.local.json
python -m duolingal preflight "<PROJECT_ROOT>" --config configs/toolchain.local.json
python -m duolingal build-lines "<PROJECT_ROOT>"
python -m duolingal export-dataset "<PROJECT_ROOT>" "<PROJECT_ROOT>\extracted_voice"
python -m duolingal prepare-gptsovits "<PROJECT_ROOT>"跑到这里为止,你已经完成了:
- 项目初始化
- 脚本与语音资源导出
- 角色级训练清单与多语言预览生成
接下来请按目标进入下面三条路径之一。
如果你想先验证某个角色能不能训出来、听起来像不像原角色,当前推荐顺序是:
prepare-gptsovits-train
-> run-prepare-all.ps1
-> run-train-gpt.ps1
-> run-train-sovits.ps1
-> 准备目标语言批次
-> 本地试听 / 回灌游戏
先生成单角色训练工作区:
$env:PYTHONPATH='src'
python -m duolingal prepare-gptsovits-train "<PROJECT_ROOT>" --speaker "<SPEAKER_NAME>"然后进入生成出来的:
tts-training/<EXPERIMENT_NAME>/scripts/
按顺序运行:
powershell -NoProfile -ExecutionPolicy Bypass -File .\run-prepare-all.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\run-train-gpt.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\run-train-sovits.ps1可以看看这些文档:
如果你已经不只是验证单角色,而是要顺序训练多个角色并批量生成目标语言语音,当前推荐顺序是:
prepare-gptsovits-production
-> run-gptsovits-production
-> 每角色自动执行:
前处理 -> GPT -> SoVITS -> 切权重 -> 推理 -> wav -> ogg
-> 合并总覆盖树
-> 重建 patch-build
-> 可选同步到真实游戏目录
先准备一条量产计划。
默认不传 --target-language 时,会准备英文量产计划,计划目录通常会叫:
tts-production/all-cast-v1
例如准备一条简体中文量产计划:
$env:PYTHONPATH='src'
python -m duolingal prepare-gptsovits-production "<PROJECT_ROOT>" --target-language zh-cn如果只想排部分角色:
$env:PYTHONPATH='src'
python -m duolingal prepare-gptsovits-production "<PROJECT_ROOT>" `
--speaker "ムラサメ" `
--speaker "芳乃" `
--speaker "茉子" `
--target-language zh-cn然后运行:
$env:PYTHONPATH='src'
python -m duolingal run-gptsovits-production "<PROJECT_ROOT>\tts-production\all-cast-zh-cn-v1"或者直接执行生成出来的:
tts-production/<PLAN_NAME>/scripts/run-production.ps1
如果某些角色需要固定锚点,或某些角色暂时应排除在量产队列外,请在项目根目录放:
tts-production/production-overrides.json
多角色量产的详细说明看:
量产跑完以后,不要直接删原始成果。当前正确顺序是:
run-gptsovits-production
-> prepare-final-cleanup
-> 审核 cleanup-review.ready.csv
-> 在副本上删除不该覆盖原音的 .ogg
-> rebuild-patch-from-clean-copy.ps1
-> patch-build/<CLEANUP_PATCH_DIR>/pack-patch2.ps1
-> patch2.xp3
先生成安全副本:
$env:PYTHONPATH='src'
python -m duolingal prepare-final-cleanup "<PROJECT_ROOT>"然后在:
tts-release/final-cleanup-v1/review/cleanup-review.ready.csv
里只把你确认应当回退原日语的行标成 remove。
接着运行:
powershell -NoProfile -ExecutionPolicy Bypass -File "<PROJECT_ROOT>\tts-release\final-cleanup-v1\scripts\apply-reviewed-removals.ps1"
powershell -NoProfile -ExecutionPolicy Bypass -File "<PROJECT_ROOT>\tts-release\final-cleanup-v1\scripts\rebuild-patch-from-clean-copy.ps1"最后进入清理后补丁对应的 namespaced 目录,例如:
- 英文:
<PROJECT_ROOT>\patch-build\all-cast-v1-final-cleanup-v1 - 简中:
<PROJECT_ROOT>\patch-build\all-cast-zh-cn-v1-final-cleanup-zh-cn-v1
执行:
powershell -NoProfile -ExecutionPolicy Bypass -File .\pack-patch2.ps1得到最终的:
- 英文清理版:
<PROJECT_ROOT>\patch-build\all-cast-v1-final-cleanup-v1\patch2.xp3 - 简中清理版:
<PROJECT_ROOT>\patch-build\all-cast-zh-cn-v1-final-cleanup-zh-cn-v1\patch2.xp3
说明:
- 最终补丁文件名仍然必须叫
patch2.xp3 - 但现在不同语言/流程会放进不同文件夹,不再互相覆盖
当前仓库已经支持一条 可恢复 的多角色量产队列,流程如下:
export-dataset
-> prepare-gptsovits
-> prepare-gptsovits-production
-> run-gptsovits-production
-> speaker prepare
-> speaker GPT
-> speaker SoVITS
-> batch infer
-> wav -> ogg
-> combined override tree
-> patch-build
-> optional game-root sync
更具体地说:
prepare-gptsovits-production负责扫描角色、生成训练工作区、写出夜跑计划和run-production.ps1run-gptsovits-production负责顺序执行:前处理 -> GPT -> SoVITS -> 切权重 -> 批量推理 -> 转 OGG -> 合并覆盖树 -> 重建 patch-build- 队列是可恢复的
中断后重新执行同一个
run-production.ps1,已完成角色会自动跳过 - 队列会持续更新:
production-state.jsonproduction-status.txt
这一点很重要:训练出来的角色权重、配置和批量生成结果,都应该长期保存。
至少建议保留这些目录:
<PROJECT_ROOT>/tts-training/<EXPERIMENT_NAME>/weights/gpt/<PROJECT_ROOT>/tts-training/<EXPERIMENT_NAME>/weights/sovits/<PROJECT_ROOT>/tts-training/<EXPERIMENT_NAME>/configs/<PROJECT_ROOT>/tts-production/<PLAN_NAME>/
原因很简单:
- 这些权重是你已经花时间、显卡和调参成本换来的成果
- 它们不只是能给当前语言版本用,也能给后续其他文本版本复用
当前仓库已经支持基础保护:
- 纯标点目标文本在批次准备阶段会被跳过
- 个别被
/tts判为无效文本的句子会被记录并跳过
但更强的“纯语气/弱句保留原音”规则,当前建议放到整轮量产结束之后做最后收尾,而不是提前加进跑主线。
原因是:
- 过早做强过滤,容易误删本来已经生成得不错的目标语言语音
- 量产先跑完,才能保住尽可能完整的第一版成果
- 最后如果删掉某些
.ogg,游戏会自然回退到原始日语语音
当前更推荐的顺序是:
- 先完成整轮训练、推理、转码、覆盖树构建
- 运行
prepare-final-cleanup,生成一份安全副本 - 审核
cleanup-review.ready.csv - 再在副本上清理纯语气句、叫声、拟声句
- 用清理后的副本重建
patch-build - 最后把清理后的副本用于正式 release 打包
对应命令是:
$env:PYTHONPATH='src'
python -m duolingal prepare-final-cleanup "<PROJECT_ROOT>"- Feasibility and Risk Assessment
- Project Plan
- Structure and Runtime Flow
- Local Validation Checklist
- Single-line PoC Guide
- Patch Packaging Guide
- Dataset Export Guide
- GPT-SoVITS Preparation Guide
- GPT-SoVITS Batch Guide
- GPT-SoVITS Reinject Guide
- GPT-SoVITS Training Guide
- GPT-SoVITS Local Runbook
- GPT-SoVITS Production Guide
如果你只是按上面的 CLI 工作流复现项目,可以先跳过本节。
本地 API 更适合你准备自己包一层界面或服务时再用。
可选安装 API 依赖并启动 FastAPI:
pip install -e .[api]
$env:PYTHONPATH='src'
uvicorn duolingal.api.app:create_app --factory --reload可用接口包括:
GET /healthPOST /api/analyzePOST /api/projects/initPOST /api/projects/preflightPOST /api/projects/build-linesPOST /api/projects/export-datasetPOST /api/projects/prepare-gptsovitsPOST /api/projects/prepare-gptsovits-batchPOST /api/projects/prepare-gptsovits-trainPOST /api/projects/prepare-gptsovits-productionPOST /api/projects/run-gptsovits-production
DuolinGal/
|-- apps/
|-- configs/
|-- docs/
|-- src/duolingal/
| |-- api/
| |-- core/
| |-- domain/
| `-- services/
`-- tests/
当前仓库已经证明:
- 角色级训练可以在 Windows 单卡环境下稳定运行
- 多角色量产可以持续推进
- 可以在安全副本上做最终弱句清理并回退原音
- 生成语音可以真正回灌到游戏里体验
没有解决:
- 专有名词发音词典,比如角色名总是被英语自然拼读,而不是正确的日语发音
- 最佳 epoch 自动搜索
- 弱句/拟声句的最终判定仍然需要人工审核,当前不建议前置自动强过滤
所以当前更适合把 DuolinGal 看成:
-
一条已经打通的 工程化研究工作流
-
一个能持续产出成果的 本地量产入口
