示例#1
0
def write_id3(mp3_file, track, cover=None):
    t = mp3.Open(mp3_file)
    if not t.tags:
        t.add_tags()

    album = track['albums'][0]

    t_add = t.tags.add
    t_add(id3.TIT2(encoding=3, text=track['title']))
    t_add(id3.TPE1(encoding=3, text=track['artists']))
    t_add(id3.TCOM(encoding=3, text=track[FLD_COMPOSERS]))
    t_add(id3.TALB(encoding=3, text=album['title']))

    if 'labels' in album:
        t_add(id3.TPUB(encoding=3,
                       text=', '.join(l['name'] for l in album['labels'])))
    if FLD_TRACKNUM in track:
        tnum = '{}/{}'.format(track[FLD_TRACKNUM], album['trackCount'])
        t_add(id3.TRCK(encoding=3, text=tnum))
    if FLD_VOLUMENUM in album:
        t_add(id3.TPOS(encoding=3, text=str(album[FLD_VOLUMENUM])))
    if 'year' in album:
        t_add(id3.TDRC(encoding=3, text=str(album['year'])))
    if args.genre:
        t_add(id3.TCON(encoding=3, text=album['genre'].title()))
    if cover:
        t_add(id3.APIC(encoding=3, desc='', mime=cover.mime,
                       type=3, data=cover.data))

    t.tags.update_to_v23()
#id3.ID3v1SaveOptions.CREATE = 2
    t.save(v1=2, v2_version=3)
示例#2
0
    def save(self):
        if self.clr:
            for file in self.audiofiles:
                tmp = mid3.ID3(file)
                tmp.clear()
                tmp.add(mid3.TIT2(text=""))  # title frame
                tmp.add(mid3.TPE1(text=""))  # artist frame
                tmp.add(mid3.TALB(text=""))  # album frame
                tmp.add(mid3.TPE2(text=""))  # album artist frame
                tmp.add(mid3.TCOM(text=""))  # composer frame
                tmp.add(mid3.TCON(text=""))  # genre frame
                tmp.add(mid3.TDRC(text=""))  # date frame
                tmp.add(mid3.TRCK(text=""))  # tracknumber frame
                tmp.add(mid3.TPOS(text=""))  # discnumber frame
                tmp.add(mid3.TBPM(text=""))  # bpm frame
                tmp.save()

        if self.artwork:
            with open(self.artwork, 'rb') as albumart:
                for file in self.audiofiles:
                    tmp = mid3.ID3(file)
                    tmp['APIC'] = mid3.APIC(
                        encoding=3,
                        mime='image/jpeg',
                        type=3, desc=u'Cover',
                        data=albumart.read()
                    )
                    tmp.save()
                    albumart.seek(0)

        for file in self.audiofiles:
            tmp = EasyID3(file)
            for tag in self.__sets:
                if self.__sets[tag]:
                    tmp[tag] = self.__sets[tag]
                    tmp.save()
示例#3
0
    def __update_tag(self, download_dir, audio_file, image_file,
                     song_title=None, album_title=None, album_artist=None, album_composer=None,
                     track_number=-1, process_index=-1, process_total=-1):
        """
        The function that update audio metadata for each song.

        :param str download_dir: Download directory
        :param str audio_file: Path to audio file
        :param str image_file: Path to image file
        :param str song_title: Song title
        :param str album_title: Album title to be saved in metadata
        :param str album_artist: Album artist to be saved in metadata
        :param str album_composer: Album composer to be saved in metadata
        :param int track_number: track number to be saved in metadata
        :param int process_index: Current process index displayed in log message
        :param int process_total: Total number of process displayed in log message
        """

        if audio_file is None:
            logger.warning('[Process:{}/{}][Track:{}] Could not update metadata because there is no data found on the playlist. The video may be private or deleted.'.format(process_index, process_total, track_number))
            return

        if process_index > 0 and process_total > 0:

            if track_number > 0:
                log_prefix = '[Process:{}/{}][Track:{}]'.format(process_index, process_total, track_number)

            else:
                log_prefix = '[Process:{}/{}]'.format(process_index, process_total)

        else:
            log_prefix = ''

        audio_filename = os.path.basename(audio_file)

        try:
            # Validate audio data
            if not os.path.isfile(audio_file):
                raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), audio_file)

            audio_mime_type = mimetypes.guess_type(audio_file)

            if contains_at_least(audio_mime_type, ['audio/x-mp4', 'audio/x-m4a', 'audio/mp4a-latm']):

                # For more info about mp4 tag is available at
                # https://github.com/quodlibet/mutagen/blob/cf399dc58940fb1356f672809d763be9e2af0033/mutagen/mp4/__init__.py
                # http://atomicparsley.sourceforge.net/mpeg-4files.html
                mp4_data = mp4.MP4(audio_file)
                # Track Number
                if not self.no_track_number and track_number > 0:
                    mp4_data['trkn'] = [(track_number, 0)]
                # Cover image
                if not self.no_artwork:
                    image_data = self.__get_tag_image(image_file, audio_mime_type)
                    if image_data:
                        mp4_data['covr'] = [image_data]
                # Album title
                if not self.no_album_title and album_title is not None:
                    mp4_data['\xa9alb'] = album_title
                # Album artist
                if not self.no_album_artist and album_artist is not None:
                    mp4_data['aART'] = album_artist
                # Composer
                if not self.no_composer and album_composer is not None:
                    mp4_data['\xa9wrt'] = album_composer
                # Part of compilation
                if not self.no_compilation:
                    mp4_data['cpil'] = True
                # Save
                mp4_data.save()

            elif contains_at_least(audio_mime_type, ['audio/x-mp3', 'audio/mpeg']):

                # For more info about ID3v2 tag is available at
                # https://github.com/quodlibet/mutagen/blob/4a5d7d17f1a611280cc52d229aa70b77ca3c55dd/mutagen/id3/_frames.py
                # https://help.mp3tag.de/main_tags.html
                mp3_data = id3.ID3(audio_file)
                # Cover image
                if not self.no_artwork:
                    image_data = self.__get_tag_image(image_file, audio_mime_type)
                    if image_data:
                        mp3_data['APIC'] = image_data
                # Track number
                if not self.no_track_number and track_number > 0:
                    mp3_data.add(id3.TRCK(encoding=3, text=['{}/{}'.format(track_number, 0)]))
                # Album title
                if not self.no_album_title and album_title is not None:
                    mp3_data["TALB"] = id3.TALB(encoding=0, text=album_title)
                # Album artist
                if not self.no_album_artist and album_artist is not None:
                    mp3_data["TPE2"] = id3.TPE2(encoding=0, text=album_artist)
                # Composer
                if not self.no_composer and album_composer is not None:
                    mp3_data["TCOM"] = id3.TCOM(encoding=0, text=album_composer)
                # Part of compilation
                if not self.no_compilation:
                    mp3_data['TCMP'] = id3.TCMP(encoding=0, text=['1'])
                # Save
                mp3_data.save()

            elif contains_at_least(audio_mime_type, ['audio/x-aac']):

                # TODO: Add AAC support
                pass
                # image_data = __get_tag_image(image_file, audio_mime_type)
                # aac_data = aac.AAC(audio_file)
                # if not self.no_track_number:
                #     if track_number > 0 and track_total > 0:
                #         aac_data.add_tags(id3.TRCK(encoding=3, text=['{}/{}'.format(track_number, track_total)]))
                #         # mp3_data['TRCK'] = id3.TRCK(encoding=3, text=[str(track_number)])
                # if image_data:
                #     mp3_data['APIC'] = image_data
                #     aac_data.save()

            elif contains_at_least(audio_mime_type, ['audio/x-flac']):

                # https://github.com/quodlibet/mutagen/blob/a1db79ece62c4e86259f15825e360d1ce0986a22/mutagen/flac.py
                # https://github.com/quodlibet/mutagen/blob/4a5d7d17f1a611280cc52d229aa70b77ca3c55dd/tests/test_flac.py

                flac_data = flac.FLAC(audio_file)
                # Artwork
                if not self.no_artwork:
                    image_data = self.__get_tag_image(image_file, audio_mime_type)
                    if image_data:
                        flac_data.add_picture(image_data)
                # Save
                flac_data.save()

                flac_data = File(audio_file)
                # Track number
                if not self.no_track_number and track_number > 0:
                    flac_data.tags['tracknumber'] = str(track_number)
                # Album title
                if not self.no_album_title and album_title is not None:
                    flac_data.tags['album'] = album_title
                # Album artist
                if not self.no_album_artist and album_artist is not None:
                    flac_data.tags['albumartist'] = album_artist
                # Composer
                if not self.no_composer and album_composer is not None:
                    flac_data.tags['composer'] = album_composer
                # Part of compilation
                if not self.no_compilation:
                    pass
                # Save
                flac_data.save()
                # audio = File(audio_file, easy=True)

            else:
                raise InvalidMimeTypeException("Invalid audio format.", audio_mime_type)

            # Remove artwork if succeeded
            if os.path.exists(image_file):
                os.remove(image_file)

            # Rename filename from id to title
            dest_audio_file = os.path.join(download_dir, '{}.{}'.format(song_title, self.audio_codec))
            os.rename(audio_file, dest_audio_file)

            dest_audio_filename = os.path.basename(dest_audio_file)
            logger.info('{}[File:{}] Updated.'.format(log_prefix, dest_audio_filename))

        except FileNotFoundError:
            message = 'File not found. Skipped.'
            logger.warning('{}[File:{}] {}'.format(log_prefix, audio_filename, message))

        except InvalidDataException as e:
            message = e.message + ' Skipped.'
            logger.warning('{}[File:{}] {}'.format(log_prefix, audio_filename, message))

        except InvalidMimeTypeException as e:
            message = e.message + ' Skipped.'
            logger.warning('{}[File:{}] {}'.format(log_prefix, audio_filename, message))

        except Exception as e:
            message = 'Error {}: {} Skipped.'.format(type(e), str(e))
            logger.error('{}[File:{}] {}'.format(log_prefix, audio_filename, message))
示例#4
0
 def _write_tags(self, tags):
     for tag, value in tags.items():
         if tag == "releaseName" or tag == "release_name" or tag == "TALB":
             self._add_tag(id3.TALB(encoding=UTF_8, text=value))
         elif tag == "front_cover" or tag == "APIC_FRONT":
             mime, desc, data = value
             self._add_tag(id3.APIC(UTF_8, mime, FRONT_COVER, desc, data))
         elif tag == "backCover" or tag == "APIC_BACK":
             mime, desc, data = value
             self._add_tag(id3.APIC(UTF_8, mime, BACK_COVER, desc, data))
         elif tag == "lead_performer" or tag == "TPE1":
             self._add_tag(id3.TPE1(encoding=UTF_8, text=value))
         elif tag == "lead_performer_region" or tag == "TXXX_LEAD_PERFORMER_REGION":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8,
                          desc="LEAD-PERFORMER-REGION:UN/LOCODE",
                          text=value))
         elif tag == "lead_performer_date_of_birth" or tag == "TXXX_LEAD_PERFORMER_DATE_OF_BIRTH":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8,
                          desc="LEAD-PERFORMER-DATE-OF-BIRTH",
                          text=value))
         elif tag == "guestPerformers" or tag == "TMCL":
             self._add_tag(id3.TMCL(encoding=UTF_8, people=value))
         elif tag == "label_name" or tag == "TOWN":
             self._add_tag(id3.TOWN(encoding=UTF_8, text=value))
         elif tag == "catalogNumber" or tag == "TXXX_CATALOG_NUMBER":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8, desc="Catalog Number",
                          text=value))
         elif tag == "upc" or tag == "TXXX_UPC":
             """ Deprecated and replaced with BARCODE """
             self._add_tag(id3.TXXX(encoding=UTF_8, desc="UPC", text=value))
         elif tag == "barcode" or tag == "TXXX_BARCODE":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8, desc="BARCODE", text=value))
         elif tag == "recording_time" or tag == "TDRC":
             self._add_tag(
                 id3.TDRC(encoding=UTF_8, text=[id3.ID3TimeStamp(value)]))
         elif tag == "releaseTime" or tag == "TDRL":
             self._add_tag(
                 id3.TDRL(encoding=UTF_8, text=[id3.ID3TimeStamp(value)]))
         elif tag == "originalReleaseTime" or tag == "TDOR":
             self._add_tag(
                 id3.TDOR(encoding=UTF_8, text=[id3.ID3TimeStamp(value)]))
         elif tag == "tagging_time" or tag == "TDTG":
             self._add_tag(
                 id3.TDTG(encoding=UTF_8, text=[id3.ID3TimeStamp(value)]))
         elif tag == "recordingStudios" or tag == "TXXX_RECORDING_STUDIO":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8,
                          desc="Recording Studio",
                          text=value))
         elif tag == "TIPL":
             self._add_tag(id3.TIPL(encoding=UTF_8, people=value))
         elif tag == "comments" or tag == "COMM":
             text, lang = value
             self._add_tag(
                 id3.COMM(encoding=UTF_8, text=text, desc="", lang=lang))
         elif tag == "track_title" or tag == "TIT2":
             self._add_tag(id3.TIT2(encoding=UTF_8, text=value))
         elif tag == "version_info" or tag == "TPE4":
             self._add_tag(id3.TPE4(encoding=UTF_8, text=value))
         elif tag == "featured_guest" or tag == "TXXX_FEATURED_GUEST":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8, desc="Featured Guest",
                          text=value))
         elif tag == "lyricist" or tag == "TEXT":
             self._add_tag(id3.TEXT(encoding=UTF_8, text=value))
         elif tag == "composer" or tag == "TCOM":
             self._add_tag(id3.TCOM(encoding=UTF_8, text=value))
         elif tag == "publisher" or tag == "TPUB":
             self._add_tag(id3.TPUB(encoding=UTF_8, text=value))
         elif tag == "isrc" or tag == "TSRC":
             self._add_tag(id3.TSRC(encoding=UTF_8, text=value))
         elif tag == "labels" or tag == "TXXX_TAGS":
             self._add_tag(id3.TXXX(encoding=UTF_8, desc="Tags",
                                    text=value))
         elif tag == "isni" or tag == "TXXX_ISNI_Joel_Miller":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8,
                          desc="ISNI:Joel Miller",
                          text=value))
         elif tag == "TXXX_ISNI_Rebecca_Ann_Maloy":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8,
                          desc="ISNI:Rebecca Ann Maloy",
                          text=value))
         elif tag == "TXXX_IPI_Joel_Miller":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8,
                          desc="IPI:Joel Miller",
                          text=value))
         elif tag == "TXXX_IPI_Rebecca_Ann_Maloy":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8,
                          desc="IPI:Rebecca Ann Maloy",
                          text=value))
         elif tag == "TXXX_ISNI":
             self._add_tag(id3.TXXX(encoding=UTF_8, desc="ISNI",
                                    text=value))
         elif tag == "iswc" or tag == "TXXX_ISWC":
             self._add_tag(id3.TXXX(encoding=UTF_8, desc="ISWC",
                                    text=value))
         elif tag == "lyrics" or tag == "USLT":
             text, lang = value
             self._add_tag(
                 id3.USLT(encoding=UTF_8, text=text, desc="", lang=lang))
         elif tag == "language" or tag == "TLAN":
             self._add_tag(id3.TLAN(encoding=UTF_8, text=value))
         elif tag == "primary_style" or tag == "TCON":
             self._add_tag(id3.TCON(encoding=UTF_8, text=value))
         elif tag == "compilation" or tag == "TCMP":
             self._add_tag(id3.TCMP(encoding=UTF_8, text=value))
         elif tag == "tagger" or tag == "TXXX_TAGGER":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8, desc="TAGGER", text=value))
         elif tag == "TXXX_Tagger":
             """ Deprecated and replaced with separate TAGGER and VERSION tags """
             self._add_tag(
                 id3.TXXX(encoding=UTF_8, desc="Tagger", text=value))
         elif tag == "tagger_version" or tag == "TXXX_TAGGER_VERSION":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8, desc="TAGGER_VERSION",
                          text=value))
         elif tag == "TXXX_Tagging_Time":
             """ Deprecated and replaced with TAGGING_TIME """
             self._add_tag(
                 id3.TXXX(encoding=UTF_8, desc="Tagging Time", text=value))
         elif tag == "TXXX_TAGGING_TIME":
             """ Deprecated and replaced with TDTG """
             self._add_tag(
                 id3.TXXX(encoding=UTF_8, desc="TAGGING_TIME", text=value))
         elif tag == "TXXX_PRODUCTION_COMPANY":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8,
                          desc="PRODUCTION-COMPANY",
                          text=value))
         elif tag == "TXXX_PRODUCTION_COMPANY_REGION":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8,
                          desc="PRODUCTION-COMPANY-REGION:UN/LOCODE",
                          text=value))
         elif tag == "TXXX_RECORDING_STUDIO_REGION":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8,
                          desc="RECORDING-STUDIO-REGION:UN/LOCODE",
                          text=value))
         elif tag == "TXXX_RECORDING_STUDIO_ADDRESS":
             self._add_tag(
                 id3.TXXX(encoding=UTF_8,
                          desc="RECORDING-STUDIO-ADDRESS",
                          text=value))
         elif tag == "TRCK":
             self._add_tag(id3.TRCK(encoding=UTF_8, text=value))
         else:
             raise AssertionError("Knows nothing about '{0}'".format(tag))
示例#5
0
    try:
        url = api.get_stream_url(trackIDs[0])
        urlretrieve(url, filePath)
    except:
        print("Error occurred downloading trackID " + trackIDs[0] +
              ". Skipping...")
        del trackIDs[0]
        continue
    errorTrack = 0
    mp3File = File(filePath)
    mp3File.add_tags()
    mp3File.tags.add(id3.TIT2(encoding=3, text=id3Title))
    mp3File.tags.add(id3.TALB(encoding=3, text=id3Album))
    mp3File.tags.add(id3.TPE1(encoding=3, text=id3Artist))
    mp3File.tags.add(id3.TPE2(encoding=3, text=id3AlbumArtist))
    mp3File.tags.add(id3.TCOM(encoding=3, text=id3Composer))
    if id3Genre:
        mp3File.tags.add(id3.TCON(encoding=3, text=id3Genre))
    if id3Year:
        mp3File.tags.add(id3.TYER(encoding=3, text=id3Year))
    mp3File.tags.add(id3.TRCK(encoding=3, text=id3TrackNumber))
    mp3File.tags.add(id3.TPOS(encoding=3, text=id3DiscNumber))
    if id3AlbumCover:
        mp3File.tags.add(
            id3.APIC(mime='image/jpeg',
                     type=3,
                     desc=u'Cover',
                     data=id3AlbumCover))
    mp3File.save()
    del trackIDs[0]