ts ファイルのチャネルを自動的に読み取って mp4に変換する

ffprobeでchannelの情報を読み出して解析し、その結果を反映してffmpegでmp4にエンコードします。副音声がある場合は、異なるbit rateのaudio channelを複数含むようです。ここでは120 kbs以上のchannelはエンコードするようにしています。

以下はrubyで書いた例です。コードは綺麗ではないです。無保証ですので、このコードを実行して何か不具合が生じても責任は取りません。 ffmpegとffprobeはパスを通しておきます。

ffprobeの情報はstderrのようなので、”open3″を使っています。

#!/usr/bin/ruby

require "open3"
require 'nkf'

def get_ch(info)
  ch_video = ""; ch_audio = []
  info.each_line{|line|
    if /Stream\s+\#(\d+:\d+).+Video.*,\s+(\d+x1080)/i =~ line
      ch_video = $1
    elsif /stream\s+\#(\d+:\d+).+audio.*,\s+(\d+)\s+kb\/s/i =~ line
      if $2.to_i > 120
        ch_audio << $1
      end
    end
  }
  return ch_video, ch_audio.uniq
end

ARGV.each{|ts|
  if /\.ts/ =~ ts then
    stdout, stderr, status = Open3.capture3("ffprobe #{ts}")
    info = NKF.nkf("-w", stderr)
    v,a  = get_ch(info)

    map_v = " -map #{v}"
    map_a = ""
    a.each{|aa|
      map_a += " -map #{aa}"
    }
    
    outfile = ts.gsub(/\.ts/, '.mp4')
    command = "ffmpeg -y -i #{ts}  -threads 0 -f mp4"
    command += " -vcodec libx264 -b:v 2000k -vpre libx264 -r 30000/1001 -aspect 16:9 -s 1024x758"
    command += " -bufsize 20000k -maxrate 25000k -vsync 1 -async 1000 -crf 23.0 -level 30 -qmin 10"
    command += " -acodec libfaac -b:a 128k -ac 2 -ar 48000 #{map_v} #{map_a}  #{outfile}"
    puts command
    system(command)

    end
}

2017年1月29日修正: Videoの判定を1440×1080から\d+x1080に変更しました。1920×1080の場合もありますから。