def SearchMusicFiles(dir): fileList = [] ProcessFile = [] for ext in (SUPPORTEDFILES): fileList.append(glob.glob((dir + "/**/*" + ext), recursive=True)) for SFiles in SUPPORTEDFILES: if SFiles == ".flac": for y in range(len(fileList[0])): MFile = FLAC(fileList[0][y]) not GetLyricsInFiles(MFile) and ProcessFile.append(MFile) elif SFiles == ".ogg": for y in range(len(fileList[1])): MFile = OggVorbis(fileList[1][y]) not GetLyricsInFiles(MFile) and ProcessFile.append(MFile) elif SFiles == ".mp3": for y in range(len(fileList[2])): try: MFile = EasyID3(fileList[2][y]) not GetLyricsInFiles(MFile) and ProcessFile.append(MFile) except: MFile = MP3(fileList[2][y]) not GetLyricsInFiles(MFile) and ProcessFile.append(MFile) elif SFiles == ".m4a" or SFiles == ".mp4": for y in range(len(fileList[3])): MFile = EasyMP4(fileList[3][y]) not GetLyricsInFiles(MFile) and ProcessFile.append(MFile) for y in range(len(fileList[4])): MFile = EasyMP4(fileList[4][y]) not GetLyricsInFiles(MFile) and ProcessFile.append(MFile) return ProcessFile
def add_tag_m4a(self, fichero, name_cancion, parDir, directorio): # No Funciona patronMusicam4a = re.compile('.\.m4a') if patronMusicam4a.search(str(fichero)): name_cancion = name_cancion.rstrip( ".m4a" ) # ahora al nombre le quitamos la extension que queda fea. try: print( "file", os.path.basename(str(fichero)), "directory_1", os.path.basename(str(self.ruta)), "dir_2:", os.path.basename( os.path.dirname(os.path.normpath(str(self.ruta))))) EasyMP4Tags.RegisterTextKey("artist", "@ART") audioTag = EasyMP4(str(fichero)) audioTag['title'] = name_cancion audioTag['artist'] = parDir audioTag['album'] = directorio EasyMP4.RegisterTextKey("album_artist", "TPE2") audioTag['album_artist'] = "" print(audioTag['title'], "nuevo") audioTag.save() except: audioTag = mutagen.File(fichero, easy=True) audioTag.add_tags() audioTag['title'] = name_cancion audioTag['album'] = directorio audioTag['artist'] = parDir print("No existe un tag previo") audioTag.save(v2_version=3) audioTag.save()
def test_write_date_double(self): self.mp4["date"] = ["2004", "2005"] self.mp4.save(self.filename) mp4 = EasyMP4(self.filename) self.failUnlessEqual(mp4["date"], ["2004", "2005"]) self.mp4["date"] = ["2004", "2005"] self.mp4.save(self.filename) mp4 = EasyMP4(self.filename) self.failUnlessEqual(mp4["date"], ["2004", "2005"])
def setUp(self): fd, self.filename = mkstemp('.mp4') os.close(fd) empty = os.path.join('tests', 'data', 'has-tags.m4a') shutil.copy(empty, self.filename) self.mp4 = EasyMP4(self.filename) self.mp4.delete()
def editMP4(self, genre="Genre", album="Album", artist="Artist", date="2016"): """ """ for root, dirs, files in os.walk(self.filefolder): for f in files: if f.endswith(".m4a"): fullpath = root + os.sep + f self.tracks.append(fullpath) for track in self.tracks: print(track) audio = EasyMP4(track) print(audio) audio["genre"] = genre audio["album"] = album audio["artist"] = artist audio["albumartist"] = artist audio["artistsort"] = artist audio.save() print(audio) print()
def handle_mp4(filename): mp4_dir = os.path.join(recover_dir, 'mp3') mp4 = EasyMP4(filename) artist = (mp4.get('artist', ['noartist']))[0] album = (mp4.get('album', ['noalbum']))[0] title = (mp4.get('title', ['notitle']))[0] try: tracknumber = mp4['tracknumber'][0] except KeyError: tracknumber = 'XX' tracknumber = re.sub(r'/.*', '', tracknumber) try: tracknumber = '%02d' % int(tracknumber) except ValueError: pass track_file = ''.join([tracknumber, '-', title, '.mp4']) artist_dir = os.path.join(mp4_dir, artist) final_path = os.path.join(artist_dir, album, track_file) #os.renames(filename, final_path) if not os.path.isdir(os.path.dirname(final_path)): os.makedirs(os.path.dirname(final_path)) shutil.copy(filename, final_path) print final_path
def TAG_it(output_format, track_path, artist, album_title, index, track): if output_format in TAG_formats: print("\t\tTagging") if output_format == "mp3": from mutagen.easyid3 import EasyID3 song = EasyID3(track_path) elif output_format == "mp4" or output_format == "m4a": from mutagen.easymp4 import EasyMP4 song = EasyMP4(track_path) elif output_format == 'ogg': from mutagen import File as mFile song = mFile(track_path) elif output_format == 'flac': from mutagen.flac import FLAC song = FLAC(track_path) else: from mutagen import File as mFile song = mFile(track_path) if artist: song['artist'] = artist if album_title: song['album'] = album_title song['title'] = track song['tracknumber'] = str(index + 1) song.save() else: print("Tagging is not supported on {} format at this moment.".format( output_format)) return
def get_ext(link): if (link.endswith('.mp3')): return EasyMP3(link) elif (link.endswith('.m4a')): return EasyMP4(link) else: raise ValueError('Unable to read file extension.')
def tag_m4a(self, file_path, track_info, album_info, lyrics, album_art_path=None): tagger = EasyMP4(file_path) # Register ISRC, UPC, lyrics and explicit tags tagger.RegisterTextKey('isrc', '----:com.apple.itunes:ISRC') tagger.RegisterTextKey('upc', '----:com.apple.itunes:UPC') tagger.RegisterTextKey('explicit', 'rtng') tagger.RegisterTextKey('lyrics', '\xa9lyr') self._meta_tag(tagger, track_info, album_info, 'm4a') if self.fmtopts['embed_album_art'] and album_art_path is not None: pic = None with open(album_art_path, 'rb') as f: pic = MP4Cover(f.read()) tagger.RegisterTextKey('covr', 'covr') tagger['covr'] = [pic] # Set lyrics from Deezer if lyrics: tagger['lyrics'] = lyrics tagger.save(file_path)
def update_id3(fp, id3): """ Update file ID3 tag Try ID3 first, if not exist, try MP4, if still not exist, initialize an ID3. :param fp: (Purepath) file with absolute path :param id3: (dict) ID3 info in dict format :return: """ logger.info('Updating ID3 for {0}'.format(fp)) if Path(fp).is_file(): try: audio_file = EasyID3(fp) audio_file['tracknumber'] = id3.get('tracknumber') except mutagen.id3._util.ID3NoHeaderError: logger.warning('No ID3 available, try MP4') try: audio_file = EasyMP4(fp) audio_file['tracknumber'] = str(id3.get('tracknumber') + 1) except mutagen.mp4.MP4StreamInfoError: logger.warning('Not an MP4 file, create ID3 tag') audio_file = mutagen.File(fp, easy=True) audio_file.add_tags() audio_file['album'] = id3.get('album') audio_file['title'] = id3.get('title') audio_file.save() else: raise SystemExit('Audio File {0} is not found'.format(fp))
def rename_with_id3(fp): """ Rename with ID3 info Read ID3/MP4 info from given audio file, and use ID3/MP4 info to rename it. format is tracknum_title :param fp: (Purepath) audio file name with absolute path :return: """ if Path(fp).is_file(): try: audio_file = EasyID3(fp) new_name = '{0}_{1}{2}'.format(audio_file['tracknumber'], audio_file['title'], fp.suffix) except mutagen.id3._util.ID3NoHeaderError: audio_file = EasyMP4(fp) new_name = '{0}_{1}{2}'.format(audio_file['tracknumber'][0], audio_file['title'][0], fp.suffix) # filter out invalid characters from windows file name new_name = new_name.replace('?', '?') new_name = new_name.replace('"', "'") new_name = new_name.replace('“', "'") new_name = new_name.replace('”', "'") try: os.rename(fp, fp.parent.joinpath(new_name)) except FileExistsError: msg = 'File {0} exists, overwirting.'.format(new_name) print(msg) logger.warning(msg) os.remove(fp.parent.joinpath(new_name)) os.rename(fp, fp.parent.joinpath(new_name)) logger.info('Renamed {0} to {1}'.format(fp, fp.parent.joinpath(new_name))) else: raise SystemExit('File {0} is not found'.format(fp))
def GetMetadata(self, fpath): from mutagen import MutagenError from mutagen.mp3 import EasyMP3 from mutagen.easymp4 import EasyMP4 from mutagen.flac import FLAC from mutagen.apev2 import APEv2 try: if (fpath.endswith("mp3") or fpath.endswith("ogg") or fpath.endswith("wma")): audio = EasyMP3(fpath) elif (fpath.endswith("m4a") or fpath.endswith("m4v") or fpath.endswith("mp4")): audio = EasyMP4(fpath) elif fpath.endswith("flac"): audio = FLAC(fpath) elif fpath.endswith("ape"): audio = APEv2(fpath) elif fpath.endswith("wav"): audio = dict() except MutagenError as e: logger.warning("Mutagen parse metadata failed, ignore.\n" "file: {}, exception: {}".format(fpath, str(e))) return None metadata_dict = dict(audio) for key in metadata_dict.keys(): metadata_dict[key] = metadata_dict[key][0] if "title" not in metadata_dict: title = os.path.split(fpath)[-1].split(".")[0] metadata_dict["title"] = title return metadata_dict
def get_file_info(file_path: str) -> tuple: """ Get mp3/mp4/flac tags from a file. :param file_path: the file path. :return: a tuple of (title, genre, artist, album, length) """ empty = lambda: (Path(file_path).name, None, None, None, None) tag = None try: if file_path.endswith('.flac'): tag = FLAC(file_path) elif file_path.endswith('.mp3'): tag = EasyMP3(file_path) elif file_path.endswith('m4a'): tag = EasyMP4(file_path) else: return empty() get = lambda t, s: t.get(s, None) or t.get(s.upper(), None) title = get(tag, 'title') or Path(file_path).name genre = get(tag, 'genre') artist = get(tag, 'artist') album = get(tag, 'album') length = tag.info.length if isinstance(length, (int, float)): minutes, seconds = divmod(length, 60) length_str = f'{int(minutes)}:{round(seconds):02d}' else: length_str = None return (__to_string(title), __to_string(genre), __to_string(artist), __to_string(album), length_str) except MutagenError: return empty() finally: del tag
def Save(self, song): if (song['title'] == 'Advertisement') or (song.get('saved')) or ( not song.get('cached', False)): return if (Val('mode') in ('0', '3')) or ((Val('mode') == '2') and (song.get('rated') not in ('3', '4', '5'))): return if (not self.Tag(song)): return tmp = "%s.%s" % (song['path'], song['encoding']) if not xbmcvfs.copy(song['path_cch'], tmp): Log('Save BAD', song) return if song['encoding'] == 'm4a': tag = EasyMP4(tmp) elif song['encoding'] == 'mp3': tag = MP3(tmp, ID3=EasyID3) if tag == None: Log('Save BAD', song) xbmcvfs.delete(tmp) return tag['tracknumber'] = "%d/%d" % (song['number'], song['count']) tag['musicbrainz_trackid'] = song['brain'] tag['artist'] = song['artist'] tag['album'] = song['album'] tag['title'] = song['title'] if song['encoding'] == 'mp3': tag.save(v2_version=3) else: tag.save() xbmcvfs.mkdirs(song['path_dir']) xbmcvfs.copy(tmp, song['path_lib']) xbmcvfs.delete(tmp) song['saved'] = True self.M3U(song) if (song.get('art', False)) and ((not xbmcvfs.exists(song['path_alb'])) or (not xbmcvfs.exists(song['path_art']))): try: strm = self.Proxy().open(song['art']) data = strm.read() except ValueError: Log("Save ART '%s'" % song['art']) # xbmc.log(str(song)) return for jpg in [song['path_alb'], song['path_art']]: if not xbmcvfs.exists(jpg): file = xbmcvfs.File(jpg, 'wb') file.write(data) file.close() Log('Save OK', song, xbmc.LOGNOTICE)
def test_write_double(self): for key in EasyMP4.Get: if key in ["tracknumber", "discnumber", "date", "bpm"]: continue self.mp4[key] = ["a test", "value"] self.mp4.save(self.filename) mp4 = EasyMP4(self.filename) self.failUnlessEqual(mp4.get(key), ["a test", "value"]) self.failUnlessEqual(list(mp4.keys()), [key]) self.mp4[key] = ["a test", "value"] self.mp4.save(self.filename) mp4 = EasyMP4(self.filename) self.failUnlessEqual(mp4.get(key), ["a test", "value"]) self.failUnlessEqual(list(mp4.keys()), [key]) del (self.mp4[key])
def test_write_single(self): for key in EasyMP4.Get: if key in ["tracknumber", "discnumber", "date", "bpm"]: continue # Test creation self.mp4[key] = "a test value" self.mp4.save(self.filename) mp4 = EasyMP4(self.filename) self.failUnlessEqual(mp4[key], ["a test value"]) self.failUnlessEqual(list(mp4.keys()), [key]) # And non-creation setting. self.mp4[key] = "a test value" self.mp4.save(self.filename) mp4 = EasyMP4(self.filename) self.failUnlessEqual(mp4[key], ["a test value"]) self.failUnlessEqual(list(mp4.keys()), [key]) del (self.mp4[key])
def tag_m4a(self, file_path, track_info, album_info, album_art_path=None): tagger = EasyMP4(file_path) self._meta_tag(tagger, track_info, album_info, 'm4a') if self.fmtopts['embed_album_art'] and album_art_path is not None: pic = None with open(album_art_path, 'rb') as f: pic = MP4Cover(f.read()) tagger.RegisterTextKey('covr', 'covr') tagger['covr'] = [pic] tagger.save(file_path)
def metadata(self, **kwargs): """Write album and artist information to audiobook file. Changes the filename, expects album and artist to be defined by the first track""" if self.nodo: return track = EasyMP4(self.output0) track['album'] = kwargs.get('album', self[0].album) track['title'] = track['album'] track['artist'] = kwargs.get('artist', self[0].artist) track.save()
def get_from_files(self, img_url, img_name): logger.info('extract image from {}'.format(img_url)) if img_url.endswith('mp3') or img_url.endswith('ogg') or img_url.endswith('wma'): from mutagen.mp3 import EasyMP3 metadata = EasyMP3(img_url) content = metadata.tags._EasyID3__id3._DictProxy__dict['APIC:'].data elif img_url.endswith('m4a'): from mutagen.easymp4 import EasyMP4 metadata = EasyMP4(img_url) content = metadata.tags._EasyMP4Tags__mp4._DictProxy__dict['covr'][0] return content
def test_numeric(self): for tag in ["bpm"]: self.mp4[tag] = "3" self.failUnlessEqual(self.mp4[tag], ["3"]) self.mp4.save() mp4 = EasyMP4(self.filename) self.failUnlessEqual(mp4[tag], ["3"]) del (mp4[tag]) self.failIf(tag in mp4) self.failUnlessRaises(KeyError, mp4.__delitem__, tag) self.failUnlessRaises(ValueError, self.mp4.__setitem__, tag, "hello")
def find_underoccupied_dates(mon, year=_default_year): newdict = {} days = find_occupied_days(mon, year=year) daydict = { day: os.path.join(_default_inputdir, 'NPR.FreshAir.%02d.%02d.%d.m4a' % (day, mon, year)) for day in days } actdict = { day: EasyMP4(daydict[day]).info.length for day in filter( lambda day: os.stat(daydict[day]).st_size <= 4e7 and EasyMP4( daydict[day]).info.length <= 35 * 60, daydict) } # now get tree for each of these files for day in actdict: dt_s = datetime.datetime.strptime('%02d.%02d.%04d' % (day, mon, year), '%d.%m.%Y').date() tree = freshair.get_freshair(os.path.expanduser('~'), dt_s, debug=True, to_file_debug=False) expectdur = 0 for elem in tree.iter('story'): durs = list(elem.iter('duration')) if len(durs) == 0: continue expectdur += int(max(elem.iter('duration')).text) totlength = actdict[day] if expectdur == 0: newdict[day] = (totlength, 1.0, get_color(1.0)) continue discrep = max(0.0, expectdur * 0.985 - totlength) / (0.985 * expectdur) if discrep <= 1e-6: continue newdict[day] = (totlength, discrep, get_color(discrep)) return newdict
def set_tag_info_aac(f_path, tag_info, cover_data=None): if tag_info.get('date'): tag_info['date'] = tag_info['date'] + 'Z' audio = EasyMP4(f_path) audio.delete() for key in tag_info.keys(): audio[key] = tag_info[key] audio.save() if cover_data: audio = mutagen.mp4.MP4(f_path) audio['covr'] = [mutagen.mp4.MP4Cover( cover_data, imageformat=13 # 13 or 14 for png )] audio.save()
def apply_tags(file_path, tag_list): """ Using mutagen, apply the tags to the file. """ if file_path.endswith(".mp3"): muta = EasyID3(file_path) elif file_path.endswith(".m4a"): muta = EasyMP4(file_path) else: muta = File(file_path) for key in tag_list: muta.update({key: tag_list[key]}) muta.save()
def __init__(self, aacfilepath): """ """ self.songpath = aacfilepath try: self.audio = EasyMP4(self.songpath) except BaseException: # print(self.songpath) flag = False try: with open("failures.txt", "a+") as f: f.writelines(str(self.songpath)) f.write("\n") except BaseException: pass
def read_artists(path): artist_set = set() total_count = 0 unreadable_count = 0 for root, dirs, files in os.walk(path, topdown=False): file_count = 0 for file_count, filename in enumerate(files, start=1): path = root + "/" + filename ext = os.path.splitext(path)[1] # skip some common file extensions that may be found in music folders if filename.startswith( ".") or ext == ".jpg" or ext == ".m3u" or ext == ".txt": continue try: # guess the file type by extension. this is faster than looking at file contents if ext == ".m4v" or ext == ".mp4" or ext == ".m4a": audio = EasyMP4(path) elif ext == ".ogg": audio = OggVorbis(path) elif ext == ".flac": audio = FLAC(path) else: audio = EasyID3(path) except Exception as e: Logger.debug(e) # try slower magic number/tag lookup if filename based guess doesn't work. audio = mutagen.File(path, easy=True) if audio is not None and 'artist' in audio: for artist in audio['artist']: if len(artist) != 0 and not artist.lower().startswith( "various") and not artist.lower().startswith( "unknown"): artist_set.add(artist) else: unreadable_count += 1 total_count += file_count Logger.info("Total files %i, Total unreadable %i", total_count, unreadable_count) Logger.info("Total artist count %i", len(artist_set)) Logger.debug(artist_set) return artist_set
def parse_m4a(cls, filename): # EasyMP4() creates an EasyMP4 object that can be conveniently converted into a dictionary audio = EasyMP4(cls.mediadir + filename) d = dict(audio) # All values in the dict are further stored inside lists; this removes that unnecessary layer for key in d: d[key] = d[key][0] # Removes total from disc and track number values try: d['tracknumber'] = d['tracknumber'].split('/')[0] d['discnumber'] = d['discnumber'].split('/')[0] except KeyError: pass return d
def get_mutagen_audio_options(): """Build the list of options to give mutagen.File for reading audio tags according to the supported formats in the config. """ formats = settings.SUPPORTED_FORMATS from mutagen.easyid3 import EasyID3FileType audio_options = [EasyID3FileType] for fmt in formats: if fmt == 'mp3': from mutagen.mp3 import EasyMP3 # Add a key for the ID3 tag holding cover art information def cover_get(id3, key): for k in id3.keys(): if re.match(r'APIC:.*', k): return [id3[k].data] return [None] EasyMP3.ID3.RegisterKey('cover', cover_get) audio_options.append(EasyMP3) elif fmt == 'mp4' or fmt == 'm4a': from mutagen.easymp4 import EasyMP4 # Add a key for the ID3 tag holding cover art information EasyMP4.RegisterTextKey('cover', 'covr') audio_options.append(EasyMP4) elif fmt == 'ogg': from mutagen.oggvorbis import OggVorbis from mutagen.oggspeex import OggSpeex from mutagen.oggflac import OggFLAC audio_options += [OggVorbis, OggSpeex, OggFLAC] elif fmt == 'flac': from mutagen.flac import FLAC audio_options.append(FLAC) elif fmt == 'wma': from mutagen.asf import ASF audio_options.append(ASF) else: LOGGER.info('"%s" support not implemented yet' % fmt) return audio_options
def retrive_tags(file_path): """ Retrieve the Title, Album, and Artist Name from a file. """ tag_list = {"title": "", "album": "", "artist": ""} if file_path.endswith(".mp3"): muta = EasyID3(file_path) elif file_path.endswith(".m4a"): muta = EasyMP4(file_path) else: muta = File(file_path) for key in tag_list: tag_list.update({key: muta[key]}) return tag_list
def tag_video(file_path, track_info, album_art_path): tagger = EasyMP4(file_path) tagger.RegisterTextKey('explicit', 'rtng') tagger['title'] = track_info['title'] tagger['artist'] = track_info['artist']['name'] tagger['tracknumber'] = str( track_info['trackNumber']).zfill(2) + '/' + str( track_info['volumeNumber']) if track_info['explicit'] is not None: tagger['explicit'] = b'\x01' if track_info['explicit'] else b'\x02' pic = None with open(album_art_path, 'rb') as f: pic = MP4Cover(f.read()) tagger.RegisterTextKey('covr', 'covr') tagger['covr'] = [pic] tagger.save(file_path)
def reNum(self): """ """ for root, dirs, files in os.walk(self.filefolder): for f in files: if f.endswith(".m4a"): fullpath = root + os.sep + f self.tracks.append(fullpath) for track in self.tracks: print(track) audio = EasyMP4(track) tname = audio["title"] tnum = audio["tracknumber"][0].split("/")[0] if len(tnum) < 2: tnum = "0" + tnum newname = tnum + " " + tname[0] + ".m4a" newname = self.filefolder + os.sep + newname print(newname) os.rename(track, newname) print()