现在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 <kayneo@yeah.net>
# 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 <kayneo@yeah.net>
# 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 <kayneo@yeah.net>
# 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)
---------------------------------