使用ffmpeg连接两个mp4文件
我试图使用ffmpeg连接两个mp4文件。 我需要这是一个自动过程,因此我select了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文件并使其工作。
FFmpeg有三个concat方法。 (在Windows中,使用双引号"
)
concat协议
ffmpeg -i 'concat:input1|input2' -codec copy output
concatvideofilter
ffmpeg -i opening.mkv -i episode.mkv -i ending.mkv \ -filter_complex '[0:0] [0:1] [1:0] [1:1] [2:0] [2:1] concat=n=3:v=1:a=1 [v] [a]' \ -map '[v]' -map '[a]' output.mkv
请注意,此方法执行重新编码。
连接分路器
$ cat mylist.txt file '/path/to/file1' file '/path/to/file2' file '/path/to/file3' $ ffmpeg -f concat -i mylist.txt -c copy output
对于Windows :
(echo file ../../../../1.mp4 & echo file ../../../../2.mp4 )>%tmp%/list.txt ffmpeg -safe 0 -f concat -i %tmp%/list.txt -c copy c:/output.mp4
哪一个使用
- concat协议 :使用支持文件级联(MPEG-1,MPEG-2 PS,DV)的格式。
- concatfilter :如果您需要重新编码,例如在应用filter或文件使用不同的编解码器时使用(或者您可以对“不匹配”进行重新编码,以便它们是相同的编解码器,则使用不同的编解码器)选项,以避免重新编码部分input)。
- concat demuxer :当你想避免重新编码,而你的格式不支持文件级联。
如果有疑问,尝试连接分路器。
另见
- FFmpeg FAQ:如何joinvideo文件?
- FFmpeg Wiki:如何连接(连接,合并)媒体文件
这是一个快速(less于1分钟)和无损的方式来做到这一点,而不需要中间文件: –
ls Movie_Part_1.mp4 Movie_Part_2.mp4 | perl -ne 'print "file $_"' | ffmpeg -f concat -i - -c copy Movie_Joined.mp4
“ls”包含要join的文件“perl”实时创build连接文件到pipe道中“-i – ”部分告诉ffmpeg从pipe道读取
(注意 – 我的文件中没有空格或怪异的东西 – 如果你想用“硬”文件来做这个想法,你需要适当的shell转义)。
我结束了使用MPG作为中间格式,它的工作(注意这是一个危险的例子,-qscale 0将重新编码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
我试图将三个.mp3
audio文件连接成一个.m4a
文件,这个ffmpeg命令起作用。
input命令:
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
意思是: “-filter_complex concat = n = 3:v = 0:a = 1” :
concat意味着使用媒体连接(join)function。
n表示确认input文件的总数。
v意味着有video ? 使用0 =没有video,1 =包含video。
一种手段有audio ? 使用0 =没有audio,1 =包含audio。
-f表示强制设置文件格式(查看所有支持的格式,使用ffmpeg -formats
)
-vn表示禁用video(也可以禁用audio,如果不需要)
-y表示覆盖输出文件(如果输出文件已经存在)。
有关更多信息:使用ffmpeg -h full
打印所有选项(包括所有格式和编解码器特定选项,很长)
对于MP4文件:
如果他们不完全相同(100%相同的编解码器和相同的分辨率)的MP4文件,那么你必须首先将它们转码为MPEGstream:
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
结果 :输出将像第一个文件(而不是第二个文件)
对于MP4文件
对于.mp4文件(我从DailyMotion.com获得:一个50分钟的电视节目,只能下载三部分,作为三个.mp4video文件)以下是Windows 7的有效解决scheme,并不涉及重新编码文件。
我重命名了文件(如file1.mp4 , file2.mp4 , file3.mp4 ),使得这些部分以正确的顺序查看完整的电视剧集。
然后我创build了一个简单的batch file (concat.bat),其内容如下:
:: 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
batch file和ffmpeg.exe必须放在与要join的.mp4文件相同的文件夹中。 然后运行batch file。 通常运行时间不到十秒钟。
有关ffmpeg中各种连接方式的详细文档可以在这里find 。
你可以使用'Concat filter'来快速连接。
它执行重新编码。 当input具有不同的video/audio格式时,此选项是最好的。
连接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
这适用于相同以及多个input文件types。
这是一个脚本,我把几个GoPro mp4连接成一个720p mp4。 希望有帮助。
#!/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}
基于rogerdpack和Ed999的回应,我创build了我的.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
它将当前文件夹中的所有*.mp4
文件joined-out.mp4
在Mac上testing。
结果文件大小是我的60testing文件的确切总和。 不应该有任何损失。 正是我所需要的
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