トップ 最新 追記 RDF

雄也の?日坊主日記


2008-08-07

_ [Ruby] 音声ファイルの長さを調べるためのプログラム作成

音声ファイルの長さを調べるためのコマンドラインプログラムを探したけど,なかったので作った.

背景

Beep Media Playerとかで一つ一つファイルを開けばわかるんだけど,ファイルがいっぱいだとGUIのツールは面倒だ.

画像ファイルの縦横サイズはfileコマンドで取れたりするので,音声ファイルの長さも取れないかなあと思ったが...

% file 'ACIDMAN - Loop - 01 - type A.mp3'
ACIDMAN - Loop - 01 - type A.mp3: Audio file with ID3 version 2.3, MP3 encoding

うーん,取れん.

探し方が悪いのかもしれないけど,めぼしいコマンドはないようなので作ってみた.

ruby-audioinfo

ruby-audioinfoというライブラリでMP3ファイルやOgg,FLAC,...の情報が取れる. これは,各種ライブラリをラップして共通のインターフェースを用意してくれるライブラリなんだけど目的に十分かなっている.

インストールは以下でできる.

# gem install ruby-audioinfo

長さの取得

ということでruby-audioinfoを使って長さを取得してみた.

% cat ./getaudiolength
#! /usr/bin/env ruby

begin
  require "audioinfo"
rescue LoadError
  require "rubygems"
  require "audioinfo"
end

ARGV.each do |filename|
  AudioInfo.open(filename) do |info|
    puts([filename, info.length].join(": "))
  end
end
% ./getaudiolength 'ACIDMAN - Loop - 01 - type A.mp3'
ACIDMAN - Loop - 01 - type A.mp3: 214

おお,取れる取れる. 実質5行で書けた. これは6行のrequireよりも短い.

...ってでも得られる結果は秒精度なのか!?

精度について

1/10秒精度ぐらいまでは出してくれてもいいんじゃないかと考えて調べてみる.

audioinfo.rbを読むと,以下のようにわざわざto_iメソッドで秒単位にしていることがわかった.

class AudioInfo
  ...
  VERSION = "0.1.4"
  ...
  attr_reader :artist, :album, :title, :length, :date
  ...
  def initialize(fn, encoding = 'utf-8')
    ...
    case @extension
      when 'mp3'
        @info = Mp3Info.new(fn, :encoding => @encoding)
        ...
        @length = @info.length.to_i

なお,この場合にバックエンドとして使われるruby-mp3infoではFloatで入っている. どんな音声ファイルでもAudioInfo#lengthはIntegerにしたかったとか,なにか作者の設計思想があるのかと思ってしまう.

しかしながら,FLACの場合はFloatが入るようだ.

when 'flac'
  @info = FlacInfo.new(fn)
  ...
  @length = @info.streaminfo["total_samples"] / @info.streaminfo["samplerate"].to_f

提案と場当たりと

せっかくなんだからあえてto_iして精度を落とさなくてもいいんじゃないだろうか. 作者にはto_iしないでくださいと懇願しよう.

この場はAudioInfo#length_as_floatなるメソッドを追加して解決することにした.

修正後のものは以下のようになった. メソッド名の都合上to_fを呼んでいる.

% cat ./getaudiolength
#! /usr/bin/ruby

begin
  require "audioinfo"
rescue LoadError
  require "rubygems"
  require "audioinfo"
end

class AudioInfo
  def length_as_float
    return (@info.respond_to?(:length) ? @info.length : @length).to_f
  end
end

ARGV.each do |filename|
  AudioInfo.open(filename) do |info|
    puts([filename, info.length_as_float].join(": "))
  end
end
% ./getaudiolength 'ACIDMAN - Loop - 01 - type A.mp3'
ACIDMAN - Loop - 01 - type A.mp3: 214.3346875
% ./getaudiolength 'ACIDMAN - green_chord - 13 - toward.mp3'
ACIDMAN - green_chord - 13 - toward.mp3: 632.8946875

うん,多少長いファイルでもちゃんと取得できるようだ. 完成〜.よかった.よかった.


2008-08-14

_ [software][Ruby] FizzBuzz問題を解いてみる

一時話題になったFizzBuzz問題,そういえば自分なりには解いてなかったなあと思い出し,今さらながらやってみた.

% ruby -e '100.times do |i| puts([[1, i], [3, "fizz"], [5, "buzz"]].collect { |mod, output| (i % mod).zero? ? output : "" }.join) end'

ワンライナではなくてワンステートメントでできた.

気に入ったところは,1で割った余りもまた0であるかどうかを判定するところだ. 条件分岐を一箇所で記述できたことがうれしい.


2008-08-23

_ [Ruby] PerlとRubyの間になにがあるのかを調べる

画期的なプログラムを開発したのでMasaruに投稿しておいた.


2004|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|
2006|05|
2007|04|05|09|10|11|
2008|04|05|08|10|11|
2009|02|03|04|05|06|07|08|09|10|11|
2010|02|03|04|07|10|
2011|04|08|
2012|02|10|
2014|05|06|08|
2018|03|
楽天で探す
楽天市場
キーワードから探す
楽天トラベル