Конструктор плейлистов для Spotify
Статья о том, как Spotify Web API (SWA) и платформа Google Apps Script (GAS) позволили превратить библиотеку в гибкий конструктор плейлистов с бесплатным исполнением по расписанию.
Под конструктором плейлистов понимаем механизм сбора, фильтрации, сортировки и добавления треков.
Ссылки на исходный код и документацию в конце статьи.
Проблема
Наличие официального API породило для Spotify множество интересных инструментов. В нашем контексте рассмотрим Smarter Playlists. Графический интерфейс в виде графов, множество управляющих блоков делают его довольно дружелюбным для обычного пользователя.
Плотное использование сервиса выявило ряд недостатков: отсутствие истории прослушиваний, лимитированное добавление треков, ограниченное количество запусков по расписанию, некорректная работа с кириллицей. С течением времени сюда добавляется желание новых источников треков, более сложных алгоритмов фильтрации. Сервис перестал развиваться с точки зрения новых функций.
В связи с этим появилось желание альтернативы, устраняющей данные недостатки.
Решение
В результате была разработана библиотека для GAS на JavaScript – Goofy. Конструктором её делает возможность запуска на платформе в редакторе или по расписанию (триггерам) без стороннего ПО.
Естественно GAS накладывает свои ограничения, но другого порядка. Например, время исполнения не более 6 минут; количество запросов к внешним API не более 20 тысяч в день. С другой стороны, круг возможностей существенно расширился. Реализованы все функции Smarter Playlists, устранены его недостатки. Появились новые функции.
Алгоритм
Несколько простых примеров, которые можно реализовать с помощью Goofy
-
Объединение личных миксов с удалением ранее прослушанных треков
-
Выявление давно непрослушиваемых треков
-
Сбор новинок отслеживаемых исполнителей
-
Накопление треков обновляемого источника в плейлисте с удалением уже прослушанных
-
Рекомендации Last.fm любого пользователя, топ за период и прочее
Новые возможности
Особое внимание уделю истории прослушиваний. Частое прослушивание музыки без особо активных действий приводят стриминг платформы к повторам. Одни и те же треки приходят изо дня в день. Goofy позволяет удалить ранее прослушанные треки. Однако это сложнее, чем казалось на первых взгляд.
-
SWA дает возможность получить только 50 последних прослушанных треков. Появление 51-ого делает недоступным 1-й.
GAS имеет выход к Google Drive. Библиотека создает повторяющийся триггер и опрашивает SWA на предмет новых прослушиваний. Если они есть, сохраняет в файл. Таким образом, появляется локальная полная история прослушиваний.
-
Есть другая проблема. Трек считается прослушанным только после 30 секунд. Причем зачастую недавние треки обновляются не сразу или вовсе теряются. Списываю это на “качество” SWA.
Решение есть и здесь – использовать Last.fm. Реализовано два подхода. Во первых, можно просто запросить недавние прослушивания и удалять совпадения по названию трека. Во вторых, можно выполнить поиск трека в Spotify и сохранить его в файл на Google Drive. Тем самым получая историю прослушиваний от Last.fm готовую к работе со Spotify.
Кроме того, Last.fm API используется и для получения других источников. Например, рекомендации, треки соседей по музыкальным вкусам, любимые треки, топ за разный период.
Пример
Нужно выполнить установку (копирование в GAS) и настройку (выдача разрешений, ключи доступа). Все подробно есть в документации.
1) Простой пример: получить любимые треки, взять пять случайных и добавить в плейлист.
Далее графическими средствами GAS создаем триггер. В результате, например, раз в минуту плейлист будет обновляться пятью случайными треками.
function createHelloPlaylist() {
let tracks = Source.getSavedTracks();
Selector.keepRandom(tracks, 5);
Playlist.saveWithReplace({
name: 'Hello, playlist',
tracks: tracks,
});
}
2) Выявить любимые треки, которые не были прослушаны более чем месяц.
function templateSavedAndForgot(){
let recentTracks = Source.getRecentTracks(2500);
let savedTracks = Source.getSavedTracks();
Filter.removeTracks(savedTracks, recentTracks);
let startDate = new Date('2006-01-01');
let endDate = Filter.getDateRel(30, 'endDay');
Filter.rangeDateAbs(savedTracks, startDate, endDate);
Selector.keepRandom(savedTracks, 20);
Order.sort(savedTracks, 'meta.added_at', 'asc');
Playlist.saveWithReplace({
name: 'Любимо и забыто',
tracks: savedTracks,
randomCover: 'update', // установить случайную обложку плейлиста
});
}
3) Получить треки альбомов и синглов отслеживаемых исполнителей за неделю.
function createNewRelease() {
const playlistId = 'abc';
let tracks = Source.getArtistsTracks({
artist: {
followed_include: true
},
album: {
groups: 'album,single',
release_date: { sinceDays: 7, beforeDays: 0 }
},
});
Order.shuffle(tracks);
Combiner.push(tracks, Source.getPlaylistTracks('name', playlistId));
Filter.removeTracks(tracks, RecentTracks.get(3000));
Filter.matchOriginalOnly(tracks);
Playlist.saveWithReplace({
id: playlistId,
name: 'Новые релизы',
tracks: tracks,
randomCover: 'update',
});
}
Ссылки
Документация писалась с ориентиром на пользователя, который не знаком с программированием. Чтобы дать возможность использовать Goofy через копипаст шаблонов и примеров.