/
/
# What does this implement/fix? Adds **Spotify Soloist** as a second way to play Spotify audio, alongside the existing librespot. Soloist is Spotify's own playback engine, so it works with accounts created since December 2024 (which librespot cannot play), and it brings Spotify's crossfade and its loudness normalization. Unlike the earlier attempt (#5832, which fetched every song separately and felt sluggish), this keeps **one playback session** and feeds it the next song ahead of time. The session plays the songs continuously and Music Assistant splits that audio back into normal queue items — so only the first song of a queue cold-starts, the ones after it follow on without a break, and the crossfade is simply part of the audio. librespot stays the default and existing setups are untouched: a fresh setup preselects it, and so does a reconfigure of any instance that predates the choice. **Related issue (if applicable):** - companion models PR (merged): https://github.com/music-assistant/models/pull/374 ## Types of changes - [ ] Bugfix (non-breaking change which fixes an issue) — `bugfix` - [x] New feature (non-breaking change which adds functionality) — `new-feature` - [ ] Enhancement to an existing feature — `enhancement` - [ ] New music/player/metadata/plugin provider — `new-provider` - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) — `breaking-change` - [ ] Refactor (no behaviour change) — `refactor` - [ ] Documentation only — `documentation` - [ ] Maintenance / chore — `maintenance` - [ ] CI / workflow change — `ci` - [ ] Dependencies bump — `dependencies` ## Changes **Setup** - The Spotify provider now asks which playback engine to use, with the Soloist terms, a personal API key and pairing with your Spotify account behind that choice. - Pairing has to be done from an app signed in to the same account you connected, so your library and your audio cannot end up on different accounts. **Playback** - New Soloist backend: one continuous session, fed one track ahead, handed to the queue as ordinary tracks. - The next track is prepared when the session actually reaches it, rather than on a timer that cannot work for audio arriving in real time. - Skipping and seeking use the session's own controls where they can, instead of starting a new one. **Options** - **Let Spotify even out the volume between songs** (on by default). Spotify normalizes using values computed for its whole catalogue, and Music Assistant then leaves the level alone rather than correcting it twice — which also makes songs start noticeably quicker. Turn it off and Music Assistant normalizes instead, as it does for every other source. - **Streaming quality**, sharing the tiers the Spotify Connect plugin already offers and defaulting to lossless. - The queue's crossfade setting now drives Spotify's crossfade, so that toggle stops being inert for Spotify playback. - The stream path reports what Spotify served (lossless for music, Ogg Vorbis for podcasts and audiobooks) instead of Music Assistant's internal format. **Core** - Volume normalization can be skipped for a source that already normalized its own audio. - A track from a source that hands over audio in real time is recognised as such by Sendspin players, and no longer has a next-track buffer prepared before that audio exists. ## Checklist - [x] The code change is tested and works locally. - [x] `pre-commit run --all-files` passes. - [x] `pytest` passes, and tests have been added/updated under `tests/` where applicable. - [x] For changes to shared models, the companion PR in `music-assistant/models` is linked. - [ ] For changes affecting the UI, the companion PR in `music-assistant/frontend` is linked. - [x] I have read and complied with the project's [AI Policy](https://github.com/music-assistant/.github/blob/main/AI_POLICY.md) for any AI-assisted contributions. - [ ] I have [raised a PR against the documentation repository](https://github.com/music-assistant/music-assistant.io/blob/main/CONTRIBUTING.md) targeting the main or beta branch as appropriate.