Wie blendet man einen Video-/Audioclip mit unbekannter Dauer ein/aus?

Ich arbeite an einem Projekt, bei dem ich ffmpeg verwende, um einige Videodateien stapelweise zu konvertieren und Ein-/Ausblendeffekte am Anfang und Ende jedes Clips hinzuzufügen.

Ich habe diesen Codeabschnitt verwendet, um den Fade/Out-Effekt auf Clips mit bekannter Dauer hinzuzufügen:

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

Meine zwei Fragen lauten:

  1. Wie kann ich den Ton gleichzeitig ein-/ausblenden?
  2. Kann ffmpeg automatisch die Dauer des Clips ermitteln und nur die letzten 30 Frames ausblenden?

Danke!

Antworten (3)

#1 Zum gleichzeitigen Ein-/Ausblenden des Tons:

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

Die Afade-Zeiten sind in Sekunden angegeben .

#2 Automatisch? Nein. Aber siehe Problemumgehung unten

Sie können zuerst ffprobe ausführen, um die Dauer zu erhalten.

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

Sie erhalten so etwas:

video|13.556000
audio|13.816000

Sie können dann das obige verwenden, um Ihre Überblendungen zu platzieren. Diese Zeiten sind in Sekunden angegeben.

Problemumgehung

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 hat eine sseofOption, mit der man eine Eingabe vom Ende suchen kann. Das können wir nutzen, um unser Ziel zu erreichen. Also füttern wir den Input zweimal, wobei das 2. Mal nur die letzte Sekunde aufgenommen wird. Wir weisen FFmpeg an, die Zeitstempel beizubehalten, sodass ffmpeg die zeitliche Position dieses Endabschnitts beibehält.

Wir wenden eine Ausblendung auf diesen Schwanz an und legen das Ergebnis dann auf die vollständige Eingabe. Da es sich um dieselbe Mediendatei handelt, deckt der Vordergrund den Hintergrund vollständig ab, und da copytser angewendet wurde, erfolgt die Überlagerung auf dem entsprechenden identischen Frame in der Hintergrundeingabe.

Für Audio erstellen wir ein leeres Dummy-Audio mit einer Dauer von 2 Sekunden und wenden dann eine Audioüberblendung vom Hauptaudio auf dieses Dummy-Audio an. Da das 2. Audio leer ist, ist dies tatsächlich eine Ausblendung für den Haupteingang. Der -shortestwird hinzugefügt, um Teile des Dummy-Audios wegzulassen, nachdem die Überblendung aufgetreten ist.

Dies gibt den Fehler "kein solcher Filter!" für den Audiofilter.
Es werden 4 Audiofilter verwendet. Welcher? Führen Sie Ihren Befehl mit -reporthinzugefügt aus und teilen Sie den Bericht.

Es ist ein schrecklicher Hack, aber das könnte funktionieren, wenn Sie nur Audio ein- und ausblenden möchten, aber nicht genau wissen, wie lang der Clip ist:

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

[bearbeiten 24.07.2019: Beachten Sie, dass diese Lösung nicht für Streaming-Lösungen geeignet ist, da der gesamte Track verarbeitet werden muss, bevor das erste Byte gestreamt werden kann]

Eine weitere Option, die ich verwende, ist die Verwendung acrossfademit einer stillen Spur:

ffmpeg -i input.mp4 -filter_complex "aevalsrc=0:d=0.6 [a_silence]; [0:a:0] [a_silence] acrossfade=d=0.6" output.mp4
Das ist eigentlich ziemlich elegant :-)
das funktioniert super. kannst du erklären wie das geht. versuche die Dokumentation zu verstehen..
@oberhamsi: Option 1: Der erste Filter fügt am Anfang des Tracks eine Überblendung hinzu. Es kehrt dann das Audio um und fügt am Anfang (das eigentlich das Ende ist) eine weitere Einblendung hinzu. Schließlich wird die Spur wieder umgekehrt. Option 2 erstellt eine stumme Spur von 0,6 Sekunden und überblendet sie für die gleiche Zeitdauer mit der Originalspur. Alle Filter und ihre Verwendung sind hier dokumentiert: ffmpeg.org/ffmpeg-filters.html (obwohl ich zustimmen muss, dass es etwas kryptisch ist)
Was wäre das Skript zum Zusammenführen von Video + Audio (Audio ist länger) und zum Einblenden und unserem für das Audio (sagen wir, das Einblenden endet nach 2 Sekunden, das Ausblenden beginnt bei 48 und endet bei 51)?

Die Antwort auf Frage 2 ist ein klares JA! Ich suchte nach der gleichen Funktionalität und schrieb schließlich ein Bash-Skript, das nach der Fade-Dauer in Sekunden fragt und den Anfangsframe für das Fade-Out berechnet:

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

Überblendungen erfordern eine Neucodierung, sodass die Verwendung eines niedrigen crfWerts für libx264eine Neucodierung in hoher Qualität ergibt. Die Kommentare sollten alles andere erklären.

Die Antwort auf Frage 2 ist ein klares JA! --> es ist immer noch Nein. Das Q ist Kann ffmpeg automatisch die Dauer herausfinden ... aber Sie haben ein Skript geschrieben, das mehrere ff * -Befehle ausführt, um dies zu tun. Nützlich für *nix-Systeme.
Ich verstehe, also bestehen Sie darauf, dass IHRE Antwort NOCH richtig ist? Wenn Sie meinem Skript folgen, werden Sie sehen, dass es tatsächlich , das automatically figure out the durationmit ffprobeinstalliert wird, verwendet ffmpeg. Wer hat etwas von einer Beschränkung der Anzahl der Befehle oder gesagt *nix? Es scheint, dass das OP eine Version von UNIX verwendet. Nein .exeim ffmpegBefehl. Ich selbst benutze OS Xdas, was aufgebaut ist, UNIXaber nicht UNIX.
* Wenn Sie meinem Skript folgen, werden Sie sehen, dass es tatsächlich automatisch herausfindet * --> Ihr Skript tut es, ffmpeg nicht.
Aber ffprobeist ein fester Bestandteil der ffmpegDistribution. Du pickst an Nissen herum, um das Gesicht zu wahren, IMO.
Ich muss zustimmen, dass etwas, das von einem Bash-Skript ausgeführt wird , nicht automatisch von ffmpeg ausgeführt wird. Aber wenn dies funktioniert, ist dies eine Möglichkeit, dieses Problem zu umgehen. Daher der Begriff „Workaround“. Ich kann nicht sagen, ob es funktioniert, weil ich, wie die meisten Leute da draußen, keine Bash oder ein Unix-System habe. +1 für die Mühe sowieso.