

0. Предисловие, о документе и вообще

В некоторой степени это даже не хавту, а туду-чеклист, которое пилится в срочном дедлайне. Так как от дедлайнов у меня стресс и я впадаю в ступор, то этот документ скорее для меня самого.
А поскольку я не один такой аутист, то попробую прокомментировать каждый пункт.
Следует отметить, что оригинальный The_Nikolai_Project проебан, так как у меня ебнули свет и оно все накрылось. Я конечно думал, что я успел все сохранить, но ничего не нашел.
Впрочем, не стоит грустить, поэтому параллельно исполнению этой тудушки я буду дописывать и части проекта, которые были проебаны, равно как и открывать тайны мироздания.

1. Скачиваем кинцо

Очень важный пункт, так как именно он позволил мне найти кучу времени на написание данного текста. Само собой, кино должно быть с СУБТИТРАМИ, а если вы скачаете кино без сабов, то
на следующем пункте вас ждет эксепшен и вселенная схлопнется.

2. Выдираем субтитры

Если субтитры не отдельным файлом, то выдрать субтитры в общем-то просто:
ffmpeg -i kintso.mkv -map 0:5 subs.ass
Ключик -map опционален, он определяет какой поток использовать, в данном примере мы берем нулевой файл (самый первый) и поток 5 (шестой от начала). Увидеть какие потоки чем являются можно
просто запустив команду с любым номером, они все будут перечислены. Ну или юзаем команду ffprobe, что правильней, но откуда она у спермоблядей? Если в файле всего одни сабы, то это не важно.

Если у нас субтитры в формате srt и тому подобном (или даже ASS), где нету проставленный ролей/стилей персонажей, то скачиваем AegiSub и долбим-долбим, расставляя роли.
Лично у меня на Кики деливери сервис ушел 1 день + еще 1 у еще одного Анона, суммарно 2 человеко-дня. А вот Бразилию я 2 месяца прокрастинировал, а кто-то за 2 часа забил ее.

Субтитры крайне желательно поредактировать, как это описано на http://anon.fm/anondub/ (раздел про подготовку субтитров), а именно склеить разрезанные диалоги, подогнать
тайминг, разрезать диалоги разных персонажей и тому подобное. Но если времени нет, или сабы выглядят достаточно качественными, то можно на это и забить.

Хочу поблагодарить Anon2Anon за качественные сабы и их оформление.

3. Выдираем роли из субтитров

Надо получить список персонажей, кто кем будет и кто за что говорит. Утилька get_roles.pl поможет. Так как сейчас я делаю конеебство, то:

Person Twilight speaks 529.76 seconds
Person SunsetShimmer speaks 395.02 seconds
Person Somepony speaks 392.99 seconds
Person PrincipalCinch speaks 379.95 seconds
Person RainbowDash speaks 193.06 seconds
Person PrincessCadence speaks 157.99 seconds
Person AppleJack speaks 127.02 seconds
Person Celestia speaks 117.5 seconds
Person Rarity speaks 115.87 seconds
Person FlutterShy speaks 88.5 seconds
Person PinkiePie speaks 75.87 seconds
Person Luna speaks 52.48 seconds
Person Spike speaks 43.68 seconds
Person SourSweet speaks 35.1 seconds
Person FlashSentry speaks 18.26 seconds
Person SugarCoat speaks 15.06 seconds
Person ShiningArmor speaks 12.2 seconds
Person IndigoZap speaks 9.12 seconds
Person Auto speaks 3.29 seconds
Person SunnyFlare speaks 3 seconds
Person Cinch speaks 1.57 seconds
Person BonBon speaks 1.09 seconds
Actor  speaks 2768.46 seconds
Neighbors of Twilight (529.76): PrincipalCinch (153.03), SunsetShimmer (112.29), Somepony (82.02), PrincessCadence (76.19), Celestia (42.02), Spike (35.52), FlutterShy (35.35), AppleJack (30.09), SourSweet (15.21), FlashSentry (14.22), Rarity (13.89), PinkiePie (12.93), ShiningArmor (12.2), RainbowDash (9.05), IndigoZap (7.35), SugarCoat (4.4), Auto (3.29), SunnyFlare (3), Luna (2.42), BonBon (1.09)
Neighbors of SunsetShimmer (395.02): RainbowDash (103.62), Rarity (88.26), AppleJack (79.98), Twilight (77.32), Somepony (63.19), FlutterShy (55.53), PinkiePie (41.82), Luna (36.89), PrincipalCinch (35.28), PrincessCadence (27.72), Celestia (25.42), Spike (5.25), SunnyFlare (1.86)
Neighbors of Somepony (392.99): RainbowDash (87.27), Twilight (81.27), PrincipalCinch (77.05), SunsetShimmer (37.66), PrincessCadence (25.86), AppleJack (21.73), Rarity (20.4), FlutterShy (13.96), PinkiePie (10.6), Luna (9.01), FlashSentry (6.54), Celestia (6.33), SourSweet (5.11), SugarCoat (2.98), Cinch (1.57), Spike (1.26), BonBon (1.09)
Neighbors of PrincipalCinch (379.95): Somepony (56.09), Twilight (50.61), Celestia (44.57), SunsetShimmer (30.31), Spike (26.26), PrincessCadence (20.04), AppleJack (15.75), PinkiePie (13.64), ShiningArmor (12.2), FlutterShy (11.1), SourSweet (10.33), Rarity (8.8), SugarCoat (8.71), Luna (7.44), RainbowDash (2.48), SunnyFlare (1.86)
Neighbors of RainbowDash (193.06): SunsetShimmer (127.18), Somepony (75.28), Rarity (72.95), AppleJack (61.34), Celestia (42.66), FlutterShy (40.83), Luna (34.31), Twilight (28.86), PinkiePie (28.03), PrincessCadence (18.53), PrincipalCinch (3.71), FlashSentry (2.31), IndigoZap (1.76), Cinch (1.57)
Neighbors of PrincessCadence (157.99): Twilight (102.3), PrincipalCinch (51.76), SunsetShimmer (35.15), Luna (29), Somepony (20.98), Celestia (15.82), SourSweet (15.28), FlutterShy (12.83), AppleJack (12.47), RainbowDash (9.27), IndigoZap (7.35), Rarity (6.72), PinkiePie (4.71), ShiningArmor (2.7), FlashSentry (2.65), SugarCoat (1.49), Spike (1.26), SunnyFlare (1.14)
Neighbors of AppleJack (127.02): SunsetShimmer (162.18), Rarity (100.57), RainbowDash (74.02), FlutterShy (43.84), PrincipalCinch (40.3), PinkiePie (33.81), Somepony (26.94), Twilight (23.04), Luna (20.55), PrincessCadence (16.68), Celestia (14.68), SourSweet (9.55), SugarCoat (2.92), Spike (1.86), IndigoZap (1.76), FlashSentry (1.51)
Neighbors of Celestia (117.5): PrincipalCinch (64.48), SunsetShimmer (51.79), Twilight (27.34), RainbowDash (24.6), PinkiePie (24.27), PrincessCadence (16.76), Rarity (11.4), Spike (8.13), Luna (7.44), AppleJack (6.8), SourSweet (5.21), FlutterShy (4.68), SugarCoat (2.63), FlashSentry (2.31), Somepony (1.8)
Neighbors of Rarity (115.87): SunsetShimmer (113.09), RainbowDash (97.81), AppleJack (83.67), FlutterShy (57.17), PinkiePie (44.86), Luna (36.89), PrincipalCinch (25.5), Twilight (15.92), Somepony (14.51), Celestia (11.48), PrincessCadence (10.99), IndigoZap (1.76)
Neighbors of FlutterShy (88.5): SunsetShimmer (115.43), RainbowDash (61.02), Rarity (48.8), AppleJack (48.01), Twilight (45.93), PinkiePie (35.95), PrincessCadence (23.77), PrincipalCinch (17.91), Somepony (14.23), Spike (12.41), Luna (6.84), Celestia (4.76), SugarCoat (1.49)
Neighbors of PinkiePie (75.87): RainbowDash (60.65), SunsetShimmer (54.35), Celestia (40.2), AppleJack (29.03), PrincipalCinch (25.6), Rarity (21.23), Twilight (19.6), FlutterShy (19.14), Luna (9.8), PrincessCadence (9.78), Somepony (7.79), SugarCoat (7.28), SourSweet (5.21), Spike (2.67)
Neighbors of Luna (52.48): PrincessCadence (31.15), Somepony (19.72), SunsetShimmer (16.99), Twilight (14.68), Celestia (14), PrincipalCinch (13.46), AppleJack (12.2), RainbowDash (11.75), Rarity (10.07), Spike (3.61), FlutterShy (3.46), PinkiePie (3.36), Cinch (1.57), SunnyFlare (1.14), IndigoZap (1.13)
Neighbors of Spike (43.68): Twilight (43.8), PrincipalCinch (28.85), Celestia (20.61), SunsetShimmer (13.51), PrincessCadence (7.71), SugarCoat (7.28), AppleJack (6.53), FlutterShy (5.47), SourSweet (5.21), PinkiePie (3.65), Luna (2.53), Somepony (0.91)
Neighbors of SourSweet (35.1): PrincipalCinch (32.28), Twilight (22.54), AppleJack (17.17), SugarCoat (10.65), PrincessCadence (8.44), IndigoZap (7.35), Celestia (6.28), PinkiePie (3.65), Spike (2.67), SunnyFlare (1.14), Somepony (0.9)
Neighbors of FlashSentry (18.26): Celestia (22.08), Twilight (11.07), AppleJack (8.76), Somepony (8.06), PrincessCadence (6.68), RainbowDash (4.82)
Neighbors of SugarCoat (15.06): PrincipalCinch (38.8), AppleJack (16), SourSweet (14.03), Twilight (8.17), PrincessCadence (4.36), Somepony (4.12), Celestia (3.84), PinkiePie (3.65), Spike (2.67), FlutterShy (2.59), BonBon (1.09)
Neighbors of ShiningArmor (12.2): PrincipalCinch (49.95), Twilight (8.41), PrincessCadence (4.79)
Neighbors of IndigoZap (9.12): Twilight (26.48), SourSweet (10.91), PrincessCadence (8.12), Luna (4.91), Rarity (2.09), AppleJack (2.01), SunnyFlare (1.14), RainbowDash (1.03)
Neighbors of Auto (3.29): Twilight (15.65)
Neighbors of SunnyFlare (3): Twilight (8.22), PrincessCadence (5.38), SourSweet (5.15), SunsetShimmer (2.63), Luna (1.99), PrincipalCinch (1.92), IndigoZap (1.13)
Neighbors of Cinch (1.57): Somepony (16.31), Luna (6.58), RainbowDash (1.71)
Neighbors of BonBon (1.09): Somepony (6.31), SugarCoat (1.87), Twilight (1.55)

Тут мы видим роли, "актера" и "соседей". Изначально хотелось сделать автоматическое назначение актера на каждую роль, но процесс сложный, да и даже в случае с синтезаторами речи не все так очевидно.
Роли отсортированы по длительности пиздежа, потому самые лучшие распределяем сразу, пока у нас есть актеры.
В соседях же показано, кто с кем пиздит, таким образом нельзя назначать одного актера на роль Twilight и PrincipalCinch, так как они пиздят почти 3 минуты вместе.

4. Создаем маппинг голосов

В качестве фронтенда для генерации голосов я использую Balabolka_console, потому запускаем с ключиком -l и получаем список установленных голосов

>balabolka_console.exe -l

SAPI 4:
  Alyona :: Alyona (Russian) SAPI4 22kHz
  Nicolai :: Digalo Russian Nicolai
  Nicolai :: ELAN TTS Russian (Nicolai 16Khz)
SAPI 5:
  Acapela Alyona22k
  ELAN TTS Russian (Nicolai 16Khz)
  IVONA 2 Tatyana
  Loquendo Dmitri
  Loquendo Olga
  Microsoft Mary
  Microsoft Mike
  Microsoft Sam
  Nuance Automotive Milena Compact 22kHz
  Nuance Automotive Milena Premium 22kHz
  Nuance Automotive Milena Premium High 22kHz
  Nuance Automotive Milena Standard 22kHz
  Nuance Automotive Milena Standard High 22kHz
  ScanSoft Katerina_Full_22kHz
  UkrVox Igor
Microsoft Speech Platform:
  Microsoft Server Speech Text to Speech Voice (ru-RU, Elena)

Это первые попавшиеся голоса, которые можно найти, в реальности их существует куда больше. Вообще, можно использовать любой фронтенд/бекенд/движки/голоса, просто есть что есть, под балаболку же заточена генерация скрипта

И создаем портяночку вида

%roles=(
"Twilight","Nuance Automotive Milena Premium High 22kHz",
"SunsetShimmer","Acapela Alyona22k",
"Somepony","ELAN TTS Russian (Nicolai 16Khz)",
"PrincipalCinch","IVONA 2 Tatyana",
"RainbowDash","Loquendo Olga",
"PrincessCadence","ScanSoft Katerina_Full_22kHz",
"AppleJack","Microsoft Server Speech Text to Speech Voice (ru-RU, Elena)",
"Celestia","Microsoft Server Speech Text to Speech Voice (ru-RU, Elena)",
"Rarity","ScanSoft Katerina_Full_22kHz",
"FlutterShy","IVONA 2 Tatyana",
"PinkiePie","IVONA 2 Tatyana",
"Luna","IVONA 2 Tatyana",
"Spike","UkrVox Igor",
"SourSweet","IVONA 2 Tatyana",
"FlashSentry","Loquendo Dmitri",
"SugarCoat","IVONA 2 Tatyana",
"ShiningArmor","ELAN TTS Russian (Nicolai 16Khz)",
"IndigoZap","Loquendo Olga",
"Auto","ELAN TTS Russian (Nicolai 16Khz)",
"SunnyFlare","Loquendo Olga",
"Cinch","IVONA 2 Tatyana",
"BonBon","Loquendo Olga",
);

Конечно, надо бы провести кастинг, потом расставить их по характеру и вообще, выбрать любимчиков. Но суровая реальность нам диктует следующее:
1. Главные герои берут на себя основных актеров
2. Главные герои говорят со всеми - значит на второстепенных персонажей этих актеров ставить нельзя
3. Конец добиваем как можем и как умеем из мусора

И после выдрачивания, переназначения и прочей ебли получаем примерно такое:

Conflicts of Twilight (Nuance Automotive Milena Premium High 22kHz):
Conflicts of SunsetShimmer (Acapela Alyona22k):
Conflicts of Somepony (ELAN TTS Russian (Nicolai 16Khz)):
Conflicts of PrincipalCinch (IVONA 2 Tatyana): PinkiePie (13.64), FlutterShy (11.1), SourSweet (10.33), SugarCoat (8.71), Luna (7.44)
Conflicts of RainbowDash (Loquendo Olga): IndigoZap (1.76)
Conflicts of PrincessCadence (ScanSoft Katerina_Full_22kHz): Rarity (6.72)
Conflicts of AppleJack (Microsoft Server Speech Text to Speech Voice (ru-RU, Elena)): Celestia (14.68)
Conflicts of Celestia (Microsoft Server Speech Text to Speech Voice (ru-RU, Elena)): AppleJack (6.8)
Conflicts of Rarity (ScanSoft Katerina_Full_22kHz): PrincessCadence (10.99)
Conflicts of FlutterShy (IVONA 2 Tatyana): PinkiePie (35.95), PrincipalCinch (17.91), Luna (6.84), SugarCoat (1.49)
Conflicts of PinkiePie (IVONA 2 Tatyana): PrincipalCinch (25.6), FlutterShy (19.14), Luna (9.8), SugarCoat (7.28), SourSweet (5.21)
Conflicts of Luna (IVONA 2 Tatyana): PrincipalCinch (13.46), FlutterShy (3.46), PinkiePie (3.36), Cinch (1.57)
Conflicts of Spike (UkrVox Igor):
Conflicts of SourSweet (IVONA 2 Tatyana): PrincipalCinch (32.28), SugarCoat (10.65), PinkiePie (3.65)
Conflicts of FlashSentry (Loquendo Dmitri):
Conflicts of SugarCoat (IVONA 2 Tatyana): PrincipalCinch (38.8), SourSweet (14.03), PinkiePie (3.65), FlutterShy (2.59)
Conflicts of ShiningArmor (ELAN TTS Russian (Nicolai 16Khz)):
Conflicts of IndigoZap (Loquendo Olga): SunnyFlare (1.14), RainbowDash (1.03)
Conflicts of Auto (ELAN TTS Russian (Nicolai 16Khz)):
Conflicts of SunnyFlare (Loquendo Olga): IndigoZap (1.13)
Conflicts of Cinch (IVONA 2 Tatyana): Luna (6.58)
Conflicts of BonBon (Loquendo Olga):

Чем меньше конфликтов - тем лучше, но тут конфликты все равно остались. Мало того, что у меня через час должен быть релиз, так еще и голосов мало. АААААААА!!!!!!1111

5. Запускаем генерацию фраз (нужен windows c самими голосами)

Тут все просто, я копирую сгенеренный батник на виндовую машину со всеми этими голосами, отключаю в ней сеть и запускаю генерацию. По результату будет дохуя wav-файлов из цифирок, они то нам и нужны будут дальше.
Процесс не быстрый, именно благодаря нему я пишу эти строки, а не пиздец как отлаживаю стретчинг, которого судя по всему в этом релизе не будет. Надо было встать раньше.

6. Выдираем звуковую дорожку

И сохраняем ее в формате wav, сделать это можно при помощи ffmpeg -i kintso.avi -ac 1 -ar 44100 sound.wav
Параметры важны для следующего шага, они задают 1 канал звука (моно) и частоту дискретизации 44100 Hz
Если в файле много озвучек, то не забываем найти и выбрать нужную при помощи -map
Stream #0:5(eng): Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s
Значит добавим -map 0:5 к опциям. Это было замечено в самый последний момент, а то получился бы рудаб поверх рудаба

Опционально провести нормализацию звука, но см. последний пункт

7. Смешивание звуков в звуковую дорожку

Процедура подрезания/подтягивания фраз под тайминг. Вообще, берем файлик mix.pl, правим пути к файлам речи и wav-файлу.
Фактически тут происходит полнейший пиздец, но происходит он относительно быстро и заключается в том, что каждый файл:
- приводится к 44100/моно формату, делаем временный вавик
- сжимаем по длительности, юзая soundstretch из Soundtouch (жутко кривое говно, потому я юзаю ПЕРЕБОР)
- патчим БАЙТИКАМИ наш оригинальный файл
В процессе получаем ПИЗДИЛЛИОН мелких файлов, потому я запускаю на рамдиске и работает приемлемо, за минутку-другую оно растянет и "запатчит" все что есть.
Основное время уходит на подбор размера, чтобы речь вместить куда надо.

8. Нормализация результата

Лично я считаю, что все должно быть ровненько, потому результирующий вавик прогоняю через AntiSound и сразу получаю файлик пожатый в AAC+

9. Склеиваение (ремуксинг)

Ну тут все до примитивности просто:
ffmpeg -i kintso.mkv -i koni.aac -map 0:0 -map 1:0 -c copy KONINA.avi
главное тут - это -map 0:0 -map 1:0, что означает "взять файла 0 поток 0", "взять из файла 1 поток 0". Как правило видео является первым потоком, а в файле звука все равно один поток. Но можно промахнуться, в этом случае смотрите сами какие потоки в файлах

Enjoy new great rudabchik!




