2012/06/06

最新ffmpegでどうにかする


wavecast標準システムも epgrec も、 なんとなく落ち着いてきたが、たまに録画結果にがっかりする時がある。途中から音と映像が大きく(数秒)ズレこんでしまうのだ。これをどうにか解消したい。

現在の手順
  1. TSからHDストリームだけを抽出
  2. HDTSからビデオとオーディオをdemuxして分離
  3. ビデオ(m2v)をH264にエンコード
  4. オーディオ(wav)をsoxでズレを微調整
  5. オーディオ(wav)をfaacにエンコードと同時にビデオとミックス
  • 最後の合成段階で同期処理が適切に行われない場合があるんじゃないか?
  • -vsync 1オプションで同期されるというが、壊れるケースがあるんじゃ困る。
  • 分離した方が機能がフルに使えて都合がよいというが、地デジ録画という特定条件に対して、どれほどの意味があるのか、自分はよく分からない。
ということでエンコードフローを見直すことにした。根拠が薄いので、これも実験だけど。

プランとしてはこんなイメージ
  • フローを最小化することで途中の問題点を回避できるかも
  • 最新ffmpegを使用することで不具合が解消できるかも
  • 全体の処理時間が短縮出来ればそれはそれで喜ばしい
最初は楽してどうにかならないかと思って、apt-get でffmpegインストールしてみたけど、コンフィグが--enable-libfaacじゃなかった。h264とかfaacとかライセンスがめんどくさいんで、使いたい人は自分でコンフィグしろよって感じかな。ということで、ソースからビルドです。

wavecast-01(v1.8)に入っているffmpegのバージョンは「SVN-r26402」ですな。これはこれで古くはないけど、ffmpeg.orgへ行くと、SVNリポジトリはこのリビジョンで凍結。以降はGitリポジトリで開発するって。今後のメンテナンスも考えるとGitリポジトリで進めるほうがよさそう。

ffmpeg Gitリポジトリの入手  (色んなミラーがあるけど自分はここにした)
$ git clone git://github.com/FFmpeg/FFmpeg.git ffmpeg
これでffmpegにソース一式がダウンロードされる。リポジトリのアップデートは
$ cd ffmpeg
$ git pull
ってやれば現在の最新にアップデートされる。だけど最新≠安定じゃないから理解の上で。
ffmpegディレクトリ以下で、コンフィグ確認。

$ ./configure --enable-libx264 --enable-libfaac
libx264はGPLだから--enable-gplつけろって怒られる

$ ./configure --enable-libx264 --enable-libfaac --enable-gpl
libfaacはnonfreeだから--enable-nonfreeつけろって怒られる

$ ./configure --enable-libx264 --enable-libfaac --enable-gpl --enable-nonfree
libx264 version must be >= 0.118と怒られる

$ sudo apt-get install x264=0.118
とか、適当じゃ入らなかった。新しめのことはやっぱり面倒くさい。
まずはlibx264を入手して、ソースからビルド
$ git clone git://git.videolan.org/x264.git でリポジトリから入手。最近はgitが多いね。
コンフィグテストでyasmが無いよって言われたので
$ sudo apt-get install yasm
で入れる。
$ ./configure --enable-shared(アプリじゃなくライブラリが欲しいので)
$ make
$ sudo make install
/usr/local/libに入る。念のため、ldconfigやるか?いっか。
ffmpegへもどって
$ ./configure --enable-libx264 --enable-libfaac --enable-gpl --enable-nonfree
通った。そうそう、libfaacは最初から入ってたのを使う。これでビルド環境は整った。

本番コンフィグ

wavecastにインプリメントされているffmpegは以下のようにコンフィグされている
configuration: --enable-gpl --enable-version3 --enable-nonfree --enable-postproc --enable-libfaac --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxvid --enable-x11grab --extra-cflags='-mtune=core2 -mfpmath=sse -msse'
これを参考に、最新には使えなかった設定とx11grabとかいらないよ。と思うやつを消して
./configure --enable-gpl --enable-version3 --enable-nonfree --enable-postproc --enable-libfaac --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libtheora --enable-libvorbis --enable-libx264 --enable-libxvid --extra-cflags='-mtune=core2 -mfpmath=sse -msse' --enable-avresample
 な感じになった。最後の--enable-avresampleを追加したのは、ドキュメントを読むとasynctsオプションが使えるようになるらしいと、asynctsは音声をタイムスタンプに同期するためのものらしいと、今回の目的に合いそうなオプションなので入れてみた。

で、無事コンフィグが通ったら
$ make
$ sudo make install
で、ビルド&インストール。
アプリは/usr/local/bin、プリセットは/usr/local/share/ffmpeg に入る。

エンコードテスト

$ ffmpeg -y -i TEST.ts -c:v libx264 -c:a libfaac -vpre ibento7 -f mp4 TEST.mp4
(ibento7はwavecastで用意されているプリセット)
Unrecognized option 'directpred'
/home/wave/.ffmpeg/ibento7.ffpreset: Invalid option or argument: 'directpred=1
', parsed as 'directpred' = '1'
エラー出るじゃないですか!

$ ffmpeg -y -i TEST.ts -c:v libx264 -c:a libfaac -vpre libx264-fast -f mp4 TEST.mp4
(libx264-fastはffmpegの付属プリセット)

でも同じエラーが。

試しに、directpredオプションを外してみたが、別のエラーが出てダメなプリセットだと言われる。
これを質問している記事を何件か見つけたけど、めぼしい解答が付いてない。
が、ひとつ糸口を見つけた。-presetを使ってみよという記事が。
(何処の記事だったかわからなくなりました・・)

確かにドキュメントを読むと、-vpre,-apre,-spreの他に-presetがある。しかも
-preset libx264-fastじゃだめで、-preset fastって書くらしい。
ファイル名のプリフィックスはエンコーダ名に紐付いているようなのだが・・・

結局のところ、-presetは、x264の--presetのことらしい。
詳しくは’x264 --fullhelp’ってやんなさいってffmpegのヘルプに書いてある。ややこしい。

$ ffmpeg -y -i TEST.ts -c:v libx264 -c:a libfaac -preset fast -f mp4 TEST.mp4

おお。動いた! 
そうそう。-c:v -c:aは、-vcodec,-acodecの別の書き方。気分です。

-vpre -fpreが使えないっす。実際のところ、どうするんでしょ? 

カスタムプリセットはひとまず諦め。x264プリセットなら使えそうなので、方針変更。
最新で標準的な使い方は2012年版FFmpeg が詳しく書かれています。


で、なんだかんだと実験した結果、こうなった
 (以前書いた、epgrec/do-record.shから抜粋)
  1. /usr/local/bin/ffmpeg -y -i /tmp/${REC}.ts -c:v libx264 -c:a libfaac -preset fast -b 2000k -s 960x540 -aspect 16:9 -f mp4 -threads 0 /tmp/${REC}.mp4
  2. /usr/bin/MP4Box -ipod -inter 500 /tmp/${REC}.mp4 -out $OUTPUT
  • tssplit2でのHDストリーム抽出やめ。
  • tsdemux2でのvideo/audio分離やめ。
  • よって、sox調整なし
  • よって、video/audio合成なし
素のTSファイルからh264/faacのmp4を作成。MP4BoxでiPod対応。だけになった。

映像は?
自分にとっては、-preset fast -b 2000k で十分かつ現実的かな。ウソ。現実的じゃなかった。続編へ。
以前は-r 24とか入れてたけどスポーツ番組には不向きだったので外した。

サウンドは?
エンコード劣化があると、こもった感じになるんで、48kHz,128kbpsのまま。

同期は?
今のところ良い感じ。ちょっと音が速いのでは?という番組もあるが、数秒ずれてしまう現象は今のところ発生していない。まあこの辺はもう少し実績をつまないとだけど。

 -tune ってのがあるらしい
x264の--tuneへ渡すオプションがffmpegの-tuneらしい。-tune animation とか、-tune film とかやれるそうな。録画情報からタイプを識別して振り分けとか出来るかもね。

asyncts どうなった?
えー、良く分からん。というか全然分からん。ドキュメントによると、
‘compensate’‘min_delta’‘max_comp’という3つのパラメータがあるらしいのだが
$ ffmpeg -i TS -filter_complex asyncts=max_comp OUT-file
ってやってみたものの、max_compなんて知らんって言われる。
色々入出力条件とかあるのか?・・・忘れることにする。


様子見
/root/taskの方は今までどおり、epgrec/do-record.sh を実験台にして様子見。
特に悪くなさそうなら、/root/taskの方へも反映させよう。

なんてもっともらしいことを書いてまとめようとしているが、結果から別段最新ffmpegである必要はなかったのでは?とも思う。が、色々やるんだったらやっぱり新しい方を使いたかったのだよ。私はやっぱり新車に乗りたいのだよ。

0 件のコメント:

コメントを投稿