103 lines
2.8 KiB
Python
Executable File
103 lines
2.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# Dependencies:
|
|
# - python3 command
|
|
# - python3-mutagen package
|
|
|
|
import getopt
|
|
import glob
|
|
import mutagen.id3
|
|
import mutagen.mp3
|
|
import os
|
|
import sys
|
|
import re
|
|
|
|
min_mp3s_for_album = 4
|
|
dry_run = False
|
|
|
|
def walk_tree(base_dir, visit_function):
|
|
visit_function(base_dir)
|
|
for ent in os.listdir(base_dir):
|
|
if ent.startswith("."):
|
|
next
|
|
path = "%s/%s" % (base_dir, ent)
|
|
if os.path.isdir(path):
|
|
walk_tree(path, visit_function)
|
|
|
|
def process_dir(path):
|
|
mp3s = glob.glob("%s/*.mp3" % path)
|
|
jpgs = glob.glob("%s/*.jpg" % path)
|
|
artwork_path = choose_artwork(mp3s, jpgs)
|
|
for mp3 in mp3s:
|
|
process_mp3(mp3, artwork_path)
|
|
|
|
def choose_artwork(mp3s, jpgs):
|
|
if len(mp3s) < min_mp3s_for_album:
|
|
return None
|
|
if len(jpgs) == 0:
|
|
sys.stderr.write("No .jpg files found\n")
|
|
return None
|
|
if len(jpgs) > 1:
|
|
sys.stderr.write("Multiple .jpg album artwork files found\n")
|
|
return None
|
|
return jpgs[0]
|
|
|
|
|
|
def read_file(fname):
|
|
f = open(fname, "rb")
|
|
data = f.read()
|
|
f.close()
|
|
return data
|
|
|
|
def clean_title(title):
|
|
new_title = re.sub(r'[\[\(]((explicit\s+)?album\s+version|explicit|clean)[\]\)]', '', title, flags = re.IGNORECASE)
|
|
new_title = re.sub(r'\s\s+', ' ', new_title)
|
|
return new_title.strip()
|
|
|
|
def clean_tag(mp3, tagname):
|
|
if tagname in mp3:
|
|
tag = mp3[tagname]
|
|
if tag is not None:
|
|
orig_text = tag.text[0]
|
|
new_text = clean_title(orig_text)
|
|
if new_text != orig_text:
|
|
sys.stdout.write("Changing %s from \"%s\" to \"%s\"\n" % (tagname, orig_text, new_text))
|
|
tag.text = [new_text]
|
|
return True
|
|
return False
|
|
|
|
def process_mp3(mp3_path, artwork_path):
|
|
mp3 = mutagen.mp3.MP3(mp3_path)
|
|
current_tags = mp3.tags
|
|
changed = False
|
|
changed = clean_tag(mp3, "TIT2") or changed
|
|
changed = clean_tag(mp3, "TALB") or changed
|
|
if artwork_path is not None:
|
|
apic_tags = [tag for tag in current_tags if tag == "APIC" or tag.startswith("APIC:")]
|
|
if len(apic_tags) < 1:
|
|
print("Adding APIC tag to %s..." % mp3_path)
|
|
jpg_data = read_file(artwork_path)
|
|
apic = mutagen.id3.APIC(0, "image/jpeg", 0, "", jpg_data)
|
|
mp3.tags.add(apic)
|
|
changed = True
|
|
if changed and not dry_run:
|
|
sys.stdout.write("Writing %s\n" % mp3_path)
|
|
mp3.save()
|
|
|
|
def main(argv):
|
|
base_dir = "."
|
|
opts, args = getopt.getopt(argv, 'd:n')
|
|
for opt, val in opts:
|
|
if opt == '-d':
|
|
base_dir = val
|
|
elif opt == '-n':
|
|
global dry_run
|
|
dry_run = True
|
|
if len(args) > 0:
|
|
sys.stderr.write("Usage: %s\n" % (sys.argv[0]))
|
|
return
|
|
walk_tree(base_dir, process_dir)
|
|
|
|
if __name__ == "__main__":
|
|
main(sys.argv[1:])
|