Russian narration for the Enshrouded notes: mod 0.4.0, installer, generation pipeline

This commit is contained in:
2026-10-18 15:56:52 +03:00
commit 73dee2d786
557 changed files with 4051 additions and 0 deletions
+187
View File
@@ -0,0 +1,187 @@
# Enshrouded — русская озвучка записок
Русская озвучка всех **525 озвученных записок и мини-историй** (Ministory) Enshrouded. Голос — клон
английского диктора игры, текст — официальный русский перевод игры. Мод ставится через EML
(Enshrouded Mod Loader) и не трогает оригинальные файлы игры.
| | |
|---|---|
| Версия | 0.4.0 (игра 1.0, октябрь 2026) |
| Объём | 525 записок, 425 минут, 467 МБ |
| Синтез | Qwen3-TTS 1.7B, дообучение [`ru-stress-cf`](https://huggingface.co/siriusfreak/qwen3-tts-12hz-1.7b-ru-stress-cf) с ударениями, ICL-клон диктора |
| Контроль | автоматический, без прослушивания: ударения 99,9 % по всем кускам; WER 2,4 % и MOS 3,45 на выборке из 60 записок |
> Озвучка — синтез, а не запись актёра. Голос повторяет тембр английского диктора, тексты принадлежат
> Keen Games. Это любительский мод: не продавайте его и не выдавайте за официальный.
## Что в репозитории
```
mod/ru_voice_notes/ готовый мод: data/*.qoa (Git LFS), src/*.lua, mod.json
install.py установка и удаление мода (только стандартная библиотека Python)
run.py конвейер генерации по шагам (каждый шаг в своём окружении)
ensvoice/ ключевые скрипты конвейера
extract.py тексты и английский звук из файлов игры
refs.py референсы диктора, его тембр и паузы
segments.py текст для голоса: лексикон, ударения, нарезка по абзацам
lexicon.py ← главное место для правок: имена, ударения, сокращения
render.py, tts/ синтез (локальный GPU или сервер media-node)
qc.py, pick.py автоматическая проверка дублей и отбор лучшего
assemble.py, mod.py склейка записок, QOA, сборка мода
refbench.py сравнение референсов голоса по метрикам
env/ зависимости двух окружений
docs/GENERATION.md как устроена генерация и как её улучшать
config.example.toml пример настроек
```
В репозиторий не попадают данные, извлечённые из игры (`work/`), окружения (`.venv-*`), модели,
бинарники EML (`tools/`) и `config.toml`: всё это перечислено в `.gitignore`.
---
## Установка мода (для игрока)
Нужны Windows, Steam-версия Enshrouded, Python 3.11+, Git с Git LFS.
```bash
git clone https://git.shahovalov.ru/mikhail/enshrouded-ru-voice.git
cd enshrouded-ru-voice
git lfs pull
python install.py
```
В конце должна появиться строка `[ru_voice] replaced 525 notes, 0 failed`, затем `INSTALLED`.
Игру запускать как обычно, из Steam. Язык озвучки в игре оставить **английским**: мод подменяет
английскую дорожку записок, своего русского слота у озвучки в игре нет.
Удаление: `python install.py --uninstall` (или «Проверить целостность файлов» в Steam).
---
## Инструкция для агента: установка
Агент выполняет шаги по порядку. После каждого шага есть проверка: если она не прошла, агент не идёт
дальше и разбирает причину по таблице ниже. Команды даны для Git Bash или PowerShell 7 на Windows.
### A. Только поставить мод (без генерации)
1. **Проверить окружение.**
```bash
python --version
git lfs version
```
Ожидаемо: Python 3.11 или новее, git-lfs 3.x. Если Python нет, поставить `winget install Python.Python.3.12`;
если нет Git LFS, поставить `winget install GitHub.GitLFS`, затем выполнить `git lfs install`.
2. **Клонировать и скачать звук.**
```bash
git clone https://git.shahovalov.ru/mikhail/enshrouded-ru-voice.git
cd enshrouded-ru-voice
git lfs pull
```
Проверка: в `mod/ru_voice_notes/data` лежат 525 файлов `.qoa`, все больше 1 КБ, вместе около 467 МБ.
Файлы меньше 1 КБ — это LFS-указатели: снова выполнить `git lfs pull`.
3. **Спросить пользователя**, закрыта ли игра и можно ли записать в папку игры `dbghelp.dll` и
`mods/ru_voice_notes`. Без согласия дальше не идти.
4. **Установить.**
```bash
python install.py
```
Если игра стоит не в библиотеке Steam, добавить `--game "<папка с enshrouded.kfc>"`.
Ожидаемо: строки `[ru_voice] replaced 525 notes, 0 failed` и `INSTALLED`.
5. Сообщить пользователю: игру запускать из Steam, язык озвучки оставить английским, записки читаются
по-русски. Откат: `python install.py --uninstall`.
### B. Поставить конвейер генерации (чтобы дорабатывать)
Требования: NVIDIA GPU с 12 ГБ VRAM и больше (проверено на RTX 5080 16 ГБ и Tesla V100 32 ГБ),
32 ГБ RAM, около 35 ГБ на диске (модели около 10 ГБ, рабочая папка около 15 ГБ), свежий драйвер NVIDIA
(CUDA 12.8), [uv](https://docs.astral.sh/uv/). Сначала выполнить раздел A до шага 2 включительно.
1. **Проверить GPU и uv.**
```bash
nvidia-smi
uv --version
```
Если `uv` нет: `winget install astral-sh.uv`.
2. **Создать два окружения.** Их два, потому что `qwen-tts` требует transformers 4.x, а модели контроля
качества требуют 5.x.
```bash
uv venv -p 3.12 .venv-tts
uv pip install -p .venv-tts/Scripts/python.exe torch torchaudio --index-url https://download.pytorch.org/whl/cu128
uv pip install -p .venv-tts/Scripts/python.exe -r env/tts.txt
uv venv -p 3.12 .venv-qc
uv pip install -p .venv-qc/Scripts/python.exe torch torchaudio --index-url https://download.pytorch.org/whl/cu128
uv pip install -p .venv-qc/Scripts/python.exe -r env/qc.txt
```
На Linux путь к интерпретатору — `.venv-tts/bin/python`.
3. **Настроить.** Скопировать `config.example.toml` в `config.toml` и заполнить:
- `paths.game` — папка игры (её нашёл `install.py`, путь напечатан в строке `game:`);
- `paths.work` — папка на **том же диске, что и игра** (см. «Ловушки»), с 15 ГБ свободного места;
- `tts.dtype` — `bfloat16` для RTX 30xx и новее, `float16` для RTX 20xx, GTX 16xx, V100.
4. **Инструменты EML.** Если `install.py` ещё не запускался, скачать их через него, ответив пользователю
по шагу A.3, либо взять `kfc-parser.exe` и `emm.exe` вручную из релиза
[Brabb3l/kfc-parser v0.2.0](https://github.com/Brabb3l/kfc-parser/releases/tag/v0.2.0) в `tools/`.
5. **Проверить установку.**
```bash
python run.py check
```
Ожидаемо: две строки с версией torch, `cuda True` и именем GPU, затем `CHECK_OK`.
6. **Пробный прогон на трёх записках**, около 15 минут. Модели (около 10 ГБ) скачиваются с Hugging Face
при первом запуске.
```bash
export ENSVOICE_NOTES=n016,n238,n363 # PowerShell: $env:ENSVOICE_NOTES="n016,n238,n363"
python run.py extract
python run.py refs
python run.py segments
python run.py render
python run.py qc
python run.py pick
python run.py assemble
```
Ожидаемо: после `extract` — `notes 525 EN minutes 488`; после `refs` —
`configured reference ... found`; после `pick` — `'segments': 16, 'picked': 16`;
после `assemble` — `ASSEMBLED 3 notes`. Готовые WAV для проверки лежат в `<work>/wav48/`.
**Не запускать** `python run.py mod` с переменной `ENSVOICE_NOTES`: собранный мод заменит в
`mod/ru_voice_notes` все 525 записок тремя.
7. Снять переменную (`unset ENSVOICE_NOTES`) и сообщить пользователю, что конвейер работает.
Полный прогон (`python run.py all`) на RTX 5080 занимает около суток (см. docs/GENERATION.md), его
запускают по просьбе пользователя.
### Ловушки и ошибки
| Симптом | Причина и что делать |
|---|---|
| `extract`: `EN minutes` не 488, а около 425 | В игре применён мод: EML пропатчил `enshrouded.kfc`, и прочиталась русская озвучка. `extract` сам берёт исходный индекс из `enshrouded.kfc.bak` через жёсткие ссылки — для этого `paths.work` должен быть на диске игры. Иначе: `tools/emm.exe restore -g "<игра>"` и повторить `extract`. |
| `install.py`: `close Enshrouded first`, `os error 32` | Игра запущена: закрыть её. |
| `.qoa` по 130 байт, `LFS pointers` | Не скачан LFS: `git lfs install`, затем `git lfs pull`. |
| `render`: `CUDA out of memory` | Уменьшить `tts.batch` до 4. Больше 8 не ставить: на RTX 5080 16 ГБ батч 16 упирается в видеопамять и работает в разы медленнее. |
| `bf16 is not supported` / NaN | GPU старше Ampere: `tts.dtype = "float16"`. |
| `qc` убит, `Killed`, MemoryError | Каждый процесс QC берёт 8–13 ГБ RAM: запускать меньше шардов. |
| `refs`: `configured reference ... NOT FOUND` | Другая версия игры: выбрать id из `<work>/refs.json` через `refbench`. |
| `extract`: `expected 525 voiced notes` | Обновление игры изменило записки: конвейер работает, но мод из репозитория может не подойти — собрать свой. |
---
## Как дорабатывать и делиться
Порядок работы и все приёмы описаны в [docs/GENERATION.md](docs/GENERATION.md). Коротко: правки идут в
`lexicon.py` или конфиг, затем по цепочке `segments → render → qc → pick → assemble → mod` (заново
считаются только изменённые куски) и `python install.py`.
Делиться результатом: ветка с изменениями кода, лексикона и обновлённым `mod/ru_voice_notes` плюс
pull request. В описании PR привести числа из `<work>/pick_report.json` до и после (`wer`, `stress`,
`mos`, `weak`): по ним видно, что правка улучшила озвучку, а не просто изменила её. Без доступа на запись
в этот Gitea — форк или patch-файл с `git format-patch`.
## Благодарности
[Brabb3l/kfc-parser](https://github.com/Brabb3l/kfc-parser) (распаковка и EML) ·
[Qwen3-TTS](https://github.com/QwenLM/Qwen3-TTS) ·
[siriusfreak/qwen3-tts-12hz-1.7b-ru-stress-cf](https://huggingface.co/siriusfreak/qwen3-tts-12hz-1.7b-ru-stress-cf) (ударения и meter2) ·
[RUAccent](https://github.com/Den4ikAI/ruaccent) ·
[GigaAM](https://github.com/salute-developers/GigaAM) ·
[UTMOSv2](https://github.com/sarulab-speech/UTMOSv2) ·
[WavLM](https://huggingface.co/microsoft/wavlm-base-plus-sv)
Код — MIT (см. `LICENSE`). Озвучка в `mod/` — производная от материалов игры и не покрывается
лицензией кода.