mp3タグ情報の抽出,更新 ruby-mp3info

mp3のID3タグの情報を一括して処理したくなったのでrubyのライブラリを探した.
最初は id3lib-ruby を使おうかと思ったが,gem のインストールで失敗してダメだった.

$ sudo apt-get install libid3-3.8.3-dev 
$ sudo gem install id3lib-ruby
Building native extensions.  This could take a while...
ERROR:  Error installing id3lib-ruby:
        ERROR: Failed to build gem native extension.

/usr/local/ruby19/bin/ruby extconf.rb install id3lib-ruby
checking for main() in -lstdc++... yes
checking for main() in -lz... yes
checking for id3.h... yes
checking for ID3Tag_New() in -lid3... yes
creating Makefile

make
g++ -I. -I/usr/local/ruby19/include/ruby-1.9.1/i686-linux -I/usr/local/ruby19/include/ruby-1.9.1/ruby/backward -I/usr/local/ruby19/include/ruby-1.9.
1 -I. -DHAVE_ID3_H  -D_FILE_OFFSET_BITS=64  -fPIC  -O2 -g -Wall -Wno-parentheses    -o id3lib_api_wrap.o -c id3lib_api_wrap.cxx
id3lib_api_wrap.cxx: In function ‘size_t ID3_Field_set_binary(ID3_Field*, VALUE)’:
id3lib_api_wrap.cxx:1837: error: ‘struct RString’ has no member named ‘ptr’
id3lib_api_wrap.cxx:1838: error: ‘struct RString’ has no member named ‘len’
id3lib_api_wrap.cxx: In function ‘size_t ID3_Field_set_unicode(ID3_Field*, VALUE)’:
id3lib_api_wrap.cxx:1846: error: ‘struct RString’ has no member named ‘len’
id3lib_api_wrap.cxx:1853: error: ‘struct RString’ has no member named ‘ptr’
make: *** [id3lib_api_wrap.o] エラー 1


Gem files will remain installed in /usr/local/ruby19/lib/ruby/gems/1.9.1/gems/id3lib-ruby-0.5.0 for inspection.
Results logged to /usr/local/ruby19/lib/ruby/gems/1.9.1/gems/id3lib-ruby-0.5.0/ext/gem_make.out

めんどくさそうなエラーが出たのでid3lib-rubyを使うのは断念.
同じようなライブラリに ruby-mp3info(http://ruby-mp3info.rubyforge.org/) があったのでこっちを採用.

$ sudo gem install ruby-mp3info

こっちは何のエラーもなくインストール完了.とりあえずタグの内容は以下のようにして読める.(ruby-1.9.1)

require 'mp3info'

Mp3Info.open("filename.mp3") do |mp3|
  p mp3.tag  #=> {"title"=>"hoge", "artist"=>"fuga", "comment"=>"foo"}
  p mp3.tag2.keys #=> ["TPE1", "TIT2", "COMM", "APIC"]
end

アートワークの画像を抽出することも無事にできた.注意点は最初の1バイト目の"\000"を削ること.これをしないとファイルが破損状態になって読めなかった.
参考:http://rubyforge.org/forum/forum.php?thread_id=27204&forum_id=229

Mp3Info.open("filename.mp3") do |mp3|
  text_encoding, mime_type, picture_type, picture_data = mp3.tag2["APIC"].unpack("c Z* c a*")
  imgfile = "#{File.basename(file, ".*")}.#{mime_type.sub('image/','')}"
  File.open(imgfile, "w") {|f|
    f.print picture_data.sub(/^\000/, '')  # 最初の1バイト目の\000を削除
  }
end