- BrainTools - https://www.braintools.ru -
Я попытался сделать веб приложение, которое позволяет написать текст под бит. Механика следующая: загружаешь бит, задаешь характеристики текста – основная тема, настроение, форма рифмы и др – получаешь куплеты и припев, разложенные по тактам этого бита: строка на такт. Первая версия выдавала мягко говоря плохой результат. Ниже расскажу о том, что получилось докрутить, чтобы получить приемлемый результат.
Модель не слышит аудио, и я ей его не отправляю. Отправляю только числа: темп, где стоят такты, какие части у бита и как бьют барабаны в каждой шестнадцатой. Всё это считается на сервере обычной обработкой сигнала, без нейросетей, меньше чем за секунду.
Темп считается так же, как в любом определителе BPM, но с одной поправкой: я сворачиваю его в диапазон 70–140. Хай-хэты восьмыми делают 90 и 180 одинаково периодичными, и по сигналу их не различить. А куплет читают на медленном счёте, поэтому выбирается он. Если два числа расходятся, страница показывает оба.
Оценка темпа точна примерно до половины процента. Кажется, это немного, но за три минуты бита полпроцента набегают в целую долю, и к концу трека сетка тактов уезжает. Поэтому темп дополнительно ищется в пределах ±2%: выбирается та сетка, на которую по всему треку приходится больше всего атак. На синтетических битах (75, 90, 100 и 140 BPM) это попадает в настоящий темп с точностью до 0,03 BPM. Первая тактовая черта получается на 37–45 мс раньше, это два кадра анализа, рэпер столько не заметит.
С сильной долей сложнее. В бум-бэпе бочка стоит на первой и третьей долях, и по бочке их не отличить. Помогает то, что части трека меняются на тактовой черте. Поэтому «раз» — это доля, где больше всего бочки и одновременно сильнее всего меняется звук. Части (интро, куплеты, хуки, проигрыши) режутся по четырёхтактовым фразам там, где скачет спектр или громкость. Если бит — одна петля без изменений, он режется по договорённости 16 + 8, и страница честно это помечает.
Первая версия просила у модели двенадцать слогов на строку и получала двенадцать слогов. Если читать их под подсветку, выходило ровное «та-та-та-та». Это стихи под музыку, не рэп.
Флоу — это не количество слогов, а то, где они стоят в такте: какие шестнадцатые заняты, где паузы, куда падают ударения. Рэперы ищут его раньше слов, бормоча под бит «на-на-на». Музыканты называют это «йогурт». Страница делает то же самое: для каждой части выбирается флоу (синкопы, ровно в долю, триоли, дабл-тайм, рубленый), и сначала проигрывается он, короткое «та» на каждом слоге поверх бита. Слова пишутся под ритм, который уже слышно.
Самое интересное измерение во всей работе. Один бит, 90 BPM, 24 строки, один и тот же бриф.
Когда модели давали ритм строки как шаблон вида x.x.X..x, она попала в число слогов в 8 строках из 24, а в ударения — в одной.
Когда то же самое сказали словами («9 слогов, ударные: 3-й и 8-й») и попросили отметить ударения в написанном, 21 строка из 24 легла точно в рисунок.
Вывод для себя я сделал такой: расставлять ударения в собственном тексте модель умеет хорошо, а считать — плохо. Значит, считать нужно не ей. Число слогов и позиции ударений ей сообщаются готовыми, а оставшиеся строки, которые промахнулись, сервер перекладывает на сетку сам. Это небольшое динамическое программирование: ударения тянутся на сильные шаги флоу, расстояния между слогами берутся из флоу. После этого в флоу сидят 24 строки из 24, и подсветка с «йогуртом» идут по реально написанным словам, а не по задуманным.
Для русского языка счёт слогов точный: слогов столько же, сколько гласных. С ударениями хуже: ударение есть в каждом слове, и их больше, чем акцентов в любом флоу. Поэтому строка считается «севшей», если последнее ударение, то есть рифма, падает на сильный шаг и ещё хотя бы одно ударение тоже.
Была ещё одна неожиданность. Когда модель знала точное число слогов, она добивала строки до длины: шесть строк куплета из шестнадцати однажды начались с «и». Раз промахнувшуюся строку всё равно переложат, ей разрешили слог-два в любую сторону и запретили набивку. Заодно попросили писать как рэпер, а не как поэт: разговорный язык, конкретные детали, панчлайны, первое лицо и никаких первых образов, которые подсказывает тема.
Почти вся цена одной генерации — это время, которое модель думает. Промпт около 3 200 токенов, сам текст около 1 000, всё остальное — рассуждение. Резать промпт почти бесполезно, решают модель и уровень усилий. Тот же бит, 24 строки, по одному прогону:
|
Модель, усилие |
Цена |
Время |
В флоу |
Рифмы |
|---|---|---|---|---|
|
Opus, low |
$0.03 |
12 с |
24/24 |
18/24 |
|
Opus, medium |
$0.24 |
118 с |
23/24 |
22/24 |
|
Sonnet, medium |
$0.28 |
243 с |
24/24 |
23/24 |
|
Sonnet, low |
$0.33 |
299 с |
24/24 |
14/24 |
Sonnet вдвое дешевле за токен и всё равно вышел дороже: на этой задаче он думает в два-три раза дольше. Поэтому черновик пишется на Opus с низким усилием, а галочка «аккуратнее» включает среднее: в восемь раз дороже, зато рифмы плотнее.
Для пользователя это бесплатно, платит автор. Поэтому текст под бит открывается только после входа через Telegram или Google: так проще отсечь ботов, которые сожгли бы бюджет.
Готовые флоу — только начало. Можно напеть свой «на-на-на» поверх бита, и ритм прочитается из записи до того, как написано хоть одно слово. Это работает в браузере: запись никуда не уходит, на сервер отправляются только получившиеся рисунки.
Первая же настоящая запись в Bluetooth-наушниках разъехалась целиком. Слоги детектор нашёл все, но браузер сообщил задержку 178 мс, а запись всё равно сидела ещё на ~100 мс позже. Каждый слог попал на шаг мимо, а четыре триоли от каждой доли прочитались как рваные шестнадцатые. По одной записи задержку не узнать: шестнадцатая на шаг раньше выглядит так же, и та запись одинаково хорошо ложилась и со сдвигом 100 мс, и с 260 мс. Поэтому задержку теперь меряют: десять щелчков, на каждый «та», берётся медиана. Хранится она для каждого микрофона отдельно.
Разделение трека на голос и музыку на той же странице делает Demucs, на двух серверных ядрах без видеокарты. На ноутбуке пятиминутный трек делился за 23 секунды, и я рассчитывал на что-то похожее. На сервере вышло примерно 1,3 длины трека: те же пять минут аудио делятся за 6 мин 40 с, в пике 2,5 ГБ памяти [1]. Разница почти в двадцать раз, а не в два. Мораль простая и обидная: сайзить сервер по ноутбуку нельзя, мерить надо на той машине, где будет работать.
Чтобы минус не звучал хуже оригинала, инструментал — это исходник минус вокал, а не сумма того, что вернула модель. Так дорожки в сумме дают исходный трек с точностью до 1e-5, и тесты это проверяют. Если качество разделения просядет, упадут тесты, а не тихо испортится звук.
Пока писал этот текст, к сайту добавился бот в Telegram: присылаете ему песню, через несколько минут он возвращает два файла — минус и акапеллу. Внутри то же разделение, что на сайте, и тот же принцип: минус считается как исходник минус голос, поэтому вместе они дают ровно исходный трек. Бот: @hotmusiclab_bot
Счёт слогов для английского — оценка по группам гласных, а не точный счёт. Диапазоны слогов на строку для разного темпа (11–15 ниже 80 BPM, 8–11 выше 120) — эмпирика, а не измерение. Флоу написаны вручную по распространённой фразировке, а не выучены. И главное, что я пока не могу проверить сам: как это звучит у живого рэпера на живом бите.
Попробовать можно здесь: https://hotmusiclab.com/ru/rap-writer [2]
Если у вас есть бит, загрузите его и напишите в комментариях две вещи: в каком такте строка легла мимо и на каком темпе. По этим двум числам я найду, где ошибается сетка.
Автор: roneyocean
Источник [3]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/37649
URLs in this post:
[1] памяти: http://www.braintools.ru/article/4140
[2] https://hotmusiclab.com/ru/rap-writer: https://hotmusiclab.com/ru/rap-writer
[3] Источник: https://habr.com/ru/articles/1100580/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1100580
Нажмите здесь для печати.