现在Python3下的ID3v2标签读取与修改模块特别少,python2下比较好用的一些模块在python3均不能安装使用,于是,自己写了一个。


---1/3------------

# ID3v2.py  version 1.2


# Module for manipulating ID3 informational tags in MP3 audio files

# 鉴于现在适用与python3的ID3软件包很少,遂自己写了一个。现在网上的mp3一般都有ID3v2标签,

# 本模块功能就是读取mp3文件的ID3v2标签,把标签记录在一个集合里面。

# 特别的,对于最常见的歌手,曲名和专辑名,可以通过一些内部属性直接调用访问。


# Written 2013/4/19 By Kayneo <[email protected]>

# This is the first thing I've written in Python.


# constructor:

#       ID3(filename)

# then you can use the ID3v2 tag as in the follwing

#

# ID3.d

#   It's a set containing all the tag found in ID3v2

#

# ID3.title or ID3.d['TIT2']

#   The title of the song

#

# ID3.artist of ID3.d['TPE1']

#    The artist

#

# ID3.album or ID3.d['TALB']

#    The album

#

# ID3.haspic

#    Whether or not has a pic

#

# ID3.tagverison

#    The ID3v2 version :v2.3 or v2.4

#

# ID3.tagsize

#    The size of the ID3 tag

#

# ID3.d['TYER']

#    The year

#

# ID3.d[etc.]

#    Other tags.


# Usage :

# import ID3v2

# a=ID3v2.ID3('filename')

# print(a.d)

# print(a.artist, a.title, a.album)





def trip_space(s):

    while len(s) > 0 and s[-1] == '\x00':

        s = s[:-1]

##    while len(s) > 0 and s[:2]  == b'\x00\x00':

##        s = s[2:]


    return s


class NoID3v2Error(Exception):

    def __init__(self, msg):

        self.msg = msg

    def __str__(self):

        return self.msg


class ID3:


    def __init__(self, file):

        self.fname = file

        try:

            self.file = open(file, 'rb')


        except IOError as msg:

            print('{0:s} open Error! {1:s}'.format(self.fname,msg))

            return


        

        if self.file.read(3) != b'ID3' :

            #print('No ID3v2 Tag')

            raise NoID3v2Error('No ID3v2 Tag')

            self.file.close()

            return


        self.d = {}

        self.tagversion = 0

        self.tagsize = 0

        self.haspic = False

        self.artist = ''

        self.title = ''

        self.album = ''

        

        HDR = self.file.read(7)


        self.tagv = 'v%d.%d'%(2,HDR[0])

        self.tagsize = HDR[-1]+HDR[-2]*0x80+HDR[-3]*0x4000+HDR[-4]*0x200000 +10

        #print (self.tagsize)

        

        while True:

            a = self.file.read(1)

            if a ==  b'\x00' or a == b'\xff': break

            

            self.file.seek(-1,1)

            fhdr = self.file.read(10) # ;print (fhdr)

            sz = fhdr[-3]+fhdr[-4]*0x100 +fhdr[-5]*0x10000+fhdr[-6]*0x1000000

            kind = fhdr[0:4].decode()


            if kind != 'APIC':

                info = self.file.read(sz) #;print (info)


                try:

                    st = info.rfind(b'\xff\xfe')

                    if st != -1: # \x01\xff\xfe.....\xff\xfe

                       self.d[kind] = trip_space(info[st+2:].decode('utf16'))

                       

                    elif info.startswith(b'\x03'):

                        self.d[kind] = trip_space(info[1:].decode())

                        

                    else: #\x00

                        self.d[kind] = info[1:-1].replace(b'\x00',b'\x20').decode('gbk')

                        

                except UnicodeDecodeError as msg:

                    #print('Decode Error @%s, Content is %s\nMsg:%s'%(kind,info, msg))

                    pass

                    

            else:

                self.haspic = True

                break

                #self.file.seek(sz,1)


            #print(self.file.tell()) 


        

        if 'TPE1' in self.d.keys(): self.artist = self.d['TPE1']

        if 'TIT2' in self.d.keys(): self.title  = self.d['TIT2']

        if 'TALB' in self.d.keys(): self.album  = self.d['TALB']


        self.file.close()



---2/3-------------

# MP3.py  Version 1.0


# This module is to get the ID3v2 and infomation of MP3 file.

#获取MP3的信息包含id3v2信息


# Written 2013/4/19 By Kayneo <[email protected]>

# This is the first thing I've written in Python.


# Constrctor:

#       MP3(filename)

#then you can use the ID3v2 tag as in the follwing

#

# MP3.title or MP3.d['TIT2']

#   The title of the song

#

# MP3.artist of MP3.d['TPE1']

#    The artist

#

# MP3.album or MP3.d['TALB']

#    The album

#

# MP3.bitrate or ID3.d['Bitrate']

#   The bitrate of the song

#

# MP3.trackmod or MP3.d['Trackmod']

#    The mode of track. 声道模式

#

# MP3.sample_freq or MP3.d['Sample Frequency']

#    The frequency of sample 采样率

#

# MP3.d[...]

#    Various properties of MP3

#

# Usage :

# import MP3

# a=MP3.MP3('filename')

# print(a.d)

# print(a.artist, a.title, a.bitrate)



from MP3Info import MP3Info

from ID3v2 import *


class MP3:


    def __init__(self, file, name='unknown'):

        self.name = file


        self.artist  = ''

        self.title   = ''

        self.album   = ''

        

        self.bitrate     = ''

        self.trackmod    = ''

        self.sample_freq = ''

        self.d={}

        

        try:

            mp3info = MP3Info(file)

            

            self.bitrate = mp3info.bitrate

            self.trackmod= mp3info.trackmod

            self.sample_freq = mp3info.sample_freq

        

            id3     = ID3(file)

            

            self.artist = id3.artist

            self.title = id3.title

            self.album = id3.album

            self.d = dict(mp3info.d, **id3.d)

            

        except NoID3v2Error as msg:

            self.d = mp3info.d

            print(msg)


##        except :

##            print('Some Error!')

##            

            

---3/3------------------------------------------------------            

# MP3Info.py Version 1.0


# This module focus on geting the infomation of the MP3 file, such as bitrate, sample frequency.

# 获取MP3的信息,包括比特率,取样率,等等。


# Written 2013/4/19 By Kayneo <[email protected]>

# This is the first thing I've written in Python.


# constructor:

#       MP3Info(filename)

# then you can use the ID3v2 tag as in the follwing

#

# MP3.d

#   It's a set containing all the tag found in MP3

#

# MP3Info.version of MP3Info.d['Version']

#    The version of the file

#

# MP3Info.bitrate or MP3Info.d['Bitrate']

#   The bitrate of the song

#

# MP3Info.trackmod or MP3Info.d['Trackmod']

#    The mode of track. 声道模式

#

# MP3Info.sample_freq or MP3Info.d['Sample Frequency']

#    The frequency of sample 采样率

#

# MP3Info.copyright or MP3Info.d['Copyright']

#    The copyright of MP3

#

# MP3Info.original or MP3Info.d['Original']

#    Whether or not Original 是否原版

#

# MP3Info.frame_mod or MP3Info.d['Frame Mode']

#    The mode of frame


# Usage :

# import MP3Info 

# a=MP3Info.MP3Info('filename')

# print (a.d)

# print(a.bitrate)


class MP3Info:


    MP3Version = {0b00:'MPEG 2.5', 0b01:'UNDEFINED', 0b10:'MPEG 2', 0b11:'MPEG 1'}

    MP3Layer = {0b00:'UNDEFINED', 0b01:'Layer 3', 0b10:'Layer 2', 0b11:'Layer 1'}

    MP3CRC = {0b0:'校检', 0b1:'非校检'}

    MP3Bitrate = {0b0000:'free',

                  0b0001:32,

                  0b0010:40,

                  0b0011:48,

                  0b0100:56,

                  0b0101:64,

                  0b0110:80,

                  0b0111:96,

                  0b1000:112,

                  0b1001:128,

                  0b1010:160,

                  0b1011:192,

                  0b1100:224,

                  0b1101:256,

                  0b1110:320,

                  0b1111:'bad'}

    MP3Samp_freq = {0b00:441000, 0b01:48000, 0b10:32000, 0b11:'UNdefined'}

    MP3Frame_mod = {0:'无需调整',1:'调整'}

    MP3Trackmod ={0b00:'立体声',0b01:'联合立体声',0b10:'双声道',0b11:'单声道'}

    MP3Copyright ={0b0:'不合法', 0b1:'合法'}

    MP3Original = {0b0:'非原版', 0b1:'原版'}



    def __init__(self, file):

        self.name = file

        try:

            self.file = open(file, 'rb')


        except IOError as msg:

            print('{0:s} open Error! {1:s}'.format(self.fname,msg))

            return


        if self.file.read(3) == b'ID3':

            HDR=self.file.read(7)

            tagsz = HDR[-1]+HDR[-2]*0x80+HDR[-3]*0x4000+HDR[-4]*0x200000 +10

            self.file.seek(tagsz,0)

        else:

            self.file.seek(0)



        framehdr = self.file.read(4)

        vbrinfo  = self.file.read(32)

        

        self.file.close()


        self.d={}

        

        self.version = self.MP3Version[(framehdr[1]&0b00011000)>>3] +' - ' +self.MP3Layer[(framehdr[1] & 0b00000110)>>1]

        self.bitrate = self.MP3Bitrate[framehdr[2]>>4]

        self.sample_freq = self.MP3Samp_freq[(framehdr[2]&0b00001100)>>2]

        self.padding = (framehdr[2]&0b00000010)>>1

        self.frame_mod = self.MP3Frame_mod[self.padding]

        self.trackmod = self.MP3Trackmod[framehdr[3]>>6]

        self.copyright = self.MP3Copyright[(framehdr[3]&0b00001000)>>3]

        self.original = self.MP3Original[(framehdr[3] &0b00000100)>>2]


        if self.version : self.d['Version'] = self.version

        if self.bitrate : self.d['Bitrate'] = self.bitrate

        if self.sample_freq : self.d['Sample Frequency'] = self.sample_freq

        if self.frame_mod : self.d['Frame Mode'] = self.frame_mod

        if self.trackmod :self.d['Track Mode'] = self.trackmod

        if self.copyright: self.d['Copyright'] = self.copyright

        if self.original : self.d['Original'] = self.original


        

        

 ------------ single.py -----------------

import MP3,re

file = r'a.mp3'

a = MP3.MP3(file)

print (a.d)

---------------------------------

【原】Python3&nbsp;下&nbsp;MP3格式文件的ID…




        


            

        


阅读(0)| 评论(0)

相关文章: