使用第三方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-自由无损音频压缩编码...(貌似目前越来越流行无损音乐,无论是硬件播放器还是音频的高保真文件格式,或者本来就流行,奈我从未发现~~)
然后就是查看JAudiotagger API,编写代码,就简单多了...
此文不对Flac中的每一个Tag信息进行英-中文对照说明,如果在音乐技术方面有深入研究的朋友可以私下交流沟通或有更好的网站方便提供一下,不胜感激~~PS:可以根据Tag映射中的英文key与Mp3tag中文版对照,或许可以找到答案。。。
下面说明一下读取和写入(编辑)Tag信息的一般步骤及可能出现的困惑或卡壳(Stuck):
1,阅JAudiotagger API知,使用FlacFileReader对象的read方法读取一个Flac文件,返回一个AudioFile(接口)类型的对象(实现了该接口的类的实例),再通过AudioFile中的方法getAudioHeader和getTag分别获得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,其它的信息不会丢失)。
使用第三方Java类库jaudiotagger完成Flac音频文件metadata(元数据)的读和修改的更多相关文章
- Qt笔记——连接第三方库&用libZPlay库获取音频文件的艺术家、专辑等信息
连接第三方库libZPlay 概述 需要.a/.lib ,.h , .dll 三个文件 官网下载 http://libzplay.sourceforge.net/ import .h 链接 .a 放入 ...
- C语言解析WAV音频文件
C语言解析WAV音频文件 代码地址: Github : https://github.com/CasterWx/c-wave-master 目录 前言 了解WAV音频文件 什么是二进制文件 WAV的二 ...
- Java如何检查文件是否在服务器上被修改了?
在Java编程中,如何检查文件是否在服务器上被修改了? 以下示例显示如何检查文件是否在服务器上进行了修改. package com.yiibai; import java.net.URL; impor ...
- 让时间处理简单化 【第三方扩展类库org.apache.commons.lang.time】
JAVA的时间日期处理一直是一个比较复杂的问题,大多数程序员都不能很轻松的来处理这些问题.首先Java中关于时间的类,从 JDK 1.1 开始,Date的作用很有限,相应的功能已由Calendar与D ...
- Effective Java 第三版——59. 熟悉并使用Java类库
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- Java 类库和常用类库
Java 类库概念: Java 的应用程序接口 (API) 以包的形式来组织,每个包提供了大量的相关类.接口和异常处理类,这些包的集合就是 Java 的类库 包名以 Java 开始的包是 Java 核 ...
- [Liferay6.2]启动Tomcat提示APR不能在java类库路径中被找到的解决办法
问题描述 启动liferay之后,在控制台中打印出会打印出以下信息: 信息: The APR based Apache Tomcat Native library which allows optim ...
- 使用CocoaPods管理第三方开源类库
iOS开发中经常会用到许多第三方开源类库,比如AFNetworking.FMDB.JSONKit等等,使用CocoaPods这个工具就能很方便得对工程中用到的类库进行管理,包括自动下载配置以及更新. ...
- xcode引入第三方静态类库 duplicate symbol _OBJC_XXX 重复编译错误
xcode引入第三方静态类库 duplicate symbol _OBJC_XXX 重复编译错误 一:场景 xcode 同时引入了 libA.a, libB.a 两个静态类库,如果 这两个静态类库之中 ...
随机推荐
- IntelliJ IDEA 2017 Dubbo Elastic-job Redis Zookeeper RabbitMQ FastDFS MyCat 简介以及部分实现(三)
前言 首先需要说明一下,与前两章的安装篇不太一样,这篇主要扫清一下这些插件/框架 等都是干什么用的,大多数都会用于服务端或监测工具或其他,作为新手建立一个大概的思想更好的了解自己的项目.废话不多 ...
- UOJ#468. 【ZJOI2019】Minimax搜索 动态DP
原文链接www.cnblogs.com/zhouzhendong/p/UOJ468.html 前言 毒瘤题 题解 首先,将问题稍加转化,将"等于k"转化为"小于等于k&q ...
- CSS3 clip-path & clip-path 打破矩形设计的限制
CSS 形状模块标准1(CSS Shapes Module Level 1)这个规范打破了 WEB 中的矩形盒模型的限制,并且将网页设计提升到一个新的高度. 关于 Shapes 规范 shape-ou ...
- Easytrader踩坑之旅(二)
快速阅读 用的是THSTrader进行的调试,同花须必须用8.0的. 在新的机子重新安装requirements已经调用同花顺查股票余额. 继续昨天的话费. 昨天到最后,虽然显示了余额,但是和自己帐户 ...
- 2019年领航杯 江苏省网络信息安全竞赛 初赛部分writeup
赛题已上传,下载连接:https://github.com/raddyfiy/2019linghangcup 做出了全部的misc和前三道逆向题,排名第10,暂且贴一下writeup. 关卡一 编码解 ...
- pythonw.exe不能用
其实可以直接执行python目录下的Lib/idlelib/idle.bat即可,对于非安装版的python来说开始菜单是找不到启动快捷方式的.
- Win10 剪贴板 快捷键是什么?
使用基于云的剪贴板从一台电脑上复制图像和文本并粘贴到另一台电脑上.你不仅可以从剪贴板历史记录中粘贴,还可以固定你发现自己经常使用的项目. 若要随时访问剪贴板历史记录,请按 Windows 徽标键 ...
- 【Java/Json】Java对Json进行建模,分词,递归向下解析构建Json对象树
伸手党的福音 代码下载:https://files.cnblogs.com/files/xiandedanteng/JsonLexerBuilder20191202.rar 互联网上成型的对Json进 ...
- Python带参数的函数装饰器
# -*- coding: utf-8 -*- # author:baoshan # 带参数的函数装饰器 def say_hello(country): def wrapper(func): def ...
- idea的一些常用快捷键
快捷键 1.进入实现方法的快捷键 Ctrl + Alt + B Ctrl + Alt + 鼠标点击 2.自动给方法添加注释的快捷键 输入/**,然后回车 3.删除一行 CTRL + Y / CTRL ...