Add MusicBrainz provider #1

Open
opened 2025-10-14 15:57:49 -06:00 by navan · 0 comments
Owner

Originally created by @jwillikers on 10/14/2025

Brief summary

Adds a MusicBrainz provider as a source for audiobook metadata and cover art.

Which issue is fixed?

Fixes #4125.

In-depth Description

This PR makes it possible to retrieve metadata and cover art for audiobooks from MusicBrainz releases.
The metadata on MusicBrainz is contributed and maintained by its community.
The MusicBrainz API is documented here and rate-limiting is documented here.
For example data, the Wind and Truth Release Group is probably a good place to start.
This PR adds a proper MusicBrainz provider implementation with support in the Match and Cover Art dialogues.
Cover Art is provided through the Cover Art Archive, which is maintained by the Internet Archive.

Right now, I've opted to use the score returned from the MusicBrainz search as the confidence rating, although it should be noted that the MusicBrainz score does not incorporate duration. Not sure if that's the best choice or not.

The genres, tags, abridged, and explicit fields are all determined via MusicBrainz tags. Genres in MusicBrainz are kind of different than genres for audiobooks, and in MusicBrainz, genres are just a specific set of tags anyways. Any entity in MusicBrainz can have tags, and sometimes they make sense in certain places over others. For instance, tags related to audiobook genres often apply to the written work, so they make the most sense on the work and work series entities. However, unabridged and abridged tags make more sense at the release group level. I basically implemented genres as everything not beloging to a set of special purpose tags, and the presence or abscence of some of those special purpose tags is used to define the values for the abridged and explicit fields.

For language, I directly use the the ISO 639-3 three-letter language code used by MusicBrainz. Maybe I should convert this to the full name of the language to match what the Audible provider returns?

Remaining Work

I could use help with the following, assuming they should even be implemented.

  • Display the disambiguation comment in the Match list, since similar releases are common, i.e. digital and CD releases.
  • Reduce MusicBrainz API usage. Right now, I gather pretty much all of the information for each match listed in the search results. Gathering the necessary metadata used in the search results requires a separate API call for each release to get details including total duration, authors, and narrators. MusicBrainz allows selectively requesting the information that should be included in the response. Not all of the collected metadata is displayed for the matches in the search results listing, like genres, tags, and publishers. Getting all of the tags and genres requires additional API calls for related works and series entities. Those extra API calls result in rate-limiting. Ideally I could provide only the minimum metadata necessary in the results list and upon selection of a match, retrieve the remaining metadata. I'm not sure how to go about that. Another method to avoid rate limiting would be to cache some of the API responses, particularly those for work and series entities which are often the same among similar releases.

What's Not Implemented in this PR

  • Chapters lookup in the chapters editor. The current chapters editor is made for ASIN's and not set up to allow other providers. It will need to be updated to allow using a MusicBrainz Release ID to obtain the chapters from a MusicBrainz Release's track list or annotation. Since chapters are not incorporated directly from the Match dialogue, returning chapters there isn't useful. I've already implemented functions to parse chapters from a MusicBrainz track list as part of this PR, but figured a follow up PR would be better suited to implementing support for multiple chapters providers.
  • Using AcoustID fingerprinting to lookup a MusicBrainz release. This is significantly more complex and is limited in its utility until the AcoustID server supports tracks with lengths greater than ~9 hours. This would also most likely provide a method for submitting missing AcoustID fingerprints to the AcoustID server.
  • Support for podcasts. I'm not familiar with how podcasts are handled on MusicBrainz, but I know that they are. I'm not planning on adding this myself, but it should be possible.

How have you tested this?

So far, I've tested its usage to retrieve metadata and cover art with Skyward.

Screenshots

*Originally created by @jwillikers on 10/14/2025* ## Brief summary Adds a [MusicBrainz](https://musicbrainz.org/) provider as a source for audiobook metadata and cover art. ## Which issue is fixed? Fixes #4125. ## In-depth Description This PR makes it possible to retrieve metadata and cover art for audiobooks from MusicBrainz releases. The metadata on MusicBrainz is contributed and maintained by its community. The MusicBrainz API is documented [here](https://musicbrainz.org/doc/MusicBrainz_API) and rate-limiting is documented [here](https://musicbrainz.org/doc/MusicBrainz_API/Rate_Limiting). For example data, the [Wind and Truth Release Group](https://musicbrainz.org/release-group/200278c4-e2bf-4a99-8758-8253b282e226) is probably a good place to start. This PR adds a proper MusicBrainz provider implementation with support in the Match and Cover Art dialogues. Cover Art is provided through the [Cover Art Archive](https://coverartarchive.org/), which is maintained by the Internet Archive. Right now, I've opted to use the `score` returned from the MusicBrainz search as the confidence rating, although it should be noted that the MusicBrainz score does not incorporate duration. Not sure if that's the best choice or not. The `genres`, `tags`, `abridged`, and `explicit` fields are all determined via MusicBrainz `tags`. Genres in MusicBrainz are kind of different than genres for audiobooks, and in MusicBrainz, genres are just a specific set of tags anyways. Any entity in MusicBrainz can have tags, and sometimes they make sense in certain places over others. For instance, tags related to audiobook genres often apply to the written work, so they make the most sense on the work and work series entities. However, `unabridged` and `abridged` tags make more sense at the release group level. I basically implemented genres as everything not beloging to a set of special purpose tags, and the presence or abscence of some of those special purpose tags is used to define the values for the `abridged` and `explicit` fields. For language, I directly use the the [ISO 639-3](https://en.wikipedia.org/wiki/ISO_639-3) three-letter language code used by MusicBrainz. Maybe I should convert this to the full name of the language to match what the Audible provider returns? ### Remaining Work I could use help with the following, assuming they should even be implemented. - [ ] Display the disambiguation comment in the Match list, since similar releases are common, i.e. digital and CD releases. - [ ] Reduce MusicBrainz API usage. Right now, I gather pretty much all of the information for each match listed in the search results. Gathering the necessary metadata used in the search results requires a separate API call for each release to get details including total duration, authors, and narrators. MusicBrainz allows selectively requesting the information that should be included in the response. Not all of the collected metadata is displayed for the matches in the search results listing, like genres, tags, and publishers. Getting all of the tags and genres requires additional API calls for related works and series entities. Those extra API calls result in rate-limiting. Ideally I could provide only the minimum metadata necessary in the results list and upon selection of a match, retrieve the remaining metadata. I'm not sure how to go about that. Another method to avoid rate limiting would be to cache some of the API responses, particularly those for work and series entities which are often the same among similar releases. ### What's Not Implemented in this PR - [ ] Chapters lookup in the chapters editor. The current chapters editor is made for ASIN's and not set up to allow other providers. It will need to be updated to allow using a MusicBrainz Release ID to obtain the chapters from a MusicBrainz Release's track list or annotation. Since chapters are not incorporated directly from the Match dialogue, returning chapters there isn't useful. I've already implemented functions to parse chapters from a MusicBrainz track list as part of this PR, but figured a follow up PR would be better suited to implementing support for multiple chapters providers. - [ ] Using AcoustID fingerprinting to lookup a MusicBrainz release. This is significantly more complex and is limited in its utility until the AcoustID server supports tracks with lengths greater than ~9 hours. This would also most likely provide a method for submitting missing AcoustID fingerprints to the AcoustID server. - [ ] Support for podcasts. I'm not familiar with how podcasts are handled on MusicBrainz, but I know that they are. I'm not planning on adding this myself, but it should be possible. ## How have you tested this? So far, I've tested its usage to retrieve metadata and cover art with [Skyward](https://musicbrainz.org/release-group/1e97eb8b-9d20-4cb2-be3f-d498a06f70c1). ## Screenshots <!-- If your PR includes any changes to the web client, please include screenshots or a short video from before and after your changes. -->
Sign in to join this conversation.
No labels
authentication
awaiting release
awaiting release
awaiting release
awaiting release
backlog
backlog
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
bug
chapter editor
chapter editor
chapter editor
chapter editor
chapter editor
ebooks
ebooks
ebooks
ebooks
ebooks
ebooks
ebooks
ebooks
ebooks
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
enhancement
possible plugin
progress sync
sorting/filtering/searching
sorting/filtering/searching
sorting/filtering/searching
sorting/filtering/searching
sorting/filtering/searching
sorting/filtering/searching
sorting/filtering/searching
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
unable to reproduce
upload
users & permissions
users & permissions
users & permissions
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
waiting
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github/audiobookshelf#1
No description provided.