Озвучка Руси-тян

Реплик героини: 49. Нарация (6 строк) не озвучивается — это голос за кадром.

Как записать

  1. Взять lines_for_minimax.txt — реплики через паузу <#2.5#> (MiniMax вставляет по ней тишину, а нарезка получает готовые границы). Если модель прочитает маркеры вслух — брать lines_clean.txt без них.

  2. Сгенерировать голос одним файлом (MiniMax, speech-2.8-hd, тембр вроде «Calm Woman»).

  3. Нарезать и разложить по репликам одной командой:

    python3 tools/vn_voice_slice.py --audio ~/Downloads/rusi.mp3

    Инструмент сам найдёт паузы, сверит их число с числом реплик и напишет tl3.mp3, tl4.mp3, … в эту папку. Не совпало — ничего не запишет и покажет таблицу, что подкрутить (--min-silence).

Если реплики генерируются по одной — сохраняй сразу под именем из таблицы.

№ Файл Реплика
1 tl3.mp3 Ты… ты чего уселся? Я тебя не звала. Вообще-то.
2 tl4.mp3 Ладно. Раз уж открыл — знакомься. Это Russiano2D. Мой движок.
3 tl5.mp3 А я — Руси-тян, его маскот. Да, я цундэрэ. Это не баг, это фича!
4 tl6.mp3 И самое главное. Внутри — JavaScript. Не Python. JavaScript. Повтори.
5 tl7.mp3 Игровая логика — на JS, ядро — на C. Общение — через одну точку входа: $.
6 tl8.mp3 Ну? Что скажешь про мой язык?
7 tl9.mp3 Хм! Ну… наконец-то кто-то с мозгами. Не то чтобы мне было важно твоё мнение!
8 tl10.mp3 П-просто… приятно. Всё. Молчи. Идём дальше.
9 tl11.mp3 ПИТОН?! Ты… ты… БАКА!!!
10 tl12.mp3 Python — это язык, на котором аналитики считают таблички! А тут ДВИЖОК! C и JS! Понимаешь? ДВИЖОК!
11 tl14.mp3 …Ладно. Проехали. Но я запомнила. Я всё запоминаю, учти.
12 tl15.mp3 Unity. Понятно. Тогда зачем ты вообще здесь?
13 tl16.mp3 У меня игра — это текст. Её можно читать, diff-ить и ревьюить. А у тебя что? Клики по сцене и молитва, чтобы .meta-файлы не разъехались!
14 tl17.mp3 …Прости. Я не хотела кричать. Просто мне правда важно, чтобы ты понял.
15 tl18.mp3 Так. Смотри сюда. Одна точка входа. Всё — через $.
16 tl19.mp3 $('', { id: 'hero' }).at(100, 300).controls('wasd').appendTo($.world);
17 tl20.mp3 Читается как предложение! Как обычный текст, а не как вызов с десятком параметров.
18 tl21.mp3 Почему так? Потому что $ всегда возвращает обёртку. Поэтому цепочки работают. Поэтому же поиск — как в CSS: $(«.enemy»).damage(10).
19 tl22.mp3 И да: низкоуровневый engine никуда не делся. $ построен поверх него, оба доступны одновременно.
20 tl23.mp3 Спрашивай. Один вопрос — и идём дальше.
21 tl24.mp3 Философия простая: игра — это текст.
22 tl25.mp3 Уровень и логика описываются кодом и данными, а не кликами по сцене. Такой проект удобно читать, diff-ить, ревьюить и генерировать.
23 tl26.mp3 И редактора поэтому нет. И не нужен! Код — лучший редактор. Он не забудет сохранить сцену.
24 tl27.mp3 Умеют! --agent: команды приходят JSON-строками в stdin, ответы уходят в stdout. Окно можно спрятать — рендер и скриншоты работают.
25 tl28.mp3 И движок сам о себе рассказывает: $.agent.expose(«score», …) — игра становится инструментом для программы, а не только для человека.
26 tl29.mp3 Представляешь? Даже агент может пройти эту новеллу. И выбрать неправильный ответ. И я его тоже назову бака.
27 tl30.mp3 Редактора нет. И не нужен.
28 tl31.mp3 Уровень — это код. Его можно diff-ить. Попробуй сделать diff бинарной сцены. Попробуй. Я подожду.
29 tl32.mp3 …Всё, молчу. Идём, покажу закат. Там красиво. Не подумай чего.
30 tl33.mp3 Здесь я иногда компилирую. Ну… то есть сижу. Просто сижу, ясно?
31 tl34.mp3 И вообще. Ты, кажется, не самый ужасный человек. КАЖЕТСЯ. Не обольщайся.
32 tl35.mp3 Держи. Чай. Он не отравлен. Наверное.
33 tl37.mp3 Ч-что? Ничего я не дрожу! Это ветер! Ветер, ясно?!
34 tl38.mp3 Я, между прочим, старалась. Движок — это как… как торт. Только из C и JavaScript.
35 tl39.mp3 И если ты скажешь, что он плохой, я… я не расстроюсь. Я просто уйду компилировать. Навсегда.
36 tl40.mp3 Ладно. Хватит экскурсий. Один вопрос, и я отстану.
37 tl41.mp3 Тебе понравился мой движок? Только честно.
38 tl42.mp3 Мне не важно. Совсем не важно. Но если ты соврёшь — я узнаю. У меня есть $.agent.snapshot().
39 tl43.mp3 Итак? Я слушаю.
40 tl44.mp3 …П-правда? Ты… ты серьёзно? Не шути так, я компилирую чувства без предупреждений!
41 tl45.mp3 Тогда ладно! Но у нас будет код-ревью. И ты будешь писать логику, а я — компилировать. И никаких print в моём коде!
42 tl46.mp3 И… и, может, вечером посмотрим на звёзды. Как партнёры по проекту. ТОЛЬКО по проекту!
43 tl48.mp3 Ну? Чего замер? Берём задачу в работу, бака. У нас теперь общий репозиторий.
44 tl49.mp3 Утро. Двор. Ты уже взял задачу в трекере, а я... я не ждала. Просто мимо проходила.
45 tl50.mp3 И да: код-ревью в девять. Не опаздывай, партнёр.
46 tl51.mp3 …Ясно. Бака.
47 tl52.mp3 Иди. Пиши свои скрипты. Я не расстроена. Я вообще не умею расстраиваться, у меня assert вместо слёз.
48 tl54.mp3 …Если передумаешь — движок лежит в dist/. И документация. Она хорошая. Правда хорошая.
49 tl55.mp3 И новелла эта никуда не денется. Я буду ждать. Не то чтобы я жду!

Почему имена такие

Движок ищет озвучку по id реплики в таймлайне: <dir>/<id>.mp3 (см. voice в demos/russi_vn/index.js и $.timeline.lines() в docs/highlevel/timeline.md). Так соответствие «реплика ↔ файл» не нужно хранить отдельной таблицей: переименовал файл — реплика замолчала, и это видно сразу.