elif isinstance(metadata, FLAC): picture = metadata.pictures[0] elif isinstance(metadata.tags, VCommentDict): picture = Picture(b64decode(metadata.tags["METADATA_BLOCK_PICTURE"][0])) else: return None return picture.data def has_embedded_cover(metadata): if not isinstance(metadata, FileType): # pragma: nocover raise TypeError("Expecting mutagen.FileType, got " + str(type(metadata))) pictures = [] if isinstance(metadata.tags, EasyID3): pictures = metadata.get("pictures", []) elif isinstance(metadata, FLAC): pictures = metadata.pictures elif isinstance(metadata.tags, VCommentDict): pictures = metadata.tags.get("METADATA_BLOCK_PICTURE", []) return len(pictures) > 0 def _get_id3_apic(id3, key): return id3.getall("APIC") EasyID3.RegisterKey("pictures", _get_id3_apic)
"""Mutagen ID3 utility module.""" from mutagen.id3 import APIC from mutagen.easyid3 import EasyID3 from mutagen.mp3 import EasyMP3 import requests ENCODING_UTF8 = 3 TYPE_COVER_FRONT = 3 def set_albumart(id3, key, urls): """ Set the cover album art ID3 tag. Originally from https://stackoverflow.com/q/14369366 """ for url in urls: response = requests.get(url) tag = APIC(encoding=ENCODING_UTF8, mime=response.headers['Content-Type'], type=TYPE_COVER_FRONT, desc=u'Cover', data=response.content) id3.add(tag) EasyID3.RegisterKey('albumart', setter=set_albumart) __all__ = ('EasyMP3', )
for key, frameid in { 'albumartist': 'TPE2', 'album artist': 'TPE2', 'grouping': 'TIT1', 'content group': 'TIT1', }.iteritems(): EasyID3.RegisterTextKey(key, frameid) def comment_get(id3, _): return [comment.text for comment in id3['COMM'].text] def comment_set(id3, _, value): id3.add(mutagen.id3.COMM(encoding=3, lang='eng', desc='', text=value)) def originaldate_get(id3, _): return [stamp.text for stamp in id3['TDOR'].text] def originaldate_set(id3, _, value): id3.add(mutagen.id3.TDOR(encoding=3, text=value)) EasyID3.RegisterKey('comment', comment_get, comment_set) EasyID3.RegisterKey('description', comment_get, comment_set) EasyID3.RegisterKey('originaldate', originaldate_get, originaldate_set) EasyID3.RegisterKey('original release date', originaldate_get, originaldate_set)
for key, frameid in { "albumartist": "TPE2", "album artist": "TPE2", "grouping": "TIT1", "content group": "TIT1", }.items(): EasyID3.RegisterTextKey(key, frameid) def comment_get(id3, _): return [comment.text for comment in id3["COMM"].text] def comment_set(id3, _, value): id3.add(mutagen.id3.COMM(encoding=3, lang="eng", desc="", text=value)) def originaldate_get(id3, _): return [stamp.text for stamp in id3["TDOR"].text] def originaldate_set(id3, _, value): id3.add(mutagen.id3.TDOR(encoding=3, text=value)) EasyID3.RegisterKey("comment", comment_get, comment_set) EasyID3.RegisterKey("description", comment_get, comment_set) EasyID3.RegisterKey("originaldate", originaldate_get, originaldate_set) EasyID3.RegisterKey("original release date", originaldate_get, originaldate_set)
id3.add( mutagen.id3.POPM(encoding=3, email="no@email", rating=value, count=0)) else: frame.encoding = 3 frame.rating = value frame.count = 0 def rating_delete(id3, key): del id3["POPM"] EasyID3.RegisterKey("rating", rating_get, rating_set, rating_delete) def comment_get(id3, key): return id3["COMM"].text def comment_set(id3, key, value): try: frame = id3["COMM"] except KeyError: id3.add(mutagen.id3.COMM(encoding=3, text=value)) else: frame.encoding = 3 frame.text = value
def read_cover_image(id3, key): """ add cover image reading from mp3s """ apic = id3.getall('APIC') images = sorted(list( filter( lambda pic: pic.type in [PictureType.OTHER, PictureType.COVER_FRONT], apic)), key=(lambda pic: -pic.type)) if len(images): return images[0] return None ID3.RegisterKey('cover', getter=read_cover_image) # allow for case insensitive searching for cover.jpg COVER_FORMAT = re.compile(r"^(?i)cover\.jpg$") def get_cover(songpath): """ Get the safest file/data to use as the cover image """ song = MP3(songpath) cover = None mime = 'image/jpeg' try: if song.tags:
id3.add(COMM( encoding=3, lang='eng', text=value, )) else: frame.encoding = 3 frame.lang = 'CHI' frame.text = value def comment_delete(id3, key): del(id3["COMM"]) EasyID3.RegisterKey("comment", comment_get, comment_set, comment_delete) def cover_get(id3, key): return id3['APIC'].type def cover_set(id3, key, img: Image): buf = BytesIO() img.save(buf, format=img.format) id3['APIC'] = APIC( encoding=3, # 3 is for utf-8 mime=Image.MIME[img.format], # image/jpeg or image/png type=3, # 3 is for the cover image desc='',
raise EasyID3KeyError(key) def lyrics_set(id3, key, value): try: language = id3['language'] except KeyError: language = 'eng' id3.add(mutagen.id3.USLT(encoding=3, lang=language, desc='desc', text=value[0])) def lyrics_delete(id3, key): id3.delall('USLT') def lyrics_list(): return EasyID3.RegisterKey('picture', getter=picture_get, setter=picture_set, deleter=picture_delete, lister = picture_list) #EasyID3.RegisterKey('comments', getter=comments_get, setter=comments_set, deleter=comments_delete, lister = comments_list) EasyID3.RegisterKey('lyrics', getter=lyrics_get, setter=lyrics_set, deleter=lyrics_delete, lister = lyrics_list) EasyID3.RegisterTextKey('language', 'TLAN') class IrreplaceableKeyError(Exception): def __init__(self, msg): self.msg = msg def __str__(self): return repr(self.msg) class Song: #wiping TXXX wipes replaygain calc. def __init__(self, location, tagsToReplace=['album', 'artist', 'title', 'tracknumber', 'picture'], # future tags: comments/COMM, url/WXXX