diff --git a/arts/Assassin's Creed OST.jpg b/arts/Assassin's Creed OST.jpg new file mode 100644 index 0000000..a19079a Binary files /dev/null and b/arts/Assassin's Creed OST.jpg differ diff --git a/arts/Bon Jovi.jpg b/arts/Bon Jovi.jpg new file mode 100644 index 0000000..ba3317d Binary files /dev/null and b/arts/Bon Jovi.jpg differ diff --git a/arts/Borderlands OST.jpg b/arts/Borderlands OST.jpg new file mode 100644 index 0000000..979a063 Binary files /dev/null and b/arts/Borderlands OST.jpg differ diff --git a/arts/Command and Conquer OST.jpg b/arts/Command and Conquer OST.jpg new file mode 100644 index 0000000..10cf15e Binary files /dev/null and b/arts/Command and Conquer OST.jpg differ diff --git a/arts/Counter Strike OST.jpg b/arts/Counter Strike OST.jpg new file mode 100644 index 0000000..5527fa4 Binary files /dev/null and b/arts/Counter Strike OST.jpg differ diff --git a/arts/Dota OST.jpg b/arts/Dota OST.jpg new file mode 100644 index 0000000..007b0dd Binary files /dev/null and b/arts/Dota OST.jpg differ diff --git a/arts/Dynasty Warriors OST.jpg b/arts/Dynasty Warriors OST.jpg new file mode 100644 index 0000000..2509b79 Binary files /dev/null and b/arts/Dynasty Warriors OST.jpg differ diff --git a/arts/Eminem.jpg b/arts/Eminem.jpg new file mode 100644 index 0000000..fa607bc Binary files /dev/null and b/arts/Eminem.jpg differ diff --git a/arts/Final Fantasy OST.jpg b/arts/Final Fantasy OST.jpg new file mode 100644 index 0000000..4342467 Binary files /dev/null and b/arts/Final Fantasy OST.jpg differ diff --git a/arts/Flying Steps.jpg b/arts/Flying Steps.jpg new file mode 100644 index 0000000..270b5ff Binary files /dev/null and b/arts/Flying Steps.jpg differ diff --git a/arts/Fort Minor.jpg b/arts/Fort Minor.jpg new file mode 100644 index 0000000..1580ffb Binary files /dev/null and b/arts/Fort Minor.jpg differ diff --git a/arts/Geoplex.jpg b/arts/Geoplex.jpg new file mode 100644 index 0000000..8338a30 Binary files /dev/null and b/arts/Geoplex.jpg differ diff --git a/arts/Granblue Fantasy OST.jpg b/arts/Granblue Fantasy OST.jpg new file mode 100644 index 0000000..f897c2a Binary files /dev/null and b/arts/Granblue Fantasy OST.jpg differ diff --git a/arts/Hexyz Force OST.jpg b/arts/Hexyz Force OST.jpg new file mode 100644 index 0000000..f81f53e Binary files /dev/null and b/arts/Hexyz Force OST.jpg differ diff --git a/arts/Immediate Music.jpg b/arts/Immediate Music.jpg new file mode 100644 index 0000000..3fadb29 Binary files /dev/null and b/arts/Immediate Music.jpg differ diff --git a/arts/Linkin Park.jpg b/arts/Linkin Park.jpg new file mode 100644 index 0000000..20402b8 Binary files /dev/null and b/arts/Linkin Park.jpg differ diff --git a/arts/Metal Slug OST.jpg b/arts/Metal Slug OST.jpg new file mode 100644 index 0000000..789083c Binary files /dev/null and b/arts/Metal Slug OST.jpg differ diff --git a/arts/Michael Jackson.jpg b/arts/Michael Jackson.jpg new file mode 100644 index 0000000..7432dd1 Binary files /dev/null and b/arts/Michael Jackson.jpg differ diff --git a/arts/Music Instructor.jpg b/arts/Music Instructor.jpg new file mode 100644 index 0000000..270b5ff Binary files /dev/null and b/arts/Music Instructor.jpg differ diff --git a/arts/Nightwish.jpg b/arts/Nightwish.jpg new file mode 100644 index 0000000..ab83b26 Binary files /dev/null and b/arts/Nightwish.jpg differ diff --git a/arts/Portal OST.jpg b/arts/Portal OST.jpg new file mode 100644 index 0000000..e346e1d Binary files /dev/null and b/arts/Portal OST.jpg differ diff --git a/arts/Radiant Historia OST.jpg b/arts/Radiant Historia OST.jpg new file mode 100644 index 0000000..a3d3d6f Binary files /dev/null and b/arts/Radiant Historia OST.jpg differ diff --git a/arts/Rammstein.jpg b/arts/Rammstein.jpg new file mode 100644 index 0000000..43b1a01 Binary files /dev/null and b/arts/Rammstein.jpg differ diff --git a/arts/Touhou OST.jpg b/arts/Touhou OST.jpg new file mode 100644 index 0000000..4a9c038 Binary files /dev/null and b/arts/Touhou OST.jpg differ diff --git a/arts/Two Steps From Hell.jpg b/arts/Two Steps From Hell.jpg new file mode 100644 index 0000000..5cc2dfb Binary files /dev/null and b/arts/Two Steps From Hell.jpg differ diff --git a/arts/Vae.jpg b/arts/Vae.jpg new file mode 100644 index 0000000..64c1c2c Binary files /dev/null and b/arts/Vae.jpg differ diff --git a/arts/Xenoblade Chronicles OST.jpg b/arts/Xenoblade Chronicles OST.jpg new file mode 100644 index 0000000..fe44dae Binary files /dev/null and b/arts/Xenoblade Chronicles OST.jpg differ diff --git a/arts/_.jpg b/arts/_.jpg new file mode 100644 index 0000000..731aad1 Binary files /dev/null and b/arts/_.jpg differ diff --git a/arts/_Battlefield.jpg b/arts/_Battlefield.jpg new file mode 100644 index 0000000..27f8812 Binary files /dev/null and b/arts/_Battlefield.jpg differ diff --git a/arts/_Digimon.jpg b/arts/_Digimon.jpg new file mode 100644 index 0000000..c59cc05 Binary files /dev/null and b/arts/_Digimon.jpg differ diff --git a/arts/_Dragonball Super.jpg b/arts/_Dragonball Super.jpg new file mode 100644 index 0000000..c34528e Binary files /dev/null and b/arts/_Dragonball Super.jpg differ diff --git a/arts/_Metal Gear Rising.jpg b/arts/_Metal Gear Rising.jpg new file mode 100644 index 0000000..230c3c8 Binary files /dev/null and b/arts/_Metal Gear Rising.jpg differ diff --git a/arts/_Monster Hunter 3G.jpg b/arts/_Monster Hunter 3G.jpg new file mode 100644 index 0000000..0abebf4 Binary files /dev/null and b/arts/_Monster Hunter 3G.jpg differ diff --git a/arts/_Monster Hunter 4G.jpg b/arts/_Monster Hunter 4G.jpg new file mode 100644 index 0000000..f8dc52c Binary files /dev/null and b/arts/_Monster Hunter 4G.jpg differ diff --git a/arts/_Monster Hunter Frontier.jpg b/arts/_Monster Hunter Frontier.jpg new file mode 100644 index 0000000..ddb336c Binary files /dev/null and b/arts/_Monster Hunter Frontier.jpg differ diff --git a/arts/_Monster Hunter Stories.jpg b/arts/_Monster Hunter Stories.jpg new file mode 100644 index 0000000..f1142f7 Binary files /dev/null and b/arts/_Monster Hunter Stories.jpg differ diff --git a/arts/_Monster Hunter World.jpg b/arts/_Monster Hunter World.jpg new file mode 100644 index 0000000..13599ce Binary files /dev/null and b/arts/_Monster Hunter World.jpg differ diff --git a/arts/_Monster Hunter XX.jpg b/arts/_Monster Hunter XX.jpg new file mode 100644 index 0000000..5abf0dc Binary files /dev/null and b/arts/_Monster Hunter XX.jpg differ diff --git a/arts/_Nier Automata.jpg b/arts/_Nier Automata.jpg new file mode 100644 index 0000000..da027c5 Binary files /dev/null and b/arts/_Nier Automata.jpg differ diff --git a/arts/_Pokemon BW2.jpg b/arts/_Pokemon BW2.jpg new file mode 100644 index 0000000..24ae306 Binary files /dev/null and b/arts/_Pokemon BW2.jpg differ diff --git a/arts/_Pokemon ORAS.jpg b/arts/_Pokemon ORAS.jpg new file mode 100644 index 0000000..ac8069c Binary files /dev/null and b/arts/_Pokemon ORAS.jpg differ diff --git a/arts/_Pokemon Origins.jpg b/arts/_Pokemon Origins.jpg new file mode 100644 index 0000000..3e19ce2 Binary files /dev/null and b/arts/_Pokemon Origins.jpg differ diff --git a/arts/_Pokemon RSE.jpg b/arts/_Pokemon RSE.jpg new file mode 100644 index 0000000..30a18e9 Binary files /dev/null and b/arts/_Pokemon RSE.jpg differ diff --git a/arts/_Pokemon SM.jpg b/arts/_Pokemon SM.jpg new file mode 100644 index 0000000..6b90ba2 Binary files /dev/null and b/arts/_Pokemon SM.jpg differ diff --git a/arts/_Pokemon SnS.jpg b/arts/_Pokemon SnS.jpg new file mode 100644 index 0000000..de487dc Binary files /dev/null and b/arts/_Pokemon SnS.jpg differ diff --git a/arts/_Pokemon Super Mystery Dungeon.jpg b/arts/_Pokemon Super Mystery Dungeon.jpg new file mode 100644 index 0000000..e361771 Binary files /dev/null and b/arts/_Pokemon Super Mystery Dungeon.jpg differ diff --git a/arts/_Pokemon USUM.jpg b/arts/_Pokemon USUM.jpg new file mode 100644 index 0000000..6b90ba2 Binary files /dev/null and b/arts/_Pokemon USUM.jpg differ diff --git a/arts/_Slam Dunk.jpg b/arts/_Slam Dunk.jpg new file mode 100644 index 0000000..0c8f9cd Binary files /dev/null and b/arts/_Slam Dunk.jpg differ diff --git a/arts/_Undertale.jpg b/arts/_Undertale.jpg new file mode 100644 index 0000000..1d556ad Binary files /dev/null and b/arts/_Undertale.jpg differ diff --git a/arts/__Catastrophe.jpg b/arts/__Catastrophe.jpg new file mode 100644 index 0000000..f69e465 Binary files /dev/null and b/arts/__Catastrophe.jpg differ diff --git a/arts/__Dragon Rises.jpg b/arts/__Dragon Rises.jpg new file mode 100644 index 0000000..f08641c Binary files /dev/null and b/arts/__Dragon Rises.jpg differ diff --git a/arts/__Gordon Montage.jpg b/arts/__Gordon Montage.jpg new file mode 100644 index 0000000..5901b8d Binary files /dev/null and b/arts/__Gordon Montage.jpg differ diff --git a/arts/__True Survivor.jpg b/arts/__True Survivor.jpg new file mode 100644 index 0000000..e4bb80b Binary files /dev/null and b/arts/__True Survivor.jpg differ diff --git a/arts/周杰伦.jpg b/arts/周杰伦.jpg new file mode 100644 index 0000000..46f5b0d Binary files /dev/null and b/arts/周杰伦.jpg differ diff --git a/arts/林俊杰.jpg b/arts/林俊杰.jpg new file mode 100644 index 0000000..7ad2b40 Binary files /dev/null and b/arts/林俊杰.jpg differ diff --git a/musick.py b/musick.py new file mode 100644 index 0000000..d9af105 --- /dev/null +++ b/musick.py @@ -0,0 +1,204 @@ +import os +from mutagen.easyid3 import EasyID3 +from mutagen.id3 import ID3, APIC +import getopt +import sys +import shutil + +total_proc = 0 +total_succ = 0 +total_error = 0 +total_cover = 0 + +input_dir = None +output_dir = None +cover_dir = None +cover_arts = [] + +UNKNOWN_ARTIST_NAME = "Unknown Artists" +UNKNOWN_ALBUM_NAME = "Unknown Album" + +WILDCARD_MATCH_SCORE = 1 +ARTIST_MATCH_SCORE = 10 +ALBUM_MATCH_SCORE = 100 +TITLE_MATCH_SCORE = 1000 + +# to get a > 0 score, each field either must match or the cover tuple is wildcare (None) +def calc_cover_score(artist: str, album: str, title: str, tup : tuple): + score = 0 + + if (tup[0] == artist): + score += ARTIST_MATCH_SCORE + elif (tup[0] == ""): + score += WILDCARD_MATCH_SCORE + else: + # mismatched artist, discard + return 0 + + if (tup[1] == album): + score += ALBUM_MATCH_SCORE + elif (tup[1] == ""): + score += WILDCARD_MATCH_SCORE + else: + # mismatched album, discard + return 0 + + if (tup[2] == title): + score += TITLE_MATCH_SCORE + elif (tup[2] == ""): + score += WILDCARD_MATCH_SCORE + else: + # mismatched title, discard + return 0 + + return score + +# returns the idx into cover_arts array. +# < 0 means no match +def find_best_cover(artist: str, album: str, title: str): + best_idx = -1 + best_score = 0 + for i in range(0, len(cover_arts)): + score = calc_cover_score(artist, album, title, cover_arts[i]) + if score > best_score: + best_idx = i + best_score = score + + return best_idx + + +def load_cover_arts(): + global cover_arts + + if cover_dir == None: + return + + cdir = cover_dir + files = os.listdir(cdir) + for f in files: + try: + triple = os.path.splitext(f)[0].split("_") + f = os.path.join(cover_dir, f) + print("Processing cover art - " + f) + artist = triple[0] + album = "" + title = "" + if len(triple) >= 2: + album = triple[1] + if len(triple) >= 3: + title = triple[2] + with open(f,'rb') as img: + cover_arts.append((artist, album, title, img.read(), os.path.basename(f))) + print(" Loading cover art - " + f + " Artist: " + artist + " Album: " + album + " Title: " + title) + except Exception as e: + print(" Skipping due to Exception - " + str(e)) + print("") + + +def usage(): + print("Usage: python musik.py [options]\n\n\ + options:\n\ + -h : show usage.\n\ + -i input : input directory\n\ + -o output : output directory\n\ + -c cover : cover arts page\n") + + +def process_file(f: str, odir: str): + global total_cover + global total_succ + global total_error + global total_proc + + try: + print("Processing file - " + f) + total_proc += 1 + id3 = ID3(f) + + album = str(id3.get("TALB") if id3.get("TALB") != None else "") + if album == "": + album = UNKNOWN_ALBUM_NAME + + artist = str(id3.get("TPE1") if id3.get("TPE1") != None else "") + if artist == "": + artist = UNKNOWN_ARTIST_NAME + + title = str(id3.get("TIT2") if id3.get("TIT2") != None else "") + if artist == "": + raise Exception("No title") + + print(" Artist: " + artist + " Album: " + album + " Title: " + title) + + target_dir = os.path.join(odir, artist, album) + os.makedirs(target_dir, exist_ok = True) + + target_f = os.path.join(target_dir, os.path.basename(f)) + shutil.copyfile(f, target_f) + print(" Copied file to - " + target_f) + + cover_idx = find_best_cover(artist, album, title) + + if cover_idx >= 0: + # install cover + id3 = ID3(target_f) + id3.delall("APIC") + id3.add(APIC(3, "image/jpeg", 3, "Front cover", cover_arts[cover_idx][3])) + id3.save(v2_version=3) + total_cover += 1 + print(" Written cover art - " + cover_arts[cover_idx][4]) + + total_succ += 1 + + except Exception as e: + total_error += 1 + print(" Skipping due to exception - %s" % str(e)) + + print("") + +def process_directory(idir: str, odir: str): + print("Processing directory - " + idir) + files = os.listdir(idir) + for f in files: + f = os.path.join(idir, f) + if os.path.isdir(f): + process_directory(f, odir) + else: + process_file(f, odir) + + +def main(): + global input_dir + global output_dir + global cover_dir + + try: + opts , _ = getopt.getopt(sys.argv[1:], "hi:o:c:") + except getopt.GetoptError as err: + print(str(err)) + usage() + sys.exit(1) + + for o, a in opts: + if o == "-h": + usage() + sys.exit(0) + elif o == "-i": + input_dir = a + elif o == "-o": + output_dir = a + elif o == "-c": + cover_dir = a + else: + print("Unrecognized option: " + o) + sys.exit(1) + + if input_dir == None or output_dir == None: + print("Must specify both -i and -o") + sys.exit(1) + + load_cover_arts() + process_directory(input_dir, output_dir) + + print("\nSummary - Total Files: " + str(total_proc) + " Total Errors: " + str(total_error) + " Total Covers: " + str(total_cover)) + +main()