HiFi/MB cover art: use CAA 1200px thumbnail, not the flaky /front original

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.
This commit is contained in:
BoulderBadgeDad 2026-05-28 14:37:03 -07:00
parent c9ad4f496f
commit abdea631a7
2 changed files with 28 additions and 18 deletions

View file

@ -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()

View file

@ -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