背景
前回と同じ。
JewelCaseは音楽ファイルを使うアプリなので、flacとmp3のタグの解析にこのtaglib-ruby
を使います。
詳細
ドキュメントなど
rubygem: https://rubygems.org/gems/taglib-ruby/versions/0.5.2-x86-mingw32?locale=ja
github.io: https://robinst.github.io/taglib-ruby/
rubydoc: https://rubydoc.info/gems/taglib-ruby
インストールするときはapt-get install libtag1-dev
など、libtagのインストールも必要です。
(Dockerで使うときも下記のようにインストールしてあります)
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client libtag1-dev
基本的な使い方
基本的にブロックの中で使用します。
flacファイルの情報を得る
TagLib::FLAC::File.open(fpath) do |flac|
tag = flac.tag
ret = {
:album => tag.album, # アルバム名
:artist => tag.artist, # アーティスト名
:genre => tag.genre, # ジャンル
:track_no => tag.track, # トラック番号
:title => tag.title, # 曲名
}
end
mp3ファイルの情報を得る
mp3のID3タグはV1とV2があり、確認しながら読み取ります。
TagLib::MPEG::File.open(fpath) { |mpeg| # mpegとして開く
if mpeg.id3v2_tag? then
tag = mpeg.id3v2_tag
ret = {
:album => tag.album,
:artist => tag.artist,
:genre => tag.genre,
:track_no => tag.track,
:title => tag.title,
}
elsif mpeg.id3v1_tag? then # V1の場合もある
tag = mpeg.id3v1_tag
# 省略
else # どちらでもない?
# 適当に処理する
end
あまり使われない?項目名のタグを得る
私は曲のアーティスト名とは別にアルバムアーティストを音楽ファイルにつけていますが、あまり使われないのか、音楽ファイルによってサポートされない場合があるためか、TagLib::Tag
で取得することができません。
そこでflacとmp3ではそれぞれ下記のように取得します。
ret = ""
TagLib::FLAC::File.open(fpath) do |flac|
return ret if not flac.xiph_comment?
fl = flac.xiph_comment.field_list_map
ret = fl["ALBUMARTIST"]
end
ret
ret = ""
TagLib::MPEG::File.open(fpath) do |mpeg|
return ret if mpeg.id3v1_tag? # id3v1も取得できるだろうが面倒なので無視
return ret if not mpeg.id3v2_tag? # どうしようもないので無視
tag = mpeg.id3v2_tag
ret = tag.frame_list("TPE2")
end
ret
flacのfield_list_map
で使えるフィールド名はmetaflacで使うフィールド名と同じと思われます。
mp3のframe_list
で使えるフィールド名(フレーム名)はID3v2の仕様に従っていると思われます。
ジャケット画像を抽出する
flacではpicture_list
メソッドによりTagLib::FLAC::Picture
の配列を取得できます(複数のジャケット画像がつけられるらしい)。
TagLib::FLAC::File.open(fpath) { |flac|
pics = flac.picture_list
}
ジャケット画像はjpegだったりpngだったりいろいろですが、mime_type
でMIME Type識別子(文字列)を返してくれるので判別は簡単です。
case pic.mime_type
when /.*png/
ext = '.png'
when /.*jpeg/, /.*jpg/
ext = '.jpeg'
when /.*bmp/
ext = '.bmp'
else
puts "mine: " + pic.mime_type
end
画像データはPictureクラスのdata
で取得できます。画像データそのものなので、適当な描画ライブラリに渡したり、バイナリでファイル出力して画像ファイルを作成できます。
IO::binwrite(JACKET_PATH + name + ".png", pic.data)
mp3の場合はpicture_list
みたいなメソッドは使えませんが、APICフレームを取得すればジャケット画像を抽出したことになります。
(APICはID3v2でID3v1には無いっぽい)
TagLib::MPEG::File.open(fpath) { |mpeg|
return ret if mpeg.id3v1_tag?
return ret if not mpeg.id3v2_tag?
tag = mpeg.id3v2_tag
pics = tag.frame_list('APIC')
if pics.length > 0 then # これも配列として取得できる
pic = pics[0]
オブジェクトを取得したあとの扱いはflacの場合と同じです。