MP3ストリーミングでUTF-16なTAGの文字化けをなおす その1 [linux]
私は、icecast-2.3.2+ices-0.4の環境で自宅用のMP3ストリーミングをしています。
最近、mp3ファイルのTAG管理にMp3tagを導入し、TAG形式を UTF-16で統一するようにしました
すると、配信されたMP3ストリーミングをwinampで受信すると、 アーティスト名やタイトルが文字化けするようになってしまいました。。。 orz..
(ま、当たり前と言えば当たり前ですが。。)
icecast-2.3.2はUTF-8なTAGは任意のキャラクタセットに変更できるようですが、UTF-16は当然ながらサポートされていません。
ならば、と思い無理やり対処してみたところ、見事に文字化けが直りました!!
まずは、情報集めから。。
続いて、Mp3tagのUTF-16がどういう形式なのか調べてみました。
というのも一口にUTF-16といっても実際には3種類あるからです
Mp3tagでTAGを入れたmp3ファイルをいくつかバイナリエディタで確認したところ、
のようになっていました。
先頭の10Byteがフレームヘッダです
さらにTPE1やTIT2は、TEXT情報フレームなので続く1byteがテキストエンコード情報です
テキストエンコード情報は
のように定義されており、この例では 01 なので BOMつきUTF-16であることがわかります。
続く2byteがBOMでFF FEになっていることからリトルエンディアンです
つまりMp3tagのUTF-16はBOM付きリトルエンディアンのUTF-16ということがわかりました
ちなみにiTunesのTAGも同じ形式のようです
続いて、ices0からicecast2に渡されるmetadataのフォーマットを調査してみました。
ices0のソースを眺めてみると、ID3v2タグがある場合は必ず、"song"として、
ここに先の例のUTF-16のArtistとTitleを当てはめると、
となり、これがicecast2に渡されることになります。
以上から、ices0での問題点を整理すると、
(1)TAGをchar型で扱うために、UTF-16のTAG中に現れる0x00がNULL文字として判断されるので実際のTAGと異なった情報になる
(2)"song"にはUTF16とUTF-16の間に普通の "スペース、マイナス、スペース(202D20)があるために、"song"全体をUTF-16からデコードできない
ということになります
そこで、上記の問題を以下のように修正することにしました。
(1)TAG中に現れる0x00を別の文字で置き換えることでchar型でもUTF-16を扱えるようにする
(2)icecast2に"song"として渡すのではなく、"artist","title"の別々のmetadataとして渡す
まずは上記方針に従って変更したices-0.4用のパッチを以下に掲載しておきます。
今回はUTF-16なmp3 TAGを解析してices0での問題点とその対策を考察してみました
次回はices0の変更に対応できるようにicecast2を修正します
最近、mp3ファイルのTAG管理にMp3tagを導入し、TAG形式を UTF-16で統一するようにしました
すると、配信されたMP3ストリーミングをwinampで受信すると、 アーティスト名やタイトルが文字化けするようになってしまいました。。。 orz..
(ま、当たり前と言えば当たり前ですが。。)
icecast-2.3.2はUTF-8なTAGは任意のキャラクタセットに変更できるようですが、UTF-16は当然ながらサポートされていません。
ならば、と思い無理やり対処してみたところ、見事に文字化けが直りました!!
本手法は環境によっては対応できないかもしれません。
試される方はあくまでも自己責任でお願いします。
まずは、情報集めから。。
UTF-16についてはこちら
ID2v2.3についてはこちら
続いて、Mp3tagのUTF-16がどういう形式なのか調べてみました。
というのも一口にUTF-16といっても実際には3種類あるからです
Mp3tagでTAGを入れたmp3ファイルをいくつかバイナリエディタで確認したところ、
のようになっていました。
先頭の10Byteがフレームヘッダです
さらにTPE1やTIT2は、TEXT情報フレームなので続く1byteがテキストエンコード情報です
テキストエンコード情報は
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).
のように定義されており、この例では 01 なので BOMつきUTF-16であることがわかります。
続く2byteがBOMでFF FEになっていることからリトルエンディアンです
つまりMp3tagのUTF-16はBOM付きリトルエンディアンのUTF-16ということがわかりました
ちなみにiTunesのTAGも同じ形式のようです
続いて、ices0からicecast2に渡されるmetadataのフォーマットを調査してみました。
ices0のソースを眺めてみると、ID3v2タグがある場合は必ず、"song"として、
[Artist]-[Title]
が渡されます。ここに先の例のUTF-16のArtistとTitleを当てはめると、
FF FE 4A 20 2D 20 FF FE 55 4F 4B 30 72 30 68 30 64 30 20
となり、これがicecast2に渡されることになります。
以上から、ices0での問題点を整理すると、
(1)TAGをchar型で扱うために、UTF-16のTAG中に現れる0x00がNULL文字として判断されるので実際のTAGと異なった情報になる
(2)"song"にはUTF16とUTF-16の間に普通の "スペース、マイナス、スペース(20
ということになります
そこで、上記の問題を以下のように修正することにしました。
(1)TAG中に現れる0x00を別の文字で置き換えることでchar型でもUTF-16を扱えるようにする
(2)icecast2に"song"として渡すのではなく、"artist","title"の別々のmetadataとして渡す
まずは上記方針に従って変更したices-0.4用のパッチを以下に掲載しておきます。
今回はUTF-16なmp3 TAGを解析してices0での問題点とその対策を考察してみました
次回はices0の変更に対応できるようにicecast2を修正します
いかがだったでしょうか
2011-04-12 21:51
nice!(0)
コメント(0)
トラックバック(1)
コメント 0