FFMPEG 视频分割和合并

使用FFMPEG可以很方便的对视频文件进行分割和合并处理,特别是某些视频文件较大较长,需要分割成多个不同长度的短片的时候。可以通过FFMPEG的copy命令无损的切割视频文件,达到快速分割的效果。

具体的CMD命名如下:

ffmpeg -ss 00:00:00 -t 00:00:10 -i input.mp4 -vcodec copy -acodec copy output.mp4

其中,
-ss 指定从00秒时间开始start,如果从视频中间开始则需要准确填写具体的时间。这个FFMPEG会根据视频编码块chunk自动调整时间到关键帧I帧,根据原始视频文件最大编码区块时长会最多可能误差好几秒,如果需要准确控制编码时间,需要强制精确控制时间的话,可以上FFMPEG官网查一下重编码参数。

-t 指定需要截取多长时间time,可以简化为-to 截至特定时间
-to 如果输入时间是to则是到00:00:10时间停止
-i 指定输入文件

这个命令处理视频文件非常快,中间约等于没有解码、编码过程,基本等同于硬盘文件拷贝速度。

去除视频文件中的声音或图像

去除视频文件中的声音或图像,只保留静音画面或音频文件。当输出选择-vn无图像的文件时,可以将输出文件格式设置为output.m4a或output.aac,都是纯粹的音频文件。如果想将视频的音频部分导出为MP3,则需要设置音频编码器-c:a lame,利用lame编码器重编码为MP3格式。
另外,如果只想要音频或视频文件,可以将-vcodec或-acodec改成-vn 或-an。

将视频文件转为关键帧I帧编码的中间文件

如果要求精确分割时间,那么就要将输入的视频先转换成所有的帧都为I帧的关键帧视频。这一步可以用手机或电脑的硬件编码,利用CPU或GPU或SoC中硬件编码器快速完成编码,硬件编码器不能编码B帧的特性可以最大化发挥硬件编码的高速特点,记得把图像质量参数选高点,硬件编码的质量比软件编码差很多。

ffmpeg -i input.mp4 -sameq -intra output.mp4

其中,
-i 输入,后面是空格,紧跟着就是输入视频input.mp4文件;
-sameq 表示保持同样的视频质量;
-intra, 帧内编码,即将所有帧都转为关键帧;
output.mp4 输出文件名。
注意视频全部转为关键帧会导致视频文件非常大,最好先截取略大于目标长度的视频,然后再转化为关键帧编码的中间视频文件。

如:ffmpeg -i ./inputVideo.mpg -sameq -intra ./temp_output.mpg
注意,这里./表示下一级文件夹中的inputVideo.mpg视频文件。
然后,再将得到temp_output.mpg作为输入,就可以精确控制视频剪切时长了。

注意,新版本可以参考下面的命令

ffmpeg -i output.mp4 -strict -2  -qscale 0 -intra keyoutput.mp4

合并视频

分段切割准备

先分别将多个需要合并的视频进行分割,将需要合并的部分单独截取出来。

ffmpeg -ss 00:00:00 -t 00:00:30 -i input1.mp4 -vcodec copy -acodec copy SplitPart1.mp4

//将第一段视频input1.mp4截取从0秒开始的30s视频输出至SplitPart1.mp4片段。
这里也可以直接写-c copy,同时设定视频编码器和音频编码器为直接复制。

ffmpeg -ss 00:00:30 -t 00:00:15 -i input2.mp4 -vcodec copy -acodec copy SplitPart2.mp4

//将第二段视频input2.mp4截取从30秒开始的15秒的视频输出至SplitPart2.mp4片段

视频片段合并

ffmpeg -f concat -i list.txt -c copy concat.mp4

使用concat参数进行视频合并,通过在list.txt文件中对要合并的视频片段进行说明,高速FFMPEG需要合并的视频文件。
内容如下

file ./SplitPart1.mp4
file ./SplitPart2.mp4

其他常用参数

虽然FFMPEG功能强大,但通过命令行进行参数控制,难免操作起来不那么方便,以下简单介绍部分常用命令。
去掉视频中的音频-an,去掉视频-vn,不询问直接覆盖输出的视频文件(有时会多次操作,因为之前已经输出相同名字的文件,如果不强制覆盖,软件会停下来等待确认,再进行后续操作)。

视频编码参数

-vn 关闭视频输出,只保留源文件的音频。
-ss position 可以直接设定开始时间为10秒,也可以设置转码开始时间 [-]hh:mm:ss[.xxx]的格式。
-t duration 可以设定转换时长为20s,也可以设置具体截止时间 hh:mm:ss[.xxx]格式。
-to position 转码截止时间点hh:mm:ss[.xxx]格式
-vcodec 视频编码选项,后面跟copy表示直接复制拷贝,也写作-c:v,与之相对的是-c:a音频编码器。
-acodec 视频编码选项,也写作-c:a,后面跟copy表示直接复制拷贝,不重新编码。
-y 设定不需要询问直接覆盖现有文件。不确定的话不要选,可能把需要的文件覆盖掉。
-vcodec xvid 使用xvid压缩,还可以指定libx264或libx265,实现x264或x265编码,和独立的x264、x265编码效果完全相同(FFMPEG内部集成了x264和x265编码器)。也写作-v:c libx264或-v:c libx265。
-s 320x240 指定分辨率,iw宽度ih高度。
-vf scale 960:540 设定输出分辨率为 960x540。如果是 960:-1 则是按原始宽高比变化设置高度。
-aspect 16:9 设定输出比例为 16:9。
-r 30 设定输出帧率是 30 fps 设置帧频,默认25。这个不用设置,通常由FFMPEG自动选择适宜的帧率即可,很多手机拍摄的视频帧率是30fps或60fps,指定帧率不恰当的话,FFMPEG会大量丢弃时间戳不匹配的帧。
-vf fps 30 设定输出帧率是 30效果与-r一样。
-preset:v slow 设定视频编码preset参数为slow。由快到慢可选 ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow;placebo。
-pix_fmt yuv420p 设定输出视频帧色彩格式为yuv420p 需要视频编码器支持。
-b <比特率> 指定压缩比特,这个是设置视频文件的码率,除非必须控制特定码率,否则不推荐采用此参数。
-b:v 1500K 输出视频码率是 1500K。
-crf 视频质量控制参数,x264编码默认为23,x265编码默认为28。一般crf数值增加6,视频体积减小一半,crf减小6,视频体积增加一倍。没有特别要求的话,直接采用默认参数即可,PT圈重编码的时候,多采用crf=15-19的实现极其优秀的画质。
-c:v hevc_nvenc 设定视频编码器为 nvidia硬件h265编码器 与-vcodec选项相同 或者设定为 copy 代表复制原始视频流
-maxrate bitrate设置视频最大码率,主要是对于播放器buffer区大小的控制,防止码率溢出,通常不用单独设置。
-bufsize size 设置码率控制缓冲区大小
-vcodec codec 强制使用codec编解码方式。 如果用copy表示原始编解码数据必须被拷贝。
-sameq 使用同样视频质量作为源(VBR)
-pass n 选择编码次数1或2或3。常说的2PASS就是这项,主要是对于需要设置特定码率的时候,采用2PASS可以让FFMPEG码率控制更为合适,提高编码质量。FFMPEG会在第1遍编码时生成统计信息,然后第2遍编码时按照设置的码率进行精确的码率。

音频编码相关参数

-acodec aac 设定声音编码
-an 关闭音频输出。
-ac <数值> 设定声道数,1就是单声道,2就是立体声
-ar <采样率> 设定声音采样率,PSP只认24000
-ab <比特率> 设定声音比特率,参考MP3文件常用码率128-320 Kbps,一般认为320Kbps的MP3相当于无损CD音质,128Kpbs音质是以往网络较为优质的效果。默认-c:a 采用AAC编码器,大约可以省30%-50%码率,设置96-320Kbps都是合理的,如果音乐多则码率高点,如果只有人声对话,码率低点也不影响。取128-192Kbps总是很合理的。

ffmpeg -i input.mp4 -vcodec copy -an output.mp4
// -an去掉音频,提取视频文件;
ffmpeg -i input.mp4 -vn output.m4a
// -vn去掉视频;提取音频文件,输出为m4a纯音频文件;
ffmpeg -ss 0:10:10 -t 0:0:20 -i input.mp4 -vcodec copy -acodec copy output.mp4
// 剪切视频  -ss 开始时间; -t 持续时间
ffmpeg –i input.mp4 -t 00:00:30 -s 320x240 output.mp4 
// -s 设置分辨率320x240;
ffmpeg -i input.mp4 -vf scale=iw/2:-1 output.mp4
// 缩放视频,iw是输入视频宽度,iw/2就是一半;-1 为保持宽高比,让FFMPEG自动设置高度值
ffmpeg -i input.mp4 -ss 0:0:10 -t 10 -s 320x240 -pix_fmt rgb24 output.gif
// 将视频转为gif

复制MP4文件的元数据

手机拍摄的视频文件包含大量元数据metadata,记录了视频拍摄时间、拍摄地点GPS坐标等,当使用FFMPEG进行重编码mp4时,metadata中的GPS定位数据丢失。尝试使用-map_metadata -1 -movflags faststart复制GPS坐标等metadata,结果失败了。

苹果手机拍摄的视频文件,丢失的GPS坐标信息是com.apple.quicktime.location.I & ©xyz
安卓手机拍摄的视频文件,同样也会丢失GPS数据

ffmpeg -i source.mov -r 60 -c:v libx264 -c:a aac -map_metadata -1 -movflags faststart destination.mp4

解决办法是,使用ExifTool实现metadata的复制,利用exiftool将全部ALL的metadata复制到转码后的视频文件中。
ExifTool官网
https://exiftool.org/

exiftool.exe -TagsFromFile .\sourceVideo.mp4 -All:All .\TargetVideo.mp4

批量处理手机视频文件并复制元数据

  1. 将FFMPEG和EXIFTOOL添加到系统环境变量(如果未添加,则需要填写完整路径)。
  2. 将需要转码的视频文件存放在一个文件夹A。
  3. 在视频文件夹A添加BAT批处理,写入以下命名(其中转码的视频参数可以自行设定)。
  4. 双击BAT一键完成全部‘视频转码’和‘metadata复制’。
md output
for %%i in (*.mp4) do ffmpeg.exe -noautorotate -i ".\%%i" -c:v libx264 -c:a copy  ".\output\%%i"
for %%i in (*.mp4) do exiftool.exe -TagsFromFile ".\%%i" -All:All ".\output\%%i"  -overwrite_original

创建输出文件夹output;
将所有视频采用x264重编码,复制音频,并存入output文件夹;
将所有视频文件的metadata复制到转码后的视频文件中。

生成动图

将视频转换webp或gif文件,可以获得静态图或动态图。例如,将视频前5秒截取生成webp动图。

ffmpeg -ss 0:00:00.000 -t 5 -i input.mp4 output.webp
ffmpeg -ss 0:00:00.000 -t 5 -i input.mp4 output.gif
ffmpeg -i 1.apng -lossless 1 2.webp
ffmpeg -i 1.apng -compression_level 3 -q:v 70 2.webp