unstable
This commit is contained in:
parent
08098695cc
commit
fdeb1c4289
140
mobject.py
Normal file
140
mobject.py
Normal file
@ -0,0 +1,140 @@
|
||||
from mutagen.id3 import ID3, APIC, TIT2, TPE1, TALB, Encoding, PictureType
|
||||
from mutagen.flac import FLAC, Picture
|
||||
from pathlib import Path
|
||||
import io
|
||||
|
||||
class MObject:
|
||||
_file_bytes : bytes
|
||||
_file_io : io.BytesIO
|
||||
|
||||
def __init__(self, fb : bytes):
|
||||
self._file_bytes = fb
|
||||
self._file_io = io.BytesIO(fb)
|
||||
return
|
||||
|
||||
def get_bytes(self) -> bytes:
|
||||
return self._file_io.getbuffer()
|
||||
|
||||
def get_title(self) -> str:
|
||||
raise Exception("unimplemented")
|
||||
|
||||
def get_album(self) -> str:
|
||||
raise Exception("unimplemented")
|
||||
|
||||
def get_artist(self) -> str:
|
||||
raise Exception("unimplemented")
|
||||
|
||||
def get_cover(self) -> bytes:
|
||||
raise Exception("unimplemented")
|
||||
|
||||
def set_artist(self, val : str) -> None:
|
||||
raise Exception("unimplemented")
|
||||
|
||||
def set_album(self, val : str) -> None:
|
||||
raise Exception("unimplemented")
|
||||
|
||||
def set_title(self, val : str) -> None:
|
||||
raise Exception("unimplemented")
|
||||
|
||||
def set_cover(self, val : bytes, png : bool = False) -> None:
|
||||
raise Exception("unimplemented")
|
||||
|
||||
class MMP3Object(MObject):
|
||||
_id3 : ID3
|
||||
def __init__(self, file : bytes):
|
||||
super().__init__(self, file)
|
||||
|
||||
self._id3 = ID3()
|
||||
self._id3.load(self._file_io, translate = True)
|
||||
return
|
||||
|
||||
def get_title(self) -> str:
|
||||
return self._id3.get("TIT2", default = TIT2(text = None)).text
|
||||
|
||||
def set_title(self, val : str) -> None:
|
||||
self._id3.delall("TIT2")
|
||||
self._id3.add(TIT2(text = val))
|
||||
self._id3.save()
|
||||
|
||||
def get_album(self) -> str:
|
||||
return self._id3.get("TALB", default = TALB(text = None)).text
|
||||
|
||||
def set_album(self, val : str) -> None:
|
||||
self._id3.delall("TALB")
|
||||
self._id3.add(TALB(text = val))
|
||||
self._id3.save()
|
||||
|
||||
def get_artist(self) -> str:
|
||||
return self._id3.get("TPE1", default = TPE1(text = None)).text
|
||||
|
||||
def set_artist(self, val : str):
|
||||
self._id3.delall("TPE1")
|
||||
self._id3.add(TPE1(text = val))
|
||||
self._id3.save()
|
||||
|
||||
def get_cover(self) -> bytes:
|
||||
cover = self._id3.get("APIC", default=APIC(encoding = Encoding.UTF8, mime = "image/jpeg", type=PictureType.COVER_FRONT, desc=u"Cover", data = None))
|
||||
return cover.data
|
||||
|
||||
def set_cover(self, val : bytes, png : bool = False) -> None:
|
||||
self._id3.delall("APIC")
|
||||
self._id3.add(APIC(encoding = Encoding.UTF8, mime = "image/png" if png else "image/jpeg", type=PictureType.COVER_FRONT, desc=u"Cover", data = val))
|
||||
self._id3.save()
|
||||
|
||||
|
||||
class MFLACObject(MObject):
|
||||
_flac : FLAC
|
||||
def __init__(self, file : bytes):
|
||||
super().__init__(self, file)
|
||||
|
||||
self._flac = FLAC(self._file_io)
|
||||
return
|
||||
|
||||
def get_title(self) -> str:
|
||||
return self._flac.get("TITLE", default = None)
|
||||
|
||||
def set_title(self, val : str) -> None:
|
||||
self._flac["TITLE"] = val
|
||||
self._flac.save()
|
||||
|
||||
def get_album(self) -> str:
|
||||
return self._flac.get("ALBUM", default = None)
|
||||
|
||||
def set_album(self, val : str) -> None:
|
||||
self._flac["ALBUM"] = val
|
||||
self._flac.save()
|
||||
|
||||
def get_artist(self) -> str:
|
||||
return self._flac.get("ARTIST", default = None)
|
||||
|
||||
def set_artist(self, val : str):
|
||||
self._flac["ARTIST"] = val
|
||||
self._flac.save()
|
||||
|
||||
def get_cover(self) -> bytes:
|
||||
pics = self._flac.pictures
|
||||
if len(pics) > 0:
|
||||
return pics[0].data
|
||||
else:
|
||||
return None
|
||||
|
||||
def set_cover(self, val : bytes, png : bool = False) -> None:
|
||||
self._flac.clear_pictures()
|
||||
pic = Picture()
|
||||
pic.type = PictureType.COVER_FRONT
|
||||
pic.mime = "image/png" if png else "image/jpeg"
|
||||
pic.desc = "Cover"
|
||||
pic.data = val
|
||||
self._flac.add_picture(pic)
|
||||
self._flac.save()
|
||||
|
||||
|
||||
def create_mobject(filepath : str) -> MObject:
|
||||
fp = Path(filepath)
|
||||
with open(fp, "rb") as f:
|
||||
buf = f.read()
|
||||
if (fp.suffix == "mp3"):
|
||||
return MMP3Object(buf)
|
||||
if (fp.suffix == "flac"):
|
||||
return MFLACObject(buf)
|
||||
return None
|
71
musick.py
71
musick.py
@ -1,15 +1,14 @@
|
||||
import os
|
||||
import mutagen
|
||||
from mutagen.easyid3 import EasyID3
|
||||
from mutagen.id3 import ID3, APIC, TIT2, TPE1, TALB
|
||||
import getopt
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
import mobject
|
||||
|
||||
total_proc = 0
|
||||
total_succ = 0
|
||||
total_error = 0
|
||||
total_cover = 0
|
||||
total_missing_cover = 0
|
||||
|
||||
input_dir = None
|
||||
output_dir = None
|
||||
@ -108,10 +107,8 @@ def usage():
|
||||
-o output : output directory\n\
|
||||
-c cover : cover arts page\n")
|
||||
|
||||
no_match = []
|
||||
|
||||
def process_file(f: str, odir: str):
|
||||
global total_cover
|
||||
global total_missing_cover
|
||||
global total_succ
|
||||
global total_error
|
||||
global total_proc
|
||||
@ -120,51 +117,41 @@ def process_file(f: str, odir: str):
|
||||
total_proc += 1
|
||||
|
||||
artist, album, title = parse_triple(f)
|
||||
|
||||
# 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 title == "":
|
||||
raise Exception("No title")
|
||||
|
||||
print(" Identified artist: " + artist + " album: " + album + " title: " + title)
|
||||
mobj = mobject.create_mobject(f)
|
||||
|
||||
print(f" Artist: \"{mobj.get_artist()}\" -> \"{artist}\"\n" +
|
||||
f" Album: \"{mobj.get_album()}\" -> \"{album}\"\n" +
|
||||
f" Title: \"{mobj.get_title()}\" -> \"{title}\"")
|
||||
|
||||
mobj.set_artist(artist)
|
||||
mobj.set_album(album)
|
||||
mobj.set_title(title)
|
||||
|
||||
if (mobj.get_cover() == None):
|
||||
cover_idx = find_best_cover(artist, album, title)
|
||||
if (cover_idx >= 0):
|
||||
mobj.set_cover(cover_arts[cover_idx][3])
|
||||
print(" Cover: <None> -> <New>")
|
||||
else:
|
||||
total_missing_cover += 1
|
||||
print(" Cover: <None> -> <None>")
|
||||
else:
|
||||
print(" Cover: <Exists>")
|
||||
|
||||
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))
|
||||
try:
|
||||
shutil.copyfile(f, target_f)
|
||||
except shutil.SameFileError:
|
||||
pass
|
||||
print(" Copied file to: " + target_f)
|
||||
|
||||
cover_idx = find_best_cover(artist, album, title)
|
||||
|
||||
audio = mutagen.File(f)
|
||||
print(f" File info: {audio.info.pprint()}")
|
||||
audio["title"] = title
|
||||
audio["artist"] = artist
|
||||
audio["album"] = album
|
||||
audio.save()
|
||||
|
||||
# if cover_idx >= 0:
|
||||
# # install cover
|
||||
# id3.delall("APIC")
|
||||
# id3.add(APIC(3, "image/jpeg", 3, "front cover", cover_arts[cover_idx][3]))
|
||||
# total_cover += 1
|
||||
# print(f" Written metadata for {f} with cover art - " + cover_arts[cover_idx][4])
|
||||
# else:
|
||||
# no_match.append(target_f)
|
||||
with open(target_f, "wb") as tf:
|
||||
tf.write(mobj.get_bytes())
|
||||
print(" Written file to: " + target_f)
|
||||
|
||||
total_succ += 1
|
||||
|
||||
@ -218,8 +205,6 @@ def main():
|
||||
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))
|
||||
for each in no_match:
|
||||
print("No match: " + each)
|
||||
print("\nSummary - Total Files: " + str(total_proc) + " Total Errors: " + str(total_error) + " Total Missing Covers: " + str(total_missing_cover))
|
||||
|
||||
main()
|
||||
|
Loading…
Reference in New Issue
Block a user