Skip to content

Add API command to get the color palette for any image#4193

Merged
marcelveldt merged 3 commits into
devfrom
add-image-palette-api
Jun 12, 2026
Merged

Add API command to get the color palette for any image#4193
marcelveldt merged 3 commits into
devfrom
add-image-palette-api

Conversation

@marcelveldt

@marcelveldt marcelveldt commented Jun 12, 2026

Copy link
Copy Markdown
Member

What does this implement/fix?

Color-palette extraction (Sendspin color@v1) was only available internally, for now-playing artwork. This exposes it as a metadata API command so any image can be turned into a palette, and moves the palette cache to the cache controller so results persist across restarts instead of living in a volatile in-memory LRU.

Changes:

  • Add metadata/get_image_palette — accepts a MediaItemImage or an image URL and returns a MediaItemPalette.
  • Back palette caching with the cache controller (sqlite) instead of the in-memory LRU; remove the bespoke LRU and the synchronous peek_palette_for_url.
  • Carry the current image's resolved palette on player state (set by the async fetch) so the synchronous player-state serialization stays non-blocking.

Types of changes

  • Bugfix (non-breaking change which fixes an issue) — bugfix
  • 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

Checklist

  • The code change is tested and works locally.
  • pre-commit run --all-files passes.
  • pytest passes, and tests have been added/updated under tests/ where applicable.
  • 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.
  • I have read and complied with the project's AI Policy for any AI-assisted contributions.
  • I have raised a PR against the documentation repository targeting the main or beta branch as appropriate.

Add metadata/get_image_palette, accepting a MediaItemImage or an image
URL and returning the Sendspin color@v1 palette. Reuses the existing
process-wide palette memory cache (shared with the player queue logic),
so repeated requests for the same image are cheap.
Store extracted palettes in the cache controller (sqlite) so they persist
across restarts, are shared, and clear with the cache. Drop the bespoke
in-memory LRU and the synchronous peek_palette_for_url: the cache controller
is async-only and cannot be read during the (sync) player-state
serialization, so the resolved palette for the currently shown image is now
carried on player state (set by the async fetch) and read back at serialize
time. User-visible behaviour is unchanged.
Copilot AI review requested due to automatic review settings June 12, 2026 17:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR exposes image color-palette extraction (Sendspin color@v1) as a public metadata API command and changes palette caching to use the cache controller (sqlite) so results persist across restarts, while keeping synchronous player state serialization non-blocking by carrying the resolved palette on Player.

Changes:

  • Add metadata/get_image_palette API command to return a MediaItemPalette for a MediaItemImage or image URL.
  • Move palette caching from an in-memory LRU to the cache controller (sqlite) and remove the sync peek_palette_for_url path.
  • Attach asynchronously-resolved palettes to player state so sync serialization can include palettes without blocking.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/core/test_image_proxy.py Updates test docstring wording around cache key behavior.
music_assistant/models/player.py Adds carried palette fields + setter and uses carried palette during sync state serialization.
music_assistant/helpers/colors.py Switches palette caching to cache controller; removes in-memory LRU + peek_palette_for_url.
music_assistant/controllers/players/controller.py Updates palette-fetch scheduling/attachment flow to use async resolution and player-carried palette.
music_assistant/controllers/metadata.py Adds metadata/get_image_palette API command wiring to palette extraction helpers.
Comments suppressed due to low confidence (1)

music_assistant/controllers/players/controller.py:1680

  • [CRITICAL] _schedule_palette_fetch dedupes tasks only by player_id+slot, so if the current track changes while a previous palette fetch is still running, the new fetch will be dropped and the new track may never get a palette until another state update happens. Set abort_existing=True for current-track fetches (or include an image-specific suffix in the task_id) so the latest image always gets fetched.
        # The caller only schedules a current-track fetch when no palette is set yet,
        # and the task_id dedupes concurrent fetches, so no extra cache probe is needed.
        slot = "current" if trigger_update else "next"
        self.mass.create_task(
            self._fetch_palette(player_id, image_url, trigger_update=trigger_update),
            task_id=f"palette_fetch_{player_id}_{slot}",
            abort_existing=False,
        )

Comment thread music_assistant/controllers/metadata.py Outdated
Comment thread music_assistant/controllers/metadata.py
- Fix stale docstring: palettes are cached via the cache controller, not memory.
- Key the palette-fetch task on the image so a track change always schedules a
  fetch for the new image instead of being dropped by an in-flight fetch for the
  previous one (same-image schedules still dedupe).
- Add tests for the get_image_palette command dispatch and error handling.
@marcelveldt

Copy link
Copy Markdown
Member Author

re the suppressed task_id comment: valid edge - a quick track change could drop the new fetch while the previous one is still running. keyed the task on the image now (d8caebf) so the new image always schedules, same-image schedules still dedupe. went with that over abort_existing=True since that would restart an in-flight fetch on unrelated state updates.

@marcelveldt

Copy link
Copy Markdown
Member Author

This should maybe be backported to stable because this also improves the caching of the palette and it can be helpful for the (mobile) clients to have this command available

@marcelveldt marcelveldt merged commit d4a4e3e into dev Jun 12, 2026
12 checks passed
@marcelveldt marcelveldt deleted the add-image-palette-api branch June 12, 2026 18:15
anatosun pushed a commit to anatosun/music-assistant-server that referenced this pull request Jun 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants