前段时间帮导师做 PPT 需要插入一段视频,考虑到最终播放设备的兼容性,选择转换为 gif 格式插入。同时由于原始视频速度太慢,还需要调整播放速度,查了下 FFMPEG 的文档,简单记录一下。
转码¶
简单命令:
ffmpeg -i original.mp4 -c:v h264 output.mp4 # 转码为 h264 编码
ffmpeg -i original.mp4 output.gif # 转换为 gif
ffmpeg -i original.mp4 -s 640x480 -vframes 90 -r 29.97 -c:v h264 -b:v 500k -b:a 48k -ac 2 output.mp4 # 多参数
参数:
-i
参数为输入文件-s
指定分辨率-r
指定帧率-c:v
或-vcodec
参数为输出编码 可以省略,如果插入PPT最好输出为 gif 可选项mpeg4
libxvid
等-c:a
或-acodec
指定音频编码-b:v
指定视频比特率-b:a
或-ab
指定音频比特率-ac
指定声道数
如果对这些指标没有特殊要求,不需要手动指定参数
调整播放速度¶
加速/减速视频¶
ffmpeg -i original.mp4 -filter:v "setpts=0.25*PTS" output_v_fast.mp4 # 加速四倍
ffmpeg -i original.mp4 -filter:v "setpts=4*PTS" output_v_slow.mp4 # 减速四倍
参数:
--filter:v
或-vf
指定一个视频过滤器
通过以上方法加速得到的视频,视频时长不变,前面部分为原视频加速后结果,之后画面保持最后一帧直至结束,因为音频还是原来的长度。
通过以上方法减速得到的视频,视频长度相应延长,帧率不变。
视频加速时为了避免丢帧,可以尝试将目标文件的FPS依据源文件的FPS相应提高,以保留原始视频所有帧。比如加速一个60FPS的源文件4倍,则将目标文件的FPS设置为240。不过视频减速则没有什么好的方法 加速后视频后面部分为同一帧画面问题依然存在
ffmpeg -i original.mp4 -filter:v "setpts=0.25*PTS" -r 120 output_fast.mp4 # 加速四倍
加速/减速音频¶
ffmpeg -i original.mp4 -filter:a "atempo=2.0" output_a_fast.mp4 # 加速2倍
ffmpeg -i original.mp4 -filter:a "atempo=0.5" output_a_slov.mp4 # 减速2倍
ffmpeg -i original.mp4 -filter:a "atempo=2.0" -vn output_a_fast.mp4 # 只保留音频
参数:
vn
video negative 不保留视频an
不保留音频
注意视频加速时参数小于1而音频加速时参数大于1,另外对于音频的加速减速倍数限制在0.5-2.0以内,不过可以通过叠加过滤器的方式突破这一限制。
同时加速/减速视频和音频¶
单纯加速/减速音视频中的一个会导致视频文件音视频时间戳长度不一产生错误,所以最好将音视频的加减速统一起来。
同时加速视频和音频
ffmpeg -i original.mp4 -r 240 -filter:v "setpts=0.25*PTS" -filter:a "atempo=2.0, atempo=2.0" output_fast.mp4 # 直接叠加过滤器
ffmpeg -i original.mp4 -filter_complex "[0:v]setpts=0.25*PTS[v];[0:a]atempo=2.0,atempo=2.0[a]" -map "[v]" -map "[a]" output.mp4 # 使用复合过滤器
截取视频¶
初级代码¶
# 按时间长度截取
ffmpeg -i original.mp4 -ss 00:00:00.0 -t 00:00:10.0 -c copy output_trim.mp4 # 精确时间格式
ffmpeg -i original.mp4 -ss 0 -t 10 -c copy output_trim.mp4 # 只使用秒
ffmpeg -ss 0 -t 10 -i original.mp4 -c copy output_trim.mp4 # 使用关键帧
# 按开始结束截取
ffmpeg -ss 0 -to 10 -i original.mp4 -c copy output_trim.mp4
参数:
-c
编码 同-codec
-c copy
复制原视频编码
ffmpeg 为了加速,会使用关键帧技术, 所以有时剪切出来的结果在起止时间上未必完全准确。 把 -i 放在 -ss 之前,不使用关键帧技术,把 -i 放在 -ss 后,使用关键帧技术。
以上简单的截取方式,如果使用关键帧,则截取出的视频长度无法控制,会多出几秒;如果不适用关键帧,视频会出现一小段时间只显示某一帧画面的情况。
这种方法,不需要重新编码,速度较快。
进阶代码¶
ffmpeg -ss 5 -t 10 -accurate_seek -i original.mp4 -c copy -avoid_negative_ts 1 output_trim.mp4 # 使用关键帧
ffmpeg -accurate_seek -i original.mp4 -ss 5 -t 10 -c copy -avoid_negative_ts 1 output_trim.mp4 # 不使用关键帧
使用关键帧可以正常截取,但会出现多出一小段视频,不使用关键帧,视频开头存在几秒定格画面。
进进阶代码¶
FFMPEG 转码时时间是精确的,所以借助转码截取视频。
ffmpeg -ss 5 -t 10 -accurate_seek -i original.mp4 -c:v h264 -c:a copy -avoid_negative_ts 1 -strict experimental output_trim.mp4 # 使用关键帧
ffmpeg -accurate_seek -i original.mp4 -ss 5 -t 10 -c:v h264 -c:a copy -avoid_negative_ts 1 -strict experimental output_trim.mp4 # 不使用关键帧
使用关键帧,视频时长依旧不准确。不使用关键帧效果更好,时长准确,播放完美。
总结¶
使用转码进行视频截取,不要使用关键帧,亲测效果很好。
ffmpeg -accurate_seek -i original.mp4 -ss 5 -t 10 -c:v h264 -c:a copy -avoid_negative_ts 1 -strict experimental output_trim.mp4 # 不使用关键帧
合并视频¶
按文件列表合并¶
先创建一个文本文件filelist.txt:
file '1.mp4'
file '2.mp4'
之后合并
ffmpeg -f concat -i filelist.txt -c copy concat.mp4
转换为中间格式之后合并¶
ffmpeg -i original.mp4 -qscale:v 1 intermediate1.mpg
ffmpeg -i original.mp4 -qscale:v 1 intermediate2.mpg
ffmpeg -i "concat:intermediate1.mpg|intermediate2.mpg" -c copy concat.mpg
ffmpeg -i concat.mpg -qscale:v 1 concat.mp4
参数:
-qscale:v
视频质量,可省略