Перейти к содержанию
Публикация AiManual

Struna: браузерный ритм-раннер, где четыре нейросети анализируют вашу музыку локально

Struna от MrFelliks - открытый браузерный ритм-раннер, в котором BeatNet, Basic Pitch, Spleeter и SwiftF0 локально разбирают ваш mp3 и строят уровень. Разбираем

Коротко

Что будет в материале

  1. 01

    Что такое Struna и как трек превращается в уровень

  2. 02

    Локальная обработка аудио в браузере: onnxruntime-web и web worker

  3. 03

    Четыре модели и их роли в геймплее

  4. 04

    DSP поверх моделей: мир, погода и дропы

Что такое Struna и как трек превращается в уровень

Struna - браузерный ритм-раннер, в котором загруженный mp3 строит мир, по которому бежит игрок. Разработчик под ником MrFelliks выложил проект в открытый доступ под лицензией MIT: вы даёте игре свой файл, четыре нейросети разбирают его на ритм, ноты и вокал, а уровень собирается из того, что они услышали.

Вся обработка аудио идёт локально, в той же вкладке браузера. Ни один фрагмент трека не уходит на сервер, поэтому можно скармливать игре записи, которые вы не хотели бы отдавать наружу. Игра запускается и на телефоне.

Под капотом четыре компактные модели в формате ONNX общей массой около 22 МБ: BeatNet, Basic Pitch от Spotify, Spleeter и SwiftF0. Каждая решает свою задачу, а поверх них работает обычный DSP, который задаёт визуальный характер уровня. Автор описал устройство проекта в посте в r/LocalLLaMA.

Кто такой MrFelliks и что значит лицензия MIT для проекта

MrFelliks - автор Struna. Лицензия MIT разрешает читать исходники, форкать код, встраивать его в свои проекты и распространять дальше при сохранении уведомления об авторских правах и текста лицензии. Для игры это существенно: любой разработчик может разобрать пайплайн до уровня отдельных вызовов моделей и повторить схему у себя.

В публикации нет данных о коммерческой версии, платной поддержке, сроках релизов или планах развития. Речь идёт о выложенном коде и посте автора, а не о продукте с roadmap и SLA.

Почему одинаковый трек даёт одинаковый уровень

Автор отмечает: одинаковый трек всегда даёт одинаковый мир, поэтому уровень можно выучить. Детерминизм следует из устройства пайплайна: фиксированный набор моделей и фиксированные DSP-правила, без случайности в генерации геометрии трассы. Один и тот же файл на входе даёт одну и ту же расстановку препятствий.

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

Локальная обработка аудио в браузере: onnxruntime-web и web worker

Инференс идёт на onnxruntime-web в режиме WASM, каждая модель запускается в своём web worker. Onnxruntime-web исполняет ONNX-модели прямо в браузере, без Python и без серверной части. Режим WASM означает вычисления через WebAssembly на CPU устройства, а web worker даёт фоновый поток, в котором тяжёлый инференс не блокирует отрисовку интерфейса и игровой цикл.

Разнос моделей по отдельным воркерам - распространённая практика при работе с несколькими сетями в браузере: нагрузка изолируется, а подвисание одного этапа не останавливает остальные. Деталей реализации в посте нет: приоритеты воркеров, способ передачи тензоров и момент запуска каждого этапа придётся смотреть непосредственно в коде.

Ключевое ограничение схемы: WASM-инференс упирается в CPU, а не в видеокарту. Про поддержку WebGPU, конкретные версии onnxruntime и замеры скорости в публикации ничего не сказано, поэтому реальную производительность стоит проверять на своём устройстве, а не переносить чужие ожидания.

Что подтверждается прямо: файлы не загружаются на сервер, вся «прослушка» происходит в табе. Это снимает типичную для AI-сервисов зависимость от бэкенда и стоимости инференса на стороне провайдера.

Четыре модели и их роли в геймплее

Модели делят работу по типам музыкальной информации. Общая картина выглядит так:

МодельВесЗадачаЧто даёт в игре
BeatNet~1,6 МББиты и начало тактовСетка уровня: препятствия, прыжки, удары, привязка дропов
Basic Pitch (Spotify)~0,2 МБТранскрипция нотПерекладины из длинных нот, кольца из соло
Spleeter~20 МБОтделение вокала от миксаЧистая вокальная дорожка для трекинга высоты
SwiftF0~0,1 МБВысота голоса и начало слоговКольца на слогах в вокальных куплетах

Суммарный вес четырёх моделей - около 22 МБ. Разница в размерах показательна: 20 МБ из 22 приходится на одну модель разделения источников, остальные три вместе занимают примерно 2 МБ.

BeatNet: сетка битов и начало тактов

BeatNet (~1,6 МБ) находит каждый бит и определяет, где начинается такт. Это и есть сетка, на которой стоит весь уровень: каждое препятствие, каждый прыжок и удар размещаются на одном из её битов, а дропы попадают на линии тактов. Ошибка трекера смещает всю геометрию трассы, а не отдельный объект.

Именно поэтому признание автора про половинный темп на быстрых треках стоит воспринимать серьёзно: сбой в этом звене меняет ощущение ритма во всей игре.

Basic Pitch от Spotify: ноты как препятствия

Basic Pitch (~0,2 МБ) транскрибирует ноты. Длинная выдержанная нота становится перекладиной или линией, на которой игрок раскачивается. Соло превращается в цепочку колец, через которые нужно пролететь, причём каждое кольцо стоит на высоте своей ноты. Модель от Spotify весит меньше двух десятых мегабайта, а даёт самый заметный вклад в вертикальную геометрию уровня.

Spleeter: отделение вокала от микса

Spleeter (~20 МБ) вытаскивает голос из микса, чтобы остальная часть песни не путала следующую модель. Это самая крупная сеть пайплайна, и она во многом определяет вес первой загрузки: без разделения источников трекинг высоты голоса получал бы инструментал в качестве шума. Логика последовательная: сначала чистый вокал, потом анализ высоты.

SwiftF0: высота голоса и слоги каждые 16 мс

SwiftF0 (~0,1 МБ) отслеживает, как высоко поёт голос и когда начинается каждый слог, с шагом 16 мс. В вокальных куплетах игрок пролетает через кольца на слогах певца, поднимаясь и опускаясь вместе с мелодией. Плотность объектов здесь задаёт не бит, а речь и вокальная фразировка, поэтому куплет и припев ощущаются по-разному.

DSP поверх моделей: мир, погода и дропы

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

Разделение ответственности получается чётким. Модели отвечают за музыкальную структуру: биты, ноты, вокальную мелодию. DSP отвечает за атмосферу и визуальную динамику: насколько громким был такт, где случился резкий онсет, в какой момент менять картинку. Конкретные миры и типы погоды автор в посте не перечисляет, так что набор визуальных состояний и правила их выбора видны только в коде.

Вес моделей, кеш и фолбэк на слабом железе

Все четыре модели вместе весят около 22 МБ и кешируются после первой загрузки. Практический вывод: первый запуск требует скачать этот объём, последующие берут веса из кеша браузера и стартуют быстрее. На мобильном соединении первая загрузка ощутимо тяжелее, чем на десктопе с нормальным каналом.

Если устройство не успевает прогонять модели, игра откатывается на обычный DSP и продолжает работать. Деградация плавная: геймплей не ломается, но детали, которые дают нейросети, могут упроститься. Что именно отключается в резервном режиме и как быстро происходит переключение, автор не описывает, поэтому рассчитывать на конкретный перечень функций не стоит.

Требований к устройству в публикации нет: ни минимальных характеристик, ни целевого FPS, ни времени первой загрузки. Ориентироваться приходится на собственный запуск.

Ограничения и открытые вопросы: половинный темп и код с Claude Code

Автор прямо признаёт: его трекер битов иногда определяет быструю песню в половинном темпе. Это влияет на всю сетку уровня и на геймплей, потому что от BeatNet зависит расстановка препятствий и привязка дропов. Для быстрых жанров ограничение стоит держать в голове как известное поведение текущей реализации.

Второй момент, который MrFelliks не скрывает: значительная часть кода написана с помощью Claude Code, а для формулировки поста тоже использовался ИИ. Оценок качества этого инструмента автор не даёт, речь идёт о факте использования.

К сообществу он обращается с конкретным вопросом: кто ещё запускает аудиомодели в браузере и что использует для beat tracking. Пост фактически работает как запрос на обмен опытом по браузерному инференсу аудио.

Отдельная оговорка: все приведённые характеристики взяты из описания автора, независимой проверки весов, задержек и работы фолбэка в доступных материалах нет.

Что из Struna можно перенести в свои браузерные AI-проекты

Проект даёт набор приёмов, которые переносятся на любые задачи с аудио и не только:

  • Изоляция моделей по web worker. Каждая сеть крутится в своём потоке, интерфейс не замирает на время инференса.
  • Кеширование весов. Однократная загрузка около 22 МБ с последующей работой из кеша вместо повторных скачиваний.
  • Graceful degradation. Вместо падения при нехватке вычислительных ресурсов игра переключается на DSP-режим и остаётся играбельной.
  • Детерминированный пайплайн. Отсутствие случайности в генерации даёт воспроизводимый результат, удобный и для игрока, и для отладки.
  • Разделение тяжёлых моделей и лёгкого постпроцессинга. Основную смысловую нагрузку несут три модели суммарным весом около 2 МБ, а 20 МБ уходят на одну задачу разделения источников, которую стоит планировать отдельно в бюджете загрузки.

Ограничение общее для всего подхода: WASM-инференс в браузере упирается в CPU, и тяжёлую модель вроде Spleeter придётся либо кешировать агрессивно, либо предусматривать облегчённый режим. Для приложений, где аудиомодель должна работать без задержек, стоит заранее измерить реальное время инференса на целевом устройстве.

Смежный класс задач с аудио в браузере разбирается в материале про Foundation-1 и генерацию playable-синтезаторов по текстовому описанию: там аудиомодель тоже работает с сигналом на стороне пользователя, только цель другая. Struna показывает обратную сторону: анализ готового трека в реальном времени и превращение его структуры в игровые правила.

Исходники под MIT доступны для изучения, а самый быстрый способ проверить заявленные характеристики - загрузить свой mp3 и сравнить поведение уровня на медленном и быстром треке.

Подписаться на канал