Skip to content

Instantly share code, notes, and snippets.

@aembleton
Created December 13, 2015 16:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aembleton/d0adc2e6ec96e67612b3 to your computer and use it in GitHub Desktop.
Save aembleton/d0adc2e6ec96e67612b3 to your computer and use it in GitHub Desktop.
Add tags to MP3s
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, sys
def main(f):
if not os.path.splitext(f)[1].lower() == '.mp3':
err('usage')
try:
import eyeD3
except ImportError:
err('import')
ID = eyeD3.Tag()
try:
ID.link(f)
except:
err('cant_link')
artist = ID.getArtist()
track = ID.getTitle()
if artist == '' or track == '':
err('tag_missing')
import base64, urllib
from xml.dom import minidom
tags = []
artist = urllib.quote_plus(artist.encode('utf-8'))
track = urllib.quote_plus(track.encode('utf-8'))
url = 'http://ws.audioscrobbler.com/2.0/?method=track.gettoptags'
api = base64.b64decode('MDMyY2RiMmVjZDAzYThiYTY2ZThkOGYyYTdjMzhlNGU=')
# print 'Processing file "%s"...' % f
try:
r = urllib.urlopen('%s&api_key=%s&artist=%s&track=%s' % (url, api, artist, track)).read()
xtag = minidom.parseString(r).getElementsByTagName('tag')
for tag in xtag:
tags.append(tag.getElementsByTagName('name')[0].childNodes[0].data.capitalize())
except Exception, e:
err(e)
if len(tags) > 0:
try:
comment = '; '.join(tags[:5])
trackName = f.rsplit('/',1)[-1]
trackName = trackName.rsplit('.',1)[0]
ID.addComment(comment)
ID.setGenre(genre(tags))
ID.update()
print '%s -> %s' % (trackName,comment)
except:
err('update_fail')
else:
err('no_tags')
def genre(tags):
genres={'blues': 0, 'polka': 75, 'classic rock': 1, 'retro': 76, 'country': 2, 'musical': 77, 'dance': 3, 'rock & roll': 78, 'disco': 4, 'hard rock': 79, 'funk': 5, 'folk': 80, 'grunge': 6, 'folk-rock': 81, 'hip-hop': 7, 'national folk': 82, 'jazz': 8, 'swing': 83, 'metal': 9, 'fast fusion': 84, 'new age': 10, 'bebob': 85, 'oldies': 11, 'latin': 86, 'other': 12, 'revival': 87, 'pop': 13, 'celtic': 88, 'r&b': 14, 'bluegrass': 89, 'rap': 15, 'avantgarde': 90, 'reggae': 16, 'gothic rock': 91, 'rock': 17, 'progressive rock': 92, 'techno': 18, 'psychedelic rock': 93, 'industrial': 19, 'symphonic rock': 94, 'alternative': 20, 'slow rock': 95, 'ska': 21, 'big band': 96, 'death metal': 22, 'chorus': 97, 'pranks': 23, 'easy listening': 98, 'soundtrack': 24, 'acoustic': 99, 'euro-techno': 25, 'humour': 100, 'ambient': 26, 'speech': 101, 'trip-hop': 27, 'chanson': 102, 'vocal': 28, 'opera': 103, 'jazz+funk': 29, 'chamber music': 104, 'fusion': 30, 'sonata': 105, 'trance': 31, 'symphony': 106, 'classical': 32, 'booty bass': 107, 'instrumental': 33, 'primus': 108, 'acid': 34, 'porn groove': 109, 'house': 35, 'satire': 110, 'game': 36, 'slow jam': 111, 'sound clip': 37, 'club': 112, 'gospel': 38, 'tango': 113, 'noise': 39, 'samba': 114, 'alternrock': 40, 'folklore': 115, 'bass': 41, 'ballad': 116, 'soul': 42, 'power ballad': 117, 'punk': 43, 'rhythmic soul': 118, 'space': 44, 'freestyle': 119, 'meditative': 45, 'duet': 120, 'instrumental pop': 46, 'punk rock': 121, 'instrumental rock': 47, 'drum solo': 122, 'ethnic': 48, 'a cappella': 123, 'gothic': 49, 'euro-house': 124, 'darkwave': 50, 'dance hall': 125, 'techno-industrial': 51, 'goa': 126, 'electronic': 52, 'drum & bass': 127, 'pop-folk': 53, 'club-house': 128, 'eurodance': 54, 'hardcore': 129, 'dream': 55, 'terror': 130, 'southern rock': 56, 'indie': 131, 'comedy': 57, 'britpop': 132, 'cult': 58, 'negerpunk': 133, 'gangsta rap': 59, 'polsk punk': 134, 'top 40': 60, 'beat': 135, 'christian rap': 61, 'christian gangsta rap': 136, 'pop / funk': 62, 'heavy metal': 137, 'jungle': 63, 'black metal': 138, 'native american': 64, 'crossover': 139, 'cabaret': 65, 'contemporary christian': 140, 'new wave': 66, 'christian rock': 141, 'psychedelic': 67, 'merengue': 142, 'rave': 68, 'salsa': 143, 'showtunes': 69, 'thrash metal': 144, 'trailer': 70, 'anime': 145, 'lo-fi': 71, 'jpop': 146, 'tribal': 72, 'synthpop': 147, 'acid punk': 73, 'rock/pop': 148, 'acid jazz ': 74}
for tag in tags:
try: return genres[tag.lower()]
except: pass
return genres['other']
def err(c):
if c == 'import':
print 'Please install eyeD3 python module to use this script'
print 'On Ubuntu terminal: sudo apt-get install python-eyed3'
elif c == 'cant_link':
print '[Error] Could not link to file'
elif c == 'tag_missing':
print '[Error] Artist or title tag missing'
elif c == 'update_fail':
print '[Error] Failed to update tag'
elif c == 'no_tags':
print '[Info] last.fm did not return tag data'
elif c == 'usage':
print '[Usage] python lastfm_top-tags.py <mp3-file>'
else:
print '[Exception] %s' % c
sys.exit()
if __name__ == '__main__':
try:
main(sys.argv[1])
except Exception, e:
err('usage')
# Recrusurvely applies lastfm_top-tags.py to all files
current_directory=$(pwd)
mp3_files=$(find "${current_directory}" -type f -iname "*.mp3")
IFS=$'\n'
for mp3_file in ${mp3_files}; do
#print $mp3_file
python /home/arthur/Downloads/lastfm_top-tags.py "$mp3_file" ;
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment