¿Cómo desvanecer / desvanecer un video / clip de audio con duración desconocida?

19

Estoy trabajando en un proyecto en el que estoy usando ffmpeg para convertir por lotes algunos archivos de video y agrego efectos de fundido de entrada / salida en la cabeza y la cola de cada clip.

He estado usando este bit de código para agregar el efecto de desvanecimiento / desaparición en clips con duraciones conocidas:

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

Mis dos preguntas son:

  1. ¿Cómo puedo fundir simultáneamente el audio de entrada / salida?
  2. ¿Puede ffmpeg calcular automáticamente la duración del clip y se le dice que solo se desvanecen los últimos 30 fotogramas?

¡Gracias!

d13
fuente

Respuestas:

15

# 1 Para atenuar / desvanecer simultáneamente el 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

Los tiempos de fusión son en segundos .

# 2 automáticamente? No. Pero vea la solución a continuación

Primero puede ejecutar ffprobe para obtener la duración.

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

Obtendrás algo como esto:

video|13.556000
audio|13.816000

Luego puede usar lo anterior para colocar sus fundidos. Estos tiempos son en segundos.

Solución alterna

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 tiene una sseofopción que le permite a uno buscar una entrada desde el final. Podemos usar eso para lograr nuestro objetivo. Así que alimentamos la entrada dos veces, y la segunda vez ingiere solo el último segundo. Le decimos a FFmpeg que conserve las marcas de tiempo, de modo que ffmpeg conserve la posición temporal de esta parte de la cola.

Aplicamos un desvanecimiento a esta cola y luego superponemos el resultado en la entrada completa. Dado que son el mismo archivo de medios, el primer plano cubre completamente el fondo, y desde que copytsse aplicó, la superposición ocurre en el marco idéntico correspondiente en la entrada de fondo.

Para el audio, creamos un audio ficticio en blanco de 2 segundos de duración, y luego aplicamos un fundido cruzado de audio desde el audio principal a este audio ficticio. Como el segundo audio está en blanco, esto es, en efecto, un desvanecimiento para la entrada principal. Se -shortestagrega para dejar fuera partes del audio ficticio después de que se haya producido el fundido cruzado.

Gyan
fuente
Esto da el error "¡no existe ese filtro!" para el filtro de audio
Felwithe
1
Hay 4 filtros de audio utilizados. ¿Cúal? Ejecute su comando con -reportagregado y comparta el informe.
Gyan
7

Es un truco terrible, pero esto podría funcionar si todo lo que desea hacer es la aparición / desaparición gradual del audio, pero no sabe exactamente cuánto dura el clip:

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

[edit 2019-07-24: Tenga en cuenta que esta solución no es buena para las soluciones de transmisión, ya que requiere que se procese la pista completa antes de que se pueda transmitir el primer byte]

Otra opción es usar acrossfadecon una pista silenciosa:

ffmpeg -i input.mp4 -filter_complex "aevalsrc=0:d=0.6 [a_silence]; [0:a:0] [a_silence] acrossfade=d=0.6" output.mp4
marekventur
fuente
3
Esto es realmente bastante elegante :-)
bk138
Esto funciona muy bien. ¿Podría explicar cómo funciona? tratando de dar sentido a la documentación ..
oberhamsi
1
@oberhamsi: Opción 1: el primer filtro agrega un desvanecimiento al comienzo de la pista. Luego invierte el audio y agrega otro desvanecimiento al principio (que en realidad es el final). Finalmente la pista se invierte nuevamente. La opción 2 crea una pista silenciosa de 0.6 segundos y la desvanece por la misma cantidad de tiempo con la pista original. Todos los filtros y su uso están documentados aquí: ffmpeg.org/ffmpeg-filters.html (aunque estoy de acuerdo que es un poco críptico)
marekventur
3

La respuesta a la pregunta 2 es un rotundo ¡SÍ! Estaba buscando la misma funcionalidad y terminé escribiendo un script bash que solicita la duración del desvanecimiento en segundos y calcula el marco inicial para el desvanecimiento:

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

Los desvanecimientos requieren una nueva codificación, por lo que usar un crfvalor bajo para libx264obtener una nueva codificación de alta calidad. Los comentarios deberían explicar todo lo demás.

hmj6jmh
fuente
La respuesta a la pregunta 2 es un rotundo ¡SÍ! -> sigue siendo No. La Q es ¿Puede ffmpeg calcular automáticamente la duración ... pero ha escrito un script que ejecuta múltiples comandos ff * para hacerlo? Sin embargo, es útil para los sistemas * nix.
Gyan
Ya veo, ¿así que insiste en que SU respuesta TODAVÍA es correcta? Si sigues mi secuencia de comandos, verás que realmente automatically figure out the durationusa ffprobe, que está instalado con ffmpeg. ¿Quién dijo algo sobre cualquier restricción en el número de comandos o *nix? Parece que el OP está utilizando una versión de UNIX. No .exeen el ffmpegcomando. Yo mismo estoy usando el OS Xque está construido UNIXpero no lo está UNIX.
hmj6jmh
1
* Si sigues mi script, verás que de hecho se da cuenta automáticamente * -> tu script lo hace, ffmpeg no.
Gyan
Pero ffprobees una parte integral de la ffmpegdistribución. Estás escogiendo liendres para salvar la cara OMI.
hmj6jmh
Tendría que estar de acuerdo en que algo que está haciendo un script bash no es algo que está haciendo automáticamente ffmpeg. Pero si esto funciona, esta es una forma de solucionar ese problema. De ahí el término "solución". No puedo decir si funciona porque, como la mayoría de las personas, no tengo bash o un sistema unix. +1 por el esfuerzo de todos modos.
ashleedawg