[PR]

[PR]


2011.12.04更新

はじめに

これからの動画ファイルはmp4だ!ということで、今回は地デジチューナーから取り出したTSファイルをffmpegでエンコードする方法についてまとめます。
このページでは、録画からエンコードまでの効率(いかに手間を省くか)を重視しているので、CMカットや品質を重視したエンコード方法について情報収集したい方にはこのページはあまり役に立たないと思います。

環境

ffmpeg 0.6.1のインストール

yumにてffmpeg-develをインストールします。通常版だと音声のエンコードでエラーを出して無音のmp4ファイルが出来上がってしまうため、devel版を用います。
私は、この問題はffmpegの設定で回避するものと思い込み、ハマってしまいました。

# yum install ffmpeg-devel

参考(エンコード中にでてくるエラー)

Error while decoding stream #0.1
Error while decoding stream #0.1
Error while decoding stream #0.1
Error while decoding stream #0.1

この問題は、ぱぱネット(仮)(2009-07-01)さんの所で説明されており、解決するための差分パッチも用意されているようです。
しかし、わざわざソースからコンパイルする事は避けたかったので採用しません。

mp4エンコードの設定

エンコードの際は、画像のサイズや画質など多くの設定を指定する必要があります。
細かな画質の設定はオプションでプリセットファイルを指定します。ファイルはがべこれログさんのページを参考にしました。

filelibx264.ffpreset
-fpre /var/www/html/epgrec/libx264.ffpreset (ver.0.6.1の場合)

ffmpegのオプション設定

チューナーから取り出したTSファイル(生TS)は、何も加工しなければワンセグや文字情報のデータも入ったままの状態です。
しかも、録画のタイミングによっては、ワンセグ動画がHD動画より先に認識されてしまい、再生やエンコードの際にワンセグ動画 が選択されてしまうことがあります。
この問題を解決するためには、ffmpegのオプションでStreamIDを指定します。

StreamIDを調査する方法

StreamIDはffmpegで簡単に調べることができます。

$ ffmpeg -y -i [生TSファイル]

上記コマンドを実行すると、以下のような結果が出力されます。(エンコードは行われない)

    Last message repeated 1 times
[h264 @ 0x85aab10]decode_slice_header error
[h264 @ 0x85aab10]no frame!
 
Seems stream 0 codec frame rate differs from container frame rate: 59.94 (60000/1001) -> 29.97 (30000/1001)
 
Seems stream 2 codec frame rate differs from container frame rate: 29.97 (30000/1001) -> 14.99 (15000/1001)
Input #0, mpegts, from 'GR16_20100807215400_20100807220000.mp4_tmp.ts':
  Duration: 00:06:00.23, start: 85253.616078, bitrate: 14806 kb/s
  Program 2064 ~ÍÂÓKhF|J|Aw
    Stream #0.0[0x111]: Video: mpeg2video, yuv420p, 1440x1080 [PAR 4:3 DAR 16:9], 20000 kb/s, 29.97 tbr, 90k tbn, 59.94 tbc
    Stream #0.1[0x112]: Audio: aac, 48000 Hz, stereo, s16, 193 kb/s
  Program 2065 ~ÍÂÓKhF|J|Aw²
    Stream #0.0[0x111]: Video: mpeg2video, yuv420p, 1440x1080 [PAR 4:3 DAR 16:9], 20000 kb/s, 29.97 tbr, 90k tbn, 59.94 tbc
    Stream #0.1[0x112]: Audio: aac, 48000 Hz, stereo, s16, 193 kb/s
  Program 2066 ~ÍÂÓKhF|J|Aw³
    Stream #0.0[0x111]: Video: mpeg2video, yuv420p, 1440x1080 [PAR 4:3 DAR 16:9], 20000 kb/s, 29.97 tbr, 90k tbn, 59.94 tbc
    Stream #0.1[0x112]: Audio: aac, 48000 Hz, stereo, s16, 193 kb/s
  Program 2448 ~ÍÂÓKhF|J|Aw7HBS
    Stream #0.2[0x281]: Video: h264, yuv420p, 320x180, 14.99 tbr, 90k tbn, 29.97 tbc
    Stream #0.3[0x283]: Audio: aac, 24000 Hz, stereo, s16, 46 kb/s
  Program 2199 ~Ç|¬¤É
At least one output file must be specified

上記結果より、StreamIDが#0.0, #0.1, #0.2, #0.3の4種類存在することがわかります。そこで、この番号(ストリームマップ)を使ってHD動画を指定します。
mpeg2video ・・・ 1440x1080 と表示されているところがHD動画なので、それに対応するStreamIDは0.0となります。
音声の方は、ビットレートが高い方の193kb/sとなっている方に対応するStreamIDの0.1をエンコードの対象とします。

-map 0.0 -map 0.1

とすることでHD画像をエンコードできることになります。

epgrecに対応させる方法

TSファイルをエンコードする際、StreamIDをいちいち確認するのは面倒だし、epgrecなどでエンコードも同時にさせている場合はスクリプトで対応する必要があります。
そこで、StreamIDを自動で認識する簡単なスクリプトtsencode.plをperlで作成しました。

filetsencode.pl.txt

ダウンロード後、拡張子txtは削除してください。
epgrecに組み込む場合は、do-record.shを書き換えます。

PERL=/usr/bin/perl <- perlの実行パス
ENCPROG=/var/video/tsencode.pl <- tsencode.plを置いた場所
elif [ ${MODE} == 1 ]; then
    $RECORDER --b25 --strip $CHANNEL $DURATION ${OUTPUT}_tmp.ts >/dev/null
    $PERL $ENCPROG ${OUTPUT}_tmp.ts ${OUTPUT} 480x360 <-解像度は4:3で指定(理由は後述)
    rm ${OUTPUT}_tmp.ts
elif [ ${MODE} == 2 ]; then
・・・続く

また、config.phpも$MODEにあわせて書き換えます。

$RECORD_MODE = array(
	// ※ 0は必須で、変更不可です。
	0 => array(
		'name' => 'Full TS',	// モードの表示名
		'suffix' => '.ts',	// ファイル名のサフィックス
	),
	
	1 => array(
		'name' => 'MPEG4 640x360',
		'suffix' => '.mp4',
	),
	2 => array(
・・・続く

また、tsencode.pl内の変数$cmdと$ffpresetも個々の環境にあわせて変更する必要があります。

地デジ用の画像サイズとアスペクト比の指定

地デジはフルHDサイズで視聴されますが、放送データ自体の画像サイズは1440x1080のデータです。
テレビ等の受信側で、1440のサイズを1920に引き延ばして映しています。
ffmpeg -iの実行結果からもわかりますが、1440x1080と16:9という情報を元に引き延ばしが行われています。
じゃあ画像サイズはどのように指定すれば良いのか?という問題が生じます。
そこで、5分の生TSファイル523.2MBをいくつか条件を変えてエンコードして、エンコードの速さ、ファイルサイズを比較してみました。

条件-s-aspectエンコード時間ファイルサイズ再生(VLC)再生(QT)
(1)1920x1080無し30分58秒56.1MB
(2)1440x108016:922分8秒46.0MB
(3)640x360無し4分47秒12.3MB
(4)480x36016:94分23秒10.9MB

条件(1)と(2)、条件(3)と(4)はそれぞれ同じ画像サイズのファイルが出来上がりますが、画像サイズは生TSと同じ比にして、aspectで16:9に指定した方がファイルサイズが小さく、エンコードも1〜3割速いことがわかりました。

音ズレ対策

上記コマンドでは、エンコードに成功はするものの、音声が映像よりコンマ数秒遅れます。視聴していても気になる程なので、改善が必要です。
そこで、画像と音声の同期をとるオプション -vsync 1を追加します。
最終的なコマンドです。

$ ffmpeg -y -i [生TSファイル] -f mp4 -vcodec libx264 -vpre /var/xxx/yyy/lib264.ffpreset -r 30000/1001 -aspect 16:9 -s 1440x1080
 -bufsize 20000k -maxrate 25000k -vsync 1 -acodec libfaac -ac 2 -ar 48000 -ab 128k -map 0.0 -map 0.1 [出力ファイル]

参照元URL

がべこれログ - Garbage Collection Logffmpegエンコード設定について詳しく解説

コメント欄

最新の10件を表示しています。 コメントページを参照

  • コメントのテスト -- test? 2010-08-15 (日) 23:25:20
  • > 無音状態、むずかしいですね。tssplitter_lite で program id を指定してひっこぬいたとしても、CM ごとに動画の仕様がことなっていたりしますね。CMを全部引っこ抜いて、そのあとに全部結合してから、mp4 にエンコすれば、たぶん一定の動画仕様になると思うんです。私は面倒なので、CMカットはやっていません :) 暇があったら、CMカットの自動化も試みたいですね。 -- munepi? 2011-03-11 (金) 10:24:40
  • 現状では、音声の質をあきらめて、 -acodec libvo_aacenc -ac 2 -ar 48000 -ab 192 としてしまうのもありかも。libfaacは同梱エンコードされていないことも多いし -- 2011-05-03 (火) 14:32:57
  • テスト -- test? 2012-04-24 (火) 00:13:53
  • 突然失礼します。CPUの使用率が低いときにあとからエンコードさせるようなことはできないでしょうか?(直後に別の録画が複数あるときなどのために -- うにうに? 2013-07-21 (日) 22:49:43
  • do-record.shで後処理のところにatコマンドを使えば、指定時刻に実行できると思います。 -- まつかぜ? 2013-08-12 (月) 22:29:30
  • 使用率ならbatchコマンドは? -- n? 2013-08-25 (日) 20:39:33
  • Invalid option or argumen t: 'deblockalpha=0 ', parsed as 'deblockalpha' = '0' で苦しんでるとです、死にそう -- ううう? 2014-11-18 (火) 23:56:06
お名前:

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS