Pull to refresh

Умное музыкальное радио, не требующее постоянного Интернет-соединения

Reading time3 min
Views7.7K

Во время работы и прогулок я часто слушаю фоновую музыку. Раньше я использовал интернет радио под названием 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, в будущем планирую проиндексировать и другие открытые источники. Треки на сервере пока не хранятся для экономии места (экономлю на хостинге), а напрямую ссылаются на хранилище источника.


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


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

Tags:
Hubs:
Total votes 12: ↑10 and ↓2+8
Comments25

Articles