Cómo concatenar dos archivos MP4 usando FFmpeg?


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

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, estoy recibiendo el siguiente mensaje de error de ffmpeg durante 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 a mitad de camino a través de la codificación que me hace pensar que no se puede concat dos .archivos ts juntos y hacer que funcione.

13 answers

FFmpeg tiene tres métodos de concatenación.

1. filtro de vídeo 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.

Cuál a use

  • Concat filter : Úselo si sus entradas no tienen los mismos parámetros (ancho, alto, etc.), o no son los mismos formatos/códecs, o si desea realizar algún filtrado. (Puede volver a codificar solo las entradas que no coinciden para que compartan el mismo códec y otros parámetros, luego use el demuxer concat para evitar volver a codificar las otras entradas).

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

  • Protocolo Concat: Se usa con formatos que admiten la concatenación a nivel de archivo (MPEG-1, MPEG-2 PS, DV). No usar con MP4.

En caso de duda pruebe el demuxer concat.

Véase también

 417
Author: rogerdpack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-04 14:49:42

Aquí hay una forma rápida (toma menos de 1 minuto) y sin pérdidas de hacer esto 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

El " ls " contiene los archivos a unir El "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á escape de shell apropiado si desea hacer esta idea con archivos "duros").

 39
Author: cnd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-27 12:44:56

Terminé usando mpg como formato intermedio y funcionó (TENGA en cuenta que este es un ejemplo peligroso, -qscale 0 re-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
 28
Author: Mark L,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-15 23:30:03

Para archivos MP4:

Si no son exactamente los mismos (100% el mismo códec, la misma resolución, el mismo tipo) archivos MP4, entonces tienes que trans-codificarlos en flujos intermedios al principio:

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

Resultado : La salida se comportará como el primer archivo ( y no como un segundo)

 28
Author: T.Todua,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-27 21:34:12

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 media concatenar (unir).
n significa confirmar el recuento total de archivos de entrada.
v significa tiene video ? utilice 0 = sin vídeo, 1 = contiene vídeo.
a significa tiene audio ? use 0 = sin audio, 1 = contiene audio.
-f significa forzar el formato de archivo (para ver todos los formatos compatibles, use ffmpeg -formats)
-vn significa deshabilitar el video (y también -an deshabilitaría el audio si no se desea)
-y significa sobrescribir los archivos de salida (si el archivo de salida ya existe).

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

 25
Author: Ellie Tam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-01 11:44:28

PARA ARCHIVOS MP4

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

He cambiado el nombre de los archivos (como archivo1.mp4, archivo2.mp4, archivo3.mp4) tal que las partes estaban en el orden correcto para ver la completa tv episodio.

Luego creé un simple archivo por lotes (concat.mtd), con el siguiente contenido:

:: 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 , ambos deben colocarse en la misma carpeta que los archivos . mp4 a unir. A continuación, ejecute el archivo por lotes. Normalmente tardará menos de diez segundos en ejecutarse.

 23
Author: Ed999,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-29 21:42:07

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

Puede utilizar 'Filtro 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 los mismos como para varios tipos de archivos de entrada.

 10
Author: SJ00,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-15 11:57:15

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}
 3
Author: Reid Ellis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-24 19:50:53

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 de archivo resultante es la suma exacta de mis 60 archivos probados. No debería haber ninguna pérdida. Justo lo que necesitaba

 2
Author: Alexandr Perfilov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-08 15:18:05
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
 0
Author: Deepak Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-28 08:44:19

Fusionando todos los archivos mp4 del directorio actual

Personalmente me gusta no crear archivos externos que tengo que eliminar después, por lo que mi solución estaba siguiendo que incluye la lista de numeración de archivos (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
 0
Author: Pipo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-27 16:11:55

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

Python

Usando algún código python para hacerlo con tantos mp4 hay en una carpeta importar glob importar os

stringa = ""
for f in glob.glob("*.mp4"):
    stringa += f + "|"

os.system("ffmpeg -i \"concat:" + stringa + "\" -codec copy output.mp4")
 0
Author: Giovanni Gianni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-28 05:02:42

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

Si tiene archivos MP4, estos podrían ser sin pérdida concatenados primero transcodificándolos a flujos de transporte MPEG-2. Con vídeo H. 264 y audio AAC, se puede utilizar 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 se me ocurrió lo 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!')
)
 0
Author: itslittlejohn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-22 13:42:30