From fd0d8820bbcef8e2410af50ef46367c7a5ee405b Mon Sep 17 00:00:00 2001 From: Peter Schnebel Date: Wed, 16 Oct 2013 12:19:25 +0200 Subject: [PATCH 1/2] Fixed detection of the correct song in EchoNest. --- beetsplug/echonest_tempo.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/beetsplug/echonest_tempo.py b/beetsplug/echonest_tempo.py index b2178485c..920ad89a1 100644 --- a/beetsplug/echonest_tempo.py +++ b/beetsplug/echonest_tempo.py @@ -63,8 +63,8 @@ def get_tempo(artist, title): """Get the tempo for a song.""" # We must have sufficient metadata for the lookup. Otherwise the API # will just complain. - artist = artist.replace(u'\n', u' ').strip() - title = title.replace(u'\n', u' ').strip() + artist = artist.replace(u'\n', u' ').strip().lower() + title = title.replace(u'\n', u' ').strip().lower() if not artist or not title: return None @@ -74,7 +74,7 @@ def get_tempo(artist, title): # EchoNest supports foreign ids from MusicBrainz, but currently # only for artists, not individual tracks/recordings. results = pyechonest.song.search( - artist=artist, title=title, results=1, + artist=artist, title=title, results=100, buckets=['audio_summary'] ) except pyechonest.util.EchoNestAPIError as e: @@ -100,8 +100,8 @@ def get_tempo(artist, title): # artist and title. The API also doesn't have MusicBrainz track IDs; # otherwise we could use those for a more robust match. for result in results: - if result.artist_name == artist and result.title == title: - return results[0].audio_summary['tempo'] + if result.artist_name.lower() == artist and result.title.lower() == title: + return result.audio_summary['tempo'] class EchoNestTempoPlugin(BeetsPlugin): From 66c01adca199b7945087afc17b40b106c82e69ba Mon Sep 17 00:00:00 2001 From: Peter Schnebel Date: Wed, 16 Oct 2013 12:40:27 +0200 Subject: [PATCH 2/2] use duration as another hint to find good matches --- beetsplug/echonest_tempo.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/beetsplug/echonest_tempo.py b/beetsplug/echonest_tempo.py index 920ad89a1..2810b30ba 100644 --- a/beetsplug/echonest_tempo.py +++ b/beetsplug/echonest_tempo.py @@ -45,7 +45,7 @@ def fetch_item_tempo(lib, loglevel, item, write): return # Fetch tempo. - tempo = get_tempo(item.artist, item.title) + tempo = get_tempo(item.artist, item.title, item.length) if not tempo: log.log(loglevel, u'tempo not found: %s - %s' % (item.artist, item.title)) @@ -59,7 +59,7 @@ def fetch_item_tempo(lib, loglevel, item, write): item.store() -def get_tempo(artist, title): +def get_tempo(artist, title, duration): """Get the tempo for a song.""" # We must have sufficient metadata for the lookup. Otherwise the API # will just complain. @@ -99,9 +99,19 @@ def get_tempo(artist, title): # So we look through the results for songs that have the right # artist and title. The API also doesn't have MusicBrainz track IDs; # otherwise we could use those for a more robust match. + min_distance = duration + pick = None for result in results: if result.artist_name.lower() == artist and result.title.lower() == title: - return result.audio_summary['tempo'] + distance = abs(duration - result.audio_summary['duration']) + log.debug(u'echonest_tempo: candidate {} - {} [abs({:2.2f}-{:2.2f})={:2.2f}] = {}'.format( + result.artist_name, result.title, + result.audio_summary['duration'], duration, distance, + result.audio_summary['tempo'])) + if distance < min_distance: + min_distance = distance + pick = result.audio_summary['tempo'] + return pick class EchoNestTempoPlugin(BeetsPlugin):