From abdea631a70e79027f4b9b9d87423d0fea75cedc Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Thu, 28 May 2026 14:37:03 -0700 Subject: [PATCH] HiFi/MB cover art: use CAA 1200px thumbnail, not the flaky /front original MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to the album-art resolution fix. That change upgraded MusicBrainz Cover Art Archive thumbnails (/front-250) to the bare /front original — but /front redirects to archive.org, which is unreliable: probing release-group covers showed intermittent HTTP 500s (same URL 500s one second, serves the next) and multi-MB originals (2.9 MB seen). The result was the user-reported flakiness: cover art that "sometimes works, sometimes shows nothing", and a huge image embedded into every track when it did work. The sized thumbnails (/front-250, -500, -1200) are served by CAA's own CDN, not the archive.org redirect — which is why /front-250 (240p) was always reliable. Upgrade to /front-1200 instead: 1200x1200 is a massive jump from 240p, reliably CDN-served, and a sane ~40 KB instead of multi-MB. Applied in all three CAA spots for consistency: the _upgrade_art_url helper (embed + cover.jpg paths) and both prefer_caa ("CCA") blocks, which fetched the bare /front directly with no fallback — so CCA-on users hit the same flakiness. _fetch_art_bytes still falls back to the original /front-250 if /front-1200 is ever refused. Tests updated to assert the 1200px target, idempotency, and that the bare /front original is intentionally left untouched. --- core/metadata/artwork.py | 23 +++++++++++++---------- tests/metadata/test_artwork_resolution.py | 23 +++++++++++++++-------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/core/metadata/artwork.py b/core/metadata/artwork.py index f1ef58d8..0da28c58 100644 --- a/core/metadata/artwork.py +++ b/core/metadata/artwork.py @@ -287,14 +287,15 @@ def _upgrade_art_url(art_url: str) -> str: except Exception as e: logger.debug("upgrade deezer image url failed: %s", e) elif "coverartarchive.org" in art_url: - # MusicBrainz art comes in as Cover Art Archive thumbnails - # (/front-250, also -500/-1200 — see musicbrainz_search._cover_art_url). - # The bare /front is the original full-resolution upload, which always - # exists when any front art does, so rewrite the size segment back to - # it. Critical for MB-as-source users: without this, embedded art is - # the 250px search thumbnail. `_fetch_art_bytes` falls back to the - # sized URL if /front is ever refused. - return re.sub(r"/front-\d+", "/front", art_url) + # MusicBrainz art arrives as Cover Art Archive thumbnails + # (/front-250 — see musicbrainz_search._cover_art_url). Upgrade to the + # 1200px thumbnail: a huge jump from 240p yet still served by CAA's own + # CDN. Deliberately NOT the bare /front original — that redirects to + # archive.org, which is flaky (intermittent 500s/timeouts) and can be + # multi-MB, nasty to embed in every track. 1200 is the sweet spot of + # quality + reliability. `_fetch_art_bytes` falls back to the original + # sized URL if /front-1200 is ever refused. + return re.sub(r"/front-\d+", "/front-1200", art_url) return art_url @@ -342,7 +343,8 @@ def embed_album_art_metadata(audio_file, metadata: dict): release_mbid = metadata.get("musicbrainz_release_id") if release_mbid and cfg.get("metadata_enhancement.prefer_caa_art", False): try: - caa_url = f"https://coverartarchive.org/release/{release_mbid}/front" + # 1200px CDN thumbnail, not the flaky bare /front original. + caa_url = f"https://coverartarchive.org/release/{release_mbid}/front-1200" req = urllib.request.Request(caa_url, headers={"Accept": "image/*"}) with urllib.request.urlopen(req, timeout=10) as response: image_data = response.read() @@ -412,7 +414,8 @@ def download_cover_art(album_info: dict, target_dir: str, context: dict = None): image_data = None if release_mbid and prefer_caa: try: - caa_url = f"https://coverartarchive.org/release/{release_mbid}/front" + # 1200px CDN thumbnail, not the flaky bare /front original. + caa_url = f"https://coverartarchive.org/release/{release_mbid}/front-1200" req = urllib.request.Request(caa_url, headers={"Accept": "image/*"}) with urllib.request.urlopen(req, timeout=10) as response: image_data = response.read() diff --git a/tests/metadata/test_artwork_resolution.py b/tests/metadata/test_artwork_resolution.py index 3b9c976b..e07c56d0 100644 --- a/tests/metadata/test_artwork_resolution.py +++ b/tests/metadata/test_artwork_resolution.py @@ -45,19 +45,26 @@ class TestUpgradeArtUrl: url = 'https://cdn-images.dzcdn.net/images/cover/abc/1000x1000-000000-80-0-0.jpg' assert '1900x1900' in _upgrade_art_url(url) - def test_caa_thumbnail_upgraded_to_original(self): - # MusicBrainz art arrives as /front-250 (and -500/-1200) thumbnails; - # /front is the original full-resolution upload. + def test_caa_thumbnail_upgraded_to_1200(self): + # MusicBrainz art arrives as the /front-250 thumbnail; upgrade to the + # 1200px CDN thumbnail (NOT the flaky bare /front original). url = 'https://coverartarchive.org/release/abc-123/front-250' - assert _upgrade_art_url(url) == 'https://coverartarchive.org/release/abc-123/front' + assert _upgrade_art_url(url) == 'https://coverartarchive.org/release/abc-123/front-1200' - def test_caa_500_and_release_group_scope_upgraded(self): + def test_caa_500_scope_and_idempotent(self): assert _upgrade_art_url('https://coverartarchive.org/release/x/front-500') \ - == 'https://coverartarchive.org/release/x/front' + == 'https://coverartarchive.org/release/x/front-1200' + # release-group scope works the same. + assert _upgrade_art_url('https://coverartarchive.org/release-group/y/front-250') \ + == 'https://coverartarchive.org/release-group/y/front-1200' + # Idempotent — an already-1200 URL stays put. assert _upgrade_art_url('https://coverartarchive.org/release-group/y/front-1200') \ - == 'https://coverartarchive.org/release-group/y/front' + == 'https://coverartarchive.org/release-group/y/front-1200' - def test_caa_already_original_unchanged(self): + def test_caa_bare_front_left_alone(self): + # The bare /front original is intentionally NOT what we want; the + # sized-thumbnail regex doesn't touch it (and it never reaches the + # helper in practice — _cover_art_url always emits /front-250). url = 'https://coverartarchive.org/release/abc/front' assert _upgrade_art_url(url) == url