使用Python讀取和寫入mp3檔案的id3v1資訊

來源:互聯網
上載者:User
1.起因

一直以來瘋迷“冬吳相對論”,為了整理下載他的MP3花了不少功夫,今天突然發現將電腦中的mp3匯入到itunes後,檔案名稱竟然不識別了。#_* itunes自動識別了mp3的資訊內容。多次一舉麼,檔案名稱挺好。事實如此,讓我深感不完美。一定要將檔案名稱也寫如MP3資訊中區。

網上一搜,一大把的python代碼,都是用了eyeD3這個組件包。照著例子簡單搞了兩下就出來一個版本,運行發現latin_1啥的編碼問題。OK把它的tag和id3還有frames包中的編碼統統改成GBK就能解決了。但是又發現,如果檔案原本沒有id3v1時,擷取title就直接報錯了。找了兩下沒有發現有人提這個問題。看來只能自己動手了。那就完全不用eyeD3包了。因為id3v1確實很簡單。

2.分析

百度就有說,我想寫的這些資訊可儲存於mp3檔案的尾部。

ID3V1比較簡單,它是存放在MP3檔案的末尾,用16進位的編輯器開啟一個MP3檔案,查看其末尾的128個順序存放位元組,資料結構定義如下: 

char Header[3]; /標籤頭必須是"TAG"否則認為沒有標籤/

char Title[30]; /標題/

char Artist[30]; /作者/

char Album[30]; /專集/

char Year[4]; /出品年代/

char Comment[30]; /備忘/

char Genre; /類型/

ID3V1的各項資訊都是順序存放,沒有任何標識將其分開,比如標題資訊不足30個位元組,則使用'\0'補足,否則將造成資訊錯誤。

3.解決

還好,檔案結構不複雜,處理起來就相對簡單。思路很簡單,讀取mp3檔案的尾部128位元組,判斷一下有米有TAG,有了就把最後的128節用我們自己的資訊替換掉,沒有就補充128位元組上去。

4.代碼

最好的文檔就是源碼,當然我回寫注釋的。沒有依賴eyeD3這樣的包,純手工寫法。

#encoding=utf8__author__ ='pcode@qq.com'import osimportstructdefGetFiles(path):"""    讀取指定目錄的檔案    """FileDic=[]    files=os.listdir(path)for f in files:        f=f[:-4]FileDic.append(f)returnFileDic,filesdef_GetLast128K(path,file):    ff1=open(os.path.join(path,file),"rb")    ff1.seek(-128,2)    id3v1data=ff1.read()    ff1.close()return id3v1datadef_GetAllBinData(path,file):    ff1=open(os.path.join(path,file),"rb")    data=ff1.read()    ff1.close()return datadefSetTag(path,file,title,artist,album,year,comment,genre):"""    設定mp3的ID3 v1中的部分參數    char Header[3]; /*標籤頭必須是"TAG"否則認為沒有標籤*/    char Title[30]; /*標題*/    char Artist[30]; /*作者*/    char Album[30]; /*專集*/    char Year[4]; /*出品年代*/    char Comment[30]; /*備忘*/    char Genre; /*類型*/    mp3檔案尾部128位元組為id3v1的資料,如果有資料則讀取修改,無資料則補充    """    header='TAG'#組合出最後128K的id3V1的資料內容    str =struct.pack('3s30s30s30s4s30ss',header,title,artist,album,year,comment,genre)#擷取原始全部資料    data=_GetAllBinData(path,file)#擷取末尾的128位元組資料    id3v1data=_GetLast128K(path,file)#開啟原檔案準備寫入    ff=open(os.path.join(path,file),"wb")try:#判斷是否有id3v1資料if id3v1data[0:3]!=header:#倒數128位元組不是以TAG開頭的說明沒有#按照id3v1的結構補充上去            ff.write(data+str)else:#有的情況下要換一下            ff.write(data[0:-128]+str)        ff.close()print"OK"+title    except:        ff.write(data)print"Error "+title    finally:if ff :ff.close()if __name__=="__main__":#我存放mp3檔案的目錄    path=u"K:\\reading\\閱讀\\相對論"#擷取到檔案名稱和檔案全名    names,files=GetFiles(path)#苦力代碼for i in range(len(files)):#注意編碼解碼        title=names[i].encode('gbk')        artist=u'作者'.encode('gbk')        album=u'相對論'.encode('gbk')        year=''        comment=''        genre=''#調用函數處理SetTag(path,files[i],title,artist,album,year,comment,genre)

5.後續

使用了以後id3v1的資訊全部按檔案名稱改好了,其中的SetTag函數也可以遷移到別的程式裡用來改id3v1的資訊。但是寫檔案那裡,無論是否有TAG都得重寫全部檔案內容。效率一般般。速度沒有eyeD3這種組件快。但那時eyeD3不能支援中文,而且檔案本來沒id3v1資訊時會出錯,自己的就放心多了。 bingo 收工。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.