動画の大きさ(縦横サイズ)を調べる

ffmpeg などで動画の大きさを変更してエンコードするときに、元の動画の大きさやそこからわかるアスペクト比などを得たいことがあります。上下や左右に黒帯が付加され、コンテンツ自体のサイズと異なる場合もあります。

そこで ffmpegmplayer が出力した内容を使って大きさを取得してみます。(ちゃんとした仕様やソースをあたっていません。予想に依るところがあります。)

ffmpeg が出力する情報

$ ffmpeg -i input.mp4
()
    Stream #0.0(und): Video: h264 (High), yuv420p, 960x720 [PAR 479:480 DAR 479:360], 768 kb/s, 29.97 fps, 30 tbr, 90k tbn, 180k tbc
()

ffmpeg で入力ファイルのみを指定して実行すると変換自体は行うことはできませんが、そのとき出力されるエラーの中に入力ファイルの情報が出力されます。

このときの 960x720 は縦横のドット数であり、そのあとの PAR はピクセルアスペクト比DAR はディスプレイアスペクト比を意味するものだと思われます。特にピクセルアスペクト比(1ドットの縦横比)が 1:1 のときはドット数がすなわち動画サイズとなりますが、それ以外のときは縦ないし横に引き伸ばした結果が動画の大きさとなるため、その値を計算する必要がでてきます。

mplayer が出力する情報

動画プレイヤーのひとつである mplayer で映像音声ともに出力をなしにした状態で 1 フレームのみ再生し、出力する情報を利用することもできます。

$ mplayer -vo null -ao null -frames 1 input.mp4 2>/dev/null
()
Movie-Aspect is 1.33:1 - prescaling to correct movie aspect.
VO: [null] 960x720 => 960x722 Planar YV12
()

このような VO: [null] からはじまる行があり左の値がドット数、右の値がピクセルアスペクト比を加味して変換された大きさになると思われます。

mplayer の方はピクセルアスペクト比を考慮した結果を出力してくれるので、こちらを利用する方が楽といえば楽です。

変換すべき否か

ただし、今回の例で用いたファイルは、ピクセルアスペクト比 479:480 で 960x720 を 960x722 に変換しています。この場合はアスペクト比情報の方が間違って指定されており、変換しない方が映像として好ましいものだと思われます。一方で、ピクセルアスペクト比を適用した方が意図通りになるものもあります。

スクリプト

最後に個人的に使用しているスクリプトを簡単に。

#!/usr/local/bin/ruby

# usage:
#   ./video_size.rb VIDEO_FILE [VIDEO_FILE ...]
# example:
#   ./video_size.rb *.mp4

videos = []
ARGV.each do |arg|
  Dir.glob(arg) do |path|
    videos << path
  end
end
videos.uniq.sort.each do |path|
  open("| mplayer -ao null -vo null -frames 1 #{path} 2>/dev/null") do |io|
    w = h = nil
    io.each do |line|
      if line.strip =~ /^VO: \[null\] \d+x\d+ => (\d+)x(\d+).*$/
        w = $1
        h = $2
      end
    end
  end
  unless w.nil? || h.nil?
    puts "%sx%s %s" % [w, h, path]
  else
    puts "Error - #{path}"
  end
end

当然ですが mplayer が必要です。