2019年2月2日土曜日

早送りのスムーズな動画を作りたい(ffmpeg)

撮影した動画を変換するときに、Windowsムービーメーカーを愛用していました。

PanasonicのビデオカメラのMTS形式の動画を、mp4形式に変換していたのですが、一括での変換が出来ないんです。。。
なので、まずはffmpegを使用してWindowsムービーメーカーと同等の動画を作ってみます。

1.ほしい動画の要件

ほしい動画は
・サイズは小さくなってOK
・音ズレはしてほしくない
GOMPlayerで再生できる
・再生位置の移動(早送り)が早い
です。

2.ffmpegの利用

変換のベースとしてffmpegを使用しました。
ffmpegは細かな設定が可能な動画編集アプリです。
一般的なWindowsフォームアプリではなく、コンソール(コマンドプロンプト)で動くアプリなので、とっつきにくい印象派あるかと思いますが、自作のプログラムからの呼び出しも可能なのでとても便利です♪
FFmpegについてはWindowsで使用しています。

3.mp4形式へ変換する

変換するためのコマンドはこれだけでOKです。

  ffmpeg -i 変換した動画名.MTS 変換後の動画名.mp4  

でも、ただ変換しただけだと、なんだか再生したときの感じが違っていました。
なので、理想の動画にするために、動画の情報を比較してみました。


4.動画の形式を調べる

まずは、現状のWindowsムービーメーカーで作成した動画の情報を調べました。

コマンドプロンプトで

  ffmpeg -i 情報を確認したい動画名.mp4  

のように入力することで、動画の情報が表示されます。

私の場合、ムービーメーカーで変換した動画では、以下のような情報が表示されました。
(必要な部分を抜粋しています)

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'Movie.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: mp41isom
  Duration: 00:00:21.61,
  start: 0.000000,
  bitrate: 2690 kb/s
  Stream #0:0(und):
    Video: h264 (Constrained Baseline) (avc1 / 0x31637661),
    yuv420p,
    854x480,
    2484 kb/s,
    29.97 fps,
    29.97 tbr,
    29970 tbn,
    59940 tbc (default)

  Metadata:
    handler_name: VideoHandler
    encoder         : AVC Coding
  Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D),
  48000 Hz,
  stereo, fltp, 197 kb/s (default)
  Metadata:
    handler_name    : SoundHandler
At least one output file must be specified


同様に、ffmpegで変換した動画についても、情報を取得し異なっている部分について、設定を入れていきます。

「Stream #0:0」と「Stream #0:1」という部分があり、「Stream #0:0」が動画で「Stream #0:1」が音声についての情報です。
今回は音声は気にしていないので、動画部分の情報だけ調べていきます。

また「Metadata」部分は関係ないので無視します。

5.動画の情報を比較する

今回の比較対象は以下の部分です

ムービーメーカーで変換した動画の情報

 Duration: 00:00:21.61,
  start: 0.000000,
  bitrate: 2690 kb/s
  Stream #0:0(und):
    Video: h264 (Constrained Baseline) (avc1 / 0x31637661),
    yuv420p,
    854x480,
    2484 kb/s,
    29.97 fps,
    29.97 tbr,
    29970 tbn,
    59940 tbc (default)


ffmpegで単純に変換した動画

  Duration: 00:00:21.61,
  start: 0.000000,
  bitrate: 5197 kb/s
  Stream #0:0(und):
    Video: h264 (High) (avc1 / 0x31637661), yuv420p,
    1920x1080 [SAR 1:1 DAR 16:9],
    5067 kb/s,
    29.97 fps,
    29.97 tbr,
    30k tbn,
    59.94 tbc (default)


たとえば、サイズを指定する場合、

  ffmpeg -i 変換した動画名.MTS -s 854x480  変換後の動画名.mp4  

プロファルを指定する場合

  ffmpeg -i 変換した動画名.MTS -profile:v baseline  変換後の動画名.mp4  

の赤字のように設定を追記していきます。

両方を指定するなら、続けて書けばOKです。

  ffmpeg -i 変換した動画名.MTS -s 854x480  -profile:v baseline 変換後の動画名.mp4  

6.GOPを指定する

私の場合、設定を合わせていっても、望んだ動画になりませんでした。。。
先に書いた要件は満たしているのですが、
動画を早送りしたときに遅い
という問題がありました。一瞬、移動先で固まるんです・・・

ちなみに、動画の早送りはシークと言います。
シークで調べると、GOPを指定することで対応が出来るようです。

  ffmpeg -i 変換した動画名.MTS -g 1  変換後の動画名.mp4  

上記の例では1秒ごとにキーフレームを設定しています
「1」の部分が小さいほど、早送りがスムーズになりますが、動画のファイルサイズは大きくなります。

7.一括変換する

プログラムの作りによりますが、ドラッグ&ドロップされた動画について変換するようなプログラムを書くことになるのかなと思います。
シェルなどでも書けそうですが、C#を使う場合、以下のように記述することでffmpegを呼び出すことが出来ます。



System.Diagnostics.Process p = new System.Diagnostics.Process();

p.StartInfo.FileName = ffmpegのパス;

p.StartInfo.Arguments = "ffmpegで指定したいプロパティ";

p.StartInfo.UseShellExecute = false;

p.Start();

p.WaitForExit();



ちなみに、一括処理としてはHandbrake も使用できます。
設定が多いので、細かい設定を狙い通りに出来るのかは試せていないのですが・・・