def _write_to_mp3(chapters=List[Chapter], filepath=str): import eyed3 from eyed3.id3 import Tag # write chapters to mp3 metadata tag = Tag() tag.parse(filepath) # remove chapters if already set # tag.table_of_contents.set(b'toc', child_ids=[]) # for every chapter id (i.e. 'ch0' od. 'chp0'), do # tag.chapters.remove(b'chp3') chapterIds = [] for i, chapter in enumerate(chapters): endTime = int(chapter.time * 1000) startTime = 0 if i != 0: startTime = int(chapters[i - 1].time * 1000) chapterId = str.encode('ch' + str(i)) newChapter = tag.chapters.set(chapterId, (startTime, endTime)) newChapter.sub_frames.setTextFrame(b'TIT2', u'{}'.format(chapter.title)) chapterIds.append(chapterId) tag.table_of_contents.set(b"toc", child_ids=chapterIds) tag.save()
def main(): "Entry point" args = docopt(__doc__, version="mp3chaps 0.1") tag = Tag() tag.parse(args["<filename>"]) if args["-l"]: list_chaps(tag) elif args["-i"]: add_chapters(tag, args["<filename>"]) elif args["-r"]: remove_chaps(tag)
def music_naming(path_to_file, music_performer, music_title): logger.info(path_to_file) audiofile = Tag() logger.info(audiofile) audiofile.parse(path_to_file) audiofile.artist = f"{music_performer}" audiofile.title = f"{music_title}" audiofile.save() logger.info( f'New audio attribute: Artist: {audiofile.artist}, Title: {audiofile.title}' )
def add_mp3_tags(path, tags, image, lyrics=None, image_mimetype='image/png'): tag = Tag() tag.parse(path) for key, val in tags.items(): try: setattr(tag, key, val) except Exception as e: print(e) if lyrics: tag.lyrics.set(lyrics) if image: tag.images.set(type_=3, img_data=image, mime_type=image_mimetype) tag.save(encoding='utf-8')
def main(mp3file, chaptersfile): total_length = int(core.load(mp3file).info.time_secs * 1000) chapters = [] n = 0 tag = Tag() tag.parse(mp3file) for i in open(chaptersfile, 'r').readlines(): chapter_time = to_millisecs(i[0:12]) chapter_title = u'{}'.format(i[13:]).rstrip() chapters.append([[chapter_time, 0], chapter_title, 'ch_' + str(n)]) if n > 0: chapters[n - 1][0][1] = chapter_time n += 1 chapters[n - 1][0][1] = total_length for times, title, id in chapters: chapter_frame = tag.chapters.set(id, tuple(times)) chapter_frame.sub_frames.setTextFrame(b"TIT2", title) tag.table_of_contents.set('toc', child_ids=[e[2] for e in chapters]) show_chapters(tag) tag.save()
class ID3Tagger(object): def __init__(self, filepath): self.filepath = filepath self.tag = Tag() def parse(self): self.tag.parse(self.filepath) return self def save(self): try: self.tag.save(self.filepath, version=ID3_V2_4, encoding="utf8") except TagException: pass try: self.tag.save(self.filepath, version=ID3_V2_3, encoding="utf8") except TagException: pass # Loss of the release date month and day. # Loss of the comment with description. try: self.tag.save(self.filepath, version=ID3_V1_1, encoding="utf8") except (TagException, UnicodeEncodeError): pass # Loses what v1.1 loses, and the track # try: self.tag.save(self.filepath, version=ID3_V1_0, encoding="utf8") except (TagException, UnicodeEncodeError): pass def __getattr__(self, name): return getattr(self.tag, name) def __setattr__(self, name, value): if name in ['filepath', 'tag']: self.__dict__[name] = value else: setattr(self.tag, name, value)
def add_chapters(fname, chaps): tag = Tag() tag.parse(fname) audioFile = core.load(fname) total_length = audioFile.info.time_secs * 1000 tag.setTextFrame(b"TLEN", str(int(total_length))) for i, chap in enumerate(chaps): if i < (len(chaps) - 1): chap.end = chaps[i + 1].start chaps[-1].end = total_length index = 0 child_ids = [] for chap in chaps: element_id = "ch{}".format(index).encode() print("Adding chapter {} at {}".format(chap.title, chap.start)) new_chap = tag.chapters.set(element_id, (chap.start, chap.end)) new_chap.sub_frames.setTextFrame(b"TIT2", u"{}".format(chap.title)) child_ids.append(element_id) index += 1 tag.table_of_contents.set(b"toc", child_ids=child_ids) list_chaps(tag) tag.save()
show_chapters(tag) tag.save() argp.add_argument('-i', help='mp3 file input') argp.add_argument('-l', help='show a chapter list') argp.add_argument('-c', help='chapters file input') args = vars(argp.parse_args()) if args['i']: mp3file = args['i'] chaptersfile = args['c'] if mp3file and chaptersfile: if not os.path.isfile(mp3file): argp.error('File {} not exists'.format(mp3file)) if not os.path.isfile(chaptersfile): argp.error('File {} not exists'.format(chaptersfile)) main(mp3file, chaptersfile) else: argp.print_help() elif args['l']: mp3file = args['l'] if mp3file: tag = Tag() tag.parse(mp3file) show_chapters(tag) else: argp.print_help() else: argp.print_help()
class CleanMyMusic: def __init__(self): self.regex = r"" self.t = Tag() self.parser = argparse.ArgumentParser(description='A Python Script to clean/format mp3 file metadata', prog='mp3clean', usage='python %(prog)s.py [options]', formatter_class=argparse.ArgumentDefaultsHelpFormatter, epilog="And that's how its done") self.args = None self.t_map = {'Title': 'title', 'Album': 'album', 'Artist': 'artist', 'AlbumArtist': 'album_artist', 'Genre': 'genre.name'} def main(self): self._parse_args() if self.args.case: self._title_case() if self.args.trim == 'r': self._rtrim() if self.args.trim == 'l': self._ltrim() if self.args.nocomments: self._no_comments() if self.args.set: self._set_value() if self.args.cleanse: self._cleanse() if self.args.trackno: self._get_track() if self.args.invtrackno: self._inv_track() if self.args.gettrack: self._set_track() if self.args.newtrack: self._new_track() if self.args.gettitle: self._get_title() def _title_case(self): for filename in os.listdir(self.args.dir): if filename.endswith(".mp3"): file_path = os.path.join(self.args.dir, filename) self.t.parse(file_path) if "All" in self.args.entity: for et in self.t_map: eval('self.t._set' + et + '(self.t.' + self.t_map[et] + '.title())') else: for et in self.args.entity: if et != "Filename": try: eval('self.t._set' + et + '(self.t.' + self.t_map[et] + '.title())') except NotImplementedError: continue self.t.save() if "Filename" in self.args.entity or "All" in self.args.entity: os.rename(file_path, file_path[:-4].title() + ".mp3") def _rtrim(self): for filename in os.listdir(self.args.dir): if filename.endswith(".mp3"): file_path = os.path.join(self.args.dir, filename) self.t.parse(file_path) if "All" in self.args.entity: for et in self.t_map: eval('self.t._set' + et + '(self.t.' + self.t_map[et] + '[:-self.args.num])') else: for et in self.args.entity: if et != "Filename": eval('self.t._set' + et + '(self.t.' + self.t_map[et] + '[:-self.args.num])') self.t.save() if "Filename" in self.args.entity or "All" in self.args.entity: os.rename(file_path, os.path.join(self.args.dir, filename[:-4 - self.args.num]) + ".mp3") def _ltrim(self): for filename in os.listdir(self.args.dir): if filename.endswith(".mp3"): file_path = os.path.join(self.args.dir, filename) self.t.parse(file_path) if "All" in self.args.entity: for et in self.t_map: eval('self.t._set' + et + '(self.t.' + self.t_map[et] + '[self.args.num:])') else: for et in self.args.entity: if et != "Filename": eval('self.t._set' + et + '(self.t.' + self.t_map[et] + '[self.args.num:])') self.t.save() if "Filename" in self.args.entity or "All" in self.args.entity: os.rename(file_path, os.path.join(self.args.dir, filename[self.args.num:])) def _no_comments(self): for filename in os.listdir(self.args.dir): if filename.endswith(".mp3"): file_path = os.path.join(self.args.dir, filename) self.t.parse(file_path) self.t.comments.set(u"") self.t.save() def _set_value(self): for filename in os.listdir(self.args.dir): if filename.endswith(".mp3"): file_path = os.path.join(self.args.dir, filename) self.t.parse(file_path) eval('self.t._set' + self.args.set + '(u"\u0020".join(self.args.value))') self.t.save() @staticmethod def _clean_using_regex(strng, regex): if regex == "[*]": return re.sub(r"\[*\]", '', strng) elif regex == "(*)": return re.sub(r"\(*\)", '', strng) elif regex == "* -": return strng.split(" -")[-1].strip() elif regex == "- *": return strng.split("- ")[0].strip() elif regex == ":: *": return strng.split(":: ")[0].strip() elif regex == '-': return re.sub("-", '', strng) elif regex == '-': return re.sub("_", ' ', strng) else: return strng def _cleanse(self): for filename in os.listdir(self.args.dir): if filename.endswith(".mp3"): file_path = os.path.join(self.args.dir, filename) self.t.parse(file_path.strip()) for et in self.args.entity: if et == "Filename": old = filename new = self._clean_using_regex(old, self.args.cleanse) os.rename(file_path, os.path.join(self.args.dir, new) + ".mp3") else: old = eval('self.t.' + self.t_map[et]) new = re.sub(' ', u"\u0020", self._clean_using_regex(old, self.args.cleanse)) eval('self.t._set' + et + '(u\"' + new + '\")') self.t.save() def _get_track(self): for filename in os.listdir(self.args.dir): if filename.endswith(".mp3"): file_path = os.path.join(self.args.dir, filename) self.t.parse(file_path) self.t.track_num = (filename[:2], 5) self.t.save() def _set_track(self): for filename in os.listdir(self.args.dir): if filename.endswith(".mp3"): file_path = os.path.join(self.args.dir, filename) self.t.parse(file_path) self.t.track_num = (self.t.title[:2], 5) self.t.save() def _inv_track(self): for filename in os.listdir(self.args.dir): if filename.endswith(".mp3"): file_path = os.path.join(self.args.dir, filename) self.t.parse(file_path) if len(str(self.t.track_num[0])) == 1: new_name = "0" + str(self.t.track_num[0]) + " " + filename else: new_name = str(self.t.track_num[0]) + " " + filename new_path = os.path.join(self.args.dir, new_name) os.rename(file_path, new_path) def _new_track(self): i = 1 for filename in os.listdir(self.args.dir): if filename.endswith(".mp3"): file_path = os.path.join(self.args.dir, filename) self.t.parse(file_path) self.t.track_num = (i, 5) self.t.save() if len(str(self.t.track_num[0])) == 1: new_name = "0" + str(i) + " " + filename else: new_name = str(i) + " " + filename new_path = os.path.join(self.args.dir, new_name) os.rename(file_path, new_path) i += 1 def _get_title(self): # fails for single word titles for filename in os.listdir(self.args.dir): if filename.endswith(".mp3"): file_path = os.path.join(self.args.dir, filename) try: self.t.parse(file_path) new_title = re.sub(' ', u"\u0020", filename[:-4]) self.t._setTitle(new_title) self.t.save() except TypeError: continue def _parse_args(self): group = self.parser.add_argument_group('options') self.parser.add_argument('--version', action='version', version='%(prog)s 0.5.0') self.parser.add_argument('dir', help='Directory of the files to be formatted', type=str) group.add_argument('-c', '--case', help='Change the case to Title Case', action='store_true') group.add_argument('-nc', '--nocomments', help='Remove comments if any', action='store_true') group.add_argument('-tn', '--trackno', help='Get Track No from Filename', action='store_true') group.add_argument('-itn', '--invtrackno', help='Add Track No to Filename', action='store_true') group.add_argument('-cl', '--cleanse', help='Remove unwanted characters that match a pattern', choices=['[*]', '(*)', '- *', '* -', ':: *', '_', '-'], type=str) group.add_argument('-gt', '--gettrack', help='Gets track number from Title', action='store_true') group.add_argument('-gtn', '--gettitle', help='Gets Title from Filename', action='store_true') group.add_argument('-nt', '--newtrack', help='Adds new track numbers', action='store_true') group.add_argument('-e', '--entity', help='What to format', required=False, action='append', choices=['Title', 'Filename', 'Album', 'Artist', 'AlbumArtist', 'Genre', 'All'], type=str) group.add_argument('-t', '--trim', help='Trim characters to left or right', choices=['l', 'r'], type=str) group.add_argument('-n', '--num', help='Number of character to be trimmed', type=int) group.add_argument('-s', '--set', help='Set any option', choices=['Album', 'Artist', 'AlbumArtist', 'Genre'], type=str) group.add_argument('-v', '--value', nargs="*", help='Value of choice given in set', type=str) self.args = self.parser.parse_args() if self.args.entity == "All": self.args.entity = self.t_map.keys()
root_path = os.getcwd() + "/" only_folders_from_root_path = [ f for f in listdir(root_path) if isdir(join(root_path, f)) ] items = [] tag = Tag() for path_folder in only_folders_from_root_path: path_files = root_path + path_folder only_files = [ f for f in listdir(path_files) if isfile(join(path_files, f)) and not islink(join(path_files, f)) ] for path in only_files: tag.parse(path_files + "/" + path) item = PyRSS2Gen.RSSItem( title=unidecode.unidecode(tag.artist), link=("https://www.simx.mobi/weszlo/" + path_folder + "/" + path), description=unidecode.unidecode(tag.title), guid=PyRSS2Gen.Guid("https://www.simx.mobi/weszlo/" + path_folder + "/" + path), pubDate=datetime.datetime(2018, 9, 5, 2, 00), ) items.append(item) rss = PyRSS2Gen.RSS2(title="WESZLO FM", link="https://www.simx.mobi/weszlo/feed.rss", description="Nieoficjalne archiwum WESZLO FM", lastBuildDate=datetime.datetime.now(), items=items)
] items = [] for path_folder in sorted(only_folders_from_root_path)[-7:]: path_files = unicode(root_path + path_folder) only_files = [ f for f in listdir(path_files) if isfile(join(path_files, f)) and not islink(join(path_files, f)) and f.endswith('.mp3') and (ads and not f.endswith('.noads.mp3') or not ads and f.endswith('.noads.mp3')) ] for path in only_files: full_path = path_files + "/" + path tag = Tag() tag.parse(full_path) if not tag.artist and not tag.title: continue item = fg.add_entry() item.id(url + path_folder + "/" + path) item.title(path[11:13] + ':' + path[13:15] + ' ' + (tag.title or '')) item.podcast.itunes_summary(tag.artist or '') item.podcast.itunes_subtitle(tag.artist or '') item.podcast.itunes_author(tag.artist or '') size = '%i' % os.path.getsize(full_path) path_for_url = path if not aac else (path + '.m4a') item.enclosure( url + path_folder + "/" + urllib.quote(path_for_url.encode('utf8')), size, 'audio/mpeg')