def set_id3_tags(audio): # add ID3 tag if it doesn't exist audio.add_tags() def embed_image(data): audio.tags.add( id3.APIC( encoding=3, mime='image/jpeg', type=3, desc='Front Cover', data=data ) ) save_cover_image(embed_image) if album is not None: audio.tags.add( id3.TALB(text=[tag_to_ascii(track.album.name, album)], encoding=3)) audio.tags.add( id3.TIT2(text=[tag_to_ascii(track.name, title)], encoding=3)) audio.tags.add( id3.TPE1(text=[tag_to_ascii(artists, artists_ascii)], encoding=3)) if album_artist is not None: audio.tags.add( id3.TPE2(text=[tag_to_ascii( track.album.artist.name, album_artist)], encoding=3)) audio.tags.add(id3.TDRC(text=[str(track.album.year)], encoding=3)) audio.tags.add( id3.TPOS(text=[idx_of_total_str(track.disc, num_discs)], encoding=3)) audio.tags.add( id3.TRCK(text=[idx_of_total_str(track.index, num_tracks)], encoding=3)) if args.comment is not None: audio.tags.add( id3.COMM(text=[tag_to_ascii(comment, comment_ascii)], encoding=3)) if args.grouping is not None: audio.tags.add( id3.TIT1(text=[tag_to_ascii(grouping, grouping_ascii)], encoding=3)) if genres is not None and genres: tcon_tag = id3.TCON(encoding=3) tcon_tag.genres = genres if args.ascii_path_only \ else genres_ascii audio.tags.add(tcon_tag) if args.id3_v23: audio.tags.update_to_v23() audio.save(v2_version=3, v23_sep='/') audio.tags.version = (2, 3, 0) else: audio.save()
def fix_tags(abs, ext, f_meta): """ :param abs: Path of the file we're tagging :param ext: Extension of the file we're tagging :param f_meta: Dict containing the metadata of the track we're tagging. """ if ext == "mp3": try: audio = id3.ID3(abs) except ID3NoHeaderError: audio = id3.ID3() audio['TRCK'] = id3.TRCK(text=str(audio['TRCK']) + "/" + str(f_meta['track_total'])) audio['TPOS'] = id3.TPOS(text=str(audio['TPOS']) + "/" + str(f_meta['disc_total'])) audio['TDRC'] = id3.TPOS(text=f_meta['release_date']) audio['TPUB'] = id3.TPOS(text=f_meta['planning']) audio['TPE1'] = id3.TPE1(text=f_meta['track_artist']) audio['TPE2'] = id3.TPE2(text=f_meta['album_artist']) audio.save(abs, "v2_version=3") else: audio = FLAC(abs) audio['TRACKTOTAL'] = str(f_meta['track_total']) audio['DISCTOTAL'] = str(f_meta['disc_total']) audio['DATE'] = f_meta['release_date'] audio['LABEL'] = f_meta['planning'] audio['ARTIST'] = f_meta['track_artist'] audio['ALBUMARTIST'] = f_meta['album_artist'] audio.save()
def set_id3_tags_raw(audio, audio_file): try: id3_dict = id3.ID3(audio_file) except id3.ID3NoHeaderError: id3_dict = id3.ID3() def embed_image(data): id3_dict.add( id3.APIC(encoding=3, mime='image/jpeg', type=3, desc='Front Cover', data=data)) save_cover_image(embed_image) if album is not None: id3_dict.add( id3.TALB(text=[tag_to_ascii(track.album.name, album)], encoding=3)) id3_dict.add( id3.TIT2(text=[tag_to_ascii(track.name, title)], encoding=3)) id3_dict.add( id3.TPE1(text=[tag_to_ascii(artists, artists_ascii)], encoding=3)) if album_artist is not None: id3_dict.add( id3.TPE2(text=[ tag_to_ascii(track.album.artist.name, album_artist) ], encoding=3)) id3_dict.add(id3.TDRC(text=[str(track.album.year)], encoding=3)) id3_dict.add( id3.TPOS(text=[idx_of_total_str(track.disc, num_discs)], encoding=3)) id3_dict.add( id3.TRCK(text=[idx_of_total_str(track.index, num_tracks)], encoding=3)) if args.comment is not None: id3_dict.add( id3.COMM(text=[tag_to_ascii(comment, comment_ascii)], encoding=3)) if args.grouping is not None: audio.tags.add( id3.TIT1(text=[tag_to_ascii(grouping, grouping_ascii)], encoding=3)) if genres is not None and genres: tcon_tag = id3.TCON(encoding=3) tcon_tag.genres = genres if args.ascii_path_only \ else genres_ascii id3_dict.add(tcon_tag) if args.id3_v23: id3_dict.update_to_v23() id3_dict.save(audio_file, v2_version=3, v23_sep='/') id3_dict.version = (2, 3, 0) else: id3_dict.save(audio_file) audio.tags = id3_dict
def set_tags(self, audio): try: id3_dict = id3.ID3(self.audio_file) except id3.ID3NoHeaderError: id3_dict = id3.ID3() def embed_image(data): id3_dict.add( id3.APIC(encoding=3, mime='image/jpeg', type=3, desc='Front Cover', data=data)) self.save_cover_image(embed_image) if self.album() is not None: id3_dict.add(id3.TALB(text=[self.album()], encoding=3)) id3_dict.add(id3.TIT2(text=[self.title()], encoding=3)) id3_dict.add(id3.TPE1(text=[self.artists()], encoding=3)) if self.album_artist() is not None: id3_dict.add(id3.TPE2(text=[self.album_artist()], encoding=3)) id3_dict.add(id3.TDRC(text=[self.year()], encoding=3)) id3_dict.add(id3.TPOS(text=[self.disc_idx_and_total()], encoding=3)) id3_dict.add(id3.TRCK(text=[self.track_idx_and_total()], encoding=3)) if self.comment() is not None: id3_dict.add(id3.COMM(text=[self.comment()], encoding=3)) if self.grouping() is not None: id3_dict.add(id3.TIT1(text=[self.grouping()], encoding=3)) if self.genres() is not None: tcon_tag = id3.TCON(encoding=3) tcon_tag.genres = self.genres() id3_dict.add(tcon_tag) if self.args.id3_v23: id3_dict.update_to_v23() id3_dict.save(self.audio_file, v2_version=3, v23_sep='/') id3_dict.version = (2, 3, 0) else: id3_dict.save(self.audio_file) audio.tags = id3_dict
def set_tags(self, audio): # add ID3 tag if it doesn't exist audio.add_tags() def embed_image(data): audio.tags.add( id3.APIC(encoding=3, mime='image/jpeg', type=3, desc='Front Cover', data=data)) self.save_cover_image(embed_image) if self.album() is not None: audio.tags.add(id3.TALB(text=[self.album()], encoding=3)) audio.tags.add(id3.TIT2(text=[self.title()], encoding=3)) audio.tags.add(id3.TPE1(text=[self.artists()], encoding=3)) if self.album_artist() is not None: audio.tags.add(id3.TPE2(text=[self.album_artist()], encoding=3)) audio.tags.add(id3.TDRC(text=[self.year()], encoding=3)) audio.tags.add(id3.TPOS(text=[self.disc_idx_and_total()], encoding=3)) audio.tags.add(id3.TRCK(text=[self.track_idx_and_total()], encoding=3)) if self.comment() is not None: audio.tags.add(id3.COMM(text=[self.comment()], encoding=3)) if self.grouping() is not None: audio.tags.add(id3.TIT1(text=[self.grouping()], encoding=3)) if self.genres() is not None: tcon_tag = id3.TCON(encoding=3) tcon_tag.genres = self.genres() audio.tags.add(tcon_tag) if self.args.id3_v23: audio.tags.update_to_v23() audio.save(v2_version=3, v23_sep='/') audio.tags.version = (2, 3, 0) else: audio.save()
def save(self): if self.clr: for file in self.audiofiles: tmp = mid3.ID3(file) tmp.clear() tmp.add(mid3.TIT2(text="")) # title frame tmp.add(mid3.TPE1(text="")) # artist frame tmp.add(mid3.TALB(text="")) # album frame tmp.add(mid3.TPE2(text="")) # album artist frame tmp.add(mid3.TCOM(text="")) # composer frame tmp.add(mid3.TCON(text="")) # genre frame tmp.add(mid3.TDRC(text="")) # date frame tmp.add(mid3.TRCK(text="")) # tracknumber frame tmp.add(mid3.TPOS(text="")) # discnumber frame tmp.add(mid3.TBPM(text="")) # bpm frame tmp.save() if self.artwork: with open(self.artwork, 'rb') as albumart: for file in self.audiofiles: tmp = mid3.ID3(file) tmp['APIC'] = mid3.APIC( encoding=3, mime='image/jpeg', type=3, desc=u'Cover', data=albumart.read() ) tmp.save() albumart.seek(0) for file in self.audiofiles: tmp = EasyID3(file) for tag in self.__sets: if self.__sets[tag]: tmp[tag] = self.__sets[tag] tmp.save()
def __update_tag(self, download_dir, audio_file, image_file, song_title=None, album_title=None, album_artist=None, album_composer=None, track_number=-1, process_index=-1, process_total=-1): """ The function that update audio metadata for each song. :param str download_dir: Download directory :param str audio_file: Path to audio file :param str image_file: Path to image file :param str song_title: Song title :param str album_title: Album title to be saved in metadata :param str album_artist: Album artist to be saved in metadata :param str album_composer: Album composer to be saved in metadata :param int track_number: track number to be saved in metadata :param int process_index: Current process index displayed in log message :param int process_total: Total number of process displayed in log message """ if audio_file is None: logger.warning('[Process:{}/{}][Track:{}] Could not update metadata because there is no data found on the playlist. The video may be private or deleted.'.format(process_index, process_total, track_number)) return if process_index > 0 and process_total > 0: if track_number > 0: log_prefix = '[Process:{}/{}][Track:{}]'.format(process_index, process_total, track_number) else: log_prefix = '[Process:{}/{}]'.format(process_index, process_total) else: log_prefix = '' audio_filename = os.path.basename(audio_file) try: # Validate audio data if not os.path.isfile(audio_file): raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), audio_file) audio_mime_type = mimetypes.guess_type(audio_file) if contains_at_least(audio_mime_type, ['audio/x-mp4', 'audio/x-m4a', 'audio/mp4a-latm']): # For more info about mp4 tag is available at # https://github.com/quodlibet/mutagen/blob/cf399dc58940fb1356f672809d763be9e2af0033/mutagen/mp4/__init__.py # http://atomicparsley.sourceforge.net/mpeg-4files.html mp4_data = mp4.MP4(audio_file) # Track Number if not self.no_track_number and track_number > 0: mp4_data['trkn'] = [(track_number, 0)] # Cover image if not self.no_artwork: image_data = self.__get_tag_image(image_file, audio_mime_type) if image_data: mp4_data['covr'] = [image_data] # Album title if not self.no_album_title and album_title is not None: mp4_data['\xa9alb'] = album_title # Album artist if not self.no_album_artist and album_artist is not None: mp4_data['aART'] = album_artist # Composer if not self.no_composer and album_composer is not None: mp4_data['\xa9wrt'] = album_composer # Part of compilation if not self.no_compilation: mp4_data['cpil'] = True # Save mp4_data.save() elif contains_at_least(audio_mime_type, ['audio/x-mp3', 'audio/mpeg']): # For more info about ID3v2 tag is available at # https://github.com/quodlibet/mutagen/blob/4a5d7d17f1a611280cc52d229aa70b77ca3c55dd/mutagen/id3/_frames.py # https://help.mp3tag.de/main_tags.html mp3_data = id3.ID3(audio_file) # Cover image if not self.no_artwork: image_data = self.__get_tag_image(image_file, audio_mime_type) if image_data: mp3_data['APIC'] = image_data # Track number if not self.no_track_number and track_number > 0: mp3_data.add(id3.TRCK(encoding=3, text=['{}/{}'.format(track_number, 0)])) # Album title if not self.no_album_title and album_title is not None: mp3_data["TALB"] = id3.TALB(encoding=0, text=album_title) # Album artist if not self.no_album_artist and album_artist is not None: mp3_data["TPE2"] = id3.TPE2(encoding=0, text=album_artist) # Composer if not self.no_composer and album_composer is not None: mp3_data["TCOM"] = id3.TCOM(encoding=0, text=album_composer) # Part of compilation if not self.no_compilation: mp3_data['TCMP'] = id3.TCMP(encoding=0, text=['1']) # Save mp3_data.save() elif contains_at_least(audio_mime_type, ['audio/x-aac']): # TODO: Add AAC support pass # image_data = __get_tag_image(image_file, audio_mime_type) # aac_data = aac.AAC(audio_file) # if not self.no_track_number: # if track_number > 0 and track_total > 0: # aac_data.add_tags(id3.TRCK(encoding=3, text=['{}/{}'.format(track_number, track_total)])) # # mp3_data['TRCK'] = id3.TRCK(encoding=3, text=[str(track_number)]) # if image_data: # mp3_data['APIC'] = image_data # aac_data.save() elif contains_at_least(audio_mime_type, ['audio/x-flac']): # https://github.com/quodlibet/mutagen/blob/a1db79ece62c4e86259f15825e360d1ce0986a22/mutagen/flac.py # https://github.com/quodlibet/mutagen/blob/4a5d7d17f1a611280cc52d229aa70b77ca3c55dd/tests/test_flac.py flac_data = flac.FLAC(audio_file) # Artwork if not self.no_artwork: image_data = self.__get_tag_image(image_file, audio_mime_type) if image_data: flac_data.add_picture(image_data) # Save flac_data.save() flac_data = File(audio_file) # Track number if not self.no_track_number and track_number > 0: flac_data.tags['tracknumber'] = str(track_number) # Album title if not self.no_album_title and album_title is not None: flac_data.tags['album'] = album_title # Album artist if not self.no_album_artist and album_artist is not None: flac_data.tags['albumartist'] = album_artist # Composer if not self.no_composer and album_composer is not None: flac_data.tags['composer'] = album_composer # Part of compilation if not self.no_compilation: pass # Save flac_data.save() # audio = File(audio_file, easy=True) else: raise InvalidMimeTypeException("Invalid audio format.", audio_mime_type) # Remove artwork if succeeded if os.path.exists(image_file): os.remove(image_file) # Rename filename from id to title dest_audio_file = os.path.join(download_dir, '{}.{}'.format(song_title, self.audio_codec)) os.rename(audio_file, dest_audio_file) dest_audio_filename = os.path.basename(dest_audio_file) logger.info('{}[File:{}] Updated.'.format(log_prefix, dest_audio_filename)) except FileNotFoundError: message = 'File not found. Skipped.' logger.warning('{}[File:{}] {}'.format(log_prefix, audio_filename, message)) except InvalidDataException as e: message = e.message + ' Skipped.' logger.warning('{}[File:{}] {}'.format(log_prefix, audio_filename, message)) except InvalidMimeTypeException as e: message = e.message + ' Skipped.' logger.warning('{}[File:{}] {}'.format(log_prefix, audio_filename, message)) except Exception as e: message = 'Error {}: {} Skipped.'.format(type(e), str(e)) logger.error('{}[File:{}] {}'.format(log_prefix, audio_filename, message))
def visit(arg, dirname, names): print dirname # Do some math/checking for disk number info parent = os.path.dirname(dirname) thisdir = os.path.basename(dirname) m = re.search(r'(?:cd|dis[ck])\s+([AB]|\d+)\b', thisdir, flags=re.IGNORECASE) disknum = 0 numdisks = 0 if m: disknum = m.group(1) if disknum == 'A': disknum = 1 elif disknum == 'B': disknum = 2 else: disknum = int(disknum) for dir in os.listdir(parent): if not os.path.isdir(os.path.join(parent, dir)): continue m = re.search(r'(?:cd|dis[ck])\s+([AB]|\d+)\b', dir, flags=re.IGNORECASE) if m: d = m.group(1) if d == 'A': d = 1 elif d == 'B': d = 2 else: d = int(d) numdisks = max(numdisks, d) # Parse the files mp3 = [] m4a = [] for file in names: if file.startswith('.'): continue elif file.endswith('.m4a'): m4a.append(file) elif file.endswith('.mp3'): mp3.append(file) else: try: # Clean up the name if os.path.isdir(os.path.join(dirname, file)): new = fix_name(file.decode("utf-8")) else: new = fix_name_full(file.decode("utf-8")) #print os.path.join(dirname, file) if file.decode("utf-8") != new.decode("utf-8"): print ' {0}\n {1}'.format(file, new) if not dryrun: os.rename(os.path.join(dirname, file), os.path.join(dirname, new)) except: print " FILE: "+os.path.join(dirname, file) raise # Now, parse the music files music = [] artists = {} is_comp = False artist = None for file in m4a: # Load some info about this mp4 for later comparison (mp4, name, changed) = load_mp4(dirname, file, len(m4a), int(disknum), int(numdisks)) # Setup for compilation detection if not is_comp: if artist: if artist != mp4[t4['artist']][0]: is_comp = True else: artist = mp4[t4['artist']][0] if artist.lower() == 'various': is_comp = True a_artist = mp4.get(t4['albumartist'], [None])[0] if a_artist and artist and a_artist != artist: is_comp = True # Save music files for later music.append({ 'file': file, 'name': name, 'mp4': mp4, 'changed': changed, }) for file in mp3: # Load some info about this mp4 for later comparison (mp3, name, changed) = load_mp3(dirname, file, len(mp3), disknum, numdisks) # Setup for compilation detection if not is_comp: if artist: if t3['artist'] in mp3 and artist != mp3[t3['artist']].text[0]: is_comp = True elif t3['artist'] in mp3: artist = mp3[t3['artist']].text[0] if artist.lower() == 'various': is_comp = True if t3['albumartist'] in mp3: a_artist = mp3[t3['albumartist']].text[0] if a_artist and artist and a_artist != artist: is_comp = True # Save music files for later music.append({ 'file': file, 'name': name, 'mp3': mp3, 'changed': changed, }) if len(artists) > 1: is_comp = True # Now parse the music files that we found for group in music: # Load the data from the group, for easier manipulation file = group['file'] name = group['name'] changed = group['changed'] #print file if 'mp4' in group: m = group['mp4'] # Compilation? compilation = m.get(t4['partofcompilation']) if is_comp and not compilation: compilation = True m[t4['partofcompilation']] = True changed.append('partofcompilation') a_artist = m.get(t4['albumartist'], [None])[0] if compilation and not a_artist: m[t4['albumartist']] = ['Various'] changed.append('albumartist') elif 'mp3' in group: m = group['mp3'] # Compilation? compilation = None if t3['partofcompilation'] in m: compilation = m[t3['partofcompilation']].text[0] if is_comp and not compilation: m[t3['partofcompilation']] = id3.TCMP(0, '1') changed.append('partofcompilation') if compilation and not (t3['albumartist'] in m and m[t3['albumartist']].text[0]): m[t3['albumartist']] = id3.TPE2(0, 'Various') changed.append('albumartist') # Save if changed and len(changed) > 0: print " Save {0}\n {1}".format(file, ','.join(changed)) if not dryrun: m.save() if name: print ' {0}\n {1}'.format(file, name) if not dryrun: os.rename(os.path.join(dirname, file), os.path.join(dirname, name))
def setAlbumArtist(self, _value): self.isSave = True self.tags["TPE2"] = id3.TPE2( encoding=3, text=self.correctValuesForMusicTagType(_value))
id3Title + " by " + id3Artist) try: url = api.get_stream_url(trackIDs[0]) urlretrieve(url, filePath) except: print("Error occurred downloading trackID " + trackIDs[0] + ". Skipping...") del trackIDs[0] continue errorTrack = 0 mp3File = File(filePath) mp3File.add_tags() mp3File.tags.add(id3.TIT2(encoding=3, text=id3Title)) mp3File.tags.add(id3.TALB(encoding=3, text=id3Album)) mp3File.tags.add(id3.TPE1(encoding=3, text=id3Artist)) mp3File.tags.add(id3.TPE2(encoding=3, text=id3AlbumArtist)) mp3File.tags.add(id3.TCOM(encoding=3, text=id3Composer)) if id3Genre: mp3File.tags.add(id3.TCON(encoding=3, text=id3Genre)) if id3Year: mp3File.tags.add(id3.TYER(encoding=3, text=id3Year)) mp3File.tags.add(id3.TRCK(encoding=3, text=id3TrackNumber)) mp3File.tags.add(id3.TPOS(encoding=3, text=id3DiscNumber)) if id3AlbumCover: mp3File.tags.add( id3.APIC(mime='image/jpeg', type=3, desc=u'Cover', data=id3AlbumCover)) mp3File.save() del trackIDs[0]