Come sfumare in / out un video / clip audio con durata sconosciuta?


19

Sto lavorando a un progetto in cui sto usando ffmpeg per convertire in batch alcuni file video e aggiungendo effetti di dissolvenza in apertura / chiusura alla testa e alla coda di ogni clip.

Ho usato questo bit di codice per aggiungere l'effetto dissolvenza / chiusura sui clip con durata nota:

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

Le mie due domande sono:

  1. Come posso dissolvere simultaneamente l'audio in / out?
  2. Ffmpeg è in grado di capire automaticamente la durata della clip e può dirsi che è sufficiente sfumare gli ultimi 30 fotogrammi?

Grazie!

Risposte:


15

# 1 Per sfumare contemporaneamente l'audio in / out:

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

I tempi di dissolvenza sono in secondi .

# 2 automaticamente? No. Ma vedi la soluzione alternativa di seguito

Puoi prima eseguire ffprobe per ottenere la durata.

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

Otterrai qualcosa del genere:

video|13.556000
audio|13.816000

È quindi possibile utilizzare quanto sopra per posizionare le dissolvenze. Questi tempi sono in secondi.

Soluzione

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 ha sseofun'opzione che consente di cercare un input dalla fine. Possiamo usarlo per raggiungere il nostro obiettivo. Quindi alimentiamo l'input due volte, con la seconda volta ingerendo solo l'ultimo secondo. Diciamo a FFmpeg di preservare i timestamp, in modo che ffmpeg preservi la posizione temporale di questa porzione di coda.

Applichiamo una dissolvenza su questa coda e quindi sovrapponiamo il risultato sull'input completo. Dal momento che sono lo stesso file multimediale, il primo piano copre completamente lo sfondo e, poiché è copytsstato applicato, la sovrapposizione avviene sul frame identico corrispondente nell'input di sfondo.

Per l'audio, creiamo un audio fittizio vuoto della durata di 2 secondi, quindi applichiamo una dissolvenza incrociata audio dall'audio principale a questo audio fittizio. Poiché il secondo audio è vuoto, si tratta, in effetti, di una dissolvenza per l'ingresso principale. La -shortestsi aggiunge omettere porzioni di audio manichino dopo il verificarsi della dissolvenza incrociata.


Questo dà l'errore "nessun filtro del genere!" per il filtro audio.
felwithe il

1
Sono utilizzati 4 filtri audio. Quale? Esegui il comando con -reportaggiunto e condividi il rapporto.
Gyan,

7

È un hack terribile, ma potrebbe funzionare se tutto ciò che vuoi fare è dissolvenza in entrata / uscita audio ma non sai esattamente quanto dura la clip:

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

[modifica 24-07-2019: si noti che questa soluzione non è adatta per le soluzioni di streaming poiché richiede l'elaborazione della traccia completa prima di poter eseguire lo streaming del primo byte]

un'altra opzione che devo usare acrossfadecon una traccia silenziosa:

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
In realtà è piuttosto elegante :-)
bk138

funziona alla grande. potresti spiegare come funziona. cercando di dare un senso alla documentazione ..
oberhamsi,

1
@oberhamsi: Opzione 1: il primo filtro aggiunge una dissolvenza all'inizio della traccia. Quindi inverte l'audio e aggiunge un'altra dissolvenza all'inizio (che in realtà è la fine). Alla fine la traccia viene nuovamente invertita. L'opzione 2 crea una traccia silenziosa di 0,6 secondi e la dissolve incrociata per lo stesso periodo di tempo con la traccia originale. Tutti i filtri e il loro utilizzo sono documentati qui: ffmpeg.org/ffmpeg-filters.html (anche se devo ammettere che è un po 'criptico)
marekventur

3

La risposta alla domanda 2 è un clamoroso SÌ! Stavo cercando la stessa funzionalità e ho finito per scrivere uno script bash che richiede la durata della dissolvenza in secondi e calcola il frame iniziale per la dissolvenza:

#!/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"

Le dissolvenze richiedono una ricodifica, quindi l'utilizzo di un crfvalore basso per libx264fornisce una ricodifica di alta qualità. I commenti dovrebbero spiegare tutto il resto.


La risposta alla domanda 2 è un clamoroso SÌ! -> è ancora No. Il Q is Can ffmpeg calcola automaticamente la durata ... ma hai scritto uno script che esegue più comandi ff * per farlo. Utile per i sistemi * nix, comunque.
Gyan,

Capisco, quindi insisti sul fatto che la TUA risposta sia ANCORA corretta? Se segui il mio script, vedrai che effettivamente automatically figure out the durationutilizza ffprobe, che è installato con ffmpeg. Chi ha detto qualcosa riguardo a qualsiasi restrizione sul numero di comandi o *nix? Sembra che l'OP stia usando una versione di UNIX. No .exenel ffmpegcomando. Io stesso sto usando OS Xquale è costruito UNIXma non lo è UNIX.
hmj6jmh

1
* Se segui la mia sceneggiatura, vedrai che effettivamente capisce automaticamente * -> la tua sceneggiatura lo fa, ffmpeg no.
Gyan,

Ma ffprobeè parte integrante della ffmpegdistribuzione. Stai prendendo a segno per salvare il viso IMO.
hmj6jmh

Dovrei essere d'accordo sul fatto che qualcosa che viene fatto da uno script bash non è qualcosa che viene fatto automaticamente da ffmpeg. Ma se funziona, questo è un modo per aggirare quel problema. Da qui il termine "soluzione alternativa". Non posso dire se funziona perché io, come la maggior parte delle persone là fuori, non ho un sistema bash o unix. +1 per lo sforzo comunque.
ashleedawg,
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.