¿Cuál es una forma eficiente de hacer un fundido cruzado de video con FFmpeg?

11

Hacer un fundido cruzado entre dos piezas de contenido de video en realidad es bastante complicado en FFmpeg. No hay filtro de "fundido cruzado" como el que hay para el audio.

¿Cuál es una manera eficiente de hacerlo?

Mark Gerolimatos
fuente
¡Bonita pregunta con respuesta propia!
JakeGould
Esta respuesta necesita MUCHO más votos positivos ... Mark, me encantaría por siempre si agregaras un desvanecimiento cruzado para el audio también ...
Merc
Tan pronto como descubra cómo, lo agregaré. Creo que el fundido cruzado de audio es instantáneo, aunque, creo que hay un filtro simple para ello.
Mark Gerolimatos
Simplemente agregué [0:a][1:a] acrossfade=d=1 [audio]al filtro y luego -map "[audio]" al comando y funcionó. Si lo desea, pruébelo y actualice la respuesta.
Merc
Posible duplicado de fundido cruzado entre 2 videos usando ffmpeg
r_alex_hall

Respuestas:

17

TL; versión DR:

Este ejemplo solo realiza video, suponiendo que ambos videoclips tengan la misma resolución, velocidad de fotogramas, etc. Esto creará un desvanecimiento de 1 segundo entre fadeoutclip y fadeinclip. Suponga que el clip de desvanecimiento dura 10 segundos. Tenga en cuenta que esto está formateado para mayor claridad: es realmente una línea de código.

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>

Versión completa:

Aquí hay una explicación de lo que se trataba todo esto:

Especificación de entrada ... obvio

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

Crear un filter_complex: suponiendo que ya comprenda los complejos de filtro:

-filter_complex

Primero, dividimos las dos corrientes en dos partes, cada una con el filtro de recorte : el contenido y la sección de fundido cruzado. El desvanecimiento se divide en contenido y sección de desvanecimiento, mientras que el desvanecimiento se corta en la sección de desvanecimiento y el contenido. Total de cuatro secciones.

Tenga en cuenta que, estrictamente hablando, no tenemos que separar las secciones de desvanecimiento cruzado: PODRÍAMOS especificar el desvanecimiento y el desvanecimiento en tiempos para los dos videoclips. Sin embargo, al hacer esto, nosotros:

  • Siga la metodología típicamente utilizada por los editores de video GUI
  • Evite la complejidad frustrante overlaydel uso del filtro.
  • Asegúrese de que la solución sea lo más general posible (es decir, código reutilizable)
  • Permítanos preprocesar y postprocesar la sección de fundido cruzado según sea necesario (no se hace aquí)

Cada una de estas cuatro secciones especifica: tiempo de inicio (segundos), tiempo de finalización (segundos) y el setpts=PTS-STARTPTSfiltro misterioso , que esencialmente hace que cada subclip de video comience a 0 segundos. Esto será vital al volver a componerlos.

Tenga en cuenta que los s=0especificadores son redundantes, y el setptsfiltro para s=0los TAMBIÉN es redundante. Sin embargo, ambos se especifican de forma redundante para permitir que el tiempo de inicio cambie de 0, sin romper el complejo del filtro. Además, el segundo clip de contenido se ejecuta hasta el final, por lo que e=no se especifica la parte (end =).

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

A continuación, especificamos la aparición y desaparición gradual: primero agregamos un canal alfa (transparencia) a ambas secciones de desvanecimiento especificando un formato de píxel deyuva420p . En realidad, puede usar cualquier formato que proporcione un canal alfa.

A continuación, en este subcomplejo de filtro, especificamos uno para desvanecer y otro para desvanecer. Esto alpha=1significa que el video en sí no se oscurecerá, solo que la cantidad de transparencia se desvanecerá. stsignifica inicio, dsignifica duración.

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

¿Qué es esto ?: El fifofiltro garantiza que haya espacio de búfer disponible en el complejo del filtro. Sorprendentemente, este NO es el predeterminado. Si no hace esto, el fundido cruzado podría fallar si la salida de la etapa anterior supera el filtro de superposición a continuación. Sí, sé lo que estás pensando ahora. De hecho, es un error FFMPEG .

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

Ahora, superponga las dos secciones de fundido: Al asegurarnos de que las dos secciones de fundido cruzado sean del mismo tamaño, no tenemos que preocuparnos por las opciones bastante desagradables que toma el filtro de superposición (y por eso las ignoramos aquí):

    [fadeoutfifo][fadeinfifo]overlay[crossfade];

Finalmente, alineamos nuestros tres segmentos usando el filtro concat .

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

Y ahora, asigne el pad de salida como fuente de video.

¡NO OLVIDE configurar el formato de píxeles PARA LO QUE USTED NORMALMENTE (normalmente yuv420p), ya que la sección de fundido cruzado lo habrá configurado yuv420en el canal de salida! (como no lo especificamos, puedes usar los argumentos de superposición) Por supuesto, si QUIERES yuv420, entonces estás bien :-)

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

Luego puede recombinar el audio más tarde (fuera del alcance de estas preguntas y respuestas)

Mark Gerolimatos
fuente
1
En el último ffmpeg, debe ser trim=start=0:end=9, (en lugar de trim=st=0:e=9,..
Merc
Pero en serio, esta tendrá que ser la mejor respuesta en FFMPEG que he visto, y la explicación más clara de ffmpeg.
Merc
Hombre, eso se me va a la cabeza :-) ¡Gracias por los accesorios!
Mark Gerolimatos
Sin preocupaciones. Actualice la respuesta especialmente con = trim = start = 0 ya que ahora no funciona con el último ffmpeg
Merc
La última versión de ffmpeg me da este error: Filter setpts has an unconnected outputpara el script. Ya cambié los parámetros de recorte para comenzar y finalizar.