RaspberryPiで動画をエンコードする

  • 46
    Like
  • 0
    Comment
More than 1 year has passed since last update.

どうしたの?

TSファイルがどんどん溜まっていく・・・
当初は見たらすぐ消すし、、、とか思ってたけど結構溜まっていって消すに消せない貧乏性発動・・・
でも、HDD容量持たないのでエンコードしてみたら30分の動画のエンコード2時間かかって泣きそうだしエンコード中はPC爆音でやばい。

どうしよう

ハードウェアエンコードできると速度速いし消費電力やCPUにも優しいらしい。
というわけで失敗しても懐が痛くないRaspberry Piを購入して試してみました。

Raspberry Piって?

4000円ぐらいで買えるARMプロセッサを搭載した小型PC(的な基板)です。
今回はRaspberry Pi B+を使いました。あとセットで箱(1000円)を買いました
SDカードフォーマットしてネットインストーラー入れて起動すれば後はぽちぽち選ぶだけでLinuxが環境が出来上がります。
ということでOSはraspbianを利用しました。

Mpeg2のライセンス

こちらから別で買う必要があります。500円ぐらい
http://www.raspberrypi.com/mpeg-2-license-key/

私の場合購入から4時間程でキーが届きました。

エンコードの準備

Gstreamerをインストールします

sudo apt-get install gstreamer1.0-*

さてエンコードだ!・・・の前に

エンコードの結果どの程度の画質にするのかを決める必要があります。
H.264ってやつ使えばいいらしい。
びっとれーと?いんたーれーす?おいしいの?状態だったのでまずそっちの知識をつけます。

コーデックとコンテナ

今回作る動画はMP4(コンテナ)でH.264(映像コーデック)でAAC(音声コーデック)です。
他にもMOVとかVP8とかMP3とか色々と有りますがそれぞれ何に当たるのかを見分けれると理解が進むと思います

インターレース

wikipedia - インターレース
1080i とか 1080pとかの後ろについてるiとpがそれです。
インターレースは奇数番目の走査線と偶数番目の走査線を交互に送ってテレビ側でうまいこと描写しています。
要は1回の伝送当たりの情報量がプログレッシブと比べて半分しか無いということになります。
このためインターレース動画をそのままエンコードすると動きの大きなシーン等でジャギーが現れてしまうのでデインターレース等を行ってプログレッシブ化をする必要がありました

H.264はインターレースをサポートしており対応のプレイヤーであれば再生時に処理してくれます。
なので今回はインターレースの解除はしません。(というか最初はやろうとしたが出来ませんでした)

ビットレート

1秒あたりのデータサイズです。大きくすればその分綺麗で重い動画が出来上がります。
素人的にはデータサイズを決めるのは解像度が重要に思いがちですが、どれだけ大きな解像度にしようともビットレートが同じである限り出来上がるファイルサイズは同じになります。
可変ビットレートや2パスエンコードはこのビットレートをシーン毎に最適な量にしてファイル容量を小さくする方法です。

動画解像度

録画した映像の解像度を調べると1440x1080とフルHD動画じゃないことに気が付きます。
しかしこれをプレイヤーで再生すると何故か1920x1080の液晶で画面一杯に表示されます。
これは動画ファイルに映像をこの画面比率で表示せよという情報が含まれており、
プレイヤー側が横方向に引き伸ばしていることで画面一杯に表示されています。

このためフルHDは1920x1080だから1280x720にしようと単純に考えると汚い動画が出来上がってしまいます。
(また出来上がったファイルのアスペクト比がおかしくなったりもします)

実際どうするか

今回は映像ソースの縦方向を480pxとし、それに合わせて横方向の解像度とビットレートを減らすことにします。

エンコード用シェルスクリプトを書く

なれないシェルスクリプトを頑張って書きました。

bash;encode.sh
#!/bin/sh
INPUT="$1"
OUTPUT="$2"

TARGET_HEIGHT="480"

## mediainfo
echo "check media info..."
MEDIA_INFO=`mediainfo --Inform='Video;%FrameRate%,%DisplayAspectRatio/String%,%BitRate%,%Width%,%Height%' "$1"`
FPS=`echo ${MEDIA_INFO} | awk -F',' '{print $1}'`
ASPECT_RATIO=`echo ${MEDIA_INFO} | awk -F',' '{print $2}'`
BIT_RATE=`echo ${MEDIA_INFO} | awk -F',' '{print $3}'`
SOURCE_WIDTH=`echo ${MEDIA_INFO} | awk -F',' '{print $4}'`
SOURCE_HEIGHT=`echo ${MEDIA_INFO} | awk -F',' '{print $5}'`

echo "source info       -----------------"
echo "  fps         : ${FPS}fps"
echo "  bit rate    : ${BIT_RATE}bps"
echo "  aspect ratio: ${ASPECT_RATIO}"
echo "  width       : ${SOURCE_WIDTH}px"
echo "  height      : ${SOURCE_HEIGHT}px"

## calc convert setting
TARGET_SCALE=`echo "scale=2; ${SOURCE_HEIGHT} / ${TARGET_HEIGHT}" | bc`
TARGET_WIDTH=`echo "scale=0; ${SOURCE_WIDTH} / ${TARGET_SCALE}" | bc`
TARGET_BIT_RATE=`echo "scale=0; ${BIT_RATE} / (${TARGET_SCALE} * 2)" | bc`
echo "convert settings  ------------------"
echo "  scale       : ${TARGET_SCALE}"
echo "  width       : ${TARGET_WIDTH}px"
echo "  height      : ${TARGET_HEIGHT}px"
echo "  bitrate     : ${TARGET_BIT_RATE}"

## encode start
echo "encode start  ------------------"

gst-launch-1.0 \
    filesrc location="${INPUT}" \
    ! progressreport \
    ! tsdemux name=demuxer demuxer. \
    ! queue \
    ! aacparse \
    ! avdec_aac \
    ! audioresample \
    ! audioconvert dithering=0 \
    ! voaacenc bitrate=192000 \
    ! mux. mp4mux  name=mux \
    ! filesink location="${OUTPUT}" demuxer. \
    ! queue \
    ! mpegvideoparse \
    ! omxmpeg2videodec \
    ! videoconvert \
    ! omxh264enc target-bitrate=${TARGET_BIT_RATE} control-rate=variable \
    ! video/x-h264,width=${TARGET_WIDTH},height=${TARGET_HEIGHT}, \
      stream-format=byte-stream,profile=high \
    ! h264parse \
    ! mux.

status=$?
echo "encode exit"
exit $status

使い方

./encode.sh hoge.ts hoge.mp4

後は適当に特定のフォルダ監視して回すなり適時手動で実行するなりお好みでどうぞ
処理時間は動画時間とほぼ同じ。
ファイルサイズはフルHDの番組は1/4程度。縮小が発生しない場合は8割程度になりました。

課題

  • 縦方向を決め打ちするのではなく1/2とか切りの良い縮小にしたほうが綺麗なのではないか・・?
  • 音声はなんか適当なまま。
  • nasne便利ダナー

参考にさせていただいたサイト