Cree videos con 5 imágenes con efecto de fundido de entrada / salida en ffmpeg

27

Con 5 imágenes tengo que crear un video de 60 segundos en ffmpeg, cada imagen tiene que mostrarse durante 15 segundos. después de 15 segundos, la primera imagen tiene que desvanecerse y la segunda imagen tiene que desvanecerse, después de que la segunda imagen tiene que desvanecerse, la tercera imagen tiene que desvanecerse ... etc. Guíame, ¿cómo puedo lograr esto usando los comandos ffmpeg?

usuario384847
fuente
44
¿Qué has intentado y luego podemos ayudarte? Este foro no es un tipo de foro "por favor, dame la respuesta sin hacer ningún trabajo". Dicho esto, le proporcionaré el enlace a la documentación de ffmpeg fade - ffmpeg.org/ffmpeg-filters.html#fade
Mike Diglio

Respuestas:

49

Dip / fade a negro

Desplácese hacia abajo para el método de fundido cruzado.

ejemplo de desvanecimiento

Ejemplo donde cada imagen se muestra durante 5 segundos y cada una tiene un desvanecimiento que dura 1 segundo. Cada entrada de imagen tiene el mismo ancho, alto y relación de aspecto de muestra. Si varían en tamaño, vea el ejemplo # 3 a continuación.

Salida MP4

ffmpeg \
-loop 1 -t 5 -i input0.png \
-loop 1 -t 5 -i input1.png \
-loop 1 -t 5 -i input2.png \
-loop 1 -t 5 -i input3.png \
-loop 1 -t 5 -i input4.png \
-filter_complex \
"[0:v]fade=t=out:st=4:d=1[v0]; \
 [1:v]fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v1]; \
 [2:v]fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v2]; \
 [3:v]fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v3]; \
 [4:v]fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v4]; \
 [v0][v1][v2][v3][v4]concat=n=5:v=1:a=0,format=yuv420p[v]" -map "[v]" out.mp4

Con audio

Igual que el anterior pero con audio:

ffmpeg \
-loop 1 -t 5 -i input0.png \
-loop 1 -t 5 -i input1.png \
-loop 1 -t 5 -i input2.png \
-loop 1 -t 5 -i input3.png \
-loop 1 -t 5 -i input4.png \
-i audio.m4a \
-filter_complex \
"[0:v]fade=t=out:st=4:d=1[v0]; \
 [1:v]fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v1]; \
 [2:v]fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v2]; \
 [3:v]fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v3]; \
 [4:v]fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v4]; \
 [v0][v1][v2][v3][v4]concat=n=5:v=1:a=0,format=yuv420p[v]" -map "[v]" -map 5:a -shortest out.mp4

Para imágenes de entrada con tamaños variables o arbitrarios

Como el primer ejemplo, pero con imágenes de entrada que varían en ancho x alto. Se rellenarán para caber dentro de una caja de 1280x720:

ffmpeg \
-loop 1 -t 5 -i input0.png \
-loop 1 -t 5 -i input1.png \
-loop 1 -t 5 -i input2.png \
-loop 1 -t 5 -i input3.png \
-loop 1 -t 5 -i input4.png \
-filter_complex \
"[0:v]scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2,setsar=1,fade=t=out:st=4:d=1[v0]; \
 [1:v]scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2,setsar=1,fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v1]; \
 [2:v]scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2,setsar=1,fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v2]; \
 [3:v]scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2,setsar=1,fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v3]; \
 [4:v]scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2,setsar=1,fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v4]; \
 [v0][v1][v2][v3][v4]concat=n=5:v=1:a=0,format=yuv420p[v]" -map "[v]" out.mp4

Vea los ejemplos en Cambiar el tamaño de los videos para que se ajusten al reproductor de tamaño estático si desea recortar (llenar la pantalla) en lugar de pad (letterbox / pillarbox), o si desea evitar el aumento de escala.

Salida GIF

Agrega los filtros de ¿Cómo convierto un video a GIF usando ffmpeg, con una calidad razonable?

ffmpeg \
-framerate 10 -loop 1 -t 5 -i input0.png \
-framerate 10 -loop 1 -t 5 -i input1.png \
-framerate 10 -loop 1 -t 5 -i input2.png \
-framerate 10 -loop 1 -t 5 -i input3.png \
-framerate 10 -loop 1 -t 5 -i input4.png \
-filter_complex \
"[0:v]fade=t=out:st=4:d=1[v0]; \
 [1:v]fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v1]; \
 [2:v]fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v2]; \
 [3:v]fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v3]; \
 [4:v]fade=t=in:st=0:d=1,fade=t=out:st=4:d=1[v4]; \
 [v0][v1][v2][v3][v4]concat=n=5:v=1:a=0,split[v0][v1]; \
 [v0]palettegen[p];[v1][p]paletteuse[v]" -map "[v]" out.gif

Use la -loopopción de salida para controlar la cantidad de veces que el GIF se repite. El valor predeterminado es bucle infinito si no se utiliza esta opción. Un valor de -1es no loop.

Opciones y filtros utilizados:

  • -t para establecer la duración en segundos de cada entrada.

  • -loop 1 realiza un bucle de la imagen; de lo contrario, tendría una duración de 1 fotograma.

  • -frameratepara establecer la velocidad de fotogramas de la imagen de entrada (el valor predeterminado cuando no se declara es 25). Útil para hacer GIF.

  • escale con la almohadilla para ajustar las imágenes de entrada en un tamaño específico y uniforme (usado en el ejemplo # 3).

  • desvanecerse para desvanecerse dentro y fuera. des la duración del desvanecimiento. stes cuando comienza.

  • concat para concatenar (o "unir") cada imagen.

  • formato para generar un esquema de submuestreo de croma que sea compatible con reproductores no basados ​​en FFmpeg si genera MP4 y codifica con libx264 (el codificador predeterminado para la salida MP4 si es compatible con su compilación).

  • dividir para hacer copias de una salida de filtro. Necesario por los filtros de paleta * para hacer todo en un comando.

  • palettegen y paletteuse para hacer un GIF bonito.


Fundido cruzado

ejemplo de fundido cruzado

Ejemplo donde cada imagen se muestra durante 5 segundos y cada una tiene un fundido cruzado que dura 1 segundo. Cada entrada de imagen tiene el mismo ancho, alto y relación de aspecto de muestra. Si varían en tamaño, entonces adapte el ejemplo # 3 anterior.

Salida MP4

ffmpeg \
-loop 1 -t 5 -i 1.png \
-loop 1 -t 5 -i 2.png \
-loop 1 -t 5 -i 3.png \
-loop 1 -t 5 -i 4.png \
-loop 1 -t 5 -i 5.png \
-filter_complex \
"[1]format=yuva444p,fade=d=1:t=in:alpha=1,setpts=PTS-STARTPTS+4/TB[f0]; \
 [2]format=yuva444p,fade=d=1:t=in:alpha=1,setpts=PTS-STARTPTS+8/TB[f1]; \
 [3]format=yuva444p,fade=d=1:t=in:alpha=1,setpts=PTS-STARTPTS+12/TB[f2]; \
 [4]format=yuva444p,fade=d=1:t=in:alpha=1,setpts=PTS-STARTPTS+16/TB[f3]; \
 [0][f0]overlay[bg1];[bg1][f1]overlay[bg2];[bg2][f2]overlay[bg3]; \
 [bg3][f3]overlay,format=yuv420p[v]" -map "[v]" -movflags +faststart out.mp4

Con audio

ffmpeg \
-loop 1 -t 5 -i 1.png \
-loop 1 -t 5 -i 2.png \
-loop 1 -t 5 -i 3.png \
-loop 1 -t 5 -i 4.png \
-loop 1 -t 5 -i 5.png \
-i music.mp3 \
-filter_complex \
"[1]format=yuva444p,fade=d=1:t=in:alpha=1,setpts=PTS-STARTPTS+4/TB[f0]; \
 [2]format=yuva444p,fade=d=1:t=in:alpha=1,setpts=PTS-STARTPTS+8/TB[f1]; \
 [3]format=yuva444p,fade=d=1:t=in:alpha=1,setpts=PTS-STARTPTS+12/TB[f2]; \
 [4]format=yuva444p,fade=d=1:t=in:alpha=1,setpts=PTS-STARTPTS+16/TB[f3]; \
 [0][f0]overlay[bg1];[bg1][f1]overlay[bg2];[bg2][f2]overlay[bg3]; \
 [bg3][f3]overlay,format=yuv420p[v]" -map "[v]" -map 5:a -shortest -movflags +faststart out.mp4

Fundido cruzado entre dos videos con audio

Seleccione un segmento de 5 segundos de cada entrada y agregue un fundido cruzado de 1 segundo:

ffmpeg -i input0.mp4 -i input1.mp4 -filter_complex \
"[0:v]trim=start=5:end=10,setpts=PTS-STARTPTS[v0];
 [1:v]trim=start=12:end=17,setpts=PTS-STARTPTS+4/TB,format=yuva444p,fade=st=4:d=1:t=in:alpha=1[v1];
 [v0][v1]overlay,format=yuv420p[v];
 [0:a]atrim=start=5:end=10,asetpts=PTS-STARTPTS[a0];
 [1:a]atrim=start=12:end=17,asetpts=PTS-STARTPTS[a1];
 [a0][a1]acrossfade=d=1[a]" \
-map "[v]" -map "[a]" output.mp4

Salida GIF

ffmpeg \
-framerate 10 -loop 1 -t 5 -i 1.png \
-framerate 10 -loop 1 -t 5 -i 2.png \
-framerate 10 -loop 1 -t 5 -i 3.png \
-framerate 10 -loop 1 -t 5 -i 4.png \
-framerate 10 -loop 1 -t 5 -i 5.png \
-filter_complex \
"[1]format=rgba,fade=d=1:t=in:alpha=1,setpts=PTS-STARTPTS+4/TB[f0]; \
 [2]format=rgba,fade=d=1:t=in:alpha=1,setpts=PTS-STARTPTS+8/TB[f1]; \
 [3]format=rgba,fade=d=1:t=in:alpha=1,setpts=PTS-STARTPTS+12/TB[f2]; \
 [4]format=rgba,fade=d=1:t=in:alpha=1,setpts=PTS-STARTPTS+16/TB[f3]; \
 [0][f0]overlay[bg1];[bg1][f1]overlay[bg2];[bg2][f2]overlay[bg3];[bg3][f3]overlay,split[v0][v1]; \
 [v0]palettegen[p];[v1][p]paletteuse[v]" -map "[v]" out.gif

Use la -loopopción de salida para controlar la cantidad de veces que el GIF se repite. El valor predeterminado es bucle infinito si no se utiliza esta opción. Un valor de -1es no loop.

lema
fuente
1
@ LordNeckbeard, gracias por esta respuesta, la usé para otro ejemplo. ¿He entendido bien que el número siguiente -ten -loop 1 -t 1 -i 001.pngDefine la duración de fotogramas individuales, y que los números que siguen T/dentro de filter_complexbloque define la duración de la transición? ¿Y se cuenta la duración del marco en este ejemplo, incluida la duración de la transición o no?
cincplug
1
@Nisarg Ese no parece ser el resultado completo y no estoy seguro de qué comando proviene de los dos que mostró anteriormente. De todos modos, intente agregar -preset ultrafast.
llogan
1
@LordNeckbeard Necesito combinar un conjunto de imágenes, videoclips y una pista de audio para crear un solo archivo de video (preferiblemente ogg, pero eso es menos relevante en este punto). Además, necesito crear algunos efectos de transición entre imágenes adyacentes. ¿Hay alguna forma de guiar toda esta tarea usando ffmpeg y / u otras herramientas de línea de comandos? El objetivo es automatizar la tarea a través de una interfaz de línea de comandos.
Usuario web
1
Las transiciones de @WebUser probablemente serán más fáciles de usar melt.
llogan
2
El enfoque ffmpeg está funcionando bien para mí; ¡Gracias! Un consejo para los recién llegados a la página; en la concat=n=9parte del comando, 9proviene de las 5 imágenes del ejemplo + 4 transiciones entre las imágenes. Si está manejando un número diferente de imágenes, deberá ajustarlo en consecuencia.
Jim Miller
4

Escribí un script bash general que toma una ruta a una carpeta de imágenes y genera un video de fundido cruzado con ffmpeg:

https://gist.github.com/anguyen8/d0630b6aef6c1cd79b9a1341e88a573e

El script esencialmente mira las imágenes en una carpeta e imprime un comando que es similar a la respuesta de @LordNeckbeard anterior, y ejecuta el comando. Este script ayuda cuando tiene muchas imágenes en una carpeta y no desea escribir manualmente un comando deprimentemente largo.

anh_ng8
fuente
Lo sentimos, pero su script falla con ffmpeg 3.0.1, con las entradas # 0 a # 4, devuelve: "Índice de archivo no válido 5 en la descripción del filtro"
Krzysztof Bociurko
TobySpeight: buen punto, he editado la respuesta para que sea más clara. Básicamente, la idea principal ya está dada por @LordNeckbeard arriba. Este script solo se generaliza a muchas imágenes.
anh_ng8