MP3::Tag を使い iTunes で読めるようなID3タグを付けたかったのだが、何パターンか試したもののうまくいかなかった。原因がわからないので iTunes が生成した ID3 タグを MP3::Tag の出力結果と比べ、同じような結果が得られるようなコードを書いたのだがそれでもなお、うまくいかない。
寝たり他ごとしたりしつつ 12 時間ぐらいたってしまったが、解決しないので、 ID3v2 フォーマットの仕様書を見てみた。
ID3 tag version 2.4.0 - Main Frames の 4. ID3v2 frame overview には、以下の通り記述がある。
Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings: $00 ISO-8859-1 [ISO-8859-1]. Terminated with $00. $01 UTF-16 [UTF-16] encoded Unicode [UNICODE] with BOM. All strings in the same frame SHALL have the same byteorder. Terminated with $00 00. $02 UTF-16BE [UTF-16] encoded Unicode [UNICODE] without BOM. Terminated with $00 00. $03 UTF-8 [UTF-8] encoded Unicode [UNICODE]. Terminated with $00. Strings dependent on encoding are represented in frame descriptions as, or if newlines are allowed. Any empty strings of type $01 which are NULL-terminated may have the Unicode BOM followed by a Unicode NULL ($FF FE 00 00 or $FE FF 00 00).
つまり iTunes 互換の UTF-16 Little Endian でエンコードする場合は
- BOM (リトルエンディアンの場合は 0xFF 0xFE) ではじまり、 0x00 0x00 で終わること
- encoding description byte が 1 であること
上記 2 点を満たす必要があるようだ。これを MP3::Tag で素直に書くと
use MP3::Tag; use Encode qw/encode/; (省略) $id3v2->add_frame("TPE1", 1, #encoding description byte sprintf("\xFF\xFE%s\x00\x00", encode('UTF-16LE', '初音ミク'));
という感じになるのだが、手元のマシンにインストールされていた sarge の MP3::Tag 0.40 だと ID3v2.pm に以下の Encoding=0 を強制するコードがあって encoding=1 を受け入れてくれない。まったく余計なことしてくれる。
MP3/Tag/ID3v2.pm 450 if ($fs->{name} eq "_encoding") { 451 $encoding = shift @data unless $defenc; 452 warn "Encoding of text not supported yet\n" if $encoding; 453 $encoding = 0; # other values are not used yet, so let's not write them in a tag 454 $datastring .= chr($encoding); 455 next; 456 }
仕方ないので 453 行目をコメントアウトしてしまい、とりあえず目的は達成できるようになった。だるー。さっさとソースや仕様にあたれってことですかね...
0 件のコメント:
コメントを投稿