最近,我一直在尝试编写一个可以更改mp3文件的ID3标签的程序。我设法编写代码来轻松获取这些标签,但我不知道如何编写代码来修改标签。我认为可能没有简单的解决方案,所以我决定尝试一些库。这可能是我的错,但它们都不起作用..
无论如何,我的问题是:如何编写自己的代码来修改ID3标签?如果不是那么容易,有什么可以推荐的库吗?
你应该看看库jAudioTagger。下面是将自定义标签 (TXXX) 写入音频文件的示例:
/**
* This will write a custom ID3 tag (TXXX).
* This works only with MP3 files (Flac with ID3-Tag not tested).
* @param description The description of the custom tag i.e. "catalognr"
* There can only be one custom TXXX tag with that description in one MP3 file
* @param text The actual text to be written into the new tag field
* @return True if the tag has been properly written, false otherwise
*/
public boolean setCustomTag(AudioFile audioFile, String description, String text){
FrameBodyTXXX txxxBody = new FrameBodyTXXX();
txxxBody.setDescription(description);
txxxBody.setText(text);
// Get the tag from the audio file
// If there is no ID3Tag create an ID3v2.3 tag
Tag tag = audioFile.getTagOrCreateAndSetDefault();
// If there is only a ID3v1 tag, copy data into new ID3v2.3 tag
if(!(tag instanceof ID3v23Tag || tag instanceof ID3v24Tag)){
Tag newTagV23 = null;
if(tag instanceof ID3v1Tag){
newTagV23 = new ID3v23Tag((ID3v1Tag)audioFile.getTag()); // Copy old tag data
}
if(tag instanceof ID3v22Tag){
newTagV23 = new ID3v23Tag((ID3v11Tag)audioFile.getTag()); // Copy old tag data
}
audioFile.setTag(newTagV23);
}
AbstractID3v2Frame frame = null;
if(tag instanceof ID3v23Tag){
frame = new ID3v23Frame("TXXX");
}
else if(tag instanceof ID3v24Tag){
frame = new ID3v24Frame("TXXX");
}
frame.setBody(txxxBody);
try {
tag.addField(frame);
} catch (FieldDataInvalidException e) {
e.printStackTrace();
return false;
}
try {
audioFile.commit();
} catch (CannotWriteException e) {
e.printStackTrace();
return false;
}
return true;
}
我最终自己编写了一个标签编辑器,因为我不想使用库。仅适用于 ID3v1 标签。 完整代码
这里是它的工作原理:
因此您所要做的就是将 128 字节写入文件末尾。以
TAG
开头,后跟 30 个字节的标题,30 个字节的艺术家等。流派列表可以在 here 找到。
public void writeID3v1Tags(File file, String title, String artist, String album, String year, String comment, int genreId) { throws IOException {
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
FileChannel channel = randomAccessFile.getChannel();
if (!hasID3v1Tag(channel)) {
channel.position(channel.size());
writeTag(channel, "TAG", 3);
}
writeTag(channel, title, 30);
writeTag(channel, artist, 30);
writeTag(channel, album, 30);
writeTag(channel, year, 4);
writeTag(channel, comment, 30);
writeTag(channel, String.valueOf((char) genreId), 1);
channel.close();
}
private void writeTag(FileChannel channel, String tagValue, int maxLength) throws IOException {
int length = tagValue.length();
if (length > maxLength) {
tagValue = tagValue.substring(0, maxLength);
length = tagValue.length();
}
ByteBuffer byteBuffer = ByteBuffer.wrap(tagValue.getBytes());
channel.write(byteBuffer);
byteBuffer = ByteBuffer.allocate(maxLength - length);
channel.write(byteBuffer);
}
private boolean hasID3v1Tag(FileChannel channel) throws IOException {
channel.position(channel.size() - 128);
String prefix = readTag(channel, 3);
return "TAG".equals(prefix);
}
如果您想要更多标签(例如专辑封面、歌词等等),您需要使用 ID3v2。它的工作原理基本相同,但稍微复杂一点,更多信息见https://id3.org/id3v2.3.0