Qual è un modo efficace per eseguire una dissolvenza incrociata video con FFmpeg?


11

Fare una dissolvenza incrociata tra due contenuti video è in realtà abbastanza complicato in FFmpeg. Non esiste un filtro "dissolvenza incrociata" come nel caso dell'audio.

Qual è un modo efficiente per farlo?


Bella domanda con risposta autonoma!
Jake Gould

Questa risposta ha bisogno di ottenere MOLTO più voti ... Mark, ti ​​amerei per sempre se aggiungessi anche dissolvenza incrociata per l'audio ...
Merc

Non appena avrò capito come, lo aggiungerò. Penso che l'audio della dissolvenza incrociata sia istantaneo, anche se, credo che ci sia un semplice filtro per questo.
Mark Gerolimatos,

Ho semplicemente aggiunto [0:a][1:a] acrossfade=d=1 [audio]al filtro e poi -map "[audio]" al comando e ha funzionato. Se ti piace, fai un test e aggiorna la risposta!
Merc

Risposte:


17

TL; versione DR:

Questo esempio esegue solo video, supponendo che entrambi i videoclip abbiano la stessa risoluzione, frequenza di fotogrammi, ecc. Ciò creerà una dissolvenza di 1 secondo tra la clip di dissolvenza e la clip di dissolvenza. Supponiamo che la dissolvenza in apertura sia lunga 10 secondi. Nota che questo è formattato per chiarezza: è davvero una riga di codice.

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>

Versione completa:

Ecco una spiegazione di cosa si trattasse:

Specifica di input ... ovvia

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

Creazione di un filter_complex: presupponendo che tu abbia già capito i complessi di filtri:

-filter_complex

Per prima cosa spezziamo i due flussi in due pezzi ciascuno usando il filtro trim : il contenuto e la sezione di dissolvenza incrociata. La dissolvenza viene suddivisa in sezione contenuto e dissolvenza, mentre la dissolvenza in entrata viene tagliata nella sezione e contenuto di dissolvenza. Totale di quattro sezioni.

Si noti che, a rigor di termini, non è necessario interrompere le sezioni di dissolvenza incrociata: potremmo semplicemente specificare la dissolvenza in uscita e la dissolvenza in tempo per i due videoclip. Tuttavia, facendo questo, noi:

  • Segui la metodologia generalmente utilizzata dagli editor video della GUI
  • Evita la frustrante complessità overlaydell'uso del filtro
  • Garantire che la soluzione sia il più generale possibile (ovvero codice riutilizzabile)
  • Consentici di pre-elaborare e post-elaborare la sezione di dissolvenza incrociata, se necessario (non eseguita qui)

Ognuna di queste quattro sezioni specifica: ora di inizio (secondi), ora di fine (secondi) e il setpts=PTS-STARTPTSfiltro misterioso , che essenzialmente fa iniziare ogni sottoclip video a 0 secondi. Ciò sarà di vitale importanza nel ricomposirli.

Si noti che gli s=0specificatori sono ridondanti e il setptsfiltro per s=0quelli è ANCHE ridondante. Tuttavia, entrambi vengono specificati in modo ridondante per consentire il cambio dell'ora di inizio da 0, senza interrompere il complesso di filtri. Inoltre, la seconda clip di contenuto viene eseguita fino alla fine, quindi la e=parte (end =) non viene specificata.

    [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];

Successivamente, specifichiamo la dissolvenza in entrata e in uscita: per prima cosa aggiungiamo un canale alfa (trasparenza) ad entrambe le sezioni di dissolvenza specificando un formato pixel diyuva420p . Puoi effettivamente utilizzare qualsiasi formato che fornisca un canale alfa.

Successivamente in questo sottocomponente del filtro ne specifichiamo uno da sfumare e uno da sfumare. Il alpha=1mezzo in cui il video stesso non si oscurerà, solo la quantità di trasparenza "sbiadirà". stsignifica inizio, dsignifica durata.

    [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];

Che cos'è ?: Il fifofiltro assicura che ci sia spazio buffer disponibile nel complesso di filtri. Sorprendentemente, questo NON è il valore predefinito. In caso contrario, la dissolvenza incrociata potrebbe non riuscire se l'output dello stage sopra supera il filtro di overlay sottostante. Sì, so cosa stai pensando in questo momento. È davvero un bug di FFMPEG .

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

Ora, sovrapponi le due sezioni di dissolvenza: assicurandoti che le due sezioni di dissolvenza incrociata abbiano le stesse dimensioni, non dobbiamo preoccuparci delle opzioni piuttosto cattive che il filtro di sovrapposizione prende (e quindi le ignoriamo qui):

    [fadeoutfifo][fadeinfifo]overlay[crossfade];

Infine, allineiamo i nostri tre segmenti usando il filtro concat .

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

E ora, mappa il pad di output come sorgente video.

NON DIMENTICARE di impostare il formato pixel SU QUELLO CHE USATE NORMALMENTE (in genere yuv420p), poiché la sezione di dissolvenza incrociata lo avrà impostato yuv420sul canale di uscita! (dato che non l'abbiamo specificato, è possibile utilizzare gli argomenti di overlay) Naturalmente, se VUOI yuv420, allora stai bene :-)

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

È quindi possibile ricombinare l'audio in un secondo momento (al di fuori dell'ambito di queste domande e risposte)


1
Nell'ultima versione di ffmpeg, deve essere trim=start=0:end=9(piuttosto che trim=st=0:e=9,...
Merc

Ma seriamente, questa sarà la migliore risposta su FFMPEG che abbia mai visto, e la più chiara spiegazione di ffmpeg di sempre.
Merc

Amico, mi verrà in mente :-) Grazie per gli oggetti di scena !!!!
Mark Gerolimatos,

Nessun problema. Aggiorna la risposta soprattutto con = trim = start = 0 poiché in questo momento non funziona con l'ultimo ffmpeg
Merc

L'ultima versione di ffmpeg mi dà questo errore: Filter setpts has an unconnected outputper lo script. Ho già modificato i parametri di taglio per iniziare e finire.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.