¿Cómo concatenar dos archivos MP4 usando FFmpeg?

444

Estoy tratando de concatenar dos archivos mp4 usando ffmpeg. Necesito que este sea un proceso automático, por eso elegí ffmpeg. Estoy convirtiendo los dos archivos en archivos .ts y luego los concateno y luego intento codificar ese archivo conts. Los archivos están codificados en h264 y aac y espero mantener la calidad igual o lo más cercana posible al 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, 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 la mitad de la codificación, lo que me hace pensar que no puedes concatenar dos archivos .ts juntos y hacer que funcione.

Mark L
fuente

Respuestas:

788

FFmpeg tiene tres métodos de concatenación:

1. filtro de video concat

Use este método si sus entradas no tienen los mismos parámetros (ancho, alto, etc.), o no tienen 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).

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 nueva codificación.

2. demuxer concat

Utilice este método cuando desee evitar una nueva codificación y su formato no sea compatible con la concatenación de nivel de archivo (la mayoría de los archivos utilizados por los usuarios generales no son compatibles con la concatenación de nivel de archivo).

$ cat mylist.txt
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'

$ ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4

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

Utilice este método con formatos que admitan la concatenación de nivel de archivo (MPEG-1, MPEG-2 PS, DV). No , no utilizar con MP4.

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

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


Si tiene dudas sobre qué método usar, pruebe el demuxer concat.

Ver también

rogerdpack
fuente
3
El carácter de escape del símbolo del sistema de Windows es ^; También tuve problemas con las comillas, por lo que se convirtió en: ffmpeg -i concat: input1 ^ | input2 -codec copy output
user423430
1
Respuesta útil Y tenía aún más sentido para mí cuando leí esta variación: superuser.com/a/607384/74576
Ryan
3
concat demuxer funciona para video, pero estoy perdiendo audio
Loïc
24
Para uso en línea: ffmpeg -safe 0 -f concat -i <(find . -type f -name '*' -printf "file '$PWD/%p'\n" | sort) -c copy output.mkv(mkv acepta más códecs que mp4, pero también puede probarlo con mp4). El -safe 0es para las versiones recientes de FFmpeg se quejan de nombre de archivo inseguro , y el -type fes solo para la lista de archivos. Agregué | sortpara ordenar los archivos alfabéticamente; porque los findlee en orden como guardados en el sistema de archivos. Funciona también para archivos con espacios en blanco.
erik
1
Para mí, en Windows, comillas dobles trabajadas (en lugar de la única en su ejemplo): ffmpeg -i "concat:input1|input2" -codec copy output. No hay necesidad de escapar del carácter de la tubería.
Shovalt
85

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 estaban en el orden correcto para ver el episodio de televisión completo.

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. Luego ejecute el archivo por lotes. Por lo general, demorará menos de diez segundos en ejecutarse.
.

Anexo (21/10/2018) -

Si lo que estaba buscando 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 ( DEBE incluir la opción -safe 0 ):

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

:: Concatenate Files
ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4

Esto funciona en Windows 7, en un archivo por lotes. ¡No intentes usarlo en la línea de comando, porque solo funciona en un archivo por lotes!

Ed999
fuente
55
La solución más fácil con diferencia.
1934286
Esta debería ser la mejor y más fácil respuesta. Buen trabajo, hermano. Salvaste mi día.
DysaniazzZ
Esta es una buena solución, pero hablar de un archivo por lotes hace que este sonido sea primitivo (como se hizo en lote) y más complejo de lo que es (porque un archivo por lotes es completamente innecesario). Es mucho más claro si simplemente se muestra C:\blah>type mylist.txt<ENTER>(para que vean el contenido de ese archivo) Entonces ffmpeg -f concat -i mylist.txt -c copy output.mp4<ENTER> también debe incluir una referencia trac.ffmpeg.org/wiki/Concatenate (esa referencia incluso usa el mismo nombre de archivo, mylist.txt)
barlop
Esta es una muy buena solución porque le ahorra escribir en largas listas de archivos para el -iparámetro. En Linux hice esto: ls -1 P1041*.mp4 | sed s/"P"/" file P"/g > mylist.txtque es aún más genial que codificar un script por lotes. De todos modos, se -c copyrealiza muy rápidamente (que no sabía) y esta es la verdadera magia de esta respuesta.
Würgspaß
1
Con mis archivos mp4, no hay audio en absoluto en el archivo de salida después de ejecutar su código concat en una Mac, usando ffmpeg v3.2.2.
kakyo
60

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

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, necesitará un escape de shell apropiado si desea hacer esta idea con archivos "duros").

cnd
fuente
2
Hice esto en OSX y funcionó muy bien. Impresionante, rápida solución sin pérdidas con pocos requisitos.
GM Lucid
1
Con escape adecuado para archivos que contienen espacios en blanco:ls Movie_Part_1.mp4 Movie_Part_2.mp4 | perl -ne '$_ =~ s/\n$//; print "file '"'"'$_'"'"'\n"' | ffmpeg -f concat -i - -c copy Movie_Joined.mp4
Thomas Bachem
44
También puede hacerlo ls * | perl -ne 'print "file $_"' | ffmpeg -f concat -i - -c copy Movie_Joined.mp4si sus archivos están bien nombrados y en orden. Me funcionó muy bien en OS X, exactamente lo que quería.
natebeaty
3
En Linux utilicé este oneliner: ffmpeg -safe 0 -f concat -i <(find . -type f -name '*' -printf "file '$PWD/%p'\n" | sort) -c copy output.mkv(mkv acepta más códecs que mp4, pero también puedes probarlo con mp4). El -safe 0es para las versiones recientes de FFmpeg se quejan de nombre de archivo inseguro , y el -type fes solo para la lista de archivos. Agregué | sortpara ordenar los archivos alfabéticamente; porque los findlee en orden como guardados en el sistema de archivos. Funciona también para archivos con espacios en blanco.
erik
13
Tuve que agregar este parámetro para ffmpegque funcione:-protocol_whitelist file,tcp,http,pipe
Bensge
45

para archivos MP4:

Si no son exactamente los mismos archivos MP4 (100% del mismo códec, misma resolución, mismo tipo), primero debe transcodificarlos 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 el segundo)

T.Todua
fuente
2
Como se ilustra en mi respuesta, a continuación, no es necesario transcodificar los archivos. FFmpeg puede concatenar múltiples archivos mp4 en un solo archivo mp4, sin ningún paso intermedio y sin ninguna nueva codificación. El único caso en el que sería necesaria una nueva codificación es si los archivos originales no son archivos mp4, pero la intención es crear un archivo mp4 como archivo de salida.
Ed999
@T. Todua: Me interesaría saber cuáles son precisamente las diferencias entre sus dos archivos fuente mp4. ¿Están utilizando diferentes frecuencias de muestreo (p. Ej. 44.100 Hz y 48.000 Hz)? ¿O están usando diferentes velocidades de bits (por ejemplo, 128 kbps y 64 kbps)? En cualquiera de estos casos, no entiendo cómo el comando -c copy (una instrucción de copia de flujo) modificaría los archivos fuente para hacerlos compatibles.
Ed999
44
@ T.Todua Hola, el comando funciona bien cuando los videos no tienen pista de audio. Sin embargo, cuando myfile1.mp4 no tiene audio y myfile2.mp4 tiene audio, el resultado output.mp4 no tiene audio. El output.mp4 esperado debería contener audio. ¿Cómo puedo resolverlo?
AnswerZhao
2
@ T.Todua er .... Es una lástima. El archivo1 | archivo2 genera el video diferente con el archivo2 | archivo1. El orden es importante.
AnswerZhao
1
Probé tu comando en archivos concat 2 mp4. Funciona. Sin embargo, el audio del segundo archivo se entrecorta como las voces Ah-oh-Ee en la nueva concatenación producida. ¿Tienes una solución para esto?
superlinux
35

Estaba tratando de concatenar tres .mp3archivos de audio en un solo .m4aarchivo 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 de concatenación de medios (unión).
n significa confirmar el recuento total de archivos de entrada.
v significa tiene video ? use 0 = sin video, 1 = contiene video.
un medio tiene audio ? use 0 = sin audio, 1 = contiene audio.
-f significa forzar el formato del archivo establecido (para ver todos los formatos compatibles, usar ffmpeg -formats)
-vn significa deshabilitar el video (y también -andeshabilitaría el audio si no se desea)
-y significa sobrescribir los archivos de salida (si el archivo de salida ya existe).

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

Ellie Tam
fuente
1
Si usa esto -f concat -safe 0 -i "file.txt" -c copy -y "OutPut.mp4", concatá, pero cuando algunos videos tienen audio y otros no tienen audio, no funciona, ¿cómo puedo solucionar esto? Gracias -
Ahmad
1
Esto funciona. Gracias por la explicación detallada en su respuesta. Es muy útil
Joe T. Boka
31

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
Mark L
fuente
8
A partir de este comentario, -sameqfue eliminado. Usar en su -qscale 0lugar.
Xavier Ho
66
-sameqno significa "misma calidad" y se ha eliminado de ffmpeg como lo menciona @XavierHo.
llogan
3
Parece una pena tener que transcodificar el video a través de un formato intermedio solo para concatenar dos archivos. Obtendrá pérdida de generación. Es mejor no ir más profundo que el formato contenedor y usar el concatcomando en ffmpeg, como lo hace @rogerdpack arriba.
Randall Cook
8
¿Cómo es que esta es una respuesta aceptada? Este es un método muy malo.
Nombre para mostrar el
44
@SargeBorsch Porque funciona. He intentado todo lo demás en la página. Ninguno de ellos funciona.
15

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

Puedes usar 'filtro Concat' para una concatenación rápida.

Realiza una nueva codificació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 para los mismos tipos de archivos de entrada y múltiples.

SJ00
fuente
¿Puedes especificar más detalles sobre las opciones que tienes en este ejemplo?
Desarrollador
@Developer: para una explicación de las opciones -> wiki de filtro
Concat
44
Al concatenar 3 archivos, debe usar concat = n = 3: v = 1: a = 1 no n = 2
Cynapsis
1
no obtengo una concatenación sin pérdidas mi ouput.mp4tasa de bits de video es significativamente menor que la tasa de bits de video de los videos de entrada
jasan
Gracias Cynapsis por señalarlo y georgiecasey por actualizar el comando
SJ00
10

Encontré que el operador de tubería no funcionaba para mí cuando usaba la opción 3 para concatenar 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 crear archivos intermedios.

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

Ben Siver
fuente
2
Esta respuesta simple es la única que realmente funcionó para mí. Páginas y páginas de documentación aquí y en otros lugares, mientras que esta simple línea es todo lo que se requiere, y realmente funciona. Gracias.
Blujay
10

Aquí 2 soluciones de bash puro usando solo ffmpegy no usando

  • un archivo intermediario
  • perl, python ni javascript

Solución de una línea usando ls

ls video1.mp4 video2.mp4 | while read line; do echo file \'$line\'; done | ffmpeg -protocol_whitelist file,pipe -f concat -i - -c copy output.mp4

Función que toma 0 o 2+ argumentos

#######################################
# Merge mp4 files into one output mp4 file
# usage:
#   mergemp4 #merges all mp4 in current directory
#   mergemp4 video1.mp4 video2.mp4
#   mergemp4 video1.mp4 video2.mp4 [ video3.mp4 ...] output.mp4 
#######################################
function mergemp4() {
  if [ $# = 1 ]; then return; fi

  outputfile="output.mp4"

  #if no arguments we take all mp4 in current directory as array
  if [ $# = 0 ]; then inputfiles=($(ls -1v *.mp4)); fi
  if [ $# = 2 ]; then inputfiles=($1 $2); fi  
  if [ $# -ge 3 ]; then
    outputfile=${@: -1} # Get the last argument
    inputfiles=(${@:1:$# - 1}) # Get all arguments besides last one as array
  fi

  # -y: automatically overwrite output file if exists
  # -loglevel quiet: disable ffmpeg logs
  ffmpeg -y \
  -loglevel quiet \
  -f concat \
  -safe 0 \
  -i <(for f in $inputfiles; do echo "file '$PWD/$f'"; done) \
  -c copy $outputfile

  if test -f "$outputfile"; then echo "$outputfile created"; fi
}

Nota: había probado algunas soluciones en este hilo y ninguna me satisfizo

Roques Florent
fuente
9

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 *.mp4archivos en la carpeta actual enjoined-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

Alexandr Perfilov
fuente
9

esto funcionó para mí (en windows)

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

un ejemplo...

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

Pitón

Usando algún código de Python para hacerlo con la cantidad de mp4 que hay en una carpeta (instale python desde python.org, copie y pegue y guarde este código en un archivo llamado mp4.py y ejecútelo desde el cmd abierto en la carpeta con python mp4.py y todos los mp4 en la carpeta se concatenarán)

import glob
import os

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

Versión 2 con Python

Tomado de mi publicación en mi blog , así es como lo hago en python:

import os
import glob

def concatenate():
    stringa = "ffmpeg -i \"concat:"
    elenco_video = glob.glob("*.mp4")
    elenco_file_temp = []
    for f in elenco_video:
        file = "temp" + str(elenco_video.index(f) + 1) + ".ts"
        os.system("ffmpeg -i " + f + " -c copy -bsf:v h264_mp4toannexb -f mpegts " + file)
        elenco_file_temp.append(file)
    print(elenco_file_temp)
    for f in elenco_file_temp:
        stringa += f
        if elenco_file_temp.index(f) != len(elenco_file_temp)-1:
            stringa += "|"
        else:
            stringa += "\" -c copy  -bsf:a aac_adtstoasc output.mp4"
    print(stringa)
    os.system(stringa)

concatenate()
Giovanni G. PY
fuente
1
El protocolo concat no debe usarse con MP4 y no funcionará como se menciona en la respuesta aceptada .
llogan
@LordNeckbeard Me pregunto si conoce la respuesta a esta pregunta de ffmpeg sobre la concatenación de 2 videos MP4 mientras especifica la tasa de bits de salida. video.stackexchange.com/q/24569/5657 Gracias.
Ryan
@LordNeckbeard ¡Supongo que tu respuesta sería la mejor, aún si estás preparado! No estoy particularmente satisfecho con el mío.
Ryan
No solo (como señala Lord Neckbeard) es necesario convertir un archivo .mp4 al formato intermedio .TS para que la concatenación tenga éxito, sino que, quizás peor, esta respuesta ni siquiera comienza a abordar la necesidad de la entrada los archivos de video tienen una tasa de bits, velocidad de cuadros, frecuencia de muestreo, base de tiempo y duración coincidentes. Sin los 5 de esos factores en común, los archivos no pueden concatenarse (es decir, unirse mediante la copia de flujo ), sino que deben volver a codificarse.
Ed999
7

Para .mp4archivos, he encontrado que funciona mejor y más rápido de usar la herramienta de línea de comandos de código abierto: 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/

Mario
fuente
2
Aunque esto podría ser útil para alguien, el requisito era: " Estoy tratando de concatenar dos archivos mp4 usando ffmpeg. Necesito que esto sea un proceso automático ". Lea la pregunta completa e intente proporcionar una respuesta correcta.
thvs86
55
Esta respuesta es totalmente precisa. Es una herramienta de software libre que hace el mismo trabajo. Se puede usar en un script como FFmpeg. Hace el trabajo de manera más simple que cualquiera de las respuestas de FFmpeg. ¡Mira lo complicados que son! ¡Uno de ellos usa Node.js para llamar a FFmpeg! Locura. Deténgase con el wonkism e intente hacer que StackOverflow sea útil nuevamente. Este sitio es una sombra de lo que era antes gracias a maravillas como tú. Además, esta pregunta es un ejemplo del "Problema XY", con el que una persona como usted debería estar familiarizado.
Blujay
No importa que mp4box sea una herramienta FOSS. La pregunta pedía respuestas usando ffmpeg, no mp4box.
jramos775
@ thvs86 Soy un ejemplo de eso. Utilizo ffmpeg, ya que es un verdadero cuchillo suizo para los medios. También busco ayuda con mis casos de uso particulares, ya que la estructura de los argumentos puede ser bastante compleja (como lo demuestran las variadas respuestas aquí). Esta es la primera vez que escucho sobre mp4box y no lo habría encontrado si no fuera por esta respuesta. Entonces haga un +1 de mí y, por favor, piense más en las personas que buscan respuestas que en los puntos de Internet sin sentido y las reglas rígidas.
Pavel
4

Aquí hay un script que hice para concatenar varios GoPro mp4 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}
Reid Ellis
fuente
Esto NO es concatenante. Este código no concatena las entradas, las vuelve a codificar. Esto toma cualquier archivo de video arbitrario y los cambia a una tasa de bits de audio y video común (independientemente de la tasa de bits original o el tamaño de fotograma original de los archivos fuente). El o / p quería unir dos archivos usando la copia de flujo, no volver a codificarlos, por lo que esto no responde a la pregunta formulada.
Ed999
4

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

Si tiene archivos MP4, estos podrían concatenarse sin pérdidas al transcodificarlos primero a secuencias de transporte MPEG-2. Con video H.264 y 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 utilicé fluent-ffmpegla 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!')
)
itslittlejohn
fuente
1
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
Deepak Kumar
fuente
1
No solo publicando una respuesta, podría agregar una pequeña explicación que entienda mejor la solución para OP y futuros lectores también.
Balagurunathan Marimuthu
1
Esto creó un nuevo video silencioso con ambas entradas reproduciéndose al mismo tiempo una al lado de la otra. Esperaba que la concatenación creara un video donde se jugara input_1.mp4 y luego input_2.mp4
Alexx Roche
3
Esta fue la respuesta incorrecta por completo. Esto no concató los videos, solo los reproduce en silencio uno al lado del otro, como había mencionado @AlexxRoche.
Kalob Taulien
1

Fusionar 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 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
Pipo
fuente
Copié este código en el Bloc de notas y no pasó nada.
7vujy0f0hy
1
@ 7vujy0f0hy esto funciona en un Linux con un bash shell tal vez podría funcionar con cygwin
Pipo
1

Después de varios intentos, el siguiente script funcionó para mí en Windows 10 PowerShell.

    $files=Get-ChildItem -path e:\ -Filter *.mp4


    $files| ForEach-Object  {"file '$($_.FullName)'"}| Out-File -FilePath e:\temp.txt -Encoding ASCII


    if (-not (test-path "e:\ffmpeg\bin\ffmpeg.exe")) {throw "e:\ffmpeg\bin\ffmpeg.exe needed"}

    E:\ffmpeg\bin\ffmpeg.exe -safe 0 -f concat -i "e:\temp.txt" -c copy -bsf:v hevc_mp4toannexb -an e:\joined.mp4

    # Conversion Cleanup
    Remove-Item e:\temp.txt

Aquí las dos primeras líneas crean un archivo de texto temp.txt que tiene el siguiente contenido

file 'e:\first.mp4'
file 'e:\second.mp4'

3ra, 4ta línea verifica si ffmpeg está disponible en la ruta y crea el "join.mp4"

Las diferencias clave de otras respuestas son las siguientes

usage  of -bsf:v hevc_mp4toannexb -an

para mi archivo mp4 anterior funcionó, es posible que deba usar otras alternativas como las siguientes, dependiendo de su codificación de video.

h264_mp4toannexb

Todos estos posibles filtros de Bitstream se pueden encontrar en https://ffmpeg.org/ffmpeg-bitstream-filters.html

rahul maindargi
fuente
Los míos eran MP4 provenientes de una cámara CCTV. Sin ese comando, la conversación no puede generar el archivo de salida. Estoy usando el último ffmpeg de su sitio web.
rahul maindargi
0

Este es mi método para unirme a un directorio lleno de archivos MP4 usando la sustitución de comandos y el filtro de video concat (esto se volverá a codificar). se unieron a 17 archivos de una sola vez):

ffmpeg $(for f in *.mp4 ; do echo -n "-i $f "; done) -filter_complex \
"$(i=0 ; for f in *.mp4 ; do echo -n "[$i:v] [$i:a] " ; i=$((i+1)) ; done \
&& echo "concat=n=$i:v=1:a=1 [v] [a]")" -map "[v]" -map "[a]" output.mp4

Nota: este comando une sus archivos en el orden en que se nombran (es decir, el mismo orden en que se presentan si ejecuta ls *.mp4); en mi caso, cada uno tenía un número de pista, por lo que funcionó muy bien.

Peter
fuente
0

El protocolo concat descrito aquí; https://trac.ffmpeg.org/wiki/Concatenate#protocol

Cuando se implementa utilizando canalizaciones con nombre para evitar archivos intermedios

Es muy rápido (léase: instantáneo), no tiene marcos caídos y funciona bien.

Recuerde eliminar los archivos de tubería con nombre y recuerde verificar si el video es H264 y AAC, lo que puede hacer con solo ffmpeg -i filename.mp4(verifique las menciones h264 y aac)

Roel Van de Paar
fuente
-1

La respuesta aceptada en forma de script reutilizable de PowerShell

Param(
[string]$WildcardFilePath,
[string]$OutFilePath
)
try
{
    $tempFile = [System.IO.Path]::GetTempFileName()
    Get-ChildItem -path $wildcardFilePath | foreach  { "file '$_'" } | Out-File -FilePath $tempFile -Encoding ascii
    ffmpeg.exe -safe 0 -f concat -i $tempFile -c copy $outFilePath
}
finally
{
    Remove-Item $tempFile
}
fjch1997
fuente