我正在尝试使用ffmpeg连接两个mp4文件。我需要这是一个自动过程,因此我选择了ffmpeg。我将这两个文件转换为.ts文件,然后将它们连接起来,然后尝试对连接的.ts文件进行编码。文件是h264和aac编码的,我希望保持质量相同或尽可能接近原始。

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

不幸的是,我在编码过程中从ffmpeg返回以下错误消息:

[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

这种情况大约发生在编码的一半,这让我认为不能将两个.ts文件合并在一起并使其正常工作。


当前回答

这里有一种快速(不到1分钟)且无损的方法,无需中间文件即可完成此操作:

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

“ls”包含要加入的文件“perl”在管道中动态创建连接文件“-i-”部分告诉ffmpeg从管道读取

(注意——我的文件中没有空格或奇怪的东西——如果你想用“硬”文件实现这个想法,你需要适当的shell转义)。

其他回答

如果您想连接文件,而不必创建一个烦人的单独文本文件,只需包含文件名,您可以这样做:

echo -e "file 'in1.mp4'\nfile 'in2.mp4'" | ffmpeg -f concat -safe 0 -i /dev/stdin -c copy out.mp4

事实上,每次命令需要传入文件时,您都可以回显一个字符串并将其通过管道发送到命令,只需使用/dev/stdin作为文件名。

关于ffmpeg中各种连接方式的详细文档可以在这里找到。

您可以使用“Concat filter”进行快速连接。

它执行重新编码。当输入具有不同的视频/音频格式时,此选项最佳。

对于合并2个文件:

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

对于连接3个文件:

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

这适用于相同的以及多种输入文件类型。

我有不同编码器libx264和H.264的剪辑

我将所有剪辑转换为libx264,并使用了来自最高投票答案的解复用器方法。

ffmpeg -i input.flv -vcodec libx264 output.mp4
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

当使用选项3在Mac上连接多个MP4时,我发现管道操作员不适合我。

以下一行程序适用于bash(Mac、Linux),不需要中间文件:

ffmpeg-f concat-safe 0-i<(对于./*.mp4中的f;do echo“文件'$PWD/$f'”;已完成)-c copy output.mp4

这里,<()语法实际上在后台创建了一个临时文件