docs(yandex): Media Types, My Wave / Wave Modes / My Presets, Device Flow auth#629
Merged
OzGav merged 1 commit intomusic-assistant:betafrom May 7, 2026
Merged
Conversation
…Flow auth Brings the Yandex Music source page in line with ma-provider-yandex-music v3.4.0 (https://github.com/trudenboy/ma-provider-yandex-music, shipped via music-assistant/server#3606): - Media Types adds Podcasts and Audiobooks (v3.1–v3.3 landed those library types with library sync, browse, streaming and in v3.3 cross-device resume-point sync for audiobooks). - Login Method now Device Flow / QR Code / Token (v3.0 added Device Flow and QR; the old single-token path stays as advanced). - Other section calls out the v3.4 rotor-session work: long-lived My Wave session, the 11 one-click Wave Modes, user-defined My Presets, and the behaviour where Radio Mode continues the active wave instead of branching. - Configuration section rewritten around the three auth methods. - Settings lists the new 'Remember session' toggle and the wave presets builder. - Known Issues notes that Yandex Listening History is only written from an Ynison WebSocket session, so regular MA playback isn't visible there without the companion plugin — avoids the FAQ that kept coming up during v3.4 rollout.
✅ Deploy Preview for ohf-music-assistant ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
4 tasks
OzGav
approved these changes
Apr 24, 2026
MarvinSchenkel
pushed a commit
to music-assistant/server
that referenced
this pull request
Apr 28, 2026
…nc improvements (#3606) Syncs the Yandex Music provider in MA core with the out-of-tree provider repo [`trudenboy/ma-provider-yandex-music`](https://github.com/trudenboy/ma-provider-yandex-music) through **v3.4.0**. The last in-tree version was pre-v3. This PR folds in several release lines worth of functional, infrastructure and UX work. ## Highlights ### v3.4.0 — rotor session API + Wave Modes + user presets ([#118](trudenboy/ma-provider-yandex-music#118)) **Rotor session API migration.** My Wave, tagged stations (genre:rock / mood:calm / activity:workout / epoch:*) and track-seed similar-tracks all moved from the legacy `/rotor/station/{id}/*` endpoint to Yandex's newer `/rotor/session/{new,tracks,feedback}`. The server returns a long-lived `radioSessionId` on `POST /rotor/session/new` (together with `includeWaveModel=true` + `interactive=true` flags) that anchors all subsequent feedback, so wave state now survives across browse / recommendations / play entry points instead of losing a per-request `batch_id` on every entry. **Wave Modes browse folder (11 playable presets).** diversity (Discover / Favorites / Popular), moodEnergy (Calm / Active / Fun / Sad) and language (Russian / Non-Russian / Without Words). Each is a separate playable BrowseFolder that creates a rotor session with the matching seed setting. Composite item_ids encode the preset, so rotor feedback lands on the right session. **User-defined wave presets** — advanced settings expose a small builder: name + three dropdowns + Save / Delete action buttons. Presets are persisted in a hidden JSON config key and surface as playable folders under Radio → My Presets. Unlimited count, no hand-editing of JSON. **Rotor likes / prefetch.** `library_add` on a wave track also fires a rotor `like` event on the active session (so _this_ session adapts, not just the next one). `on_played` kicks off a background prefetch of the next wave batch into `wave.prefetched` so MA's DSTM refill (if the user enables it) gets Yandex-curated tracks without an extra round-trip. The provider does **not** toggle DSTM — that stays a user decision. **`is_dynamic` on autoplaylists.** Feed-generated playlists (Playlist of the Day / DejaVu / Premiere / Missed Likes) now carry `is_dynamic=True` so MA doesn't long-cache their content — Yandex regenerates them on a schedule. **Browse fixes that landed in the same release.** - Collection child paths are nested (`<prov>://collection/tracks`) so the back button returns to the listing instead of the provider root; dispatcher still delegates `collection/<sub>` to core's default library handler. - Wave Modes / My Presets back-navigation — same dual-form path contract (`item_id` underscore form so play-time reconstruction works, `path` slash form so back-nav works). - Listening History was empty because MarshalX stopped populating `full_model` — switched to collecting `track_id`s from `item_id` and batch-hydrating via `get_tracks`. 42 tracks returned where before 0. - AI Wave Sets / Featured Waves rendered empty sub-folders because the payload uses camelCase (`stationId`, `compactImageUrl`) while the code asked for snake_case. Both forms now accepted. ### v3.3.1 — search fix `fix(search): apply limit per bucket after classify_album` ([#116](trudenboy/ma-provider-yandex-music#116)). Album/audiobook split now respects the requested `limit` per media-type bucket, not per raw API page. ### v3.3.0 — audiobook progress sync & discovery ([#115](trudenboy/ma-provider-yandex-music#115)) - **Progress sync to Yandex.** `on_played` / `on_streamed` push chapter position via a new `play_audio` API wrapper so the user's Yandex apps stay in sync with MA's resume point. `parse_audiobook` propagates `album.listening_finished` → `Audiobook.fully_played`. - **Audiobook search.** `MediaType.AUDIOBOOK` maps to Yandex `album` search; results split by `classify_album` into albums / audiobooks. Dedup so `ALBUM + AUDIOBOOK` issues a single API call. - **Collection browse.** *My Audiobooks* / *My Podcasts* sub-folders (RU + EN) routed through base `MusicProvider.browse` → existing `get_library_audiobooks` / `get_library_podcasts` generators. - **Robustness.** Advisory progress path swallows any non-`CancelledError` failure from chapter-map resolution; `_audiobook_progress_point` helper handles EOF (reports end of last chapter, not start) and clamps `track_length_seconds ≥ 1` / offset into `[0, track_length]`. Caches (`_audiobook_chapter_cache`, `_audiobook_play_ids`) cleared on `on_streamed` and `unload`. ### v3.2.x — audiobook streaming - `fix(audiobook): wire seek through can_seek and bound chapter failures` (v3.2.1). - `feat(audiobook): stream audiobooks via chapter concatenation` (v3.2.0) — CUSTOM StreamType iterating per-chapter byte streams with seek translation + failure tolerance. ### v3.1.x — library classifier + auth fixes - Podcast + audiobook classifier (Phase 1): liked albums routed to music / podcast / audiobook via `meta_type` / `type`. - Short-lived `_get_liked_albums_cached` dedupes the three library syncs. - `fix(auth)` series: clear stale refresh_token on QR re-auth, wrap transient Passport errors, don't clear creds on transient failures. ### v3.0.x — yandex-music v3 migration - `yandex-music[async]` v2 → v3.0.0, parsers updated for stricter typing. - Device Flow auth added alongside QR; auto-refresh via `ya-passport-auth` v1.3.0. - `/get-file-info` unified for all quality tiers with native byte-range seek. - Pinned items + Listening History browse folders. ## Dependencies - `yandex-music==3.0.0` - `ya-passport-auth==1.3.0` ## Documentation Docs PR adding the v3.4 feature coverage to music-assistant.io (Wave Modes / My Presets / Device Flow auth, podcast & audiobook support, Known Issues note about Listening History): [music-assistant/music-assistant.io#629](music-assistant/music-assistant.io#629). ## Review history on the upstream repo PR [#118](trudenboy/ma-provider-yandex-music#118) went through three rounds of Copilot review that caught: - rotor session request swallowing `NetworkError` before `_call_with_retry` could see it (transient retry never fired); - `_fetch_similar_tracks_for_seed` creating an unbounded `_wave_states` entry per seed (cached, but stateful) — now stateless; - `_prefetch_rotor_session` mutating shared state between lock phases — now direct `rotor_session_tracks` without going through the session helper; - locking gaps in `_get_my_wave_recommendations`, `get_rotor_station_tracks`, `_prefetch_rotor_session`; - duplicated JSON preset parser in two files — extracted to `provider/presets.py`. All 14 review threads resolved before merge. Also addressed Marvin Schenkel's review on [#3234](#3234) about providers not toggling queue UX settings on the user's behalf — `_ensure_dont_stop_the_music` / `queue.radio_source` writes were removed. ## Test plan - [x] Provider unit tests green — 254 passed covering rotor session plumbing, wave state machine, preset routing, prefetch, rotor feedback, browse listings, audiobook progress, search routing, auth, parsers. - [x] ruff / mypy clean. - [x] Live validation against a real Yandex account in Docker — session API round-trips verified for user:onyourwave / track:{id} / genre:rock / mood:calm / activity:workout / epoch:eighties; feedback + pagination; browse back-nav; history hydration. - [ ] Core-side: provider loads; library sync still works; My Wave plays; Wave Modes / My Presets render and play; audiobook position round-trips with Yandex mobile app; search returns audiobooks under `MediaType.AUDIOBOOK`. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
fionn-r
pushed a commit
to fionn-r/music-assistant-server
that referenced
this pull request
May 4, 2026
…nc improvements (music-assistant#3606) Syncs the Yandex Music provider in MA core with the out-of-tree provider repo [`trudenboy/ma-provider-yandex-music`](https://github.com/trudenboy/ma-provider-yandex-music) through **v3.4.0**. The last in-tree version was pre-v3. This PR folds in several release lines worth of functional, infrastructure and UX work. ## Highlights ### v3.4.0 — rotor session API + Wave Modes + user presets ([music-assistant#118](trudenboy/ma-provider-yandex-music#118)) **Rotor session API migration.** My Wave, tagged stations (genre:rock / mood:calm / activity:workout / epoch:*) and track-seed similar-tracks all moved from the legacy `/rotor/station/{id}/*` endpoint to Yandex's newer `/rotor/session/{new,tracks,feedback}`. The server returns a long-lived `radioSessionId` on `POST /rotor/session/new` (together with `includeWaveModel=true` + `interactive=true` flags) that anchors all subsequent feedback, so wave state now survives across browse / recommendations / play entry points instead of losing a per-request `batch_id` on every entry. **Wave Modes browse folder (11 playable presets).** diversity (Discover / Favorites / Popular), moodEnergy (Calm / Active / Fun / Sad) and language (Russian / Non-Russian / Without Words). Each is a separate playable BrowseFolder that creates a rotor session with the matching seed setting. Composite item_ids encode the preset, so rotor feedback lands on the right session. **User-defined wave presets** — advanced settings expose a small builder: name + three dropdowns + Save / Delete action buttons. Presets are persisted in a hidden JSON config key and surface as playable folders under Radio → My Presets. Unlimited count, no hand-editing of JSON. **Rotor likes / prefetch.** `library_add` on a wave track also fires a rotor `like` event on the active session (so _this_ session adapts, not just the next one). `on_played` kicks off a background prefetch of the next wave batch into `wave.prefetched` so MA's DSTM refill (if the user enables it) gets Yandex-curated tracks without an extra round-trip. The provider does **not** toggle DSTM — that stays a user decision. **`is_dynamic` on autoplaylists.** Feed-generated playlists (Playlist of the Day / DejaVu / Premiere / Missed Likes) now carry `is_dynamic=True` so MA doesn't long-cache their content — Yandex regenerates them on a schedule. **Browse fixes that landed in the same release.** - Collection child paths are nested (`<prov>://collection/tracks`) so the back button returns to the listing instead of the provider root; dispatcher still delegates `collection/<sub>` to core's default library handler. - Wave Modes / My Presets back-navigation — same dual-form path contract (`item_id` underscore form so play-time reconstruction works, `path` slash form so back-nav works). - Listening History was empty because MarshalX stopped populating `full_model` — switched to collecting `track_id`s from `item_id` and batch-hydrating via `get_tracks`. 42 tracks returned where before 0. - AI Wave Sets / Featured Waves rendered empty sub-folders because the payload uses camelCase (`stationId`, `compactImageUrl`) while the code asked for snake_case. Both forms now accepted. ### v3.3.1 — search fix `fix(search): apply limit per bucket after classify_album` ([music-assistant#116](trudenboy/ma-provider-yandex-music#116)). Album/audiobook split now respects the requested `limit` per media-type bucket, not per raw API page. ### v3.3.0 — audiobook progress sync & discovery ([music-assistant#115](trudenboy/ma-provider-yandex-music#115)) - **Progress sync to Yandex.** `on_played` / `on_streamed` push chapter position via a new `play_audio` API wrapper so the user's Yandex apps stay in sync with MA's resume point. `parse_audiobook` propagates `album.listening_finished` → `Audiobook.fully_played`. - **Audiobook search.** `MediaType.AUDIOBOOK` maps to Yandex `album` search; results split by `classify_album` into albums / audiobooks. Dedup so `ALBUM + AUDIOBOOK` issues a single API call. - **Collection browse.** *My Audiobooks* / *My Podcasts* sub-folders (RU + EN) routed through base `MusicProvider.browse` → existing `get_library_audiobooks` / `get_library_podcasts` generators. - **Robustness.** Advisory progress path swallows any non-`CancelledError` failure from chapter-map resolution; `_audiobook_progress_point` helper handles EOF (reports end of last chapter, not start) and clamps `track_length_seconds ≥ 1` / offset into `[0, track_length]`. Caches (`_audiobook_chapter_cache`, `_audiobook_play_ids`) cleared on `on_streamed` and `unload`. ### v3.2.x — audiobook streaming - `fix(audiobook): wire seek through can_seek and bound chapter failures` (v3.2.1). - `feat(audiobook): stream audiobooks via chapter concatenation` (v3.2.0) — CUSTOM StreamType iterating per-chapter byte streams with seek translation + failure tolerance. ### v3.1.x — library classifier + auth fixes - Podcast + audiobook classifier (Phase 1): liked albums routed to music / podcast / audiobook via `meta_type` / `type`. - Short-lived `_get_liked_albums_cached` dedupes the three library syncs. - `fix(auth)` series: clear stale refresh_token on QR re-auth, wrap transient Passport errors, don't clear creds on transient failures. ### v3.0.x — yandex-music v3 migration - `yandex-music[async]` v2 → v3.0.0, parsers updated for stricter typing. - Device Flow auth added alongside QR; auto-refresh via `ya-passport-auth` v1.3.0. - `/get-file-info` unified for all quality tiers with native byte-range seek. - Pinned items + Listening History browse folders. ## Dependencies - `yandex-music==3.0.0` - `ya-passport-auth==1.3.0` ## Documentation Docs PR adding the v3.4 feature coverage to music-assistant.io (Wave Modes / My Presets / Device Flow auth, podcast & audiobook support, Known Issues note about Listening History): [music-assistant/music-assistant.io#629](music-assistant/music-assistant.io#629). ## Review history on the upstream repo PR [music-assistant#118](trudenboy/ma-provider-yandex-music#118) went through three rounds of Copilot review that caught: - rotor session request swallowing `NetworkError` before `_call_with_retry` could see it (transient retry never fired); - `_fetch_similar_tracks_for_seed` creating an unbounded `_wave_states` entry per seed (cached, but stateful) — now stateless; - `_prefetch_rotor_session` mutating shared state between lock phases — now direct `rotor_session_tracks` without going through the session helper; - locking gaps in `_get_my_wave_recommendations`, `get_rotor_station_tracks`, `_prefetch_rotor_session`; - duplicated JSON preset parser in two files — extracted to `provider/presets.py`. All 14 review threads resolved before merge. Also addressed Marvin Schenkel's review on [music-assistant#3234](music-assistant#3234) about providers not toggling queue UX settings on the user's behalf — `_ensure_dont_stop_the_music` / `queue.radio_source` writes were removed. ## Test plan - [x] Provider unit tests green — 254 passed covering rotor session plumbing, wave state machine, preset routing, prefetch, rotor feedback, browse listings, audiobook progress, search routing, auth, parsers. - [x] ruff / mypy clean. - [x] Live validation against a real Yandex account in Docker — session API round-trips verified for user:onyourwave / track:{id} / genre:rock / mood:calm / activity:workout / epoch:eighties; feedback + pagination; browse back-nav; history hydration. - [ ] Core-side: provider loads; library sync still works; My Wave plays; Wave Modes / My Presets render and play; audiobook position round-trips with Yandex mobile app; search returns audiobooks under `MediaType.AUDIOBOOK`. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
OzGav
approved these changes
May 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Updates the Yandex Music source documentation to reflect features shipped in the provider after #498 — specifically ma-provider-yandex-music versions v3.0 through v3.4.0 (landing in core via music-assistant/server#3606).
Changes
Features table
Other section — added
Configuration section — rewritten
Three authentication methods now, each as its own subsection. Device Flow is presented first as the recommended path (non-interactive, refreshable). QR second. Manual OAuth token stays as advanced/fallback.
Settings — expanded
Known Issues / Notes — added
Related