前言
前面有一段时间需要对视频做一些简单的处理,所以就去查了一下一些常用的视频处理工具,因为不想再另外装个什么软件,所以就决定直接采用 FFmpeg 了,毕竟其它的一些视频处理软件也极有可能只是对 FFmpeg 进行一些图形化界面的封装而已。
而在查找 FFmpeg 相关资料的时候,也同时发现了 Libav , 对于 FFmpeg 和 Libav Shaun 只想说,开源界的战争总是这么莫名其妙,有各种各种一些奇怪的原因(或许大佬们都是各有各的脾性吧 ╮(╯▽╰)╭),像两个小飞机的战争也是如此,不过神仙打架,凡人享福也好 ~\(≧▽≦)/~。神仙们的想法我等凡人是无法揣测了,不过这种事还是少出点为好,不然下次变为小鬼遭殃就不好了。
使用 FFmpeg 而不是 Libav 是因为 FFmpeg 的相关资料相对来说要多很多;而且Libav 更新的特性,FFmpeg 全都支持;更重要的是 FFmpeg 是更新特别频繁,差不多是日更了,几乎每天都会发布一个稳定版;而且从两者的下载页面来看, FFmpeg 好像更会照顾跨平台用户一点。下文主要是对 FFmpeg 的部分命令进行记录总结。
Shaun 的系统环境为 Win10 1607,测试的 FFmpeg 版本为 ffmpeg-20180429-19c3df0-win64-static。
在 Win10 下使用 FFmpeg 前首先需要配置系统环境变量,Windows 下 FFmpeg 的安装是下载完 Windows 版编译好的 FFmpeg 压缩包后直接解压即可,将解压后的 FFmpeg 文件夹中的 bin 目录添加到系统环境变量 Path 中,不然系统会无法找到 ffmpeg 命令。
提取命令
FFmpeg 的提取命令的参数很多,因此可以使用不同参数排列组合达到不同的提取效果,具体如下:
1 | # (1)快速提取video.mp4从第一分钟开始持续两分钟的视频,即到第三分钟,并将提取结果输出为cut.mp4 |
以下为各参数的含义:
-i
:用法为-i INPUT_VIDEO
,代表输入的视频,该视频应为 MPEG 编码(h.264, MPEG4/divx/xvid, MPEG2; MP2, MP3, AAC) ;-ss
:用法为-ss START_TIME
,代表提取的开始时间,时间格式有两种写法:1、纯数字格式,以秒为单位(eg:-ss 90
,代表从第90秒开始提取);2、时:分:秒 格式(eg:-ss 00:01:30
,代表从 0 时 1 分 30 秒开始提取);-to
:用法为-to STOP_TIME
,代表提取的结束时间,时间格式同样有两种写法:1、纯数字格式,以秒为单位(eg:-to 180
,代表第180秒结束提取);2、时:分:秒 格式(eg:-to 00:03:00
,代表 0 时 3 分 00 秒结束提取);-t
:用法为-t DURATION_TIME
,代表提取的持续时间,时间格式同样有两种写法:1、纯数字格式,以秒为单位(eg:-to 180
,代表提取持续180秒);2、时:分:秒 格式(eg:-to 00:03:00
,代表提取持续 0 时 3 分 00 秒);-c
:用法为-c CODEC
,代表音视频编码格式(若 CODEC 为copy
则代表输出视频的音视频编码格式与原视频一样),其实-c
是-codec
的缩写,其中包含音频编码参数-acodec
和 视频编码参数-vcodec
;-copyts
:保持原有时间戳,即使当-ss
在-i
之前时,仍使-t
和-to
保持原有效果,不会被同化;-avoid_negative_ts
:当开启该参数时,提取视频会找到首尾的相邻关键帧(这样会造成提取时间不精确),补全视频,当-ss
在-i
之前时该参数默认开启;-accurate_seek
:使提取时间更精确,在转码时该参数默认启用。- 更多参数可参考:Format-Options 。
※注: 1、-t
和 -to
不能同时使用,若同时使用,将以 -t
为准; 2、当 -ss
在 -i
之前时,可以实现快速提取,但提取的时间点不精确,此时-to
和 -t
的效果一样,都表现为 -t
,此时可以加上 -copyts
参数使两者效果不一样; 3、当 -ss
在 -i
之后时,提取的时间点比较精确,但提取速度比较慢。
以上命令(1)、(2)是一样的提取结果,命令(3)的 -t
和 -to
会产生不一样的结果,(6)的 -t
和 -to
会产生一样的结果。因此若只考虑速度,可以使用命令(3),若需使提取时间精确,则需使用命令(4)和(5)。
PS:当然还有一种更精确的方式,通过命令 ffmpeg -i input.mp4 -strict -2 -qscale 0 -intra output.mp4
将输入视频由原来的帧间编码转换为帧内编码,使每一帧都成为关键帧,如此转换之后再进行提取,可使提取时间十分精确,但该转换方式会造成视频文件空间成倍增大。
合并命令
FFmpeg 的合并命令大概有 4 种,可参考: FFMpeg无损合并视频的多种方法 。这里主要介绍两种:
方法一:使用 FFmpeg concat 分离器(推荐)
该方法使用命令为:ffmpeg -f concat -i filelist.txt -c copy output.mp4
,其中 filelist.txt 文件最好和待合并的视频在同一个文件夹中,文件中内容就是待合并的视频的描述,具体内容如下:
1 | file 'input1.mp4' |
或
1 | file ./input1.mp4 |
※注: 待合并的视频文件名最好由英文、数字、连接符(-
)或下划线(_
)组成,且中间最好不要有空格,不然可能会因为文件名而在合并时出现一些奇怪的错误。
方法二:利用中间格式合并
所谓利用中间格式进行合并是因为可能有些待合并的视频编码不一致,这时采用方法一可能无法进行合并,这时需要对待合并的视频的进行统一转码,都转成同一个编码格式。若要采用这种方法,建议都转成 mpg 格式,因为 mpg 格式可以直接 cat 命令进行合并,具体如下:
1 | # 将input1.avi转成intermediate1.mpg,输出视频质量为1 |
其中参数 -qscale
是指使用固定的视频量化标度 ,取值范围为 0.01 ~ 255 ,越小代表质量越好,一般推荐取值为 2 ~ 5,实际使用不能超过 50, -qscale:v
代表设置视频输出质量。
PS: 方法一为无损合并,方法二为有损合并。
后记
以后有用到新的命令再继续记录吧 ↖(^ω^)↗ 。纯命令行不太方便的话,可以试试 Avidemux,全平台通用。
参考资料
[1] ffmpeg Documentation(https://ffmpeg.org/documentation.html)