I'estou tentando concatenar dois arquivos mp4 usando ffmpeg. Eu preciso que isto seja um processo automático e por isso eu escolhi ffmpeg. I'm convertendo os dois arquivos em arquivos .ts e depois concatenando-os e depois tentando codificar aquele arquivo .ts côncavo. Os arquivos são h264 e aac codificados e I'm esperando manter a qualidade igual ou o mais próximo possível do 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
Infelizmente I'estou recebendo a seguinte mensagem de erro que volta de ffmpeg durante a codificação:
[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
Isto acontece cerca de metade da codificação, o que me faz pensar que você pode't concatinar dois arquivos .ts juntos e tê-lo funcionando.
FFmpeg tem três métodos de concatenação:
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
Note que este método realiza uma re-encodificação.
$ 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
ffmpeg -i "concat:input1|input2" -codec copy output.mkv
Este método não funciona para muitos formatos, incluindo o MP4, devido à natureza destes formatos e à concatenação simplista realizada por este método.
*filtro de gato***: Utilize se as suas entradas não tiverem os mesmos parâmetros (largura, altura, etc.), ou não tiverem os mesmos formatos/codecs, ou se quiser realizar alguma filtragem. (Você poderia re-encodificar apenas as entradas que não't correspondem para que elas compartilhem o mesmo codec e outros parâmetros, então use o concat demuxer para evitar re-encodificar as outras entradas).
*concat demuxer***: Use quando quiser evitar uma recodificação e o seu formato não suporta concatenação de nível de arquivo (a maioria dos arquivos usados por usuários gerais não suporta concatenação de nível de arquivo).
*Protocolo do gato***: Usar com formatos que suportem concatenação de nível de arquivo (MPEG-1, MPEG-2 PS, DV). Não usar com MP4.
Em caso de dúvida, tente o concat demuxer.
Acabei por usar o mpg como formato intermédio e funcionou (NOTA: este é um exemplo perigoso, -qscale 0 irá recodificar o vídeo...)
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
Aqui está um script que fiz para concatenar vários GoPro mp4's em um mp4 de 720p. Espero que seja's de ajuda.
#!/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}