def fetch_metadata(top): for dirpath, dirnames, filenames in os.walk(top): for filename in filenames: abs_path = os.path.join(dirpath, filename) if filename.lower().endswith(".mp3"): info = EasyID3(abs_path) else: info = MutagenFile(abs_path) if info is None: continue title = "".join(info.get("title", "")).encode("utf-8") artist = "".join(info.get("artist", "")).encode("utf-8") try: unicode_abs_path = unicode(abs_path.decode("utf-8")) audio_file = AudioFile.select_cond("path = ?", (unicode_abs_path,)).next() if os.stat(abs_path).st_mtime > audio_file.modtime: audio_file.title = title audio_file.artist = artist audio_file.path = abs_path audio_file.modtime = time.time() print "Updated %s" % abs_path except StopIteration: audio_file = AudioFile.new(title=title, artist=artist, path=abs_path, modtime=time.time()) print "Added %s to database" % abs_path
def cleanup_tags(self) -> None: '''Delete any ReplayGain tags from track. This dicards any unsaved changes, then modifies and saves the track's tags on disk and then reloads the new tags from disk. ''' tags_to_clean = set(rg_tags) # type: Set[str] tags_to_clean.update('QuodLibet::' + tag for tag in rg_tags) tags_to_clean.update('TXXX:' + tag for tag in rg_tags) tags_to_clean.update(['RVA2:track', 'RVA2:album']) tags_to_clean = { tag.lower() for tag in tags_to_clean } # Need a non-easy interface for proper ID3 cleanup t = MusicFile(self.filename, easy=False) tags_to_delete = [] for k in t.keys(): if k.lower() in tags_to_clean: tags_to_delete.append(k) for k in tags_to_delete: logger.debug("Deleting tag: %s", repr(k)) del t[k] t.save() # Re-init to pick up tag changes new_track = type(self.track)(self.filename) self.track = new_track
def __init__(self, path): self.path = path self.corrupt = False self.bitrate = self.length = 0 self.title = self.artist = self.album = '' try: self.mimetype = subprocess.Popen([ "/usr/bin/file", "--mime-type", path], stdout=subprocess.PIPE).communicate()[0].split(": ")[-1].rstrip() except ValueError: print(path) av = self.mimetype[0:5] # enqueue any audio file if av == "audio": audio = MutagenFile( path, easy=True ) try: self.bitrate = int(audio.info.bitrate) except: pass try: self.length = int(audio.info.length) except: pass try: self.artist = unicode( audio.get('artist', [''])[0] ) self.album = unicode( audio.get('album', [''])[0] ) self.title = unicode( audio.get('title', [''])[0] ) self.tracknumber = int( audio.get('tracknumber', [0])[0].split("/")[0] ) # split in above b/c sometimes encoders will list track numbers as "i/n" except Exception, e: print e, audio, audio.info.bitrate
class TFileType(TestCase): def setUp(self): self.vorbis = File(os.path.join(DATA_DIR, "empty.ogg")) filename = get_temp_copy(os.path.join(DATA_DIR, "xing.mp3")) self.mp3_notags = File(filename) self.mp3_filename = filename def tearDown(self): os.remove(self.mp3_filename) def test_delitem_not_there(self): self.failUnlessRaises(KeyError, self.vorbis.__delitem__, "foobar") def test_add_tags(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") self.failUnlessRaises(NotImplementedError, FileType().add_tags) def test_delitem(self): self.vorbis["foobar"] = "quux" del(self.vorbis["foobar"]) self.failIf("quux" in self.vorbis) def test_save_no_tags(self): self.assertTrue(self.mp3_notags.tags is None) self.assertTrue(self.mp3_notags.filename) self.mp3_notags.save() self.assertTrue(self.mp3_notags.tags is None)
def write_info2file(self, info): # open file with mutagen audio = File(info['filename'], easy=True) if audio is None: return # write title+album information into audio files if audio.tags is None: audio.add_tags() # write album+title if info['album'] is not None: audio.tags['album'] = info['album'] if info['title'] is not None: audio.tags['title'] = info['title'] # write genre tag if self.container.config.genre_tag is not None: audio.tags['genre'] = self.container.config.genre_tag else: audio.tags['genre'] = '' # write pubDate if info['pubDate'] is not None: audio.tags['date'] = info['pubDate'] audio.save()
def ensure_id3_tag_present(filepath): try: meta = EasyID3(filepath) except ID3NoHeaderError: meta = File(filepath, easy=True) meta.add_tags() meta.save()
class TFileType(TestCase): def setUp(self): self.vorbis = File(os.path.join(DATA_DIR, "empty.ogg")) fd, filename = mkstemp(".mp3") os.close(fd) shutil.copy(os.path.join(DATA_DIR, "xing.mp3"), filename) self.mp3_notags = File(filename) self.mp3_filename = filename def tearDown(self): os.remove(self.mp3_filename) def test_delitem_not_there(self): self.failUnlessRaises(KeyError, self.vorbis.__delitem__, "foobar") def test_add_tags(self): self.failUnlessRaises(NotImplementedError, FileType().add_tags) def test_delitem(self): self.vorbis["foobar"] = "quux" del(self.vorbis["foobar"]) self.failIf("quux" in self.vorbis) def test_save_no_tags(self): self.assertTrue(self.mp3_notags.tags is None) self.mp3_notags.save() self.assertTrue(self.mp3_notags.tags is None)
def save(pf): metadata = Metadata() metadata.copy(pf.metadata) mf = MFile(pf.filename) if mf is not None: mf.delete() return pf._save_and_rename(pf.filename, metadata)
def getSongInfo(inputFile): info = {} # detect format and type of tags file = File(inputFile) """ if 'APIC:' in file.keys(): artwork = file.tags['APIC:'].data # access APIC frame and grab the image with open('./image.jpg', 'wb') as img: img.write(artwork) # write artwork to new image """ # check for album art existence if "APIC:" in file.keys(): artwork = file.tags["APIC:"].data # access APIC frame and grab the image # extract image info["image"] = artwork # extract title info["title"] = str(file["TIT2"][0]) # extract artist info["artist"] = str(file["TPE1"][0]) # extract album info["album"] = str(file["TALB"][0]) if "TDRC" in file.keys(): # extract year info["year"] = str(file["TDRC"][0]) if "TCON" in file.keys(): # extract genre info["genre"] = str(file["TCON"][0]) if "TPUB" in file.keys(): # extract publisher info["publisher"] = str(file["TPUB"][0]) # extract length / duration info["length"] = str(round(file.info.length / 60, 2)) return info
def fixup_ID3(fname: Union[str, MusicFileType]) -> None: '''Convert RVA2 tags to TXXX:replaygain_* tags. Argument should be an MusicFile (instance of mutagen.FileType) or a string, which will be loaded by mutagen.MusicFile. If it is an instance of mutagen.id3.ID3FileType, the ReplayGain information in the RVA2 tags (if any) will be propagated to 'TXXX:replaygain_*' tags. Thus the resulting file will have the ReplayGain information encoded both ways for maximum compatibility. If the track is an instance of 'mutagen.mp3.EasyMP3', it will be re-opened as the non-easy equivalent, since EasyMP3 maps the replaygain tags to RVA2, preventing the editing of the TXXX tags. This function modifies the file on disk. ''' # Make sure we have the non-easy variant. if isinstance(fname, MusicFileType): fname = fname.filename track = MusicFile(fname, easy=False) # Only operate on ID3 if not isinstance(track, id3.ID3FileType): return # Get the RVA2 frames try: track_rva2 = track['RVA2:track'] if track_rva2.channel != 1: track_rva2 = None except KeyError: track_rva2 = None try: album_rva2 = track['RVA2:album'] if album_rva2.channel != 1: album_rva2 = None except KeyError: album_rva2 = None # Add the other tags based on RVA2 values if track_rva2: track['TXXX:replaygain_track_peak'] = \ id3.TXXX(encoding=id3.Encoding.UTF8, desc='replaygain_track_peak', text=format_peak(track_rva2.peak)) track['TXXX:replaygain_track_gain'] = \ id3.TXXX(encoding=id3.Encoding.UTF8, desc='replaygain_track_gain', text=format_gain(track_rva2.gain)) if album_rva2: track['TXXX:replaygain_album_peak'] = \ id3.TXXX(encoding=id3.Encoding.UTF8, desc='replaygain_album_peak', text=format_peak(album_rva2.peak)) track['TXXX:replaygain_album_gain'] = \ id3.TXXX(encoding=id3.Encoding.UTF8, desc='replaygain_album_gain', text=format_gain(album_rva2.gain)) track.save()
def set_tags(cls, audiobook, file_name): tags = getattr(audiobook, "%s_tags" % cls.ext)['tags'] if not tags.get('flac_sha1'): tags['flac_sha1'] = audiobook.get_source_sha1() audio = File(file_name) for k, v in tags.items(): audio[k] = v audio.save()
def get_artist_sort_title(self): try: tags = MFile(self.filename, easy=True) tag = tags.get('albumartistsort') # 'soaa' if tag: return tag[0] return tags.get('artistsort')[0] # 'soar' except: return None
def metadata(self): """ Updates metadata """ print("Starting to update metadata") glib = self.glib db = self.db man = self.man mMeta = {} for g in man.getAllMeta(): mMeta[g[0]] = {'title':g[1], 'artist':g[3], 'albumArtist':g[4], 'album':g[2], 'genre':g[6], 'trackNumber':g[7], 'totalTrackCount':g[8], 'diskNumber':g[9], 'totalDiskCount':g[10]} for i in glib: lid = db.getGLID(i['id']) if not lid: continue ipath = db.getPath(lid) try: m = mMeta[i['id']] except KeyError: db.addGID(lid, None) continue tags = [t for t in m for j in i if t == j] nMatch = [] for t in tags: if m[t] != i[t]: nMatch += [t] if nMatch: if '.mp3' in ipath or '.m4a' in ipath: try: sng = GLB(ipath, easy=True) except IOError: db.remove(lid) continue else: continue for n in nMatch: if '.mp3' in ipath and n == 'albumArtist': sng['performer'] = [i['albumArtist']] man.setMeta(i['id'], 'MusicAlbumArtist', i['albumArtist']) else: if n in ('trackNumber', 'totalTrackCount', 'diskNumber', 'totalDiskCount'): if n in ('trackNumber', 'totalTrackCount'): sng['tracknumber'] = [str(i['trackNumber']) + '/' + str(i['totalTrackCount'])] man.setMeta(i['id'], 'MusicTrackNumber', int(i['trackNumber'])) man.setMeta(i['id'], 'MusicTrackCount', int(i['totalTrackCount'])) else: sng['disknumber'] = [str(i['diskNumber']) + '/' + str(i['totalDiskCount'])] man.setMeta(i['id'], 'MusicDiscNumber', int(i['discNumber'])) man.setMeta(i['id'], 'MusicDiscCount', int(i['totalDiscCount'])) else: sng[n.lower()] = [i[n]] man.setMeta(i['id'], n.lower().replace('title', 'MusicName').replace('albumArtist', 'MusicAlbumArtist').replace('album', 'MusicAlbum').replace('artist', 'MusicArtist').replace('genre', 'MusicGenre'), i[n]) db.setUpMeta(lid) sng.save() print("Finished updating metadata")
def update_album_cover(filename, new_cover): conf = get_or_create_config() bak_conf = conf.copy() song_album = '' for album in bak_conf['library']: for i, song in enumerate(bak_conf['library'][album]['songs']): if song == filename: song_album = album image = Image.open(new_cover) output = StringIO.StringIO() image.save(output, format="JPEG") data = output.getvalue() output.close() audio = File(filename) audio.tags.add( APIC( encoding=3, # 3 is for utf-8 mime='image/jpeg', # image/jpeg or image/png type=3, # 3 is for the cover image desc=u'', data=data ) ) #from PyQt4.QtCore import pyqtRemoveInputHook #pyqtRemoveInputHook() #from IPython.Shell import IPShellEmbed; IPShellEmbed()() audio.save() break if song_album: break covers = set() for i, song in enumerate(bak_conf['library'][song_album]['songs']): covers.add(get_full_song_info(song)[4]) if len(covers) == 1: data = covers.pop() #print data if data: #all new cover are the same, updating album cover song_file = File(filename) album_name = get_cover_hash(song_file) iconpath = os.path.join(ROOT_PATH,'cover_cache',album_name+'.png') iconpath_jpg = os.path.join(ROOT_PATH,'cover_cache',album_name+'.jpg') with open(iconpath_jpg, 'wb') as img: img.write(data) im = Image.open(iconpath_jpg) #im = im.resize((cover_size, cover_size), Image.ANTIALIAS) im.thumbnail((cover_size,cover_size), Image.ANTIALIAS) im.save(iconpath) try: os.remove(iconpath_jpg) except: pass conf['library'][song_album]['cover'] = getCoverArt(filename)[0] save_config(conf)
def postProcessSong(self, song): if self.shouldGenerateTags: try: name = self.getSongPath(song) localList = song.name.split("- ") #The song should be split as "artist - title". If not, it won't be recognized artist = localList[0] if len(localList) > 1 else self.defaultArtist #The artist is usually first if its there. Otherwise no artist if self.allSongsDefaultArtist: artist = self.defaultArtist title = localList[1] if len(localList) > 1 else localList[0] #If there is no artist, the whole name is the title artist = artist.lstrip().rstrip() title = title.lstrip().rstrip() #Appreciate this. It took upwards of 5 hours to get the damn software to do this. try: songID = EasyID3(name) except ID3NoHeaderError: songID = MutagenFile(name, easy = True) songID.add_tags() songID['artist'] = artist songID['title'] = title songID.save() songID = ID3(name, v2_version=3) #EasyID3 doesn't support saving as 2.3 to get Windows to recognize it songID.update_to_v23() songID.save(v2_version=3) except FileNotFoundError: debug("File not found for: ", name)
def insert_coverart(self): audio = File(self.filename) if self.cover.endswith('png'): cover_format = MP4Cover.FORMAT_PNG else: cover_format = MP4Cover.FORMAT_JPEG data = open(self.cover, 'rb').read() audio.tags['covr'] = [MP4Cover(data, cover_format)] audio.save()
def read_from_file(cls, file_path): audio_file = File(file_path) audio_type = type(audio_file) if audio_type is MP3: return cls(**{k: Metadata.flatten(v) for k, v in EasyID3(file_path).items()}) if audio_type is FLAC: return cls(**{k: Metadata.flatten(v) for k, v in audio_file.items()}) raise UnknownFileFormatError('File %s does not seem to be a audio file' % file_path)
def get_track_genres(self): genre_list = [] try: tags = MFile(self.filename) genres = tags.get('\xa9gen') if genres is not None and len(genres) > 0: for genre in genres: for sub_genre in parse_genres(genre): genre_list.append(sub_genre.strip()) except Exception, e: Log('Exception reading (genre): ' + str(e))
def get_cover_art(song): if song.path == 'None': return None file = File(song.path) APIC = None for key in file.keys(): if 'APIC:' in key: APIC = key if APIC is None: return None artwork = file.tags[APIC].data return artwork
def parse(self): print os.path.abspath(self.filename) tag = MutagenFile(self.filename) if tag == None: print self.filename else: for key, value in tag.iteritems(): if key in GENERAL_KEYS.keys(): self.dict[ GENERAL_KEYS[key] ] = unicode(value) elif key in MP3_KEYS.keys(): self.dict[ MP3_KEYS[key] ] = unicode(value) elif key in MP4_KEYS.keys(): self.dict[ MP4_KEYS[key] ] = unicode(value)
def tag(self): data = self.get_parent_instance().metadata() with tempfile.NamedTemporaryFile(suffix='-musicdb.mp3') as f: # Download with default_storage.open(self.file.location) as g: contents = g.read() f.write(contents) f.flush() f.seek(0) audio = MutagenFile(f.name) audio.delete() if isinstance(audio, mp3.MP3): audio.tags = easyid3.EasyID3() audio.update(data) audio.save() self.length = int(audio.info.length) # Copy it back default_storage.delete(self.file.location) dst = default_storage.save(self.file.location, DjangoFile(f)) assert dst == self.file.location
def tag(filename, data): audio = File(filename) audio.delete() if isinstance(audio, mp3.MP3): audio.tags = easyid3.EasyID3() audio.update(data) audio.save()
def update_id3_tags(self): """ Update ID3 tags of downloaded song """ # Must init ID3 tags for appropriate header settings audio = File(self.tags._title+'.mp3', easy=True) audio.add_tags() # Save new tags audio['title'] = self.tags._title audio['artist'] = self.tags._artist audio['album'] = self.tags._album audio.save(self.tags._title+'.mp3')
def scan_track(path, from_dir = ''): t = None try: t = File(path) except Exception: pass if t is not None: if from_dir: t.relpath = t.filename.replace(from_dir, '', 1).lstrip('/') t.reldir = t.relpath.rsplit('/', 1) if len(t.reldir) > 1: t.reldir = t.reldir[0] else: t.reldir = '' return t
def on_episode_downloaded(self, episode): # exit if mutagen is not installed if not mutagen_installed: return # read filename (incl. file path) from gPodder database filename = episode.local_filename(create=False, check_only=True) if filename is None: return # open file with mutagen audio = File(filename, easy=True) if audio is None: return # read title+album from gPodder database album = episode.channel.title title = episode.title if (strip_album_from_title and title and album and title.startswith(album)): title = title[len(album):].lstrip() # convert pubDate to string try: pubDate = datetime.datetime.fromtimestamp(episode.pubDate).strftime('%Y-%m-%d %H:%M') except: pubDate = None # write title+album information into audio files if audio.tags is None: audio.add_tags() # write album+title if album is not None: audio.tags['album'] = album if title is not None: audio.tags['title'] = title # write genre tag if genre_tag is not None: audio.tags['genre'] = genre_tag else: audio.tags['genre'] = '' # write pubDate if pubDate is not None: audio.tags['date'] = pubDate audio.save() log(u'tagging.on_episode_downloaded(%s/%s)' % (episode.channel.title, episode.title))
def __init__(self, filename): self.filename = filename ext = os.path.splitext(filename)[1].lower() if ext == u'.flac': self.file = FLAC(filename) elif ext == u'.wma': self.file = ASF(filename) elif ext == u'.wv': self.file = WavPack(filename) elif ext in [u'.mpc', u'.mpp', u'.mp+']: self.file = Musepack(filename) elif ext in [u'.ogg', u'.ape']: self.file = File(filename) else: raise TypeError
def __init__(self, filename, blacklist=[], easy=True): self.filename = filename self.data = MusicFile(self.filename, easy=easy) if self.data is None: raise ValueError("Unable to identify %s as a music file" % (repr(filename))) # Also exclude mutagen's internal tags self.blacklist = [ re.compile("^~") ] + blacklist
def setUp(self): self.vorbis = File(os.path.join(DATA_DIR, "empty.ogg")) fd, filename = mkstemp(".mp3") os.close(fd) shutil.copy(os.path.join(DATA_DIR, "xing.mp3"), filename) self.mp3_notags = File(filename) self.mp3_filename = filename
def download(self, path: str, web_driver: WebDriver = None, service_url: str = '', lyrics='', website='', comment=''): file_path = super().download(path) try: meta = id3.ID3(file_path) except id3.ID3NoHeaderError: meta = File(file_path) meta.add_tags() if web_driver: lyrics = self.load_lyrics(web_driver) meta['TPE1'] = id3._frames.TPE1(text=[self.artist]) meta['TIT2'] = id3._frames.TIT2(text=[self.title]) meta['USLT'] = id3._frames.USLT(text=lyrics) meta['WORS'] = id3._frames.WORS(text=[website]) meta['COMM'] = id3._frames.COMM(text=[comment]) meta.save() return file_path
def convert_file(self, full_path): try: out_path = self.get_out_path(full_path) lame_options = self.lame_options or ['--preset', 'standard', '-h'] metadata = FLAC(full_path) try: os.makedirs(os.path.dirname(out_path)) except OSError as e: if e.errno != 17: raise # only raise if not "file exists" error flac_p = subprocess.Popen( [self.flac, '-s', '-d', '--stdout', full_path], stdout=subprocess.PIPE, preexec_fn=ignore_sigint) lame_cmd = [self.lame] + lame_options + ['--quiet', '-', out_path] lame_p = subprocess.Popen(lame_cmd, stdin=flac_p.stdout, preexec_fn=ignore_sigint) flac_p.wait() lame_p.wait() # now apply gain if self.apply_mp3gain: mp3gain_cmd = [self.mp3gain, '-q', '-T', '-r', '-k', out_path] subprocess.check_call(mp3gain_cmd, stdout=open('/dev/null', 'wb')) # finally, correct the tags id3data = File(out_path, easy=True) for attr in ('title', 'artist', 'album', 'date', 'genre', 'tracknumber'): id3data[attr] = metadata.get(attr) id3data.save() except Exception as e: status_queue.put(('ERROR', full_path, str(e))) if os.path.exists(out_path): os.unlink(out_path) else: status_queue.put(('OK', full_path, out_path))
def run(self): """ 开始爬取信息 """ self.kuGouCrawler = KuGouCrawler(self.albumCover_set, self.albumCoverFolder) for index, (songer, songname, songPath) in enumerate( zip(self.songer_list, self.songname_list, self.songPath_list)): if not self.keepRunning: break self.crawlSignal.emit(f"当前进度:{index}/{len(self.songPath_list)}") self.id_card = File(songPath) isTextModified = self.modifyTextPart(songname, songer) isAlbumModified = self.fetchAlbum(songer, songname) if isTextModified or isAlbumModified: try: # 歌曲播放时会导致保存失败 self.id_card.save() except: print(f"{songPath} 写入发生异常") else: self.crawlSignal.emit(f"当前进度:{index+1}/{len(self.songPath_list)}") self.kuGouCrawler.browser.quit() # 爬取流派 albumTcon_dict = {} if not self.keepRunning: return self.qqMusicCrawler = QQMusicCrawler(albumTcon_dict) self.crawlSignal.emit("酷狗爬取完成") for index, (songname, songPath) in enumerate( zip(self.songname_list, self.songPath_list)): if not self.keepRunning: self.qqMusicCrawler.browser.quit() break self.crawlSignal.emit(f"当前进度:{index}/{len(self.songPath_list)}") song = os.path.basename(songPath) self.qqMusicCrawler.get_tcon(song, songname, songPath) else: self.crawlSignal.emit(f"当前进度:{index+1}/{len(self.songPath_list)}") self.crawlSignal.emit("全部完成") self.qqMusicCrawler.browser.quit()
def generate_music(self): if 'audio' in self.attachments_types: log.info('[AP] Извлечение аудио...') user_id = self.api_vk.users.get()[0]['id'] response = self.audio_session._vk.http.get(self.post_url) tracks = scrap_data(response.text, user_id, filter_root_el={'class': 'audios_list'}) for track in tracks: name = sub(r"[^a-zA-Z '#0-9.а-яА-Я()-]", '', track['artist'] + ' - ' + track['title'] + '.mp3') try: file = download(track['url'], out=name) except (urllib.error.URLError, IndexError): log.exception( '[AP] Не удалось скачать аудиозапись. Пропускаем ее...' ) continue if getsize(file) > 52428800: log.warning( '[AP] Файл весит более 50 МиБ. Пропускаем его...') continue try: music = EasyID3(file) except id3.ID3NoHeaderError: music = File(file, easy=True) music.add_tags() music['title'] = track['title'] music['artist'] = track['artist'] music.save() del music self.tracks.append((name, track['duration']))
def add_metadata(filename: str, args): """Add metadata to an existing file.""" f = File(filename) f.add_tags() for title, tag in METADATA_FIELDS.items(): f.tags.add(tag(encoding=Encoding.UTF8, text=[getattr(args, title)])) f.save()
def generate_music(self): if 'attachments' in self.post: log.info('[AP] Извлечение аудио...') log.info('[AP] Данная функция находится в стадии тестирования.') n = 0 session.http.cookies.update(dict(remixmdevice=self.remixmdevice)) user_id = api_vk.users.get()[0]['id'] for attachment in self.post['attachments']: if attachment['type'] == 'audio': post_url = 'https://m.vk.com/wall%(owner_id)s_%(id)s' % self.post soup = BeautifulSoup(session.http.get(post_url).text, 'html.parser') track_list = [decode_audio_url(track.get('value'), user_id) for track in soup.find_all(type='hidden') if 'mp3' in track.get('value')] dur_list = [dur.get('data-dur') for dur in soup.find_all('div') if dur.get('data-dur')] name = sub(r"[/\"?:|<>*]", '', attachment['audio']['artist'] + ' - ' + attachment['audio']['title'] + '.mp3') try: file = download(track_list[n], out=name) except urllib.error.URLError: continue try: music = EasyID3(file) except id3.ID3NoHeaderError: music = File(file, easy=True) music.add_tags() music['title'] = attachment['audio']['title'] music['artist'] = attachment['audio']['artist'] music.save() del music self.tracks.append((name, dur_list[n])) n += 1
def testFileTagProcessor(self): from mutagen import File from klangbecken.playlist import ( FileAddition, FileDeletion, MetadataChange, file_tag_processor, ) # No-ops file_tag_processor( self.tempdir, "nonexistant", "fileIdZZ", "mp3", [ FileAddition(""), MetadataChange("id", "abc"), MetadataChange("playlist", "abc"), MetadataChange("ext", "abc"), MetadataChange("nonexistant", "abc"), FileDeletion(), ], ) changes = { "artist": "New Artist (๛)", "title": "New Title (᛭)", "cue_in": "0.123", "cue_out": "123", "track_gain": "-12 dB", } metadata_changes = [ MetadataChange(key, val) for key, val in changes.items() ] # Valid files for filename in ["silence.mp3", "silence-stripped.mp3"]: prefix, ext = filename.split(".") path = os.path.join(self.tempdir, "music", filename) mutagenfile = File(path, easy=True) # Make sure tags are not already the same before updating for key, val in changes.items(): self.assertNotEqual(val, mutagenfile.get(key, [""])[0]) # Update and verify tags file_tag_processor(self.tempdir, "music", prefix, ext, metadata_changes) mutagenfile = File(path, easy=True) for key, val in changes.items(): self.assertEqual(len(mutagenfile.get(key, [""])), 1) self.assertEqual(val, mutagenfile.get(key, [""])[0])
def fix_music(): ''' Searches for '.mp3' files in directory and checks whether they already contain album art and album name tags or not. ''' files = [f for f in listdir('.') if f[-4:] == '.mp3'] for file_name in files: tags = File(file_name) if 'APIC:Cover' in tags.keys() and 'TALB' in tags.keys( ): #Checks whether there is album art and album name print("%s already has tags " % tags["TIT2"]) elif not ('APIC:Cover' in tags.keys()) and 'TALB' in tags.keys(): album = tags["TALB"].text[0] print("........................\n") print("%s Adding metadata" % file_name) try: albumart = albumsearch.img_search_google(album) except Exception: albumart = albumsearch.img_search_bing(album) add_albumart(albumart, file_name) else: print("........................\n") print("%s Adding metadata" % file_name) try: artist, album, song_name, lyrics, match_bool, score = get_details_spotify( file_name) # Try finding details through spotify except Exception: artist, album, song_name, lyrics, match_bool, score = get_details_letssingit( file_name) # Use bad scraping method as last resort try: print('*Trying to extract album art from Google.com') albumart = albumsearch.img_search_google(album) except Exception: print('*Trying to extract album art from Bing.com') albumart = albumsearch.img_search_bing(album) if match_bool: add_albumart(albumart, file_name) add_details(file_name, song_name, artist, album, lyrics) else: print("*Couldn't find appropriate details of your song") with open("musicrepair_log.txt", "a") as problems: problems.write(str(file_name) + '\n') #log song that couldn't be repaired print("\nMatch score : %s%s" % (round(score * 10, 1), "/10.0")) print("........................\n\n")
def generate_music(self): if 'audio' in self.attachments_types: log.info('[AP] Извлечение аудио...') n = 0 self.session.http.cookies.update(dict(remixmdevice=self.remixmdevice)) user_id = self.api_vk.users.get()[0]['id'] for attachment in self.post['attachments']: if attachment['type'] == 'audio': post_url = 'https://m.vk.com/wall%(owner_id)s_%(id)s' % self.post soup = BeautifulSoup(self.session.http.get(post_url).text, 'html.parser') track_list = [decode_audio_url(track.get('value'), user_id) for track in soup.find_all(type='hidden') if 'mp3' in track.get('value')] dur_list = [dur.get('data-dur') for dur in soup.find_all('div') if dur.get('data-dur')] name = sub(r"[/\"?:|<>*]", '', attachment['audio']['artist'] + ' - ' + attachment['audio']['title'] + '.mp3') try: file = download(track_list[n], out=name) except (urllib.error.URLError, IndexError): log.exception('[AP] Не удалось скачать аудиозапись. Пропускаем ее...') continue if getsize(file) > 52428800: log.warning('[AP] Файл весит более 50 МиБ. Пропускаем его...') continue try: music = EasyID3(file) except id3.ID3NoHeaderError: music = File(file, easy=True) music.add_tags() music['title'] = attachment['audio']['title'] music['artist'] = attachment['audio']['artist'] music.save() del music self.tracks.append((name, dur_list[n])) n += 1
def process_metadata(self, metadata): Log('Reading OGG tags from: ' + self.filename) try: tags = MFile(self.filename) Log('Found tags: ' + str(tags.keys())) except: Log('An error occured while attempting to parse the OGG file: ' + self.filename) return # Genres try: genres = tags.get('genre') if genres is not None and len(genres) > 0: metadata.genres.clear() for genre in genres: for sub_genre in parse_genres(genre): if sub_genre.strip(): metadata.genres.add(sub_genre.strip()) except Exception, e: Log('Exception reading genre: ' + str(e))
def __init__(self, path): self._path = path try: self.info = EasyID3(path) except: title = [] title.append(os.path.basename(path)) self.info = {"artist": ["Nieznany wykonawca"], "title": title} try: self.length = File(path).info.length except: self.length = 0
def upload_audio(con, pista_id, file): file.seek(0) audio = File(file) if audio is not None: filename = secure_filename(file.filename) archivo_id = str(insert_archivo(con, audio, filename, pista_id)) path = app.config['UPLOAD_FOLDER'] + '/audio/' + str(pista_id) + '/' + archivo_id file.seek(0) os.makedirs(path, exist_ok=True) file.save(os.path.join(path, filename)) file.close() else: flash('No es un archivo de audio', 'danger')
def get_tag(tags: File, tag_names: List[str], get_all=False): for tag in tag_names: val = tags.get(tag) if val: if hasattr(val, 'text'): val = val.text if get_all: return val while type(val) == list or type(val) == tuple: val = val[0] return val
def coverImage(): cover = request.args["music"] cover = File(cover) if "APIC:" in cover.tags.keys(): imgcover = cover.tags["APIC:"].data strIO = BytesIO() strIO.write(imgcover) strIO.seek(0) return send_file(strIO, mimetype="image/jpg") else: return app.send_static_file('images/cover.png')
def tagless_sha256sum(self): with self.path.open('rb') as f: tmp = BytesIO(f.read()) try: File(tmp).tags.delete(tmp) except AttributeError as e: log.error('Error determining tagless sha256sum for {}: {}'.format( self._f.filename, e)) return self._f.filename tmp.seek(0) return sha256(tmp.read()).hexdigest()
def home(): musiclist = glob.glob("static/musics/*.mp3") musicJ = [{ 'filename': mi.split("/")[-1], "coverURL": url_for('coverImage', music=mi), "fileURL": url_for('sounds', music=mi), "length": sec2minString(File(mi).info.length), "Tags": None } for mi in musiclist] for i in range(len(musicJ)): tag = File(musiclist[i]) if 'TIT2' in tag.keys(): musicJ[i]['Tags'] = { 'TIT2': tag['TIT2'].text[0], 'TPE1': tag['TPE1'].text[0] } return render_template("home.html", musicJ=musicJ, musicJson=json.dumps(musicJ))
def modifySongInfo(songInfo: dict) -> str: """ 从字典中读取信息并修改歌曲的标签卡信息 """ id_card = File(songInfo['songPath']) if songInfo['suffix'] == '.mp3': id_card['TRCK'] = TRCK(encoding=3, text=songInfo['tracknumber']) id_card['TIT2'] = TIT2(encoding=3, text=songInfo['songName']) id_card['TDRC'] = TDRC(encoding=3, text=songInfo['year'][:4]) id_card['TPE1'] = TPE1(encoding=3, text=songInfo['songer']) id_card['TPE2'] = TPE2(encoding=3, text=songInfo['songer']) id_card['TALB'] = TALB(encoding=3, text=songInfo['album']) id_card['TCON'] = TCON(encoding=3, text=songInfo['tcon']) elif songInfo['suffix'] == '.flac': id_card['tracknumber'] = songInfo['tracknumber'] id_card['title'] = songInfo['songName'] id_card['year'] = songInfo['year'][:4] id_card['artist'] = songInfo['songer'] id_card['album'] = songInfo['album'] id_card['genre'] = songInfo['tcon'] elif songInfo['suffix'] == '.m4a': # m4a写入曲目时还需要指定总曲目数 tag = TinyTag.get(id_card.filename) trackNum = int(songInfo['tracknumber']) trackTotal = 1 if not tag.track_total else int(tag.track_total) trackTotal = max(trackNum, trackTotal) id_card['trkn'] = [(trackNum, trackTotal)] id_card['©nam'] = songInfo['songName'] id_card['©day'] = songInfo['year'][:4] id_card['©ART'] = songInfo['songer'] id_card['aART'] = songInfo['songer'] id_card['©alb'] = songInfo['album'] id_card['©gen'] = songInfo['tcon'] try: id_card.save() except MutagenError: return 0 # 保存失败返回0 else: return 1 # 保存成功返回1
def write_tags(song, data): try: tag = FLAC(song) tag.delete() images = Picture() images.type = 3 images.data = data['image'] tag.clear_pictures() tag.add_picture(images) tag['lyrics'] = data['lyric'] except FLACNoHeaderError: try: tag = File(song, easy=True) except: return tag['artist'] = data['artist'] tag['title'] = data['music'] tag['date'] = data['year'] tag['album'] = data['album'] tag['tracknumber'] = data['tracknum'] tag['discnumber'] = data['discnum'] tag['genre'] = data['genre'] tag['albumartist'] = data['ar_album'] tag['author'] = data['author'] tag['composer'] = data['composer'] tag['copyright'] = data['copyright'] tag['bpm'] = data['bpm'] tag['length'] = data['duration'] tag['organization'] = data['label'] tag['isrc'] = data['isrc'] tag['replaygain_*_gain'] = data['gain'] tag['lyricist'] = data['lyricist'] tag.save() try: audio = ID3(song) audio.add( APIC(encoding=3, mime="image/jpeg", type=3, desc=u"Cover", data=data['image'])) audio.add( USLT(encoding=3, lang=u"eng", desc=u"desc", text=data['lyric'])) audio.save() except _util.ID3NoHeaderError: pass
def get_art(self): found_art = False try: # MP3 file = File(self.path) # Access APIC frame and grab bytes art_bytes = file.tags["APIC:"].data # Create new PIL image from bytes img = Image.open(io.BytesIO(art_bytes)) found_art = True except Exception: pass try: # FLAC file = FLAC(self.path) if len(file.pictures): img = Image.open(io.BytesIO(file.pictures[0].data)) found_art = True except Exception: pass try: # MP4 file = MP4(self.path) art_bytes = file.tags["covr"][0] img = Image.open(io.BytesIO(art_bytes)) found_art = True except Exception: pass if not found_art or prefer_external: art_files = [ "folder.jpg", "folder.png", "folder.gif", "cover.png", "cover.jpg", "cover.gif", "front.jpg", "front.png", "front.gif" ] folder, filename = os.path.split(self.path) for filename in art_files: if os.path.isfile(folder + "\\" + filename): try: img = Image.open(folder + "\\" + filename) found_art = True except Exception: pass if found_art and img is not None: # Resize image img = img.resize((40, 40), Image.ANTIALIAS) else: img = self.recol_image(Image.open("res\\album_art.png"), col_fg) return ImageTk.PhotoImage(img)
def media_info_extract(self, f_path): _MEDIA_INFO = { "title": "UNKNOWN", "artist": "UNKNOWN", "album": "UNKNOWN", "shortcut": "UNKNOWN", "bitrate": "UNKNOWN" } media_info = File(f_path) if media_info.tags is not None: if media_info.tags.__contains__("APIC:"): preview = media_info.tags["APIC:"].data tmp = config.get_tmp_by_type("image") + "short.jpg" with open(tmp, "wb") as img: img.write(preview) obj_id = self.__mongo.insert_singlefile_by_path( self.__short_cut, tmp, {"belongs": os.path.split(f_path)[1]}) if obj_id: os.remove(tmp) _MEDIA_INFO["shortcut"] = obj_id if obj_id else "" if media_info.tags.__contains__("T1T2"): _MEDIA_INFO["title"] = media_info.tags["T1T2"].text[0].replace( " ", "") if media_info.tags.__contains__("TPE1"): _MEDIA_INFO["artist"] = media_info.tags["TPE1"].text[ 0].replace(" ", "") if media_info.tags.__contains__("TALB"): _MEDIA_INFO["album"] = media_info.tags["TALB"].text[0].replace( " ", "") if media_info.info is not None: if hasattr(media_info.info, "bitrate"): _MEDIA_INFO["bitrate"] = media_info.info.bitrate MEDIA_INFO = { "title": _MEDIA_INFO["title"] if _MEDIA_INFO["title"] != "" else "UNKNOWN", "artist": _MEDIA_INFO["artist"] if _MEDIA_INFO["artist"] != "" else "UNKNOWN", "album": _MEDIA_INFO["album"] if _MEDIA_INFO["album"] != "" else "UNKNOWN", "shortcut": _MEDIA_INFO["shortcut"] if _MEDIA_INFO["shortcut"] != "" else "UNKNOWN", "bitrate": _MEDIA_INFO["bitrate"] if _MEDIA_INFO["bitrate"] != "" else "UNKNOWN", "lyric": 0 } return MEDIA_INFO
def write_tags(file, data): audio = File(file, easy=True) for key, value in data.items(): if key in valid_id3_tags: audio[key] = value audio.save(file, v2_version=3) audio = File(file) albumart = get(data['cover']).content audio['APIC'] = APIC(encoding=3, mime='image/jpeg', type=3, desc=u'Cover', data=albumart) audio['TYER'] = TYER(text=data['date']) # audio['TPUB'] = TPUB(text=data['label']) # audio['TPE2'] = TPE2(text=data['album_artist']) audio.save(file, v2_version=3)
def list_albums_with_songs_longer_than_25min(library): long_tracks = OrderedDict({"issue_type": "long_tracks"}) albums = [] for band in library.bands: for album in band.albums: for track in album.tracks: file = File(track.path) if file.info.length > 1500: albums.append({"band": track.band, "album": track.album}) break long_tracks.update({"album": albums}) return long_tracks
def process_metadata(self, metadata): Log('Reading MP4 tags from: ' + self.filename) try: tags = MFile(self.filename) Log('Found tags: ' + str(tags.keys())) except: Log('An error occurred while attempting to parse the MP4 file: ' + self.filename) return # Genres try: genres = tags.get('\xa9gen') if genres is not None and len(genres) > 0: for genre in genres: for sub_genre in parse_genres(genre): sub_genre_stripped = sub_genre.strip() if sub_genre_stripped: if sub_genre_stripped not in metadata.genres: metadata.genres.add(sub_genre_stripped) except Exception, e: Log('Exception reading \xa9gen (genre): ' + str(e))
def _write_flac_tags(self, path, track, tags=None): if "DATA" in track: track = track["DATA"] if not tags: tags = self.get_track_tags(track) audio = File(path) audio.delete() pic = mutagen.flac.Picture() pic.data = tags["_albumart"]["image"] audio.clear_pictures() audio.add_picture(pic) del tags["_albumart"] for key, val in tags.items(): audio[key] = str(val) audio.save() return True
def add_flac_cover(filename, albumart): audio = File(str(filename)) image = Picture() image.type = 3 image.mime = "image/jpeg" with open(albumart, 'rb') as f: image.data = f.read() audio.add_picture(image) audio.save()
class Tagging: def __init__(self, io): """ """ try: self.fileObj = io if self.fileObj.url.rsplit('.')[-1] != 'mp3': raise ExtensionException('Not Expecting file extension') self.audio = EasyID3(self.fileObj.path) except mutagen.id3.ID3NoHeaderError as err: self.audio = File(self.fileObj.path, easy=True) self.audio.add_tags() self.audio.save(self.fileObj.path, v1=2) except (mutagen.MutagenError, ExtensionException) as err: self.audio = None def add_tag(self, tags, image): if tags is not None: for key, value in tags.items(): if value is not None or value != '': if key != 'cover': self.audio[u'{}'.format(key)] = value self.audio.save(self.fileObj.path, v1=2) if image is not None: img = image.path fileObj = open(img.path, 'rb').read() img_ext = img.name.rsplit('.')[-1] multipart = [('jpg', 'image/jpeg'), ('png', 'image/png'), ('jpeg', 'image/jpeg')] img_typ = '' for typ in multipart: if img_ext in typ: img_typ = typ[1] break id3 = ID3(self.fileObj.path) id3.add(APIC(3, img_typ, 3, 'Front Cover', fileObj)) id3.save(v2_version=3) def tags(self): tags = {} if self.audio is not None: for key, value in self.audio.items(): tags[key] = value[0] return tags
def import_track(full_path: str, track: Track = None): music_path = os.path.expanduser( settings.get_key('plugins.base.music.path')) tags = File(full_path) if tags is None: return relative_path = full_path.replace('%s/' % music_path, '') name = get_name(tags) name_sort = get_name_sort(name) artist = get_artist(get_artist_name(tags)) album_artist = get_artist(get_album_artist_name(tags)) album = get_album(get_album_name(tags), get_release_date(tags), get_genres(tags), artist, album_artist) duration = get_duration(tags) track_num = get_track_num(tags) disc_num = get_disc_num(tags) disc_name = get_disc_name(tags) format = relative_path.split('.')[-1] size = os.path.getsize(full_path) bitrate = tags.info.bitrate add = False if track is None: track = Track() add = True track.name = name track.name_sort = name_sort track.artist = artist track.album = album track.duration = duration track.track_num = track_num track.disc_num = disc_num track.disc_name = disc_name track.path = relative_path track.format = format track.bitrate = bitrate track.size = size if add: database.db.session.add(track)
def deal_mp3(root_path): names = os.listdir(root_path) for name in names: path = os.path.join(root_path, name) if os.path.isdir(path): deal_mp3(path) if path.endswith('.aac'): afile = File(path) try: title = afile.tags.get("TIT2").text[0] os.rename(path, os.path.join(os.path.dirname(path), title + '.mp3')) except AttributeError: print(path + " 标题输入不全") exit()
def process_metadata(self, metadata, episode=None): if episode == None: item = metadata else: item = episode Log('Reading MP4 tags') try: tags = File(self.filename, options=[MP4]) except Exception, e: Log('An error occurred while attempting to parse the MP4 file: ' + self.filename) Log(str(e)) return
def _parse_artist_from_tags(self): file = File(self.filename) for tag in ('TPE1', u'©ART', 'Author', 'Artist', 'artist', 'ARTIST', 'TRACK ARTIST', 'TRACKARTIST', 'TrackArtist', 'Track Artist'): try: self.artist = file[tag][0].strip() break except KeyError: pass except ValueError: pass if self.artist == '': self._parse_album_artist_from_tags()
def retag(filepath): logger.debug('Loading File: %r' % filepath) audio = File(filepath, easy=True) if audio is None: logger.debug('Invalid Audio File: %r' % filepath) else: try: artist, title = get_artist_title_from_filename(filepath) except ValueError: return try: clear_and_set_tags(audio, artist, title) except Exception: logger.debug('Invalid Audio File: %r' % filepath) logger.info('%s - %s' % (artist, title))
def __init__(self, filePath): if os.path.isfile(filePath) is False: return self._filepath = filePath self._ext = __extension__(filePath) self._handle = File(filePath) self.title = '' self.album = '' self.albumartist = '' self.artist = '' self.copyright = '' self.tracknumber = '' self.totaltrack = '' self.discnumber = '' self.totaldisc = '' self.genre = '' self.date = '' self.composer = '' self.isrc = '' self.lyrics = '' self.__load__()