使用Python讀取Mp3的標(biāo)簽信息

什么是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個字符。


image

具體的字段信息

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)給用戶斗幼。


image

列舉一些特性:

  • 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 模塊

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蔽介,隨后出現(xiàn)的幾起案子摘投,更是在濱河造成了極大的恐慌,老刑警劉巖虹蓄,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件犀呼,死亡現(xiàn)場離奇詭異,居然都是意外死亡薇组,警方通過查閱死者的電腦和手機(jī)外臂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來律胀,“玉大人宋光,你說我怎么就攤上這事√烤” “怎么了罪佳?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長黑低。 經(jīng)常有香客問我赘艳,道長,這世上最難降的妖魔是什么克握? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任蕾管,我火速辦了婚禮,結(jié)果婚禮上菩暗,老公的妹妹穿的比我還像新娘娇掏。我一直安慰自己,他們只是感情好勋眯,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布婴梧。 她就那樣靜靜地躺著下梢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪塞蹭。 梳的紋絲不亂的頭發(fā)上孽江,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天,我揣著相機(jī)與錄音番电,去河邊找鬼岗屏。 笑死,一個胖子當(dāng)著我的面吹牛漱办,可吹牛的內(nèi)容都是我干的这刷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼娩井,長吁一口氣:“原來是場噩夢啊……” “哼暇屋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起洞辣,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤咐刨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后扬霜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體定鸟,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年著瓶,在試婚紗的時候發(fā)現(xiàn)自己被綠了联予。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡材原,死狀恐怖沸久,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情华糖,我是刑警寧澤麦向,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布瘟裸,位于F島的核電站客叉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏话告。R本人自食惡果不足惜兼搏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望沙郭。 院中可真熱鬧佛呻,春花似錦、人聲如沸病线。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绑莺,卻和暖如春暖眼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纺裁。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工诫肠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人欺缘。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓栋豫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谚殊。 傳聞我的和親對象是個殘疾皇子丧鸯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容