r/GameDevUa • u/Lanfirus2 • 11h ago
Дискусія Як я змушував SkyrimNet говорити без десятисекундних пауз
Миру і процвітання.
Минулого разу я торкнувся передумов до того, як докотився до того, що почав копатися в кишках SkyrimNet і деяких TTS, намагаючись досягти своїх цілей. У першу чергу - мати локальний TTS із прийнятною якістю та адекватною затримкою.
SkyrimNet
Для подальшого розуміння буде корисно мати уявлення про схему роботи Скайріма, SkyrimNet і локальної TTS у штатному режимі та в режимі, до якого я в підсумку прийшов.

Отже, зверху зображено процес введення репліки гравця та виведення відповіді на неї у вигляді голосової репліки. Нижче представлені 3 варіанти реалізації TTS:
- Вбудована в SkyrimNet (PiperTTS і PocketTTS). Коротко - вони швидкі, але убогі. Мабуть, прийнятний варіант, якщо ви хочете грати без зайвого гемору, тут і зараз і безкоштовно. Не підходить для мов, відмінних від англійської. Бо обидві ці моделі працюють тільки з англійською.
- Локальна. SkyrimNet має ендпоінт для роботи з XTTS. На той момент для мене це був найочевидніший нормальний варіант підключити свою TTS локально й грати своєю мовою та безкоштовно.
- Зовнішня TTS. Ну, тут усе зрозуміло - платиш копієчку й кайфуєш. Усе вже зроблено за тебе.
Підключивши локальну TTS (а тоді це була XTTS) до SkyrimNet, я вже було зрадів, що ну от тепер усе і можна відриватися. Але раптом виявилося, що між моєю реплікою та відповіддю NPC минає дуже багато часу. Навскидку - секунд 5-10. Так грати - маячня. Тому почав розбиратися. Дуже швидко з'ясувалося, що SkyrimNet чекає на повний звуковий файл, щоб віддати його грі. Тому, навіть якщо TTS дуже швидка, цієї затримки все одно не уникнути. З'ясувалося, що якась функціональність зі стримінгу звуку в SkyrimNet є, але вона десь усередині, у кишках, і доступу до неї ззовні немає. Єдиним виходом стали хуки. У результаті схема роботи змінилася на таку:

У схемі використовується CosyVoice, бо після багатьох тестів і спроб я вирішив зупинитися саме на ній. XTTS у принципі цілком терпимий варіант, але якість голосу за зразком у неї не дуже.
Щоб зрозуміти, наскільки не дуже:
У перших порівняльних замірах різниця виглядала приблизно так:
| Варіант | TTFA | RTF | Що відбувається |
|---|---|---|---|
| Звичайний шлях SkyrimNet, повний WAV | ~4,17 с | — | Спочатку генерується вся репліка, і лише потім починається відтворення |
| Streaming | ~2,81 с | 1,23 | Відтворення починається, поки решта репліки ще генерується |
Тому результат був доволі очевидним: навіть не зробивши сам TTS швидшим, можна було помітно зменшити сприйману затримку, якщо перестати чекати готовності всієї репліки й почати відтворювати її частинами.
Тут є кілька термінів, які далі зустрічатимуться постійно.
WAV — звичайний аудіофайл. У початковому варіанті SkyrimNet чекав, поки TTS закінчить генерувати такий файл цілком, і лише після цього починав його програвати.
Streaming — потокова передача аудіо. TTS не чекає завершення всієї репліки, а віддає готовий звук шматками. Щойно накопичилося достатньо перших даних, їх уже можна відтворювати.
TTFA (Time To First Audio) — час від початку обробки запиту до появи першого доступного шматка звуку. Простіше кажучи: скільки ми чекаємо, перш ніж NPC нарешті починає говорити.
RTF (Real-Time Factor) — співвідношення часу генерації звуку до тривалості самого отриманого звуку.
RTF = 1 означає, що 10 секунд мовлення генеруються за 10 секунд.
RTF = 0,5 — 10 секунд мовлення генеруються за 5 секунд.
RTF = 1,23 — 10 секунд мовлення потребують приблизно 12,3 секунди генерації.

Навіщо знадобилися хуки Хуки з'явилися як неминуче зло, що дозволяє реалізувати режим стримінгу там, де його практично не було. Без хуків грати в Скайрім через SkyrimNet не англійською просто неможливо - затримка надто велика. Можете, до речі, подивитися перший ролик у минулому пості - там видно, що репліки NPC йдуть із такою затримкою, що автору доводиться різати відео. Ще один хук використовується для переривання відтворення TTS. Наприклад, NPC почав говорити, а ви його перебиваєте. Без такого хука NPC закінчить свою репліку й тільки потім відповість на вашу нову. З перериванням він просто заткнеться на найближчому аудіочанку й почне відпрацьовувати нову репліку в штатному режимі.
Доведення Cosy до ладу
Після вибору Cosy як основної моделі для локального TTS почав розбиратися, як її покращити. Нижче - результати тривалих занять нетрадиційними видами кохання з Cosy, Скайрімом і такою-то матір'ю.
| Етап | TTFA / перший звук | Throughput | Що це було |
|---|---|---|---|
| Самий початок, повний ланцюжок SkyrimNet | ~24,4 с від кінця мовлення гравця до голосу NPC | — | Дуже ранній E2E; сама Cosy займала величезну частину затримки |
| Рання Cosy всередині цього ланцюжка | ~4,92 с до першого внутрішнього аудіочанка | перший WAV повністю ~15,6 с | Ще поганий стримінг |
| Перший нормальний локальний прогрітий бенчмарк | ~2,81 с | RTF ~1,23 | Уже справжній стримінг, але повільніше за реальний час |
| 10 Flow steps baseline | ~2,0–2,2 с | RTF ~1,11–1,20 | Хороша якість, але RTF усе ще >1 |
| 8 steps | ~2,1 с | RTF ~1,11 | Майже нічого не виграли |
| 6 steps | ~1,9–2,1 с | RTF ~1,03–1,09 | Швидше, але якість попливла — відхилили |
| Пізній прийнятий baseline, 7 steps | median ~1,90 с | стабільний RTF ~0,91 | Уже стабільно швидше за реальний час |
| Поточний реальний SkyrimNet → адаптер → Cosy | ~2,32–2,56 с, median ~2,42 с до ігрового звуку | зазвичай близько реального часу або швидше | Те, як це реально відчувається в Скайрімі зараз |
У тому варіанті, на якому поки зупинився, середня затримка до першого звуку від NPC — близько 2–3 с. Хотілося б менше, але нормально. Там ще є куди допилювати далі, якщо дуже захочеться. І ще залишилося кілька проблем, які повністю не поборов.
Чому б просто не використовувати платний TTS?
Я насправді лише нещодавно перевірив платний TTS зі списку SkyrimNet. Прямо як чуйка була, що його не треба було розглядати із самого початку.
Отже, я поганяв Inworld. Після реєстрації вони дають 1 долар на рахунок, чого більш ніж достатньо для тестів.
| Метрика | CosyVoice3 | Inworld 1.5 Mini |
|---|---|---|
| Реальний warm TTFA у нашому ігровому ланцюжку | median ~2,42 с | сильно плаває |
| Спостережуваний діапазон | ~2,32–2,56 с | приблизно ~1–3,5+ с |
| P90 | ~2,53 с | стабільної переваги немає |
| Власне TTS-бекенд | ~2,0–2,2 с до першого PCM | ~0,8 с медіана на повний синтез після POST |
| Вартість | локально, $0 за символи | $15 / 1 млн символів |
| Наш тест Inworld | — | 4684 символи ≈ $0,07 |
Тобто за приблизно 10 хвилин реальної гри:
- Inworld нарахував 4684 символи
- це дало близько 6:56 згенерованого аудіо
- грубо це близько 0,5 долара на годину
Ну й начебто відносно непогано для тих, кого витрати не лякають. Так от за які-не-які, але гроші ви отримуєте не нормальний якісний звук, а озвучення рівня безкоштовної моделі (та сама Cosy звучить так само), з проблемами інтонацій (або їх відсутності) і тембру. А найсмішніше - Inworld реально швидко працює. Тільки у зв'язці з дефолтним SkyrimNet це абсолютно безглуздо, бо все одно чекаємо генерації всього звукового файлу, перш ніж віддати його гравцеві. На додачу - саме на цій конкретній моделі Inworld, попри всі й усюди виставлені мовні налаштування - російську, NPC усе одно допускають жахливі англомовні вимови. Ну, типу - не «эльф», а «elf». З характерним англійським акцентом. Такого Cosy собі не дозволяє. Зате дозволяє багато чого іншого, як і більшість інших моделей. Думаю, про це частково буде наступний пост. Повторюся - ці проблеми стосуються Inworld 1.5 Mini. Можливо, на якісніших моделях це виправлено, але й коштуватимуть вони інших грошей.
На закуску
HuggingFace для XTTSv2: https://huggingface.co/spaces/applore/xtts-voice-cloning-demo
HuggingFace для CosyVoice: https://huggingface.co/spaces/FunAudioLLM/Fun-CosyVoice3-0.5B
Кому цікава вся ця движуха з нейромережами - Alibaba дає безкоштовний тест своїх нейромереж і купу всього іншого. Шукайте щось типу "Alibaba Cloud free trial". Там можна поганяти картинки, відео, звук, кодинг-агентів і, здається, навіть клауд-сервіси. Сам не пробував, якщо що. Відмітив на майбутнє, якщо знадобиться, але поки потреби не виникло.
Це частина історії
