原文:Mp3文件标签信息读取和写入(Kotlin) - Stars-One的杂货小窝
最近准备抽空完善了自己的星之小说下载器(JavaFx应用 ),发现下载下来的mp3文件没有对应的标签
也是了解可以通过mpatric这个库来实现标签的读取和写入,下面介绍一下关于mp3标签和贴上对应的代码示例
标签介绍
在研究过程,发现mp3音乐标签主要有以下几种格式:
ID3v1- 
ID3v2(目前常用) APEv2
ID3v1位于文件尾部,不支持封面,不支持一些特殊字符,长度短,但兼容老设备。
ID3v2是ID3v1的后继替代者,位于文件头部,支持封面和特殊字符,长度任意。推荐使用。
APEv2位于文件尾部(同时与ID3v1存在时,在ID3v1之前),同样支持封面和特殊字符,但不推荐用于mp3。
常用的主要是ID3v2.而ID3v2格式又可具体分为3种:
- ID3v2.4 UTF-8
 - ID3v2.3 UTF-16
 - ID3v2.3 ISO-8859-1
 
推荐用ID3v2.4 UTF-8,如果设备不支持可退一步用ID3v2.3 UTF-16,如果设备仍不支持可再退一步用ID3v2.3 ISO-8859-1。
如果数码设备不支持,那么再试APEv2或ID3v1。根据设备支持情况进行调整就可以。
使用
引入依赖:
<dependency>
  <groupId>com.mpatric</groupId>
  <artifactId>mp3agic</artifactId>
  <version>0.9.1</version>
</dependency>
@Test
fun testRead() {
    val mp3Path = "D:\\temp\\music-download-test\\封印されし神々(東方風神録) - Whirling Truth.mp3"
    val mp3File = Mp3File(mp3Path)
    if (mp3File.hasId3v2Tag()) {
        val id3v2Tag = mp3File.id3v2Tag
        println("唱片歌曲数量: " + id3v2Tag.track)
        println("艺术家: " + id3v2Tag.artist)
        println("歌曲名: " + id3v2Tag.title)
        println("唱片名: " + id3v2Tag.album)
        println("歌曲长度:" + mp3File.lengthInSeconds + "秒")
        println("码率: " + mp3File.bitrate + " kbps " + if (mp3File.isVbr) "(VBR)" else "(CBR)")
        println("专辑插画类型" + id3v2Tag.albumImageMimeType)
        println("发行时间: " + id3v2Tag.year)
        println("流派: " + id3v2Tag.genre + " (" + id3v2Tag.genreDescription + ")")
        println("注释: " + id3v2Tag.comment)
        println("歌词: " + id3v2Tag.lyrics)
        println("作曲家: " + id3v2Tag.composer)
        println("发行公司: " + id3v2Tag.publisher)
        println("Original artist: " + id3v2Tag.originalArtist)
        println("Album artist: " + id3v2Tag.albumArtist)
        println("版权: " + id3v2Tag.copyright)
        println("URL: " + id3v2Tag.url)
        println("编码格式: " + id3v2Tag.encoder)
        //专辑插画
        val albumImageData = id3v2Tag.albumImage
        if (albumImageData != null) {
            println("专辑插图长度: " + albumImageData.size + " bytes")
            println("专辑插图类型: " + id3v2Tag.albumImageMimeType)
        }
        val imgFile = File("D:\\temp\\output.jpg")
        imgFile.writeBytes(albumImageData)
    }
}
@Test
fun testWrite() {
    //todo m4a转MP3
    //val mp3Path = "D:\\temp\\music-download-test\\Romantic Night.mp3"
    val mp3Path = "D:\\temp\\music-download-test\\test.mp3"
    val imgFile = File("D:\\temp\\music-download-test\\109951167834013257.jpg")
    val mp3File = Mp3File(mp3Path)
    val tag = mp3File.id3v2Tag
    //歌曲名
    tag.title = mp3File.filename
    //歌手
    tag.artist = "张三"
    //唱片名(专辑)
    tag.album = "张三的专辑"
    tag.setAlbumImage(imgFile.readBytes(), MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(imgFile))
    mp3File.save("D:\\temp\\music-download-test\\output.mp3")
}
之后测试,在window系统右键属性就可以看到显示了对应的属性
API大全
Mp3File对象方法
| 方法名 | 说明 | 
|---|---|
| getFrameCount() | 获取MP3文件帧数 | 
| getStartOffset() | 获取起始设置 | 
| getEndOffset() | 获取结束设置 | 
| getLengthInMilliseconds() | 获取MP3长度,单位毫秒 | 
| getLengthInSeconds() | 获取MP3长度,单位秒 | 
| isVbr() | 是否为VBR编码,不是为CBR编码 | 
| getBitrate() | 获取码率 | 
| getBitrates() | 获取码率,返回map,key为码率,value为 MutableInteger 对象 | 
| getChannelMode() | 获取渠道模式 | 
| isCopyright() | 是否有版权 | 
| getEmphasis() | 获取强调信息 | 
| getLayer() | 获取压缩级别 | 
| getModeExtension() | 获取模式扩展 | 
| isOriginal() | 是否是原版 | 
| getSampleRate() | 获取音频采样率 | 
| getVersion() | 获取版本 | 
| hasXingFrame() | 判断是否有 xing帧 | 
| getXingOffset() | 获取xing设置 | 
| getXingBitrate() | 获取xing比特率 | 
| hasId3v1Tag() | 判断是否有3v1本版标签 | 
| getId3v1Tag() | 获取3v1本版标签 | 
| setId3v1Tag(ID3v1 var1) | 设置3v1本版标签 | 
| removeId3v1Tag() | 移除3v1本版标签 | 
| hasId3v2Tag() | 判断是否有3v2本版标签 | 
| getId3v2Tag() | 获取3v2本版标签 | 
| setId3v2Tag(ID3v2 var1) | 设置3v2本版标签 | 
| removeId3v2Tag() | 移除3v2本版标签 | 
| hasCustomTag() | 判断是否有自定义标签 | 
| getCustomTag() | 获取自定义标签 | 
| setCustomTag(byte[] var1) | 设置自定义标签 | 
| removeCustomTag() | 移除自定义标签 | 
| save(String var1) | 保存mp3文件 | 
ID3v1对象方法
| 方法名 | 说明 | 
|---|---|
| getVersion() | 获取版本 | 
| getTrack() | 获取唱片歌曲数量 | 
| setTrack(String var1) | 设置唱片歌曲数量 | 
| getArtist() | 获取艺术家 | 
| setArtist(String var1) | 设置艺术家 | 
| getTitle() | 获取歌曲名 | 
| setTitle(String var1) | 设置歌曲名 | 
| getAlbum() | 获取唱片名 | 
| setAlbum(String var1) | 设置唱片名 | 
| getYear() | 获取发行时间 | 
| setYear(String var1) | 设置发行时间 | 
| getGenre() | 获取流派 | 
| setGenre(int var1) | 设置流派 | 
| getGenreDescription() | ; 获取流派描述 | 
| getComment() | ; 获取注释 | 
| setComment(String var1) | 设置注释 | 
| toBytes() | 转换为字节数组 | 
ID3v2对象方法(ID3v2为ID3v1的子类)
| 方法名 | 说明 | 
|---|---|
| getPadding() | 判断是否填充 | 
| setPadding(boolean var1) | 设置是否填充 | 
| hasFooter() | 判断是否有页脚 | 
| setFooter(boolean var1) | 设置页脚 | 
| hasUnsynchronisation() | 判断是否有不同步 | 
| setUnsynchronisation(boolean var1) | 设置是否有不同步 | 
| getBPM() | 获取每分钟节拍数 | 
| setBPM(int var1) | 设置每分钟节拍数 | 
| getGrouping() | 获取分组 | 
| setGrouping(String var1) | 设置分组 | 
| getKey() | 获取调号,它关系到我们整首歌曲的音高范围 | 
| setKey(String var1) | 设置调号 | 
| getDate() | 获取日期 | 
| setDate(String var1) | 设置日期 | 
| getComposer() | 获取作曲家 | 
| setComposer(String var1) | 设置作曲家 | 
| getPublisher() | 获取发版者 | 
| setPublisher(String var1) | 设置发版者 | 
| getOriginalArtist() | 获取原创艺术家 | 
| setOriginalArtist(String var1) | 设置原创艺术家 | 
| getAlbumArtist() | 获取专辑艺术家 | 
| setAlbumArtist(String var1) | 设置专辑艺术家 | 
| getCopyright() | 获取版权信息 | 
| setCopyright(String var1) | 设置版权信息 | 
| getArtistUrl() | 获取艺术家url地址 | 
| setArtistUrl(String var1) | 设置艺术家url地址 | 
| getCommercialUrl() | 获取广告url地址 | 
| setCommercialUrl(String var1) | 设置广告url地址 | 
| getCopyrightUrl() | 获取版权url地址 | 
| setCopyrightUrl(String var1) | 设置版权url地址 | 
| getAudiofileUrl() | 获取音频文件路径 | 
| setAudiofileUrl(String var1) | 设置音频文件路径 | 
| getAudioSourceUrl() | 获取音频资源路径 | 
| setAudioSourceUrl(String var1) | 设置音频资源路径 | 
| getRadiostationUrl() | 获取广播url地址 | 
| setRadiostationUrl(String var1) | 设置广播url地址 | 
| getPaymentUrl() | 获取付款url地址 | 
| setPaymentUrl(String var1) | 设置付款url地址 | 
| getPublisherUrl() | 获取发版url地址 | 
| setPublisherUrl(String var1) | 设置发版url地址 | 
| getUrl() | 获取MP3地址 | 
| setUrl(String var1) | 设置MP3地址 | 
| getPartOfSet() | 获取部分配置信息 | 
| setPartOfSet(String var1) | 设置部分配置信息 | 
| isCompilation() | 获取是否汇编 | 
| setCompilation(boolean var1) | 设置是否汇编 | 
| getChapters() | 获取章节 | 
| setChapters(ArrayList var1) | 设置章节 | 
| getChapterTOC() | 获取章节目录 | 
| setChapterTOC(ArrayList var1) | 设置章节目录 | 
| getEncoder() | 获取编码格式 | 
| setEncoder(String var1) | 设置编码格式 | 
| getAlbumImage() | 专辑插画 | 
| setAlbumImage(byte[] var1, String var2) | 设置专辑插画 | 
| setAlbumImage(byte[] var1, String var2, byte var3, String var4) | 设置专辑插画 | 
| clearAlbumImage() | 清除专辑插画 | 
| getAlbumImageMimeType() | 专辑插画类型 | 
| getWmpRating() | 获取评分 | 
| setWmpRating(int var1) | 设置评分 | 
| getItunesComment() | 获取调音方式 | 
| setItunesComment(String var1) | 设置调音方式 | 
| getLyrics() | 获取歌词 | 
| setLyrics(String var1) | 设置歌词 | 
| setGenreDescription(String var1) | 设置类型说明 | 
| getDataLength() | 获取数据长度 | 
| getLength() | 获取长度 | 
| getObseleteFormat() | 获取过时的格式 | 
| getFrameSets() | 获取帧组 | 
| clearFrameSet(String var1) | 清除帧组 | 
参考
- mpatric/mp3agic: A java library for reading mp3 files and reading / manipulating the ID3 tags (ID3v1 and ID3v2.2 through ID3v2.4).
 - mp3处理工具(mp3agic)_郑重其事,鹏程万里的博客-CSDN博客
 - 请问mp3音乐标签中,ID3v1,ID3v2,APEv2这三种类型的标签能否任意添加或者删除? - 知乎
 - Java为MP3文件嵌入封面图片_来自大山深处的Doge_的博客-CSDN博客