navidrome/core/artwork
Deluan Quintão 83fff44c82
feat(archiver): add folder cover image to downloaded zips (#6224)
* feat(archiver): add folder cover image to downloaded zips

Album, artist, playlist and share downloads now include the item's cover as
folder.<ext>, the image most players and car stereos show for the files next to
it. This helps users who copy transcoded downloads to offline devices, since
transcoding drops the embedded artwork (#5841).

Album folders get the album cover, the artist zip root gets the artist image,
and playlist and share zips get the playlist or shared item's cover at the root.
The image is the same one getCoverArt serves, resized to 500px (not square),
and named by its detected type. Items without artwork get no image, and a cover
that fails to load is logged and skipped so it never breaks the archive.

The archiver reads covers through a new core.CoverArtReader interface,
implemented by artwork.CoverArtReader, to avoid an import cycle between core
and core/artwork.

* refactor(archiver): read covers through artwork.Artwork directly

The archiver no longer needs a local CoverArtReader interface and adapter.
The only reason core/artwork imported core was a core.AbsolutePath call in
loadArtistFolder, which now reads the library path from the repository and
cleans it the same way. With the import cycle gone, the archiver takes
artwork.Artwork and treats ErrUnavailable and ErrNotFound as no cover.

Covers are now written after each album's tracks (and after all tracks for
the archive root), so a slow artwork lookup does not delay the first bytes
of the download.

* fix(archiver): read share covers as admin so private playlists keep theirs

Public share downloads run with an anonymous context, and the playlist
repository hides private playlists from anonymous users, so a zip of a shared
private playlist silently had no folder image. Like the public image handler,
the share itself is the authorization: the cover lookup now runs with an admin
user. Only the cover read is elevated; streaming keeps the anonymous context,
so the transcode limiter still keys public downloads the same way.

* style(archiver): trim comments

Shorten the comments added by the folder cover image change and drop the ones the names already explain.

* fix(archiver): add one cover per album folder in artist zips

Albums with the same name share a zip folder (pre-existing naming), so an
artist zip with two such albums wrote two folder.<ext> entries at the same
path. Keep the first cover and skip the rest for that folder.
2026-09-25 16:42:49 -04:00
..
blurhash perf(artwork): compute the blurhash DCT separably (#5989) 2026-08-19 16:20:38 -04:00
dominant feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
e2e fix(test): stop the Windows test job from failing at random (#6182) 2026-09-20 15:27:20 -04:00
thumbhash feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
agent_images.go fix(scrobbler): back off when a provider asks us to, instead of retrying per play (#6028) 2026-08-29 17:28:29 -04:00
agent_images_test.go fix(scrobbler): back off when a provider asks us to, instead of retrying per play (#6028) 2026-08-29 17:28:29 -04:00
animation.go feat(artwork): preserve animated image artwork during resize (#5184) 2026-03-13 18:11:12 -04:00
animation_test.go feat(artwork): preserve animated image artwork during resize (#5184) 2026-03-13 18:11:12 -04:00
artwork.go fix(artwork): only use image files as local artwork sources (#6180) 2026-09-20 13:40:14 -04:00
artwork_suite_test.go fix(artwork): block private and loopback addresses in remote image fetches (#6181) 2026-09-20 20:46:46 -04:00
artwork_test.go fix(artwork): only use image files as local artwork sources (#6180) 2026-09-20 13:40:14 -04:00
benchmark_decode_test.go perf(artwork): improve image serving performance with WebP encoding and optimized pipeline (#5181) 2026-03-13 09:35:59 -04:00
benchmark_encode_test.go perf(artwork): improve image serving performance with WebP encoding and optimized pipeline (#5181) 2026-03-13 09:35:59 -04:00
benchmark_helpers_test.go feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
benchmark_pipeline_test.go feat(artwork): preserve animated image artwork during resize (#5184) 2026-03-13 18:11:12 -04:00
benchmark_tag_test.go perf(artwork): improve image serving performance with WebP encoding and optimized pipeline (#5181) 2026-03-13 09:35:59 -04:00
disc.go feat(cli): add an artwork command group for diagnosing and re-driving artwork (#5957) 2026-08-14 21:07:56 -04:00
disc_test.go feat(cli): add an artwork command group for diagnosing and re-driving artwork (#5957) 2026-08-14 21:07:56 -04:00
folders_album.go feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
folders_album_test.go feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
folders_artist.go feat(archiver): add folder cover image to downloaded zips (#6224) 2026-09-25 16:42:49 -04:00
folders_artist_paths_test.go feat(archiver): add folder cover image to downloaded zips (#6224) 2026-09-25 16:42:49 -04:00
folders_artist_test.go feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
gate.go fix(artwork): honor a provider's explicit retry-later delay in the circuit breaker (#6056) 2026-09-01 11:07:58 -04:00
gate_test.go fix(artwork): honor a provider's explicit retry-later delay in the circuit breaker (#6056) 2026-09-01 11:07:58 -04:00
hash_encoder_bench_test.go feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
housekeeping.go fix(artwork): never retry absent artwork on its own (#6054) 2026-09-01 20:48:41 -04:00
housekeeping_test.go fix(artwork): never retry absent artwork on its own (#6054) 2026-09-01 20:48:41 -04:00
image_cache.go feat(cli): add an artwork command group for diagnosing and re-driving artwork (#5957) 2026-08-14 21:07:56 -04:00
image_cache_test.go feat(cli): add an artwork command group for diagnosing and re-driving artwork (#5957) 2026-08-14 21:07:56 -04:00
image_store.go fix(artwork): make stored images group-readable (#6189) 2026-09-21 17:25:46 -04:00
image_store_test.go fix(artwork): make stored images group-readable (#6189) 2026-09-21 17:25:46 -04:00
library_fs.go feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
library_fs_test.go feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
playlist_cover.go feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
processor.go fix(scrobbler): back off when a provider asks us to, instead of retrying per play (#6028) 2026-08-29 17:28:29 -04:00
processor_test.go fix(scrobbler): back off when a provider asks us to, instead of retrying per play (#6028) 2026-08-29 17:28:29 -04:00
prune.go feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
prune_test.go feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
resize.go fix: miscellaneous fixes for shares, artwork resize, auth limits, and watcher start (#6098) 2026-09-11 15:03:54 -04:00
resize_test.go fix: miscellaneous fixes for shares, artwork resize, auth limits, and watcher start (#6098) 2026-09-11 15:03:54 -04:00
resolve.go fix(artwork): only use image files as local artwork sources (#6180) 2026-09-20 13:40:14 -04:00
resolve_test.go fix(artwork): only use image files as local artwork sources (#6180) 2026-09-20 13:40:14 -04:00
sources.go fix(artwork): block private and loopback addresses in remote image fetches (#6181) 2026-09-20 20:46:46 -04:00
sources_internal_test.go fix(artwork): block private and loopback addresses in remote image fetches (#6181) 2026-09-20 20:46:46 -04:00
trace.go feat(artwork): store the resolution trace so artwork explain works offline (#5980) 2026-08-21 10:24:01 -04:00
trace_test.go feat(artwork): store the resolution trace so artwork explain works offline (#5980) 2026-08-21 10:24:01 -04:00
uploader.go feat(artwork): make the artwork image size cap configurable (#5931) 2026-08-11 10:42:39 -04:00
uploader_test.go feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
wire_providers.go feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
worker.go fix(scanner): stop DB lock starvation during scans on slow storage (#6201) 2026-09-23 17:04:50 -04:00
worker_soak_test.go fix(scrobbler): back off when a provider asks us to, instead of retrying per play (#6028) 2026-08-29 17:28:29 -04:00
worker_test.go fix(scanner): stop DB lock starvation during scans on slow storage (#6201) 2026-09-23 17:04:50 -04:00
worker_timing_test.go fix(artwork): ramp the external circuit breaker back up instead of closing on one answer (#5961) 2026-08-15 10:36:14 -04:00