FFmpegで範囲指定でフレーム抽出する2つの方法とコマンド例

FFMpegで動画フレームを抽出したかったです。

▼ より具体的に書くならこういうこと

  • 動画の一定時間の範内だったり、
  • 動画のフレーム番号の範囲内だったり、
  • その間のフレーム画像を全保存したい

そういった処理はFFmpegでやる方法について

ffmpegでは2つほどやり方があるので、
範囲内のフレーム抽出するコマンド例を紹介します。

方法1.時間範囲を指定してフレーム抽出

初めは時間指定でフレーム抽出する方法

ffmpegではミリ秒単位まで時間指定ができます。

抽象的なコマンド構文は以下の通りです。

▼ 時間指定フレームを抽出するコマンド構文

このコマンドでは [START_TIME] から [END_TIME] までの時間範囲で入力動画(input.mp4)を読み込みしてます。時間表現は 00:12:34.567 みたいにミリ秒単位で可能

そしてffmpegが各フレーム画像を 001.png , 002.png, 003.png みたいに連番で保存していってくれます。

 

以下はより具体的なコマンド例…

  • コマンド例1

    入力動画の 00:15:10.625 ~ 00.19:24.19 までの全てのフレームをカレントディレクトリに連番((001.png, 002.png, 003.png ...)でpng画像保存される

  • コマンド例2

    入力動画の 01:57:24.172 ~ 02.01:83.842 までの全てのフレームをpath/toディレクトリ以下に連番(00001.png, 00002.png, 00003.png ...)で画像保存する

時間指定は人間的には分かりやすいです。

手入力でコマンド実行する時はこっちを使うかも

方法2.フレーム番号の範囲指定でフレーム抽出

お次はフレーム番号によるフレーム抽出です。

例えば 200フレーム目から500フレーム目までとか。

そういう時に使えるのが以下コマンドになります。

▼ フレーム番号指定で抽出するコマンド構文

このコマンドでは [START_FRAME_IDX] から [END_FRAME_IDX] までのフレーム番号の範囲内で入力動画(input.mp4)のフレーム抽出してます。ただし番号が 0 から始まるインデックス

実行するとffmpegがそのフレーム番号内のフレームを連番で保存していきます。001.png, 002.png , 003.png みたいな感じで

 

これも以下に具体的なコマンド例を示します。

  • コマンド例その1

    入力動画の2735~3218フレーム目までが3桁0埋めの連番画像(001.png , 002.png , 003.png...)で保存される

  • コマンド例その2

    入力動画の12345~67890フレーム目までが5桁0埋めの接頭辞付き連番画像(frame_00001.png , frame_00002.png , frame_00003.png...)で保存される

これはffmpegをAPI経由で実行する時に便利です。

後者の方法はFFmpegをコード実行する時に便利!

後者のフレーム番号で抽出する方法について

ffmpegをコード的に実行する時に便利です。

例えばAndroidではffmpegライブラリがあります。

ffmepgコマンドを実行できるAPI

こういったライブラリではコード的にffmpegコマンドを実行するため、フレーム番号指定がとても便利なことがあります。逆に手入力でコマンド実行するなら、前者の 12:34:56.789 みたいな時間指定が直観的で分かりやすいですね。

使い分ければいいと思う

動画時間とフレーム番号の相互変換について

それから最後に豆知識

動画のフレームを抽出する時、

  • 再生ミリ秒時間 ⇒ フレーム番号
  • フレーム番号 ⇒ 再生ミリ秒時間

みたいに相互変換することも可能です。

それぞれ具体的に次の変換式です。

▼ 再生時間 ⇒ フレーム番号 に変換する式

※ ただし FPS = Frames Per Seconds

まず (1000 / FPS) によって1フレーム当たりの経過ミリ秒を計算し、それとミリ秒換算の再生時間(TIME_MILLIS)を割ってるだけです

▼ フレーム番号 ⇒ 再生時間 に変換する式

1つ前の式をいじくって変形しただけです。