FFmpegで素早く正確に動画をカットする自分的ベストプラクティス

  • 65
    Like
  • 3
    Comment
More than 1 year has passed since last update.

ちょっと昔のリリースになるのですが、FFmpeg 2.1から動画の一部分を切り出す性能が大幅に上がりました。ここでは、バージョン2.1以降のFFmpegを前提に、動画を素早く正確にカットする自分的ベストプラクティスをメモします。

※ドキュメントをよく読めば書いてあるのですが、結構ハマりどころなので自分でテストもしてみました

はじめに...結論を

はじめに結論を言ってしまうと、バージョン2.1以降であれば

  • 開始地点(-ss)はソースの指定(-i)より手前に置く
  • 必ずエンコードする(-codec copyとかやらない)

とやるのが一番正確に(かつそこそこ速く)カットできます!例えばこんな感じです。

ffmpeg -ss [開始地点(秒)] -i [入力する動画パス] -t [切り出す秒数] [出力する動画パス]

背景を少し

これまで

FFmpegはバージョン2.1以前でも簡単に動画を切り出すことができました。例えば、

ffmpeg -i input.mp4 -ss 300 -t 60 output.mp4

とやると、input.mp4の5分地点から1分間の動画を切り出すことができます。しかしこれには問題があり、 切り出し開始地点までシークするのにめっちゃ時間かかるんです!

このあたりの挙動は公式ドキュメントのSeeking-FFmpegに書かれていて、曰く「-ssを書く位置によってシークの早さが変わるよ。-ssを-iより手前に置くと爆速だよ。」とのこと。

実際に-ssを-iより手前に置いてやってみると、確かにシークは早くなる(ほぼ一瞬)のですが、トレードオフとして正確性が損なわれます。10秒くらい平気でズレます。

バージョン2.1以降

しかし、2.1リリース後に上記のドキュメントにこんな内容が追記されました。

As of FFmpeg 2.1, when transcoding with ffmpeg (i.e. not just stream copying), -ss is now also "frame-accurate" even when used as an input option. Previous behavior (seeking only to the nearest preceding keyframe, even if not precisely accurate) can be restored with the -noaccurate_seek option.

つまり、-ssを-iより手前に置いても トランスコードさえすれば 正確にシークできるようになったと。これは嬉しい!

各パターンでテストしてみる

テストといっても4パターンだけなのですが、それぞれ何が起こるのか実際に動かしてみました。

パターン

以下の変数を掛け合わせた計4パターンで、処理時間の違いや、切り出される動画の正確性の違いを確認していきます。

  • -ssの位置
    • -iより手前
    • -iより後ろ
  • トランスコード
    • やらない(-codec copyを指定)
    • やる

実施内容

スイスアルプスを優雅に駆け抜ける約2時間のフライト動画から、ちょうどマッターホルンが見えてくる1時間15分地点から1分間の動画を切り出します。

パターン コマンド
1a. -ss手前,エンコなし ffmpeg -ss 4500 -i input.mp4 -t 60 -vcodec copy -acodec copy 1a.mp4
1b. -ss手前,エンコあり ffmpeg -ss 4500 -i input.mp4 -t 60 1b.mp4
2a. -ss後ろ,エンコなし ffmpeg -i input.mp4 -ss 4500 -t 60 -vcodec copy -acodec copy 2a.mp4
2b. -ss後ろ,エンコあり ffmpeg -i input.mp4 -ss 4500 -t 60 2b.mp4

結果

正確に切り出しができたのはトランスコードを行った1bと2bですが、パフォーマンス面で1bの方が優れています。トランスコードを行わなかった1aと2aは、正確性面で何らかの問題がありました。バージョン2.1で何が嬉しくなったかといえば、1bのやり方でも正確に切り出せるようになったことなのです!

パターン 処理時間 ffprobeより抜粋 その他備考 結果動画
1a. -ss手前,エンコなし 0.19秒 Duration: 00:01:01.86
start: -1.853605
指定した-tより1.86秒
長く切り出されている。
見る
1b. -ss手前,エンコあり 24.8秒 Duration: 00:01:00.04
start: 0.036281
見る
2a. -ss後ろ,エンコなし 1.38秒 Duration: 00:01:00.00
start: 0.002993
はじめの3秒くらい
映像が存在しない。
見る
2b. -ss後ろ,エンコあり 133.26秒 Duration: 00:01:00.04
start: 0.036281
-ssの値が大きければ
大きいほどシークに
時間がかかる。
見る

以上、何かのお役に立てれば幸いです。