Skip to content

Read Artist Watch discographies from MusicBrainz too - #588

Merged
henriquesebastiao merged 1 commit into
henriquesebastiao:mainfrom
BigBrownMF69:feat/artist-watch-musicbrainz
Nov 14, 2026
Merged

henriquesebastiao merged 1 commit into
henriquesebastiao:mainfrom
BigBrownMF69:feat/artist-watch-musicbrainz

Conversation

@BigBrownMF69

Copy link
Copy Markdown
Contributor

Phase 2 of #581, first part: Artist Watch reads MusicBrainz as a third catalogue, beside YouTube Music and Deezer. It fills in what both miss: mixtapes, and older and rarer releases. It reads MusicBrainz directly, not Lidarr's metadata server, since #581 left that question open and MusicBrainz's data is CC0 with public rules for clients.

What it does

downtify/musicbrainz.py is a small web-service client:

  • Polite. At most one request a second, shared by every caller in the process. The User-Agent names Downtify and the repository. A 503/429 ("slow down") is retried after a growing pause. In practice MusicBrainz sends 503 now and then even at 1/s.
  • The artist is found once and kept on the watch (new column musicbrainz_id, migrated like deezer_id). In order:
    1. through the artist's Deezer page (the id Read Artist Watch discographies from Deezer too #583 finds just before), using MusicBrainz's URL relationships;
    2. through the YouTube Music channel;
    3. by name, but only when exactly one artist has exactly that name at score 100. A common name never picks a stranger; MusicBrainz is then skipped for that watch and the other catalogues carry on.
  • Release groups are read page by page with their artist credits, using release-group-status=website-default, the list MusicBrainz's own artist page shows. So groups made only of bootlegs are left out. A group is one album, EP or single with all of its editions, typed like Lidarr's metadata profiles: a primary type and secondary types.
  • Kept:
    • The artist's own groups and joint ones ("PARTYNEXTDOOR & Drake"), not the ones they are a guest on ("Rihanna feat. Drake"). This is decided from the credit's join phrases and MusicBrainz artist ids, not from names.
    • Primary types Album, Single and EP, filtered further by the watch's release_types as before.
    • Secondary types only if let in by artist_watch_musicbrainz_kinds. The default is ["mixtape", "soundtrack"]. Live, compilation, remix, DJ-mix and demo groups mostly repeat the artist's songs, so they're off unless asked for. A group must have all of its secondary types let in, so a remix mixtape stays out.
  • One official edition per group: not a clean/edited version, the most tracks (a deluxe edition holds the standard one), digital, then the earliest. A group with no Official edition (bootlegs, promos) is recorded as skipped and never asked for again.
    • Its tracks become Downtify songs, numbered straight through all discs, with ISRCs.
    • The cover is the Cover Art Archive front image at 500 px. It is resolved to the archive's final URL, because _download_cover doesn't follow redirects. Without one, the YouTube Music match's cover is used, as before.

In monitor._artist_discography:

  • MusicBrainz runs last and leaves to YouTube Music and Deezer any group they already list under the same name and type. It fills gaps rather than fetching every release a third time.
  • Everything else works as for Deezer in Read Artist Watch discographies from Deezer too #583:
    • the songs PR 579's matching already finds in the library (or earlier in the sweep) are linked, not downloaded;
    • a "new releases only" watch that finds its MusicBrainz artist records every group as already there;
    • the sweep fails only when every catalogue failed.

Settings: artist_watch_musicbrainz (default on) and artist_watch_musicbrainz_kinds. There's no UI for them yet. I'd add it with the next part (below), where a per-watch choice fits better.

Also: library_songs._SAME_RECORDING_TAG now folds (From "…") and [From "…"], the film a soundtrack song comes from. Indian labels add it on one catalogue and not another: Tum Hi Ho (From "Aashiqui 2") is MusicBrainz's and Spotify's Tum Hi Ho. The length must still agree, and (Unplugged) and the like stay different songs.

Drake, dry run against the real catalogues

A fresh Drake watch, one full sweep with a fake downloader, so nothing was downloaded. These are anonymous public APIs, the same probe as in #583:

YouTube Music + Deezer (#583) + MusicBrainz, first version + MusicBrainz, this PR
Songs downloaded 384 917 527
From MusicBrainz — 533, from 72 groups 143, from 40 groups
Linked instead of downloaded again — 575 528
Same song downloaded twice 0 0 0
Guest singles skipped 28 28 30
  • The MusicBrainz artist was found through the Deezer page (9fff2f8a…).
  • The first version took any edition and listed every group. It brought in dozens of fan-made "street" compilations, 24 of Drake's 37 mixtape groups being bootleg-only. Hence website-default and the official-edition rule.
  • What MusicBrainz still adds for Drake:
    • his early official mixtapes, which aren't on Deezer or YouTube Music: Comeback Season (24) and Room for Improvement (23);
    • about 35 standalone singles and freestyles: Duppy Freestyle, Behind Barz, Draft Day, Trust Issues, Jodeci Freestyle…
    • a few groups MusicBrainz editors have marked official although they look like fan compilations: Heartbreak Drake (23), Young & Successful (15), No More Thank Yous (11), 5 AM in Toronto (11).
  • That last group is the case for the per-album switches below. Until then, artist_watch_musicbrainz_kinds: ["soundtrack"] turns mixtapes off.
  • A first sweep of a big artist takes a few minutes because of the one-request-a-second rule. Later sweeps cost one request per 100 groups (3 for Drake), plus one per new group.

Next (not in this PR)

The rest of Phase 2: a catalogue view per watched artist. It would show each release group with have / partly / missing, let you switch single albums on and off (Lidarr's per-album monitoring), and have a UI for the release kinds. It would build on this client.

Tests

  • tests/test_artist_watch_musicbrainz.py, 19 tests, all offline:
    • the client: User-Agent and fmt=json; the slow-down retry and giving up; one request per interval; artist mapping by Deezer page, then channel, then unambiguous name; paging; credits (own, joint, guest, with a guest); kinds;
    • edition choice (official only > not clean > most tracks; numbering across discs; ISRC; cover resolution and none; bootleg-only groups);
    • the sweep: MusicBrainz fills gaps and leaves listed groups alone; a song another catalogue fetched is linked; the artist is looked up once; no settled artist and a MusicBrainz failure don't stop the sweep; only all catalogues failing fails it; the new-releases-only baseline; a group with no official edition skipped once and not asked again; defaults.
  • test_library_songs_folds_the_film_a_song_is_from.
  • Full backend suite in Docker (python 3.13 + ffmpeg): 3441 passed. The 13 failures are the music-trash tests, which fail the same way on main on my Windows/Docker setup. ruff check . passes.
  • Docs tests: the only failure is zh-CN/features/doctor.md, already failing on main since docs: complete Simplified Chinese feature translations and fix iOS links #585.
  • Docs: features/playlist-monitor.md, a MusicBrainz paragraph after the Deezer one (English only, no structure change, like Read Artist Watch discographies from Deezer too #583).

🤖 Generated with Claude Code

Phase 2 of henriquesebastiao#581, first part. Artist Watch reads MusicBrainz as a third
catalogue (downtify/musicbrainz.py): one request a second process-wide,
a User-Agent naming Downtify, 503s retried. The artist is found once
through their Deezer page, YouTube Music channel or an unambiguous
name, and kept (musicbrainz_id).

Only the artist's own release groups (not guest spots), of the watch's
primary types, with secondary types let in by
artist_watch_musicbrainz_kinds (mixtapes and soundtracks by default),
and not bootleg-only. One official edition per group: explicit, the
most tracks, digital, earliest. Groups YouTube Music or Deezer already
list are left to them; songs found elsewhere are linked as before.

library_songs also folds (From "Film") title tags, which Indian labels
add on one catalogue and not another.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codspeed

codspeed Bot commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

1 warning

⚠️ 1 benchmark is dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

✅ 10 untouched benchmarks


Comparing BigBrownMF69:feat/artist-watch-musicbrainz (9c5213d) with main (ead6db5)

Open in CodSpeed

@henriquesebastiao
henriquesebastiao merged commit dadb838 into henriquesebastiao:main Nov 14, 2026
8 checks passed
@github-project-automation github-project-automation Bot moved this to Done in Downtify Nov 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend documentation Improvements or additions to documentation frontend monitor tests

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants