20 March 2012

(Perl) MP3::Tag を用いた ID3v2タグの読み取り・書き込み

■ ID3v2タグを読み取る方法

TIT2やTPE1などのフレーム名はMP3::Tag::ID3v2_Dataに列挙されている

#!/usr/bin/perl use warnings; use strict; use MP3::Tag; my $mp3 = MP3::Tag->new('test.mp3') or die; $mp3->get_tags() or die; if (exists $mp3->{ID3v2}){ my $id3v2 = $mp3->{ID3v2}; # ID3よりタグを読み込む my $title = $id3v2->get_frame('TIT2'); my $artist = $id3v2->get_frame('TPE1'); my $album = $id3v2->get_frame('TALB'); my $year = $id3v2->get_frame('TYER'); my $track = $id3v2->get_frame('TRCK'); my $genre = $id3v2->get_frame('TCON'); my $comment_hash = $id3v2->get_frame('COMM'); my $comment = undef; if (defined($comment_hash)){ my %comments = %{$comment_hash}; $comment = $comments{'Text'}; } my $copyright = $id3v2->get_frame('TCOP'); my $diskno = $id3v2->get_frame('TPOS'); print(" ID3v2 tag exist\n". " artist : ".(defined($artist)?$artist:'')."\n". " title : ".(defined($title)?$title:'')."\n". " album : ".(defined($album)?$album:'')."\n". " year : ".(defined($year)?$year:'')."\n". " track no : ".(defined($track)?$track:'')."\n". " genre : ".(defined($genre)?$genre:'')."\n". " comment : ".(defined($comment)?$comment:'')."\n". " copyright : ".(defined($copyright)?$copyright:'')."\n". " disk no : ".(defined($diskno)?$diskno:'')."\n" ); } $mp3->close();

読み込まれるタグの文字コードはutf8とは限らない。Encode::encode('utf8', '文字列')を用いて表示前にutf8に変換するとよい。

■ ID3v2タグを書き込む方法

#!/usr/bin/perl use warnings; use strict; use MP3::Tag; my $mp3 = MP3::Tag->new('test.mp3') or die; $mp3->get_tags() or die; if (exists $mp3->{ID3v2}){ my $id3v2 = $mp3->{ID3v2}; # ID3よりタグを読み込む my $title = $id3v2->get_frame('TIT2'); my $artist = $id3v2->get_frame('TPE1'); my $album = $id3v2->get_frame('TALB'); my $year = $id3v2->get_frame('TYER'); my $track = $id3v2->get_frame('TRCK'); my $genre = $id3v2->get_frame('TCON'); my $comment_hash = $id3v2->get_frame('COMM'); my $comment = undef; if (defined($comment_hash)){ my %comments = %{$comment_hash}; $comment = $comments{'Text'}; } my $copyright = $id3v2->get_frame('TCOP'); my $diskno = $id3v2->get_frame('TPOS'); # artistタグを書き込む if(defined($artist_new)){ if(!defined($artist)){ $id3v2->add_frame('TPE1', $artist_new); } else{ $id3v2->change_frame('TPE1', $artist_new); } print(" artist : ".(defined($artist)?$artist:'')." -> $artist_new\n"); } # titleタグを書き込む if(defined($title_new)){ if(!defined($title)){ $id3v2->add_frame('TIT2', $title_new); } else{ $id3v2->change_frame('TIT2', $title_new); } print(" title : ".(defined($title)?$title:'')." -> $title_new\n"); } # albumタグを書き込む if(defined($album_new)){ if(!defined($album)){ $id3v2->add_frame('TALB', $album_new); } else{ $id3v2->change_frame('TALB', $album_new); } print(" album : ".(defined($album)?$album:'')." -> $album_new\n"); } # yearタグを書き込む if(defined($year_new)){ $year_new = sub_conv_to_flagged_utf8($year_new); if(!defined($year)){ $id3v2->add_frame('TYER', $year_new); } else{ $id3v2->change_frame('TYER', $year_new); } print(" year : ".(defined($year)?$year:'')." -> $year_new\n"); } # trackタグを書き込む if(defined($track_new)){ if(!defined($track)){ $id3v2->add_frame('TRCK', $track_new); } else{ $id3v2->change_frame('TRCK', $track_new); } print(" track : ".(defined($track)?$track:'')." -> $track_new\n"); } # genreタグを書き込む if(defined($genre_new)){ if(!defined($genre)){ $id3v2->add_frame('TCON', $genre_new); } else{ $id3v2->change_frame('TCON', $genre_new); } print(" genre : ".(defined($genre)?$genre:'')." -> $genre_new\n"); } # commentタグを書き込む if(defined($comment_new)){ if(!defined($comment)){ $id3v2->add_frame('COMM', 'ENG', '', $comment_new); } else{ $id3v2->change_frame('COMM', 'ENG', '', $comment_new); } print(" comment : ".(defined($comment)?$comment:'')." -> $comment_new\n"); } # copyrightタグを書き込む if(defined($copyright_new)){ if(!defined($copyright)){ $id3v2->add_frame('TCOP', $copyright_new); } else{ $id3v2->change_frame('TCOP', $copyright_new); } print(" copyright : ".(defined($copyright)?$copyright:'')." -> $copyright_new\n"); } $id3v2->write_tag() or die("E: tag write error, $filename_base\n"); } $mp3->close();

日本語を書きこむ場合、「utf8フラグ付き」に明示的に変換しておく必要がある。フラグなしの文字列にフラグを付けるにはdecode('文字列')のようにすればよい。
Windows Media Playerに対応するためにはUTF-16LE+BOMでID3v2に書きこむ必要があるので、環境変数 MP3TAG_USE_UTF_16LE をセットしてからこのスクリプトを実行する必要がある。 (また、マイクロソフト製品のバグ仕様かよ…)