k_piの雑記帳

個人的に困った点と、その解決法などをつらつら書き連ねた備忘録を兼ねたブログ

ffmpegでMPEG2-TSファイルをmp4に変換する

【変換元・変換先】

変換元MPEG2-TS:動画MPEG2(インターレース)・音声AAC
変換先MP4:動画H.264/AVC・音声AAC

【動機】

最近まで、FreemakeVideoConverterを使っていたのだが、Freemakeという組織があまりはっきりしないことから脱FreemakeVideoConverterを図ることにした。
調べてみると、%PROGRAMFILES%\Freemake\Freemake Video Converter\FMCommon\FreemakeCommon\Profiles\FMCommonCodecProfiles.xmlffmpegのオプションが書かれているし、
%PROGRAMFILES%\Freemake\COM\1.1\ffmpeg.exeにはffmpegが存在している。
つまりは、FreemakeVideoConverterは内部的にはffmpegで処理しており、ffmpegに置き換えられるということなので、ffmpegへの置き換えを図る。

【概要】

今回は、Windows上で、ffmpegバージョンgit-6c91afeを利用し、MPEG2-TSファイルをmp4に変換する。
ffmpegはバージョンによって、オプションや変数の表記が違うようなのでそこらへんも書いていこうと思う。

【変換の下準備】

  1. libx264を導入したffmpegを用意する。

    http://ffmpeg.org/download.htmlからビルド済みのものをダウンロードすれば良いだろう。

  2. ffmpeg.exeがあるフォルダに、以下のようなプリセットファイルを作成する。


    <x264_main.ffpreset>*1

    x264-params=vbv-maxrate=20000:vbv-bufsize=25000:nal-hrd=vbr 
    profile:v=main
    level=40
    b:v=5120000
    movflags=+faststart
    coder=1
    cmp=+chroma
    partitions=+parti4x4+partp8x8+partb8x8
    me_method=hex
    subq=6
    me_range=16
    g=250
    keyint_min=25
    sc_threshold=40
    i_qfactor=0.71
    b_strategy=1
    qcomp=0.6
    qmin=10
    qmax=51
    qdiff=4
    fast-pskip=1
    direct-pred=3
    
  3.  ffmpeg.exeがあるフォルダに、以下のようなバッチを作成する。
    (2019/02/21追記あり。下記の【追記2】も確認のこと)
    <encode.bat>
    (デインターレースする場合)
    cd /d %~dp0
    ffmpeg.exe -i %1 -fpre x264_main.ffpreset -pass 1 -filter:v yadif -flags +loop+global_header -vcodec libx264 -acodec copy -bsf:a aac_adtstoasc %~dpn1.mp4
    del "ffmpeg2pass-0.log"
    del "ffmpeg2pass-0.log.mbtree"
    pause
    
    (インターレース保持する場合)
    cd /d %~dp0
    ffmpeg.exe -i %1 -fpre x264_main.ffpreset -pass 1 -flags +loop+global_header+ildct+ilme -weightp 0 -vcodec libx264 -acodec copy -bsf:a aac_adtstoasc %~dpn1.mp4
    del "ffmpeg2pass-0.log"
    del "ffmpeg2pass-0.log.mbtree"
    pause
    

【変換】

encord.batに変換元のファイルをドラッグアンドドロップでOK

【プリセットファイル・バッチファイルのオプションについて】

大体は、最新FFmpeg - MobileHackerz Knowledgebase Wikiからいただきました。
変更箇所としては、

  • profile:v=main・level=40を追加して、partitionsからparti8x8を削除することで確実にmainプロファイル・レベル4.0に合致させている。
  • b:v=5120000を追加しターゲットビットレートを5000kbpsにセットした。
  • aacがadtsヘッダを持つ場合、-bsf:a aac_adtstoascを追加することで、-acodec copyにしておいても、上手いことraw aacに変換してくれる。
  • x264-params=vbv-maxrate=20000:vbv-bufsize=25000:nal-hrd=vbrを追加し、再生互換性の向上を行っている。多少ファイルサイズが大きくなるようだが、今回の場合は誤差に収まる。*2
  • ワンパスにするために-pass 1を追加。
  • movflags=+faststartを追加し、動画情報を保持しているmoovをファイル先頭に移動させ、動画情報を速く取得できるようにする。
    これには、多少時間がかかるが、そんなにかかりはしない。
  • flags2=+fastpskip→fast-pskip=1・directpred=1→direct-pred=3に変更。
    どうやら、表記法が変わったようだ。
  • flagsに+global_headerを追加。
    「グローバルヘッダー」が何たるかは把握していないが、これをしないとテレビやスマホといったDLNA対応機器で再生できなかったので注意。
    他のサイトでは、あまり指定するようには言われていないことから、バージョンアップでデフォルトではなくなったのかもしれない。
  • (デインターレースする場合)
    現在、デインターレースは-deinterlaceではなく-filter:v yadifを指定してやるのが標準であり、今回の場合では特にジャギーなどは気にならなかった。
  • インターレース保持する場合)
    flagsに+ildct+ilmeを追加すれば、インターレース用の処理をしてくれる。
  • インターレース保持する場合)
    -weightp 0を追加した。これは、インターレースを保持する場合はweight pを無効にする必要があるからである。

 

その他いろいろやりたい場合は、ffmpeg Documentationを参考にすれば良いだろう。

いろいろ書いたが、良く分かっている方からすれば「?」と思われるところもありそうで怖い(´・ω・`)

 

【追記】

音声部分のADTSヘッダが壊れている場合、

  • 一旦分離して別のツールで補正する。
  • 「-acodec copy -bsf:a aac_adtstoasc」→「-acodec aac -profile:a aac_low -strict experimental」としてffmpeg内蔵aacコーデック(vo_aacenc)による再変換をする。

という二択になりそう。
(「vo_aacencは評判が良くないから使いたくない!」という場合は、FDK-AACを含んだffmpegを自力でビルドすることになる。(FDK-AACはライセンスの関係上、ffmpegと一緒には配布できない。))

【追記2】

記事作成時から自前環境のオプションを変更したので、一応追記しておく。
変更理由は以下の二点。

  •  b:vでビットレートを指定するよりも、CRF値(品質値)で設定したほうが、品質を維持しながらファイルサイズを小さくできる。
  • 自前のプリセットではなく、x264のデフォルトプリセットでも品質は十分保てる

ということで、これらの変更を加えた以下のような感じでエンコしている。参考まで。
<encode.bat>

(デインターレースする場合)
cd /d %~dp0
ffmpeg.exe -i %1 -pass 1 -filter:v yadif -vcodec libx264 -x264-params vbv-maxrate=20000:vbv-bufsize=25000:nal-hrd=vbr -profile:v main -level 40 -crf 18 -preset slower -pass 1 -flags loop+global_header -movflags +faststart -acodec copy -bsf:a aac_adtstoasc %~dpn1.mp4
del "ffmpeg2pass-0.log"
del "ffmpeg2pass-0.log.mbtree"
pause

(インターレース保持する場合)
cd /d %~dp0
ffmpeg.exe -i %1 -pass 1 -vcodec libx264 -x264-params vbv-maxrate=20000:vbv-bufsize=25000:nal-hrd=vbr -profile:v main -level 40 -crf 18 -preset slower -pass 1 -flags loop+global_header+ildct+ilme -weightp 0 -movflags +faststart -acodec copy -bsf:a aac_adtstoasc %~dpn1.mp4
del "ffmpeg2pass-0.log"
del "ffmpeg2pass-0.log.mbtree"
pause