def set_image(self, image): """Replaces all embedded images by the passed image""" with translate_errors(): audio = self.MutagenType(self["~filename"]) try: data = image.read() except EnvironmentError as e: raise AudioFileError(e) pic = Picture() pic.data = data pic.type = APICType.COVER_FRONT pic.mime = image.mime_type pic.width = image.width pic.height = image.height pic.depth = image.color_depth audio.pop("coverart", None) audio.pop("coverartmime", None) audio["metadata_block_picture"] = base64.b64encode( pic.write()).decode("ascii") with translate_errors(): audio.save() self.has_images = True
def embed_metadata(music_file, cover_image, song): """Add metadata to extracted OGG files. For details on the METADATA_BLOCK_PICTURE struct format, see https://xiph.org/flac/format.html#metadata_block_picture """ music_file.seek(0) audio = OggVorbis(music_file) audio["title"] = song.title audio["artist"] = song.artist audio["album"] = song.album_name audio["tracknumber"] = str(song.track_number) audio["tracktotal"] = str(song.track_total) if song.genre is not None: audio["genre"] = song.genre picture = Picture() # PIL does not allow for direct saving to bytes cover_image_file = io.BytesIO() cover_image.save(cover_image_file, format="png") picture.data = cover_image_file.getvalue() picture.type = 3 # Cover (front) picture.mime = "image/png" picture.width = cover_image.width picture.height = cover_image.height # PIL does not give depth, so we assert then hardcode assert cover_image.mode == "RGBA" picture.depth = 32 audio["metadata_block_picture"] = [ base64.b64encode(picture.write()).decode("ascii") ] audio.save(music_file)
def set_image(self, image): """Replaces all embedded images by the passed image""" with translate_errors(): tag = FLAC(self["~filename"]) try: data = image.read() except EnvironmentError as e: raise AudioFileError(e) pic = Picture() pic.data = data pic.type = APICType.COVER_FRONT pic.mime = image.mime_type pic.width = image.width pic.height = image.height pic.depth = image.color_depth tag.add_picture(pic) with translate_errors(): tag.save() # clear vcomment tags super(FLACFile, self).clear_images() self.has_images = True
def get_cover_art_from_song(song_path): """ Takes in path pointing to an audio file of arbitrary format and finds the cover art, if any, and returns it as a File. """ file_type = mutagen.File(song_path) pic = None # TODO: Look to add support for more tag formats. if isinstance(file_type.tags, mutagen.id3.ID3): apic_frames = [file_type.tags[t] for t in file_type.tags.keys() if t.startswith("APIC")] cover_frame = apic_frames[0] if len(apic_frames) > 1: cover_frame = [f for f in apic_frames if f.type == mutagen.id3.PictureType.COVER_FRONT][0] downscaled_data = __downscale_cover_art(cover_frame.data) pic = Picture() pic.data = downscaled_data pic.type = cover_frame.type pic.mime = cover_frame.mime pic.width = THUMBNAIL_DIMENSION pic.height = THUMBNAIL_DIMENSION pic.depth = 16 # color depth return pic
def download_and_fix_ogg(ogg, audio_metadata, cover_art_file): global DRY_RUN if DRY_RUN: print "This is a dry run. So pretending to download the ogg..." return "/tmp/ogg" print "Now downloading the ogg in order to set the metadata in it..." if not LIVE and len(sys.argv) >= 6 and os.path.exists(sys.argv[5]): ogg_local_fn = sys.argv[5] print "(using presupplied file %s)" % ogg_local_fn else: f, metadata = client.get_file_and_metadata(ogg) ogg_local_fn = fetch_file(f, metadata) print "Successfully downloaded (to %s): now editing metadata..." % ogg_local_fn audio = OggVorbis(ogg_local_fn) for k in audio_metadata.keys(): audio[k] = audio_metadata[k] # add cover art im = Image.open(cover_art_file) w, h = im.size p = Picture() imdata = open(cover_art_file, 'rb').read() p.data = imdata p.type = 3 p.desc = '' p.mime = 'image/jpeg' p.width = w p.height = h p.depth = 24 dt = p.write() enc = base64.b64encode(dt).decode('ascii') audio['metadata_block_picture'] = [enc] audio.save() print "Successfully updated metadata." return ogg_local_fn
def set_image(self, image): """Replaces all embedded images by the passed image""" with translate_errors(): tag = FLAC(self["~filename"]) try: data = image.read() except EnvironmentError as e: raise AudioFileError(e) pic = Picture() pic.data = data pic.type = APICType.COVER_FRONT pic.mime = image.mime_type pic.width = image.width pic.height = image.height pic.depth = image.color_depth tag.add_picture(pic) with translate_errors(): tag.save() # clear vcomment tags super().clear_images() self.has_images = True
def download_and_fix_ogg(ogg, audio_metadata, cover_art_file): global DRY_RUN if DRY_RUN: print "This is a dry run. So pretending to download the ogg..." return "/tmp/ogg" print "Now downloading the ogg in order to set the metadata in it..." if not LIVE and len(sys.argv) >= 6 and os.path.exists(sys.argv[5]): ogg_local_fn = sys.argv[5] print "(using presupplied file %s)" % ogg_local_fn else: f, metadata = client.get_file_and_metadata(ogg) ogg_local_fn = fetch_file(f, metadata) print "Successfully downloaded (to %s): now editing metadata..." % ogg_local_fn audio = OggVorbis(ogg_local_fn) for k in audio_metadata.keys(): audio[k] = audio_metadata[k] # add cover art im=Image.open(cover_art_file) w,h=im.size p=Picture() imdata=open(cover_art_file,'rb').read() p.data=imdata p.type=3 p.desc='' p.mime='image/jpeg'; p.width=w; p.height=h p.depth=24 dt=p.write(); enc=base64.b64encode(dt).decode('ascii'); audio['metadata_block_picture']=[enc]; audio.save() print "Successfully updated metadata." return ogg_local_fn
def _addCoverToFile(self, album): if self.fileType == 'FLAC': if not self.hasCover or ( self.audioTag.pictures[0].height != 1000 and self.audioTag.pictures[0].width != 1000): if self.hasCover: self.audioTag.clear_pictures() # Build the file path by concatenating folder in the file path path = '' for folder in self.pathList: path += '{}/'.format(folder) path += album.coverName with open(path, "rb") as img: data = img.read() # Open physical image im = PIL.Image.open(path) width, height = im.size # Create picture and set its internals picture = Picture() picture.data = data picture.type = 3 # COVER_FRONT picture.desc = path.rsplit('/', 1)[-1] # Add picture name as a description picture.mime = mimetypes.guess_type(path)[0] picture.width = width picture.height = height picture.depth = mode_to_bpp[im.mode] # Save into file's audio tag self.audioTag.add_picture(picture) self.audioTag.save() else: # TODO for APIC frame pass
def set_image(self, image): """Replaces all embedded images by the passed image""" with translate_errors(): audio = self.MutagenType(self["~filename"]) try: data = image.read() except EnvironmentError as e: raise AudioFileError(e) pic = Picture() pic.data = data pic.type = APICType.COVER_FRONT pic.mime = image.mime_type pic.width = image.width pic.height = image.height pic.depth = image.color_depth audio.pop("coverart", None) audio.pop("coverartmime", None) audio["metadata_block_picture"] = base64.b64encode( pic.write()).decode("ascii") with translate_errors(): audio.save() self.has_images = True
def download_flac(track: tidalapi.models.Track, file_path, album=None): if album is None: album = track.album url = session.get_media_url(track_id=track.id) r = requests.get(url, stream=True) r.raw.decode_content = True data = BytesIO() shutil.copyfileobj(r.raw, data) data.seek(0) audio = FLAC(data) # general metatags audio['artist'] = track.artist.name audio[ 'title'] = f'{track.name}{f" ({track.version})" if track.version else ""}' # album related metatags audio['albumartist'] = album.artist.name audio[ 'album'] = f'{album.name}{f" ({album.version})" if album.version else ""}' audio['date'] = str(album.year) # track/disc position metatags audio['discnumber'] = str(track.volumeNumber) audio['disctotal'] = str(album.numberOfVolumes) audio['tracknumber'] = str(track.trackNumber) audio['tracktotal'] = str(album.numberOfTracks) # Tidal sometimes returns null for track copyright if hasattr(track, 'copyright') and track.copyright: audio['copyright'] = track.copyright elif hasattr(album, 'copyright') and album.copyright: audio['copyright'] = album.copyright # identifiers for later use in own music libraries if hasattr(track, 'isrc') and track.isrc: audio['isrc'] = track.isrc if hasattr(album, 'upc') and album.upc: audio['upc'] = album.upc pic = Picture() pic.type = id3.PictureType.COVER_FRONT pic.width = 640 pic.height = 640 pic.mime = 'image/jpeg' r = requests.get(track.album.image, stream=True) r.raw.decode_content = True pic.data = r.raw.read() audio.add_picture(pic) data.seek(0) audio.save(data) with open(file_path, "wb") as f: data.seek(0) shutil.copyfileobj(data, f)
async def add(self): loop = asyncio.get_event_loop() await loop.run_in_executor( None, super().__init__, f"{self.trackInfo['trackId']}.ogg" ) async with httpx.AsyncClient() as client: albumArtResponse = await client.get(self.trackInfo["albumArtHigh"]) picture = Picture() picture.data = albumArtResponse.content """ Initially Vorbis comments didn't contain album arts, now they can keep album arts according to FLAC's specifications, thus using Picture class from flac. mutagen example uses picture.type = 17 here: https://mutagen.readthedocs.io/en/latest/user/vcomment.html. Keeping it's value as 17 makes Android's MediaMetadataRetriever to not detect the album art. What on earth is "A bright coloured fish" ? Reference: https://xiph.org/flac/format.html#metadata_block_picture. """ picture.type = 3 picture.desc = "Cover (front)" picture.mime = "image/jpeg" picture.width = 544 picture.height = 544 encoded_data = base64.b64encode(picture.write()) vcomment_value = encoded_data.decode("ascii") """ Sets album art. """ self["metadata_block_picture"] = [vcomment_value] """ In Vorbis comments, a key e.g. "artists" can have more than one value. In mutagen implementation, that's why we give values in a list. Reference: https://gitlab.gnome.org/GNOME/rhythmbox/-/issues/16 """ self["title"] = [self.trackInfo["trackName"]] self["album"] = [self.trackInfo["albumName"]] """ This is where we can simply provide simply a list of artists, as written above (for having mutiple value for the same key). But, by that MediaMetadataRetriever is just shows first artist :-(. So, I'm just joining all artists with "/" separator. (Though, this is incorrect according to official reference). """ self["artist"] = ["/".join(self.trackInfo["trackArtistNames"])] """ No reference of this comment at http://age.hobba.nl/audio/mirroredpages/ogg-tagging.html, still using because a mutagen example uses it. Thus, unable to read. """ self["albumartist"] = [self.trackInfo["albumArtistName"]] """ This needs a fix. Vorbis comment keeps date instead of year & MediaMetadataRetriever is unable to read this. Fix if you get to know something... """ self["date"] = [str(self.trackInfo["year"])] self["tracknumber"] = [f"{self.trackInfo['trackNumber']}/{self.trackInfo['albumLength']}"] """ Again, no official reference of this one at http://age.hobba.nl/audio/mirroredpages/ogg-tagging.html. Thus, unable to read. """ self["tracktotal"] = [str(self.trackInfo["albumLength"])] loop = asyncio.get_event_loop() await loop.run_in_executor(None, self.save) """
def _picture_f2m(flackup_picture): """Create a Mutagen Picture from a Flackup Picture.""" picture = MutagenPicture() picture.type = flackup_picture.type picture.mime = flackup_picture.mime picture.width = flackup_picture.width picture.height = flackup_picture.height picture.depth = flackup_picture.depth picture.data = flackup_picture.data return picture
def tag_flac(self, file_path, track_info, album_info, album_art_path=None): tagger = FLAC(file_path) self._meta_tag(tagger, track_info, album_info, 'flac') if self.fmtopts['embed_album_art'] and album_art_path is not None: pic = Picture() with open(album_art_path, 'rb') as f: pic.data = f.read() pic.type = PictureType.COVER_FRONT pic.mime = u"image/jpeg" try: img = cv2.imread(album_art_path) pic.height, pic.width, channels = img.shape except Exception as e: pic.width = 1280 pic.height = 1280 pic.depth = 24 tagger.add_picture(pic) tagger.save(file_path)
def buttonAddPictureClicked(self): self.logger("buttonAddPictureClicked") filename = QtGui.QFileDialog.getOpenFileName(self, "Image File") reader = QtGui.QImageReader(filename) rformat = reader.format() image = reader.read() self.coverArtPixmap = QtGui.QPixmap.fromImage(image) self.logger( 'width = %d, height = %d' % (self.coverArtPixmap.width(), self.coverArtPixmap.height())) self.labelPicture.setPixmap( self.coverArtPixmap.scaled(self.labelPicture.width(), self.labelPicture.height(), QtCore.Qt.KeepAspectRatio)) pic = Picture() data = Qt.QByteArray() buf = Qt.QBuffer(data) pic.type = 3 # APICType.COVER_FRONT self.logger('format: %s' % rformat) if rformat == 'png': pic.mime = 'image/png' image.save(buf, 'PNG') elif rformat == 'jpg' or rformat == 'jpeg': pic.mime = 'image/jpeg' image.save(buf, 'JPG') else: pic.mime = 'image/unknown' self.logger("format: %s" % pic.mime) pic.data = data.data() pic.width = self.coverArtPixmap.width() pic.height = self.coverArtPixmap.height() pic.depth = self.coverArtPixmap.depth() pic.colors = image.colorCount() if len(self.audio.pictures) > 0: ret = QtGui.QMessageBox.warning( self, "FLAC Tagger", "This FLAC file already contains one or more pictures.\n" "Do you want to replace them?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel) if ret == QtGui.QMessageBox.Yes: self.audio.clear_pictures() self.audio.addPicture(pic) else: # make sure the old picture is displayed again self.displayPictures() else: self.audio.addPicture(pic)
def set_image(self, image): pic = Picture() pic.data = image.read() pic.type = COVER_FRONT pic.mime = image.mime_type pic.width = image.width pic.height = image.height # pic.depth = image.color_depth self.audio.add_picture(pic) with translate_errors(): self.audio.save() # clear vcomment tags super().clear_images()
def set_image(self, image): """Replaces all embedded images by the passed image""" with image: pic = Picture() pic.data = image.read() pic.type = COVER_FRONT pic.mime = image.mime_type pic.width = image.width pic.height = image.height self.audio.pop("coverart", None) self.audio.pop("coverartmime", None) self.audio["metadata_block_picture"] = base64.b64encode( pic.write()).decode("ascii")
def tag_put_picture(album_id): pic = Picture() album = get_album(album_id) with open(album['Path'] + "/folder.jpg", "rb") as f: pic.data = f.read() if not pic.data: return 'No folder.jpg found' pic.type = id3.PictureType.COVER_FRONT pic.mime = u"image/jpeg" pic.width = 500 pic.height = 500 pic.depth = 16 for p in tag_get_piece_paths(album_id): set_pic(p, pic) return 'success'
def _add_ogg_image(audio: File, image: Image, image_data: bytes): picture = Picture() picture.data = image_data picture.type = 3 # Front cover picture.desc = u"Cover Art" picture.mime = _image_mimes[image.format] picture.width = image.width picture.height = image.height picture.depth = 24 picture_data = picture.write() encoded_data = base64.b64encode(picture_data) vcomment_value = encoded_data.decode("ascii") audio["metadata_block_picture"] = [vcomment_value] audio.save()
def tag_flac(self, file_path, track_info, album_info, album_art_path=None): tagger = FLAC(file_path) self._meta_tag(tagger, track_info, album_info) if self.fmtopts['embed_album_art'] and album_art_path is not None: pic = Picture() with open(album_art_path, 'rb') as f: pic.data = f.read() pic.type = PictureType.COVER_FRONT pic.mime = u"image/jpeg" # TODO: detect this automatically? pic.width = 1280 pic.height = 1280 pic.depth = 24 tagger.add_picture(pic) tagger.save(file_path)
def to_flac(self, flac_meta: FLAC, builtin_cuesheet=False) -> None: ''' :param builtin_cuesheet: Whether to use the cuesheet field builtin FLAC specs ''' def add_if_exist(obj, tag_key): if obj: flac_meta.tags[tag_key] = obj add_if_exist(self.title, 'ALBUM') add_if_exist(self.genre, 'GENRE') add_if_exist(self.date, 'DATE') if self.artists: flac_meta.tags['ALBUM ARTIST'] = list(self.artists) if self.discnumber is not None: flac_meta.tags['DISCNUMBER'] = str(self.discnumber) if self.cover: image = Image.open(BytesIO(self.cover)) pic = Picture() pic.type = PictureType.COVER_FRONT pic.data = self.cover pic.mime = Image.MIME[image.format] pic.width = image.width pic.height = image.height flac_meta.add_picture(pic) if self.cuesheet: if builtin_cuesheet: flac_meta.cuesheet = self.cuesheet.to_flac( flac_meta.info.sample_rate) flac_meta.cuesheet.tracks.append( CueSheetTrack(170, flac_meta.info.total_samples)) # lead-out # save track-wise tags in foobar2000 style tracks = next(iter(self.cuesheet.files.values())) for i, track in tracks.items(): add_if_exist(track.title, f'CUE_TRACK{i:02}_TITLE') add_if_exist(track.performer, f'CUE_TRACK{i:02}_PERFORMER') else: flac_meta.tags['CUESHEET'] = str(self.cuesheet) add_if_exist(self.cuesheet.catalog, 'Catalog') add_if_exist(self.cuesheet.rems.get('COMMENT', None), 'Comment') flac_meta.save()
def updateCoverOgg(lossyFileName, artworkFileName): # # Embed album art into transcoded file: OGG # import base64 from mutagen.oggvorbis import OggVorbis from mutagen.flac import Picture import PIL.Image import tempfile from shutil import copyfile # Use copyfile b/c this will *not* copy rights (which is error prone on gvfs/samba) log('- embedding album art ' + artworkFileName + ' to ' + lossyFileName) # Copy lossy file to a local location; to prevent (save) errors in a samba environment tempLossyFile = tempfile.gettempdir() + '/' + 'temp.ogg' copyfile(lossyFileName, tempLossyFile) # Embed the image o = OggVorbis(tempLossyFile) im = PIL.Image.open(artworkFileName) w, h = im.size p = Picture() imdata = open(artworkFileName, 'rb').read() p.data = imdata p.type = 3 p.desc = '' p.mime = 'image/jpeg' p.width = w p.height = h p.depth = 24 dt = p.write() enc = base64.b64encode(dt).decode('ascii') o['metadata_block_picture'] = [enc] o.save() # Now we are ready; copy the file to the desired output directory copyfile(tempLossyFile, lossyFileName) os.remove(tempLossyFile) # Remove the temporary file(s) return
def addCover(self): if self.fileSuffix == "mp3" or self.fileSuffix == "MP3": self.songFile.tags.add( APIC(encoding=3, mime='image/jpeg', type=3, desc="Cover", data=self.albumart)) elif self.fileSuffix == "flac" or self.fileSuffix == "FLAC": image = Picture() image.type = id3.PictureType.COVER_FRONT image.mime = 'image/jpeg' image.desc = "Cover" image.data = self.albumart image.width = 500 image.height = 500 image.depth = 16 self.songFile.add_picture(image) self.songFile.save()
def get_image_size(fname): '''Determine the image type of fhandle and return its size. from draco''' with open(fname, 'rb') as fhandle: head = fhandle.read(24) if len(head) != 24: return if imghdr.what(fname) == 'png': check = struct.unpack('>i', head[4:8])[0] if check != 0x0d0a1a0a: return width, height = struct.unpack('>ii', head[16:24]) elif imghdr.what(fname) == 'gif': width, height = struct.unpack('<HH', head[6:10]) elif imghdr.what(fname) == 'jpeg': try: fhandle.seek(0) # Read 0xff next size = 2 ftype = 0 while not 0xc0 <= ftype <= 0xcf: fhandle.seek(size, 1) byte = fhandle.read(1) while ord(byte) == 0xff: byte = fhandle.read(1) ftype = ord(byte) size = struct.unpack('>H', fhandle.read(2))[0] - 2 # We are at a SOFn block fhandle.seek(1, 1) # Skip `precision' byte. height, width = struct.unpack('>HH', fhandle.read(4)) except Exception: #IGNORE:W0703 printError() return else: return fhandle.seek(0) imgdata = fhandle.read() img = Picture() img.data = imgdata img.width = width img.height = height return img
def write_cover_opus(afile, cover): file_ = OggOpus(afile) with open(cover, "rb") as h: data = h.read() picture = Picture() picture.data = data picture.type = 17 picture.desc = u"cover art" picture.mime = u"image/" + os.path.splitext(cover)[1][1:] dim = [int(x) for x in COVER_DIMENSION_INTERN.split("x")] picture.width = dim[0] picture.height = dim[1] picture.depth = 24 picture_data = picture.write() encoded_data = base64.b64encode(picture_data) vcomment_value = encoded_data.decode("ascii") file_["metadata_block_picture"] = [vcomment_value] file_.save()
def ogg_coverart(config): print("Adding " + config.coverart_mime + " cover art to " + config.ogg_file) coverart = config.coverart imgdata = open(coverart,'rb').read() im = Image.open(coverart) w,h = im.size p = Picture() p.data = imgdata p.type = 3 p.desc = 'Cover' p.mime = config.coverart_mime p.width = w p.height = h p.depth = 24 dt=p.write() enc=base64.b64encode(dt).decode('ascii') audio = OggVorbis(config.ogg_file) audio['metadata_block_picture']=[enc] audio.save()
def write_ogg_meta(ogg_file_path, cover_bytes, dimensions, year, artist, album, title): ogg_file = OggVorbis(ogg_file_path) picture = Picture() picture.data = cover_bytes picture.type = 3 picture.mime = u"image/jpeg" picture.width = dimensions[0] picture.height = dimensions[1] picture.depth = 24 picture_data = picture.write() encoded_data = b64encode(picture_data) comment = encoded_data.decode("ascii") ogg_file["metadata_block_picture"] = [comment] ogg_file["date"] = [year] ogg_file["artist"] = [artist] ogg_file["album"] = [album] ogg_file["title"] = [title] ogg_file.save()
def ogg_coverart(config): print("Adding " + config.coverart_mime + " cover art to " + config.ogg_file) coverart = config.coverart imgdata = open(coverart,'rb').read() im = Image.open(coverart) w,h = im.size p = Picture() p.data = imgdata p.type = 3 p.desc = 'Cover' p.mime = config.coverart_mime p.width = w p.height = h p.depth = 24 dt=p.write() enc=base64.b64encode(dt).decode('ascii') audio = OggVorbis(config.ogg_file) audio['metadata_block_picture']=[enc] audio.save()
def set_image(self, image): """Replaces all embedded images by the passed image""" try: audio = self.MutagenType(self["~filename"]) data = image.file.read() except EnvironmentError: return pic = Picture() pic.data = data pic.type = APICType.COVER_FRONT pic.mime = image.mime_type pic.width = image.width pic.height = image.height pic.depth = image.color_depth audio.pop("coverart", None) audio.pop("coverartmime", None) audio["metadata_block_picture"] = base64.b64encode(pic.write()) audio.save() self.has_images = True
def set_image(self, image): """Replaces all embedded images by the passed image""" try: audio = self.MutagenType(self["~filename"]) data = image.file.read() except EnvironmentError: return pic = Picture() pic.data = data pic.type = APICType.COVER_FRONT pic.mime = image.mime_type pic.width = image.width pic.height = image.height pic.depth = image.color_depth audio.pop("coverart", None) audio.pop("coverartmime", None) audio["metadata_block_picture"] = base64.b64encode(pic.write()) audio.save() self.has_images = True
def tagOGG(conf, mediafile): # https://mutagen.readthedocs.io/en/latest/user/vcomment.html # https://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE # https://xiph.org/flac/format.html#metadata_block_picture # https://github.com/quodlibet/mutagen/issues/200 img_stream, img_meta = imgConv(conf['tags']['img']) picture = Picture() picture.data = img_stream picture.type = 3 picture.description = '{0} ({1})'.format(conf['tags']['artist'], conf['tags']['comment']) picture.mime = img_meta['mime'] picture.width = img_meta['width'] picture.height = img_meta['height'] picture.depth = img_meta['depth'] picture.desc = '{0} ({1})'.format(conf['tags']['artist'], conf['tags']['comment']) containered_data = picture.write() encoded_data = base64.b64encode(containered_data) img_tag = encoded_data.decode('ascii') print('{0}: Now adding tags to {1}...'.format(datetime.datetime.now(), mediafile)) tag = OggVorbis(mediafile) tag['TITLE'] = conf['episode']['pretty_title'] tag['ARTIST'] = conf['tags']['artist'] tag['ALBUM'] = conf['tags']['album'] tag['DATE'] = '{0}.{1}.{2}'.format(conf['tags']['year'], conf['episode']['month'], conf['episode']['day']) tag['TRACKNUMBER'] = conf['tags']['track'] tag['GENRE'] = conf['tags']['genre'] tag['DESCRIPTION'] = conf['tags']['comment'] tag['COPYRIGHT'] = conf['tags']['copyright'] tag['CONTACT'] = conf['tags']['url'] tag['ENCODED-BY'] = conf['tags']['encoded'] tag['ENCODER'] = conf['tags']['encoded'] tag['METADATA_BLOCK_PICTURE'] = [img_tag] tag.save()
def UpdateCoverOgg(lossyFileName, artworkFileName): import base64; from mutagen.oggvorbis import OggVorbis from mutagen.flac import Picture; import PIL.Image import tempfile from shutil import copyfile # Use copyfile b/c this will *not* copy rights (which is error prone on gvfs/samba) Log('- embedding album art in ' + lossyFileName) # Copy lossy file to a local location; to prevent (save) errors in a samba environment tempLossyFile = tempfile.gettempdir() + '/' + 'temp.ogg' copyfile(lossyFileName, tempLossyFile) o = OggVorbis(tempLossyFile) im = PIL.Image.open(artworkFileName) w,h = im.size p = Picture() imdata = open(artworkFileName,'rb').read() p.data = imdata p.type = 3 p.desc = '' p.mime = 'image/jpeg' p.width = w p.height = h p.depth = 24 dt = p.write() enc = base64.b64encode(dt).decode('ascii') o['metadata_block_picture'] = [enc] o.save() copyfile(tempLossyFile, lossyFileName) os.remove(tempLossyFile) return
def set_image(self, image): """Replaces all embedded images by the passed image""" try: tag = FLAC(self["~filename"]) data = image.file.read() except EnvironmentError: return pic = Picture() pic.data = data pic.type = APICType.COVER_FRONT pic.mime = image.mime_type pic.width = image.width pic.height = image.height pic.depth = image.color_depth tag.add_picture(pic) tag.save() # clear vcomment tags super(FLACFile, self).clear_images() self.has_images = True
def _write_tags(self, flacfile, cover=False): f = FLAC(flacfile) f['albumartist'] = self._author f['tracknumber'] = str(self._track_number) f['album'] = self._album_title f['title'] = self._title f['artist'] = self._author f['genre'] = 'Audiobook' f['comment'] = 'Generated by WaveReader - https://github.com/kerenon/wavereader' if self._coverfile: p = Picture() with open(self._coverfile, "rb") as pf: p.data = pf.read() i = Image.open(self._coverfile) p.width = i.width p.height = i.height p.mime = i.get_format_mimetype() i.close() p.type = id3.PictureType.COVER_FRONT f.add_picture(p) f.save()
def Utils_Meta_setMusicInfo(path, info): """ TODO: Write lyrics to file :param path:文件目录 :param info:字典,详情: { "TALB": "Name of Album", "TIT2": "Title", "TPE1": "Author,Separate with '/'", "APIC": "Path to cover photo", "STRICT": Boolean:strict cover mode, "TRANSCODE": Boolean:convert to mp3, "TRANSPATH": "Path to converted file" } :return: int { 0: Nothing need done 1: Need reExt } """ status_code = 0 try: id3 = ID3(path) id3.update_to_v23() id3.delall("TALB") id3.delall("TIT2") id3.delall("TPE1") id3.delall("APIC") id3.add(TALB(encoding=3, text=info["TALB"])) id3.add(TIT2(encoding=3, text=info["TIT2"])) id3.add(TPE1(encoding=3, text=info["TPE1"])) if info["STRICT"]: image = Image.open(info["APIC"]) img_bytes = io.BytesIO() if image.size[0] > image.size[1]: image = image.crop( (int((image.size[0] - image.size[1]) / 2), 0, int((image.size[0] + image.size[1]) / 2), image.size[1])) elif image.size[0] < image.size[1]: image = image.crop((0, int( (image.size[1] - image.size[0]) / 2), 0, int((image.size[0] + image.size[1]) / 2))) image.resize((300, 300)).save(img_bytes, format="JPEG") id3.add( APIC(encoding=0, mime=mimetypes.guess_type(info["APIC"])[0], type=6, data=img_bytes.getvalue())) else: with open(info["APIC"], "rb") as f: id3.add( APIC(encoding=0, mime=mimetypes.guess_type(info["APIC"])[0], type=6, data=f.read())) id3.save() except ID3NoHeaderError: traceback.print_exc() ext = os.path.splitext(path)[1] if ".flac" in ext or ".FLAC" in ext: flac = FLAC(path) flac.tags['TITLE'] = info["TIT2"] flac.tags['ALBUM'] = info["TALB"] flac.tags['ARTIST'] = info["TPE1"] with open(info["APIC"], "rb") as f: image = Image.open(info["APIC"]) p = Picture() p.data = f.read() p.type = 3 p.mime = mimetypes.guess_type(info["APIC"])[0] p.width = image.size[0] p.height = image.size[1] p.depth = 24 # color depth flac.add_picture(p) image.close() flac.save() else: try: mp4 = MP4(path) mp4.tags["\xa9alb"] = info["TALB"] mp4.tags["\xa9nam"] = info["TIT2"] mp4.tags["\xa9ART"] = info["TPE1"] with open(info["APIC"], "rb") as f: mp4["covr"] = [ MP4Cover(f.read(), imageformat=MP4Cover.FORMAT_PNG) ] mp4.save() status_code = 1 except Exception: traceback.print_exc() if info["TRANSCODE"]: if not os.path.exists(os.path.split(info["TRANSPATH"])[0]): os.makedirs(os.path.split(info["TRANSPATH"])[0]) Utils_FormatTools.Utils_Format_autoTranscode( path, info["TRANSPATH"]) info["TRANSCODE"] = False Utils_Meta_setMusicInfo(info["TRANSPATH"], info) except MutagenError: traceback.print_exc() return status_code
def tag(file_path: Path, track: Track) -> None: """ Tag the music file at the given file path using the specified [Track][deethon.types.Track] instance. Args: file_path (Path): The music file to be tagged track: The [Track][deethon.types.Track] instance to be used for tagging. """ ext = file_path.suffix if ext == ".mp3": tags = ID3() tags.clear() tags.add(Frames["TALB"](encoding=3, text=track.album.title)) tags.add(Frames["TBPM"](encoding=3, text=str(track.bpm))) tags.add(Frames["TCON"](encoding=3, text=track.album.genres)) tags.add(Frames["TCOP"](encoding=3, text=track.copyright)) tags.add(Frames["TDAT"](encoding=3, text=track.release_date.strftime("%d%m"))) tags.add(Frames["TIT2"](encoding=3, text=track.title)) tags.add(Frames["TPE1"](encoding=3, text=track.artist)) tags.add(Frames["TPE2"](encoding=3, text=track.album.artist)) tags.add(Frames["TPOS"](encoding=3, text=str(track.disk_number))) tags.add(Frames["TPUB"](encoding=3, text=track.album.label)) tags.add(Frames["TRCK"]( encoding=3, text=f"{track.number}/{track.album.total_tracks}")) tags.add(Frames["TSRC"](encoding=3, text=track.isrc)) tags.add(Frames["TYER"](encoding=3, text=str(track.release_date.year))) tags.add(Frames["TXXX"](encoding=3, desc="replaygain_track_gain", text=str(track.replaygain_track_gain))) if track.lyrics: tags.add(Frames["USLT"](encoding=3, text=track.lyrics)) tags.add(Frames["APIC"](encoding=3, mime="image/jpeg", type=3, desc="Cover", data=track.album.cover_xl)) tags.save(file_path, v2_version=3) else: tags = FLAC(file_path) tags.clear() tags["album"] = track.album.title tags["albumartist"] = track.album.artist tags["artist"] = track.artist tags["bpm"] = str(track.bpm) tags["copyright"] = track.copyright tags["date"] = track.release_date.strftime("%Y-%m-%d") tags["genre"] = track.album.genres tags["isrc"] = track.isrc if track.lyrics: tags["lyrics"] = track.lyrics tags["replaygain_track_gain"] = str(track.replaygain_track_gain) tags["title"] = track.title tags["tracknumber"] = str(track.number) tags["year"] = str(track.release_date.year) cover = Picture() cover.type = 3 cover.data = track.album.cover_xl cover.width = 1000 cover.height = 1000 tags.clear_pictures() tags.add_picture(cover) tags.save(deleteid3=True)