in reply to I need help about MP3::Tag and perl script.

Oh, and cover art is a whole different challenge. Here's how I do it (for ID3v2 and jpg images).

use constant COVERART_LOCATOR => "coverart"; use constant PICTURE_TYPE => "Cover (front)"; use constant PICTURE_COMMENT => "Cover Image"; use constant APIC => "APIC"; sub attach { # Find a suitable image and attach it to the suggested mp3 file my($track,$mp3_file,$image_file) = @_; return undef if(!defined $image_file); if(!-w $mp3_file) { # This shouldn't happen but... chmod 0755,$mp3_file; } if(!-w $mp3_file) { carp("Cannot write to $mp3_file"); return undef; } my $mp3 = MP3::Tag->new($mp3_file); if(!defined $mp3) { carp("Cannot read tags from $mp3_file"); return undef; } # Attempt to read the tags $mp3->get_tags(); if(!defined $mp3->{ID3v2}) { # Need to create a new set of tags $mp3->new_tag("ID3v2"); } if(!defined $mp3->{ID3v2}) { carp("Cannot create ID3v2 tags in $mp3_file"); return undef; } my($mime_type,$image_data) = read_image($image_file); return undef if(!defined $mime_type); my $encoding = 0; my @apic_parts = ($encoding, $mime_type, picture_type_idx(PICTURE_TYPE), PICTURE_COMMENT, $image_data); if(defined $mp3->{ID3v2}->get_frame(APIC)) { # Modifying an existing image $mp3->{ID3v2}->change_frame(APIC,@apic_parts); } else { # Create a new frame $mp3->{ID3v2}->add_frame(APIC,@apic_parts); } $mp3->{ID3v2}->write_tag(); return $image_file; } sub read_image { # Read the image file my($file_name) = @_; my $image_type; my $image_data; if(!-f $file_name) { error("Cannot read file \"$file_name\""); return; } if($file_name =~ /\.jpg$/i) { $image_type = "jpg"; my $ifh = IO::File->new($file_name); if(!defined $ifh) { error("Failed to open \"$file_name\""); return; } binmode $ifh; $image_data = ""; # This reads the data in 16k chunks, but the images should be +small anyway while(!$ifh->eof()) { my $c = $ifh->read($image_data,1024*16,length($image_data) +); } $ifh = undef; } if(!defined $image_type) { error("Does not yet support file type for \"$file_name\""); return; } if(!defined $image_data) { error("Cannot extract $image_type data from \"$file_name\""); return; } return("image/$image_type",$image_data); } sub picture_type_idx { # Given a picture type string convert it into a number suitable # for MP3::Tag my($picture_type) = @_; # The picture types that are currently understood (from MP3::Tag:: +ID3v2): my @picture_types = ("Other", "32x32 pixels 'file icon' (PNG only)", "Other file +icon", "Cover (front)", "Cover (back)", "Leaflet page", "Media (e.g. lable side of CD)", "Lead artist/lead performe +r/soloist" , "Artist/performer", "Conductor", "Band/Orchestra", "Compose +r", "Lyricist/text writer", "Recording Location", "During recor +ding", "During performance", "Movie/video screen capture", "A bright coloured fish", "Illustration", "Band/artist logo +type", "Publisher/Studio logotype"); # This approach is easy to understand for(my $i=0;$i<=$#picture_types;$i++) { if(lc($picture_type) eq lc($picture_types[$i])) { return chr($i); } } error("The picture type \"$picture_type\" is not valid"); return chr(3); }

Update: This defines a new subroutine called attach(). The first parameter has no affect (its important in my script but for your purposes you can ignore it). Suppose you want to attach a file "foo/cool.jpg" to an mp3 file called "1.mp3" as the front cover, you would just do (untested)


This, of course, requires that you add the appropriate packages and copy the definition of the subroutine somewhere into your script.