web-dev-qa-db-ja.com

FFMPEG複数出力パフォーマンス(単一インスタンスと複数インスタンス)

私は単一のファイル入力(.mp4)から複数のエンコードされたストリームを作成することに取り組んでいます。入力ストリームに音声がありません。エンコードされた各ストリームは、入力の異なる部分をトリミングして作成され、32コアシステムで同じビットレートでエンコードされます。

複数の出力を作成するためにffmpegwikiで説明されているように私が試しているシナリオは次のとおりです。 https://trac.ffmpeg.org/wiki/Creating%20multiple%20outputs

シナリオ1(単一のffmpegインスタンスを使用)

ffmpeg -i input.mp4 \

-filter:vクロップ= iw/2:ih/2:0:0 -c:v libx264 -b:v 5M out_1.mp4 \

-filter:v Crop = iw/2:ih/2:iw/2:0 -c:v libx264 -b:v 5M out_2.mp4 \

-filter:v Crop = iw/2:ih/2:0:ih/2 -c:v libx264 -b:v 5M out_3.mp4

この場合、ffmpegは入力を1回だけデコードし、すべてのクロップフィルターに供給されると想定しています。それが正しくない場合は私を訂正してください。

シナリオ2(複数のffmpegインスタンスを使用しているため、3つの別々のプロセスを使用しています)

ffmpeg -i input.mp4 -filter:vクロップ= iw/2:ih/2:0:0 -c:v libx264 -b:v 5M out_1.mp4

ffmpeg -i input.mp4 -filter:v Crop = iw/2:ih/2:iw/2:0 -c:v libx264 -b:v 5M out_2.mp4

ffmpeg -i input.mp4 -filter:v Crop = iw/2:ih/2:0:ih/2 -c:v libx264 -b:v 5M out_3.mp4

私の場合、実際には、入力ビデオのさまざまなセクションをトリミングして、さらに多くのストリームをエンコードする必要があります。この例を簡単にするために、ここでは3つを示しています。

ここで、fpsパフォーマンスの観点から、シナリオ2のパフォーマンスが向上していることがわかります。また、CPUを最大限に使用します(95%を超えるCPU使用率)。シナリオ1のfpsは低く、CPU使用率ははるかに低くなっています(65%近く)。また、この場合、エンコードするストリームの数を増やしても、CPU使用率は直線的に増加しません。 1つのストリームから2つのストリームに移行すると、ほぼ1.5倍になります。しかし、その後は増分が非常に低くなります(おそらく10%で、ストリーム数が増えるとさらに少なくなります)。

だから私の質問は:複数回のデコードを回避し、入力が4Kにもなる可能性があるため、単一インスタンスのffmpegを使用したいまたはさらに大きい。 CPU使用率(> 90%)を向上させ、FPSを向上させるにはどうすればよいですか?また、なぜCPU使用率がエンコードされるストリームの数に比例して増加しないのですか?単一インスタンスのffmpegが複数のインスタンスほどうまく機能しないのはなぜですか?単一のffmpegインスタンスでは、すべてのエンコードが実際に並行して実行されているわけではないように思われます。

編集:これは、物事がそれほど明確でない場合に問題を再現して説明できる最も簡単な方法です。これは問題を理解するための実験目的のためだけであることを覚えておいてください。

シングルインスタンス:ffmpeg -y -i input.mp4 -c:v libx264 -x264opts thread = 1 -b:v 1M -f null --- c:v libx264 -x264opts thread = 1 -b:v 1M -f null --- c:v libx264-x264optsスレッド= 1 -b:v 1M -f null-

複数のインスタンス:ffmpeg -y -i input.mp4 -c:v libx264 -x264opts thread = 1 -b:v 1M -f null- | ffmpeg -y -i input.mp4 -c:v libx264 -x264opts thread = 1 -b:v 1M -f null- | ffmpeg -y -i input.mp4 -c:v libx264 -x264opts threads = 1 -b:v 1M -f null-

X264をシングルスレッドに制限していることに注意してください。単一インスタンスの場合、ffmpegがx264エンコードごとに1つのエンコードスレッドを生成し、それらを並列に実行することを期待します。しかし、完全に使用されているCPUコアは1つだけであるため、一度に1つのエンコードセッションしか実行されていないと思います。一方、複数のインスタンスの場合、3つのCPUコアが完全に利用されていることがわかります。これは、3つのエンコードがすべて並行して実行されていることを意味します。

私は本当に一部の専門家が参加してこれを手伝ってくれることを願っています。

5
shalin

それほど明白ではない問題は、入力/出力またはフィルターによっては、ffmpegが内部でピクセル形式の変換を行う必要がある場合があり、場合によっては、ストリームごとに個別に実行すると、並列出力を使用するときにこれがボトルネックになることがあります。

アイデアは、可能であれば、次のようにピクセル形式の変換を1回実行することです。

-filter_complex '[0:v]format=yuv420p, split=3[s1][s2][s3]' \
-map '[s1]' ... \
-map '[s2]' ... \
-map '[s3]' ... \

すべての出力に適用される同じフィルターも、1回だけ使用する必要があります。一部のフィルターでは、特定のピクセル形式が必要になる場合があります。

その他の原因については、 wiki の下部にある小さなメモを参照してください:

並列エンコーディング

同じFFmpegプロセスで複数回出力および再エンコードすると、通常、リスト内の「最も遅いエンコーダー」まで速度が低下します。一部のエンコーダー(libx264など)は、「スレッド化されたバックグラウンドで」エンコードを実行するため、並列エンコードが効果的に可能になりますが、オーディオエンコードはシリアルであり、ボトルネックになる可能性があります。シリアルであるエンコードがある場合は、 、それはFFmpegによって「実際のシリアル」として扱われるため、FFmpegはすべての利用可能なコアを使用しない場合があります。

1
aergistal

私はあなたの問題を再現することはできません。セットアップ:

Powershellの私のコード:

# Measure time of FFMPEG process
$time = Measure-Command{
    ffmpeg -ss 00:01:00.000 -i .\ToS-4k-1920.mov `
    -to 00:00:25.000 -c:v libx264 -b:v 5M -y .\out_1.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_2.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:0:ih/2" -c:v libx264 -b:v 5M -y .\out_3.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_4.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_5.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_6.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_7.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_8.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_9.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_10.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_11.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_12.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:0:0" -c:v libx264 -b:v 5M -y .\out_13.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_14.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:0:ih/2" -c:v libx264 -b:v 5M -y .\out_15.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_16.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_17.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_18.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_19.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_20.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_21.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_22.mp4 `
    -to 00:00:25.000 -c:v libx264 -b:v 5M -y .\out_23.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_24.mp4
}

Write-Host "Time spent: $time"

結果:

  • $time:00:05:52.7747482
  • ffmpegの速度:speed=0.0711x

どちらの値も私には理にかなっているようです。

24のパラレル出力でも問題はありません。CPUはプロセス全体で約95%を超え、SSDはほとんど使用されず(<5%)、約75%のRAM使用されます(アイドル時、最大30%が使用されます)(タスクマネージャーを介して手動でチェックされた値)

したがって、ここにはいくつかの可能性があります。

  • 古いバージョンのFFmpegを使用しています
  • 他の何か(HDD、RAM)がボトルネックになっています
  • ファイルに問題があります-ありそうもないと思います
  • CPUに何か問題があります-ffmpegの複数のインスタンスを使用するときにフルキャパシティーで動作すると述べているのと同じように、ありそうもないです)
  • 別の-threads-コード内の値と、それが違いを生むかどうかを確認します。
0
flolilo

私はこれが低い/デフォルトのビデオバッファサイズであることに気づきました。

Bufsizeを50Mまたはファイルサイズの半分のいずれか小さい方に増やしてみてください。

また、bufsizeパラメーターはkの単位で示されるため、-bufsize50000kのようになります。

0
Akumaburn