videos unir safe juntar con ffmpeg h.264 mp4

ffmpeg - safe - ubuntu unir dos videos



¿Cómo concatenar dos archivos MP4 usando FFmpeg? (15)

Estoy tratando de concatenar dos archivos mp4 usando ffmpeg. Necesito que esto sea un proceso automático, por lo tanto, elegí ffmpeg. Estoy convirtiendo los dos archivos en archivos .ts y luego concatenándolos y luego tratando de codificar ese archivo .ts concatenado. Los archivos están codificados en h264 y aac y espero mantener la calidad lo más original posible.

ffmpeg -i part1.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part1.ts ffmpeg -i part2.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part2.ts cat part1.ts part2.ts > parts.ts ffmpeg -y -i parts.ts -acodec copy -ar 44100 -ab 96k -coder ac -vbsf h264_mp4toannexb parts.mp4

Desafortunadamente, recibo el siguiente mensaje de error de ffmpeg durante la codificación:

[h264 @ 0x1012600]sps_id out of range [h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period [h264 @ 0x1012600]sps_id out of range [h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period [NULL @ 0x101d600]error, non monotone timestamps 13779431 >= 13779431kbits/s av_interleaved_write_frame(): Error while opening file

Esto sucede aproximadamente a mitad de la codificación, lo que me hace pensar que no se pueden agrupar dos archivos .ts juntos y hacer que funcionen.


para archivos MP4:

Si no son exactamente los mismos archivos MP4 (el 100% del mismo códec, la misma resolución, el mismo tipo), al principio debe codificarlos en secuencias intermedias:

ffmpeg -i myfile1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts temp1.ts ffmpeg -i myfile2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts temp2.ts // now join ffmpeg -i "concat:temp1.ts|temp2.ts" -c copy -bsf:a aac_adtstoasc output.mp4

¡NOTA! : La salida será como el primer archivo (y no un segundo)


Fusionando todos los archivos mp4 del directorio actual

Personalmente me gusta no crear un archivo externo que tengo que eliminar después, por lo que mi solución fue la siguiente, que incluye la lista de archivos de numeración (como file_1_name, file_2_name, file_10_name, file_20_name, file_100_name , ...)

#!/bin/bash filesList="" for file in $(ls -1v *.mp4);do #lists even numbered file filesList="${filesList}${file}|" done filesList=${filesList%?} # removes trailing pipe ffmpeg -i "concat:$filesList" -c copy $(date +%Y%m%d_%H%M%S)_merged.mp4


Aquí hay un script que hice para concatenar varios mp4 de GoPro en un mp4 de 720p. Espero que sea de ayuda.

#!/bin/sh cmd="( " for i; do cmd="${cmd}ffmpeg -i $i -ab 256000 -vb 10000000 -mbd rd -trellis 2 -cmp 2 -subcmp 2 -g 100 -f mpeg -; " done cmd="${cmd} ) | ffmpeg -i - -vb 10000000 -ab 256000 -s 1280x720 -y out-`date +%F-%H%M.%S`.mp4" echo "${cmd}" eval ${cmd}


Aquí hay una manera rápida (de menos de 1 minuto) y sin pérdida de hacerlo sin necesidad de archivos intermedios:

ls Movie_Part_1.mp4 Movie_Part_2.mp4 | perl -ne ''print "file $_"'' | ffmpeg -f concat -i - -c copy Movie_Joined.mp4

La "ls" contiene los archivos para unirse. La "perl" crea el archivo de concatenación sobre la marcha en una tubería La parte "-i -" le dice a ffmpeg que lea desde la tubería

(nota: mis archivos no tenían espacios o cosas extrañas en ellos; necesitarás un escape de shell adecuado si quieres hacer esta idea con archivos "duros").


De la documentación aquí: https://trac.ffmpeg.org/wiki/Concatenate

Si tiene archivos MP4, estos podrían ser concatenados sin pérdidas al primero, transcodificándolos a flujos de transporte MPEG-2. Con el video H.264 y el audio AAC, se puede usar lo siguiente:

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

Este enfoque funciona en todas las plataformas.

Necesitaba la capacidad de encapsular esto en un script multiplataforma, así que usé fluent-ffmpeg y encontré la siguiente solución:

const unlink = path => new Promise((resolve, reject) => fs.unlink(path, err => (err ? reject(err) : resolve())) ) const createIntermediate = file => new Promise((resolve, reject) => { const out = `${Math.random() .toString(13) .slice(2)}.ts` ffmpeg(file) .outputOptions(''-c'', ''copy'', ''-bsf:v'', ''h264_mp4toannexb'', ''-f'', ''mpegts'') .output(out) .on(''end'', () => resolve(out)) .on(''error'', reject) .run() }) const concat = async (files, output) => { const names = await Promise.all(files.map(createIntermediate)) const namesString = names.join(''|'') await new Promise((resolve, reject) => ffmpeg(`concat:${namesString}`) .outputOptions(''-c'', ''copy'', ''-bsf:a'', ''aac_adtstoasc'') .output(output) .on(''end'', resolve) .on(''error'', reject) .run() ) names.map(unlink) } concat([''file1.mp4'', ''file2.mp4'', ''file3.mp4''], ''output.mp4'').then(() => console.log(''done!'') )


Descubrí que el operador de tuberías no me funcionó cuando usé la opción 3 para calcular varios MP4 en una Mac en la respuesta aceptada.

El siguiente one-liner funciona en una Mac (High Sierra) para concatenar mp4s, sin necesidad de creación de archivos intermediarios.

ffmpeg -f concat -safe 0 -i <(for f in ./*.mp4; do echo "file ''$PWD/$f''"; done) -c copy output.mp4


Estaba tratando de concatenar tres archivos de audio .mp3 en un archivo .m4a y este comando ffmpeg funciona.

Comando de entrada:

ffmpeg -i input1.mp3 -i input2.mp3 -i input3.mp3 -filter_complex concat=n=3:v=0:a=1 -f MOV -vn -y input.m4a

Significados de: "-filter_complex concat = n = 3: v = 0: a = 1" :

concat significa usar la función concatenar (unirse) de medios.
n significa confirmar el recuento total de archivos de entrada.
v significa tiene video ? use 0 = no video, 1 = contiene video.
¿Un medio tiene audio ? use 0 = sin audio, 1 = contiene audio.
-f significa forzar el conjunto de formatos de archivo (para ver todos los formatos compatibles, use ffmpeg -formats )
-vn significa deshabilitar video (y también -an deshabilitaría el audio si no se desea)
-y significa sobrescribir archivos de salida (si el archivo de salida ya existe).

Para obtener más información: use ffmpeg -h full print todas las opciones (incluyendo todas las opciones específicas de formato y códec, muy largas)


FFmpeg tiene tres métodos de concatenación.

1. filtro de video concat

ffmpeg -i opening.mkv -i episode.mkv -i ending.mkv / -filter_complex "[0:v] [0:a] [1:v] [1:a] [2:v] [2:a] concat=n=3:v=1:a=1 [v] [a]" / -map "[v]" -map "[a]" output.mkv

Tenga en cuenta que este método realiza una recodificación.

2. concat demuxer

$ cat mylist.txt file ''/path/to/file1'' file ''/path/to/file2'' file ''/path/to/file3'' $ ffmpeg -f concat -i mylist.txt -c copy output

para Windows :

(echo file ''first file.mp4'' & echo file ''second file.mp4'' )>list.txt ffmpeg -safe 0 -f concat -i list.txt -c copy output.mp4

3. protocolo concat

ffmpeg -i "concat:input1|input2" -codec copy output

Este método no funciona para muchos formatos, incluyendo MP4, debido a la naturaleza de estos formatos y la concatenación simplista realizada por este método.

Cual usar

  • filtro concat : utilícelo si sus entradas no tienen los mismos parámetros (ancho, altura, etc.), no son los mismos formatos / códecs, o si desea realizar algún tipo de filtrado. (Puede volver a codificar solo las entradas que no coincidan para que compartan el mismo códec y otros parámetros, y luego usar el demonio de concat para evitar volver a codificar las otras entradas).

  • concat demuxer : se usa cuando se quiere evitar una recodificación y su formato no admite la concatenación de nivel de archivo (la mayoría de los archivos utilizados por los usuarios generales no admiten la concatenación de nivel de archivo).

  • protocolo concat : se utiliza con formatos que admiten concatenación de nivel de archivo (MPEG-1, MPEG-2 PS, DV). No utilizar con MP4.

En caso de duda probar el demoledor concat.

Ver también


La documentación detallada sobre varias formas de concatenación en ffmpeg se puede encontrar aquí .

Puede usar el ''filtro de concat'' para una concatenación rápida.

Realiza una recodificación. Esta opción es mejor cuando las entradas tienen diferentes formatos de video / audio.

Para concatenar 2 archivos:

ffmpeg -i input1.mp4 -i input2.webm / -filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] concat=n=2:v=1:a=1 [v] [a]" / -map "[v]" -map "[a]" output.mp4

Para concatenar 3 archivos:

ffmpeg -i input1.mp4 -i input2.webm -i input3.mp4 / -filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] [2:v:0] [2:a:0] concat=n=3:v=1:a=1 [v] [a]" / -map "[v]" -map "[a]" output.mp4

Esto funciona tanto para el mismo como para múltiples tipos de archivos de entrada.


Para los archivos mp4, encontré que funciona mejor y más rápido para usar la herramienta de línea de comandos opensource "mp4box". Entonces puedes usarlo de esta manera:

mp4box.exe -add video1.mp4 -cat video2.mp4 destvideo.mp4

Descárguelo aquí para la mayoría de las plataformas: https://gpac.wp.imt.fr/mp4box/


Terminé usando mpg como formato intermedio y funcionó (NOTA: este es un ejemplo peligroso, -qscale 0 volverá a codificar el video ...)

ffmpeg -i 1.mp4 -qscale 0 1.mpg ffmpeg -i 2.mp4 -qscale 0 2.mpg cat 1.mpg 2.mpg | ffmpeg -f mpeg -i - -qscale 0 -vcodec mpeg4 output.mp4


basado en las respuestas de rogerdpack y Ed999, he creado mi versión .sh

#!/bin/bash [ -e list.txt ] && rm list.txt for f in *.mp4 do echo "file $f" >> list.txt done ffmpeg -f concat -i list.txt -c copy joined-out.mp4 && rm list.txt

une todos los archivos *.mp4 en la carpeta actual en joined-out.mp4

probado en mac.

el tamaño del archivo resultante es la suma exacta de mis 60 archivos probados. No debería haber ninguna pérdida. Justo lo que necesitaba


esto funcionó para mí (en windows)

ffmpeg -i "concat:input1|input2" -codec copy output

en particular

ffmpeg -i "concat:01.mp4|02.mp4" -codec copy output.mp4

Pitón

Usando algo de código python para hacerlo con tantos mp4 hay en una carpeta.

stringa = "" for f in glob.glob("*.mp4"): stringa += f + "|" os.system("ffmpeg -i /"concat:" + stringa + "/" -codec copy output.mp4")


PARA ARCHIVOS MP4

Para los archivos .mp4 (que obtuve de DailyMotion.com: un episodio de televisión de 50 minutos, descargable solo en tres partes, como tres archivos de video .mp4) la siguiente fue una solución efectiva para Windows 7 , y NO implica volver a codificar el archivos.

Cambié el nombre de los archivos (como file1.mp4 , file2.mp4 , file3.mp4 ) de modo que las partes estuvieran en el orden correcto para ver el episodio completo de televisión.

Luego creé un archivo por lotes simple (concat.bat), con los siguientes contenidos:

:: Create File List echo file file1.mp4 > mylist.txt echo file file2.mp4 >> mylist.txt echo file file3.mp4 >> mylist.txt :: Concatenate Files ffmpeg -f concat -i mylist.txt -c copy output.mp4

El archivo por lotes , y ffmpeg.exe , deben colocarse en la misma carpeta que los archivos .mp4 para unirse. A continuación, ejecute el archivo por lotes. Por lo general, tardará menos de diez segundos en ejecutarse.
.

Anexo (2018/10/21) -

Si lo que buscaba es un método para especificar todos los archivos mp4 en la carpeta actual sin tener que volver a escribirlos, intente esto en su archivo por lotes de Windows:

:: Create File List for %%i in (*.mp4) do echo file "%%i">> mylist.txt


ffmpeg / -i input_1.mp4 / -i input_2.mp4 / -filter_complex ''[0:v]pad=iw*2:ih[int];[int][1:v]overlay=W/2:0[vid]'' / -map [vid] / -c:v libx264 / -crf 23 / -preset veryfast / output.mp4