FFmpeg divide video y vuelve a fusionar

8

Estoy tratando de usar FFmpeg para dividir video basado en algunos start_timey end_timeentradas, y reemplazarlos con otros archivos de video. Por ejemplo, para la entrada 10 15necesitaré reemplazar los segundos EXACTOS 10 to 15con otro video.

OKAY. Lo que viene a mi mente es esto:

  1. Primero divida el video (en este caso, 0-10, 10-15 y 15 finales)
  2. Reemplace el 10-15 con el otro video
  3. Fusionar todos los sub-videos

Primera pregunta: ¿Es esta la mejor y más rápida solución? ¿Tenemos un comando más fácil u otras herramientas para reemplazar un período específico de tiempo en video con otro video?

Segunda pregunta: suponiendo que FFmpeg es la solución viable, cuando simplemente uso el comando ffmpeg -I input.video -ss 10 -t 5 -c copy output.mp4, mi código de procesamiento de video no puede leer y procesar el archivo. Utilicé la mediainfoherramienta para comparar los dos archivos y noté diferencias en los tamaños de encabezado, mientras que todas las cosas relacionadas con el códec de video eran iguales. Noté que el TAMAÑO DEL CABEZAL es diferente, lo que aparentemente está causando el problema. ¿Hay alguna forma de forzar que el tamaño del encabezado también (aparte de los códecs) sea el mismo?

ACTUALIZACIÓN: Aquí está el .mp4archivo original que funciona bien en el emulador.

Ariana
fuente
Primero tendríamos que lidiar con el problema que mencionas en tu segunda pregunta. Muestre el comando exacto que está utilizando y la salida de línea de comandos completa y sin cortes que obtiene de ffmpeg. También muestre cualquier error real que obtenga al leer el archivo; sería bueno saber cuál es exactamente su "código de procesamiento".
slhck
@slhck, el código de procesamiento de video es una gran base de código. No puedo compartirlo. Es solo que, por alguna razón, el archivo original se lee pero no el regenerado. Sin embargo, puedo compartir el .mp4archivo original si es necesario.
Ariana
Utilicé la herramienta mediainfo para comparar los dos archivos y notar diferencias en el tamaño de los encabezados y demás
Ariana
Tener el original ayudaría, pero no podremos resolver por qué no se puede leer, me temo, si se trata de algún código interno.
slhck
@slhck Subí el archivo. Mi pregunta se actualiza
Ariana

Respuestas:

9

Usando trimy concat- archivos fuente con diferentes códecs

Para ello, asegúrese de que sus archivos individuales tengan la misma resolución y, idealmente, la misma velocidad de fotogramas y submuestreo de croma, etc. Esto evitará errores o fallas durante la concatenación.

Puede hacer todo de una vez sin dividir el archivo, utilizando los filtros trimy concat:

ffmpeg -i edv_g24.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[v0][v1][v2]concat=n=3:v=1:a=0[out]" \
-map "[out]" output.mp4

Aquí, trimse usa para especificar las porciones individuales de las transmisiones de video de entrada ( 0:v, 1:v) que luego desea concatenar. Estas partes se nombran a v0través de v2. (El setptsfiltro restablece las marcas de tiempo de estas partes individuales a 0, lo cual es necesario para la concatenación). Más tarde, concatenamos las tres partes.

Si desea recortar desde una determinada marca de tiempo hasta el final, use en trim=start=15lugar de especificar el rango.

Si sus archivos tienen audio, debe recortar esas transmisiones por separado:

ffmpeg -i edv_g24_2.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[0:a]atrim=0:10,asetpts=PTS-STARTPTS[a0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[1:a]atrim=0:5,asetpts=PTS-STARTPTS[v1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[0:a]atrim=15:30,asetpts=PTS-STARTPTS[a2]; \
[v0][a0][v1][a1][v2][a2]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" output.mp4

Tenga en cuenta que el video y el audio se volverán a codificar en este caso; asegúrese de especificar los objetivos de calidad de salida adecuados (por ejemplo, -crfpara x264, x265 o libvpx-vp9). Puede leer más sobre esto en FFmpeg Wiki, por ejemplo, para VP9 o H.264 .

Usando segmentos individuales

Si desea dividir los clips y luego volver a ensamblarlos:

ffmpeg -i edv_g24.mp4 -ss 0 -to 10 -c copy part1.mp4
ffmpeg -i edv_g24.mp4 -ss 10 -to 15 -c copy part2.mp4
ffmpeg -i edv_g24.mp4 -ss 15 -c copy part3.mp4

ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][1:v][2:v]concat=n=3:v=1:a=0[outv]" \
-map "[outv]" -t 30 output.mp4

Si los archivos tienen audio, utilice el mismo enfoque que el anterior:

ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" -t 30 output.mp4

Esto volverá a codificar nuevamente la transmisión de video. Es un poco más sencillo, pero de lo contrario debería ser equivalente al método anterior.

Usando concatdemuxer

En principio, también puede intentar concatenar los flujos de bits sin volver a codificarlos, utilizando el demuxer concat. Cree un archivo llamado concat.txty agregue las siguientes entradas (correspondientes a los videoclips creados anteriormente):

file 'part1.mp4'
file 'short-video.mp4'
file 'part3.mp4'

Luego concatene estos archivos individuales:

ffmpeg -f concat -i concat.txt -c copy output.avi

Sin embargo, esto requiere que sus clips tengan el mismo códec, resolución, velocidad de cuadros, etc., por lo que no funciona con todo tipo de fuentes heterogéneas.

Utilizando el concatprotocolo

El tipo de concatenación a nivel de archivo anterior también se puede lograr utilizando el concatprotocolo, con el mismo tipo de restricciones que el anterior (mismo códec, resolución, etc.):

ffmpeg -i "concat:part1.avi|part2.avi|part3.avi" -c copy output.mp4

Para obtener más información sobre la concatenación, lea la página Wiki de FFmpeg correspondiente .

slhck
fuente
Esto se ve muy completo! Gracias. ¡Los probaré!
Ariana
No sé por qué usar el concatmétodo arroja un error:[concat @ 00000000025c2560] Line 1: unknown keyword 'part1.mp4 \\ text.txt: Invalid data found when processing input
Ariana
Para "usar segmentos individuales", veo un alto y un pequeño corte en la salida. ¿Hay alguna forma de arreglar esto?
Ariana
El método 1 funciona perfectamente. Una cosa: ¿cómo podemos especificar "hasta el final" sin indicar un número específico (en lugar de 30 s)
Ariana
1
Lo siento, cometí un error. Para el concatdemuxer, la sintaxis era diferente. Corregido ahora. Para ir hasta el final, use trim=start=15, consulte la documentación del filtro de recorte: ffmpeg.org/ffmpeg-filters.html#trim : en cuanto a los problemas de tiempo, esto realmente depende de su material de origen. Sin embargo, no he tenido problemas para concatenar con el clip que subiste.
slhck