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


  • недоступность во время почти ежедневных прогулок по лесу (т.е. без подключения к Интернету).
  • Необходимость переключения между разными каналами, чтобы сменить жанр музыки. Другими словами, у слушателя Jango мало шансов открывать для себя новые музыкальные жанры.

Однажды в голову пришла идея мобильного приложения для прослушивания музыки, которое большую часть времени могло бы работать без Интернета (т.е. кэшировало бы музыку) с автоматическим определением музыкальных пристрастий пользователя. Ничего подобного я не видел (может, просто плохо искал?), поэтому решил реализовать самостоятельно. Сейчас, после нескольких месяцев кодирования в свободное от основной работы время я опубликовал первую, ещё очень сырую, но уже достаточно рабочую версию Android-приложения.



Хотелось реализовать приложение с очень простым и интуитивным интерфейсом (по-сути, только с двумя кнопками: "pause" и "skip"), но с достаточно продвинутой внутренней логикой для анализа музыкальных предпочтений (на основе сбора статистики о продолжительности прослушивания треков до пропуска) и кэширования треков. Поскольку не хотелось дублировать логику для разных платформ, было решено её реализовать на C++ (являющимся "общим знаменателем" для iOS и Android).


Для хранения метаданных о треках, а также пользовательских настроек я выбрал SQLite. Файлы обложек альбомов и музыкальных треков хранятся в трёхуровневом дереве директорий на основе хеша (подобно тому, как это устроено в Git).


Размер кэша выбрал 512 MiB (эти и любые другие цифры, разумеется, могут конфигурироваться). Логика ротации треков следующая: за одну итерацию обновления закачивается по 20 треков. После того, как пользователь как минимум дважды прослушал каждый трек инициируется новое обновление. Удаляются треки, у которых среднее время прослушивания ниже заданного предела, и с сервера загружаются метаданные новых треков, после чего начинается их скачивание.


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


Будучи опытным C++-разработчиком, я не испытал особых трудностей в реализации описанной выше логики (хотя в реальности она несколько более сложная). Однако, не имея опыта написания приложений под Android, мне пришлось затратить много времени и усилий на реализацию соответствующего программного слоя (особенно UI). Уверен, что многие вещи сейчас реализованы не самым лучшим образом.


Android-обёртку я решил писать на Kotlin. В самом деле, Java не сулила никаких преимуществ, ведь всё равно пришлось бы возиться с JNI (в iOS ситуация будет другая, там Objective C гораздо удобнее Swift по части интеграции с нативным кодом основной логики).


Для загрузки JSON-метаданных я использовал Fuel, а для загрузки файлов — Fetch (был удивлён, что Fuel не умеет эффективно скачивать файлы). Кстати, ко второй библиотеке у меня есть претензии по стабильности работы.


Серверный код был написан на Golang и использует PostgreSQL через reform. Текущая база метаданных была построена путём индексирования Free Music Archive, в будущем планирую проиндексировать и другие открытые источники. Треки на сервере пока не хранятся для экономии места (экономлю на хостинге), а напрямую ссылаются на хранилище источника.


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


Буду рад, если попробуете моё приложение. Вдруг вам понравится. Наверняка во время использования вы столкнётесь с багами (программа пока сырая). Скорость их исправления будет напрямую зависеть от востребованности моей работы.

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


  1. Wesha
    13.08.2019 01:37

    кэшировало бы музыку

    Вангую скорый вынос приложеня из аппстора под жалобы и крики вида "ой, а теперь он и тебя сосчитал он нашу музыку бесплатно без разрешения скачивает!!!1111АДЫНАДЫНАДЫН" от копи-сами-знаете-кого. :(


    1. ababo Автор
      13.08.2019 01:39

      Не исключено, но я сознательно индексировал только «бесплатную» музыку.


  1. cjbars
    13.08.2019 05:44

    А не получается ли так, что в ротации остаются одни и те же треки, а новые попадаются все реже и реже?


    1. ababo Автор
      13.08.2019 06:51

      Получится, если размер кэша будет неограниченно расти. А в целом вы правы, старые треки звучат намного чаще новых. Это компенсируется тем, что старые всегда более любимые (прослушиваемые).


      1. UnclShura
        14.08.2019 17:49

        А вот как раз и нет. Старые настолько надоели, что я всегда проматываю некогда любимые треки. Это относится и к топу песен исполнителя — оно все слушано-переслушано.

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

        Я много думал начсет подобных радио. С одной стороны понятно, что автомат не годится совсем — они страдают подбором средней музыки (что если я обажаю металл, но терпеть не могу Металлику или люблю англоязычный металл и русских панков, но не люблю русский металл и не хочу англоязычных панков?). С другой стороны ручные плей листы тоже не годятся — слишком много возни. Возможно подойдет что-то типа ручного выбора исполнителей с весами. И чтоб играло реально случайно, а не «это всем нравится, значит и этому подойдет».


        1. ababo Автор
          14.08.2019 17:54

          А вот как раз и нет. Старые настолько надоели, что я всегда проматываю некогда любимые треки. Это относится и к топу песен исполнителя — оно все слушано-переслушано.
          Это не проблема, поскольку после N (сейчас стоит 30) числа проигрываний трек автоматически удаляется, даже с высоким средним временем прослушивания. Более того, практика показывает, что даже с учётом эффекта, который вы упомянули, среднее время прослушивания (в пределах N проигрываний) очень хорошо коррелирует с музыкальными пристрастиями.


          1. UnclShura
            14.08.2019 18:03

            Это сильно зависит. Я обычно слушаю нового исполнителя несколько дней (все подряд, особенно то, что не в топе). Автомат после этого подумает, что я просто без ума от этого исполнителя, хотя я просто пытался понять что за г№% мне подсунули. Это разумеется если оно вообще в жанр попало.

            За последние три года я протестировал все доступные у нас платные подписки — Deezer, Google Music, Spotify, Apple Music, YouTube Music. Ни один из них не дает нормального радио — все сваливаются в 10 песен топа 10 исполнителей. Существуют заколдованые круги (замкнутые группы) исполнителей из которых нет выхода по similar artists и т.д.

            А как тут написали тратить время (даже 3 секунды) на то, чтоб обучать алгоритм путем слушания явного треша — это не дело.

            ЗЫ: а еще ни один сервис не делит закладки на русскоязычные и англоязычные. Для меня это большая проблема потому, что я их не смешиваю никогда.


            1. MotoDruG
              16.08.2019 07:26

              ИИ лучше знает, что вам нравится, не спорьте))

              специально потратил полчаса на пролайкивание нескольких страниц в яндекс.музыке разных металлистов, в итоге плейлист радио.яндекса свернулся до найтвиша, саббатона, повервольфа, феофана, киш/князя, и ещё нескольких групп. Причём я вообще крайне редко что-то проматывал. Где же та сотня групп, которые я явным образом указал в рекомендуемых для себя? а ИИ его знает…


  1. Shtucer
    13.08.2019 06:06
    -1

    Ничего подобного я не видел (может, просто плохо искал?)

    Неприметный Google Music?


    1. TyZ_21
      13.08.2019 06:52

      Или BOOM от вк или яндекс музыка предоставляют аналогичную логику.


    1. fareloz
      13.08.2019 10:56

      Подозреваю, что подразумевалась бесплатность музыки. Но я так же, как и вы, подумал о Google Play Music сразу.


  1. SOmni
    13.08.2019 06:52

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


  1. alex6999
    13.08.2019 07:46

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


    Первый трек 2999 Laser Furniture
    Второй трек речь Рэйгана
    Третий трек какие-то наркоманы
    Четвертый трек жизнь в бункера.
    5 трек негры по репу чтото гундосят


    Мне хочется закидать помидорами диджея


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


    Я люблю русскую попсу, я люблю иностранную музыку 70х-80х, как мне сказать об этом вашему ИИ, если он мне такие композиции не предлагает?


    1. ababo Автор
      13.08.2019 07:51

      Простите, я 5 минут ждал загрузки первого трека, причем я уже подумал что «оно» неработает
      К сожалению, иногда подглючивает сам Free Music Archive (где физически хранятся файлы), это особенно заметно при первой загрузке музыки. В будущем возможно перенесу на свой сервер. Попробуйте перезапустить программу.

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


      1. smarthomeblog
        13.08.2019 08:54

        ИМХО такая кнопка весьма полезна. Зачем терять время и слушать то, что не нравится, если можно просто пропустить трек и улучшить рекомендательную логику для себя любимого?


        1. ababo Автор
          13.08.2019 08:57

          Может вы и правы, надо подумать. Просто основной акцент ставился на использование в наушниках (там удобно ставить на паузу и пропускать треки).


      1. alex6999
        13.08.2019 09:35
        +2

        Мне почему-то вспоминается фраза Стива Джобса "мы лучше знаем что надо пользователю", увы это не работает. Терпеливыми бывают только платные тестеры.


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


        1. ababo Автор
          13.08.2019 09:37

          Спасибо за совет, подумаю.


  1. PendalFF
    13.08.2019 09:21
    +1

    Начало использования приложения похоже на изощренное издевательство над пользователем
    Попытка пропустить первый трэк(какая-то попса) — вызывает его воспроизведение по кругу в течение 15 раз. Потом добавляется второй (японская народная) и опять 15 раз 2 песни по кругу. Ну и так далее.
    ИМХО нужен крыжик «режим обучения» с расширенными возможностями интерфейса, не ориентированными строго на наушники и минимализм, а позволяющими максимально быстро и удобно обьяснить прикладу что надо предлагать. По достижении приемлемого результата пользователь снимает крыжик и начинает пользоваться в боевом режиме.
    Только лишь гигантский кредит терпения для автора с хабра удержал меня от удаления в первые 5 минут.Однако сейчас я уже устал скипать то что мне не интересно от слова вообще и скорее всего не хватит у меня терпения обучить оно так как мне нужно.


    1. ababo Автор
      13.08.2019 09:25

      К сожалению, это проблемы хостинга файлов на Free Music Archive, который периодически валится. Обычно UX совсем другой. Очень жаль. Могу лишь посоветовать перезапустить приложение через минут 5. Ну или удалить, что, конечно же, проще.


      1. PendalFF
        13.08.2019 11:55

        Я сделал акцент именно на дополнительном режиме, более дружественном к пользователю, наверное.
        Приложение на данный момент никак не информирует о том что происходит в данный момент, что уже отрицательный опыт. Приложение не дает пользователю хоть как-то видимо повлиять на процесс что есть ещё более отрицательный опыт и начинает вызывать раздражение.
        То есть если вы это делаете для себя и вас все устраивает — вообще вопросов быть не может, as is как он есть, не считаю что это плохо. Если вы делаете приложение в том числе с прицелом на бОльшую аудиотрию — у вас есть мое субъективное мнение как бета-тестера.
        Резюмируя — я бы предложил все-же перейти на двухрежимный интерфейс если минималистичный основной является принципиальным по вашей задумке, чтобы дать возможность оценить эту задумку более привередливым людям типа меня.


  1. SabaySabay
    13.08.2019 11:44

    Идея в целом хорошая, но было бы здорово добавить некоторые функции.
    Вот несколько мыслей, которые родились сразу после скачивания программы.
    — При первом запуске программа встречает пользователя требованием зарегистрировать аккаунт с использованием электронной почты и пароля. Где будут храниться эти данные? В каком виде? Кто будет иметь к ним доступ?
    Мне кажется, будет лучше предложить пользователю дополнительные варианты, на пример, Google, FB, VK и так далее, так же будет не лишним написать пользовательское соглашение и добавить галочку «прочел и согласен».
    — Кеширование музыки со старта это хорошо, но сначала спросите пользователя какие стили музыки ему нравятся, а какие совсем не нравятся, как это организованно в Google Music «Улучшить рекомендации», а затем уже загрузите более-менее релевантные треки, визуализируйте процесс загрузки треков и их количество в кеше.
    — Если программа создается для людей и в ней присутстует искуственный интеллект, то необходимо учитывать не только количество прослушиваний, но и стиль музыки, темпо-ритм, пол вокалиста, а так же реакцию пользователя на трек. Лайк может быть сигналом для подбора исполнителей и треков похожих по стилю и другим характеристикам, дизлайк должен быть сигналом для анализа и сопоставления характеристик предыдущих пропущенных треков и так же получивших негативную оценку, дабы уменьшить повторяемость треков со схожими характеристиками.
    — Если треки, так или иначе, кешируются в памяти устройства, то должна быть возможность вернуться к предыдущему треку, ибо пользователь может захотеть послушать его еще раз или по ошибке перешел к следующему треку.


  1. tutam
    13.08.2019 17:34

    Пусть программа при первом запуске показывает окно со списком жанров, около которых можно поставить галочки. ИМХО, так будет лучше.


  1. justK
    13.08.2019 19:16

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

    Плюс было бы здорово видеть навигацию по треку (перемотка, в том числе тапом по полосе)

    Мини-багрепорт: Zenfone Max M1 (андроид 8) + bt уши BL6 (для перехода к следующему треку зажимается клавиша громкости на пару секунд) часто приводят к проскакиванию песни (т.е., переключается песня, раздаётся первые пару звуков из неё и сразу же переключается песня ещё раз), при переключении из приложения такого не замечено.
    Кроме того, частенько одни и те же песни включаются несколько раз подряд. Мой личный рекорд такого повторения подряд за 5 минут использования приложения: композиция №1, трижды композиция №2, композиция №1, дважды композиция №2

    Текущее мнение: не зашло, но дам приложению ещё один шанс, где-то через месяцок.