web-dev-qa-db-fra.com

FFMPEG Performance multiple de plusieurs sorties (instance unique VS Plusieurs instances)

Je travaille sur la création de multiples flux codés à partir de l'entrée de fichier unique (.mp4). Le flux d'entrée n'a pas d'audio. Chaque courant codé est créé en recadrant une partie différente de l'entrée puis codée avec le même débit binaire sur 32 système de noyau.

Voici les scénarios que j'essaie comme expliqué dans FFMPEG Wiki pour créer plusieurs sorties. https://trac.fmpeg.org/wiki/creating%20MultiPle%20OutPutts

Scénario1 (à l'aide d'une instance FFMPEG unique)

fFMPEG -I INPUT.MP4 \

-filter: v culture = IW/2: IH/2: 0: 0 -c: v libx264 -b: v 5m out_1.mp4 \

-Filtre: v culture = IW/2: IH/2: IW/2: 0 -C: v libx264 -b: v 5m out_2.mp4 \

-Filter: v culture = IW/2: IH/2: 0: IH/2 -C: V libx264 -b: v 5m out_3.mp4

Dans ce cas, je suppose que FFMPEG décodera uniquement l'entrée une seule fois et sera fournie à tous les filtres de culture. S'il vous plaît corrigez-moi si cela ne va pas.

Scénario2 (en utilisant plusieurs instances FFMPEG et donc trois processus distincts)

fFMPEG -I INPUT.MP4 -FILTER: V CROPCH = IW/2: IH/2: 0: 0 -C: V LIBX264 -B: V 5M OUT_1.MP4

fFMPEG -IO INPUT.MP4 -FILTER: V CROPCH = IW/2: IH/2: IW/2: 0 -C: V LIBX264 -B: V 5M OUT_2.MP4

fFMPEG -I INPUT.MP4 -FILTER: V CROPCH = IH/2: IH/2: 0: IH/2 -C: V LIBX264 -B: V 5M OUT_3.mp4

Dans mon cas, j'ai en fait besoin d'encoder encore plus de numéros de flux en recadrant différentes sections de la vidéo d'entrée. Je montre trois ici juste pour rendre cet exemple plus simple.

Maintenant, en termes de performances des FPS, je vois que le scénario 2 fonctionne mieux. Il utilise également la CPU à son maximum (plus de 95% d'utilisation de la CPU). Scénario 1 a moins d'utilité FPS et CPU est une voie inférieure (près de 65%). De même, dans ce cas, lorsque j'augmente le nombre de flux à coder, l'utilisation de la CPU n'augmente pas linéairement. Cela devient presque 1,5 fois quand je vais d'un flux à deux. Mais après cela, les incréments sont très bas (probablement 10% et encore moins avec plus de flux).

Donc, ma question est la suivante: Je veux utiliser une instance unique FFMPEG car elle évite de décoder plusieurs fois et que l'entrée que j'ai peut-être aussi grande que 4K que 4K ou même plus grand. Que dois-je faire pour obtenir une meilleure utilisation du processeur (> 90%) et donc mieux FPS, espérons-le? En outre, pourquoi l'utilisation du processeur n'augmente-t-elle pas linéairement avec le nombre de flux à coder? Pourquoi n'accordera-t-elle que FFMPEG fonctionne aussi bien que plusieurs instances? Il me semble que avec une seule instance FFMPEG, tous les encodes ne fonctionnent pas vraiment en parallèle.

Edit: Voici le moyen le plus simple possible que je puisse reproduire et expliquer la question au cas où les choses ne sont pas si claires. Gardez dans mon esprit que cela est juste à des fins expérimentales pour comprendre le problème.

Instance unique: FFMPEG -Y -I INPUT.MP4 -C: V LIBX264 -X264OPTS Filfs = 1 -B: V 1M -F NULL - -C: V LIBX264 -X264OPTS Threads = 1 -B: v 1m -f null - - C: V LibX264 -X264OPTS threads = 1 -b: v 1m -f null -

Plusieurs instances: FFMPEG -Y -I INPUT.MP4 -C: V LIBX264 -X264OPTS Filfs = 1 -B: V 1M -F NULL - | FFMPEG -Y -I INPUT.MP4 -C: V LIBX264 -X264OPTS Threads = 1 -B: V 1M -F NULL - | FFMPEG -Y -I INPUT.MP4 -C: V LIBX264 -X264OPTS Threads = 1 -b: v 1m -f null -

Notez que je limite X264 sur un seul thread. En cas d'instance unique, je m'attendrais à ce que FFMPEG génère 1 fil de codage pour chaque codement X264 et les exécuter en parallèle. Mais je vois que un seul noyau de la CPU est entièrement utilisé, ce qui me fait croire qu'une seule session d'encode fonctionne à la fois. D'autre part, avec le cas de nombreuses instances, je vois que trois cœurs de processeur sont entièrement utilisés, ce que je suppose que tous les trois encodes fonctionnent en parallèle.

J'espère vraiment que certains experts peuvent sauter et aider avec cela.

5
shalin

Un problème moins évident est que, en fonction de votre entrée/sortie ou filtres ffmpeg _ peut avoir besoin de faire une conversion de format de pixel en interne et, dans certains cas, cela devient un goulot d'étranglement lors de l'utilisation de sorties parallèles si elle est effectuée séparément.

L'idée est de faire la conversion au format de pixel une fois si possible, comme:

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

Les mêmes filtres appliqués à toutes les sorties ne doivent également être utilisés qu'une seule fois. Certains filtres peuvent avoir besoin d'un format de pixel spécifique.

Pour d'autres causes, voir la petite note au bas du wiki :

codage parallèle

La sortie et la codage de plusieurs fois dans le même processus FFMPEG ralentissent généralement jusqu'au "codeur le plus lent" de votre liste. Certains codeurs (comme LibX264) effectuent leur codage "fileté et en arrière-plan" afin qu'ils permettront efficacement des codages parallèles, mais le codage audio peut être en série et devenir le goulot d'étranglement, etc. Il semble que si vous avez des codages qui sont en série. , il sera traité comme "réel série" de FFMPEG et votre FFMPEG peut donc ne pas utiliser tous les cœurs disponibles.

1
aergistal

Je ne peux pas reproduire votre problème. Installer:

Mon code à 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"

Résultat:

  • $time: 00: 05: 52.7747482
  • vitesse de FFMPEG: speed=0.0711x

Les deux valeurs me semblent raisonnables.

Même 24 sorties parallèles ne montrent aucun problème ici - la CPU reste environ 95% pour l'ensemble du processus, presque aucune utilisation du SSD (<5%) et ~ 75% de RAM sont utilisés (sur ~ 30% sont utilisés). (Vérifications vérifiées manuellement via Task-Manager)

Donc, il y a quelques possibilités ici:

  • Vous utilisez une ancienne version de ffmpeg
  • Autre chose (HDD, RAM) est un goulot d'étranglement
  • Quelque chose ne va pas avec votre fichier - improbable, je pense
  • Quelque chose ne va pas avec votre CPU - tout comme improbable, comme vous l'indiquez, cela fonctionne à pleine capacité lorsque vous utilisez plusieurs instances de FFMPEG)
  • essayez différent -threads- Valeurs dans votre code et voyez si cela fait une différence.
0
flolilo