什么是ID3
MP3是音頻文件最流行的格式,它的全稱是 MPEG layer III。但是這種格式不支持對于音頻內(nèi)容的描述信息横殴,包括歌曲名稱、演唱者卿拴、專輯等等衫仑。
因此在1996年,Eric Kemp在Studio 3項(xiàng)目中提出了ID3的解決方案堕花。ID3全稱是Identity of MP3文狱,其解決方案是在音頻文件末尾附加一串?dāng)?shù)據(jù),包含關(guān)于歌曲的名稱缘挽、歌手瞄崇、圖片的信息呻粹。為了方便檢測,數(shù)據(jù)的長度固定為128bytes苏研。這個版本的解決方案稱為 ID3v1等浊。
Michael Mutschler 在 1997 對格式進(jìn)行了微小的調(diào)整,壓縮了Comment字段摹蘑,增加了Track信息筹燕,這個版本被稱為ID3v1.1。
1998年衅鹿,Martin Nilsson & Michael Mutschler牽頭撒踪,多個貢獻(xiàn)者一起發(fā)起了ID3v2的工作。這個班的結(jié)構(gòu)和ID3v1完全不同大渤,數(shù)據(jù)的長度不再固定制妄,位置也從尾部移到了頭部,并且引入了Unicode支持泵三。ID3v2的第一個版本是ID3v2.2耕捞,2000年發(fā)布了ID3v2.4。
ID3v1
附著在音頻數(shù)據(jù)之后烫幕,長度為128bytes俺抽,每個字段最大支持30個字符。
具體的字段信息
Song Title | 30 characters |
---|---|
Artist | 30 characters |
Album | 30 characters |
Year | 4 characters |
Comment | 30 characters |
Genre | 1 byte |
在數(shù)據(jù)開始之前纬霞,總是有三個字符TAG
,這樣和上面的字段加起來驱显,正好是128bytes诗芜。如果Artist字段內(nèi)容不足30個字符,不足的部分用0填充埃疫。
ID3v2
ID3v2是加在音頻數(shù)據(jù)前面的一組數(shù)據(jù)伏恐,每項(xiàng)具體的數(shù)據(jù)稱為frame(例如歌曲名稱)∷ㄋ可以包含任意類型的數(shù)據(jù)翠桦,每個frame最大支持16MB,整個tag大小最大支持256MB胳蛮。存儲編碼支持Unicode销凑,這樣就不會產(chǎn)生亂碼問題。
Tag數(shù)據(jù)放在音頻數(shù)據(jù)之前還有一個好處仅炊,對于流式訪問可以首先獲得歌曲信息并展現(xiàn)給用戶斗幼。
列舉一些特性:
- The ID3v2 tag is a container format, just like IFF or PNG files, allowing new frames (chunks) as evolution proceeds.
- Residing in the beginning of the audio file makes it suitable for streaming.
- Has an 'unsynchronization scheme' to prevent ID3v2-incompatible players to attempt to play the tag.
- Maximum tag size is 256 megabytes and maximum frame size is 16 megabytes.
- Byte conservative and with the capability to compress data it keeps the files small.
- The tag supports Unicode.
- Isn't entirely focused on musical audio, but also other types of audio.
- Has several new text fields such as composer, conductor, media type, BPM, copyright message, etc. and the possibility to design your own as you see fit.
- Can contain lyrics as well as music-synced lyrics (karaoke) in almost any language.
- Is able to contain volume, balance, equalizer and reverb settings.
- Could be linked to CD-databases such as CDDB and FreeDB.
- Is able to contain images and just about any file you want to include.
- Supports enciphered information, linked information and weblinks.
使用 Python 讀取ID3 信息
我寫了一個 Python 腳本可以用來讀取 ID3v1 的信息。實(shí)際操作過程中發(fā)現(xiàn)兩個問題:
1抚垄、ID3v1的信息沒有編碼字段蜕窿,所以有的時候同樣的Mp3谋逻,在不同的系統(tǒng)環(huán)境中播放,會顯示亂碼桐经。針對這個問題毁兆,打算再寫一篇文章說一下如何探測編碼。
2阴挣、iTunes應(yīng)該是優(yōu)先使用ID3v2的信息
我把腳本放到了 github 上气堕,感興趣的同學(xué)可以通過 https://github.com/cocowool/py-id3 查看。
# Read ID3v1 tag information
import os
import string
import base64
import chardet
def parse(fileObj, version = 'v1'):
fileObj.seek(0,2)
# ID3v1's max length is 128 bytes
if(fileObj.tell() < 128):
return False
fileObj.seek(-128,2)
tag_data = fileObj.read()
if(tag_data[0:3] != b'TAG'):
return False
return getTag(tag_data)
# Detect the encoding and decode
def decodeData(bin_seq):
# print(bin_seq)
result = chardet.detect(bin_seq)
# print(result)
if(result['confidence'] > 0):
try:
return bin_seq.decode(result['encoding'])
except UnicodeDecodeError:
return 'Decode Failed'
# Get ID3v1 tag data
def getTag(tag_data):
# STRIP_CHARS = compat.b(string.whitespace) + b"\x00"
STRIP_CHARS = b"\x00"
tags = {}
tags['title'] = tag_data[3:33].strip(STRIP_CHARS)
if(tags['title']):
tags['title'] = decodeData(tags['title'])
tags['artist'] = tag_data[33:63].strip(STRIP_CHARS)
if(tags['artist']):
tags['artist'] = decodeData(tags['artist'])
tags['album'] = tag_data[63:93].strip(STRIP_CHARS)
if(tags['album']):
tags['album'] = decodeData(tags['album'])
tags['year'] = tag_data[93:97].strip(STRIP_CHARS)
# if(tags['year']):
# tags['year'] = decodeData(tags['year'])
tags['comment'] = tag_data[97:127].strip(STRIP_CHARS)
#@TODO Need to analyze comment to verfiy v1 or v1.1
if(tags['comment']):
tags['comment'] = decodeData(tags['comment'])
tags['genre'] = ord(tag_data[127:128])
return tags
# Set ID3v1 tag data
def setTag():
pass
參考資料:
1屯吊、ID3.org
2送巡、Wiki ID3
3、Python open() 函數(shù)
4盒卸、使用Python讀取和寫入mp3文件的id3v1信息
5骗爆、Python 模塊