使用第三方Java類庫jaudiotagger完成Flac音頻文件metadata(元數據)的讀和修改


  最近需要使用Java Swing做個讀寫Flac格式音頻文件的小GUI工具,雖然Mp3tag完全可以完成Flac的讀寫(編輯)任務,但是為了簡化工作流程(編輯Flac信息后調用其它系統的接口完成部分信息上傳等功能),需要開發一個集成類似Mp3tag功能和額外功能於一體的小工具。

  開發前的思考~~,“用JDK提供的IO(NIO)讀寫Flac?...”,“Flac的格式?...”,“一直潛心於JavaWeb和服務端接口開發...幾乎沒做過Java的GUI(Swing/AWT)!...”。。

  后來,在網上Google了一下是否有第三方專門處理音頻文件(包括MP3、ape等等)的Java類庫可以使用:結果用中文關鍵字檢索很難找到滿意的答案,最后在Stack Overflow搜索到一個標題為“Reading metadata from FLAC files with Java”的Answer中找到了答案“Try using JAudiotagger. It supports MP3, MP4, Ogg Vorbis, FLAC and WMA, and it has limited support for WAV and Real.”,接着,下載jar包,或者使用Maven構建工程的話,添加dependency即可。

<dependency>
    <groupId>org</groupId>
    <artifactId>jaudiotagger</artifactId>
    <version>2.0.3</version>
</dependency>       

  其實,在讀寫Flac文件之前,還是要先了解Flac是什么...Free Lossless Audio Codec-自由無損音頻壓縮編碼...(貌似目前越來越流行無損音樂,無論是硬件播放器還是音頻的高保真文件格式,或者本來就流行,奈我從未發現~~

  Wiki   官網   Flac的格式

  然后就是查看JAudiotagger API,編寫代碼,就簡單多了...

  此文不對Flac中的每一個Tag信息進行英-中文對照說明,如果在音樂技術方面有深入研究的朋友可以私下交流溝通或有更好的網站方便提供一下,不勝感激~~PS:可以根據Tag映射中的英文key與Mp3tag中文版對照,或許可以找到答案。。。

  下面說明一下讀取和寫入(編輯)Tag信息的一般步驟及可能出現的困惑或卡殼(Stuck):

  1,閱JAudiotagger API知,使用FlacFileReader對象的read方法讀取一個Flac文件,返回一個AudioFile(接口)類型的對象(實現了該接口的類的實例),再通過AudioFile中的方法getAudioHeadergetTag分別獲得AudioHeader(接口)類型的對象和FlacTag類(實現了Tag接口)的對象。

  2, 利用獲得的AudioHeader和FlacTag的對象即可獲得想要的元數據(Metadata)信息,包括采樣率(SampleRate)、制作格式或制作技術(Format)、單曲名(TITLE)、單曲藝術家(ARTIST)、專輯名(ALBUM)、專輯藝術家(ALBUM_ARTIST)、音軌號(TRACK)、語言(LANGUAGE)、版權方(COPYRIGHT)等等,使用FlacTag對象的getFirstArtwork方法可以獲得圖片。

  3,關於FlacTag中的Tag信息的Key值,有三種情況,一個是枚舉FieldKey中的Key,另一個是FieldKey中沒有的但是Tag映射表中有的Key;在讀取Key對應的value值時,有兩個重載的方法:getFirst(FieldKey id) 和getFirst(java.lang.String id),后面的方法包含了Tag映射中所有的key,當然也包括FieldKey枚舉中的Key;最后一個就是Tag映射表中沒有的,也就是自定義的key。

  獲取單曲名稱時,兩個方法都可以,如下:

tag.getFirst("TITLE")
tag.getFirst(FieldKey.TITLE)

  但是獲取版權方Copyright(flac中對應的key是COPYRIGHT,可以從Tag映射表中查到),但是FieldKey的枚舉中沒有(這個可以通過修改JAudiotagger源代碼在枚舉里面加上需要的key,不過完全沒必要,JAudiotagger也只是把主要的可能比較重要比較常用的、一般Flac文件中都有的key放到枚舉里面,通過重載的方法只要傳入key的字符串id參數即可),像Copyright只好使用tag.getFirst("COPYRIGHT")方法讀取版權信息。

 4,在修改Tag信息時,也是有兩個方法,setField(FieldKey genericKey, java.lang.String value) 和setField(java.lang.String vorbisCommentKey, java.lang.String value) ,原因同3,像Copyright這樣的Tag信息只好使用tag.setField("COPYRIGHT", "XX唱片公司");了。
 修改單曲名時,兩個方法都可以,如下:
tag.setField(FieldKey.TITLE, "讓一切隨風");
tag.setField("TITLE", "讓一切隨風");

  仔細一點會從API發現FlacTag對象有如下方法(判讀一個Tag的key是否存在):

tag.hasField("COPYRIGHT")

  如果返回true,則讀取時可能有版權信息,因為有可能只是在Flac文件中加了COPYRIGHT卻沒有設置值,沒有值則返回"",不返回null;如果返回false,顯然Flac文件中還沒有COPYRIGHT;無論hasField方法返回的是true還是false,只要被判斷的key在Tag映射表存在,都可以直接調用tag.setField("COPYRIGHT", "XX唱片公司");方法為COPYRIGHT或者其它key設置值。

  5,3和4中討論的Tag(FlacTag)信息中的key都是Tag映射中有的Key,如果想要自定義一個key,並為自定義的key設置值,且在下次讀取該Flac文件時可以讀出這個自定義key的值,就需要另外的方法addField(java.lang.String vorbisCommentKey, java.lang.String value) ,例如自定義一個假設叫做ISTEST的key,如下:

tag.addField("ISTEST", "true");

  6, 再仔細一點就會發現,還有一個addField的重載方法,addField(FieldKey genericKey, java.lang.String value) ,這是什么意思呢?如果執行

tag.addField("COPYRIGHT")又會怎樣呢?蠻奇怪的,為什么讀取Tag信息的時候是getFirst方法?為什么有個First呢?
  假設Flac文件中已經有TITLE和COPYRIGHT,然后再執行下面兩條語句:
tag.addField(FieldKey.TITLE,"讓一切隨心");
tag.addField("COPYRIGHT","YY唱片公司");
通過調用tag.getVorbisCommentTag()方法,觀察一下OGG Tag content的內容如下:

  如果分別調用getFirst方法去獲取TITLE和COPYRIGHT的值,顯然分別是“讓一切隨風”和“XX唱片公司”。

  7,4中所言可以為Tag映射表中存在的key,即使Flac文件中沒有,也可以通過setField方法設置值,那么自定義的key可不可以呢?答案是肯定的,即可以使用setField為Flac文件添加一個自定義的Tag信息。

  通過API和代碼測試,addField和setField的區別當然也很容易就會想到,addField會不斷的create,而setField只在第一次設置值時發現key不存在才會create並設置值,否則只是改變value的值。

   8, 刪除Tag信息,直接刪除key即可,方法deleteField(FieldKey fieldKey) 和deleteField(java.lang.String id) ,這兩個方法均會刪除6中所add的所有相同key的Tag信息,表現就是刪除后調用hasField方法返回false。

   9, API中還有createField以及對圖片的獲取、圖片信息的添加修改如setField(Artwork artwork) 等,暫不敘述。

  10, 關於Tag信息修改后的保存到flac文件中去:在Tag信息通過setField方法修改后,使用FlacFileWriter對象的write方法將讀出來的AudioFile對象“寫回去”即可(flac文件只會改變set的key-value或者添加一個新的key或者刪除相同的某個key及對應value,其它的信息不會丟失)。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM