2017-06-01 11 views
0

まず、大量のビデオを処理しなければならず、ビデオ1秒間でさえシェービングしなければならないということを前提に説明しましょう。ビデオからイントラフレームを取得する

私はビデオ内のすべてのイントラフレームの位置を抽出しようとしています。

FFProbeは機能しますが、それは驚くほど遅いです。

FFMpegの方がはるかに高速ですが、まだまだ遅いです。

だから、私の質問は、私は、この擬似コードのような何かを行うことができlibに、存在する場合である:

var frame = first_frame; 
do 
{ 
    if (frame.type == intra_frame) log(frame.time); 
    frame = frame.next; 
} while (frame != null); 

をし、フレームの内側に何を見ていない、非常に高速なビデオをスキャンは、ちょうどヘッダーはフレームの種類を見つけ、次のフレームに移動します。

最後の目標は、プレビューのためにできるだけ早くフィルムストリップを生成することです。私は、ムービー全体におよそ均等に広がった48のサムネイルを生成し、ムービー全体をカバーする必要があります(両端に5秒を除く)。私はイントラフレームだけを抽出することによってプロセスを高速化することを望んでいます。私はサムネイルの固定数を必要とするので、私はイントラフレームの総量を知ることによってのみこれを行うことができます。

このシナリオは、すべてのイントラフレームインデックスを検索し、48個のイントラフレームを抽出する時間が、1回のパスで一定間隔で48回フレームを取得する時間よりも短い場合にのみ機能します。


編集:これまで私が見つけた解決策です。この例では、1分に1フレームを取ります。

ffmpeg -hide_banner -skip_frame nokey -i _a.mp4 -vf "select='eq(pict_type\,PICT_TYPE_I)*(lt(abs(t\-30)\,2)+lt(abs(t\-90)\,2)+lt(abs(t\-150)\,2)+lt(abs(t\-180)\,2)+lt(abs(t\-240)\,2)+lt(abs(t\-300)\,2)+lt(abs(t\-360)\,2)+lt(abs(t\-420)\,2))',showinfo,scale=640:480,tile=6x8" -vsync 0 frames.jpg 

フレームを直接指定すると、実際には速度の違いはありません。

APIを経由しないと、FFMPEGの方が速いのですか?

+0

これは経験的に行うことができます。 'stss'ボックスのエントリ数を読んでください。メディアの長さを調べます。粗いKF距離値を秒単位で計算します。 '-skip_frame nokey'でffmpegを使用し、フィルタを選択すると、ほぼ離れたフレームを抽出できます。余分な画像を避けるために '-vframes 48 'を追加してください。 – Mulvya

答えて

0

一般的には、そういったlibは存在しません。しかし、あなたが扱っている特定のビデオに基づいて前提を立てるならば、結果を近似することができます。それは一般化されたフレームワークなので、FFmpegはあなたのためにそれを行うことはできません。

のは簡単な始めましょう:

  • あなたのビデオは何コンテナですか?
  • 彼らはどのコーデックを使用していますか?

なぜ私はこれを尋ねますか?一部のコンテナ(AVIなど)はインデックスにフレームタイプをマークするため、求めている情報を取得するために圧縮フレームで何もする必要はありません。他のコンテナ(Matroska/WebMなど)の場合、情報はコンテナの一部ではなく、派生情報が存在します。例えば、イントラオンリーではない圧縮ストリーム(例えば、H.264/VP9)の場合、seekHeadは、実際にはAVIファイル内のインデックスの範囲と同様のキーフレーム位置のリストである。しかし、これは仕様によって保証されているわけではなく、実際には実際には起こります。

OK、コンテナがあなたの目的に十分ではないとしましょう。自分でビデオデータを解析する必要があります。 H.264では、各フレームの最初のスライスのスライスヘッダーを解析してスライスタイプを取得できます。同一のスライスタイプを持つspecによって、すべてのスライス(同じフィールド)が保証されます。これはI、B、Pのいずれかです。それが私なら、イントラフレームです。 VP9の場合、ヘッダーには、探しているものを行うキーフレームとイントラネットというフィールドがあります。他の圧縮規格(MPEG-1/2/4、HEVC、VP8など)は同じですが、これを自分で実装する必要があります。それは複雑ではありませんが、これは非常に分かりにくいユースケースなので、これを行う一般的なフレームワークはありません。

+0

私たちはmp4コンテナを持っていますが、残念なことに、ビデオの間にバリエーションがたくさんあります。なぜなら、ユーザーが投稿しているからです。フォーマットを直接解析したくないからです。最終目標を説明するために質問を編集させてください。おそらく、他の解決策がポップアップするかもしれません。 – Thomas

+0

mp4にはキーフレームマーカーも付いているので、うまくいくはずです。 libavformat/mov.cの "sc-> keyframes []"およびそれを使ってインデックスにAVINDEX_KEYFRAMEを設定する方法を参照してください。インデックスはread_header()の間に生成されるので、独自のmp4パーサーを記述することなくffmpeg APIからアクセス可能で、しかもコーデックに依存しないようにしてください。 –

+0

これは非常に興味深いです。私はこれを今見ている。 – Thomas

関連する問題