*

MPEG2-TS用のFFmpeg H.264エンコードスクリプトを作りました

  最終更新日:2018/03/18

H.264 エンコードスクリプト

 Linux PCで録画したMPEG2-TSファイル用のFFmpeg H.264エンコードスクリプトを作りました。特別な知識なしで比較的簡単に綺麗にエンコード出来ます。

スポンサーリンク

はじめに

 録画ファイルをエンコードする際、毎回面倒なFFmpegのオプションを指定するのは面倒なので、Perlでスクリプトを作りました。スクリプトは以下を目標に形にしています。

  • TSファイルを特別な知識なしで綺麗かつ高圧縮にH.264でエンコード
  • テレビ放送に対応した加工に対応

 なお、動作確認はLinuxでしかしていません。また、TSファイル以外でも使えるかもしれませんが、その動作確認はしていません。

 スクリプトの対応内容は次の通りです。

  • 入力TSファイル名と出力MP4ファイル名を引数指定するだけでエンコード可能
  • 解像度、画質、アスペクト比の指定
  • 画質調整
  • FFmpeg用のプリセットファイルの指定
  • 開始終了時間指定による動画切り抜き(コピー or エンコード選択可)
  • 再生速度倍率の変更(音程維持)
  • 2-passエンコード(通常は1-pass)
  • 額縁削除
  • 2ヶ国語、多重音声放送に対応
  • 音量変更

 インストール方法と使用方法を以降で説明します。

インストール

 スクリプト名は”ts2enc.pl”です。圧縮ファイルをダウンロードし、解凍後にインストールスクリプトを実行して下さい。こちらからもダウンロード可能です。

$ wget https://www.jifu-labo.net/files/ts2enc.tgz
$ tar xvzf ts2enc.tgz
$ cd ts2enc
$ chmod +x install.sh
※ 以降の説明に従い、"ts2enc.pl"を編集

# sudo ./install.sh
※ install.sh はrootユーザーで実行すること

 スクリプト内で”ffmpeg”と”ffprobe”コマンドを使用します。インストール前に”ts2enc.pl”ファイルを環境に合わせて編集して下さい(19行目付近)。

# ユーザー設定
my $ffmpeg_cmd  = "/usr/local/ffmpeg_build/bin/ffmpeg";
my $ffprobe_cmd = "/usr/local/ffmpeg_build/bin/ffprobe";

 本ブログの記事「LinuxでFFmpegをほぼ全自動でビルドする(CentOS、Ubuntu等に対応)」をそのまま実行してFFmpegをインストールされた方は”ts2enc.pl”を編集する必要はありません。

 同梱のFFmpeg用のプリセットファイルは、こちらの記事(ffmpeg で TS をできるだけ高画質な mp4 へ変換してみた)の”libx264-hq-ts.ffpreset”を流用して作成させて頂きました。このプリセットファイルが綺麗にエンコードするための肝(きも)なので、ご自身で調整するなり、コマンドオプションで別ファイルを指定するなりして下さい。

 インストールするファイルは次の通りです。アンインストール時はそれぞれのファイルを削除して下さい。

  • /usr/local/bin/ts2enc.pl
  • /usr/local/bin/recordedEnc.sh
  • /usr/local/etc/ts2enc.ffpreset

使用方法

 使用方法について説明します。ここから説明する内容は、基本的にヘルプでも参照できます。

$ ts2enc.pl -help

 ヘルプでは簡潔な説明のみなので、この記事で詳細を説明していきます。

基本的な使い方

 最も基本的な使い方は、入力ファイルと出力ファイルを指定して実行するだけです。

$ ts2enc.pl input.ts output.mp4

 このスクリプトではオプション指定も可能です。オプションの指定位置は先頭でも末尾でも大丈夫です。複数のオプション指定も可能です。特に位置は選びません。

$ ts2enc.pl [options] input.ts output.mp4
$ ts2enc.pl input.ts [options] output.mp4
$ ts2enc.pl input.ts output.mp4 [options]

 オプションを何も指定しない場合のデフォルトのエンコード動作は以下の通りです。赤字のパラメータはコマンドオプションで変更可能です。

ビデオ
出力解像度
  • 入力ファイルを解析して自動判定
  • 解像度幅が720以下なら720×480
  • それ以上なら1280×720
画質(CRF値) 25
アスペクト比 16:9
プリセットファイル /usr/local/etc/ts2enc.ffpreset
エンコード回数 1-pass
インターレース 解除
音声
タイプ AAC
Ch数 2 ch
周波数 48 kHz
ビットレート 192 kbps

 これらのデフォルト値のいくつかはスクリプト内でも変更できるようにしています(20行目付近)。特に出力解像度1280×720では非力なCPUではエンコードに時間がかかるので、1024×576に小さくするなど環境に合わせて変更して下さい。

my $preset_file = "/usr/local/etc/ts2enc.ffpreset";
my $reso_large = "1280x720"; # 自動判定時の出力解像度(大)
my $reso_small = "720x480";  # 自動判定時の出力解像度(小)
my $quality = 25;      # CRF値(画質, 0-51の範囲指定, 値が小さいほど高画質)
my $v_brate = "1000k"; # 動画ビットレート ※ 2-pass時のみ使用
my $a_brate = "192k";  # 音声ビットレート

 基本的なオプションである、画質、出力解像度、アスペクト比、プリセットファイルの使い方を説明します。全てではありませんが、オプション名はフルネームと短縮形でも指定可能です。

・画質を変更(範囲0から51の整数値、小さいほど高画質だがファイルサイズ増)
$ ts2enc.pl input.ts output.mp4 -quality 18
$ ts2enc.pl input.ts output.mp4 -q 18

・出力解像度とアスペクト比の変更
$ ts2enc.pl input.ts output.mp4 -size 640x480 -aspect 4:3
$ ts2enc.pl input.ts output.mp4 -s 640x480 -a 4:3

・プリセットファイルの変更
$ ts2enc.pl input.ts output.mp4 -preset ~/anime.ffpreset
$ ts2enc.pl input.ts output.mp4 -p ~/anime.ffpreset

画質調整

 ”-tune”オプションにより、映画やアニメなどに適した画質に調整します。

・映画設定
$ ts2enc.pl input.ts output.mp4 -tune film

・アニメ設定
$ ts2enc.pl input.ts output.mp4 -tune animation

・グレイン設定(画面にざらつきを与える)
$ ts2enc.pl input.ts output.mp4 -tune grain

 上記で挙げた例以外のパラメータも指定可能です。以下のコマンドで確認できます。

$ x264 --fullhelp

時間指定による動画切り抜き

 ”-interval”オプションにより、開始と終了時間を指定して動画の切り抜きエンコードを行います。

・00:00:05から01:23:45の範囲指定
$ ts2enc.pl input.ts output.mp4 -interval 00:00:05-01:23:45
$ ts2enc.pl input.ts output.mp4 -i 00:00:05-01:23:45

 時間は”XX:XX:XX”または”XX:XX:XX.XXX”の形式で指定して下さい。小数点以下の秒数も指定可能です。そして、開始と終了時間を”-”(ハイフン)でつないで指定します。

 ”-copy”オプションを使えば、TSファイルをそのまま切り出すことも可能です。

$ ts2enc.pl input.ts output.ts -interval 01:00:00,01:30:40 -copy

 このオプションを指定してエンコードを行うとTSファイルの置いてあるのと同じディレクトリに中間ファイルを作成します。十分な空き容量を確保して実行して下さい。

再生速度倍率

 ”-speed”オプションにより、音程を維持したまま再生速度倍率を変更することができます。倍率は0.5から2.0までの範囲で指定可能です。

・0.5倍速
$ ts2enc.pl input.ts output.ts -speed 0.5

・2倍速
$ ts2enc.pl input.ts output.ts -speed 2.0

2ヶ国語(モノラル主副音声)

 ”-mono”オプションにより2ヶ国語放送の音声出力方法を選択します。ここで言う2ヶ国語放送とは、左から日本語、右から英語の音声が聴こえるような放送のことです。代表的な放送は、NHKの夜7時からのニュースです。

 3種類の出力方法を用意しました。

・主音声(左)のみを使用
$ ts2enc.pl input.ts output.mp4 -mono main

・副音声(右)のみを使用
$ ts2enc.pl input.ts output.mp4 -mono sub

・どちらも使用
$ ts2enc.pl input.ts output.mp4 -mono both

 「どちらも使用」の場合、左右の音声を完全に別トラックとして分離します。VLC media playerで再生するとオーディオメニューのオーディオトラックから別々の音声として選択可能になります。

多重音声(ステレオ二重音声)

 ”-multi”オプションにより多重音声放送の複数の音声を別トラックとしてエンコード出力することができます。

$ ts2enc.pl input.ts output.mp4 -multi

 ここで言う多重音声放送とは、ステレオ音声による複数音声が選択可能な放送のことです。日本語と他国語の切り替えに使われることが多いですが、スポーツ中継などで実況と副音声の形で使われることもあります。

 注意事項があります。PCでTVを録画する場合、番組開始前に5秒程度のマージンを取っている方が多いのではないでしょうか。その場合、多重音声放送であっても、FFmpegの制限により”-multi”オプションは使えません。ファイルの先頭から多重音声でないとFFmpegが多重音声と認識できないためです。

 この問題は、Windows用の”Murdoc Cutter”と言うアプリを使って多重音声放送の頭出しをすることで解決します。FFmpegによる頭出しは出来ません。私が調べた限り、それ以外の方法は見つかっていません。

 念のため補足しておくと、多重音声の頭出しがされているTSファイルであれば、時間指定によるTSの切り出しにも対応しています。

$ ts2enc.pl input.ts output.ts -interval 00:10:00-00:20:00 -multi -copy

 2つ目の注意事項は、2音声多重にしか対応していない点です。放送規格上は8音声まで可能らしいですが、2音声以外を見たことがないので困ることはほぼ無いはずです。

額縁削除

 ”-crop”オプションを使えば、アスペクト比4:3の映像の左右の黒帯を削除することができます。以下は地デジ(解像度1440×1080)の一般的な4:3の映像の場合の指定例です。数値の単位はピクセルです。

$ ts2enc.pl input.ts output.mp4 -crop 1080:1080:180:0 -aspect 4:3

 ”-crop W:H:X:Y”のように映像の出力範囲を指定します。そのため、正確には黒帯を削除するのではなく、黒帯以外の範囲を選択して切り抜くと言うのが正しいです。

 それぞれの指定パラメータの意味は次の通りです。

パラメータ 意味
W 出力サイズ(横幅)
H 出力サイズ(高さ)
X 左上隅原点からの横軸座標、
Y 左上隅原点からの縦軸座標

 この表では意味がわからないと思うので、実際の例を参考に説明します。

FFmpeg cropの例

FFmpeg cropの例

 上の画像は台風接近時のNHKの放送画面を参考にした例です。ピンク色の範囲が切り抜きたい範囲だとすると、”W:H:X:Y”に相当する箇所が分かると思います。

 この範囲の調べ方は、VLC media playerでTSファイルの再生中のスナップショットを撮り、ペイントソフトで調べるのが良いでしょう。

 注意点は、黒帯を完全に削除してしまうと16:9や4:3のアスペクト比に合わなくなることがあります。その場合、それらのアスペクト比に適合するように余白として横または縦の黒帯をあえて残しておくのも一つの手です。

音量調整

 ”-vol”オプションにより音量調整が可能です。

・音量を1.5倍
$ ts2enc.pl input.ts output.mp4 -vol 1.5

・音量を5dB下げる
$ ts2enc.pl input.ts output.mp4 -vol -5dB

 単位dBで指定する際は必ず末尾大文字の”dB”で指定して下さい。そうしないとエラーになります。

2-passエンコード

 ”-two”オプションにより、2-passエンコードを実行します。

$ ts2enc.pl input.ts output.mp4 -two

 これは完全におまけの機能として追加しました。単純に2倍のエンコード時間がかかるので、狙ったビットレートの動画を作りたいなどの用途以外ではあまり使用する場面はないと思います。H.264の2-passエンコードについては、FFmpeg公式ページを翻訳したものがあったので、そちらが参考になります。

 2-passエンコード時の動画のビットレートも”-vbr”オプションで指定できるようにしています。このオプションを指定していない場合のデフォルト値は1000kbpsです。

$ ts2enc.pl input.ts output.mp4 -two -vbr 1500k

録画サーバで使用する方法

 Chinachuとepgrec UNAのそれぞれについて本スクリプトの使用方法を説明します。

Chinachu

 Chinachuでは”config.json”ファイルで録画終了後に任意のコマンドを実行できます。ただし、コマンドに渡される引数が、録画データファイル名と番組情報(JSON)なので、本ブログのスクリプトを使用するには工夫が必要です。

 インストールスクリプトにより、以下の内容の”recordedEnc.sh”と言う名前のスクリプトをインストール済みです(/usr/local/binディレクトリの下)。このスクリプトを録画終了後に実行することにより、録画ファイルと同一ディレクトリにエンコード出力します。エンコード方法を変えたい場合、11行目を編集して下さい。

#!/bin/sh

outfile=${1%.*}.mp4
sec=`awk "BEGIN{srand(); print int(rand()*100)%59+1;}"`

until [ ! `pidof -s ffmpeg` ]
do
    sleep ${sec}
done

/usr/local/bin/ts2enc.pl "$1" "${outfile}" > /dev/null 2>&1

exit 0

 任意のディレクトリに出力したい場合、以下の様にスクリプトを変更して下さい(3、6、14行目が異なる)。3行目で出力先ディレクトリ名を指定します。

#!/bin/sh
 
dir_output="/home/hoge"

outfile=${1%.*}.mp4
mp4file=${outfile##*/}
sec=`awk "BEGIN{srand(); print int(rand()*100)%59+1;}"`
 
until [ ! `pidof -s ffmpeg` ]
do
    sleep ${sec}
done
 
/usr/local/bin/ts2enc.pl "$1" "${dir_output}/${mp4file}" > /dev/null 2>&1
 
exit 0

 次に”recordedEnc.sh”を使うように”config.json”に設定を書き加えます。編集後はChinachuのサービスを再起動するのをお忘れなく。

"recordedCommand": "/usr/local/bin/recordedEnc.sh",

 この設定で録画終了後に”番組名.m2ts”ファイルが”番組名.mp4”ファイルとしてエンコードされます。なお、既にエンコード中の場合、負荷軽減のため終わるまで待つようにしています。並列エンコードをさせません。

epgrec UNA

 epgrec UNAで録画終了後にエンコードするためには、当ブログの記事「epgrec UNAのサムネイルとトランスコード機能(ライブ視聴、FFmpegによる録画終了後MPEG4エンコード)を有効にする方法」の内容をあらかじめ実行して下さい。

 スクリプトをepgrec UNAで使用するには、”epgrec/settings/trans_config.php”ファイルを編集する必要があります。epgrec UNAのデフォルトのエンコード設定として”H264-HD”と”H264-SD”があるので、その後に以下を追記します(40行目付近)。

        7 => array(
                'name'    => 'TS2-Enc',
                'suffix'  => '.ts',
                'tsuffix' => '.mp4',
                'command' => '/usr/bin/perl /usr/local/bin/ts2enc.pl %TS% %TRANS%',
                'succode' => TRUE,
                'tm_rate' => 4.0,
        ),

 これで番組予約時にスクリプトを選択できるようになります。もし、スクリプトのオプションを変更して複数のエンコード方法を登録したい場合、上記の1行目の’7’の値を+1増やし、’TS2-Enc’を別名に変更すれば可能です。

        7 => array(
                'name'    => 'TS2-Enc',
                'suffix'  => '.ts',
                'tsuffix' => '.mp4',
                'command' => '/usr/bin/perl /usr/local/bin/ts2enc.pl %TS% %TRANS%',
                'succode' => TRUE,
                'tm_rate' => 4.0,
        ),
        8 => array(
                'name'    => 'Lang-JP',
                'suffix'  => '.ts',
                'tsuffix' => '.mp4',
                'command' => '/usr/bin/perl /usr/local/bin/ts2enc.pl -mono main %TS% %TRANS%',
                'succode' => TRUE,
                'tm_rate' => 4.0,
        ),

 上記は2ヶ国語放送の主音声を選択するエンコード方法を追加した例です。

 エンコード設定の”tm_rate”の値はエンコードタイムアウト時間に関係しています。

  • エンコードタイムアウト時間 = 録画時間 × tm_rate

 非力なCPUでは上記の4.0では時間切れでエラーになる恐れがあります。その場合、”tm_rate”の値を大きくして時間切れを防ぐか、出力解像度を小さくしてエンコード時間を短縮する必要があります。

 なお、epgrec UNAは1番組ごとにエンコードを実行するので、並列エンコードで負荷が高くなることはありません。