Additional information for Mp3 files

Reading Data

The ID3 format used by Mp3 is more complicated than other metadata formats, so the interface is also more complex. An Mp3 can contain both a ID3v1 tag and an ID3v2 tag, both tags are optional. The ID3v1 tag can be version 1.0 or version 1.1. An ID3v2 tag can be version 2.2, 2.3 or 2.4 and the differences between the versions is quite considerable.

The stuff you might want to know about but you can't change is stored in the AudioHeader class


MP3File f      = (Mp3File)AudioFileIO.read(testFile);
MP3AudioHeader audioHeader = f.getAudioHeader();
System.out.println(audioHeader.getTrackLength());
System.out.println(audioHeader.getSampleRateAsNumber());
System.out.println(mp3AudioHeader.getChannels());
System.out.println(mp3AudioHeader.isVariableBitRate());

Mp3 provides a subclass called MP3AudioHeader that contains additional information.


System.out.println(mp3AudioHeader.getTrackLengthAsString());
System.out.println(mp3AudioHeader.getMpegVersion());
System.out.println(mp3AudioHeader.getMpegLayer());
System.out.println(mp3AudioHeader.isOriginal());
System.out.println(mp3AudioHeader.isCopyrighted());
System.out.println(mp3AudioHeader.isPrivate());
System.out.println(mp3AudioHeader.isProtected());
System.out.println(mp3AudioHeader.getBitRate());
System.out.println(mp3AudioHeader.getEncodingType());
System.out.println(mp3AudioHeader.getEncoder());

The metadata information that you can change is stored in tags. If the file contains and ID3v2 tag the getTag() method will return the ID3v2 Tag , if it does not exist but there is a ID3v1 tag it will return this instead, otherwise it will return null. You can use getID3v1Tag() and getID3v2Tag() for more control. Alternatively Jaudiotagger provides a getID3v2TagAsv24() method, this returns the v2Tag converted to v24 format if it was not already in v24 format, the advantage of this is that you can treat all Mp3 files as if their v2 tag is in v24 format whether or not it actually is.


MP3File f      = (Mp3File)AudioFileIO.read(testFile);
Tag tag        = f.getTag();
ID3v1Tag         v1Tag  = (ID3v1Tag)tag;
AbstractID3v2Tag v2tag  = f.getID3v2Tag()
ID3v24Tag        v24tag = (AbstractID3v2Tag)f.getID3v2TagAsv24();

The v1 tag only contains a very limited set of fields, these can be read as follows

  
System.out.println(tag.getFirstArtist());
System.out.println(tag.getFirstAlbum());
System.out.println(tag.getFirstTitle());
System.out.println(tag.getFirstComment());
System.out.println(tag.getFirstYear());
System.out.println(tag.getFirstTrack());	

The rest of this document deals with the ID3v2 tag, you can check that an ID3v2 tag exists with


f.hasID3v2Tag();	

In ID3v2, fields are known as frames, for simple text fields you can extract the information with


System.out.println(v2Tag.getFirst(ID3v24Frames.FRAME_ID_ARTIST));
System.out.println(v2Tag.getFirst(ID3v24Frames.FRAME_ID_ALBUM));
System.out.println(v2Tag.getFirst(ID3v24Frames.FRAME_ID_YEAR));

Or you can retrieve the frame itself and then get details of its body, this is most useful when dealing with one of the manu binary fields supported in ID3v2


AbstractID3v2Frame frame = v2Tag.getFirstField(ID3v24Frames.FRAME_ID_ARTIST);
System.out.println(text.getBody().getId();
if(frame.getBody() instanceof AbstractFrameBodyTextInfo)
{
	AbstractFrameBodyTextInfo textBody = (AbstractFrameBodyTextInfo)frame.getBody(); 
	System.out.println(text.getBody().getText();
}

Retreiving cover art can be done as follows

BufferedImage bi=null;
TagField imageField = af.getTag().get(TagFieldKey.COVER_ART).get(0);
if(imageField instanceof AbstractID3v2Frame)
{
    FrameBodyAPIC imageFrameBody = (FrameBodyAPIC)((AbstractID3v2Frame)imageField).getBody();
    if(!imageFrameBody.isImageUrl())
    {
        byte[] imageRawData = (byte[])imageFrameBody.getObjectValue(DataTypes.OBJ_PICTURE_DATA);
        bi=ImageIO.read(new ByteArrayInputStream(imageRawData));
    }
}	

Writing Data

You can create a new tag of your chosen version if one doesnt exist as follows

ID3v24Tag v2tag = new ID3v24Tag();
v2tag.setComment("Comment");
mp3File.setID3v2Tag(v2tag);

You can add images

RandomAccessFile imageFile = new RandomAccessFile(new File("testdata", "coverart.png"), "r");
byte[] imagedata = new byte[(int) imageFile.length()];
imageFile.read(imagedata);
v2tag.add(tag.createArtworkField(imagedata,"image/png"));
af.commit();

When adding images you can add linked images in addition to embedding images

v2tag.add(v2tag.createLinkedArtworkField("../testdata/coverart.jpg"));