问题背景:现在有一个没有封面的mp3文件,和封面jpg图片文件,将图片嵌入到mp3文件中作为封面。
直接上代码示例
/**
* 为 MP3 写入封面图片
*
* @param sourcePath
* @param img
* @return
*/
public static void writeMP3Image(String sourcePath, BufferedImage img) throws IOException, InvalidDataException, UnsupportedTagException, NotSupportedException {
// 图片读取成 byte 数组
ByteOutputStream baos = new ByteOutputStream();
ImageIO.write(img, "jpg", baos);
// 创建临时文件
File destFile = new File(sourcePath);
File tempFile = new File(destFile.getParent() + File.separator + "temp - " + destFile.getName());
FileUtils.copy(sourcePath, tempFile.getAbsolutePath());
// 将 tag 设置进 MP3 并保存文件
com.mpatric.mp3agic.Mp3File mp3file = new com.mpatric.mp3agic.Mp3File(tempFile.getAbsolutePath());
ID3v2 tag = mp3file.getId3v2Tag();
tag.setAlbumImage(baos.getBytes(), "image/jpeg");
mp3file.save(destFile.getAbsolutePath());
System.gc();
tempFile.delete();
}
mp3agic
依赖
<dependency>
<groupId>com.mpatric</groupId>
<artifactId>mp3agic</artifactId>
<version>0.9.1</version>
</dependency>
思路:先将专辑图片(BufferedImage
)转为byte
数组,然后创建原来mp3文件的临时文件,通过调用Mp3File
读取临时文件的Id3v2Tag
,再将byte
数组写进去,保存文件即可,最后删除临时文件。
有几个注意的地方:
-
jaudiotagger
虽然好用,但是仅仅建议只拿来读取mp3信息,如果是修改信息也只建议修改文本信息,像嵌入图片这种“力气活”还是建议交给mp3agic
来负责,因为之前踩了不少jaudiotagger
的坑,依旧在处理嵌入图片上报异常。而且,jaudiotagger处理这件事也比较繁琐:先读取Id3v2Tag
,再创建APIC
的frame
,还要创建APIC
的body
,即便是这样处理还是异常;而mp3agic
只需要读取Id3v2Tag
写入bytes
就可以了 -
为什么要创建临时文件处理再覆盖源文件? 因为直接处理源文件,当你需要保存时是不支持直接覆盖源文件的,此文件已被占用
-
为什么调用gc后再删除临时文件?
Mp3File
对象创建后,此文件被占用,而且没有close
相关的方法,删除不了;通过调用gc可以释放Mp3File
对象,才能成功删除