Несколько лет назад мы представили Мою волну — систему персональных рекомендаций в Яндекс Музыке, которая подстраивается под предпочтения пользователей. В её основе — рекомендательные нейросети-трансформеры, размер которых может достигать сотен миллиардов параметров, и поэтому без мощных дата-центров их работа просто невозможна.

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

Как это работает и что нам пришлось для этого создать — расскажем под катом.

Идея полноценного офлайн-режима для Моей волны появилась не сразу. Мы, конечно, давно хотели сделать так, чтобы пользователи могли слушать музыку и без доступа в сеть. Обычно рекомендательные системы в музыкальных стримингах работают только онлайн: если сети нет — пользователь остаётся с набором скачанных треков, а рекомендации перестают адаптироваться к его действиям. В Яндекс Музыке тоже была возможность слушать скачанные треки, находясь без интернета. Для этого был офлайн-режим, который нужно включать отдельно. 

По сути, офлайн-режим — это такой «авиарежим» для Яндекс Музыки: включаешь в конкретные периоды отсутствия связи, чтобы слушать то, что скачалось на устройство. Проблема в том, что связь может пропадать спонтанно, на произвольные промежутки времени. Например, в лифте. У меня есть ещё один пример — личный и очень показательный. Однажды мы ездили в Карелию. Там между глэмпингами есть длинные участки дороги без интернета. И мы были вынуждены либо мириться с полным отсутствием Моей волны в пути, либо регулярно вручную переключаться между рекомендациями и офлайн-режимом. Неудобно.

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

Как это работает? Этот вопрос логично разделить на два других: откуда берётся музыка без интернета и как мы её ранжируем на устройстве. Начнём с более простого.

Откуда берутся треки для Моей волны в офлайне

Приложение Яндекс Музыка использует три источника треков на устройстве:

Кэш Моей волны. Треки, которые недавно играли в онлайне, сохраняются в кэше и могут использоваться офлайн.

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

Проактивная загрузка. Это новый механизм. Теперь приложение сообщает серверу Яндекс Музыки, какие треки уже есть на устройстве, и запрашивает дополнительные «на случай отключения интернета». Наша серверная рекомендательная технология анализирует список треков и присылает список дополнительных композиций, которые соответствуют предпочтениям пользователя и могут пригодиться при отсутствии сети.

Ну а дальше приложение просто скачивает эти треки в фоне. Чтобы не расходовать мобильный интернет, треки скачиваются только при подключении к Wi-Fi. Скачивание происходит ночью, когда устройство стоит на зарядке (или достаточно заряжено). Более того, пользователи могут управлять в настройках объёмом памяти, который Моя волна использует для офлайн-работы. Но отключать полностью не рекомендуем: без этой опции офлайн-рекомендации будут куда менее разнообразными и в потоке точно не будет новых, незнакомых треков.

Как устроена технология локальных рекомендаций

В приложении Яндекс Музыки появилась не только проактивная загрузка треков, но и рекомендательная технология TinyML. Вопреки ожиданиям, это не нейросетевая модель, а куда более неожиданное решение. По сути, это очень маленькая виртуальная машина, встроенная в приложение Яндекс Музыки и выполняющая роль интерпретатора для специального байт-кода.

Байт-код — это скомпилированный код на языке C, который формирует офлайн-рекомендации на устройстве. В нём закодированы операции: вычисление косинусов между векторами, матричные умножения, применение преобразующих функций — все те базовые операции, которые производят рекомендации и на серверах. Важно, что код компилируется под конкретный набор треков на устройстве, — он «знает», с какими именно треками будет работать. Можно сказать, что мы собираем персональную «модель» рекомендаций под каждого пользователя с учётом только тех треков, которые ей доступны. Это позволяет радикально сэкономить потребление ресурсов смартфона: байт-код очень компактный, буквально десятки килобайт!

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

Байт-код и данные о треках загружаются с сервера по API раз в три дня или при существенном изменении набора кэшированных треков. Общий объём данных с учётом сжатия обычно меньше 100 КБ, в худшем случае — меньше мегабайта. Система может работать с лимитом до 10 000 треков, но чаще всего это сотни треков.

На этом месте читатели с опытом в мобильной разработке могут спросить: а зачем вы создавали свою TinyML, а не воспользовались уже существующими решениями? Ведь есть проект ONNX, есть нативные ML-библиотеки. С одной стороны, это упростило бы нам работу, не пришлось бы писать свой серверный компилятор. С другой — нам бы пришлось выносить логику работы рекомендаций из байт-кода на клиенты, писать её под каждую платформу. А ещё клиентский код не так-то просто обновить без обновления всего приложения, в отличие от загрузки простого байт-кода по API.

Кто-то может вспомнить ещё и проект WebAssembly, который уже «из коробки» позволяет работать с ML и писать код низкого уровня. Но в этом случае нам пришлось бы встроить его библиотеку в само приложение и увеличить его размер на десятки мегабайт. Столь радикально раздувать размер ради одной единственной функции мы не считаем правильным. TinyML уложился в 30 килобайт.

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

Как Моя волна в офлайне работает на практике

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

Помимо байт-кода для локального формирования рекомендаций, сервер также отдаёт предпросчитанную очередь — список треков «что поставить, если интернет отключится прямо сейчас». Это несколько десятков треков, рассчитанных тяжёлыми серверными нейросетями. Эта очередь — палочка-выручалочка для коротких перебоев с сетью вроде поездки на лифте. TinyML может использовать её как основу, но если пользователь начинает пропускать треки, система отбросит предпросчитанную очередь и будет строить рекомендации на основе свежей обратной связи. 

Например, у пользователя в кэше есть и джаз, и металл. Он начинает пропускать металл — TinyML понимает, что настроение изменилось, и переключается на джаз. Всё это происходит локально, без интернета. 

Для длительного офлайн-прослушивания (те самые несколько часов в Карелии) основную работу делает локальный код TinyML, а не предпросчитанная очередь.


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

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

Комментарии (27)


  1. ru4pae
    27.03.2026 08:07

    Как человек который одно время много перемещался на машине скажу Алилуя!

    Не прошло и 15 лет, как Яндекс музыка догадались, что если пропал интернет, то надо проигрывать файлы с телефона, а не ждать, когда вернётся связь.


    1. sunki
      27.03.2026 08:07

      Смешно. У вк кстати та же болезнь. Какое-то время работает, а потом говорит, что не может проверить подписку и превращается в тыкву.


  1. viordash
    27.03.2026 08:07

    А можете добавить в "Моя волна" настройку, период повтора композиции? А то уже часть, из ранее любимых композиций в дизлайках, так как ваша рекомендация иногда зависает на одной композиции и может в течении короткого времени проиграть ее несколько раз


  1. Dimmirslr
    27.03.2026 08:07

    Часто катаюсь из города в город, где чаще всего связи нет, поэтому вещь интересная, смотрим как работать будет


  1. VoviqueShulgin
    27.03.2026 08:07

    Спасибо за новую штуку, конечно, но... ребят, а можно сделать что-то с авиарежимом в iOS? Каждый раз, при разблокировке, приложение ругается на авиарежим, даже когда слушаешь загруженную музыку. Для чего это сделано - хз, но раздражает ужасно.


  1. Abyss777
    27.03.2026 08:07

    А можно сделать, чтоб на мою волну влиял только плейлист Понравившиеся? Я вот для ребёнка отдельный плейлист создал, когда с ним в машине еду - включаю. Смешарики - От винта конечно клёвая песня, но обычно она не соответствует моей волне.


    1. LynchTime
      27.03.2026 08:07

      Так есть же


      1. Finterio
        27.03.2026 08:07

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


  1. UFO_01
    27.03.2026 08:07

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


    1. dmitrik4321
      27.03.2026 08:07

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


  1. equeim
    27.03.2026 08:07

    Теперь при возврате в приложение после сворачивания оно будет в 50% случаев автоматически переходить в офлайн режим, как карты? Очень "удобная" фича.


  1. cmyser
    27.03.2026 08:07

    а TinyML это open source ?


  1. TyVik
    27.03.2026 08:07

    Здорово, конечно, но сколько эта ML будет жрать батарейки? И можно ли как-нибудь поэкономнее? Пишу, потому что Go съедает 50% за 20 минут в активном режиме (да, телефон старый, но рабочий); а окно курьера Еды грузит 1 ядро CPU.


  1. Druzd
    27.03.2026 08:07

    а о заряжен батарейки никто не подумал)))

    а если я трек слушаю несколько раз и на макс.громкости он учитывается в рекомендациях как самый лучший? Нет конечно. А вот в spootify это учитывается и подмешиваются близкие треки.

    А это вот Ваше tinyML - покушать батарейку))


  1. mydigitalhabb
    27.03.2026 08:07

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

    Что там у вас за дикие таймауты ожидания интернета ? Почему нельзя выставить 5 секунд - если за 5 секунд сервис не ответил, то прерываем любую загрузку и показываем оффлайн то что есть.


  1. veneamin
    27.03.2026 08:07

    Это хорошо, что оно переходит на джаз при скипании металла, это правильно. Но в "свободном" режиме можно не крутить одно и то же по сто раз? Что, музыки на свете мало? А уж если лайкнул что, жди потом поток именно в этом стиле. С одной стороны логично, но всему должна быть мера. Хочется разнообразия. Волна "незнакомое" не спасает, там сплошные каверы по 15 вариантов на сундук мертвеца. Именно разнообразия мне как давнему пользователю не хватает. Причем есть куча загруженных мною же треков в мои альбомы на сайте, но крайне редко, если вообще, оттуда что-то играет, зато уже 100 раз слушанное - Нате вам, слушайте 101й раз.

    И пожалуйста, сделайте опцию "не выключать экран" хотя бы при подключенном питании! Ведь приложение это уже умеет при показе текста, так дайте мне эту возможность без текста!


    1. Z55
      27.03.2026 08:07

      Это хорошо, что оно переходит на джаз при скипании металла, это правильно.

      сплошные каверы по 15 вариантов на сундук мертвеца

      Так правильно или не правильно? Я скипаю не метал, а "отстойный метал", теже каверы например.


      1. veneamin
        27.03.2026 08:07

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


        1. Z55
          27.03.2026 08:07

          О том и речь, что "скипнул метал, включили джаз" - это вообще непонятный поворот. А если скипнул джаз, включать шамана? ))


          1. veneamin
            27.03.2026 08:07

            скипнул-то ладно, а вот если лайкнул неосторожно инструменталку, например, то получи на весь вечер одну инструменталку


            1. Z55
              27.03.2026 08:07

              О да ))


  1. kiff2007200
    27.03.2026 08:07

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


    1. veneamin
      27.03.2026 08:07

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


  1. EspritDeCorps
    27.03.2026 08:07

    О, а они что-то знают о том, что грядет, да?
    Эх, была бы там еще музыка, было бы вообще супер. А так, до спотика им еще далеко, как до луны.


  1. vikarti
    27.03.2026 08:07

    Чтобы не расходовать мобильный интернет, треки скачиваются только при подключении к Wi-Fi. Скачивание происходит ночью, когда устройство стоит на зарядке (или достаточно заряжено).

    А можно как то сделать чтобы использовался и мобильный интернет тоже (пусть как опция)? (бывает ситуация сейчас такая что проще к WiFi телефон вообще не подключать а пакет трафика большой)

    С "достаточно заряжено" - учитывается что у некоторых телефонов есть режим когда больше 80% он в принципе не заряжается(до отключения режима)?


  1. Z55
    27.03.2026 08:07

    Лучше скажите как слушать треки со всеми словами, а не с их частью? Кажется, для этого нужно отказаться от Плюса и уйти к конкурентам?


  1. yasnolesskiy
    27.03.2026 08:07

    Сегодня мы впервые представляем нашу новую рекомендательную технологию TinyML

    Так вы "TinyML" сами придумали или готовое взяли?
    Если сами придумали, то почему взяли в качестве названия registered trademark of the Edge AI Foundation (ex. tinyML Foundation)?
    Если взяли технологии, разработанные Edge AI Foundation, то почему это никак в статье не упоминаете и выдаёте за своё?