53

大きなライブWMVビデオフィードをすべて同じサイズの小さなチャンクに分割する必要があります。これを実行して正常に機能するスクリプトを作成しました。ただし、ビデオチャンクはキーフレームで始まらないため、ほとんどのビデオチャンクを再生すると、元のビデオのキーフレームが最終的に表示されるまで画像は表示されません。到達しました。

ffmpegに出力ビデオをキーフレームで開始するように指示する方法はありませんか?

現在のコマンドラインは次のとおりです。

ffmpeg.exe -i "C:\test.wmv" -ss 00:00:00 -t 00:00:05 -acodec copy -vcodec copy -async 1 -y  "0000.wmv"
ffmpeg.exe -i "C:\test.wmv" -ss 00:00:05 -t 00:00:05 -acodec copy -vcodec copy -async 1 -y  "0001.wmv"

等々...

4

6 に答える 6

50

FFMPEGの最新のビルドには、私が必要だと思うことを正確に実行する新しいオプション「セグメント」が含まれています。

ffmpeg -i INPUT.mp4 -acodec copy -f segment -vcodec copy -reset_timestamps 1 -map 0 OUTPUT%d.mp4

これにより、キーフレームに基づいてセグメントに分割される一連の番号付き出力ファイルが生成されます。私自身のテストでは、数分以上使用したことはなく、MP4形式でしか使用していませんが、うまく機能しました。

于 2014-01-30T06:25:07.640 に答える
42

公式のFFMPEGDocsで述べられているように、生成されたビデオの先頭を、指定されたタイムスタンプの 前に見つかった最も近いキーフレームに設定する(または理解している)ため、 -ss timestart before を指定する方がうまくいきました。-i input_file.ext

例を次のように変更します。

ffmpeg.exe -ss 00:00:00 -i "C:\test.wmv" -t 00:00:05 -acodec copy -vcodec copy -async 1 -y  "0000.wmv"

.flv私はこのメソッドを.mp4ファイルで動作させてテストしました。

于 2015-10-17T15:36:44.757 に答える
22

これが私が仕事に取り掛かることができる解決策です:

av501とd33pikaで提案されているように、キーフレームがどこにあるかを見つけるためにffprobeを使用しました。ffprobeは非常に冗長であり、すべてのキーフレームを出力するのに数秒または数分かかる場合があり、長いビデオから必要なフレームの範囲をスコープする方法がないため、5つのステップに進みます。

  1. 元のファイルから、目的のチャンクサイズの約2倍のビデオチャンクをエクスポートします。

    ffmpeg -i source.wmv -ss 00:00:00 -t 00:00:06 -acodec copy -vcodec copy -async 1 -y  0001.wmv
    
  2. ffprobeを使用して、キーフレームがどこにあるかを見つけます。目的のチャンクサイズの後に最も近いキーフレームを選択します。

    ffprobe -show_frames -select_streams v -print_format json=c=1 0001.wmv
    
  3. ffprobeの出力から、pkt_dts_timeそのキーフレームの直前のフレームを取得します。

  4. ステップ1のエクスポートされたチャンクでffmpegを実行し、同じ入力ファイルと出力ファイルを指定-ss 00:00:00し、-t[ステップ3で見つかった値]を指定します。

    ffmpeg -i 0001.wmv -ss 00:00:00 -t 00:00:03.1350000 -acodec copy -vcodec copy -async 1 -y 0001.wmv
    
  5. -ss[反復でステップ3で見つかった値の累積合計]を使用して、ステップ1から再開します。

このように進めることで、キーフレームでビデオを分割するための効率的で堅牢な方法を得ることができました。

于 2012-12-23T18:17:51.200 に答える
14

の新しいビルドを使用すると、とセグメントffmpegを使用してこれを実現できます。ffprobeffmpegmuxer

  1. とawkを使用ffprobeして、目的のチャンク長にできるだけ近いキーフレームを識別します。
ffprobe -show_frames -select_streams v:0 \
        -print_format csv [SOURCE_VIDEO] 2>&1 |
grep -n frame,video,1 |
awk 'BEGIN { FS="," } { print $1 " " $5 }' |
sed 's/:frame//g' |
awk 'BEGIN { previous=0; frameIdx=0; size=0; } 
{
  split($2,time,".");
  current=time[1];
  if (current-previous >= [DURATION_IN_SECONDS]){
    a[frameIdx]=$1; frameIdx++; size++; previous=current;
  }
}
END {
  str=a[0];
  for(i=1;i<size;i++) { str = str "," a[i]; } print str;
}'

どこ

  • [SOURCE_VIDEO] =セグメント化するビデオへのパス
  • [DURATION_IN_SECONDS] =必要なセグメントの長さ(秒単位)

出力は、キーフレームのコンマ区切りの文字列です。

  1. 上記のキーフレーム出力をへの入力として使用しffmpegます。
ffmpeg -i [SOURCE_VIDEO] -codec copy -map 0 -f segment \
       -segment_frames [OUTPUT_OF_STEP_1] [SEGMENT_PREFIX] \
       _%03d.[SOURCE_VIDEO_EXTENSION]

どこ

  • [SOURCE_VIDEO] =セグメント化するビデオへのパス
  • [OUTPUT_OF_STEP_1] =キーフレームのコンマ区切り文字列
  • [SEGMENT_PREFIX] =セグメント出力の名前
  • [SOURCE_VIDEO_EXTENSION] =ソースビデオの拡張(例:mp4、mkv)
于 2013-07-16T22:58:31.587 に答える
6

ffprobe -show_frames -pretty <stream>キーフレームを識別するために使用します。

于 2012-12-23T14:11:51.423 に答える
3

スクリプトを作成する意思があり、特定の間隔でIフレームを作成する場合、その1つの方法は次のとおりです。

  1. ffprobeを実行し、出力からIフレームの位置を収集します

    ffprobe -show_streams

  2. 同じスクリプトを使用して一連の-ss-tコマンドを実行し、必要なチャンクを取得します。

次に、スクリプトに最小フレーム数を決定させることができます[たとえば、互いに10フレーム以内に2つのI画像がある場合、そこでチャンク化する必要はありません]。

もう1つの方法は、gstreamerのmultisfilesinkを使用して、モードをキーフレームに設定することです[ただし、すべてのキーフレームでチャンク化されるため、理想的ではない場合があります]

于 2012-12-23T03:36:11.217 に答える