&color(red){2012.01.23更新};&br; &color(red){2014.03.26更新};&br; #contents *はじめに [#yb05b206] これからの動画ファイルはmp4だ!ということで、今回は地デジチューナーから取り出したTSファイルをffmpegでエンコードする方法についてまとめます。&br; このページでは、録画からエンコードまでの効率(いかに手間を省くか)を重視しているので、CMカットや品質を重視したエンコード方法について情報収集したい方にはこのページはあまり役に立たないと思います。&br; ***環境 [#k4c291f7] --Scientific Linux 6.1&br; --Scientific Linux 6.1(後にCentOS 6.3に変更)&br; --アースソフト PT2&br; --ソースファイル・・・PT2から出力されたTSファイル --ffmpeg・・・FFmpeg version 0.6.1, Copyright (c) 2000-2010 the FFmpeg developers built on Dec 4 2010 09:30:59 with gcc 4.4.4 20100726 (Red Hat 4.4.4-13) --ffmpeg・・・FFmpeg version 0.6.1, Copyright (c) 2000-2010 the FFmpeg developers built on Dec 4 2010 09:30:59 with gcc 4.4.4 20100726 (Red Hat 4.4.4-13)&br; 後にアップデート後、ffmpeg version 1.1 Copyright (c) 2000-2013 the FFmpeg developers built on Jan 17 2013 20:19:15 with gcc 4.4.6 (GCC) 20120305 (Red Hat 4.4.6-4) *ffmpeg 0.6.1のインストール [#hd91e897] *ffmpegのインストール [#hd91e897] yumにてffmpeg-develをインストールします。通常版だと音声のエンコードでエラーを出して無音のmp4ファイルが出来上がってしまうため、devel版を用います。&br; 私は、この問題はffmpegの設定で回避するものと思い込み、ハマってしまいました。 # yum install ffmpeg-devel ***参考(エンコード中にでてくるエラー) [#tfbcdd73] 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)>http://linux.papa.to/?date=20090701]]さんの所で説明されており、解決するための差分パッチも用意されているようです。&br; しかし、わざわざソースからコンパイルする事は避けたかったので採用しません。 *mp4エンコードの設定 [#gecee4a3] エンコードの際は、画像のサイズや画質など多くの設定を指定する必要があります。&br; 細かな画質の設定はオプションでプリセットファイルを指定します。ファイルは[[がべこれログ>http://d.hatena.ne.jp/munepi/20091227/1261941397]]さんのページを参考にしました。&br; #ref(libx264.ffpreset)&br; -fpre /var/www/html/epgrec/libx264.ffpreset (ver.0.6.1の場合) -vpre /var/www/html/epgrec/libx264.ffpreset (ver.0.5.2の場合) -fpre /var/www/html/epgrec/libx264.ffpreset (ver.0.6.x以後の場合) -vpre /var/www/html/epgrec/libx264.ffpreset (ver.0.5.xの場合) *ffmpegのオプション設定 [#u9e16bd1] チューナーから取り出したTSファイル(生TS)は、何も加工しなければワンセグや文字情報のデータも入ったままの状態です。&br; しかも、録画のタイミングによっては、ワンセグ動画がHD動画より先に認識されてしまい、再生やエンコードの際にワンセグ動画 が選択されてしまうことがあります。&br; この問題を解決するためには、ffmpegのオプションでStreamIDを指定します。&br; **StreamIDを調査する方法 [#u8e0f674] 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動画を指定します。&br; mpeg2video ・・・ 1440x1080 と表示されているところがHD動画なので、それに対応するStreamIDは0.0となります。&br; 音声の方は、ビットレートが高い方の193kb/sとなっている方に対応するStreamIDの0.1をエンコードの対象とします。&br; -map 0.0 -map 0.1 とすることでHD画像をエンコードできることになります。&br; ***epgrecに対応させる方法 [#r2ed6ece] TSファイルをエンコードする際、StreamIDをいちいち確認するのは面倒だし、epgrecなどでエンコードも同時にさせている場合はスクリプトで対応する必要があります。&br; TSファイルをエンコードする際、StreamIDをいちいち確認するのは面倒です。&br; そこで、StreamIDを自動で認識する簡単なスクリプトtsencode.plをperlで作成しました。 &color(red){2012.01.23音声のビットレートを誤認する不具合を修正};&br; #ref(tsencode.pl.txt) ダウンロード後、拡張子txtは削除してください。&br; epgrecに組み込む場合は、do-record.shを書き換えます。&br; 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にあわせて書き換えます。&br; $RECORD_MODE = array( // ※ 0は必須で、変更不可です。 0 => array( 'name' => 'Full TS', // モードの表示名 'suffix' => '.ts', // ファイル名のサフィックス ), 1 => array( 'name' => 'MPEG4 640x360', 'suffix' => '.mp4', ), 2 => array( ・・・続く また、tsencode.pl内の変数$cmdと$ffpresetも個々の環境にあわせて変更する必要があります。&br; **地デジ用の画像サイズとアスペクト比の指定 [#qbd3b1b1] 地デジはフルHDサイズで視聴されますが、放送データ自体の画像サイズは1440x1080のデータです。&br; テレビ等の受信側で、1440のサイズを1920に引き延ばして映しています。&br; 地デジはフルHDサイズで視聴されますが、放送データ自体の画像サイズは1440x1080のデータで、それをテレビ内部で1920x1080に引き延ばして映しています。&br; ffmpeg -iの実行結果からもわかりますが、1440x1080と16:9という情報を元に引き延ばしが行われています。&br; じゃあ画像サイズはどのように指定すれば良いのか?という問題が生じます。&br; そこで、5分の生TSファイル523.2MBをいくつか条件を変えてエンコードして、エンコードの速さ、ファイルサイズを比較してみました。&br; じゃあ画像サイズはどのように指定すればエンコードの効率が良いのか?という問題が生じます。&br; そこで、5分の生TSファイル523.2MBをいくつか条件を変えてエンコードして、エンコード時間、ファイルサイズを比較してみました。&br; |条件| -s | -aspect |エンコード時間|ファイルサイズ|再生(VLC)|再生(QT)|h |(1)|1920x1080|無し|30分58秒|56.1MB|可|可| |(2)|1440x1080|16:9|22分8秒|46.0MB|可|可| |(3)|640x360|無し|4分47秒|12.3MB|可|可| |(4)|480x360|16:9|4分23秒|10.9MB|可|可| 条件(1)と(2)、条件(3)と(4)はそれぞれ同じ画像サイズのファイルが出来上がりますが、画像サイズは生TSと同じ比にして、aspectで16:9に指定した方がファイルサイズが小さく、エンコードも1〜3割速いことがわかりました。&br; **音ズレ対策 [#k9103f7c] 上記コマンドでは、エンコードに成功はするものの、音声が映像よりコンマ数秒遅れます。視聴していても気になる程なので、改善が必要です。&br; そこで、画像と音声の同期をとるオプション -vsync 1を追加します。&br; 最終的なコマンドです。&br; $ 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 [#z5447b69] [[がべこれログ - Garbage Collection Log>http://d.hatena.ne.jp/munepi/20091227/1261941397]]ffmpegエンコード設定について詳しく解説 *コメント欄 [#l4d8e5a4] #pcomment_nospam(,10,avobe)