VoxCPM2 v5 音色克隆:脚本、参考音频、游戏对白与状态文档

通过 Voice Design 试听选定各角色参考音色,Style Control 全量克隆并部署到 audio/mp3/tts;清理未引用音频与 audio_1 旧产物。
This commit is contained in:
xsl
2026-05-24 00:34:50 +08:00
parent bb79a69bd2
commit 12eb1eab44
1085 changed files with 1779 additions and 955 deletions
+236
View File
@@ -0,0 +1,236 @@
# 《林夏》音频制作 — 当前状态说明
> 更新日期:2026-05-23
> 本文档记录 TTS 音色选型、全量生成、游戏部署的**现行状态**,便于下次继续迭代。
---
## 1. 一句话总结
**游戏当前使用的是 v5 克隆音色**:从 Voice Design 试听样本中选定参考音频 → VoxCPM2 Style Control 克隆 → 部署到 `audio/mp3/tts/*_wav_v1.mp3`
`audio/mp3/` 已清理,仅保留游戏引用的 **184** 个文件。
---
## 2. 游戏实际加载哪些音频
游戏代码在 `game/js/story.js``game/js/engine.js`,根路径:
```
../audio/mp3/
├── tts/ 对白(177 条)
├── music/ BGM、铃声
├── sfx/ 音效
└── ambience/ 环境音
```
### 命名规则(重要)
| 文件名 | 游戏是否使用 |
|--------|-------------|
| `*_wav_v1.mp3` | **是** — 全部对白、系统语音都用这种 |
| `*_mp3_v1.mp3` | **否** — 旧流水线遗留,已全部删除 |
后缀里的 `wav` 表示「用 WAV 参考音色生成的 v1 版」,文件格式仍是 MP3。
### 示例
```
game/js/story.js → npc('lv11_0015_mom_call_01_wav_v1.mp3')
实际文件 → audio/mp3/tts/lv11_0015_mom_call_01_wav_v1.mp3
```
**不需要改 `story.js`**,只要更新 `audio/mp3/tts/` 里对应的 `*_wav_v1.mp3` 即可。
---
## 3. TTS 服务
| 项目 | 路径 / 值 |
|------|-----------|
| 服务目录 | `/home/xsl/tts-server/` |
| 启动脚本 | `VOXCPM_PORT=8002 VOXCPM_ENABLE_DENOISER=0 bash /home/xsl/tts-server/start-voxcpm.sh` |
| 端口 | **8002**8000 被 head3d 占用) |
| 健康检查 | `curl http://127.0.0.1:8002/health` |
| 主要接口 | `POST /v1/voices` 注册参考音频 |
| | `POST /v1/speech/styled` 合成(`voice_id` + `style` = 克隆;无 `voice_id` = Voice Design |
---
## 4. 音色演进(v1 → v5
| 版本 | 目录 | 方式 | 状态 |
|------|------|------|------|
| v1 | `audio_1/tts/v1_voxcpm2/` | 旧参考音频直接克隆,无 style | 已被 v5 替代 |
| v2 | `audio_2/tts/v2_styled/`(已不在磁盘) | 旧参考 + Style Control 表演 | 已废弃 |
| v3 | `audio_2/tts/v3_voice_design/`(已不在磁盘) | 纯 Voice Design,无参考 | 已废弃 |
| v4 | `audio_2/tts/v4_voice_samples/` | 每角色 5 条试听,用户挑选 | **保留选定样本** |
| **v5** | `audio_2/tts/v5_cloned/` | 选定样本克隆 + 表演修饰 | **当前正式版** |
| 游戏 | `audio/mp3/tts/*_wav_v1.mp3` | v5 自动部署副本 | **游戏正在使用** |
---
## 5. 各角色选定的参考音色(v4 试听挑选)
参考文件位于 `audio_2/tts/v4_voice_samples/{角色}/`,每角色仅保留 1 条 `.wav`
| 角色 | 选定文件 | 性别 |
|------|----------|------|
| linxia | `linxia_v05.wav` | 女 |
| mom | `mom_v01.wav` | 女 |
| azhe | `azhe_v03.wav` | 男 |
| xiaomei | `xiaomei_v05.wav` | 女 |
| xiaomei_drunk | `xiaomei_drunk_v05.wav` | 女 |
| zhounan | `zhounan_v05.wav` | 男 |
| hr | `hr_v05.wav` | 女 |
| anan | `anan_v04.wav` | 女 |
| dorm_a | `dorm_a_v03.wav` | 女 |
| dorm_b | `dorm_b_v02.wav` | 女 |
| dorm_c | `dorm_c_v03.wav` | 女 |
| delivery | `delivery_v04.wav` | **男** |
| self_3y | `self_3y_v03.wav` | 女 |
副本已同步到 `voice/{角色}/{角色}_ref.wav``xiaomei_drunk``voice/xiaomei/xiaomei_drunk_ref.wav``self_3y``voice/linxia/self_3y_ref.wav`)。
---
## 6. v5 全量生成结果
- **177 条** MP3`audio_2/tts/v5_cloned/*_wav_v5.mp3`
- **177 条**已部署:`audio/mp3/tts/*_wav_v1.mp3`
- 生成清单:`audio_2/tts/v5_cloned/clone_manifest.tsv`
来源台词表:`audio/batch_tts_voxcpm.py``LINES`173 条)+ 脚本内 `EXTRA_LINES`4 条):
| 额外文件 | 角色 | 说明 |
|----------|------|------|
| `lv11_0030_self3y_voice_01/02/03` | self_3y | 三年前录音三版 |
| `lv11_sys_memo_01` | linxia | 系统提示「三年前今天…」 |
克隆时**只用表演修饰**(warm/cold/分段等),音色完全由参考 wav 决定。配置见 `audio_2/voice_style_prompts.py``get_clone_style()`
---
## 7. 目录结构速查
```
blind/
├── game/js/story.js 游戏剧情 + 音频引用
├── game/js/engine.js 系统语音、结局、BGM
├── audio/
│ ├── batch_tts_voxcpm.py 台词表 LINES + 角色语速 ROLES
│ └── mp3/ 游戏运行时音频(184 文件,已清理)
│ ├── tts/ 177 条对白
│ ├── music/
│ ├── sfx/
│ └── ambience/
├── voice/ 各角色参考音频(含 v5 选定副本)
└── audio_2/
├── 项目状态说明.md ← 本文档
├── 角色语音风格提示词.md Voice Design 说明(历史参考)
├── voice_style_prompts.py 表演修饰 + Voice Design 提示词
├── voice_sample_prompts.py v4 试听:5 变体/角色 + 统一试听文本
├── scripts/
│ ├── 01_gen_tts_styled.py v2 Style Control(旧)
│ ├── 02_gen_tts_voice_design.py v3 Voice Design(旧)
│ ├── 03_gen_voice_samples.py v4 生成试听样本
│ └── 04_gen_tts_clone.py v5 克隆 + 部署游戏 ★
└── tts/
├── v4_voice_samples/ 选定参考音色(每角色 1 wav + mp3)
└── v5_cloned/ 正式产物 + clone_manifest.tsv
```
---
## 8. 常用命令
### 启动 TTS
```bash
VOXCPM_PORT=8002 VOXCPM_ENABLE_DENOISER=0 bash /home/xsl/tts-server/start-voxcpm.sh
curl http://127.0.0.1:8002/health
```
### 重跑全量克隆(改参考音频或提示词后)
```bash
cd /home/xsl/blind
VOXCPM_PORT=8002 python audio_2/scripts/04_gen_tts_clone.py --force
```
- 输出:`audio_2/tts/v5_cloned/*_wav_v5.mp3`
- 自动覆盖:`audio/mp3/tts/*_wav_v1.mp3`
### 只重跑某角色
```bash
VOXCPM_PORT=8002 python audio_2/scripts/04_gen_tts_clone.py --role mom --force
```
### 重新生成某角色试听(换提示词挑音色)
```bash
VOXCPM_PORT=8002 python audio_2/scripts/03_gen_voice_samples.py --role delivery --force
```
### 预览任务不合成
```bash
python audio_2/scripts/04_gen_tts_clone.py --dry-run
```
---
## 9. 其他音频服务(非 TTS)
| 用途 | 位置 |
|------|------|
| 音乐 / 音效生成 | `/home/xsl/tools/ACE-Step-1.5` |
| Stable Audio | `/home/xsl/tools/stable-audio-tools` |
| UI 短音效 | Web Audio(浏览器内合成) |
VoxCPM2 **不能**用提示词生成敲门、心跳等 SFX,只能做人声 TTS。
---
## 10. 已知注意点
1. **Voice Design 音色不稳定**:同角色各条可能漂移,因此最终方案是「试听选定 → 克隆锚定」。
2. **外卖小哥语速**`delivery` 提示词已调慢,`ROLES["delivery"]["speed"]` 已从 1.20 改为 **1.00**
3. **男声角色**`azhe``zhounan``delivery`
4. **重新清理未使用音频**:扫描 `game/js/*.js``audio/mp3/` 对比删除;当前已对齐(184 = 184)。
5. **改游戏引用**:若将来改用 `_wav_v5.mp3` 等新后缀,需批量改 `story.js` / `engine.js`;目前无需改动。
---
## 11. 下次可继续的事
- [ ] 实机/playtest 听一遍各角色,标记需重跑的台词或角色
- [ ] 若某角色不满意:改 `voice_sample_prompts.py` → 重跑 `03` 挑选 → 替换 `v4_voice_samples/{role}/` → 重跑 `04`
- [ ] 微调单条表演:改 `voice_style_prompts.py``_performance` 规则 → `--role xxx --force`
- [ ] 设计文档:`林夏.md``执行文档_音频素材制作.md`
---
## 12. 快速验证游戏音频是否正常
```bash
# 游戏引用的文件是否都存在
python3 - <<'PY'
import re
from pathlib import Path
root = Path("/home/xsl/blind")
text = "".join((root/"game/js/story.js").read_text() + (root/"game/js/engine.js").read_text())
refs = set()
for m in re.finditer(r'\$\{(MUS|SFX|AMB|T)\}/([^`\']+\.mp3)', text):
sub = {'MUS':'music','SFX':'sfx','AMB':'ambience','T':'tts'}[m.group(1)]
refs.add(root/f"audio/mp3/{sub}/{m.group(2)}")
for m in re.finditer(r"(?:npc|lx|rx)\('([^']+\.mp3)'\)", text):
refs.add(root/f"audio/mp3/tts/{m.group(1)}")
missing = [r for r in refs if not r.exists()]
print(f"引用 {len(refs)} 缺失 {len(missing)}")
for p in sorted(missing): print(" MISSING:", p.relative_to(root))
PY
```
预期输出:`缺失 0`