视频合并
FFmpeg concat 分离器
file 'input1.mkv' file 'input2.mkv' file 'input3.mkv'
然后:
ffmpeg -f concat -i filelist.txt -c copy output.mkv
1. 原理 比如我有三个视频片段,想要合并成一个完整视频。视频片段的文件名如下: media_w384769807_0.ts media_w384769807_1.ts media_w384769807_2.ts 那么只要新建一个文本文件,命名为list.txt,写入如下内容: file 'media_w384769807_0.ts' file 'media_w384769807_1.ts' file 'media_w384769807_2.ts' (注意:文件名前面的file是关键字,不能省略)然后用下列命令行调用ffmpeg: ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4 命令结束后,就生成你要的结果output.mp4。 顺带一说:在我认识ffmpeg这一强大工具之前,我一直用copy /b的方法合并视频。copy /b的结果,看是能看,跳着看就会花屏——原因不用想也明白,原来片段里有些文件头不是视频流数据,强行合并进来,当视频流解析当然要出错了。 2. 用批处理将上述过程自动化:第一步尝试 话虽如此,总不能让我每次合并视频的时候都新建一个文本文件,打上几行字,然后再去命令行终端调用ffmpeg吧!没错,我们可以用批处理来做这些事,比如上面建立文本文件这一步,可以用下面的批处理命令完成: (for %%a in (*.ts) do @echo file '%%a') > list.txt 这个命令执行时,它会穷举本目录下所有.ts文件的文件名,然后逐行以 "file '文件名'"的格式输出到文件list.txt中。 3. 解决文件名穷举次序与片段次序不符的问题 上面所说的方案,当片段数比较少的时候是正确运行的。但片段数比较多的时候,比如有下列超过10个的片段: media_w384769807_0.ts media_w384769807_1.ts media_w384769807_2.ts ... media_w384769807_9.ts media_w384769807_10.ts 那么当你执行: (for %%a in (*.ts) do @echo file '%%a') > list.txt 再打开list.txt文件一瞧,就会发现内容是这样: file 'media_w384769807_0.ts' file 'media_w384769807_1.ts' file 'media_w384769807_10.ts' file 'media_w384769807_2.ts' file 'media_w384769807_3.ts' file 'media_w384769807_4.ts' file 'media_w384769807_5.ts' file 'media_w384769807_6.ts' file 'media_w384769807_7.ts' file 'media_w384769807_8.ts' file 'media_w384769807_9.ts' 发现了什么?第10个片段跑到第2个片段的前面去了!而ffmpeg并没有智能,它只会忠实按照你提供的列表顺序来拼接视频,结果当然不对了。 顺便要说的是,许多人津津乐道的copy /b *.ts merge.mp4之类的命令也存在同样的问题,不要以为“能用一句命令解决任务”。问题关键在于,当DOS使用通配符 * 来穷举文件名时,用的是字典顺序而不是数字顺序,按这种顺序,当比较到从左往右第一个不相等的字符时,一看2比1大,就不管1跟2的后面还跟着多少个字符了,于是10就总在2的前面了。 那么,怎样解决这个问题呢?我们可以用带参数/l的for命令来生成数字列表。比如如果我要把上面那11个片段生成次序正确的列表,可以采用: (for /l %%i in (0,1,10) do @echo file 'media_w384769807_%%i') > list.txt 4. 较为完善的方案 用for /l解决了列举次序的问题,可是又出来两个新问题: (1) for /l 只能生成单纯的数字,而不能列举文件名,于是我们不得不在%%i的前面加上“media_w384769807_”这个前缀才能成为完整的文件名,而我下次运行时,面对的也许是另外一批片段,具有完全不同的前缀,于是我只得修改批处理。 (2) 片段的个数也是会变的,比如下一次的片段也许是从_0开始,到_15结束,那我的批处理命令又得对应改为for /l %%i in (0,1,15) ....。 怎样能让批处理适应这些变化情况,而不用每次修改批处理本身?要达到这一目的,涉及的是如何提取文件名的不变部分,以及自动判断有多少个片段要合并。这个任务的解决办法就因具体情况而异了,在这里,我只拿上面说过的例子来讲:比如在像“media_w384769807_0.ts”的文件名中,前缀“media_w384769807_”是不变部分,而“0”是序号。那么我只要把最后的序号部分切掉,就得到不变部分,把这个不变部分拼接上由for /l自动生成的序号就行了。注意到不变部分的最后一个字符是“_”,我只要随便拿一个文件名来,依次切掉尾字符,切到“_”为止就行了。另外,用于列举文件名的for命令虽然不能按片段的正确次序,却可以用于统计有多少个片段,设置一个计数器每次加一就行了。这样,我们就得到如下的代码: @echo off :: 因为下面循环每一轮都改变file_prefix的值,所以用了enabledelayedexpansion setlocal enabledelayedexpansion set aaa=%random% set bbb=%random% set /a last_index=-1 for %%a in (*.ts) do ( set file_prefix=%%~na set /a last_index+=1 ) :cutright if !file_prefix:~-1! neq ^_ ( set file_prefix=!file_prefix:~0,-1! goto cutright ) (for /l %%i in (0,1,%last_index%) do @echo file '%file_prefix%%%i.ts') > %aaa%.txt :: 这里可以加一句pause,用于确认列表文件是否正确,如不正确按Ctrl+C ffmpeg -f concat -safe 0 -i %aaa%.txt -c copy %bbb%.mp4 erase %aaa%.txt endlocal echo on
FFmpeg视频转码技巧之-crf参数
© 版权声明
本站网络名称:
乐商网络
本站永久网址:
https://ishoud.com
网站侵权说明:
本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长QQ810066660删除处理。
1 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
2 本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
3 本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。
1 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
2 本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
3 本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。
THE END
暂无评论内容