MPEG::ID3v2Tag - Parses and creates ID3v2 Tags for MPEG audio files.


  use MPEG::ID3v2Tag;
  use IO::File;
  # create a tag
  $tag = MPEG::ID3v2Tag->new();
  $tag->add_frame( "TIT2", "Happy Little Song" );    # one step
  $frame = MPEG::ID3Frame::TALB->new("Happy little album");
  $tag->add_frame($frame);                           # two steps
  $tag->add_frame( "WCOM", "" );
      -picture_type => 0,
      -file         => "happy_little_song.gif"
  print OUTFILE $tag->as_string();
  # read a tag from a file and dump out some data.
  $fh = IO::File->new("<happysong.mp3");
  binmode $fh;
  $tag = MPEG::ID3v2Tag->parse($fh);
  for $frame ( $tag->frames() ) {
      print $frame->frameid(), "\n";    # prints TALB, TIT2, WCOM, etc.
      if ( $frame->flag_read_only() ) {
          print "  read only\n";
      if ( $frame->fully_parsed() && $frame->frameid =~ /^T.../ ) {
          print "  frame text is ", $frame->text(), "\n";
      if ( $frame->fully_parsed() && $frame->frameid =~ /^W.../ ) {
          print "  url is ", $frame->url(), "\n";


MPEG::ID3v2Tag is a class capable of parsing and creating ID3v2 revision 3 tags. While not all frames are fully supported, it's easy to add support for more.

The object doesn't (currently) support modification of .mp3 files; the caller has to handle the mechanics of prepending the tag to the file.


$tag = MPEG::ID3v2Tag->new()

Creates a MPEG::ID3v2Tag. Takes no parameters.

$arrayref = $tag->frames()
@array = $tag->frames()

Returns an array or arrayref containing all the MPEG::ID3Frame-derived objects from the tag. See FRAME SUPPORT for details on what frames can do.

$tagdata = $tag->as_string

Returns the complete tag, formatted as a binary string, ready to be slapped on the front of an .mp3 file.


Sets the number of bytes of padding to add at the end of the tag. This will be added as zero bytes. Also sets the extended_header flag if $bytes > 0.

$tag->add_frame($frameid, [arguments])

Adds a new frame to the end of the tag. The first form takes an object derived from the class MPEG::ID3Frame and simply appends it to the list of frames. The second will take a four-letter frame id code (TALB, RBUF, SYLT, etc.) and attempt to call the new() method of the class MPEG::ID3Frame::<frameid> to create the frame to be added. The arguments to the constructor will be those passed to ->add_frame(), minus the frame id. If there is no new method, it will die.

For details on the arguments for supported frames, see the FRAME SUPPORT section.

@frames = $tag->get_frame(frameid)

Given a four-letter frame id, this method will search the tag's frames for all that match and return them. If called in scalar context, it will return just the first one found, if any.


These get and set the flags for the ID3v2 header. If an argument is passed, the flag will be set to that value. The current flag value is returned.

If flag_unsynchronization is set when as_string() is called, the unsynchronization scheme will be applied to the data portion of the tag.

If flag_extended_header is set when as_string() is called, an ID3v2 Extended Header will be added. This flag is set automatically when set_padding_size() is set to a non-zero value.


This method will construct a new tag by reading from a file containing an ID3v2 tag. If there is no revision 3 tag in the file, undef is returned.

The filehandle should be in binary mode. This is not necesary on some platforms, but it is on others, so it's a good habit to get into.

Frame types for which a parse_data method has been written will be parsed individually, and (should) provide appropriate access methods to retrieve the data contained in the frame.

All frame types, whether supported by a MPEG::ID3Frame subclass or not, will be read in and will be formatted appropriately when output with $tag->as_string(). You just won't be able to do anything with the data inside the tag unless a parser has been written.

This method will read the tag and leave the filehandle's file pointer at the byte immediately following the tag.

See FRAME SUPPORT for details about frames and their parsers.


Dumps out the tag to the currently selected filehandle, for debugging purposes.


Each ID3v2 frame type is implemented by its own class. TALB is implemented by MPEG::ID3Frame::TALB, OWNE is implemented by MPEG::ID3Frame::OWNE, etc.

Not all frames are currently implemented for writing, and not all frames that are implemented for writing have parsers for reading.

All frames support the following public methods, which they get from a base class called MPEG::ID3Frame.

$id = $frame->frameid()

Returns the four-letter frame id code for the frame.


When a frame is read from an ID3v2 tag which has been parsed by MPEG::ID3v2Tag->parse(), actually parsing the data into a useful form may turn out to be impossible. For example, the appropriate parser routine may not be implemented, or the tag may contain a flag demanding unimplemented functionality like encryption.

This method can be used to determine whether the tag was parsed into its component bits.

If this routine returns a false value, the reason the tag could not be parsed may be found in the $frame->{UNSUPPORTED_REASON} private variable.

Note that even if a frame can't be parsed, it can still be retained in the tag when it is output with the $tag->as_string() method. It will be output exactly as it appeared in the data stream when it was read in.


These functions get and/or set the flag bits from the frame header. See the ID3v2.3.0 informal standard for semantics.

Note that encryption is not currently supported, and that attempting to create frames with these bits turned on may create bad headers.

If you set the compression flag on a frame, this module will attempt to load the Compress::Zlib module to compress the frame, dying if the module can't be found. When parsing a compressed frame, Compress::Zlib will be used if available. If not, the frame will not be parsed (the fully_parsed method will tell you if a frame was successfully parsed, and $frame->{UNSUPPORTED_REASON} will give you a string telling you why), but no fatal errors will be generated.


Dumps out some data from this frame. This is generally overridden in subclasses to dump frame-specific data.

Support for specific frame types

In addition to the above methods, each individual supported frame will have a new() constructor (which can be called directly, or implicitly by $tag->add_frame()) and possibly access methods for the data contained in the frame. In the list below, the constructor is shown as a call to $tag->add_frame(<tagname>, <arguments>), but remember you can call MPEG::ID3Frame::TALB->new(<arguments>) and pass the return value to add_frame.

.... and so on T???

All these text information frames are supported:


The constructor is generally called like this:

[$frame = ]$tag->add_frame(TALB, "text string", [optional_encoding]) ;

You can get the encoding value with $frame->encoding() and the text string value with $frame->text().

Parsing is implemented for these frames.

.... and so on (W???)

All url link frames are supported: WCOM WCOP WOAF WOAR WOAS WORS WPAY WPUB

The constructor is generally called like this:

[$frame = ]$tag->add_frame(WCOM, "text string", [optional_encoding]) ;

You can read back the url with $frame->url().


Call the constructor like this:

[$frame = ]$tag->add_frame(UFID, $owner_idstring, $id) ;

There is currently no parsing support.


Call the constructor like this:

$tag->add_frame(USLT, $encoding, $language, $content_descriptor, $lyrics) ;

also supports parsing, and these access methods: encoding(), language(), content_descriptor(), and lyrics() ;


This is one of the more complicated frames.

The constructor is called as

$tag->add_frame(APIC, [switches])

where switches can be:

-encoding => $encoding

-mime[type] => $mime_type

-picture_type => $picture_type

-desc[ription] => $description

-fh => $filehandle

-fn[ame] => $filename

-data => $data

At least one of -fh, -fn, or -data must be provided. -data takes the images as a binary string. -fh provides an open filehandle on the image file, and -fn provides a file for reading.

-mimetype must be provided also. However, if -fname is used, and the filename ends in '.gif' or '.jpg', the mime type will be assumed 'image/gif' or 'image/jpg'.

There is currently no parsing support.


The constructor for the Terms of Use frame is called as

$tag->add_frame("USER", $encoding, $language, $text) ;

There is no parsing support.


The constructor for the Comments frame is called as

$tag->add_frame("COMM", $encoding, $language, $description, $text) ;

There is no parsing support.


This is for user-defined url link frames.

$tag->add_frame("WXXX", $encoding, $description, $url) ;

Parsing support exists. As well as the following accessor methods: encoding, description, url


This is for user-defined text fields

$tag->add_frame("TXXX", $encoding, $description, $text) ;

Parsing support exists. As well as the following accessor methods: encoding, description, text


Adding support for more frames is very simple. In general, all you need to do is copy and tweak one of the supported frames (USER is a nice simple one to start from).

Suppose we're adding support for frame XXXX. Read the section about XXXX in the ID3v2.3.0 spec, then...

Create a new package MPEG::ID3Frame::XXXX.

Derive it from MPEG::ID3Frame (put "MPEG::ID3Frame" in its @ISA array).

create a subroutine/method called frameid() that just returns "XXXX".

create a constructor called new(), which takes whatever arguments you will need.

create a data_as_string method to construct the frame based on the ID3v2.3.0 spec. pack() is helpful, here.

Optionally, create access methods for the data you passed in in your constructor.

Optionally, create a parse_data method which takes the data portion of the frame and parses out the data so your access methods can access them. If your parser finds it can't parse the body data, it should set $self->{UNSUPPORTED_BODY} to the string passed in, and $self->{UNSUPPORTED_REASON} to a short string giving the reason it failed.

Optionally, create a dump() method.

Make sure that you get the same answer if you write out the frame, read it in, and write it out again.


Creating tags with encryption will probably explode.

Encrypted tags can't be parsed. They can be read in and written back out, however.

UNICODE character encodings will currently fail on input or output.

No support for modifying .mp3 files.

Many frame types unimplemented.

Most frame types don't have parsers.

5 POD Errors

The following errors were encountered while parsing the POD:

Around line 1415:

You forgot a '=back' before '=head1'

Around line 1427:

'=item' outside of any '=over'

Around line 1483:

You forgot a '=back' before '=head2'

Around line 1493:

'=item' outside of any '=over'

Around line 1617:

You forgot a '=back' before '=head1'