如何在Java中编辑MP3文件(ID3)?

7
最近,我一直在尝试编写一个程序,可以修改MP3文件的ID3标签。我成功编写了获取这些标签的代码,但是我不知道如何编写修改标签的代码。我认为可能没有简单的解决方案,所以我决定尝试一些库。也许是我的问题,但它们都不起作用...
无论如何,我的问题是:我如何编写自己的代码来修改ID3标签?如果不是那么容易,你能否推荐一些库?

1
这个问题应该已经关闭了。它既是“过于宽泛”——“我如何编写自己的代码来修改ID3标签?”又是一个请求推荐的问题。 - Stephen C
@StephenC 虽然问题本身提得不是很好,但它似乎对社区有着重要的价值。超过13,000次的浏览量表明许多其他用户也在问这个问题。 - Cardinal System
问题不在于提问的方式不好。问题在于这是一个请求推荐的问题,而请求推荐明确地属于禁止讨论的范畴。即使很多用户希望StackOverflow成为一个推荐网站也没有用,事实是它并不是,而“禁止讨论哪些内容”页面已经非常清楚地说明了这一点。 - Stephen C
@StephenC,如果是这样的话,我想在一个更适合StackOverflow的问题上再发一份悬赏。[这个问题] (https://stackoverflow.com/q/41459061/5645656)看起来更符合主题。你同意吗? - Cardinal System
关于奖金的适当使用、推荐问题、迁移等问题,请在meta.stackoverflow.com上提出。 - Stephen C
显示剩余3条评论
3个回答

3

您应该看一下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;
}

2
顺便说一句,谢谢。我已经寻找这样的答案很久了。+100 - Cardinal System

2
我不想使用库,所以自己编写了一个标签编辑器,它只适用于ID3v1标签。 完整代码 这里是它的工作原理: enter image description here 所以你需要做的就是向文件末尾写入128个字节。从TAG开始,接着30个字节为标题,30个字节为艺术家,等等。流派列表可以在这里找到。
    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

添加了一些解释和代码。 - nhcodes

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接