diff --git a/core/artwork/serving.go b/core/artwork/serving.go index 97c46fc9b..4b86644d9 100644 --- a/core/artwork/serving.go +++ b/core/artwork/serving.go @@ -268,12 +268,17 @@ func (s *service) serveDisc(ctx context.Context, artID model.ArtworkID, size int if err != nil { return nil, err } - funcs := dr.fromDiscArtPriority(ctx, s.ffmpeg, conf.Server.DiscArtPriority) - if r, path, err := selectImageReader(ctx, artID, funcs...); err == nil && r != nil { - defer r.Close() - if data, rerr := readCapped(r); rerr == nil { - if hash, herr := HashImage(bytes.NewReader(data)); herr == nil { - return s.serveBytes(ctx, hash, data, unixMtime(mtimeViaFS(dr.lib.FS, path)), size, square) + // Only multi-disc albums use disc-specific resolution (matching the legacy reader); a + // single-disc album serves album art directly, so a stray disc*/embedded image can't + // shadow higher-priority album art. + if len(dr.album.Discs) > 1 { + funcs := dr.fromDiscArtPriority(ctx, s.ffmpeg, conf.Server.DiscArtPriority) + if r, path, err := selectImageReader(ctx, artID, funcs...); err == nil && r != nil { + defer r.Close() + if data, rerr := readCapped(r); rerr == nil { + if hash, herr := HashImage(bytes.NewReader(data)); herr == nil { + return s.serveBytes(ctx, hash, data, unixMtime(mtimeViaFS(dr.lib.FS, path)), size, square) + } } } } diff --git a/core/artwork/serving_test.go b/core/artwork/serving_test.go index b71ae1e05..68ca77cd6 100644 --- a/core/artwork/serving_test.go +++ b/core/artwork/serving_test.go @@ -257,7 +257,7 @@ var _ = Describe("Service", func() { It("delegates a multi-disc track to its disc art, not straight to the album", func() { // Not embedded-eligible: the fallback must mirror CoverArtID (disc first, then album). folderRepo.result = []model.Folder{{Path: "tests/fixtures/artist/an-album", ImageFiles: []string{"cover.jpg"}}} - albumRepo.SetData(model.Albums{{ID: "aldd", Name: "Album", FolderIDs: []string{"f1"}}}) + albumRepo.SetData(model.Albums{{ID: "aldd", Name: "Album", FolderIDs: []string{"f1"}, Discs: model.Discs{1: "One", 2: "Two"}}}) seedFoundStore("al", "aldd", []byte("album-art-distinct")) // album's own found art differs mfRepo.SetData(model.MediaFiles{{ID: "mf5", AlbumID: "aldd", DiscNumber: 1, HasCoverArt: false}}) @@ -266,6 +266,18 @@ var _ = Describe("Service", func() { // The disc-folder image wins over the album's found art, proving it routed via serveDisc. Expect(readAll(img)).To(Equal(coverBytes)) }) + + It("delegates a single-disc track straight to the album, skipping disc resolution", func() { + folderRepo.result = []model.Folder{{Path: "tests/fixtures/artist/an-album", ImageFiles: []string{"cover.jpg"}}} + albumRepo.SetData(model.Albums{{ID: "alsd", Name: "Album", FolderIDs: []string{"f1"}, Discs: model.Discs{1: ""}}}) + seedFoundStore("al", "alsd", []byte("album-art-distinct")) + mfRepo.SetData(model.MediaFiles{{ID: "mf6", AlbumID: "alsd", DiscNumber: 1, HasCoverArt: false}}) + + img, err := svc.Get(ctx, model.MustParseArtworkID("mf-mf6"), 0, false) + Expect(err).ToNot(HaveOccurred()) + // Single-disc album: album art wins; the folder disc image must not shadow it. + Expect(readAll(img)).To(Equal([]byte("album-art-distinct"))) + }) }) Describe("disc", func() {