Skip to content

Commit

Permalink
feat: force last.fm track source when remix
Browse files Browse the repository at this point in the history
When the title contains `remix` or `bootleg`, run lastgenre plugin with `source=track` instead of the genre source that the user configured which defaults to `album`.
  • Loading branch information
mgoltzsche committed Jan 28, 2024
1 parent d4af4eb commit 2534c9a
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 15 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ A [beets](https://github.com/beetbox/beets) plugin to assign genres to all items
## Features

* Gets genres from last.fm using the [lastgenre plugin](https://beets.readthedocs.io/en/stable/plugins/lastgenre.html).
* Favours track as last.fm genre source when track is a remix.
* Fallback to estimating the genre using the [xtractor plugin](https://github.com/adamjakab/BeetsPluginXtractor) / [Essentia](https://essentia.upf.edu/).
* Fixes the genre of (re)mixes by matching the genre tree against the track and album title.
* Allows to specify the genre per item manually.
Expand Down Expand Up @@ -45,7 +46,7 @@ autogenre:
lastgenre:
auto: false
prefer_specific: true
source: track
source: album
count: 4
min_weight: 15
canonical: /etc/beets/genre-tree.yaml
Expand Down
20 changes: 19 additions & 1 deletion beetsplug/autogenre/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def __init__(self):
self._xtractor = XtractorCommand(config['xtractor'])
self._lastgenre_conf = config['lastgenre'].get() or {}
self._separator = self._lastgenre_conf.get('separator') or ', '
self._remix_regex = re.compile(r'.+[^\w](remix|bootleg)', re.IGNORECASE)

def commands(self):
p = OptionParser()
Expand Down Expand Up @@ -173,8 +174,25 @@ def _run_autogenre_cmd(self, lib, opts, args):
item.store()
# TODO: match remix artist within title and get genre from artist: TITLE (ARTIST remix)

def _is_remix(self, title):
return self._remix_regex.match(title) is not None

def _lastfm_genre(self, item):
genre, src = self._lastgenre._get_genre(item)
genre = None
src = None
source = self._lastgenre.config['source'].get()
if self._is_remix(item.get('title')) and source != 'track':
# When item is remix, get genre frpm the last.fm track.
# (The artist's genre would be most likely wrong / the original.
# E.g. 'Fugees - Ready or not (Champion Bootleg)'.
# For other items the album/artist source is more reliable.)
self._lastgenre.config['source'] = 'track'
try:
genre, src = self._lastgenre._get_genre(item)
finally:
self._lastgenre.config['source'].set(source)
else:
genre, src = self._lastgenre._get_genre(item)
if genre:
msg = "[autogenre] Got last.fm genre '{}' based on {} for item: {}"
print(msg.format(genre, src, item))
Expand Down
2 changes: 1 addition & 1 deletion example_beets_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ lastgenre:
canonical: /etc/beets/genre-tree.yaml
prefer_specific: true
count: 4 # To also tag Rage Again the Machine as Hip Hop
source: track
source: album
min_weight: 15 # To prevent Amadou & Mariam from being tagged as New Wave
# This files picks some of the genres defined in the canonical tree.
# The genres listed in this files must be aligned with the playlist queries.
Expand Down
43 changes: 31 additions & 12 deletions tests/e2e/tests.bats
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,31 @@ assertGenre() {
assertGenre "$QUERY" 'lastfm | African | African'
}

@test 'force-overwrite genre' {
# Amadou & Mariam - Sénégal Fast Food
beet ytimport -q --quiet-fallback=asis https://www.youtube.com/watch?v=J43T8rEOg-I
QUERY='title:Sénégal Fast Food'
beet modify -y $QUERY genre=fake-genre
beet autogenre -f $QUERY
assertGenre "$QUERY" 'lastfm | African | African'
}

@test 'get genre from last.fm track when remix/bootleg' {
# Fugees - Ready Or Not (Champion Bootleg)
beet ytimport -q --quiet-fallback=asis https://www.youtube.com/watch?v=ts0WO6wJB3M
QUERY='fugees ready or not champion bootleg'
beet autogenre -f $QUERY
assertGenre "$QUERY" 'lastfm | Drum And Bass | Drum And Bass, Electronic'
}

@test 'get genre from last.fm artist' {
# Bellaire - Paris City Jazz
beet ytimport -q --quiet-fallback=asis https://www.youtube.com/watch?v=hyVVoLy4LSc
QUERY='title:Paris City Jazz'
beet autogenre $QUERY
assertGenre "$QUERY" 'lastfm | House | House, Downtempo, Jazz, Electronic'
}

@test 'derive genre from track title' {
# Rage Against the Machine - Wake Up (Rasticles drum n bass remix)
beet ytimport -q --quiet-fallback=asis https://www.youtube.com/watch?v=8tl7iOWZRa8
Expand All @@ -25,11 +50,12 @@ assertGenre() {
assertGenre "$QUERY" 'title | Drum And Bass | Drum And Bass, Rock, Hip Hop, Electronic'
}

@test 'force-overwrite genre' {
QUERY='title:wake up (Rasticles drum n bass remix)'
beet modify -y $QUERY genre=fake-genre
beet autogenre -f $QUERY
assertGenre "$QUERY" 'title | Drum And Bass | Drum And Bass, Rock, Hip Hop, Electronic'
@test 'derive genre from album title' {
# Reggae Jungle Drum and Bass Mix #9 New 2022
beet ytimport -q --quiet-fallback=asis https://www.youtube.com/watch?v=ZisHyhD0l_4
QUERY='album:Reggae Jungle Drum and Bass Mix #9 New 2022 Rudy, a message to you'
beet autogenre -fa $QUERY
assertGenre "$QUERY" 'title | Ragga Drum And Bass | Ragga Drum And Bass, Drum And Bass, Electronic'
}

@test 'estimate genre using essentia' {
Expand All @@ -40,13 +66,6 @@ assertGenre() {
assertGenre "$QUERY" 'essentia | Electronic | Electronic, Hip Hop, House'
}

@test 'derive genre from album name' {
# Reggae Jungle Drum and Bass Mix #9 New 2022
beet ytimport -q --quiet-fallback=asis https://www.youtube.com/watch?v=ZisHyhD0l_4
QUERY='album:Reggae Jungle Drum and Bass Mix #9 New 2022 Rudy, a message to you'
beet autogenre -fa $QUERY
assertGenre "$QUERY" 'title | Ragga Drum And Bass | Ragga Drum And Bass, Drum And Bass, Electronic'
}

@test 'specify genre manually' {
QUERY='album:Reggae Jungle Drum and Bass Mix #9 New 2022 Rudy, a message to you'
Expand Down

0 comments on commit 2534c9a

Please sign in to comment.