HandBrake で簡単自動エンコード♪

サーバー
スポンサーリンク

Ubuntu 12.04 で,TS ファイルを H.264 形式に圧縮する方法をご紹介.

x264
動画が HDD に貯まってきたので整理しようと思い立ったものの,この手のツールの状況には詳しくなく,解にたどり着くまでに時間がかかりました.問題は音ズレ.動画と音声のタイミングが時間が進むにつれて合わなくなってしまいます.

スポンサーリンク

上手くいかなかった方法

いろいろ調べて,以下のような方法を試してみたものの,いずれも微妙な結果.

ffmpeg の -vsync オプション
今回使用した TS ファイルでは効果無し.
ffmpeg の -async オプション
ズレの最大幅は緩和されたものの,違和感有り.
x264 + MP4Box の dur 指定オプション
dur で動画と音声の短い方の時間を指定するんですが,指定が面倒.違和感はほとんど無い.

お手軽 HandBrake

さらにいろいろ調べていくと,手軽にエンコードするためのツールとして HandBrake というものがあることを発見.
早速インストール.

そして,エンコード開始.

できあがったファイルを再生してみると,音ズレ無し!

やったね!

画質設定

エンコードで気になるのは,画質.そこで, --quality で指定する値と,エンコード時間(time),圧縮率(compression),画質の劣化(SSIM)の関係を調べてみました.SSIM の縦軸は右側です.SSIM は 1 が劣化無しで,そこから値が小さくなるにつれ,劣化度合いが大きくなります.

オプション指定とアウトプットの関係

私の場合,1/3 程度には圧縮したかったので,20 を指定しています.ちなみに, vbv-maxrate の指定については,このページが参考になります.

自動エンコード

HandBrake によるエンコードには時間がかかります.先ほどのグラフの時間を見ていただくと分かるように,だいたい動画の長さの 1.5 倍ほどの時間がかかっています.

わざわざ待つのは時間の無駄なので,特定のディレクトリにファイルを置くだけで自動的にエンコードするようにしてみました.

まず,指定したディレクトリにファイルが追加されたらエンコードするスクリプト(encode.zsh)を作成.

dur= avprobe ${i} |& grep -m 1 Duration | ruby -n -e 'puts ($1.to_i*3600+$2.to_i*60+$3.to_i) if $_=~/([\d]+):([\d]+):([\d]+)/'
temp= mktemp -u "${TEMP_PATH}/.${i:t:r}.XXXXXX".mp4
# encode
echo HandBrakeCLI –input “${i}” ${=VIDEO_OPT} –rate ${fps} ${=AUDIO_OPT} –output ${temp} | tee ${LOG_PATH}/${i:t:r}.log
HandBrakeCLI –input “${i}” ${=VIDEO_OPT} –rate ${fps} ${=AUDIO_OPT} –output ${temp} >>& ${LOG_PATH}/${i:t:r}.log
if (( $? != 0 )); then
echo “ERROR[handbrake] ${i}” >&2
continue
fi

# check durarion
dur_out= avprobe ${temp} |& grep -m 1 Duration | ruby -n -e 'puts ($1.to_i*3600+$2.to_i*60+$3.to_i) if $_=~/([\d]+):([\d]+):([\d]+)/'
dur_diff= echo "sqrt((${dur} - ${dur_out})^2)" | bc
if (( $dur_diff > 2 )); then
echo “ERROR[duration] ${i}” >&2
continue
fi
mv ${temp} ${OUTPUT_PATH}/${i:t:r}.mp4
mv ${i} ${PROCESSED_PATH}/
echo OK ${i}
done
}

scan_and_encode
while inotifywait -e close_write ${QUEUE_PATH} &>/dev/null; do
scan_and_encode
done
[/crayon]

このスクリプトは,QUEUE_PATH で指定したディレクトリを監視し,*.ts ファイルがあればエンコードして,OUTPUT_PATH に出力します.成功した場合は,*.ts ファイルを PROCESSED_PATH に移動します.

lsof を使って,他プロセスのファイルアクセス有無を確認しているので,QUEUE_PATH にファイルをコピーする際も安心です.

このスクリプトを cron で定期的に実行するようにすれば,自動化完了.具体的には,下記のようなエントリーを追記します.

コメント