- .gitignore: якоря /cache/, /database/, /dlna/ только для корневых каталогов - git add -f: папка Cache модуля Music (MusicMetadataCacheService и др.) — без неё Roslyn-компиляция модуля падает (CS0103) на любой машине, где проект получен из git (сервер уходил в crash-loop)
Music
Музыкальный модуль для [Lampac] — превращает Lampa в полноценный музыкальный сервис: главный экран с полками и чартами, поиск, экраны артистов и альбомов, пользовательские плейлисты, импорт из Spotify / Apple Music / SoundCloud, синхронизированные тексты песен и отдельный музыкальный плеер для iOS, Android и Windows.
Модуль серверный (C# / ASP.NET, динамическая компиляция при старте Lampac) с единым клиентом для Lampa (plugin.js), который отдаётся как /music.js.
Возможности
- Главный экран — недавно прослушанное, недавние альбомы/артисты/поиски, пользовательские плейлисты и discovery-полки (Apple Music, Spotify, VK Top, SoundCloud).
- Поиск — артисты, альбомы, треки; каноническая база метаданных MusicBrainz, дополнительные секции из YouTube Music.
- Воспроизведение — автоматический подбор playable-источника (YouTube, Sefon, SoundCloud, опционально Z3Fm) с точным поиском по ISRC, когда каталог его предоставляет, и fallback по названию/артисту; выбранный вручную источник закрепляется (
pinned) и переживает перезапуски. - Пользовательские плейлисты — создание, наполнение из любого экрана, перестановка треков, хранение на сервере с привязкой к профилю браузера.
- Импорт плейлистов и альбомов по ссылке — Spotify, Apple Music, SoundCloud; без API-ключей и без логина. Повторная синхронизация — слияние: локальный порядок и ручные правки сохраняются, новые треки источника добавляются в начало.
- Управление очередью отовсюду — лонг-тап по треку в любом списке: «Играть следующим», «Добавить в очередь», «Убрать из очереди»; перестановка и удаление также из шита очереди плеера. Очередь переживает перезапуск клиента (снапшот с восстановлением позиции).
- Радио — «Радио от трека» из меню любого трека (волна от выбранной песни) и автоподборка в конец очереди; движок похожести — рекомендации SoundCloud (related/station) со слоистым пулом и жёстким дедупом.
- Статистика прослушиваний — «Твой топ»: играбельный альбом из самых прослушиваемых треков, появляется после накопления данных; счётчики по дням в SQLite.
- Выбор плеера для музыки — отдельная настройка в «Настройки → Плеер», независимая от глобального плеера Lampa (встроенный, Music Player на Android/Windows, iOS, VLC и другие внешние).
- Тексты песен — синхронизированная (караоке) и обычная лирика через lrclib с фоллбеком на YouTube Music; ручная подгонка тайминга на телефоне и с пульта телевизора.
- iOS lock screen — в standalone-режиме плеера: play/pause, next/prev, перемотка скраббером, корректные метаданные и обложка, автопереход треков, устойчивое возобновление на заблокированном экране.
- Стриминг через сервер — клиент никогда не ходит на внешние CDN напрямую: единый relay
/music/streamс поддержкой Range-запросов, тикетами и автоматическим повторным резолвом протухших ссылок.
Архитектура
Модуль не пытается сделать «универсальный парсер любого сайта». Каждый внешний источник подключается в одной или нескольких строго разделённых ролях:
| Роль | Ответственность | Текущие источники |
|---|---|---|
| Metadata | канонические артисты, альбомы, треки | MusicBrainz |
| Discovery | полки, чарты, подборки, секции поиска | Apple Music, Spotify, VK Top, SoundCloud, YouTube Music |
| Audio | playable match и stream sources | YouTube (основной), Sefon, SoundCloud, Z3Fm (опц.) |
| Auth | внешние пользовательские аккаунты | SoundCloud (каркас, выключен по умолчанию) |
| Images | обогащение картинок | Discogs (фото артистов) |
| Import | импорт плейлистов по ссылке | Spotify, Apple Music, SoundCloud |
Ключевые принципы:
- Metadata-база одна — MusicBrainz. Discovery- и audio-источники не становятся источником правды о каталоге.
- Home всегда быстрый — discovery-провайдеры опрашиваются параллельно с бюджетом времени; медленный или упавший источник не блокирует ответ, его секция догревается в фоне.
- Durable отделён от volatile — SQLite хранит только результат действий пользователя (история, плейлисты, pinned-источники, учётные данные); все кэши живут в
HybridFileCacheи памяти.
flowchart TD
Client["plugin.js / Lampa UI"] --> Api["Controllers"]
Api --> Catalog["MusicCatalogService"]
Api --> Playback["MusicPlaybackService / MusicResolver"]
Api --> Playlists["MusicUserPlaylistService"]
Api --> Lyrics["MusicLyricsService"]
Catalog --> Metadata["Metadata providers"]
Catalog --> Discovery["Discovery providers"]
Playback --> Audio["Audio providers"]
Playback --> Relay["/music/stream relay"]
Playlists --> DB["Music.sql (SQLite)"]
Lyrics --> Cache["HybridFileCache"]
Metadata --> Cache
Audio --> Cache
Структура каталога
Controllers/ HTTP API: ApiController, SearchController, PlaybackController, AuthController
Models/ Contracts.cs — DTO контрактов API
Providers/
Abstractions/ интерфейсы провайдеров
Metadata/ MusicBrainz
Discovery/ AppleMusic, Spotify, VkTopChart, SoundCloud, YouTubeMusic
Audio/ YouTube, Sefon, Z3Fm
SoundCloud/ общий site-support (partial: Catalog / Audio / Import / Auth)
Spotify/ импорт публичных плейлистов/альбомов (анонимный embed-токен)
AppleMusic/ импорт публичных плейлистов/альбомов (анонимный web-JWT)
Services/
Catalog/ оркестрация home / search / секций, реестр провайдеров
Playback/ резолвер источников, stream relay, тикеты, история
Playlists/ пользовательские и импортированные плейлисты
Lyrics/ lrclib + YouTube Music fallback
Images/ image proxy, Discogs
Cache/ metadata cache, source-match cache
SQL/ MusicContext.cs — durable SQLite с self-healing и safe backup
plugin.js весь клиент Lampa, отдаётся как /music.js
ModInit.cs регистрация модуля и значения конфигурации по умолчанию
ModuleConf.cs схема настроек
manifest.json dynamic: true, зависимость YoutubeExplode
Установка
- Поместите каталог
MusicвModules/вашей установки Lampac. Модуль объявлен какdynamicи компилируется автоматически при старте. - Перезапустите Lampac. При первом старте создаётся
database/music/с SQLite-базой. - Клиентский плагин доступен по адресу
{host}/music.js— подключите его в Lampa штатным способом (initPluginsв конфигурации LampaWeb либо вручную как плагин).
Проверка, что сервер поднялся:
curl -fsS 'http://127.0.0.1:9118/music/home'
curl -fsS 'http://127.0.0.1:9118/music/providers'
Конфигурация
Настройки задаются в init.conf Lampac под ключом Music и подхватываются без перезапуска. Пример:
{
"Music": {
"useproxy": false,
"useproxystream": false,
"applemusic_country": "ru",
"applemusic_album_resolver": "auto",
"spotify_discovery_enabled": true,
"spotify_country": "ua",
"soundcloud_country": "UK",
"z3fm_enabled": true,
"z3fm_audio_enabled": true
}
}
Полная схема (ModuleConf.cs) со значениями по умолчанию (ModInit.cs):
| Параметр | По умолчанию | Описание |
|---|---|---|
default_metadata_provider |
musicbrainz |
metadata-база каталога |
default_audio_provider |
youtubeaudio |
основной audio-провайдер |
default_auth_provider |
(пусто) | auth-провайдер по умолчанию |
useproxy |
false |
прокси для API, поиска и discovery; используется стандартный proxy Lampac |
useproxystream |
false |
прокси для получения manifest и передачи audio-stream |
globalnameproxy |
(пусто) | имя proxy из глобального globalproxy Lampac |
proxy |
(пусто) | локальная настройка proxy Music; имеет приоритет над глобальной |
client_debug_enabled |
false |
приём клиентских трейсов на /music/clientlog (только для отладки) |
stats_clear_enabled |
false |
показывать сервисную кнопку очистки статистики «Твоего топа» в фильтре |
youtube_audio_enabled |
true |
YouTube как audio-источник (через YoutubeExplode) |
spotify_search_fallback_enabled |
false |
дополнительные результаты поиска Spotify |
spotify_discovery_enabled |
true |
региональная полка плейлистов Spotify на главном экране |
spotify_country |
us |
профиль плейлистов Spotify: UA, CA, US, RU, PL, FR, DE; для остальных ISO-кодов используется явно подписанный Global-профиль |
sefon_audio_enabled |
true |
Sefon как дополнительный audio-источник |
soundcloud_enabled |
true |
SoundCloud целиком |
soundcloud_discovery_enabled |
true |
полки/подборки SoundCloud |
soundcloud_audio_enabled |
true |
SoundCloud как audio-источник |
soundcloud_auth_enabled |
false |
вход в аккаунт SoundCloud (OAuth) |
applemusic_country |
us |
регион Apple Music Charts (ISO 3166-1 alpha-2) |
applemusic_album_resolver |
auto |
открытие альбомов из Apple-полок: auto, applemusic, spotify, soundcloud или musicbrainz |
soundcloud_client_id |
(пусто) | собственный client_id; без него скрапится публичный |
soundcloud_client_secret |
(пусто) | для OAuth-потока |
soundcloud_redirect_uri |
(пусто) | для OAuth-потока |
soundcloud_country |
US |
регион SoundCloud Charts: US или UK (GB нормализуется в UK) |
z3fm_enabled |
false |
Z3Fm целиком (требует Playwright для антибота) |
z3fm_audio_enabled |
false |
Z3Fm как audio-источник |
z3fm_proxy_enabled / z3fm_proxy_url / z3fm_proxy_username / z3fm_proxy_password |
false / (пусто) |
прокси для Z3Fm |
limit_map |
^/music: 15 req/s |
WAF rate-limit для эндпоинтов модуля |
Каждый профиль Spotify содержит одну полку с 15 плейлистами: пять основных региональных, пять дополнительных региональных тематических и пять глобальных тематических. Для CA, US, PL, FR, DE используются официальные подборки Spotify; профили UA и RU частично состоят из публичных локальных плейлистов. После смены spotify_country нужен перезапуск Lampac; недоступный плейлист пропускается, не блокируя остальные discovery-источники.
applemusic_album_resolver задаёт приоритет открытия карточек Apple Music Charts. auto использует цепочку Apple ID → Spotify → SoundCloud → MusicBrainz; applemusic — Apple ID → MusicBrainz; spotify — Spotify → MusicBrainz; soundcloud — SoundCloud → MusicBrainz; musicbrainz сохраняет старое поведение. В SoundCloud учитываются только результаты из секции альбомов, пользовательские плейлисты исключены. Spotify участвует при включённом spotify_search_fallback_enabled, SoundCloud — при включённом soundcloud_discovery_enabled; неизвестное значение строго нормализуется в auto.
HTTP API
Все эндпоинты живут под префиксом /music. Внешние картинки в ответах проксируются через image-proxy, stream-ссылки — через relay: клиенту не нужны прямые запросы к внешним сервисам.
Клиент и служебные
| Метод | Эндпоинт | Назначение |
|---|---|---|
| GET | /music.js, /music/js/{token} |
клиентский плагин |
| GET | /music/providers |
список активных провайдеров |
| POST | /music/clientlog |
приём клиентских трейсов (при client_debug_enabled) |
Каталог и поиск
| Метод | Эндпоинт | Назначение |
|---|---|---|
| GET | /music, /music/home |
главный экран |
| GET | /music/section?id= |
полный список секции («Ещё» / пагинация) |
| GET | /music/search?q= |
поиск |
| GET | /music/artist?id= |
экран артиста |
| GET | /music/artistsection |
догрузка секций артиста |
| GET | /music/artistimg |
lazy-обогащение фото артиста (Discogs) |
| GET | /music/album?id= |
экран альбома |
| GET | /music/track |
данные трека |
Воспроизведение
| Метод | Эндпоинт | Назначение |
|---|---|---|
| GET | /music/play |
playable-ответ для трека (источники + stream URL) |
| GET | /music/stream |
relay стрима (Range, тикеты, авто re-resolve) |
| GET | /music/matches |
кандидаты audio-источников для трека |
| POST | /music/match/select |
закрепить ручной выбор источника (pinned) |
| POST | /music/match/reset |
сбросить закреплённый выбор |
| GET | /music/playlist.m3u |
плейлист очереди в формате M3U |
| POST | /music/history/mark |
обновить историю; count_play=true инкрементит счётчик статистики, played_ms добавляет фактически прослушанное время |
| POST | /music/history/remove |
удалить запись истории |
| GET | /music/stats/top |
топ треков профиля + условия разблокировки «Твоего топа» |
| POST | /music/stats/clear |
очистить дневную статистику текущего профиля, не трогая историю прослушиваний |
Плейлисты
| Метод | Эндпоинт | Назначение |
|---|---|---|
| GET | /music/playlists |
список плейлистов профиля |
| GET | /music/playlists/tracks |
треки плейлиста |
| POST | /music/playlists/create |
создать плейлист |
| POST | /music/playlists/delete |
удалить плейлист |
| POST | /music/playlists/import |
импорт по ссылке (Spotify / Apple Music / SoundCloud) |
| POST | /music/playlists/sync |
пересинхронизировать импортированный плейлист |
| POST | /music/playlists/track/add |
добавить трек |
| POST | /music/playlists/track/remove |
убрать трек |
| POST | /music/playlists/track/move |
переставить трек внутри плейлиста (position — финальный индекс) |
| POST | /music/radio |
подобрать похожие треки (автоподборка очереди и «Радио от трека») |
| GET | /music/daily |
микс дня недели (day 1–7, опц. salt — счётчик сброса): треки двух артистов из истории + похожего |
Прочее
| Метод | Эндпоинт | Назначение |
|---|---|---|
| GET | /music/lyrics |
текст песни (synced/plain) |
| GET | /music/auth/state |
состояние внешней авторизации |
| POST | /music/auth/save |
сохранить учётные данные |
| POST | /music/auth/logout |
выйти |
Как это работает
Резолв и воспроизведение трека
- Клиент вызывает
/music/playс идентификатором трека и fallback-параметрами (артист, название, длительность). - MusicPlaybackService собирает track DTO, MusicResolver подбирает audio match: сначала закреплённый пользователем
pinned-источник, затем кэшированный авто-матч, затем поиск по провайдерам с ранжированием. - Выбранный провайдер возвращает stream sources; сервер превращает их в тикетные URL
/music/stream?...— прямые ссылки на CDN клиенту не отдаются. - Relay отдаёт поток с поддержкой Range. Если тикет жив, а upstream-ссылка умерла (403/404/410), выполняется прозрачный повторный резолв по fallback-параметрам — трек не прерывается ни при протухании ссылки, ни после перезапуска сервера.
Ручной выбор источника («Источники» в интерфейсе, включая поиск произвольным запросом) сохраняется как pinned в SQLite и имеет безусловный приоритет над эвристиками — это спасает треки с «грязными» метаданными из чартов.
Режимы плеера
У клиента две принципиально разные реальности воспроизведения:
inner— встроенный плеер Lampa. На iOS lock screen поддерживает play/pause, next/prev, метаданные и обложку; перемотка скраббером в этом режиме сознательно не поддерживается (подробный разбор: docs/ios-embedded-lockscreen-seek.md).ios— standalone audio-плеер модуля для iPhone: собственный полноэкранный интерфейс (очередь, shuffle/repeat, таймер сна, лирика, свайпы), полный Media Session (включая скраббер перемотки), keep-alive аудиосессии и восстановление воспроизведения на заблокированном экране.
Эти режимы не следует смешивать — у них разная логика Media Session и жизненного цикла audio-элемента.
Плейлисты и импорт
Плейлисты хранятся на сервере (SQLite, таблица user_playlists) с привязкой к профилю браузера — той же identity, что и история прослушиваний. Payload плейлиста содержит полные объекты треков, поэтому плейлист самодостаточен и не зависит от доступности внешних каталогов.
Импорт по ссылке работает без ключей и логина:
- Spotify — анонимный токен со страницы embed-плеера + внутренний GraphQL API с пагинацией; импорт атомарный (сбой любой страницы отменяет импорт целиком).
- Apple Music — анонимный developer-JWT из веб-бандла music.apple.com + публичный catalog API; поддержаны плейлисты (включая пользовательские
pl.u-…) и альбомы, все storefront'ы. - SoundCloud — публичный client_id (скрапится автоматически либо задаётся в конфиге).
Импортированный плейлист хранит source и может быть пересинхронизирован. Синхронизация зеркалит источник: ручные изменения в таком плейлисте будут перезаписаны.
Тексты песен
/music/lyrics возвращает синхронизированный (LRC, построчный тайминг) или обычный текст. Основной источник — lrclib.net; при отсутствии synced-варианта пробуется fallback через YouTube Music. Кэширование дифференцированное: synced-результаты живут долго, plain-only и «не найдено» — коротко, сетевые сбои не кэшируются вовсе и помечаются retry для клиента.
Для синхронизированного текста клиент позволяет подогнать тайминг в диапазоне от −10 до +10 секунд с шагом 0,5 секунды. + показывает текст позже, − — раньше; нажатие на значение сбрасывает сдвиг в ноль. В standalone-плеере управление находится в окне «Текст», во встроенном плеере — над лирикой и отдельными кнопками − / + на панели для управления пультом. Сдвиг действует только на текущий трек, сбрасывается при его смене и не показывается для обычного текста без таймингов.
Радио
У радио два входа:
- «Радио от трека» — пункт в лонг-тап меню любого трека: выбранный трек стартует первым, дальше — волна из ~20 подобранных. При неудаче подбора текущая очередь не меняется.
- Автоподборка — opt-in тумблер («Автоподборка треков» в фильтре и чип «Подборка» в фулл-плеере — одна настройка, выключена по умолчанию): когда очередь подходит к концу, в неё догружаются похожие треки. В шите очереди граница отмечается разделителем «Дальше автоподборка».
Движок похожести — слоистый пул на сервере (MusicRadioService):
- Рекомендации SoundCloud по треку —
relatedиtrack-station(их коллаборативная фильтрация), основной слой; - Топ-треки сид-артистов (YouTube Music / SoundCloud поиск) — только backfill при недоборе.
Пулы чередуются round-robin, чтобы выдача не вырождалась в одного исполнителя.
Контракт:
- работает только для управляемой очереди модуля (
ios/inner), не для внешних m3u-плееров; POST /music/radioпринимает seed-треки и явныйexcludeтекущей очереди; сиды всегда исключаются из выдачи;- дедуп:
track.id, нормализованныеartist + title, история прослушиваний за сутки; - шумофильтр: миксы/подкасты/реакции, треки короче 45с и длиннее 12мин; cover/karaoke/sped up/slowed/nightcore/remix — только если этих слов не было в сиде; при полностью кириллическом сид-контексте латинский мусор отсекается;
- триггер автоподборки — предпоследний трек по порядку воспроизведения (с учётом shuffle), не чаще одного запроса на поколение очереди;
repeat=allотключает автоподборку: зацикленная очередь — осознанный выбор;- если кандидатов мало, сервер честно отвечает
available:falseи клиент ничего не добавляет.
Главный риск фичи — не код, а качество рекомендаций; настройка ведётся по живым промахам, не «по формуле». SponsorBlock для YouTube-треков сознательно не в roadmap (нет реальной боли, внешний skip-сервис рискует ложными пропусками); YouTube Mix как движок рекомендаций проверен и отвергнут — анонимный доступ закрыт YouTube («Войдите в аккаунт»), логин-пути модуль не использует.
Статистика: «Твой топ»
Статистика подаётся не экраном с цифрами, а играбельным альбомом: карточка «Твой топ» появляется на главном экране рядом с плейлистами только после накопления данных (10 разных треков и либо фаворит с 10 прослушиваниями, либо 100 прослушиваний суммарно). Внутри — топ треков с настоящими «Слушать»/«Перемешать», числом прослушиваний у каждой строки и сухой метой в духе «247 прослушиваний · примерно 18 ч · артисты заработали ≈ $0.99 · почти кофе».
Данные: таблица track_stats_daily (профиль, трек, день, счётчики, last_played) — только счётчики, витрина треков джойнится из playback_history. play_count инкрементится исключительно на честном play-пути (count_play=true после реальной задержки воспроизведения), а total_ms пополняется фактическими кусками played_ms без повторного увеличения счётчика; обновления payload статистику не трогают. Дневная гранулярность оставляет пространство для будущих окон («за месяц», «На повторе», «Вернуть в ротацию»).
Хранение данных
Durable (SQLite, database/music/Music.sql) — только то, что выражает действие пользователя или долгоживущую identity: история прослушиваний, дневная статистика (track_stats_daily), пользовательские плейлисты, pinned-выборы источников, учётные данные внешних сервисов. База защищена self-healing (карантин повреждённого файла вместе с WAL/SHM-сайдкарами, восстановление из последнего валидного бэкапа) и безопасным бэкапом через SQLite backup API.
Volatile (HybridFileCache + память) — кэши метаданных, авто-матчей, лирики, картинок, stream-тикеты. Волатильный кэш никогда не попадает в SQLite.
Расширение: новый источник
Источник подключается не «сайтом целиком», а конкретной ролью. Рекомендуемый порядок внедрения незнакомого сервиса: Discovery → Audio → Auth — сначала источник безопасно появляется в интерфейсе, затем добавляется воспроизведение.
Общий порядок:
- Определить, что источник реально даёт (полки? стримы? аккаунт?).
- Реализовать провайдер под соответствующий интерфейс из Providers/Abstractions.
- Добавить флаги в ModuleConf.cs и значения по умолчанию в ModInit.cs (для audio-источников default —
false, пока не проверено качество матчей). - Зарегистрировать провайдер в MusicProviderRegistry.cs.
- Проверить через API, не трогая остальную архитектуру.
Контракты по ролям
Discovery (IMusicDiscoveryProvider): GetHomeSectionsAsync — короткие секции для home, GetSectionAsync — полный список для «Ещё»/пагинации.
Audio (IMusicAudioProvider): SearchAsync — кандидаты MusicAudioMatch по MusicTrack; GetStreamsAsync — playable MusicPlaybackSource; GetPreferredStreamAsync — быстрый exact-id путь, если он есть, иначе null.
Проверка:
curl -fsS 'http://127.0.0.1:9118/music/home'
curl -fsS 'http://127.0.0.1:9118/music/section?id=examplemusic:top'
curl -fsS 'http://127.0.0.1:9118/music/matches?title=Song&artist_name=Artist&audio_provider=examplemusicaudio'
Обязательные требования к провайдерам
- Не делать новый источник metadata-базой без отдельного архитектурного решения.
- Не блокировать
/music/homeдолгими запросами — уважать бюджет времени. - Не кэшировать сетевой сбой как «пусто навсегда»; пустые результаты кэшировать только коротко.
- Stream отдавать через
/music/stream, а не напрямую клиенту. - Уважать
pinned-выбор пользователя. - Внешние картинки возвращать в обычных полях ответа, чтобы их подхватил
MusicImageProxyService.
Разработка
После изменения серверного кода — пересборка (модуль компилируется при старте контейнера):
docker compose up -d --build lampac
После изменения только plugin.js пересборка не нужна (файл монтируется), но клиент Lampa кэширует плагин — нужно поднять revision в конфигурации подключения плагина и полностью перезапустить клиент.
Smoke-проверка:
curl -fsS 'http://127.0.0.1:9118/music/home'
curl -fsS 'http://127.0.0.1:9118/music/search?q=nirvana'
curl -fsS 'http://127.0.0.1:9118/music/providers'
Клиентская отладка: включить client_debug_enabled, трейсы клиента будут приходить на /music/clientlog и попадать в логи сервера. После отладки — выключить.
Известные ограничения
- Discovery/импорт Spotify, импорт Apple Music и авто-получение SoundCloud client_id опираются на недокументированные публичные механизмы этих сервисов; при изменениях на их стороне интеграция может временно ломаться до обновления модуля (симптом для Spotify —
PersistedQueryNotFoundв логах). - Перемотка скраббером на iOS lock screen поддерживается только в standalone-режиме плеера (
ios), не во встроенном (inner). - Синхронизация импортированного плейлиста — недеструктивное слияние: порядок и ручные правки сохраняются, новинки добавляются в начало; но треки, удалённые в источнике, локально не удаляются (убрать можно только вручную).
- Управление очередью (играть следующим, убрать, радио-догрузка) работает только для управляемой очереди модуля (
ios/inner); внешние плееры получают разовый плейлист без возможности менять его после запуска. - Статистика накапливается с момента включения фичи: прослушивания до неё известны только как «последний раз слушал», без счётчиков.
- Лайки/библиотека внешних сервисов переносятся через публичный плейлист (скопировать Liked Songs в публичный плейлист и импортировать по ссылке); прямой доступ к библиотеке требует логина и не реализован.