LoginSignup
1
0

More than 3 years have passed since last update.

「taglib-ruby」を使う

Posted at

背景

前回と同じ
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ファイルの情報を得る

app/models/MusicFile.rb
        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があり、確認しながら読み取ります。

app/models/MusicFile.rb
        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ではそれぞれ下記のように取得します。

flacの場合
            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
mp3の場合
            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の場合と同じです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0