def lookup_track(album, metadata, release, track): tagger = album.tagger upload = tagger.config.setting["echonest_upload"] artist_title_lookup = tagger.config.setting["echonest_artist_title_lookup"] songs = [] try: songs = echosong.profile([u"musicbrainz:song:%s" % metadata['musicbrainz_trackid']], buckets="audio_summary") except EchoNestAPIError: if artist_title_lookup: songs = echosong.search(title=metadata['title'], artist=metadata['artist']) min_diff = tagger.config.setting["echonest_duration_diff"] match = None for song in songs: # try to match based on duration / length len_diff = abs(metadata.length / 1000.0 - song.audio_summary['duration']) if min_diff < 0.0 or len_diff < min_diff: min_diff = len_diff match = song if match: metadata['bpm'] = str(match.audio_summary['tempo']) metadata['comment:Songs-DB_Energy'] = str(match.audio_summary['energy']) metadata['comment:Songs-DB_Danceability'] = str(match.audio_summary['danceability']) elif upload: # FIXME: how do i get the filename for this track? pass req_minus(album)
def get_url_from_track_id(track_id): s = song.profile(track_ids=track_id) assert len(s) > 0, "ERROR: Track not found in The Echo Nest!" track = s[0].get_tracks("7digital-US") assert len(track) > 0, "ERROR: Track not found in 7digital!" url = track[0]["preview_url"] return url
def get_echonest_metadata(search_terms, spotify_uris): buckets = [ 'audio_summary', 'artist_discovery', 'artist_familiarity', 'artist_hotttnesss', 'artist_location', 'song_discovery', 'song_hotttnesss', ] try: s = song.search( artist=search_terms['a'], title=search_terms['t'], buckets=buckets, )[0] except IndexError: sys.stdout.write(" Falling back to uri lookup\n") try: s = song.profile( track_ids=spotify_uris, buckets=buckets )[0] except EchoNestAPIError: sys.stdout.write(" Failed to find echonest metadata\n") return [] return json.dumps(s.__dict__)
def get_url_from_track_id(track_id): s = song.profile(track_ids=track_id) assert len(s) > 0, "ERROR: Track not found in The Echo Nest!" track = s[0].get_tracks("7digital-US") assert len(track) >0, "ERROR: Track not found in 7digital!" url = track[0]["preview_url"] return url
def get_songs(self, song_ids): songs = [] # Echo Nest limits the number of IDs you can include in a single request. id_chunks = [song_ids[i*ECHO_NEST_ID_LIMIT:(i + 1) * ECHO_NEST_ID_LIMIT] for i in range(0, (len(self.song_ids) / ECHO_NEST_ID_LIMIT) + 1)] # Using a while loop because we want it to reevaluate the conditional # expression every time through the loop. i = 0 chunks_len = len(id_chunks) while i < chunks_len: try: songs += pyechonest_song.profile(id_chunks[i], buckets = ['audio_summary']) i += 1 except EchoNestAPIError: if isinstance(id_chunks[i], list) and len(id_chunks[i]) > 1: mid = len(id_chunks[i]) / 2 # Split the current ID chunk if it's not composed of 1 id. # Otherwise just skip it. id_chunks = ( id_chunks[:i] + [id_chunks[i][:mid]] + [id_chunks[i][mid:]] + id_chunks[i+1:] ) # Update the chunks count. chunks_len = len(id_chunks) else: i += 1 return songs
def get_song_characteristics(sID): #(sTitle, sArtist): sSong = song.profile(ids =sID) dsSummary = sSong[0].get_audio_summary() print(dsSummary) #print(sSong) #sSong = song.search(artist=sArtist, title=sTitle, results=1, buckets=['audio_summary']) #print(sID) #tTrack = track.track_from_id(identifier=sID) #tTrack.get_analysis() #print(str(tTrack)) #things I may be able to impact #"tempo": 74.694, #"loudness": -4.613, #energy": 0.6617689403520844, return dsSummary
def fetch_energy_feature(track,h5=None): #get energy of the track => uses pyechonest library close = (h5== None) if h5==None: path = "../../msd_dense_subset/mood/"+track[2]+"/"+track[3]+"/"+track[4]+"/"+track+".h5" h5 = GETTERS.open_h5_file_read(path) songid = GETTERS.get_song_id(h5) if close: h5.close() results = song.profile(songid) if len(results) == 0: return 0 track = results[0] energy = track.audio_summary['energy'] if (energy != None): return float(energy) else : return 0
def get_album_art_url(self): """Searches 7digital for the given song/track, and goes for the song if it can't match the track""" song_id = self.song_id songs = [] if song_id: print "\tSearching for album art for %s" % song_id songs = song.profile(song_id, buckets=['tracks', 'id:7digital'], limit=True) # if we couldn't get songs from 7digital with this songID go ahead and try a search. if not songs: print "\tSearching for album art for %s: %s" % (self.artist, self.title) songs = song.search(artist=self.artist, title=self.title, buckets=['tracks', 'id:7digital'], limit=True) for s in songs: tracks = s.get_tracks('7digital') for t in tracks: if 'release_image' in t: # TODO: should we check metadata match? return t['release_image'] # e.g. u'http://cdn.7static.com/static/img/sleeveart/00/005/658/0000565851_200.jpg'
def fetch_energy_feature(track, h5=None): #get energy of the track => uses pyechonest library close = (h5 == None) if h5 == None: path = "../../msd_dense_subset/mood/" + track[2] + "/" + track[ 3] + "/" + track[4] + "/" + track + ".h5" h5 = GETTERS.open_h5_file_read(path) songid = GETTERS.get_song_id(h5) if close: h5.close() results = song.profile(songid) if len(results) == 0: return 0 track = results[0] energy = track.audio_summary['energy'] if (energy != None): return float(energy) else: return 0
def create_song(): try: new_song = Song.query.filter_by(artist=request.form['artist'], title=request.form['title']).first() if not new_song: new_song = Song(request.form['artist'], request.form['title'], request.form['echonest_id'],request.form['album']) db.session.add(new_song) db.session.commit() ss_results = song.profile(ids=new_song.echonestID, buckets=['id:rdio-US','id:spotify-WW']) for ensong in ss_results: for rdioTrack in ensong.get_tracks('rdio-US'): trackID = rdioTrack["foreign_id"].split(":")[2] new_songprovider = SongProvider(new_song.id, "Rdio", trackID) db.session.add(new_songprovider) for spotifyTrack in ensong.get_tracks('spotify-WW'): trackID = spotifyTrack["foreign_id"].split(":")[2] new_songprovider = SongProvider(new_song.id, "Spotify", trackID) db.session.add(new_songprovider) db.session.commit() return API_Response(SUCCESS, [new_song.serialize]).as_json() except Exception as e: print e return API_Response("ERR", [], request.form).as_json() return None
import sys from pyechonest import song from pyechonest import config config.ECHO_NEST_API_KEY="2PSC0QWFJLYNM4XA6" song_ids = ['SOBSLVH12A8C131F38', 'SOXMSGY1338A5D5873', 'SOJPHZO1376210AFE5', 'SOBHNKR12AB0186218', 'SOSJAHD13770F4D40C'] rowlst = [] import time counter = 0 while counter < 9899: if counter %9 == 0: time.sleep(6) song_id = list(song_analysis_df['track_id'])[counter*10:counter*10+10] songlst = song.profile(song_ids, buckets=['audio_summary']) rows = map(lambda x: x.audio_summary.values(), songlst) rowlst.extend(rows) counter+=1 print counter
def collect_data(song_ids): """Input: a list of song IDs Output: a list of SongData objects fulled with useful information about the songs""" song_data = [] print song_ids for song_id in song_ids: this_song = song.profile(song_id) summary = this_song[0].audio_summary print summary url = summary['analysis_url'] musical_events = dict(sects='sections', brs='bars', bts='beats', ttms='tatums', sgmnts='segments') resp = requests.get(url=url, params=musical_events) data = json.loads(resp.content) # Separate the musical elements sections = data["sections"] bars = data["bars"] beats = data["beats"] tatums = data["tatums"] segments = data["segments"] """ Get relevant information from the sections, bars, beats, tatums, and segments""" sec_starts = [] sec_durations = [] for section in xrange(len(sections)): sec_starts.append(sections[section]["start"]) sec_durations.append(sections[section]["duration"]) bar_starts = [] bar_durations = [] for bar in xrange(len(bars)): bar_starts.append(bars[bar]["start"]) bar_durations.append(bars[bar]["duration"]) beat_starts = [] beat_durations = [] for beat in xrange(len(beats)): beat_starts.append(beats[beat]["start"]) beat_durations.append(beats[beat]["duration"]) tatum_starts = [] tatum_durations = [] for tatum in xrange(len(tatums)): tatum_starts.append(tatums[tatum]["start"]) tatum_durations.append(tatums[tatum]["duration"]) seg_starts = [] seg_durations = [] seg_pitches = [] for segment in xrange(len(segments)): seg_starts.append(segments[segment]["start"]) seg_durations.append(segments[segment]["duration"]) seg_pitches.append(segments[segment]["pitches"]) song_data.append( SongData.SongData(sec_starts, sec_durations, bar_starts, bar_durations, beat_starts, beat_durations, tatum_starts, tatum_durations, seg_starts, seg_durations, seg_pitches)) return song_data
def collect_data(song_ids): """Input: a list of song IDs Output: a list of SongData objects fulled with useful information about the songs""" song_data = [] print song_ids for song_id in song_ids: this_song = song.profile(song_id) summary = this_song[0].audio_summary print summary url = summary['analysis_url'] musical_events = dict( sects='sections', brs='bars', bts='beats', ttms='tatums', sgmnts='segments') resp = requests.get(url=url,params=musical_events) data = json.loads(resp.content) # Separate the musical elements sections = data["sections"] bars = data["bars"] beats = data["beats"] tatums = data["tatums"] segments = data["segments"] """ Get relevant information from the sections, bars, beats, tatums, and segments""" sec_starts = [] sec_durations = [] for section in xrange(len(sections)): sec_starts.append(sections[section]["start"]) sec_durations.append(sections[section]["duration"]) bar_starts = [] bar_durations = [] for bar in xrange(len(bars)): bar_starts.append(bars[bar]["start"]) bar_durations.append(bars[bar]["duration"]) beat_starts = [] beat_durations = [] for beat in xrange(len(beats)): beat_starts.append(beats[beat]["start"]) beat_durations.append(beats[beat]["duration"]) tatum_starts = [] tatum_durations = [] for tatum in xrange(len(tatums)): tatum_starts.append(tatums[tatum]["start"]) tatum_durations.append(tatums[tatum]["duration"]) seg_starts = [] seg_durations = [] seg_pitches = [] for segment in xrange(len(segments)): seg_starts.append(segments[segment]["start"]) seg_durations.append(segments[segment]["duration"]) seg_pitches.append(segments[segment]["pitches"]) song_data.append(SongData.SongData(sec_starts, sec_durations, bar_starts, bar_durations, beat_starts, beat_durations, tatum_starts, tatum_durations, seg_starts, seg_durations, seg_pitches)) return song_data
def do_everything(artist_name="Anamanaguchi", song_name="Endless Fantasy", song_max=8, diversity=0): start_time = time.time() similar_artist_num = get_artist_num(song_max) if diversity: similar_artist_num /= 2 song_max -= 2 # connect to last.fm network = pylast.LastFMNetwork(api_key = config.LAST_FM_API_KEY, api_secret = config.LAST_FM_API_SECRET, username= config.LAST_FM_USERNAME, password_hash = config.LAST_FM_PASSWORD_HASH) artistgrab = network.get_artist(artist_name) # get artist name from last.fm similar = artistgrab.get_similar()[0:similar_artist_num] # get similar artists similar_artists = [] # get a specified number of similar artists [similar_artists.append(similar[i][0].get_name()) for i in range(len(similar)) if not '&' in similar[i][0].get_name()] similar_artist_num = len(similar_artists) if diversity: # get more kinda similar artists to mix in k_artistgrab = network.get_artist(similar_artists[0]) # doubt we need this line k_similar = k_artistgrab.get_similar() last = len(k_similar) k_similar_artists = [] index = 0 while len(k_similar_artists) < len(similar_artists): if index < last: if not k_similar[index][0].get_name() in similar_artists and k_similar[index][0].get_name() != artist_name: k_similar_artists.append(k_similar[index][0].get_name()) index += 1 else: break k_similar_artist_num = len(k_similar_artists) # audio summary bucket gets detailed track info, spotify-ww gets some spotify info # and tracks gets track-specific spotify info buckets = ['audio_summary', 'id:spotify-WW', 'tracks'] # setup buckets for requests # get user entered song from echonest the_song = song.search(title=song_name, artist=artist_name, buckets=buckets)[0] the_song_info = the_song.audio_summary sim_songs = [] # similar songs k_sim_songs = [] # kinda similar songs a_queue = Queue.Queue() a_list = [] # add similar artists to queue for a in similar_artists: a_queue.put(a) # get echonest artists + songs for i in range(similar_artist_num): t = echoArtistThread(a_queue, a_list, song_max) t.setDaemon(True) t.start() a_queue.join() # wait for all threads to finish # add found soungs to list [sim_songs.extend(a['songs'][0:6]) for a in a_list if a['songs']] if diversity: # make a second queue and look up second set of artists # TODO: make this part of first queue by setting artist types k_queue = Queue.Queue() k_list = [] for a in k_similar_artists: k_queue.put(a) for i in range(k_similar_artist_num): t = echoArtistThread(k_queue, k_list, song_max) t.setDaemon(True) t.start() k_queue.join() # if we found songs add them to our song list [k_sim_songs.extend(a['songs'][0:6]) for a in k_list if a] the_artist = artist.Artist(artist_name) # get user's artist artist_songs = the_artist.get_songs()[:10] # get artist songs artist_songs_ids = [s.id for s in artist_songs] # get ids for artist songs artist_songs = song.profile(artist_songs_ids, buckets=buckets) # get spotify IDs and info # sort songs by energy similarity the_songs = sorted(artist_songs, key=lambda k: abs(the_song_info[u'energy']-k.audio_summary[u'energy'])) # TODO(natdempk): have zack explain what this does to me seen = set() seen_add = seen.add the_songs = [ x for x in the_songs if x not in seen and not seen_add(x)] n = 1 tflag = True # filter to only songs that have spotify IDs the_songs = [s for s in the_songs if 'tracks' in s.cache] #first_song_id = the_songs[0].cache['tracks'][0]['foreign_id'] # set first #last_song_id = the_songs[1].cache['tracks'][0]['foreign_id'] # and last songs while tflag == True: tflag = False try: first_song_id = the_songs[n].cache['tracks'][0]['foreign_id'] except: tflag = True n += 1 try: last_song_id = the_song.cache['tracks'][0]['foreign_id'] except: n += 1 tflag = True while tflag == True: tflag = False try: last_song_id = the_songs[n].cache['tracks'][0]['foreign_id'] except: tflag = True n += 1 seen = set() seen_add = seen.add sim_songs = [ x for x in sim_songs if x not in seen and not seen_add(x)] sim_songs_info = [] i = 0 while i < len(sim_songs): sim_songs_info += song.profile(map(lambda k: sim_songs[k].id, range(i, min(i+9, len(sim_songs)-1))), buckets=buckets) i += 9 # filter to songs with similar energy sim_songs_info = filter(lambda k: k.audio_summary[u'energy'] < the_song_info[u'energy']+.3 and k.audio_summary[u'energy'] > the_song_info[u'energy']-.3, sim_songs_info) # sort songs by tempo sim_songs_info = sorted(sim_songs_info, key=lambda k: k.audio_summary[u'tempo']) # divide into slower and faster songs slow_songs = sorted(sim_songs_info[:len(sim_songs)/2], key=lambda k: k.audio_summary[u'duration']) fast_songs = sorted(sim_songs_info[len(sim_songs)/2:], key=lambda k: k.audio_summary[u'duration']) # do the same for diversity songs if diversity: k_seen = set() k_seen_add = k_seen.add k_sim_songs = [x for x in k_sim_songs if x not in seen and not k_seen_add(x)] k_sim_songs_info = [] i = 0 while i < len(k_sim_songs): k_sim_songs_info += song.profile(map(lambda k: k_sim_songs[k].id, range(i, min(i+9, len(k_sim_songs)-1))), buckets=buckets) i += 9 # filter to songs with similar energy k_sim_songs_info = filter(lambda k: k.audio_summary[u'energy'] < the_song_info[u'energy']+.3 and k.audio_summary[u'energy'] > the_song_info[u'energy']-.3, k_sim_songs_info) # sort songs by tempo k_sim_songs_info = sorted(k_sim_songs_info, key=lambda k: k.audio_summary[u'tempo']) # divide into slower and faster songs k_slow_songs = sorted(k_sim_songs_info[:len(k_sim_songs_info)/2], key=lambda k: k.audio_summary[u'duration']) k_fast_songs = sorted(k_sim_songs_info[len(k_sim_songs_info)/2:], key=lambda k: k.audio_summary[u'duration']) total_info = [] counter = 0 if diversity: # select songs from 4 lists lists = [fast_songs, slow_songs, k_fast_songs, k_slow_songs] for i in range(song_max): cur_list = lists[i%4] flag = True while flag == True: flag = False info = cur_list[random.randint(0, len(cur_list)-1)] for j in range(len(total_info)): try: if info.artist_name == total_info[j].artist_name: counter += 1 if counter < 100: flag = True except: counter += 1 if counter < 100: flag = True total_info.append(info) else: # select songs from just two lists # TODO make a conditional that sets lists and merge these two pieces of code for i in range(song_max/2): flag = True while flag == True: flag = False info = fast_songs[random.randint(0, len(fast_songs)-1)] for j in range(len(total_info)): if info.artist_name == total_info[j].artist_name: counter += 1 if counter < 100: flag = True total_info.append(info) flag = True while flag == True: flag = False info = slow_songs[random.randint(0, len(slow_songs)-1)] for j in range(len(total_info)): if info.artist_name == total_info[j].artist_name: counter += 1 if counter < 100: flag = True total_info.append(info) total_res = [] total_res.append(first_song_id) final_ids = [t.id for t in total_info] print total_info for t in total_info: try: if 'tracks' in s.cache: total_res.append(t.cache['tracks'][0]['foreign_id']) except: pass total_res.append(last_song_id) seen = set() seen_add = seen.add total_res = [ x for x in total_res if x not in seen and not seen_add(x)] return total_res
import sys from pyechonest import song from pyechonest import config config.ECHO_NEST_API_KEY = "2PSC0QWFJLYNM4XA6" song_ids = [ 'SOBSLVH12A8C131F38', 'SOXMSGY1338A5D5873', 'SOJPHZO1376210AFE5', 'SOBHNKR12AB0186218', 'SOSJAHD13770F4D40C' ] rowlst = [] import time counter = 0 while counter < 9899: if counter % 9 == 0: time.sleep(6) song_id = list(song_analysis_df['track_id'])[counter * 10:counter * 10 + 10] songlst = song.profile(song_ids, buckets=['audio_summary']) rows = map(lambda x: x.audio_summary.values(), songlst) rowlst.extend(rows) counter += 1 print counter