从 Galgame 中训练想要的角色声音模型
从 Galgame 中训练想要的角色声音模型
用 Qwen3-TTS 微调,让 AI 用你喜欢的角色声音说话
前言
每个 Galgame 玩家都有自己喜欢的角色。如果能让这个角色"活"过来,用她的声音说任何话,是不是很酷?
本文记录了我从一款 Galgame 中提取角色语音数据,并用 Qwen3-TTS 训练出该角色声音模型的完整过程。最终成果通过AstrBot 插件,可以自动将中文回复翻译成日语,再用训练好的角色声音合成语音。
你需要准备
| 工具 | 用途 | 获取方式 |
|---|---|---|
| GARbro | Galgame 资源解包 | GitHub |
| Python 3.12 | 运行环境 | Anaconda |
| Qwen3-TTS | TTS 模型 | pip install qwen-tts |
| Whisper | 语音识别(转录) | pip install openai-whisper |
| CUDA GPU | 加速训练/推理 | NVIDIA 显卡 |
第一步:用 GARbro 解包 Galgame
什么是 GARbro?
GARbro 是一个万能的 Galgame 资源浏览器/解包工具,支持几乎所有日系游戏的文件格式(XP3、ARC、HCB 等)。
解包步骤
-
安装 GARbro(建议用中文版 garbro-cn)
-
打开游戏目录下的资源文件(如
.hcb、.xp3) -
浏览其中的文件结构:
voices/— 语音文件(.ogg 格式)text/— 剧本文本images/— CG 图片
-
全选 → 右键 → 解包到指定目录
E:\galgame_kb\
├── voices\ ← 所有语音文件
│ ├── voice_00001.ogg
│ ├── voice_00002.ogg
│ └── ...
├── text\ ← 剧本文本
│ ├── all_dialogue.txt
│ └── shinku_dialogue.txt
└── shinku_voice_indices.txt ← 角色语音索引
提取角色语音
不是所有语音都是你想训练的角色。需要通过游戏脚本或 HCB 文件分析,确定哪些语音属于目标角色。
我的做法是写 Python 脚本分析 HCB 文件(游戏引擎的编译脚本),找到 SHINKU_ 开头的场景标签,定位真红的台词和对应的语音文件索引:
# 伪代码:在 HCB 二进制中搜索角色标签
while i < len(data):
if data[i:i+7] == b'SHINKU_':
label = extract_label(data, i)
shinku_labels.append(label)
i += 1
最终得到属于目标角色的语音文件。
第二步:准备训练数据
2.1 语音转文字(Whisper)
游戏语音没有附带字幕文本映射,需要识别每条语音说了什么。用 OpenAI 的 Whisper 模型:
import whisper
model = whisper.load_model("medium")
for voice_file in voice_files:
result = model.transcribe(voice_file, language="ja")
text = result["text"].strip()
# 保存到训练 JSONL
输出效果:
voice_00001.ogg → "どうしたの?大丈夫かな?"
voice_00002.ogg → "ねえ、ちょっと待ってよ"
voice_00003.ogg → "えっ、なに?"
2.2 音频格式转换
Qwen3-TTS 要求 24kHz WAV 格式。游戏中的语音通常是 44.1kHz 或 48kHz 的 OGG 格式,需要统一转换:
import torchaudio
wav, sr = torchaudio.load("voice_00001.ogg")
if sr != 24000:
wav = torchaudio.functional.resample(wav, sr, 24000)
torchaudio.save("utt_0001.wav", wav, 24000)
2.3 选择参考音频
参考音频(ref_audio)是 TTS 时用来"告诉"模型要模仿谁的声音。选择标准:
- 时长 3~10 秒
- 声音清晰,没有背景音乐
- 情绪稳定(不要太激动或太安静)
2.4 组装 JSONL 训练文件
{"audio": "utt_0001.wav", "text": "どうしたの?大丈夫かな?", "ref_audio": "ref_24k.wav"}
{"audio": "utt_0002.wav", "text": "ねえ、ちょっと待ってよ", "ref_audio": "ref_24k.wav"}
{"audio": "utt_0003.wav", "text": "えっ、なに?", "ref_audio": "ref_24k.wav"}
注意:ref_audio 建议所有样本用同一个,这样训练出的声音一致性更好。
第三步:提取 Audio Codes
Qwen3-TTS 的训练不是直接用原始音频,而是先用 Tokenizer 把音频编码成离散的 token(audio_codes):
python prepare_data.py \
--device cuda:0 \
--tokenizer_model_path Qwen/Qwen3-TTS-Tokenizer-12Hz \
--input_jsonl train_raw.jsonl \
--output_jsonl train_with_codes.jsonl
处理后的数据多了 audio_codes 字段:
{
"audio": "utt_0001.wav",
"text": "どうしたの?大丈夫かな?",
"ref_audio": "ref_24k.wav",
"audio_codes": [1995, 1159, 355, 22, ...]
}
第四步:微调模型
4.1 下载基础模型
# Tokenizer(编码/解码音频)
modelscope download --model Qwen/Qwen3-TTS-Tokenizer-12Hz
# Base 模型(微调起点)
modelscope download --model Qwen/Qwen3-TTS-12Hz-1.7B-Base
4.2 开始训练
python sft_12hz.py \
--init_model_path Qwen3-TTS-12Hz-1.7B-Base \
--output_model_path output \
--train_jsonl train_with_codes.jsonl \
--batch_size 2 \
--lr 1e-5 \
--num_epochs 10 \
--speaker_name shinku
4.3 训练过程解读
Epoch 0 | Step 0 | Loss: 13.08 ← 刚开始,模型完全不认识这个声音
Epoch 0 | Step 10 | Loss: 8.49 ← 快速下降,模型在学
Epoch 3 | Step 0 | Loss: 5.97 ← 学到了基本特征
Epoch 7 | Step 0 | Loss: 4.47 ← 声音越来越像
Epoch 9 | Step 30 | Loss: 4.96 ← 接近收敛
关键参数说明:
- Batch Size = 2:每次喂 2 条数据(受显存限制)
- Learning Rate = 1e-5:学习率,小一点学得稳
- 10 Epochs:71 条数据 × 10 遍 = 710 次训练
4.4 过拟合警告
Epoch 不是越多越好。训练太多遍,模型会"背答案"——对训练数据表现很好,但说新内容时声音会变形。
70 条左右的数据,7~15 个 epoch 比较安全。
第五步:部署 API 服务器
写一个 FastAPI 服务器,让 AstrBot 等外部程序可以调用:
from qwen_tts import Qwen3TTSModel
model = Qwen3TTSModel.from_pretrained(
"output/checkpoint-epoch-9",
device_map="cuda:0"
)
@app.post("/tts")
async def tts(request: TTSRequest):
audio_list, sample_rate = model.generate_custom_voice(
text=request.text,
speaker="shinku",
language="japanese",
non_streaming_mode=True,
)
# 返回 WAV 音频
启动:python server.py,监听 0.0.0.0:9880
第六步:接入你的应用
训练好的模型可以接入各种应用,以下是一个实际例子——将角色声音集成到聊天机器人中:
用户 QQ 消息
↓
LLM 生成中文回复
↓
插件拦截文本
↓
调用 LLM 翻译成日语(带强制翻译提示词)
↓
调用本地 Qwen3-TTS 服务器(端口 9880)
↓
返回日语语音到 QQ
常见问题
Q: 训练数据太少怎么办?
70 条是个最低门槛。如果效果不够好,可以:
- 用 Whisper 转录更多语音
- 从游戏其他场景中找目标角色的语音
- 用 Data Augmentation(变速、加噪等)扩充数据
Q: 训练需要什么硬件?
- 最低:10G+显存N卡
- 显存不够:用 0.6B 小模型替代 1.7B
Q: Loss 降到多少算好?
没有绝对标准。一般来说:
- 从 13+ 降到 5 以下就有效果
- 3~5 之间通常比较理想
- 低于 2 可能过拟合了
Q: 可以训练其他语言吗?
可以。Qwen3-TTS 原生支持 10 种语言(中日英韩德法俄葡西意),微调不限语言。
总结
整个流程概括:
GARbro 解包 → 提取角色语音 → Whisper 转文字 → 转 24kHz WAV → 训练 JSONL → 微调 Qwen3-TTS → 部署 API → 集成 AstrBot
数据量不大(70 条),训练时间不长(约 20 分钟),但效果已经能听出角色的音色特征。如果想要更精细的效果,增加训练数据是最有效的方式。
项目地址:astrbot_plugin_translate_tts
模型来源:Qwen3-TTS
更多推荐



所有评论(0)