Skip to content

Commit

Permalink
Merge pull request #3474 from x1ppy/master
Browse files Browse the repository at this point in the history
Support extra tags for MusicBrainz queries
  • Loading branch information
sampsyo authored Mar 21, 2020
2 parents b34d1f7 + 19d6dfc commit 8ed76f1
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 12 deletions.
16 changes: 11 additions & 5 deletions beets/autotag/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -614,31 +614,37 @@ def tracks_for_id(track_id):


@plugins.notify_info_yielded(u'albuminfo_received')
def album_candidates(items, artist, album, va_likely):
def album_candidates(items, artist, album, va_likely, extra_tags):
"""Search for album matches. ``items`` is a list of Item objects
that make up the album. ``artist`` and ``album`` are the respective
names (strings), which may be derived from the item list or may be
entered by the user. ``va_likely`` is a boolean indicating whether
the album is likely to be a "various artists" release.
the album is likely to be a "various artists" release. ``extra_tags``
is an optional dictionary of additional tags used to further
constrain the search.
"""

# Base candidates if we have album and artist to match.
if artist and album:
try:
for candidate in mb.match_album(artist, album, len(items)):
for candidate in mb.match_album(artist, album, len(items),
extra_tags):
yield candidate
except mb.MusicBrainzAPIError as exc:
exc.log(log)

# Also add VA matches from MusicBrainz where appropriate.
if va_likely and album:
try:
for candidate in mb.match_album(None, album, len(items)):
for candidate in mb.match_album(None, album, len(items),
extra_tags):
yield candidate
except mb.MusicBrainzAPIError as exc:
exc.log(log)

# Candidates from plugins.
for candidate in plugins.candidates(items, artist, album, va_likely):
for candidate in plugins.candidates(items, artist, album, va_likely,
extra_tags):
yield candidate


Expand Down
9 changes: 8 additions & 1 deletion beets/autotag/match.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,12 @@ def tag_album(items, search_artist=None, search_album=None,
search_artist, search_album = cur_artist, cur_album
log.debug(u'Search terms: {0} - {1}', search_artist, search_album)

extra_tags = None
if config['musicbrainz']['extra_tags']:
tag_list = config['musicbrainz']['extra_tags'].get()
extra_tags = {k: v for (k, v) in likelies.items() if k in tag_list}
log.debug(u'Additional search terms: {0}', extra_tags)

# Is this album likely to be a "various artist" release?
va_likely = ((not consensus['artist']) or
(search_artist.lower() in VA_ARTISTS) or
Expand All @@ -457,7 +463,8 @@ def tag_album(items, search_artist=None, search_album=None,
for matched_candidate in hooks.album_candidates(items,
search_artist,
search_album,
va_likely):
va_likely,
extra_tags):
_add_candidate(items, candidates, matched_candidate)

log.debug(u'Evaluating {0} candidates.', len(candidates))
Expand Down
22 changes: 20 additions & 2 deletions beets/autotag/mb.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@

SKIPPED_TRACKS = ['[data track]']

FIELDS_TO_MB_KEYS = {
'catalognum': 'catno',
'country': 'country',
'label': 'label',
'media': 'format',
'year': 'date',
}

musicbrainzngs.set_useragent('beets', beets.__version__,
'https://beets.io/')

Expand Down Expand Up @@ -411,13 +419,13 @@ def album_info(release):
return info


def match_album(artist, album, tracks=None):
def match_album(artist, album, tracks=None, extra_tags=None):
"""Searches for a single album ("release" in MusicBrainz parlance)
and returns an iterator over AlbumInfo objects. May raise a
MusicBrainzAPIError.
The query consists of an artist name, an album name, and,
optionally, a number of tracks on the album.
optionally, a number of tracks on the album and any other extra tags.
"""
# Build search criteria.
criteria = {'release': album.lower().strip()}
Expand All @@ -429,6 +437,16 @@ def match_album(artist, album, tracks=None):
if tracks is not None:
criteria['tracks'] = six.text_type(tracks)

# Additional search cues from existing metadata.
if extra_tags:
for tag in extra_tags:
key = FIELDS_TO_MB_KEYS[tag]
value = six.text_type(extra_tags.get(tag, '')).lower().strip()
if key == 'catno':
value = value.replace(u' ', '')
if value:
criteria[key] = value

# Abort if we have no search terms.
if not any(criteria.values()):
return
Expand Down
1 change: 1 addition & 0 deletions beets/config_default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ musicbrainz:
ratelimit: 1
ratelimit_interval: 1.0
searchlimit: 5
extra_tags: []

match:
strong_rec_thresh: 0.04
Expand Down
7 changes: 4 additions & 3 deletions beets/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def album_distance(self, items, album_info, mapping):
"""
return beets.autotag.hooks.Distance()

def candidates(self, items, artist, album, va_likely):
def candidates(self, items, artist, album, va_likely, extra_tags=None):
"""Should return a sequence of AlbumInfo objects that match the
album whose items are provided.
"""
Expand Down Expand Up @@ -379,11 +379,12 @@ def album_distance(items, album_info, mapping):
return dist


def candidates(items, artist, album, va_likely):
def candidates(items, artist, album, va_likely, extra_tags=None):
"""Gets MusicBrainz candidates for an album from each plugin.
"""
for plugin in find_plugins():
for candidate in plugin.candidates(items, artist, album, va_likely):
for candidate in plugin.candidates(items, artist, album, va_likely,
extra_tags):
yield candidate


Expand Down
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Changelog

New features:

* A new :ref:`extra_tags` configuration option allows more tagged metadata
to be included in MusicBrainz queries.
* A new :doc:`/plugins/fish` adds `Fish shell`_ tab autocompletion to beets
* :doc:`plugins/fetchart` and :doc:`plugins/embedart`: Added a new ``quality``
option that controls the quality of the image output when the image is
Expand Down
20 changes: 20 additions & 0 deletions docs/reference/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,26 @@ MusicBrainz server.

Default: ``5``.

.. _extra_tags:

extra_tags
~~~~~~~~~~

By default, beets will use only the artist, album, and track count to query
MusicBrainz. Additional tags to be queried can be supplied with the
``extra_tags`` setting. For example::

musicbrainz:
extra_tags: [year, catalognum, country, media, label]

This setting should improve the autotagger results if the metadata with the
given tags match the metadata returned by MusicBrainz.

Note that the only tags supported by this setting are the ones listed in the
above example.

Default: ``[]``

.. _match-config:

Autotagger Matching Options
Expand Down
2 changes: 1 addition & 1 deletion test/test_importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def restore(self):
autotag.mb.album_for_id = self.mb_album_for_id
autotag.mb.track_for_id = self.mb_track_for_id

def match_album(self, albumartist, album, tracks):
def match_album(self, albumartist, album, tracks, extra_tags):
if self.matching == self.IDENT:
yield self._make_album_match(albumartist, album, tracks)

Expand Down

0 comments on commit 8ed76f1

Please sign in to comment.