我创建了setArtwork方法来在.m4a容器中设置一个AAC文件的图稿,并且在运行main方法时它确实可以实现我想要的效果
public static void setArtwork(File art, File m4a) throws Exception{
Mp4TagReader reader = new Mp4TagReader();
Mp4TagWriter writer = new Mp4TagWriter();
RandomAccessFile song = new RandomAccessFile(m4a.toString(),"rw");
Mp4Tag mp4tag = reader.read(song);
Artwork artwork = ArtworkFactory.createArtworkFromFile(art);
mp4tag.addField(artwork);
mp4tag.setField(artwork);
RandomAccessFile temp = new RandomAccessFile(m4a,"rw");
writer.write(mp4tag,song,temp);
}
public static void main(String[] args) throws Exception{
File art = new File("C:\\Users\\Zubair\\Documents\\music\\coverArt.jpeg");
File m4a = new File("C:\\Users\\Zubair\\Documents\\music\\song.m4a");
setArtwork(art,m4a);
}
但是,当我尝试在不同类中的其他方法中使用setArtwork方法时,实际上并没有将mp4标签保存到File中。我进行了一些调试,以查看图片是否甚至已添加到美工标签中,并且看起来都不错,但是似乎标签未写入文件中。
public static void mp3Tom4a(File mp3File, File m4aFolder, File coverArt) throws Exception {
String input = mp3File.toString();
String name = mp3File.getName();
String output = name.substring(0,name.indexOf(MP3)) + M4A;
output = m4aFolder.toString() + "\\" + output;
//cd ffmpeg\bin && ffmpeg -y -i input.mp3 -an -vcodec copy cover.jpg && ffmpeg -y -i input.mp3 -c:a aac -b:a 192k -vn output.m4a
ProcessBuilder builder = new ProcessBuilder(
"cmd.exe","/c","cd ffmpeg\\bin && ffmpeg -y -i "
+ input +" -an -vcodec copy "+coverArt+
" && ffmpeg -y -i " + input + " -c:a aac -b:a 128k -vn " + output);
builder.redirectErrorStream(true);
builder.start();
JAudioData.setArtwork(coverArt,new File(output));
}
public static void main(String[] args) throws Exception {
mp3Tom4a(new File("C:\\Users\\Zubair\\Documents\\music\\song.mp3"),
new File("C:\\Users\\Zubair\\Documents\\music"),
new File("C:\\Users\\Zubair\\Documents\\music\\coverArt.jpeg"));
}
setArtwork仅在其自身类的main方法中有效时没有意义,尤其是因为我用于参数的对象彼此相同,因此结果应该没有差异。我认为这可能与正在更新的RandomAccessFile对象有关,但物理存储未更新
编辑-如果我注释掉builder.start(),则它可以成功将mp4tag写入m4a文件。但是我不明白为什么拥有builder.start()可以防止这种情况的发生。我最好的猜测是,因为builder.start()是创建song.m4a的原因,所以它仍在被它“编辑”,并且不能被任何其他进程编辑。
答案 0 :(得分:0)
我从另一个线程中找到了答案
https://stackoverflow.com/a/5483976/10194055
课程流程
由于某些本机平台仅为标准输入和>输出流提供有限的缓冲区大小,因此未能及时写入>子进程的输入流或读取子进程的输出流可能导致子进程阻塞甚至死锁。
无法从Process中清除输入流的缓冲区(通过管道将其传送到> subprocess的输出流)可能会导致子进程阻塞。
这是我的功能代码的样子。其他类和方法保持完全相同
public static void mp3Tom4a(File mp3File, File m4aFolder, File coverArt) throws Exception {
String input = mp3File.toString();
String name = mp3File.getName();
String output = name.substring(0, name.indexOf(MP3)) + M4A;
output = m4aFolder.toString() + "\\" + output;
//cd ffmpeg\bin && ffmpeg -y -i input.mp3 -an -vcodec copy cover.jpg && ffmpeg -y -i input.mp3 -c:a aac -b:a 192k -vn output.m4a
ProcessBuilder builder = new ProcessBuilder(
"cmd.exe", "/c", "cd ffmpeg\\bin && ffmpeg -y -i "
+ input + " -an -vcodec copy " + coverArt +
" && ffmpeg -y -i " + input + " -c:a aac -b:a 128k -vn " + output);
builder.redirectErrorStream(true);
Process p = builder.start();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((reader.readLine()) != null) {}
p.waitFor();
JAudioData.setArtwork(coverArt, new File(output));
}