ffmpeg une dos archivos mp4 con ffmpeg en la línea de comando

29

Puedo unir exitosamente múltiples archivos usando el siguiente comando:

ffmpeg -f concat -i input.txt -codec copy output.mp4

El único problema con este comando es que necesita leer las rutas de archivo del archivo de texto llamado input.txt con el siguiente contenido:

file 'C:\Users\fabio\Downloads\Super\Sharks\01.mp4'
file 'C:\Users\fabio\Downloads\Super\Sharks\02.mp4'
file 'C:\Users\fabio\Downloads\Super\Sharks\03.mp4'

¿Hay alguna manera de lograr el mismo objetivo sin tener que leer las rutas de archivo desde un archivo? He intentado lo siguiente sin suerte:

ffmpeg -f concat -i file "C:\a\b\01.mp4" file "C:\a\b\02.mp4" -codec copy output.mp4
ffmpeg -f concat -i "C:\a\b\01.mp4" "C:\a\b\02.mp4" -codec copy output.mp4

¿Tengo que usar un comando diferente?

Fabio Delarias
fuente
1
relacionado: stackoverflow.com/questions/7333232/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Respuestas:

37

Actualización 2019:

Como se menciona en los comentarios, Stack Overflow tiene una excelente descripción de las opciones disponibles para la concatenación, así como una discusión sobre qué método usar según los tipos de archivos que esté utilizando:

¿Cómo concatenar dos archivos MP4 usando FFmpeg?

Respuesta original de 2016:

Debería poder utilizar el método de protocolo concat para combinar los archivos:

ffmpeg -i "concat:input1.mp4|input2.mp4|input3.mp4" -c copy output.mp4

Además, el manual de FFmpeg analiza un método específicamente para archivos MP4, a fin de concatenarlos sin pérdidas, pero requiere que cree archivos temporales (o canalizaciones con nombre):

ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate1.ts
ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate2.ts
ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" -c copy -bsf:a aac_adtstoasc output.mp4
Carson Darling
fuente
1
El primer comando funcionó para mí como una mantequilla ... me llevó de 2 a 3 segundos capturar mis 6 archivos mp4 en el archivo de salida (239 MB aprox.).
Sachin
22
El primer comando no funcionó para mí. Simplemente copió el primer archivo.
Luis A. Florit
3
Esto no funciona, simplemente copió el primer archivo output.mp4.
crmpicco
2
La concatenación a nivel de archivo no funciona para MP4, por lo que el protocolo concat no se recomienda para este formato y generalmente no funcionará.
lema
1
@brasofilo Gracias por el enlace. Esto está retrasado desde hace mucho tiempo, pero actualicé la respuesta para señalar a las personas en esa dirección.
Carson Darling,
5

Puede reemplazar el archivo con la lista enviando la lista stdouty leyendo la lista desde stdinffmpeg:

(echo file 'a.mp4' & echo file 'b.mp4') | ffmpeg -protocol_whitelist file,pipe -f concat -safe 0 -i pipe: -vcodec copy -acodec copy "result.mp4"
Qwertiy
fuente
Al usar ffmpeg versión 2.4.3-tessus en Mac OS 10.12.6, esto solo arroja un error: "Opción no reconocida 'protocol_whitelist'". Sin la opción protocol_whitelist, parece que solo se hace una copia del segundo archivo MP4.
James
2

No, parece que no hay forma de usar el demuxer concat ffmpeg en una sola línea de comando sin algún truco. Debe crear el archivo de texto de entrada con la lista de archivos. Pensé que esto era extraño, tal vez alguien agregará esto a FFMpeg en una fecha posterior.

La respuesta aceptada a esta pregunta utiliza el protocolo concat, no el demuxer concat, que es lo que solicitó el OP.

georgiecasey
fuente
1
En realidad lo hay. stdin.
Qwertiy
El protocolo concat no debe usarse con MP4 o cualquier otro formato que requiera un encabezado global.
lema
1

Aún puede hacerlo en un script sin cambiar el comando. Algo como:

echo "file fname1" >$$.tmp    #single redirect creates or truncates file
echo "file fname2" >>$$.tmp   # double redirect appends
echo "file fname3" >>$$.tmp   # do as many as you want.

ffmpeg -f concat -i $$.tmp -codec copy output.mp4

rm $$.tmp  # just to clean up the temp file. 
           # For debugging, I usually leave this out.

$$ se expande al pid del shell que ejecuta el comando, por lo que el nombre del archivo será diferente cada vez que lo ejecute. así que puedes usar $$. txt si lo prefieres. O algo mas...

Además, puede usar aquí los archivos para agregar un montón de datos al archivo:

cat <<EOF >$$.tmp
file fname1
file fname2
file fname3
EOF

bash La sustitución de variables funciona, por lo que puede determinar mediante programación el contenido del archivo, no tiene que ser reparado. Incrusto este tipo de cosas en bucles todo el tiempo. Finalmente, la redirección funciona igual que antes, por lo que> $$. Tmp se trunca y luego escribe, >> $$. Tmp se agrega.

Richard Betel
fuente
2
La pregunta es: "¿hay alguna manera de lograr el mismo objetivo sin tener que leer las rutas de archivo desde un archivo?" Todo lo que ha hecho es proporcionar una forma de escribir las rutas de archivo en un archivo (antes de leer las rutas de archivo del archivo). Esto no responde la pregunta.
Scott