- PVSM.RU - https://www.pvsm.ru -

Генератор музыкальных каверов на Python в Blender

В данной статье я расскажу о моём аддоне к блендеру, о причинах, побудивших меня к его созданию, процессе разработки и об «успехе» на YouTube.

Предыстория

Началось всё с того, что примерно год назад (в ноябре 2018го) я увидел в предложке ютуба вот такой необычный кавер на The Ultimate Canon [1]

Парень записал семплы каждой ноты песни и путём кропотливого монтажа собрал из них песню целиком. Кому как, но, думаю, это по меньшей мере забавно. Да и количество просмотров (на тот момент чуть больше 1 000 000) говорило о том, что тема (1% guitar skill 99% editing skills) пользуется популярностью.

Уверен, те, кто хоть немного занимался сведением песен, знают, что порою легче чутка подрезать и подвинуть дорожку, чем просить нерадивого гитариста переиграть партию. Я тоже раньше делал классические каверы, и у меня ещё тогда закрадывалась идея психануть и слепить кавер в точности, как это сделал парень из видео. И вот я вижу, что «мою идею нагло украли» и получили неплохой выхлоп. Я было раздосадовался, что мой поезд ушёл, но вдруг меня осенило, что я могу сделать то же самое, но на другом уровне, добавив новый шаг — 1% guitar 1% editing 98% programming skills.

К тому же это позволит создавать гораздо более сложные композиции, на которые при ручном редактировании мало у кого хватит терпения.

Разработка

Итак, задача была автоматизировать процесс нарезки звуковых семплов в музыкальную композицию.

Прежде всего необходимо было как-то передать будущей программе данные о композиции, её ноты, дорожки, инструменты. Я сразу же задумался о GuitarPro и его вариантах экспорта данных: MusicXML и MIDI.

Поиски привели меня к выбору парсера midi-файлов на Python music21 [2]. Это не только лишь парсер, но кроме этого мне от модуля ничего не нужно. А аналоги были либо с ужасной документацией, либо вообще не могли делать, что мне надо настолько легко, как music21.

Отлично, теперь я могу получать данные из midi-файлов о дорожках, об их нотах, их положении и длительности. Едем дальше.

Теперь надо на основе этих данных делать нарезку из видео/аудио файлов. Тут я выбрал достаточно быстро. Однозначно Blender, даже не смотря на его скромные возможности как видео-редактора. Я имею опыт работы с Adobe PremierePro, After Effects, однако там свой диалект скриптинга, который нигде больше не пригодится, да и его возможности мне неизвестны. В Blender'е же практически любое действие может быть осуществлено через скрипт на Python. И это уже совпадает с языком music21. Тут стоит пояснить, что с Python я на тот момент был вообще не знаком, поэтому этот проект я рассматривал ещё и как отличный повод ознакомиться с этим популярным языком. Бинго!

Постепенно начал вникать в язык, выводил через music21 ноты midi-файла в консоль, бегло посмотрел как делать аддоны к блендеру и приступил к первой практической задаче: формированию данных-семплов. Записал на гитаре каждую уникальную ноту и приступил к нарезке, но вскоре осёкся. Мой внутренний программист протестовал против этой кропотливой работы (а ведь нот на каждый инструмент может быть очень много: 30-50). А это надо было бы нарезать ноты и по-отдельности их рендерить в отдельные файлы, а для этого подгонять каждую дорожку-ноту по длине в начало таймлайна… В общем, надо было упростить и этот процесс.

Решением стало использование такой вещи в Blender как маркеры. Это по сути точки с текстовой информацией, которые можно выставлять на определённый кадр. Логика была такая: пользователь располагает своё видео и аудио (если аудио записывалось на отдельную дорожку), подгоняет их друг к другу и маркерами помечает начало каждой ноты на видео, а в тексте маркера указывает, что это за нота (A#, D, C и т.д.) и её максимальную длительность на записи. Затем информация о маркерах записывается в файл и используется уже при нарезке отдельных нот.

Генератор музыкальных каверов на Python в Blender - 1

Следующим пунктом шло уже собственно «ядро» функционала — нарезка нот и их позиционирование на таймлайне. По иронии судьбы, говорить тут особо нечего: было много чтения документации, документация Блендера далеко не всегда достаточно подробная, но постепенно я добился желаемого. Когда увидел (и услышал) первый результат (это была короткая композиция группы Эпидемия — Фродо), счастью не было предела. Думаю, всем знакомо чувство, когда что-то наконец получается.

Генератор музыкальных каверов на Python в Blender - 2

Качество кода оставляет желать лучшего. Делать старался в спешке, т.к. мне чудилось, что не один я до подобного додумался, и не хотел бы, чтобы и тут меня опередили (spoiler! как же я был наивен). Поэтому придерживаться стилю и раздумывать над структурой было некогда, старался быстрее получить рабочий прототип.

Нюансы

Теперь по нюансам реализации. У Блендера стоит ограничение в слоях редактора, максимум 32. Из картинки видно, что семплы аудио и видео (зелёные и сиреневые) занимают по 14 слоёв и формируются по возрастанию, потом опять на начало своего сектора. Это сделано из-за того, что Блендер не позволят спавнить семпл поверх другого. А в музыке часто бывает, что следующая нота начинается ещё до окончания звучания предыдущей. Поэтому, чтобы избежать наложения, я решил спавнить следующую ноту на слое выше предыдущей, а когда слои сектора заканчиваются, опять начинать с первого слоя (вряд ли первая нота будет звучать на целых 14 слоёв вперёд). Да, это можно было бы сделать умнее, экономя слои, но как я уже сказал, я торопился.

Самые внимательные могли заметить, что всего сектора 2 по 14 слоёв, это 28, а максимум в Блендере 32. Дело в том, что для спавна ноты, приходится через скрипт спавнить 2 оригинальных дорожки (видео и аудио) и уже потом вырезать из них нужную ноту. А спавнить поверх другой дорожки нельзя, поэтому я зарезервировал 31й и 32й слой под это дело. 29й и 30й используются для промежуточного хранения уже сгенерированных дорожек: генерация происходит под одному треку из midi-файла, затем ноты группируются в одну дорожку, переносится на 29/30 слой, генерируем следующую дорожку и т.д.

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

  1. для каждого участка с новой скоростью делать новый midi-файл только с ним;
  2. генерировать ноты участка заново с модификатором скорости Tempo (мультипликативный коэффициент к изначальной скорости).

Генератор музыкальных каверов на Python в Blender - 3

Я предпочитаю в GuitarPro для каждой скорости добавлять свои дорожки, потом в Блендере, достаточно будет только их сгенерировать с модификатором скорости, так быстрее и сложнее запутаться.

Утилиты видеоредактора

Теперь, когда есть черновой набор сгенерированных дорожек, надо смонтировать смотрибельный кавер. Т.е. спозиционировать дорожки по углам видео, переключаться в зависимости от музыки и т.д. В блендере с этим всё довольно плохо. Для наложения эффекта к дорожке надо «приклеивать» другую дорожку сверху, которая и будет отрисовываться при рендере, и выставлять её в нужное положение.

Особо следует упомянуть аккорды. Это когда несколько нот звучат в одно и то же время, т.е. при рендеринге видео будет отображаться только верхняя нота аккорда. Решением было всё то же добавление эффекта (по счастью, они не ломаются при наложении друг на друга). Если при обычном монтаже сгенерированных дорожек я бы мог делать всё вручную, то редактировать каждую ноту аккорда — это уж слишком. Как вы понимаете, этот нюанс я тоже автоматизировал. Теперь одним нажатием кнопки «Chordify strips» выделенные семплы будут трансформированы нужным образом и каждая нота аккорда будет отрисовываться.

Генератор музыкальных каверов на Python в Blender - 4

Генератор музыкальных каверов на Python в Blender - 5

И ещё один момент автоматизации: иногда сгенерированные семплы имеют между собой пустые участки. Это из-за того, что в партитурах в этих местах, внезапно, пустые места. В GuitarPro это звучит нормально, из-за различных эффектов, звучание ноты сохраняется в промежутках. Однако в блендере образуются пустоты. Их надо заполнять растяжением предыдущей ноты до начала следующей. Ровно это задачу выполняет кнопка «Fill gaps».

Ещё по мелочи был написан функционал работы с громкостью, а также возможность заменить отсутствующую ноту другой, но с другим значением высоты звука, что позволяет выходить за границы диапазона инструмента (правда на практике не более, чем на 1 октаву).

Слава на YouTube

Итак, аддон готов. От начала задумки было потрачено примерно полтора месяца, работал по вечерам, в свободное время. Время делать кавер, который переплюнет ручной кавер того паренька. Выбрал ту же композицию, но в рок-аранжировке: Canon Rock. Она гораздо мелодичнее и сложнее оригинала, и позволит ярко продемонстрировать новый уровень моего подхода. Да и как ответка уже популярному видео может привлечь внимание аудитории.

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

И вот кавер готов и отполирован [3]! Отснял вступление и концовку, в которых на ломаном английском попытался объяснить всю крутизну моей ответки. Некоторые слова говорил нарочито с ошибками (компликатед, дабл ю ти эф), в надежде сбайтить зрителей на поправку в комментах. Подготовил превьюшку. С замиранием сердца, в предвкушении ожидаемого триумфа, загрузил и опубликовал ролик. Разослал в тематических группах по каверам, и скинул ссылку в инстаграм тому парню. У него, кстати, очень триумфальный ник: Ralph Jay Triumfo.

Время шло. Триумфа всё не было. В первые сутки набралось около 100 просмотров, половина которых были моими и моих друзей. Затем наступило затишье. С каждым новым днём я всё больше разочаровывался во всей этой затее. Неужели люди не понимают, насколько крутую штуку я сделал? Почему сарафанное радио не работает? Или может быть сама затея была крутой лишь в моей голове?

Как бы там ни было, мне нравился результат, и я стал постепенно делать всё новые каверы.
В то время я участвовал в съёмках передачи «Моделирование мозга» на местном ТВ, и однажды я упомянул о своей поделке в разговоре с ведущим. Результатом стало появление небольшого репортажа обо мне. Мама, я в телеке [4]!

Я прекрасно понимал, что местное ТВ смотрят в основном пенсионеры, поэтому никаких ожиданий от этого не было.

Я ещё тогда хотел довести код аддона до ума, оптимизировать генерацию и выложить аддон в общий доступ, но провал триумфа поубавил мой пыл. К тому же тогда во всю готовился релиз новой версии Блендера, и менялся API. Я хотел дождаться его выхода летом и перенести аддон на новую версию, и тогда уже выложить, но опять же, особого желания не было.

И вот теперь спустя почти год, когда просмотры первого ролика едва перевалили за 600, я решил выложить на публику аддон и написать эту статью, может быть хоть кому-то это скрасит досуг, а заодно я выговорился.

Конечно, попробовал перенести аддон на новую версию 2.80, но оказалось, что видео-редактор не только не улучшили, а даже ухудшили. Производительность значительно хуже, порою вылетает при генерации тяжёлых дорожек. Сам редактор подтормаживать стал. Невозможность заглушить определённые звуковые дорожки (надеюсь, это баг, и в следующем минор-релизе пофиксят). А пока что для аддона нужна старая добрая версия 2.79

Вот ссылка на аддон [5], не забудьте поставить на интерпретатор питона блендера music21. Жду массового появления синтезированных каверов от вас.

Автор: PlutonosVEt

Источник [6]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/python/332819

Ссылки в тексте:

[1] The Ultimate Canon: https://youtu.be/DWF00hRfsX0

[2] music21: https://web.mit.edu/music21/

[3] кавер готов и отполирован: https://youtu.be/PQeObgV_r6M

[4] я в телеке: https://youtu.be/iyIC5_-mfiM

[5] ссылка на аддон: https://gitlab.com/RomanProvodin/cover-creator

[6] Источник: https://habr.com/ru/post/471086/?utm_campaign=471086&utm_source=habrahabr&utm_medium=rss