Quel est un moyen efficace de réaliser un fondu enchaîné vidéo avec FFmpeg?

11

Faire un fondu enchaîné entre deux morceaux de contenu vidéo est en fait assez compliqué dans FFmpeg. Il n'y a pas de filtre «fondu enchaîné» comme il en existe pour l'audio.

Quelle est la manière efficace de procéder?

Mark Gerolimatos
la source
Belle question auto-répondue!
JakeGould
Cette réponse doit obtenir BEAUCOUP plus de votes positifs ... Mark, je t'aimerais tellement pour toujours si tu ajoutais le fondu enchaîné pour l'audio aussi ...
Merc
Dès que je saurai comment, je l'ajouterai. Je pense que le fondu enchaîné audio est instantané, mais je pense qu'il existe un filtre simple pour cela.
Mark Gerolimatos
J'ai simplement ajouté [0:a][1:a] acrossfade=d=1 [audio]au filtre, puis -map "[audio]" à la commande et cela a fonctionné. Si vous le souhaitez, faites un test et mettez à jour la réponse!
Merc
Duplication possible du fondu enchaîné entre 2 vidéos en utilisant ffmpeg
r_alex_hall

Réponses:

17

Version TL; DR:

Cet exemple effectue uniquement de la vidéo, en supposant que les deux clips vidéo ont la même résolution, la fréquence d'images, etc. Cela créera un fondu d'une seconde entre fadeoutclip et fadeinclip. Supposons que le fadeoutclip dure 10 secondes. Notez que cela est formaté pour plus de clarté: c'est vraiment une ligne de code.

ffmpeg -i fadeoutclip.mp4 -i fadeinclip.mp4 -an \
-filter_complex "\
    [0:v]trim=start=0:end=9,setpts=PTS-STARTPTS[firstclip]; \
    [1:v]trim=start=1,setpts=PTS-STARTPTS[secondclip]; \
    [0:v]trim=start=9:end=10,setpts=PTS-STARTPTS[fadeoutsrc]; \
    [1:v]trim=start=0:end=1,setpts=PTS-STARTPTS[fadeinsrc]; \
    [fadeinsrc]format=pix_fmts=yuva420p, \
                fade=t=in:st=0:d=1:alpha=1[fadein]; \
    [fadeoutsrc]format=pix_fmts=yuva420p, \
                fade=t=out:st=0:d=1:alpha=1[fadeout]; \
    [fadein]fifo[fadeinfifo]; \
    [fadeout]fifo[fadeoutfifo]; \
    [fadeoutfifo][fadeinfifo]overlay[crossfade]; \
    [firstclip][crossfade][secondclip]concat=n=3[output] \
    " \
-map "[output]" <add in encoding part here>

Version complète:

Voici une explication de ce dont il s'agissait:

Spécification d'entrée ... évidente

ffmpeg -i fadeoutclip.mp4 -i fadeinclip.mp4 -an

Créer un filter_complex: en supposant que vous comprenez déjà les complexes de filtres:

-filter_complex

Nous séparons d'abord les deux flux en deux morceaux chacun en utilisant le filtre de découpage : le contenu et la section de fondu enchaîné. Le fondu sortant est divisé en contenu et section de fondu, tandis que le fondu entrant est coupé en section et contenu de fondu. Total de quatre sections.

Notez que à proprement parler, nous ne devons briser les sections de fondu rayez: Nous pourrions simplement spécifier le fondu et fondu dans les temps pour les deux clips vidéo. Cependant, ce faisant, nous:

  • Suivez la méthodologie généralement utilisée par les éditeurs vidéo GUI
  • Évitez la complexité frustrante de l' overlayutilisation du filtre
  • Assurez-vous que la solution est aussi générale que possible (c.-à-d. Code réutilisable)
  • Permettez-nous de pré-traiter et post-traiter la section de fondu enchaîné si nécessaire (pas fait ici)

Chacune de ces quatre sections spécifie: l' heure de début (secondes), l'heure de fin (secondes) et le mystérieux setpts=PTS-STARTPTSfiltre , qui fait essentiellement démarrer chaque sous-clip vidéo à 0 seconde. Cela sera vital lors de leur recomposition.

Notez que les s=0spécificateurs sont redondants et que le setptsfiltre pour s=0ceux-ci est également redondant. Cependant, les deux sont spécifiés de manière redondante pour permettre le changement d'heure de début de 0, sans casser le complexe du filtre. En outre, le deuxième clip de contenu s'exécute jusqu'à la fin, de sorte que la e=partie (end =) n'est pas spécifiée.

    [0:v]trim=s=0:e=9,setpts=PTS-STARTPTS[firstclip];
    [1:v]trim=s=1,setpts=PTS-STARTPTS[secondclip];
    [0:v]trim=s=9:e=10,setpts=PTS-STARTPTS[fadeoutsrc];
    [1:v]trim=s=0:e=1,setpts=PTS-STARTPTS[fadeinsrc];

Ensuite, nous spécifions le fondu entrant et sortant: Nous ajoutons d'abord un canal alpha (transparence) aux deux sections de fondu en spécifiant un format de pixel deyuva420p . Vous pouvez réellement utiliser n'importe quel format qui fournit un canal alpha.

Suivant dans ce filtre , nous précisons un sous -complexe à disparaître, et un à fondu. Les alpha=1moyens que la vidéo elle - même ne sera pas assombrie, seul le montant de la transparence sera « fade ». stsignifie début, ddurée.

    [fadeinsrc]format=pix_fmts=yuva420p,      
                fade=t=in:st=0:d=1:alpha=1[fadein];
    [fadeoutsrc]format=pix_fmts=yuva420p,
                fade=t=out:st=0:d=1:alpha=1[fadeout];

Qu'est-ce que c'est?: Le fifofiltre garantit qu'il y a de l'espace tampon disponible dans le complexe de filtres. Étonnamment, ce n'est PAS la valeur par défaut. Si vous ne le faites pas, le fondu enchaîné pourrait échouer si la sortie de l'étage ci-dessus dépasse le filtre de superposition ci-dessous. Ouais, je sais ce que tu penses en ce moment. Il s'agit en effet d'un bug FFMPEG .

    [fadein]fifo[fadeinfifo];
    [fadeout]fifo[fadeoutfifo];

Maintenant, superposez les deux sections de fondu: en vous assurant que les deux sections de fondu enchaîné sont de la même taille, nous n'avons pas à nous soucier des options plutôt désagréables prises par le filtre de superposition (et nous les ignorons donc ici):

    [fadeoutfifo][fadeinfifo]overlay[crossfade];

Enfin, nous alignons nos trois segments à l'aide du filtre concat .

    [firstclip][crossfade][secondclip]concat=n=3[output]

Et maintenant, mappez le pavé de sortie comme source vidéo.

N'OUBLIEZ PAS de définir le format de pixel À CE QUE VOUS UTILISEZ NORMALEMENT (généralement yuv420p), car la section de fondu enchaîné l'aura réglé yuv420sur le canal de sortie! (comme nous ne l'avons pas spécifié, vous pouvez utiliser les arguments de superposition) Bien sûr, si vous le souhaitez yuv420, alors tout va bien :-)

-map "[output]" <add your normal encoding part here>

Vous pouvez ensuite recombiner l'audio ultérieurement (en dehors de la portée de cette Q&R)

Mark Gerolimatos
la source
1
Dans la dernière ffmpeg, elle doit l'être trim=start=0:end=9(plutôt que trim=st=0:e=9,..
Merc
Mais sérieusement, cela devra être la meilleure réponse sur FFMPEG que j'aie jamais vue, et l'explication la plus claire de ffmpeg jamais.
Merc
Mec, ça va me monter à la tête :-) Merci pour les accessoires !!!!
Mark Gerolimatos
Pas de soucis. Veuillez mettre à jour la réponse en particulier avec = trim = start = 0 car pour l'instant cela ne fonctionne pas avec la dernière ffmpeg
Merc
La dernière version de ffmpeg me donne cette erreur: Filter setpts has an unconnected outputpour le script. J'ai déjà changé les paramètres de trim pour commencer et terminer.