mp3 ファイルの id3 タグをいじる(python で日本語で id3v2)

2005/1/16 作成
(2005/1/18 SU30情報追加)
2006/2/13 date/year タグ関連情報追加

python での id3 環境

python で id3 をいじるには以下に挙げるようないくつかのライブラリを使うことができます.
id3-py
id3 v1.0 のみサポート.非unicode文字列で shift-jis を突っ込めば 日本語も書けます.FreeBSD ports では audio/py-id3 がそれ.
eyeD3
ID3 v1.0/v1.1 and v2.3/v2.4 をサポートし utf-8/utf-16 などでも書ける (shift-jis は改造しないとダメ).FreeBSD ports では audio/py-eyed3
python binding for Taglib
taglib を python から使うらしい(swig使用). 試してません.
python-id3lib
id3lib を python から使うらしい. 試してません.
以前は id3-py を使っていました (プレーヤーも v1 タグしかサポートしていないものを使っていたんで). しかし,v2 対応プレーヤーに乗り換えたのを機に,ID3 v2系への 乗り換えをして,30byte制限(日本語にしてわずか15文字!)からの解放を目指すことにします. (v2.2,v2.3,v2.4 の互いの非互換性とかいろいろあるらしいですが, 自分に関係するのは以下のもののみなので,その範囲でのみ適宜検証. なお,ID3 タグの日本語はデバイス側の都合で v1 系は通常 shift-jisで v2 系は UTF16 が基本のようです. ただし,v2 はバージョンによって互換性がなく v2.4 では UTF-8 も OKだったり, MuVo2 では自己流に shift-jisだったり(今回の確認ではUTF-16もOKでしたが)するようで, 規格などをきちんと確認したわけではありません.

eyeD3 使用方法(日本語 ID3v2)

説明はいいから example 見せろよ,ということで:
# -*- coding: euc_jp -*-
import eyeD3;

# 以下4行の順番を間違えると泣くみたい... 
tag=eyeD3.Tag();
tag.link( '01.mp3' );
tag.header.setVersion(eyeD3.ID3_V2_3);
tag.setTextEncoding( eyeD3.UTF_16_ENCODING );
# setTextEncoding() は eyeD3 v0.6.3 以降

tag.setArtist(unicode('飯島 真理','japanese.euc_jp'));
tag.setTitle(unicode('クラスメート','japanese.euc_jp'));
tag.update();
動作確認は以下のもので行いました. id3-py で書いた v1.0@shift-jis のものと,eyeD3 による v2.3,2.4@UTF-16 でテストしてます. 15文字以上の曲名なども表示されているので大丈夫なんでしょう,きっと. とりあえず id3 のバージョンは v2.3 を使うのが無難ですね (そもそも各バージョンのメリットとかなにも理解してないで使ってるし...)

参考: id3-py使用方法(昔のおさらい?)

一応こんな感じで使えてます.
import ID3

id3info = ID3.ID3(mp3filename)
tag_dict = ['ARTIST': artiststring, # 各 string は 生EUC(非unicode string) の場合
            'ALBUM': albumstring,
            'TITLE': tracktitlestring, ...]
# 他に 'YEAR', 'GENRE', 'TRACKNUMBER',  'COMMENT' など
for key in tag_dict.keys():
    id3info[key] = unicode(tag_dict[key] ,'japanese.euc-jp').encode('japanese.shift_jis')
id3info.write()

補記(2006/2/13): 日付タグ(date? year?)

日付(というか十進数四桁の"年")については

  tag.setDate(1999)
のようにするらしいのですが,どうもバグがあるようです. (私の使い方の問題かもしれません.ご存じの方は指摘をお願いします.)

簡単に検証するには,eyeD3.py コマンドの -Y オプションを試してみてください. 元の mp3 ファイルのタグの種類・付け方によるかもしれませんが,-Y で年を変更しようとすると うまく反映されません. どうなるかというと eyeD3 -v hoge.mp3 とタグの状態を確認すると year: の欄が更新されず,タグのframe構造として "<Year Frame (TYER)>" が, どんどん重複して追加されてしまいます.場合によると思いますが. (言い訳: id3v2 のframeの考え方がよく分からないので,ソースを追いきれませんでした).

本件(year frame ダブリ)の安易な対処

とりあえず setDate() の前に重複しそうなタグを飛ばしてしまえば なんとかなるようです.

  tag.frames.removeFramesByID('TYER') # おまじない
  tag.setDate(1999)
まともな解決策じゃないので,本当の原因をご存じの方は教えていただければ幸です.

参考リンク

2ch.net の python スレ/MuVo2 スレの方々に何点か教えて頂きました.
内容がおかしかったりしたらツッコミ歓迎です.
川口 銀河 (ginga-www@ginganet.org)