Comment fondre un clip vidéo / audio avec une durée inconnue?


19

Je travaille sur un projet où j'utilise ffmpeg pour convertir par lots certains fichiers vidéo et ajouter des effets de fondu d'entrée / sortie en tête et en queue de chaque clip.

J'ai utilisé ce morceau de code pour ajouter l'effet de fondu / sortie sur des clips avec des durées connues:

ffmpeg -i clip.mp4 -filter:v 'fade=in:0:30,fade=out:9650:30' -c:v libx264 -crf 22 -preset veryfast -c:a copy fadeInOut.mp4

Mes deux questions sont:

  1. Comment puis-je fondre simultanément l'audio entrant / sortant?
  2. Ffmpeg peut-il déterminer automatiquement la durée du clip et se faire dire qu'il suffit de fondre les 30 dernières images?

Merci!

Réponses:


15

# 1 Pour estomper simultanément l'entrée / la sortie audio:

ffmpeg -i clip.mp4 -vf 'fade=in:0:30,fade=out:960:30'
                   -af 'afade=in:st=0:d=1,afade=out:st=32:d=1'
       -c:v libx264 -crf 22 -preset veryfast fadeInOut.mp4

Les temps de fondu sont en secondes .

# 2 Automatiquement? Non, mais voir la solution de contournement ci-dessous

Vous pouvez d'abord exécuter ffprobe pour obtenir la durée.

ffprobe -i clip.mp4 -show_entries stream=codec_type,duration -of compact=p=0:nk=1

Vous obtiendrez quelque chose comme ceci:

video|13.556000
audio|13.816000

Vous pouvez ensuite utiliser ce qui précède pour placer vos fondus. Ces temps sont en secondes.

solution de contournement

ffmpeg -i clip.mp4 -sseof -1 -copyts -i clip.mp4 -filter_complex
       "[1]fade=out:0:30[t];[0][t]overlay,fade=in:0:30[v];
        anullsrc,atrim=0:2[at];[0][at]acrossfade=d=1,afade=d=1[a]"
       -map "[v]" -map "[a]" -c:v libx264 -crf 22 -preset veryfast -shortest fadeInOut.mp4

FFmpeg a une sseofoption qui permet de rechercher une entrée depuis la fin. Nous pouvons l'utiliser pour atteindre notre objectif. Donc, nous alimentons l'entrée deux fois, la deuxième fois n'ingérant que la dernière seconde. Nous demandons à FFmpeg de conserver les horodatages, afin que ffmpeg préserve la position temporelle de cette portion de queue.

Nous appliquons un fondu à cette queue, puis superposons le résultat sur l'entrée complète. Puisqu'il s'agit du même fichier multimédia, le premier plan recouvre complètement l'arrière-plan et, depuis qu'il a copytsété appliqué, la superposition se produit sur le cadre identique correspondant dans l'entrée d'arrière-plan.

Pour l'audio, nous créons un audio factice vierge d'une durée de 2 secondes, puis appliquons un fondu audio de l'audio principal à cet audio factice. Étant donné que le 2e audio est vierge, il s'agit en fait d'un fondu sortant pour l'entrée principale. Le -shortestest ajouté pour laisser de côté certaines parties de l'audio factice après le fondu enchaîné.


Cela donne l'erreur "pas un tel filtre!" pour le filtre audio.
felwithe

1
Il y a 4 filtres audio utilisés. Laquelle? Exécutez votre commande avec -reportajouté et partagez le rapport.
Gyan

7

C'est un piratage terrible, mais cela pourrait fonctionner si tout ce que vous voulez faire est un fondu entrant / sortant audio mais ne savez pas exactement combien de temps le clip est:

ffmpeg -i input.mp4 -filter_complex "afade=d=0.5, areverse, afade=d=0.5, areverse" output.mp4

[edit 2019-07-24: Notez que cette solution n'est pas bonne pour les solutions de streaming car elle nécessite que la piste complète soit traitée avant que le premier octet puisse être streamé]

une autre option que je dois utiliser acrossfadeavec une piste silencieuse:

ffmpeg -i input.mp4 -filter_complex "aevalsrc=0:d=0.6 [a_silence]; [0:a:0] [a_silence] acrossfade=d=0.6" output.mp4

3
C'est en fait assez élégant :-)
bk138

cela fonctionne très bien. pourriez-vous expliquer comment cela fonctionne. essayer de donner un sens à la documentation ..
oberhamsi

1
@oberhamsi: Option 1: Le premier filtre ajoute un fondu au début de la piste. Il inverse ensuite l'audio et ajoute un autre fondu au début (qui est en fait la fin). Enfin, la piste est à nouveau inversée. L'option 2 crée une piste silencieuse de 0,6 seconde et la transforme en fondu pendant la même durée avec la piste d'origine. Tous les filtres et leur utilisation sont documentés ici: ffmpeg.org/ffmpeg-filters.html (même si je dois admettre que c'est un peu cryptique)
marekventur

3

La réponse à la question 2 est un OUI retentissant! Je cherchais la même fonctionnalité et j'ai fini par écrire un script bash qui demande la durée du fondu en secondes et calcule la trame initiale du fondu sortant:

#!/bin/bash

f="$*" # all args
p="${f##*/}" # file
fn="${p%.*}" # name only
e="${p##*.}" # extension

echo
echo $f
echo $p
echo $fn
echo $e
echo

read -e -p "Number of seconds of fade-out: " -i 1 sec # prompt for fade duration in seconds

r=$(ffprobe -show_streams "$f" 2> /dev/null | grep r_frame_rate | head -1 | cut -d \= -f 2) # frame rate
let "frames = $r * $sec" # duration of fade as number of frames
echo $r
echo $sec
echo $frames
lf=$(ffprobe -show_streams "$f" 2> /dev/null | grep nb_frames | head -1 | cut -d \= -f 2) # total number of frames
let "lf = $lf - $frames" # initial frame to start fade at

ffmpeg -loglevel quiet -i "$f" -vf fade=out:$lf:$frames -r $r -vcodec libx264 -preset slow -crf 12 -bf 2 -flags +cgop -pix_fmt yuv420p -acodec copy "$fn $sec sec fade-out.$e"
open "$fn $sec sec fade-out.$e"

Les fondus nécessitent un ré-encodage, donc l'utilisation d'une crfvaleur faible pour libx264donne un ré-encodage de haute qualité. Les commentaires devraient expliquer tout le reste.


La réponse à la question 2 est un OUI retentissant! -> c'est toujours non. Le Q is Can ffmpeg détermine automatiquement la durée ... mais vous avez écrit un script qui exécute plusieurs commandes ff * pour le faire. Utile pour les systèmes * nix, cependant.
Gyan

Je vois, alors vous insistez pour que VOTRE réponse soit TOUJOURS correcte? Si vous suivez mon script, vous verrez qu'il automatically figure out the durationutilise effectivement ffprobe, qui est installé avec ffmpeg. Qui a dit quoi que ce soit sur toute restriction du nombre de commandes ou *nix? Il semble que l'OP utilise une version d'UNIX. Non .exedans la ffmpegcommande. J'utilise moi-même OS Xce qui est construit UNIXmais qui ne l'est pas UNIX.
hmj6jmh

1
* Si vous suivez mon script, vous verrez qu'il comprend en effet automatiquement * -> votre script le fait, ffmpeg non.
Gyan

Mais ffprobefait partie intégrante de la ffmpegdistribution. Vous vous attaquez aux lentes pour sauver la face de l'OMI.
hmj6jmh

Je dois convenir que quelque chose qui est fait par un script bash n'est pas quelque chose qui est fait automatiquement par ffmpeg. Mais si cela fonctionne, c'est une façon de contourner ce problème. D'où le terme «contournement». Je ne peux pas dire si cela fonctionne parce que, comme la plupart des gens, je n'ai ni bash ni système Unix. +1 pour l'effort de toute façon.
ashleedawg
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.