Exemplo n.º 1
0
async def tag(path, metadata, session=None):
    audio = mp3.MP3(path)
    audio.tags = id3.ID3()

    for maker in tagmaker.tag_makers:
        tag = maker(metadata)
        if tag:
            audio.tags.add(tag)

    if keys.IMAGE_LINK in metadata:
        url = metadata.get(keys.IMAGE_LINK)
        if session:
            mime, _ = mimetypes.guess_type(url)
            async with session.get(url) as response:
                data = await response.read()
                audio.tags.add(
                    id3.APIC(encoding=id3.Encoding.UTF8,
                             mime=mime,
                             type=id3.PictureType.COVER_FRONT,
                             desc='Front cover',
                             data=data))
        else:
            # In practice, this is unsupported by most media players
            # But there's no reason not to do it
            audio.tags.add(id3.APIC(data=url, mime='-->'))

    audio.save()
Exemplo n.º 2
0
def write_tags(f, meta, cov):
    if f.endswith('.mp3'):
        try:
            audio = id3.ID3(f)
        except ID3NoHeaderError:
            audio = id3.ID3()
        audio['TRCK'] = id3.TRCK(encoding=3,
                                 text=str(meta['TRACK']) + "/" +
                                 str(meta['TRACKTOTAL']))
        legend = {
            "ALBUM": id3.TALB,
            "ALBUMARTIST": id3.TPE2,
            "ARTIST": id3.TPE1,
            "COPYRIGHT": id3.TCOP,
            "TITLE": id3.TIT2,
            "YEAR": id3.TYER
        }
        for tag, value in meta.items():
            if not tag in ['UPC', 'TRACK', 'TRACKTOTAL']:
                id3tag = legend[tag]
                audio[id3tag.__name__] = id3tag(encoding=3, text=value)
        with open(cov, 'rb') as cov_obj:
            audio.add(id3.APIC(3, 'image/jpeg', 3, '', cov_obj.read()))
        audio.save(f, 'v2_version=3')
    else:
        audio = FLAC(f)
        for tag, value in meta.items():
            audio[tag] = str(value)
            image = Picture()
        image.type = 3
        image.mime = "image/jpeg"
        with open(cov, 'rb') as cov_obj:
            image.data = cov_obj.read()
            audio.add_picture(image)
        audio.save()
Exemplo n.º 3
0
def write_mp3_chapters(audio, chapters):
    z = 0
    chapter_ids = []
    for chapter in chapters:
        z += 1
        chap_id = 'chap%s' % str(z).zfill(4)
        start = get_milliseconds(chapter['start'])
        stop = get_milliseconds(chapter['stop'])
        embeded_elements = []
        for tag in chapter:
            if tag == 'title':
                embeded_elements.append(id3.TIT2(encoding=3,
                                                 text=chapter[tag]))
            elif tag == 'description':
                embeded_elements.append(id3.TIT3(encoding=3,
                                                 text=chapter[tag]))
            elif tag == 'image':
                image = get_mp3_coverart(chapter[tag])
                image = id3.APIC(3, 'image/jpeg', 3, '', image)
                embeded_elements.append(image)
        chap = CHAP(element_id=chap_id, start=start, stop=stop,
              embeded_frames=embeded_elements)
        audio[chap_id] = chap
        chapter_ids.append(chap_id)
    ctoc = CTOC('ctoc0001', False, True, chapter_ids)
    audio['ctoc0001'] = ctoc
Exemplo n.º 4
0
def tag_mp3(filename, title, artwork=None):
    """
    Adds ID3 tags to a file.

    Args:
        filename (str): The name of the MP3 file that needs tagging.
        title (str): The text to be used as the ID3 title.
        artwork (str): The naem of the image file to be attached as artwork.
            Defaults to None.
    """

    audio = MP3(filename)
    duration = audio.info.length
    tags = id3.ID3()

    tags['TLEN'] = id3.TLEN(encoding=3, text=str(int(duration * 1000)))

    if title:
        tags['TIT2'] = id3.TIT2(encoding=3, text=[title])

    if artwork:
        mimetype, encoding = guess_type(artwork)
        if mimetype:
            with open(artwork, 'rb') as f:
                tags['APIC'] = id3.APIC(encoding=0,
                                        mime=mimetype,
                                        type=9,
                                        data=f.read())

    tags.update_to_v23()
    tags.save(filename, v1=1, v2_version=3, padding=lambda info: 0)
Exemplo n.º 5
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)
Exemplo n.º 6
0
def write_tags_to_mp3(path, tags):
    audio = MP3(path)
    for i, tag in [['title', 'TIT2'], ['artist', 'TPE1'], ['album', 'TALB'],
                   ['date', 'TDRC'], ['composer', 'TCOM'], ['genre', 'TCON'],
                   ['lyrics', 'USLT'], ['album-artist', 'TPE2'],
                   ['disc', 'TPOS'], ['comment', 'COMM']]:
        if i in tags:
            if tag == 'USLT':
                tag = id3.Frames[tag](encoding=3, text=tags[i], lang='eng')
                audio[tag.HashKey] = tag
            elif tag == 'COMM':
                tag = id3.Frames[tag](encoding=3, text=tags[i], lang='eng')
                audio[tag.HashKey] = tag
            else:
                tag = id3.Frames[tag](encoding=3, text=tags[i])
                audio[tag.HashKey] = tag
    if 'track' in tags:
        if 'number-of-tracks' in tags:
            num_tracks = tags['number-of-tracks']
        else:
            num_tracks = 0
        track_num = "%d/%d" % (int(tags['track']), int(num_tracks))
        tag = id3.Frames['TRCK'](encoding=3, text=track_num)
        audio[tag.HashKey] = tag
    if 'cover' in tags:
        image = get_mp3_coverart(tags['cover'])
        image = id3.APIC(3, 'image/jpeg', 3, 'Cover', image)
        audio[image.HashKey] = image
    if 'chapters' in tags:
        write_mp3_chapters(audio, tags['chapters']['chapters'])
    audio.save()
Exemplo n.º 7
0
 def song_info_insert(filepath, song_name, artist_name, album_name):
     with open('cover.jpg', 'rb') as f:
         pic_data = f.read()
     info = {
         'picData': pic_data,
         'title': song_name,
         'artist': artist_name,
         'album': album_name
     }
     filepath += '.mp3'
     try:
         song_file = id3.ID3(filepath)
         song_file['APIC'] = id3.APIC(  # 插入封面
             encoding=3,
             mime='image/jpeg',
             type=3,
             desc=u'Cover',
             data=info['picData'])
         song_file['TIT2'] = id3.TIT2(  # 插入歌名
             encoding=3, text=info['title'])
         song_file['TPE1'] = id3.TPE1(  # 插入歌手
             encoding=3, text=info['artist'])
         song_file['TALB'] = id3.TALB(  # 插入专辑名
             encoding=3, text=info['album'])
         song_file.save()
     except Exception as error:
         print('无法写入歌曲信息')
         print(f'报错:{error}')
     finally:
         os.remove('cover.jpg')
Exemplo n.º 8
0
 def embed_image():
     id3_dict.add(
         id3.APIC(encoding=3,
                  mime='image/jpeg',
                  type=3,
                  desc='Front Cover',
                  data=image))
Exemplo n.º 9
0
async def _write_tag(client: api.API, file_path: pathlib.Path, song: api.Song):
    audio = id3.ID3(file_path)
    audio.add(id3.TIT2(encoding=id3.Encoding.UTF8, text=song.name))
    audio.add(id3.TPE1(encoding=id3.Encoding.UTF8, text=song.artist))
    audio.add(id3.TALB(encoding=id3.Encoding.UTF8, text=song.album))

    if song.lyric:
        audio.add(
            id3.ULT(
                encoding=id3.Encoding.UTF8,
                lang='eng',
                desc=song.name,
                text=song.lyric,
            ))

    if song.pic_url:
        try:
            resp = await client.request('GET', song.pic_url)
            data = await resp.read()
        except (aiohttp.ClientError, asyncio.TimeoutError):
            pass
        else:
            audio.add(
                id3.APIC(
                    encoding=id3.Encoding.UTF8,
                    mime='image/jpeg',
                    type=id3.PictureType.COVER_FRONT,
                    desc='Front cover',
                    data=data,
                ))

    try:
        audio.save()
    except mutagen.MutagenError:
        pass
Exemplo n.º 10
0
 def embed_image():
     audio.tags.add(
         id3.APIC(encoding=3,
                  mime='image/jpeg',
                  type=3,
                  desc='Front Cover',
                  data=image.data))
Exemplo n.º 11
0
    def id3_art(self, mp3_file):

        song = mid3.ID3(mp3_file)

        tag = mid3.APIC(encoding=3, mime='image/jpeg', type=3,
                        desc="Front Cover", data=self.art_data)
        song.add(tag)
        song.save()
def write_tags(f, meta, tag_cfg, cov, ext, embed_cov):
    if ext == ".flac":
        audio = FLAC(f)
        for k, v in meta.items():
            if tag_cfg[k]:
                audio[k] = str(v)
        if embed_cov and cov:
            with open(cov, 'rb') as cov_obj:
                image = Picture()
                image.type = 3
                image.mime = "image/jpeg"
                image.data = cov_obj.read()
                audio.add_picture(image)
        audio.save()
    elif ext == ".mp3":
        try:
            audio = id3.ID3(f)
        except ID3NoHeaderError:
            audio = id3.ID3()
        if tag_cfg['TRACKNUMBER'] and tag_cfg['TRACKTOTAL']:
            audio['TRCK'] = id3.TRCK(encoding=3,
                                     text=str(meta['TRACKNUMBER']) + "/" +
                                     str(meta['TRACKTOTAL']))
        elif tag_cfg['TRACKNUMBER']:
            audio['TRCK'] = id3.TRCK(encoding=3, text=str(meta['TRACKNUMBER']))
        if tag_cfg['DISCNUMBER']:
            audio['TPOS'] = id3.TPOS(encoding=3,
                                     text=str(meta['DISCNUMBER']) + "/" +
                                     str(meta['DISCTOTAL']))
        legend = {
            "ALBUM": id3.TALB,
            "ALBUMARTIST": id3.TPE2,
            "ARTIST": id3.TPE1,
            "COMMENT": id3.COMM,
            "COMPOSER": id3.TCOM,
            "COPYRIGHT": id3.TCOP,
            "DATE": id3.TDAT,
            "GENRE": id3.TCON,
            "ISRC": id3.TSRC,
            "LABEL": id3.TPUB,
            "PERFORMER": id3.TOPE,
            "TITLE": id3.TIT2,
            # Not working.
            "URL": id3.WXXX,
            "YEAR": id3.TYER
        }
        for k, v in meta.items():
            try:
                if tag_cfg[k]:
                    id3tag = legend[k]
                    audio[id3tag.__name__] = id3tag(encoding=3, text=v)
            except KeyError:
                pass
        if embed_cov and cov:
            with open(cov, 'rb') as cov_obj:
                audio.add(id3.APIC(3, 'image/jpeg', 3, '', cov_obj.read()))
        audio.save(f, 'v2_version=3')
Exemplo n.º 13
0
 def addImage(self, _imageType, _imagePath, _description):
     self.isSave = True
     imageData = fu.readFromBinaryFile(_imagePath)
     mimeType = fu.getMimeType(_imagePath)[0]
     self.tags.add(
         id3.APIC(encoding=3,
                  mime=mimeType,
                  type=int(_imageType),
                  desc=uni.trUnicode(_description),
                  data=imageData))
Exemplo n.º 14
0
def write_tags(pre_abs, meta, fmt, cov_abs):
    if fmt == "FLAC":
        audio = FLAC(pre_abs)
        del meta['track_padded']
        for k, v in meta.items():
            if v:
                audio[k] = str(v)
        if cov_abs:
            with open(cov_abs, "rb") as f:
                image = Picture()
                image.type = 3
                image.mime = "image/jpeg"
                image.data = f.read()
                audio.add_picture(image)
    elif fmt == "MP3":
        try:
            audio = id3.ID3(pre_abs)
        except ID3NoHeaderError:
            audio = id3.ID3()
        audio['TRCK'] = id3.TRCK(encoding=3,
                                 text="{}/{}".format(meta['track'],
                                                     meta['tracktotal']))
        legend = {
            "album": id3.TALB,
            "albumartist": id3.TPE2,
            "artist": id3.TPE1,
            #"comment": id3.COMM,
            "copyright": id3.TCOP,
            "isrc": id3.TSRC,
            "label": id3.TPUB,
            "title": id3.TIT2,
            "year": id3.TYER
        }
        for k, v in meta.items():
            id3tag = legend.get(k)
            if v and id3tag:
                audio[id3tag.__name__] = id3tag(encoding=3, text=v)
        if cov_abs:
            with open(cov_abs, "rb") as cov_obj:
                audio.add(id3.APIC(3, "image/jpeg", 3, None, cov_obj.read()))
    else:
        audio = MP4(pre_abs)
        audio['\xa9nam'] = meta['title']
        audio['\xa9alb'] = meta['album']
        audio['aART'] = meta['albumartist']
        audio['\xa9ART'] = meta['artist']
        audio['trkn'] = [(meta['track'], meta['tracktotal'])]
        audio['\xa9day'] = meta['year']
        audio['cprt'] = meta['copyright']
        if cov_abs:
            with open(cov_abs, "rb") as f:
                audio['covr'] = [
                    MP4Cover(f.read(), imageformat=MP4Cover.FORMAT_JPEG)
                ]
    audio.save(pre_abs)
Exemplo n.º 15
0
def _embed_id3_img(root_dir, audio: id3.ID3):
    emb_image = os.path.join(root_dir, "cover.jpg")
    multi_emb_image = os.path.join(
        os.path.abspath(os.path.join(root_dir, os.pardir)), "cover.jpg")
    if os.path.isfile(emb_image):
        cover_image = emb_image
    else:
        cover_image = multi_emb_image

    with open(cover_image, "rb") as cover:
        audio.add(id3.APIC(3, "image/jpeg", 3, "", cover.read()))
Exemplo n.º 16
0
def track_tagger(track_path, title, artist, album, cover_path):
    track = mp3.EasyMP3(track_path)
    track['title'] = title
    track['artist'] = artist
    track['album'] = album
    track.save()
    cover_image = open(cover_path, 'rb').read()
    track = id3.ID3(track_path)
    track.add(id3.APIC(3, 'image/jpeg', 3, u'Cover', cover_image))
    track.save()
    remove(cover_path)
Exemplo n.º 17
0
def tag(album, track, file_path, cover_path):
    lyrics = get_lyrics(track['lyrics_tp'], track['track_id'])
    meta = utils.organize_meta(album=album, track=track, lyrics=lyrics)
    if str(file_path).endswith('.flac'):
        if cover_path:
            f_file = FLAC(file_path)
            f_image = Picture()
            f_image.type = 3
            f_image.desc = 'Front Cover'
            with open(cover_path, 'rb') as f:
                f_image.data = f.read()
            f_file.add_picture(f_image)
            f_file.save()
        f = FLAC(file_path)
        logger_bugs.debug("Writing tags to {}".format(
            os.path.basename(file_path)))
        for k, v in meta.items():
            f[k] = str(v)
        f.save()
    if str(file_path).endswith('.mp3'):
        legend = {
            "ALBUM": id3.TALB,
            "ALBUMARTIST": id3.TPE2,
            "ARTIST": id3.TPE1,
            "TRACKNUMBER": id3.TRCK,
            "DISCNUMBER": id3.TPOS,
            "COMMENT": id3.COMM,
            "COMPOSER": id3.TCOM,
            "COPYRIGHT": id3.TCOP,
            "DATE": id3.TDRC,
            "GENRE": id3.TCON,
            "ISRC": id3.TSRC,
            "LABEL": id3.TPUB,
            "PERFORMER": id3.TOPE,
            "TITLE": id3.TIT2,
            "LYRICS": id3.USLT
        }
        try:
            audio = id3.ID3(file_path)
        except ID3NoHeaderError:
            audio = id3.ID3()
        logger_bugs.debug("Writing tags to {}".format(
            os.path.basename(file_path)))
        for k, v in meta.items():
            try:
                id3tag = legend[k]
                audio[id3tag.__name__] = id3tag(encoding=3, text=v)
            except KeyError:
                pass
        if cover_path:
            with open(cover_path, 'rb') as cov_obj:
                audio.add(id3.APIC(3, 'image/jpg', 3, '', cov_obj.read()))
            audio.save(file_path, 'v2_version=3')
Exemplo n.º 18
0
def addpic(mp3file, imgfile):
    type = None
    if imgfile.endswith('png'):
        type = "image/png"
    elif imgfile.endswith('jpg') or imgfile.endswith('jpeg'):
        type = "image/jpeg"
    else:
        sys.exit(1)
    tag = id3.ID3(mp3file, v2_version=3)
    with open(imgfile).read() as f:
        tag.add(
            id3.APIC(encoding=id3.Encoding.UTF16,
                     mime=type,
                     type=id3.PictureType.COVER_FRONT,
                     data=f.read()))
    tag.save()
Exemplo n.º 19
0
def compiletracl(tracl):
    rawfile = File("%s.mp3" % tracl['id'])

    rawfile['TIT2'] = id3.TIT2(encoding=3, text=tracl['title'])
    rawfile['TALB'] = id3.TALB(encoding=3, text=tracl['album'])
    rawfile['TPE1'] = id3.TPE1(encoding=3, text=tracl['artist'])
    rawfile['TCON'] = id3.TCON(encoding=3, text=tracl['genre'])
    rawfile['TYER'] = id3.TYER(encoding=3, text=tracl['year'])
    rawfile['TRCK'] = id3.TRCK(encoding=3, text=tracl['len'])
    rawfile['WOAS'] = id3.WOAS(encoding=3, text=tracl['link'])

    rawfile['APIC'] = id3.APIC(encoding=3,
                               type=3,
                               mime='image/jpeg',
                               desc='Cover',
                               data=downloadcover(tracl))

    rawfile.save(v2_version=3)
Exemplo n.º 20
0
def insert_mp3(abs_audio_f):
    cover = cut_suffix(abs_audio_f) + '.jpg'
    mime = u"image/jpeg"
    if not os.path.exists(cover):
        cover = cut_suffix(abs_audio_f) + '.png'
        mime = u"image/png"
        if not os.path.exists(cover):
            # print('Cover for [' + abs_audio_f + '] not found.')
            return
    audio = id3.ID3(abs_audio_f)

    with open(cover, 'rb') as albumart:
        audio['APIC'] = id3.APIC(
            encoding=3,
            mime='image/jpeg',
            type=3, desc=u'Cover',
            data=albumart.read()
        )

    audio.save()
Exemplo n.º 21
0
def tag_mp3(path_audio,path_pic,lrc,title,artist,album,disc,track,**kw):
    '''
    ref:
    http://id3.org/id3v2.3.0
    https://github.com/quodlibet/mutagen/blob/master/mutagen/id3/_frames.py
    http://help.mp3tag.de/main_tags.html
    http://code.activestate.com/recipes/577138-embed-lyrics-into-mp3-files-using-mutagen-uslt-tag/
    '''
    tags=id3.ID3()
    if path_pic:
        with open(path_pic,'rb') as f:
            tags['APIC']=id3.APIC(mime='image/jpeg',type=id3.PictureType.COVER_FRONT,data=f.read())
    for x in lrc:
        tags["USLT::"+x['lang']]=id3.USLT(text=x['text'],lang=x['lang'])
    tags['TIT2']=id3.TIT2(text=title)
    tags['TPE1']=id3.TPE1(text=artist)
    if album!=None:
        tags['TALB']=id3.TALB(text=album)
    tags['TPOS']=id3.TPOS(text=disc)
    tags['TRCK']=id3.TRCK(text=str(track))
    tags.save(path_audio)
Exemplo n.º 22
0
    def id3edit(self):
        """ ID3タグを編集 """

        # ID3タグ書き換え encoding: UTF-16 with BOM (1)
        self.tags['TIT2'] = id3.TIT2(encoding=1, text=self.title)
        self.tags['TALB'] = id3.TALB(encoding=1, text=self.album)
        self.tags['TPE1'] = id3.TPE1(encoding=1, text=self.artist)
        self.tags['TCON'] = id3.TCON(encoding=1, text=self.genre)
        #self.tags['TPE2'] = TPE2(encoding=1, text=self.albumartist)

        self.tags.delall('COMM')
        self.tags['COMM'] = id3.COMM(encoding=1, lang='eng', text=self.comment)

        # アートワーク書き換え
        if not self.artwork_url == '':   # アートワーク画像のURLがある場合
            # 画像読み込み
            try:
                artwork_read = urlopen(self.artwork_url).read()
            except:
                raise URLOpenError("画像を取得できません")

            # アートワーク初期化
            self.tags.delall('APIC')

            # 画像設定
            self.tags['APIC'] = id3.APIC(
                encoding=1, mime='image/jpeg', type=3, desc='Cover', data=artwork_read)

        # 保存
        self.tags.save(self.filepath)

        # 表示用アートワーク更新
        artworks = self.tags.getall('APIC')  # list
        artwork = None
        for artwork in artworks:    # 抽出
            pass
        if artwork:     # アートワーク画像が存在するか
            self.artwork = artwork.data  # type: bytes
        else:
            self.artwork = None
Exemplo n.º 23
0
    def save_stream(self, track, destination):
        if self.is_authenticated():
            with open(destination, 'w+b') as stream_file:
                urls = self.webclient.get_stream_urls(track.get('storeId'))

                if len(urls) == 1:
                    stream_file.write(
                        self.webclient.session._rsession.get(urls[0]).content)

                range_pairs = [[int(s) for s in val.split('-')] for url in urls
                               for key, val in parse_qsl(urlparse(url)[4])
                               if key == 'range']

                for url, (start, end) in zip(urls, range_pairs):
                    stream_file.truncate(start)
                    stream_file.seek(0, 2)
                    audio = self.webclient.session._rsession.get(url).content
                    stream_file.write(audio)

            tag = easyid3.EasyID3()
            tag['title'] = track.get('title').__str__()
            tag['artist'] = track.get('artist').__str__()
            tag['album'] = track.get('album').__str__()
            tag['date'] = track.get('year').__str__()
            tag['discnumber'] = track.get('discNumber').__str__()
            tag['tracknumber'] = track.get('trackNumber').__str__()
            tag['performer'] = track.get('albumArtist').__str__()
            tag.save(destination)

            tag = mp3.MP3(destination)
            tag.tags.add(
                id3.APIC(
                    3, 'image/jpeg', 3, 'Front cover',
                    urllib.urlopen(
                        track.get('albumArtRef')[0].get('url')).read()))
            tag.save()
Exemplo n.º 24
0
    def tag(self, target, track):
        mp3 = MP3(os.path.join(self.workdir, target))

        if not mp3.tags:
            mp3.add_tags()

        tags = mp3.tags
        tags.add(id3.TALB(encoding=id3.Encoding.UTF8, text=self.disc.album))
        tags.add(id3.TPE1(encoding=id3.Encoding.UTF8, text=self.disc.artist))
        tags.add(id3.TIT2(encoding=id3.Encoding.UTF8, text=track.title))
        tags.add(id3.TRCK(encoding=id3.Encoding.UTF8, text=str(track.trackno)))
        tags.add(id3.TDRC(encoding=id3.Encoding.UTF8,
                          text=str(self.disc.year)))

        tpos = str(self.disc.discno)
        if self.disc.set_size > 1:
            tpos = f"{self.disc.discno}/{self.disc.set_size}"
        tags.add(id3.TPOS(encoding=id3.Encoding.UTF8, text=tpos))

        if self.disc.cover_art:
            tags.add(
                id3.APIC(encoding=id3.Encoding.UTF8, data=self.disc.cover_art))

        mp3.save()
Exemplo n.º 25
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()
Exemplo n.º 26
0
    def _save(self, filename, metadata):
        """Save metadata to the file."""
        log.debug("Saving file %r", filename)
        tags = self._get_tags(filename)

        if config.setting['clear_existing_tags']:
            tags.clear()
        if metadata.images_to_be_saved_to_tags:
            tags.delall('APIC')

        encoding = {
            'utf-8': 3,
            'utf-16': 1
        }.get(config.setting['id3v2_encoding'], 0)

        if 'tracknumber' in metadata:
            if 'totaltracks' in metadata:
                text = '%s/%s' % (metadata['tracknumber'],
                                  metadata['totaltracks'])
            else:
                text = metadata['tracknumber']
            tags.add(id3.TRCK(encoding=0, text=id3text(text, 0)))

        if 'discnumber' in metadata:
            if 'totaldiscs' in metadata:
                text = '%s/%s' % (metadata['discnumber'],
                                  metadata['totaldiscs'])
            else:
                text = metadata['discnumber']
            tags.add(id3.TPOS(encoding=0, text=id3text(text, 0)))

        # This is necessary because mutagens HashKey for APIC frames only
        # includes the FrameID (APIC) and description - it's basically
        # impossible to save two images, even of different types, without
        # any description.
        counters = defaultdict(lambda: 0)
        for image in metadata.images_to_be_saved_to_tags:
            desc = desctag = image.comment
            if counters[desc] > 0:
                if desc:
                    desctag = "%s (%i)" % (desc, counters[desc])
                else:
                    desctag = "(%i)" % counters[desc]
            counters[desc] += 1
            tags.add(
                id3.APIC(encoding=0,
                         mime=image.mimetype,
                         type=image_type_as_id3_num(image.maintype),
                         desc=id3text(desctag, 0),
                         data=image.data))

        tmcl = mutagen.id3.TMCL(encoding=encoding, people=[])
        tipl = mutagen.id3.TIPL(encoding=encoding, people=[])

        tags.delall('TCMP')
        for name, values in metadata.rawitems():
            values = [id3text(v, encoding) for v in values]
            name = id3text(name, encoding)

            if name.startswith('performer:'):
                role = name.split(':', 1)[1]
                for value in values:
                    tmcl.people.append([role, value])
            elif name.startswith('comment:'):
                desc = name.split(':', 1)[1]
                if desc.lower()[:4] == 'itun':
                    tags.delall('COMM:' + desc)
                    tags.add(
                        id3.COMM(encoding=0,
                                 desc=desc,
                                 lang='eng',
                                 text=[v + '\x00' for v in values]))
                else:
                    tags.add(
                        id3.COMM(encoding=encoding,
                                 desc=desc,
                                 lang='eng',
                                 text=values))
            elif name.startswith('lyrics:') or name == 'lyrics':
                if ':' in name:
                    desc = name.split(':', 1)[1]
                else:
                    desc = ''
                for value in values:
                    tags.add(id3.USLT(encoding=encoding, desc=desc,
                                      text=value))
            elif name in self._rtipl_roles:
                for value in values:
                    tipl.people.append([self._rtipl_roles[name], value])
            elif name == 'musicbrainz_recordingid':
                tags.add(
                    id3.UFID(owner='http://musicbrainz.org',
                             data=bytes(values[0], 'ascii')))
            elif name == '~rating':
                # Search for an existing POPM frame to get the current playcount
                for frame in tags.values():
                    if frame.FrameID == 'POPM' and frame.email == config.setting[
                            'rating_user_email']:
                        count = getattr(frame, 'count', 0)
                        break
                else:
                    count = 0

                # Convert rating to range between 0 and 255
                rating = int(
                    round(
                        float(values[0]) * 255 /
                        (config.setting['rating_steps'] - 1)))
                tags.add(
                    id3.POPM(email=config.setting['rating_user_email'],
                             rating=rating,
                             count=count))
            elif name == 'grouping':
                if config.setting['itunes_compatible_grouping']:
                    tags.add(id3.GRP1(encoding=encoding, text=values))
                else:
                    tags.add(id3.TIT1(encoding=encoding, text=values))
            elif name == 'work':
                if config.setting['itunes_compatible_grouping']:
                    tags.add(id3.TIT1(encoding=encoding, text=values))
                    tags.delall('TXXX:Work')
                else:
                    tags.add(self.build_TXXX(encoding, 'Work', values))
            elif name in self.__rtranslate:
                frameid = self.__rtranslate[name]
                if frameid.startswith('W'):
                    valid_urls = all([all(urlparse(v)[:2]) for v in values])
                    if frameid == 'WCOP':
                        # Only add WCOP if there is only one license URL, otherwise use TXXX:LICENSE
                        if len(values) > 1 or not valid_urls:
                            tags.add(
                                self.build_TXXX(
                                    encoding, self.__rtranslate_freetext[name],
                                    values))
                        else:
                            tags.add(id3.WCOP(url=values[0]))
                    elif frameid == 'WOAR' and valid_urls:
                        for url in values:
                            tags.add(id3.WOAR(url=url))
                elif frameid.startswith('T'):
                    if config.setting['write_id3v23']:
                        if frameid == 'TMOO':
                            tags.add(self.build_TXXX(encoding, 'mood', values))
                    # No need to care about the TMOO tag being added again as it is
                    # automatically deleted by Mutagen if id2v23 is selected
                    tags.add(
                        getattr(id3, frameid)(encoding=encoding, text=values))
                    if frameid == 'TSOA':
                        tags.delall('XSOA')
                    elif frameid == 'TSOP':
                        tags.delall('XSOP')
                    elif frameid == 'TSO2':
                        tags.delall('TXXX:ALBUMARTISTSORT')
            elif name in self.__rtranslate_freetext:
                tags.add(
                    self.build_TXXX(encoding, self.__rtranslate_freetext[name],
                                    values))
            elif name.startswith('~id3:'):
                name = name[5:]
                if name.startswith('TXXX:'):
                    tags.add(self.build_TXXX(encoding, name[5:], values))
                else:
                    frameclass = getattr(id3, name[:4], None)
                    if frameclass:
                        tags.add(frameclass(encoding=encoding, text=values))
            # don't save private / already stored tags
            elif not name.startswith(
                    "~") and name not in self.__other_supported_tags:
                tags.add(self.build_TXXX(encoding, name, values))

        tags.add(tmcl)
        tags.add(tipl)

        self._remove_deleted_tags(metadata, tags)

        self._save_tags(tags, encode_filename(filename))

        if self._IsMP3 and config.setting["remove_ape_from_mp3"]:
            try:
                mutagen.apev2.delete(encode_filename(filename))
            except:
                pass
Exemplo n.º 27
0
def mark(path, song, id=None):
    def streamify(file):
        with file:
            return file.read()

    def embed(item, content, type):
        item.encoding = 0
        item.type = type
        item.mime = 'image/png' if content[0:4] == binascii.a2b_hex(
            '89504E47') else 'image/jpeg'
        item.data = content

    format = 'flac' if open(
        path, 'rb').read(4) == binascii.a2b_hex('664C6143') else 'mp3'
    audio = mp3.EasyMP3(path) if format == 'mp3' else flac.FLAC(path)

    meta = {
        'album':
        song['album']['name'],
        'albumId':
        song['album']['id'],
        'albumPic':
        song['album']['picUrl'],
        'albumPicDocId':
        str(song['album']['pic'] if 'pic' in song['album'] else re.
            search(r'/(\d+)\.\w+$', song['album']['picUrl']).group(1)),
        'alias':
        song['alias'] if 'alias' in song else [],
        'artist':
        [[artist['name'], artist['id']] for artist in song['artists']],
        'musicId':
        id if id else song['id'],
        'musicName':
        song['name'] if 'name' in song else audio['title'][0],
        'mvId':
        song['mvid'] if 'mvid' in song else 0,
        'transNames': [],
        'format':
        format,
        'bitrate':
        audio.info.bitrate,
        'duration':
        int(audio.info.length * 1000),
        'mp3DocId':
        hashlib.md5(streamify(open(path, 'rb'))).hexdigest()
    }

    cryptor = AES.new(key, AES.MODE_ECB)
    identifier = 'music:' + json.dumps(meta)
    identifier = '163 key(Don\'t modify):' + base64.b64encode(
        cryptor.encrypt(pad(identifier.encode('utf8'), 16))).decode('utf8')

    audio.delete()
    audio['title'] = meta['musicName']
    audio['album'] = meta['album']
    audio['artist'] = '/'.join([artist[0] for artist in meta['artist']])

    if format == 'flac':
        audio['description'] = identifier
    else:
        audio.tags.RegisterTextKey('comment', 'COMM')
        audio['comment'] = identifier
    audio.save()

    data = requests.get(meta['albumPic'] + '?param=300y300').content
    if format == 'flac':
        audio = flac.FLAC(path)
        image = flac.Picture()
        embed(image, data, 3)
        audio.clear_pictures()
        audio.add_picture(image)
    elif format == 'mp3':
        audio = mp3.MP3(path)
        image = id3.APIC()
        embed(image, data, 6)
        audio.tags.add(image)
    audio.save()
Exemplo n.º 28
0
def dump(input_path, output_path=None, skip=True):

    output_path = (lambda path, meta: os.path.splitext(path)[0] + '.' + meta[
        'format']) if not output_path else output_path
    output_path = (
        lambda path, meta: path) if not callable(output_path) else output_path

    core_key = binascii.a2b_hex('687A4852416D736F356B496E62617857')
    meta_key = binascii.a2b_hex('2331346C6A6B5F215C5D2630553C2728')
    unpad = lambda s: s[0:-(s[-1] if type(s[-1]) == int else ord(s[-1]))]

    f = open(input_path, 'rb')

    # magic header
    header = f.read(8)
    assert binascii.b2a_hex(header) == b'4354454e4644414d'

    # key data
    f.seek(2, 1)
    key_length = f.read(4)
    key_length = struct.unpack('<I', bytes(key_length))[0]

    key_data = bytearray(f.read(key_length))
    key_data = bytes(bytearray([byte ^ 0x64 for byte in key_data]))

    cryptor = AES.new(core_key, AES.MODE_ECB)
    key_data = unpad(cryptor.decrypt(key_data))[17:]
    key_length = len(key_data)

    # S-box (standard RC4 Key-scheduling algorithm)
    key = bytearray(key_data)
    S = bytearray(range(256))
    j = 0

    for i in range(256):
        j = (j + S[i] + key[i % key_length]) & 0xFF
        S[i], S[j] = S[j], S[i]

    # meta data
    meta_length = f.read(4)
    meta_length = struct.unpack('<I', bytes(meta_length))[0]

    if meta_length:
        meta_data = bytearray(f.read(meta_length))
        meta_data = bytes(bytearray([byte ^ 0x63 for byte in meta_data]))
        identification = meta_data.decode('utf-8')
        meta_data = base64.b64decode(meta_data[22:])

        cryptor = AES.new(meta_key, AES.MODE_ECB)
        meta_data = unpad(cryptor.decrypt(meta_data)).decode('utf-8')[6:]
        meta_data = json.loads(meta_data)
    else:
        meta_data = {
            'format':
            'flac' if os.fstat(f.fileno()).st_size > 1024**2 * 16 else 'mp3'
        }

    # crc32
    crc32 = f.read(4)
    crc32 = struct.unpack('<I', bytes(crc32))[0]

    # album cover
    f.seek(5, 1)
    image_size = f.read(4)
    image_size = struct.unpack('<I', bytes(image_size))[0]
    image_data = f.read(image_size) if image_size else None

    # media data
    output_path = output_path(input_path, meta_data)
    if skip and os.path.exists(output_path): return

    data = f.read()
    f.close()

    # stream cipher (modified RC4 Pseudo-random generation algorithm)
    stream = [S[(S[i] + S[(i + S[i]) & 0xFF]) & 0xFF] for i in range(256)]
    stream = bytes(bytearray(stream * (len(data) // 256 + 1))[1:1 + len(data)])
    data = XOR(data, stream)

    m = open(output_path, 'wb')
    m.write(data)
    m.close()

    # media tag
    def embed(item, content, type):
        item.encoding = 0
        item.type = type
        item.mime = 'image/png' if content[0:4] == binascii.a2b_hex(
            '89504E47') else 'image/jpeg'
        item.data = content

    if image_data:
        if meta_data['format'] == 'flac':
            audio = flac.FLAC(output_path)
            image = flac.Picture()
            embed(image, image_data, 3)
            audio.clear_pictures()
            audio.add_picture(image)
        elif meta_data['format'] == 'mp3':
            audio = mp3.MP3(output_path)
            image = id3.APIC()
            embed(image, image_data, 6)
            audio.tags.add(image)
        audio.save()

    if meta_length:
        if meta_data['format'] == 'flac':
            audio = flac.FLAC(output_path)
            audio['description'] = identification
        else:
            audio = mp3.EasyMP3(output_path)
            audio.tags.RegisterTextKey('comment', 'COMM')
            audio['comment'] = identification
        audio['title'] = meta_data['musicName']
        audio['album'] = meta_data['album']
        audio['artist'] = '/'.join(
            [artist[0] for artist in meta_data['artist']])
        audio.save()

    return output_path
Exemplo n.º 29
0
def dump(input_path, output_path=None, skip=True):

    output_path = (lambda path, meta: os.path.splitext(path)[0] + '.' + meta[
        'format']) if not output_path else output_path
    core_key = binascii.a2b_hex('687A4852416D736F356B496E62617857')
    meta_key = binascii.a2b_hex('2331346C6A6B5F215C5D2630553C2728')
    unpad = lambda s: s[0:-(s[-1] if type(s[-1]) == int else ord(s[-1]))]

    f = open(input_path, 'rb')

    # magic header
    header = f.read(8)
    assert binascii.b2a_hex(header) == b'4354454e4644414d'

    # key data
    f.seek(2, 1)
    key_length = f.read(4)
    key_length = struct.unpack('<I', bytes(key_length))[0]

    key_data = bytearray(f.read(key_length))
    key_data = bytes(bytearray([byte ^ 0x64 for byte in key_data]))

    cryptor = AES.new(core_key, AES.MODE_ECB)
    key_data = unpad(cryptor.decrypt(key_data))[17:]
    key_length = len(key_data)

    # S-box (standard RC4 Key-scheduling algorithm)
    key = bytearray(key_data)
    S = bytearray(range(256))
    j = 0

    for i in range(256):
        j = (j + S[i] + key[i % key_length]) % 256
        S[i], S[j] = S[j], S[i]

    # meta data
    meta_length = f.read(4)
    meta_length = struct.unpack('<I', bytes(meta_length))[0]

    meta_data = bytearray(f.read(meta_length))
    meta_data = bytes(bytearray([byte ^ 0x63 for byte in meta_data]))
    meta_data = base64.b64decode(meta_data[22:])

    cryptor = AES.new(meta_key, AES.MODE_ECB)
    meta_data = unpad(cryptor.decrypt(meta_data)).decode('utf-8')[6:]
    meta_data = json.loads(meta_data)

    # crc32
    crc32 = f.read(4)
    crc32 = struct.unpack('<I', bytes(crc32))[0]

    # album cover
    f.seek(5, 1)
    image_size = f.read(4)
    image_size = struct.unpack('<I', bytes(image_size))[0]
    image_data = f.read(image_size)

    # media data
    output_path = output_path(input_path, meta_data)
    if skip and os.path.exists(output_path): return
    m = open(output_path, 'wb')
    data = bytearray(f.read())

    # stream cipher (modified RC4 Pseudo-random generation algorithm)
    i = 0
    j = 0
    for k, _ in enumerate(data):
        i = (i + 1) % 256
        j = (i + S[i]) % 256  # in RC4, is j = (j + S[i]) % 256
        # S[i], S[j] = S[j], S[i] # no swapping
        data[k] ^= S[(S[i] + S[j]) % 256]

    m.write(data)
    m.close()
    f.close()

    # media tag
    if meta_data['format'] == 'flac':
        audio = flac.FLAC(output_path)
        # audio.delete()
        image = flac.Picture()
        image.encoding = 0
        image.type = 3
        image.mime = 'image/jpeg'
        image.data = image_data
        audio.clear_pictures()
        audio.add_picture(image)
    elif meta_data['format'] == 'mp3':
        audio = mp3.MP3(output_path)
        # audio.delete()
        image = id3.APIC()
        image.encoding = 0
        image.type = 3
        image.mime = 'image/jpeg'
        image.data = image_data
        audio.tags.add(image)
        audio.save()
        audio = mp3.EasyMP3(output_path)

    audio['title'] = meta_data['musicName']
    audio['album'] = meta_data['album']
    audio['artist'] = '/'.join([artist[0] for artist in meta_data['artist']])
    audio.save()

    return output_path
Exemplo n.º 30
0
def dumpfile(file_path):
    # 预定义key
    core_key = binascii.a2b_hex("687A4852416D736F356B496E62617857")
    meta_key = binascii.a2b_hex("2331346C6A6B5F215C5D2630553C2728")
    unpad = lambda s: s[0:-(s[-1] if type(s[-1]) == int else ord(s[-1]))]

    f = open(file_path, 'rb')

    # magic header
    header = f.read(8)
    assert binascii.b2a_hex(header) == b'4354454e4644414d'

    # key data
    f.seek(2, 1)
    key_length = f.read(4)
    key_length = struct.unpack('<I', bytes(key_length))[0]

    key_data = bytearray(f.read(key_length))
    key_data = bytes(bytearray([byte ^ 0x64 for byte in key_data]))

    cryptor = AES.new(core_key, AES.MODE_ECB)
    key_data = unpad(cryptor.decrypt(key_data))[17:]
    key_length = len(key_data)

    # key box
    key_data = bytearray(key_data)
    key_box = bytearray(range(256))
    j = 0

    for i in range(256):
        j = (key_box[i] + j + key_data[i % key_length]) & 0xff
        key_box[i], key_box[j] = key_box[j], key_box[i]

    # meta data
    meta_length = f.read(4)
    meta_length = struct.unpack('<I', bytes(meta_length))[0]

    meta_data = bytearray(f.read(meta_length))
    meta_data = bytes(bytearray([byte ^ 0x63 for byte in meta_data]))
    meta_data = base64.b64decode(meta_data[22:])

    cryptor = AES.new(meta_key, AES.MODE_ECB)
    meta_data = unpad(cryptor.decrypt(meta_data)).decode('utf-8')[6:]
    meta_data = json.loads(meta_data)

    # crc32
    crc32 = f.read(4)
    crc32 = struct.unpack('<I', bytes(crc32))[0]

    # album cover
    f.seek(5, 1)
    image_size = f.read(4)
    image_size = struct.unpack('<I', bytes(image_size))[0]
    image_data = f.read(image_size)

    author_name = ""
    # media data
    if len(meta_data['artist']) == 1:
        author_name = meta_data['artist'][0][0]
    else:
        for i in range(len(meta_data['artist'])):
            if i == len(meta_data['artist']) - 1:
                author_name += meta_data['artist'][i][0]
            else:
                author_name += meta_data['artist'][i][0]
                author_name += ','
    file_name = author_name + ' - ' + meta_data['musicName'] + '.' + meta_data['format']
    music_path = os.path.join(os.path.split(file_path)[0], file_name)
    m = open(music_path, 'wb')

    while True:
        chunk = bytearray(f.read(0x8000))
        chunk_length = len(chunk)
        if not chunk:
            break

        for i in range(chunk_length):
            j = (i + 1) & 0xff
            chunk[i] ^= key_box[(key_box[j] + key_box[(key_box[j] + j) & 0xff]) & 0xff]

        m.write(chunk)

    m.close()
    f.close()

    # media tag
    if meta_data['format'] == 'flac':
        audio = flac.FLAC(music_path)
        # audio.delete()
        image = flac.Picture()
        image.type = 3
        image.mime = 'image/jpeg'
        image.data = image_data
        audio.clear_pictures()
        audio.add_picture(image)
    elif meta_data['format'] == 'mp3':
        audio = mp3.MP3(music_path)
        # audio.delete()
        image = id3.APIC()
        image.type = 3
        image.mime = 'image/jpeg'
        image.data = image_data
        audio.tags.add(image)
        audio.save()
        audio = mp3.EasyMP3(music_path)

    audio['title'] = meta_data['musicName']
    audio['album'] = meta_data['album']
    audio['artist'] = '/'.join([artist[0] for artist in meta_data['artist']])
    audio.save()