Add Yandex Music Connect (Ynison) plugin provider#3614
Add Yandex Music Connect (Ynison) plugin provider#3614trudenboy wants to merge 26 commits intomusic-assistant:devfrom
Conversation
🔒 Dependency Security Report📦 Modified Dependencies
|
| Name | Skip Reason |
|---|---|
| torch | Dependency not found on PyPI and could not be audited: torch (2.11.0+cpu) |
| torchaudio | Dependency not found on PyPI and could not be audited: torchaudio (2.11.0+cpu) |
| ✅ No known vulnerabilities found |
Automated Security Checks
- ✅ Vulnerability Scan: Passed - No known vulnerabilities
- ✅ Trusted Sources: All packages have verified source repositories
- ✅ Typosquatting Check: No suspicious package names detected
- ✅ License Compatibility: All licenses are OSI-approved and compatible
- ✅ Supply Chain Risk: Passed - packages appear mature and maintained
Manual Review
Maintainer approval required:
- I have reviewed the changes above and approve these dependency updates
To approve: Comment /approve-dependencies or manually add the dependencies-reviewed label.
There was a problem hiding this comment.
Pull request overview
Adds a new yandex_ynison plugin provider that exposes Music Assistant players as Yandex Music Connect (Ynison) devices, including QR-based authentication, a WebSocket client for Ynison state sync, and PCM streaming via the existing yandex_music provider.
Changes:
- Introduce the Ynison WebSocket client (redirector → state service) with reconnect and state parsing/sending helpers.
- Add the plugin provider that maps Ynison state/control to Music Assistant player/source selection and streaming via ffmpeg conversion.
- Add QR authentication helpers and a unit test suite for client/provider behavior.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
music_assistant/providers/yandex_ynison/__init__.py |
Provider setup and config flow (QR auth actions, player selection options). |
music_assistant/providers/yandex_ynison/constants.py |
Centralized protocol/config constants for Ynison. |
music_assistant/providers/yandex_ynison/manifest.json |
Declares the plugin provider metadata and docs link. |
music_assistant/providers/yandex_ynison/icon.svg |
Provider icon asset. |
music_assistant/providers/yandex_ynison/yandex_auth.py |
Yandex Passport QR auth + token exchange helpers. |
music_assistant/providers/yandex_ynison/ynison_client.py |
Core Ynison WebSocket client implementation (connect, message loop, reconnect, send/state parsing). |
music_assistant/providers/yandex_ynison/provider.py |
PluginProvider implementation bridging Ynison state to MA playback/source and streaming. |
tests/providers/yandex_ynison/__init__.py |
Test package marker. |
tests/providers/yandex_ynison/test_ynison_client.py |
Unit tests for protocol header/state parsing/sending/disconnect/device-id generation. |
tests/providers/yandex_ynison/test_provider.py |
Unit tests for provider init, player selection, source selection behavior, provider matching, and Ynison state handling. |
MarvinSchenkel
left a comment
There was a problem hiding this comment.
Please refactor this PR to use the central auth like we discussed in your other PR. Will have an in depth look after that.
|
Hi @MarvinSchenkel — thanks for the pointer. The refactor landed as v1.6.0 of the plugin (trudenboy/ma-provider-yandex-ynison#34) and was synced to this PR branch after your review. Short summary of what changed:
PR title and body have been refreshed to match the current state. Ready for re-review when you get a chance. |
Summary
Add new Yandex Music Connect (Ynison) plugin provider that makes Music Assistant players appear as playback devices in the Yandex Music app — similar to how Spotify Connect works.
When a user selects the MA device in the Yandex Music app, the plugin receives track IDs via the Ynison WebSocket protocol, fetches audio from Yandex Music CDN (via the linked
yandex_musicMusicProvider), and streams PCM to the selected MA player.Architecture
Authentication model
The plugin supports two top-level auth modes, picked via the Yandex Music source dropdown. Together they give three reachable populated states:
yandex_musicMusicProvider is configured) — read OAuth credentials live from a linkedyandex_musicinstance viaProviderConfig.get_value(). No secrets stored in the Ynison config; reactive refresh fromx_tokenon 401 is in-memory only (scheduled refresh stays withyandex_music).Login with QR codeaction opens a Passport QR popup (viaAuthenticationHelper); on scan-confirm both the music token and the long-livedx_tokenare stored in this plugin's config. Each instance can be bound to its own Yandex account without sharing tokens with ayandex_musicprovider — useful withmulti_instance: truefor one-account-per-player setups. ARemember sessiontoggle controlsx_tokenpersistence; with it enabled the plugin reactively refreshes on 401 in own mode, mirroring borrow behaviour.CONF_TOKEN. With no storedx_token, expiry surfaces a clearLoginFailedso the user knows to paste a new token.Upgrades from earlier standalone versions preserve own-mode if
CONF_TOKENwas set, so no silent switch of auth source.Key features
yandex_musicMusicProvider with FFmpeg PCM conversion (-rerealtime pacing) and byte-accurate progress syncversion.device_id-based — inspects the author of incomingplayer_queueandstatusversion blocks to suppress feedback loops from our own round-tripped updates (covers both queue and status-only echoes)version/timestamp_ms/progress_ms/duration_msfields are string-typed (integers trigger HTTP 500 + WS teardown); inbound state is normalized at ingestion so reconnect replays and queue edits stay safe by constructionRemember sessionon the plugin refreshes the music token from a storedx_tokenon 401 — no manual re-paste, no sharedyandex_musicinstance requiredSyncStateFromEOVfor queue replenishment, bounds-validated queue advancementin_use_bylifecycle — released on pause, re-acquired on resume vianeeds_reselectflagStreamMetadataChanged files
providers/yandex_ynison/__init__.pyym_instancedropdown, own-mode QR/clear actions, upgrade-path preservationproviders/yandex_ynison/provider.pyproviders/yandex_ynison/ynison_client.pyproviders/yandex_ynison/auth.pyya-passport-authwrapper:perform_qr_auth(QR popup → tokens) andrefresh_music_token(x_token → fresh music token)providers/yandex_ynison/streaming.pyproviders/yandex_ynison/constants.pyx_token/account_login/QR action keys),yandex_musicconfig-key constants, defaultsproviders/yandex_ynison/protocols.pyproviders/yandex_ynison/config_helpers.pylist_yandex_music_instances()— enumerates linked YM providers for the dropdownproviders/yandex_ynison/manifest.jsonya-passport-auth==1.3.0,depends_on: yandex_music)providers/yandex_ynison/icon.svgrequirements_all.txtya-passport-auth==1.3.0tests/.../test_provider.pytests/.../test_ynison_client.pytests/.../test_config_entries.pytests/.../test_auth.pytests/.../test_streaming.pyTest plan
pytest)yandex_musicinstancex_token,Logged in as <login>status is shown; second instance can be bound to a different Yandex account; reset-auth clears all three fieldsRelated PRs
Dependencies
ya-passport-auth==1.3.0— async Yandex Passport client. Used forrefresh_music_token(x_token)(borrow + own modes) and the QR login flow (PassportClient.start_qr_login+poll_qr_until_confirmed).yandex_musicMusicProvider (depends_onin manifest) — hard requirement for audio streaming. Borrow mode additionally reads its OAuth credentials. Runtime detection via_check_yandex_provider_match()handles the edge case where the provider is unloaded while the plugin is running; borrow-mode token reads surface a clearLoginFailedif the linked instance was removed.