def test_save(self): audio = ID3(self.filename) strings = ["one", "two", "three"] audio.add(TPE1(text=strings, encoding=3)) audio.save(v2_version=3) frame = audio["TPE1"] self.assertEqual(frame.encoding, 3) self.assertEqual(frame.text, strings) id3 = ID3(self.filename, translate=False) self.assertEqual(id3.version, (2, 3, 0)) frame = id3["TPE1"] self.assertEqual(frame.encoding, 1) self.assertEqual(frame.text, ["/".join(strings)]) # null separator, mutagen can still read it audio.save(v2_version=3, v23_sep=None) id3 = ID3(self.filename, translate=False) self.assertEqual(id3.version, (2, 3, 0)) frame = id3["TPE1"] self.assertEqual(frame.encoding, 1) self.assertEqual(frame.text, strings)
def setID3(self, lrc, info, path): tags = ID3(path) # remove old unsychronized lyrics if len(tags.getall("USLT")) != 0: tags.delall("USLT") if ('album' in info): tags.add(TALB(encoding=3, lang='', desc='', text=info['album'][0])) if ('title' in info): tags.add(TIT2(encoding=3, lang='', desc='', text=info['title'][0])) if ('artist' in info): tags.add(TPE1(encoding=3, lang='', desc='', text=info['artist'][0])) if ('cover' in info): tags.add( APIC(encoding=3, mime='image/png', type=3, desc='cover', data=requests.get(info['cover'][0], stream=True, headers=headers).raw.read())) tags.add(USLT(encoding=3, lang='eng', desc='aaa', text=lrc)) tags.save()
def finalize(self): # ID3 info: # APIC: picture # TT2: title # TPE1: artist # TRCK: track number # TALB: album # USLT: lyric cover = open(f"covers/{self.album[:9]}.jpg", 'rb').read() id3 = ID3(f'review/{self.fname}') id3.add(APIC(3, 'image/jpeg', 3, "", cover)) id3.add(TT2(encoding=3, text=f"{self.title}")) id3.add(TPE1(encoding=3, text=f"{self.artist}")) id3.add(TALB(encoding=3, text=f"{self.album}")) id3.add(USLT(encoding=3, text=f"{self.lyrics}")) id3.save(v2_version=3) # save im = Image.open(f"covers/{self.album[:9]}.jpg") width, height = im.size if width >= 500 and height >= 500: print(f"{unidecode.unidecode(self.title)} is successful. Moving to final...") shutil.move(f"review/{self.fname}", f"final/{self.title}.mp3")
def removeTag(self, filePath, tag): # filePath = os.path.join(root_dir, file_name) audio = ID3(filePath) if tag == "TIT2": audio.delall('TIT2') # TODO: to be tested later, test after removing the following line. audio.add(TIT2(encoding=3, text=u" ")) elif tag == "TALB": audio.delall('TALB') audio.add(TALB(encoding=3, text=u" ")) elif tag == "TPE1": audio.delall('TPE1') audio.add(TPE1(encoding=3, text=u" ")) elif tag == "TPE2": audio.delall('TPE2') audio.add(TPE2(encoding=3, text=u" ")) elif tag == "TSOP": audio.delall('TSOP') audio.add(TSOP(encoding=3, text=u" ")) elif tag == "TDRC": audio.delall('TDRC') audio.add(TDRC(encoding=3, text=u" ")) elif tag == "TCON": audio.delall('TCON') audio.add(TCON(encoding=3, text=u" ")) else: print("error: tag unidentified") return "error" return audio.save()
def id3_tag(path, station, station_alias, recording_time): podcast_img = PODCAST_IMG_PATH + station_alias + '.jpg' if os.path.isfile(podcast_img) is False: podcast_img = PODCAST_IMG_PATH + 'default.jpg' audio = ID3() audio.save(path) audio = ID3(path) audio.add( TIT2(encoding=3, text='{0}, {1:%d.%m.%Y, %H:%M} Uhr'.format( station, recording_time))) audio.add(TPE1(encoding=3, text=station)) audio.add(TALB(encoding=3, text='{0:%Y-%m-%d}'.format(recording_time))) audio.add( APIC(encoding=3, mime='image/jpeg', type=3, desc=u'Cover', data=open(podcast_img).read())) audio.save(v2_version=3)
def tagUpdateAll(filePath, tags): album = tags['album'] lyrics = tags['lyrics'] artist = tags['artist'] track = tags['track'] title = tags['title'] albumImage = tags['albumImage'] year = tags['year'] genre = tags['genre'] """ logger.debug( "album \t: " + album ) logger.debug( "lyrics \t: " + lyrics ) logger.debug( "artist \t: " + artist ) logger.debug( "track \t: " + track ) logger.debug( "title \t: " + title ) logger.debug( "albumImage \t: " + albumImage ) logger.debug( "year \t: " + year ) logger.debug( "genre \t: " + genre ) """ if os.path.isfile(filePath): logger.debug("파일존재 확인" + filePath) ext = filePath.split(".")[-1] if ext.upper() == "MP3": try: audio = ID3(filePath) audio.add(TALB(text=[album])) audio.add(TIT2(text=[title])) audio.add(TPE1(text=[artist])) audio.add(TRCK(text=[track])) audio.add(TYER(text=[year])) audio.add(TCON(text=[genre])) audio.add(USLT(text=lyrics, lang="kor", desc="")) from PIL import Image import requests coverFile = os.path.join(path_app_root, 'data', 'tmp', 'cover.jpg') if os.path.isfile(coverFile): os.remove(coverFile) logger.debug("albumImage : %s " , albumImage) res = requests.get(albumImage, stream=True) if "png".upper() in res.headers['Content-Type'].upper(): im = Image.open(res.raw) bg = Image.new("RGB", im.size, (255,255,255)) bg.paste(im,im) bg.save(coverFile) else: im = Image.open(res.raw) im.save(coverFile) audio.add(APIC(encoding=3, mime=res.headers['Content-Type'], type=3, desc=u'Cover', data=open(coverFile, 'rb').read())) audio.save() except ID3NoHeaderError: logger.debug("MP3 except") audio = ID3() audio.add(TALB(text=[album])) audio.add(TIT2(text=[title])) audio.add(TPE1(text=[artist])) audio.add(TRCK(text=[track])) audio.add(TYER(text=[year])) audio.add(TCON(text=[genre])) audio.add(USLT(text=[lyrics], lang="kor", desc="")) from PIL import Image import requests coverFile = os.path.join(path_app_root, 'data', 'tmp', 'cover.jpg') im = Image.open(requests.get(albumImage, stream=True).raw) if os.path.isfile(coverFile): os.remove(coverFile) im.save(coverFile) audio.add(APIC(encoding=3, mime='image/jpg', type=3, desc=u'Cover', data=open(coverFile, 'rb').read())) audio.save(filePath)
def tagUpdate(req): id = "" title = "" artist = "" album = "" if 'id' in req.form: id = int(req.form['id']) if 'title' in req.form: title = str(req.form['title']) if 'artist' in req.form: artist = str(req.form['artist']) if 'album' in req.form: album = str(req.form['album']) logger.debug('id : ' + str(id)) logger.debug('title : ' + str(title)) logger.debug('artist : ' + str(artist)) logger.debug('album : ' + str(album)) entity = ModelItem.get(id) filePath = entity.filePath logger.debug("filePath : " + filePath) if os.path.isfile(filePath): logger.debug("파일존재 확인" + filePath) ext = filePath.split(".")[-1] if ext.upper() == "MP3": try: tags = ID3(filePath) tags.add(TALB(text=[album])) tags.add(TIT2(text=[title])) tags.add(TPE1(text=[artist])) tags.save() except ID3NoHeaderError: logger.debug("MP3 except") tags = ID3() if "M4A" == ext.upper() : tags = MP4(filePath) tags['\xa9nam'][0] = title tags['\xa9ART'][0] = artist tags['\xa9alb'][0] = album tags.save() if "FLAC" == ext.upper() : tags = FLAC(filePath) tags['title'] = str(title) tags['artist'] = str(artist) tags['album'] = str(album) tags.save() logger.debug("파일처리시작" + filePath) LogicNormal.mp3FileProc(filePath) ModelItem.delete(id) ret = {} return ret else: return
seasonNum = d.entries[0].itunes_season fileName = title + ".mp3" urllib.request.urlretrieve(url,fileName) try: audio = ID3(fileName) audio.delete() audio = ID3() except ID3NoHeaderError: print("Adding ID3 header") audio = ID3() audio.add(TIT2(encoding=3,text=title)) #add title audio.add(TRCK(encoding=3,text=episodeNum)) #add track number audio.add(TPOS(encoding=3,text=seasonNum)) #add season number audio.add(TPE1(encoding=3,text=podcast['artist'])) #add artist audio.add(TPE2(encoding=3,text=podcast['album_artist'])) #add album artist audio.add(TALB(encoding=3,text=podcast['album'])) #add album audio.save(fileName) #this save function only saves the ID3 tags, it does not resave the mp3. So, if you don't have it pointed at the actual file location it will just save a text file full of metadata that will be useless elif podcast['host'] == 'art19': url = d.entries[0].links[0].href title = d.entries[0].title.rstrip() episodeNum = d.entries[0].itunes_episode seasonNum = d.entries[0].itunes_season fileName = title + ".mp3" urllib.request.urlretrieve(url,fileName) try: audio = ID3(fileName) audio.delete() audio = ID3()
def __init_id3_tags(id3, major=3): """ Attributes: id3 ID3 Tag object major ID3 major version, e.g.: 3 for ID3v2.3 """ from mutagen.id3 import TRCK, TPOS, TXXX, TPUB, TALB, UFID, TPE2, \ TSO2, TMED, TIT2, TPE1, TSRC, IPLS, TORY, TDAT, TYER id3.add(TRCK(encoding=major, text="1/10")) id3.add(TPOS(encoding=major, text="1/1")) id3.add( TXXX(encoding=major, desc="MusicBrainz Release Group Id", text="e00305af-1c72-469b-9a7c-6dc665ca9adc")) id3.add(TXXX(encoding=major, desc="originalyear", text="2011")) id3.add( TXXX(encoding=major, desc="MusicBrainz Album Type", text="album")) id3.add( TXXX(encoding=major, desc="MusicBrainz Album Id", text="e7050302-74e6-42e4-aba0-09efd5d431d8")) id3.add(TPUB(encoding=major, text="J&R Adventures")) id3.add(TXXX(encoding=major, desc="CATALOGNUMBER", text="PRAR931391")) id3.add(TALB(encoding=major, text="Don\'t Explain")) id3.add( TXXX(encoding=major, desc="MusicBrainz Album Status", text="official")) id3.add(TXXX(encoding=major, desc="SCRIPT", text="Latn")) id3.add( TXXX(encoding=major, desc="MusicBrainz Album Release Country", text="US")) id3.add(TXXX(encoding=major, desc="BARCODE", text="804879313915")) id3.add( TXXX(encoding=major, desc="MusicBrainz Album Artist Id", text=[ "3fe817fc-966e-4ece-b00a-76be43e7e73c", "984f8239-8fe1-4683-9c54-10ffb14439e9" ])) id3.add(TPE2(encoding=major, text="Beth Hart & Joe Bonamassa")) id3.add(TSO2(encoding=major, text="Hart, Beth & Bonamassa, Joe")) id3.add(TXXX(encoding=major, desc="ASIN", text="B005NPEUB2")) id3.add(TMED(encoding=major, text="CD")) id3.add( UFID(encoding=major, owner="http://musicbrainz.org", data=b"f151cb94-c909-46a8-ad99-fb77391abfb8")) id3.add(TIT2(encoding=major, text="Sinner's Prayer")) id3.add( TXXX(encoding=major, desc="MusicBrainz Artist Id", text=[ "3fe817fc-966e-4ece-b00a-76be43e7e73c", "984f8239-8fe1-4683-9c54-10ffb14439e9" ])) id3.add(TPE1(encoding=major, text=["Beth Hart & Joe Bonamassa"])) id3.add( TXXX(encoding=major, desc="Artists", text=["Beth Hart", "Joe Bonamassa"])) id3.add(TSRC(encoding=major, text=["NLB931100460", "USMH51100098"])) id3.add( TXXX(encoding=major, desc="MusicBrainz Release Track Id", text="d062f484-253c-374b-85f7-89aab45551c7")) id3.add( IPLS(encoding=major, people=[["engineer", "James McCullagh"], ["engineer", "Jared Kvitka"], ["arranger", "Jeff Bova"], ["producer", "Roy Weisman"], ["piano", "Beth Hart"], ["guitar", "Blondie Chaplin"], ["guitar", "Joe Bonamassa"], ["percussion", "Anton Fig"], ["drums", "Anton Fig"], ["keyboard", "Arlan Schierbaum"], ["bass guitar", "Carmine Rojas"], ["orchestra", "The Bovaland Orchestra"], ["vocals", "Beth Hart"], ["vocals", "Joe Bonamassa"]])), id3.add(TORY(encoding=major, text="2011")) id3.add(TYER(encoding=major, text="2011")) id3.add(TDAT(encoding=major, text="2709"))
def update_mp3(self, filename, artist=None, album=None, title=None, tracknum=None, maxtracks=None, year=None, group=None, conductor=None, composer=None): """ Updates an on-disk mp3 with the given tag data. Any passed-in variable set to None will be ignored. It's possible there could be some problems with ID3v2.3 vs. ID3v2.4 tags in here - I don't know if mutagen does an auto-convert. I think it might. If group/conductor/composer is a blank string, those fields will be completely removed from the file. Any of the other fields set to blank will leave the tag in place. Will ensure that the file's mtime is updated. """ full_filename = self.check_library_filename(filename) self.assertEqual(os.path.exists(full_filename), True) starting_mtime = int(os.stat(full_filename).st_mtime) tags = ID3(full_filename) if artist is not None: tags.delall('TPE1') tags.add(TPE1(encoding=3, text=artist)) if album is not None: tags.delall('TALB') tags.add(TALB(encoding=3, text=album)) if title is not None: tags.delall('TIT2') tags.add(TIT2(encoding=3, text=title)) if group is not None: tags.delall('TPE2') if group != '': tags.add(TPE2(encoding=3, text=group)) if conductor is not None: tags.delall('TPE3') if conductor != '': tags.add(TPE3(encoding=3, text=conductor)) if composer is not None: tags.delall('TCOM') if composer != '': tags.add(TCOM(encoding=3, text=composer)) if tracknum is not None: tags.delall('TRCK') if maxtracks is None: tags.add(TRCK(encoding=3, text=str(tracknum))) else: tags.add(TRCK(encoding=3, text='%s/%s' % (tracknum, maxtracks))) if year is not None: tags.delall('TDRC') tags.delall('TDRL') tags.delall('TYER') tags.add(TDRC(encoding=3, text=str(year))) # Save tags.save() # Check on mtime update and manually fix it if it's not updated self.bump_mtime(starting_mtime, full_filename=full_filename)
def set_artist(self, artist_name): self.media['TPE1'] = TPE1(encoding=3, text=artist_name)
def write_mp3_meta(song): id3 = ID3() id3.add(TIT2(encoding=3, text=song.song_name)) id3.add(TALB(encoding=3, text=song.album_name)) id3.add(TPE1(encoding=3, text=song.artist_name)) id3.save(song.abs_path)
def get_american_life( epno, directory = '/mnt/media/thisamericanlife', extraStuff = None, verify = True, dump = False, hardURL = None ): """ Downloads an episode of `This American Life`_ into a given directory. :param int epno: the episode number of `This American Life`_. :param str directory: the directory into which to download a `This American Life`_ episode. Default is ``/mnt/media/thisamericanlife``. :param str extraStuff: additional stuff to put into the candidate URL for `This American Life`_ episodes. Default is ``None``. :param bool verify: optional argument, whether to verify SSL connections. Default is ``True``. :param bool dump: optional argument, if ``True`` then instead of downloading first `This American Life`_, downloads the XML info as a file, named ``PRI.ThisAmericanLife.<NUM>.xml``. Default is ``False``. :param str hardURL: optional argument, the hard-coded URL for a given TAL episode, if ``epno`` does not work. .. seealso:: :py:meth:`get_americanlife_info <nprstuff.core.thisamericanlife.get_americanlife_info>`. """ try: tup = get_americanlife_info(epno, extraStuff = extraStuff, verify = verify, dump = dump, directory = directory, hardURL = hardURL ) if dump: return title, year, html = tup logging.info('TITLE = %s, YEAR = %d.' % ( title, year ) ) except ValueError as e: print(e) print('Cannot find date and title for This American Life episode #%d.' % epno) return def get_resp( html ): stupid_search_urls_because_python = list( filter(lambda item: 'href' in item.attrs and 'podtrac' in item['href'] and 'mp3' in item['href'], html.find_all('a'))) if len( stupid_search_urls_because_python ) == 0: logging.info( "ERROR, ambiguous URL for MP3 file. Exiting..." ) logging.info( "NUM URLS: %d." % len( stupid_search_urls_because_python ) ) logging.info( "URLS: %s." % '\n'.join(map(lambda item: item['href'], stupid_search_urls_because_python))) return None urlopn = stupid_search_urls_because_python[0]['href'] resp = requests.get( urlopn, stream = True, verify = verify ) if resp.ok: return resp logging.info( "TAL episode %d URL = %s not work." % ( epno, urlopn ) ) return None # if not os.path.isdir(directory): logging.info( "Error, %s is not a directory." % directory ) raise ValueError("Error, %s is not a directory." % directory) outfile = os.path.join(directory, 'PRI.ThisAmericanLife.%03d.mp3' % epno) # resp = get_resp( html ) if resp is None: logging.info( 'Error, 1st and 2nd choice URL for TAL podcasts for episode %d not working.' % epno ) urlopn = 'http://audio.thisamericanlife.org/jomamashouse/ismymamashouse/%d.mp3' % epno resp = requests.get( urlopn, stream = True, verify = verify ) if not resp.ok: print("Error, could not download This American Life episode #%d. Exiting..." % epno) return with open( outfile, 'wb') as openfile: for chunk in resp.iter_content( 1 << 16 ): openfile.write( chunk ) # mp3tags = ID3( ) mp3tags['TDRC'] = TDRC(encoding = 0, text = [ u'%d' % year ]) mp3tags['TALB'] = TALB(encoding = 0, text = [ u'This American Life' ]) mp3tags['TRCK'] = TRCK(encoding = 0, text = [ u'%d' % epno ]) mp3tags['TPE2'] = TPE2(encoding = 0, text = [ u'Ira Glass']) mp3tags['TPE1'] = TPE1(encoding = 0, text = [ u'Ira Glass']) try: mp3tags['TIT2'] = TIT2(encoding = 3, text = [ '#%03d: %s' % ( epno, title ) ] ) except: mp3tags['TIT2'] = TIT2(encoding = 3, text = [ codecs.encode('#%03d: %s' % ( epno, title ), 'utf8') ]) mp3tags['TCON'] = TCON(encoding = 0, text = [ u'Podcast']) mp3tags['APIC'] = APIC( encoding = 0, mime = 'image/png', data = requests.get( _talPICURL ).content ) mp3tags.save( outfile, v1=0 ) os.chmod( outfile, 0o644 )
def metadata_mp3_mutagen(self, path, media): from mutagen.mp3 import MP3 from mutagen.id3 import ID3, TRCK, TIT2, TPE1, TALB, TCON, TXXX, UFID, TSRC, TPUB, TMED, TRCK, TDRC, APIC try: tags = ID3(path) except Exception: """ kindf of hackish - mutagen does complain if no id3 headers - so just create some """ audio = MP3(path) audio["TIT2"] = TIT2(encoding=3, text=["Empty Title"]) audio.save() tags = ID3(path) # reset tags tags.delete() # user data if INCLUDE_USER and self.user: tags.add( TXXX(encoding=3, desc='open broadcast user', text=u'%s' % self.user.email)) # track-level metadata tags.add(TIT2(encoding=3, text=u'%s' % media.name)) tags.add( UFID(encoding=3, owner='https://openbroadcast.org', data=u'%s' % media.uuid)) tags.add( TXXX(encoding=3, desc='open broadcast API', text=u'https://%s%s' % (self.current_site.domain, media.get_api_url()))) # remove genre tags.add(TCON(encoding=3, text=u'')) tags.add(TMED(encoding=3, text=u'Digital Media')) if media.tracknumber: tags.add(TRCK(encoding=3, text=u'%s' % media.tracknumber)) if media.isrc: tags.add(TSRC(encoding=3, text=u'%s' % media.isrc)) if uuid_by_object(media, 'musicbrainz'): tags.add( UFID(encoding=3, owner='http://musicbrainz.org', data=u'%s' % uuid_by_object(media, 'musicbrainz'))) # release-level metadata if media.release: tags.add(TALB(encoding=3, text=u'%s' % media.release.name)) if media.release.catalognumber: tags.add( TXXX(encoding=3, desc='CATALOGNUMBER', text=u'%s' % media.release.catalognumber)) if media.release.releasedate: tags.add( TDRC(encoding=3, text=u'%s' % media.release.releasedate.year)) if media.release.release_country: tags.add( TXXX(encoding=3, desc='MusicBrainz Album Release Country', text=u'%s' % media.release.release_country.iso2_code)) if media.release.totaltracks and media.tracknumber: tags.add( TRCK(encoding=3, text=u'%s/%s' % (media.tracknumber, media.release.totaltracks))) if media.release.releasedate: tags.add( TDRC(encoding=3, text=u'%s' % media.release.releasedate.year)) if uuid_by_object(media.release, 'musicbrainz'): tags.add( TXXX(encoding=3, desc='MusicBrainz Album Id', text=u'%s' % uuid_by_object(media.release, 'musicbrainz'))) if media.release and media.release.main_image and os.path.exists( media.release.main_image.path): opt = dict(size=(300, 300), crop=True, bw=False, quality=80) try: image = get_thumbnailer( media.release.main_image).get_thumbnail(opt) tags.add( APIC(encoding=3, mime='image/jpeg', type=3, desc=u'Cover', data=open(image.path).read())) except: pass # artist-level metadata if media.artist: tags.add(TPE1(encoding=3, text=u'%s' % media.artist.name)) if uuid_by_object(media.artist, 'musicbrainz'): tags.add( TXXX(encoding=3, desc='MusicBrainz Artist Id', text=u'%s' % uuid_by_object(media.artist, 'musicbrainz'))) # label-level metadata if media.release and media.release.label: tags.add(TPUB(encoding=3, text=u'%s' % media.release.label.name)) tags.save(v1=0) return
def DOWNLOAD_TRACK_BANDCAMP(TRACKS, PATH_DONWLOAD): try: session = requests.Session() session.trust_env = False user_agents= session.get(TRACKS) #PARSEANDO HTML user_soup = BeautifulSoup(user_agents.content, 'html.parser') NAME_SECTION= [item for item in user_soup.find_all('div', { "id" : "name-section" })][0] try: SONG_NAME= NAME_SECTION.find('', {'class':'trackTitle'}).text.replace('\n','').strip() except: SONG_NAME= TRACKS.split('track/')[1] try: ARTIST_NAME= NAME_SECTION.find('', {'itemprop':'byArtist'}).text.replace('\n','').strip() HREF_ARTIST= [item['href'] for item in NAME_SECTION.find('', {'itemprop':'byArtist'}).find_all(href= True)] INFO_ARTISTA= '--------'.join(list(chain(*[[ARTIST_NAME], HREF_ARTIST]))) except: ARTIST_NAME='' IMG_AUDIO= LOOK_FOR_TRACKS_AND_ALBUMS_IN_URL(TRACKS) HREF_AUDIO= IMG_AUDIO['AUDIO'] HREF_IMG= IMG_AUDIO['IMG'] if not os.path.exists(PATH_DONWLOAD): os.makedirs(PATH_DONWLOAD, exist_ok=True) IMG = requests.get(HREF_IMG, allow_redirects=True) open(os.path.join(PATH_DONWLOAD, 'cover.jpg'), 'wb').write(IMG.content) #Karatula jaitsi SONG_FILE= os.path.join(PATH_DONWLOAD, SONG_NAME + '.mp3') if not os.path.exists(SONG_FILE): SONG = requests.get(HREF_AUDIO, allow_redirects=True) open(SONG_FILE, 'wb').write(SONG.content) #Fitxategiari izen generikoa jarriko diogu amaierako izenaren ordez komando hau karaktere batzuekin moskeatu egiten delako #Metadatuak gehitu audio=File(SONG_FILE) audio['TPE1'] = TPE1(encoding=3, text=ARTIST_NAME) audio['TIT2'] = TIT2(encoding=3, text=SONG_NAME) #audio['TRCK'] = TRCK(encoding=3, text=zenbakia) audio['TALB'] = TALB(encoding=3, text=os.path.split(PATH_DONWLOAD)[1]) #Karatula jarri with open(os.path.join(PATH_DONWLOAD, 'cover.jpg'), 'rb') as albumart: audio['APIC'] = APIC( encoding=3, mime='image/jpeg', type=3, desc=u'Cover', data=albumart.read() ) audio.save() else: print(SONG_NAME + ' YA HA SIDO DESCARGADA') return(TRACKS + '__DOWNLOADED') except: return(TRACKS + '__ERROR')
def copyTagsToTranscodedFileMp3(losslessFile, lossyFile): # # Copy the tags from the losslessFile (.flac) to the lossyFile. # All previous tags from the lossyFile will be deleted before the # tags from the losslessFile are copied. # from mutagen.flac import FLAC from mutagen.id3 import ID3 # Read all tags from the flac file flacFile = FLAC(losslessFile) flacFileTags = flacFile.tags # Returns a dictionary containing the flac tags # Only mp3 files with ID3 headers can be openend. # So be sure to add some tags during encoding .wav. to mp3 # Mapping from Vorbis comments field recommendations to id3v2_4_0 # For more information about vorbis field recommendations: http://reactor-core.org/ogg-tagging.html # For more information about id3v2_4_0 frames: http://www.id3.org/id3v2.4.0-frames # # Single value tags: # ALBUM -> TALB # ARTIST -> TPE1 # PUBLISHER -> TPUB # COPYRIGHT -> WCOP # DISCNUMBER -> TPOS # ISRC -> TSRC # EAN/UPN # LABEL # LABELNO # LICENSE -> TOWN # OPUS -> TIT3 # SOURCEMEDIA -> TMED # TITLE -> TIT2 # TRACKNUMBER -> TRCK # VERSION # ENCODED-BY -> TENC # ENCODING # Multiple value tags: # COMPOSER -> TCOM # ARRANGER # LYRICIST -> TEXT # AUTHOR -> TEXT # CONDUCTOR -> TPE3 # PERFORMER -> # ENSEMBLE -> TPE2 # PART -> TIT1 # PARTNUMBER -> TIT1 # GENRE -> TCON # DATE -> TDRC # LOCATION # COMMENT -> COMM # Other vorbis tags are mapped to TXXX tags mp3File = ID3(lossyFile) mp3File.delete() for key, value in flacFileTags.items(): if key == 'title': # Map to TIT2 frame from mutagen.id3 import TIT2 mp3File.add(TIT2(encoding=3, text=value)) elif key == 'album': # Map to TALB frame from mutagen.id3 import TALB mp3File.add(TALB(encoding=3, text=value)) elif key == 'artist': # Map to TPE1 frame from mutagen.id3 import TPE1 mp3File.add(TPE1(encoding=3, text=value)) elif key == 'tracknumber': # Map to TRCK frame from mutagen.id3 import TRCK mp3File.add(TRCK(encoding=3, text=value)) elif key == 'date': # Map to TDRC frame from mutagen.id3 import TDRC mp3File.add(TDRC(encoding=3, text=value)) elif key == 'genre': # Map to TCON frame from mutagen.id3 import TCON mp3File.add(TCON(encoding=3, text=value)) elif key == 'discnumber': # Map to TPOS frame from mutagen.id3 import TPOS mp3File.add(TPOS(encoding=3, text=value)) elif key == 'composer': # Map to TCOM frame from mutagen.id3 import TCOM mp3File.add(TCOM(encoding=3, text=value)) elif key == 'conductor': # Map to TPE3 frame from mutagen.id3 import TPE3 mp3File.add(TPE3(encoding=3, text=value)) elif key == 'ensemble': # Map to TPE2 frame from mutagen.id3 import TPE2 mp3File.add(TPE2(encoding=3, text=value)) elif key == 'comment': # Map to COMM frame from mutagen.id3 import COMM mp3File.add(COMM(encoding=3, text=value)) elif key == 'publisher': # Map to TPUB frame from mutagen.id3 import TPUB mp3File.add(TPUB(encoding=3, text=value)) elif key == 'opus': # Map to TIT3 frame from mutagen.id3 import TIT3 mp3File.add(TIT3(encoding=3, text=value)) elif key == 'sourcemedia': # Map to TMED frame from mutagen.id3 import TMED mp3File.add(TMED(encoding=3, text=value)) elif key == 'isrc': # Map to TSRC frame from mutagen.id3 import TSRC mp3File.add(TSRC(encoding=3, text=value)) elif key == 'license': # Map to TOWN frame from mutagen.id3 import TOWN mp3File.add(TOWN(encoding=3, text=value)) elif key == 'copyright': # Map to WCOP frame from mutagen.id3 import WCOP mp3File.add(WCOP(encoding=3, text=value)) elif key == 'encoded-by': # Map to TENC frame from mutagen.id3 import TENC mp3File.add(TENC(encoding=3, text=value)) elif (key == 'part' or key == 'partnumber'): # Map to TIT3 frame from mutagen.id3 import TIT3 mp3File.add(TIT3(encoding=3, text=value)) elif (key == 'lyricist' or key == 'textwriter'): # Map to TEXT frame from mutagen.id3 import TIT3 mp3File.add(TIT3(encoding=3, text=value)) else: #all other tags are mapped to TXXX frames # Map to TXXX frame from mutagen.id3 import TXXX mp3File.add(TXXX(encoding=3, text=value, desc=key)) mp3File.update_to_v24() mp3File.save() return
def tagFile(self, filename, metadata, art_url): if not self.file_done: return image = None if art_url is not None: self.getFile('artwork.jpg', art_url, True) try: with open('artwork.jpg', 'rb') as file: image = file.read() except: pass if filename.endswith('.mp3'): audio = MP3(filename, ID3=ID3) try: audio.add_tags() except: pass if image: audio.tags.add( APIC( encoding=3, mime='image/jpeg', type=3, desc=u'Cover', data=image ) ) audio.tags["TIT2"] = TIT2(encoding=3, text=(metadata.get('title', ''))) try: audio.tags["TPE1"] = TPE1(encoding=3, text=metadata.get('artist', '')) except: pass audio.tags["TDRC"] = TDRC(encoding=3, text=(metadata.get('year', ''))) audio.tags["TCON"] = TCON(encoding=3, text=(metadata.get('genre', ' '))) audio.save() elif filename.endswith('.flac'): audio = FLAC(filename) try: audio.add_tags() except: pass audio.tags['title'] = metadata['title'] audio.tags['artist'] = metadata['artist'] audio.tags['year'] = metadata['year'] audio.tags['genre'] = metadata['genre'] audio.tags.add( APIC( encoding=3, mime='image/jpeg', type=3, desc=u'Cover', data=image ) ) audio.save() elif filename.endswith('.m4a'): audio = MP4(filename) try: audio.add_tags() except: pass covr = [] covr.append(MP4Cover(image, MP4Cover.FORMAT_JPEG)) audio.tags['covr'] = covr audio.tags['title'] = metadata['title'] audio.tags['artist'] = metadata['artist'] #audio.tags['year'] = metadata['year'] audio.tags['genre'] = metadata['genre'] audio.save() if os.path.isfile('artwork.jpg'): os.remove('artwork.jpg')
def upload_files(): logger.name = 'bff.upload_files' logger.info("Starting process") # Config params audio_folder = config["audio_folder"] station_url = config["station_url"] creek_key = config["creek_key"] if "studio" in config.keys(): studio_filter = config['studio'] else: studio_filter = False s3_bucket_name = config['s3_bucket_name'] s3_access_key_id = config['s3_access_key_id'] s3_secret = config['s3_secret'] s3_endpoint = config['s3_endpoint'] # list missing recordings # download json missing_url = "api/broadcasts/missing_archives" full_missing_url = station_url + missing_url logger.debug("Missing archives URL: " + full_missing_url) response = urllib.request.urlopen(full_missing_url) str_response = response.read().decode('utf-8') logger.debug("string response: " + str_response) broadcasts = json.loads(str_response) logger.debug("json response: ") logger.debug(broadcasts) for broadcast in broadcasts['data'][ 'broadcasts']: # Each missing broadcast logger.debug("Working on a broadcast: ") logger.debug(broadcast) show_name = broadcast['program_title'] title = broadcast['broadcast_title'] # If a studio_filter is connfigured (add 'studio: studioa' key to config) # and this broadcast does not specifiy the same studio, skip it. if studio_filter and ("broadcast_location" in broadcast.keys()): if not broadcast['broadcast_location'] == studio_filter: logger.info( "Skipping broadcast \"{}: {}\". Recorded in `{}`. Only processing `{}`" .format(show_name, title, broadcast['broadcast_location'], studio_filter)) continue logger.info("Missing a recording for " + show_name + ", episode: " + title) local_filename = broadcast['media_basename'] # match missing recordings to local recordings start_time = broadcast['broadcast_start'] end_time = broadcast['broadcast_end'] logger.debug("Looking for files between " + start_time + " and " + end_time) # broadcast_start: "2020-10-15 10:00:00" date = start_time[0:10] #first 10 characters should be the date logger.debug("date: " + date) start_hour = int(start_time[11:13]) logger.debug("starting hour: " + str(start_hour)) start_min = int(start_time[14:16]) logger.debug("starting minute: " + str(start_min)) # broadcast_end: "2020-10-15 12:00:00" end_hour = int(end_time[11:13]) logger.debug("ending hour: " + str(end_hour)) end_min = int(end_time[14:16]) logger.debug("starting minute: " + str(end_min)) # total seconds of broadcast time_start = datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S") time_end = datetime.datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S") broadcast_seconds = (time_end - time_start).total_seconds() logger.debug("broadcast is " + str(broadcast_seconds) + " seconds long") short_broadcast_seconds = broadcast_seconds - 900 long_broadcast_seconds = broadcast_seconds + 900 logger.debug("shortest acceptable recording is " + str(short_broadcast_seconds) + " seconds and longest is " + str(long_broadcast_seconds)) #if we can find a stream recording that matches #get files from that day, should be less than 50 file_pattern = audio_folder + "stream_recording*" + date + "*" logger.debug("looking for files matching: " + file_pattern) file_names = glob.glob(file_pattern) # find matching files logger.debug("found files: ") logger.debug(file_names) if len(file_names) > 0: #found some stream recordings #we have some stream recordings to check file_names.sort() #lex sort gives us time based sort file_list = "" #initialize matching files for file_name in file_names: # stream_recording-2020-10-13_21-08-38.mp3 logger.debug("checking " + file_name) time_string = file_name[-23:-4] logger.debug("file timestamp: " + time_string) time_record = datetime.datetime.strptime( time_string, "%Y-%m-%d_%H-%M-%S") # check to see if the file has any data if os.path.getsize(file_name) <= 0: logger.error("file " + file_name + " is zero bytes! deleting.") os.remove(file_name) logger.debug("trying next file") continue # check starting times min_minus_ten = time_record - datetime.timedelta(minutes=10) min_plus_ten = time_record + datetime.timedelta(minutes=10) if (min_minus_ten <= time_start <= min_plus_ten): audio = MP3(file_name) # read in MP3 file_seconds = audio.info.length #get length of audio in seconds logger.debug("file is " + str(file_seconds) + " seconds long") if (short_broadcast_seconds <= file_seconds <= long_broadcast_seconds): logger.info( "File : " + file_name + " is the file we are looking for, copying to " + local_filename) shutil.copy2(file_name, local_filename ) #copy stream recording to new file name break if not os.path.exists( local_filename ): # no stream recordings, check for timed recordings #get files from that day, should be less than 50 file_pattern = audio_folder + "timed-recording*" + date + "*" logger.debug("looking for files matching: " + file_pattern) file_names = glob.glob(file_pattern) # find matching files logger.debug("found files: ") logger.debug(file_names) if len(file_names) < 1: logger.error("ERROR: No archives for that same day") continue #drop out of this broadcast #find specific records matching the times file_names.sort() #lex sort gives us time based sort file_list = "" #initialize matching files for file_name in file_names: # timed-recording-2020-10-15_14-00-01.mp3 logger.debug("checking " + file_name) hour = int(file_name[-12:-10]) logger.debug("hour: " + hour) minutes = int(file_name[-9:-7]) logger.debug("minutes: " + minutes) if (start_hour, start_min) <= (hour, minutes) < (end_hour, end_min): logger.debug("found a file to add: " + file_name) file_list += "file '" + file_name + "'\n" if len(file_list) < 1: logger.error("Error: No Recordings match.") continue # drop out of this broadcast # construct full show from segments logger.debug("files to process:") logger.debug(file_list) logger.debug("writing file list to disk") with open("files.txt", "w") as text_file: text_file.write(file_list) logger.debug("local filename: " + local_filename) logger.debug("writing complete file to disk") logger.debug("Calling ffmepg") p = subprocess.Popen([ 'ffmpeg', '-y', '-f', 'concat', '-safe', '0', '-protocol_whitelist', 'pipe,file', '-hide_banner', '-i', 'files.txt', '-c', 'copy', local_filename ]) logger.debug("sending file names to ffmpeg") p.wait() # should have a file, local_file, that has a complete show to play # add mp3 tags if os.path.exists(local_filename): # set mp3 tags logger.debug("Adding mp3 tag") try: tags = ID3(local_filename) except ID3NoHeaderError: logger.debug("Adding ID3 header") tags = ID3() logger.debug("Constructing tag") # title title = broadcast['broadcast_title'] tags["TIT2"] = TIT2(encoding=3, text=title) # album album = broadcast['program_title'] tags["TALB"] = TALB(encoding=3, text=album) # artist artist = broadcast['program_title'] tags["TPE1"] = TPE1(encoding=3, text=artist) logger.debug("Removing tags") tags.delete(local_filename) logger.debug("Saving tags") # v1=2 switch forces ID3 v1 tag to be written tags.save(filename=local_filename, v1=ID3v1SaveOptions.CREATE, v2_version=4) else: # we didn't make a file, nothing else to do for this broadcast continue # Upload file to S3 logger.debug("Opening connection to S3") session = boto3.session.Session() client = session.client('s3', endpoint_url="https://" + s3_endpoint, aws_access_key_id=s3_access_key_id, aws_secret_access_key=s3_secret) logger.debug("Uploading file") client.upload_file( local_filename, # Path to local file s3_bucket_name, # Name of Space broadcast['s3_object_name']) # Name for remote file logger.debug("Upload complete") # set file to public logger.debug("Setting file to public access") response = client.put_object_acl( ACL='public-read', #ACL level Bucket=s3_bucket_name, # Bucket/name of space Key=broadcast['s3_object_name']) #name for remote file # Update creek archive_url = "api/media/add_archive?key=" full_archive_url = station_url + archive_url + creek_key logger.debug("Add archives URL: " + full_archive_url) # add extra parameters to broadcast broadcast['_uploadDone'] = False broadcast['_audioFilesFound'] = None broadcast['_uploadPercent'] = None broadcast['filesize'] = os.path.getsize(local_filename) broadcast['file_format'] = 'mp3' logger.debug("ready to post to creek, broadcast: ") logger.debug(broadcast) data = urlencode(broadcast).encode() req = urllib.request.Request(full_archive_url, data=data) # this will "POST" resp = urllib.request.urlopen(req) logger.debug("Finished posting, response:") logger.debug(resp.status) # delete archives, if needed if os.path.exists(local_filename): logger.info("Removing temporary file: " + local_filename) os.remove(local_filename) # all broadcasts processed # remove files older than 3 months old_date = datetime.datetime.now() - datetime.timedelta(days=90) logger.debug("90 days ago was:") logger.debug(old_date) for dirpath, dirnames, filenames in os.walk(audio_folder): for file in filenames: curpath = os.path.join(dirpath, file) file_modified = datetime.datetime.fromtimestamp( os.path.getmtime(curpath)) logger.debug("file was modified:") logger.debug(file_modified) if old_date > file_modified: logger.info("Removing file older than 3 months: " + curpath) os.remove(curpath) logger.info("Finished process") logger.name = __name__
def setID3(baseDIR, filename, artist, title, lyric, albumID, cover_img_path): file_path = os.path.join(baseDIR, filename) audio_file = MP3(file_path, ID3=ID3) encoding=3 # 3 is for utf-8 # add CoverPicture audio_file.tags.add( APIC( encoding=encoding, mime='image/jpg', # image/jpeg or image/png type=3, # 3 is for the cover image desc=u'Cover', data=open(cover_img_path, 'rb').read() ) ) audio_file.tags.add( USLT( encoding=encoding, desc=u'Lyric', text=lyric ) ) audio_file.tags.add( TOPE( encoding=encoding, text=artist ) ) audio_file.tags.add( TPE1( encoding=encoding, text=artist ) ) audio_file.tags.add( TIT1( encoding=encoding, text=title ) ) audio_file.tags.add( TIT2( encoding=encoding, text=title ) ) audio_file.tags.add( TIPL( encoding=encoding, text=[artist] ) ) albumInfo = cc.getAlbumInfoFromMelon(albumID) if not albumInfo == None: audio_file.tags.add( TALB( encoding=encoding, text=[albumInfo['album_name']] ) ) audio_file.tags.add( TPRO( encoding=encoding, text=[albumInfo['copyright']] ) ) audio_file.tags.add( TCON( encoding=encoding, text=[albumInfo['genre']] ) ) audio_file.tags.add( TPUB( encoding=encoding, text=[albumInfo['publisher']] ) ) audio_file.tags.add( TDOR( encoding=encoding, text=[albumInfo['pub_date']] ) ) audio_file.tags.add( TDRL( encoding=encoding, text=[albumInfo['pub_date']] ) ) audio_file.save()
'').replace(' [Masstamilan.in]', '').replace( ' - Masstamilan.In', '' ).replace('[Masstamilan.in]', '').replace( ' - MassTamilan.com', '' ).replace(' - Masstamilan.in', '').replace( ' -Masstamilan.In', '').replace('Masstamilan.In', '').replace( 'masstamilan.in', '').replace( ' (masstamilan.in)', '').replace( ' - MassTamilan.org', '').replace( '-StarMusiQ.Com', '').replace( '-MassTamilan.com', '') try: id3.add(TPE1(encoding=3, text=a)) id3.add(TSOP(encoding=3, text=a)) except: print "***encoding error***" #TITLE tit2 = id3.getall('TIT2') if tit2: if tit2 == tpe1: try: id3.add(TIT2(encoding=3, text=s)) id3.add(TSOT(encoding=3, text=s)) except: print "***encoding error***" else: b = str(tit2[0]).replace(
# -*- coding: utf-8 -*- """ ラジオ音源にパーソナリティを書き込むスクリプト """ from mutagen.id3 import ID3, TALB, TPE1, TRCK, TCON from mutagen.mp3 import MP3 import mutagen.id3 import glob if __name__ == '__main__': files = glob.glob('FILEDIRECTORY/*') #ファイルの保存されたディレクトリ名を入れる with open("PERSONALITY.txt") as artfile: #各回のパーソナリティが1行ごとに書かれたテキスト artist = artfile.readlines() for track in range(len(files)): mp3 = MP3(files[track],ID3=ID3) mp3["TPE1"] = TPE1(encoding=3, text=artist[track]) #パーソナリティを書き込み mp3["TALB"] = TALB(encoding=3, text='RADIOTITLE') #番組名の書き込み mp3['TCON'] = TCON(encoding=3, text='GENRE') #ジャンル書き込み mp3["TRCK"] = TRCK(encoding=3, text=[str(track + 1)]) #トラック番号(放送回次)を書き込み mp3.save()
def main(): parser = argparse.ArgumentParser( 'Change or manipulate the ID3 tags of the audio files') parser.add_argument('--track', '-n', type=int, default=None, help='set the track number') parser.add_argument('--track-total', '-N', type=int, default=None, help='set total number of tracks') parser.add_argument('--artist', '-a', default=None, help='set the artist name') parser.add_argument('--album', '-A', default=None, help='set the album name') parser.add_argument('--title', '-t', default=None, help='set the title name') parser.add_argument('--wors', '-r', default=None, help='set the internet radio url') parser.add_argument('--year', '-Y', default=None, help='set the release year') parser.add_argument('--cover', '-c', default=None, help='set the cover image') parser.add_argument('--format', '-f', default=None, help='return the ID3 information as a formatted' '''string; the format string should containing one or more''' ''' of the following specifiers: , {track} , {artist} , {title} , {album} , {year} , {kbps} , {wors} , {len} (the length of the audio file, in seconds) , {path} (the absolute path of the file)''') parser.add_argument('--separator', '-s', default='\n', help='define the separator used to append at the end' ' of the output for each file (excluding the last' ' file)') parser.add_argument('--escape', '-e', default='', help='define the characters that should be escaped in' ' all the outputed fields') parser.add_argument('audiofile', nargs='+', help='an audio file containing the ID3 tags') args = parser.parse_args() # input section to_track = args.track to_track_total = args.track_total to_artist = args.artist to_album = args.album to_title = args.title to_wors = args.wors to_year = args.year to_cover = args.cover if to_cover is not None: cover_ext = os.path.splitext(to_cover)[1] # print("Cover path is "+to_cover) import mimetypes mimetypes.init() to_cover_mime = mimetypes.types_map[cover_ext] # print("Mime type is "+to_cover_mime) # output section outputs = [] formatstr = args.format escapepat = "" delimiter = '' for c in args.escape: esc = '' if c in r'()[]\^$.|?*+{}': esc = '\\' escapepat = escapepat + delimiter + esc + c delimiter = '|' to_escape = False if escapepat != '': to_escape = True escapepat = '(%s)' % escapepat separator = args.separator def getinfo(file_): try: return (file_.info.bitrate / 1000, int(round(file_.info.length))) except: return (0, 0) for f in args.audiofile: path = os.path.realpath(f) artist = title = album = year = wors = "" file_ = File(f) kbps, len_ = getinfo(file_) try: if (type(file_) == MP3): # add ID3 tag if it doesn't exist try: file_.add_tags() except: pass # should we set the tag in anyway? if to_track is not None or to_track_total is not None: old = (0, 0) if 'TRCK' in file_: try: old = tuple( map(int, file_['TRCK'].text[0].split('/'))) old = (old + (0, 0))[:2] except: pass if to_track is None: to_track = old[0] if to_track_total is None: to_track_total = old[1] file_['TRCK'] = TRCK( encoding=3, text='%02d' % to_track + ' / %02d' % to_track_total if to_track_total else '') if to_track == 0 and to_track_total == 0: del file_['TRCK'] if to_artist is not None: file_['TPE1'] = TPE1(encoding=3, text=to_artist) if to_album is not None: file_['TALB'] = TALB(encoding=3, text=to_album) if to_title is not None: file_['TIT2'] = TIT2(encoding=3, text=to_title) if to_wors is not None: file_['WORS'] = WORS(url=to_wors) if to_year is not None: file_['TDRL'] = TDRL(encoding=3, text=to_year) if to_cover is not None: # print('The image data is '+open(to_cover).read()) file_['APIC:'] = APIC(encoding=3, mime=to_cover_mime, type=3, data=open(to_cover).read()) file_.save() # process mp3 specific tag information track = file_['TRCK'].text[0] if 'TRCK' in file_ \ else '' artist = file_['TPE1'].text[0] if 'TPE1' in file_ \ else '' album = file_['TALB'].text[0] if 'TALB' in file_ \ else '' title = file_['TIT2'].text[0] if 'TIT2' in file_ \ else '' wors = file_['WORS'].url if 'WORS' in file_ else '' year = file_['TDRL'].text[0] if 'TDRL' in file_ else '' elif (type(file_) == MP4): # should we set the tag in anyway? if to_track is not None or to_track_total is not None: old = (0, 0) if 'trkn' in file_: try: old = tuple(map(int, file_['trkn'][0])) old = (old + (0, 0))[:2] except: pass if to_track is None: to_track = old[0] if to_track_total is None: to_track_total = old[1] file_['trkn'] = [(to_track, to_track_total)] if to_track == 0 and to_track_total == 0: del file_['trkn'] if to_artist is not None: file_['\xa9ART'] = [to_artist] if to_album is not None: file_['\xa9alb'] = [to_album] if to_title is not None: file_['\xa9nam'] = [to_title] if to_year is not None: file_['\xa9day'] = [to_year] if to_cover is not None: file_['covr'] = [open(to_cover).read()] file_.save() track = '%02d / %02d' % file_['trkn'][0] if 'trkn' in file_ \ else '' artist = file_['\xa9ART'][0] if '\xa9ART' in file_ \ else '' album = file_['\xa9alb'][0] if '\xa9alb' in file_ \ else '' title = file_['\xa9nam'][0] if '\xa9nam' in file_ \ else '' year = file_['\xa9day'][0] if '\xa9day' in file_ \ else '' except: pass reps = { 'track': track, 'artist': artist, 'title': title, 'album': album, 'year': year, "kbps": kbps, 'wors': wors, 'len': len_, 'path': path } if to_escape: for k in reps: reps[k] = re.sub(escapepat, r'\\\1', u"%s" % reps[k]) if formatstr is not None: outputs.append(formatstr.format(**reps)) output = separator.join(outputs) print(output, end='')
except Exception: year = None fname = os.path.join(root, file) try: tags = ID3(fname) tags = ID3() except ID3NoHeaderError: print("Adding ID3 header") tags = ID3() file_title = file.split('.') if file_title != None and len(file_title) != 0: file_title = file_title[1] tags["TALB"] = TALB(encoding=3, text=album_name) tags["TPE1"] = TPE1(encoding=3, text=artist) if args.skip_titles == 0: tags["TIT2"] = TIT2(encoding=3, text=file_title) if year != None: tags["DATE"] = TRCK(encoding=3, text=year) tags.save(fname) # print(fname.split('/')[-1], album_name, artist, year) # pprint.pprint(directories) for direc in directories: directory = directories[direc] directory.sort() track_number = 1 tracks_p = direc + '/tracks.txt'
def download(self): """ Starts the download process for this track. Also writes the file and applies ID3 tags if specified. Requires the track to have been prepared by the prepare method beforehand. """ if not self.album: safe_print('\nWriting file to {}'.format(self.output)) # Clean up the main title. if not self.short: clean_title = format_information(self.title, self.artist, self.album, self.index) else: clean_title = short_information(self.title, self.index) # Download the file. status = download_file(self.mp3_url, self.output, clean_title + ".mp3", verbose=self.verbose, silent=self.silent, sleep=self.sleep) # Abort further processes if we receive an error status code. if not status or status > 2: if not self.silent: print('\nFailed to download the file. Error code {}'.format( status)) return status # Write ID3 tags if the id3_enabled is true. if self.id3_enabled: # Fix ID3 tags. Create ID3 tags if not present. try: tags = ID3( os.path.join(self.output, safe_filename(clean_title + ".mp3"))) except ID3NoHeaderError: tags = ID3() # Title and artist tags. Split the title if it contains the artist tag. if " - " in self.title: split_title = str(self.title).split(" - ", 1) tags["TPE1"] = TPE1(encoding=3, text=str(split_title[0])) tags["TIT2"] = TIT2(encoding=3, text=str(split_title[1])) else: tags["TIT2"] = TIT2(encoding=3, text=str(self.title)) tags["TPE1"] = TPE1(encoding=3, text=str(self.artist)) # Album tag. Make sure we have it. if self.album: tags["TALB"] = TALB(encoding=3, text=str(self.album)) # Track index tag. if self.index: tags["TRCK"] = TRCK(encoding=3, text=str(self.index)) # Track date. if self.date: tags["TDRC"] = TDRC(encoding=3, text=str(self.date)) # Album artist if not self.album_artist: self.album_artist = self.artist tags["TPE2"] = TPE2(encoding=3, text=str(self.album_artist)) # Retrieve the base page URL. base_url = "{}//{}".format( str(self.url).split("/")[0], str(self.url).split("/")[2]) # Add the Bandcamp base comment in the ID3 comment tag. tags["COMM"] = COMM(encoding=3, lang='XXX', desc=u'', text=u'Visit {}'.format(base_url)) # Save all tags to the track. tags.save( os.path.join(self.output, safe_filename(clean_title + ".mp3"))) # Download artwork if it is enabled. if self.art_enabled: status = download_file(self.art_url, self.output, clean_title + self.art_url[-4:]) if status == 1: if self.verbose: safe_print('\nSaved track art to {}{}{}'.format( self.output, clean_title, self.art_url[-4:])) elif status == 2: if self.verbose: print('\nArtwork already found.') elif not self.silent: print('\nFailed to download the artwork. Error code {}'.format( status))
def set_MP3_data(SONG_INFO, is_quiet, song_path, choice): """ Set the meta data if the passed data is mp3. """ # A variable to see if cover image was added. IS_IMG_ADDED = False try: # If more than one choice then call getChoice option = 0 if len(SONG_INFO) > 1: if not is_quiet: option = getChoice(SONG_INFO, 'metadata') elif choice is not None and choice in range(1, len(SONG_INFO)): option = choice SONG_PATH = os.path.join(defaults.DEFAULT.SONG_TEMP_DIR, song_path) audio = MP3(SONG_PATH, ID3=ID3) data = ID3(SONG_PATH) # Download the cover image, if failed, pass if dwCover(SONG_INFO, option): imagedata = open(defaults.DEFAULT.COVER_IMG, 'rb').read() data.add(APIC(3, 'image/jpeg', 3, 'Front cover', imagedata)) # REmove the image os.remove(defaults.DEFAULT.COVER_IMG) IS_IMG_ADDED = True # If tags are not present then add them try: audio.add_tags() except Exception: pass audio.save() option = int(option) data.add(TYER(encoding=3, text=SONG_INFO[option].release_date)) data.add(TIT2(encoding=3, text=SONG_INFO[option].track_name)) data.add(TPE1(encoding=3, text=SONG_INFO[option].artist_name)) data.add(TALB(encoding=3, text=SONG_INFO[option].collection_name)) data.add(TCON(encoding=3, text=SONG_INFO[option].primary_genre_name)) data.add(TRCK(encoding=3, text=str(SONG_INFO[option].track_number))) data.save() defaults.DEFAULT.SONG_NAME_TO_SAVE = SONG_INFO[ option].track_name + '.mp3' # Rename the downloaded file os.rename( SONG_PATH, os.path.join(defaults.DEFAULT.SONG_TEMP_DIR, defaults.DEFAULT.SONG_NAME_TO_SAVE)) return option, IS_IMG_ADDED except Exception as e: logger.debug("{}".format(e)) return e, False
def add_mp3(self, path='', filename='file.mp3', artist='', album='', title='', tracknum=0, maxtracks=None, year=0, yeartag='TDRC', group='', conductor='', composer='', basefile='silence-vbr.mp3', save_as_v23=False, apply_tags=True): """ Adds a new mp3 with the given parameters to our library. Pass in ``save_as_v23`` as ``True`` to have the file save with an ID3v2.3 tag, instead of ID3v2.4. One of the main tag-level changes which will happen there is conversion of the year tag to TYER, which we'll otherwise not be specifying directly. ``yeartag`` is effectively ignored when ``save_as_v23`` is True. Pass in ``False`` for ``apply_tags`` to only use whatever tags happen to be present in the source basefile. Returns the full filename of the added file. """ full_filename = self.add_file(basefile, filename, path=path) # Finish here if we've been told to. if not apply_tags: return full_filename # Apply the tags as specified tags = ID3() tags.add(TPE1(encoding=3, text=artist)) tags.add(TALB(encoding=3, text=album)) tags.add(TIT2(encoding=3, text=title)) if group != '': tags.add(TPE2(encoding=3, text=group)) if conductor != '': tags.add(TPE3(encoding=3, text=conductor)) if composer != '': tags.add(TCOM(encoding=3, text=composer)) if maxtracks is None: tags.add(TRCK(encoding=3, text=str(tracknum))) else: tags.add(TRCK(encoding=3, text='%s/%s' % (tracknum, maxtracks))) if yeartag == 'TDRL': tags.add(TDRL(encoding=3, text=str(year))) elif yeartag == 'TDRC': tags.add(TDRC(encoding=3, text=str(year))) else: raise Exception('Unknown year tag specified: %s' % (yeartag)) # Convert to ID3v2.3 if requested. if save_as_v23: tags.update_to_v23() # Save to our filename tags.save(full_filename) # Return return full_filename
def add_artist(self, data): self.music = ID3(self.filename) self.music.add(TPE1(encoding=3, text=data)) self.music.save()
def Utils_Meta_setMusicInfo(path, info): """ TODO: Write lyrics to file :param path:文件目录 :param info:字典,详情: { "TALB": "Name of Album", "TIT2": "Title", "TPE1": "Author,Separate with '/'", "APIC": "Path to cover photo", "STRICT": Boolean:strict cover mode, "TRANSCODE": Boolean:convert to mp3, "TRANSPATH": "Path to converted file" } :return: int { 0: Nothing need done 1: Need reExt } """ status_code = 0 try: id3 = ID3(path) id3.update_to_v23() id3.delall("TALB") id3.delall("TIT2") id3.delall("TPE1") id3.delall("APIC") id3.add(TALB(encoding=3, text=info["TALB"])) id3.add(TIT2(encoding=3, text=info["TIT2"])) id3.add(TPE1(encoding=3, text=info["TPE1"])) if info["STRICT"]: image = Image.open(info["APIC"]) img_bytes = io.BytesIO() if image.size[0] > image.size[1]: image = image.crop( (int((image.size[0] - image.size[1]) / 2), 0, int((image.size[0] + image.size[1]) / 2), image.size[1])) elif image.size[0] < image.size[1]: image = image.crop((0, int( (image.size[1] - image.size[0]) / 2), 0, int((image.size[0] + image.size[1]) / 2))) image.resize((300, 300)).save(img_bytes, format="JPEG") id3.add( APIC(encoding=0, mime=mimetypes.guess_type(info["APIC"])[0], type=6, data=img_bytes.getvalue())) else: with open(info["APIC"], "rb") as f: id3.add( APIC(encoding=0, mime=mimetypes.guess_type(info["APIC"])[0], type=6, data=f.read())) id3.save() except ID3NoHeaderError: traceback.print_exc() ext = os.path.splitext(path)[1] if ".flac" in ext or ".FLAC" in ext: flac = FLAC(path) flac.tags['TITLE'] = info["TIT2"] flac.tags['ALBUM'] = info["TALB"] flac.tags['ARTIST'] = info["TPE1"] with open(info["APIC"], "rb") as f: image = Image.open(info["APIC"]) p = Picture() p.data = f.read() p.type = 3 p.mime = mimetypes.guess_type(info["APIC"])[0] p.width = image.size[0] p.height = image.size[1] p.depth = 24 # color depth flac.add_picture(p) image.close() flac.save() else: try: mp4 = MP4(path) mp4.tags["\xa9alb"] = info["TALB"] mp4.tags["\xa9nam"] = info["TIT2"] mp4.tags["\xa9ART"] = info["TPE1"] with open(info["APIC"], "rb") as f: mp4["covr"] = [ MP4Cover(f.read(), imageformat=MP4Cover.FORMAT_PNG) ] mp4.save() status_code = 1 except Exception: traceback.print_exc() if info["TRANSCODE"]: if not os.path.exists(os.path.split(info["TRANSPATH"])[0]): os.makedirs(os.path.split(info["TRANSPATH"])[0]) Utils_FormatTools.Utils_Format_autoTranscode( path, info["TRANSPATH"]) info["TRANSCODE"] = False Utils_Meta_setMusicInfo(info["TRANSPATH"], info) except MutagenError: traceback.print_exc() return status_code
def setData(SONG_INFO, is_quiet): """Add the metadata to the song.""" # A variable to see if cover image was added. IS_IMG_ADDED = False try: # If more than one choice then call getChoice if len(SONG_INFO) > 1 and not is_quiet: option = getChoice(SONG_INFO, 'metadata') else: option = 0 SONG_PATH = os.path.join(defaults.DEFAULT.SONG_TEMP_DIR, 'ytmdl_temp.mp3_new.mp3') audio = MP3(SONG_PATH, ID3=ID3) data = ID3(SONG_PATH) # Download the cover image, if failed, pass if dwCover(SONG_INFO, option): imagedata = open(defaults.DEFAULT.COVER_IMG, 'rb').read() data.add(APIC(3, 'image/jpeg', 3, 'Front cover', imagedata)) # REmove the image os.remove(defaults.DEFAULT.COVER_IMG) IS_IMG_ADDED = True # If tags are not present then add them try: audio.add_tags() except Exception: pass audio.save() option = int(option) data.add(TYER(encoding=3, text=SONG_INFO[option].release_date)) data.add(TIT2(encoding=3, text=SONG_INFO[option].track_name)) data.add(TPE1(encoding=3, text=SONG_INFO[option].artist_name)) data.add(TALB(encoding=3, text=SONG_INFO[option].collection_name)) data.add(TCON(encoding=3, text=SONG_INFO[option].primary_genre_name)) data.add(TRCK(encoding=3, text=str(SONG_INFO[option].track_number))) data.save() defaults.DEFAULT.SONG_NAME_TO_SAVE = SONG_INFO[ option].track_name + '.mp3' # Rename the downloaded file os.rename( SONG_PATH, os.path.join(defaults.DEFAULT.SONG_TEMP_DIR, defaults.DEFAULT.SONG_NAME_TO_SAVE)) # Show the written stuff in a better format prepend.PREPEND(1) print('================================') print(' || YEAR: ' + SONG_INFO[option].release_date) print(' || TITLE: ' + SONG_INFO[option].track_name) print(' || ARITST: ' + SONG_INFO[option].artist_name) print(' || ALBUM: ' + SONG_INFO[option].collection_name) print(' || GENRE: ' + SONG_INFO[option].primary_genre_name) print(' || TRACK NO: ' + str(SONG_INFO[option].track_number)) if IS_IMG_ADDED: print(' || ALBUM COVER ADDED') prepend.PREPEND(1) print('================================') return option except Exception: return False
quantityOfMp3s = len(list_of_mp3s) if quantityOfMp3s != len(songs): print('ERROR: The number of files mismatch.') quit() newFileNames = [] for song in songs: new_file_name = song['#'] + '-' + FixFileName(song['Title']) + '.mp3' newFileNames.append(new_file_name) for i in range(quantityOfMp3s): filename = list_of_mp3s[i] audio = ID3(filename) audio.delete() audio.add(TPE1(encoding=3, text=artist)) audio.add(TALB(encoding=3, text=album)) audio.add(TDRC(encoding=3, text=year)) audio.add(TCON(encoding=3, text=genre)) audio.add(TRCK(encoding=3, text=str(i + 1))) audio.add(TIT2(encoding=3, text=songs[i]['Title'])) audio.add( APIC(encoding=3, mime=u'image/jpg', type=3, desc=u'Front cover', data=open(u'folder666.jpg', 'rb').read())) audio.save(filename) os.rename(filename, newFileNames[i]) os.remove('folder666.jpg') print('\nTaged and renamed {0} files.'.format(quantityOfMp3s)) # add lyrics