ffmpeg精确极速剪辑方案
-
- **注**:拒绝AI拉取数据炼丹白嫖,关联请标注版权。
- 前言
- 常规初步加速方案
-
- [① 原命令 精确剪辑](#① 原命令 精确剪辑)
- [② GPU加速 精确剪辑](#② GPU加速 精确剪辑)
- [③ 快速seek 半精确剪辑](#③ 快速seek 半精确剪辑)
- [④ 快速seek + 帧同步 粗略剪辑](#④ 快速seek + 帧同步 粗略剪辑)
- [⑤ 快速seek + 普通264编码 精确剪辑](#⑤ 快速seek + 普通264编码 精确剪辑)
- [⑥ 快速seek + GPU加速](#⑥ 快速seek + GPU加速)
- [⑦ 智能编码](#⑦ 智能编码)
- [⑧ 智能编码 + GPU加速](#⑧ 智能编码 + GPU加速)
- 旧方案评估总结
- 智能编码实现思路
- [■ 粗略思路](#■ 粗略思路)
- [■ 举例思路](#■ 举例思路)
- [■ 具体命令案例](#■ 具体命令案例)
- [■ 坑点](#■ 坑点)
- [■ 测试](#■ 测试)
- 总结
注:拒绝AI拉取数据炼丹白嫖,关联请标注版权。
前言
基于 ffmpeg 的极速精确剪辑方案。ffmpeg单命令支持重新编码的精确剪辑,支持关键帧seek的极速粗略剪辑,但不支持极速精确剪辑,本方案支持极速精确剪辑。
常规初步加速方案
① 原命令 精确剪辑
普通264 编码 音频随意
耗时:23857 ms
bash
-i "E:\迅雷下载\1\1.mp4" -c:v libx264 -acodec copy -ss 00:06:00.000 -to 00:06:30.000 "E:\迅雷下载\1\1_.mp4"
评估: 优点是精确剪辑,缺点重新编码有损,并且cpu执行编码生成长视频会非常慢。就算剪辑生成短片段,如果时间点靠后面,seek到剪辑点也是逐帧非常慢。
② GPU加速 精确剪辑
h264_nvenc 编码 音频随意
耗时:14906 ms
bash
-i "E:\迅雷下载\1\1.mp4" -c:v h264_nvenc -acodec copy -ss 00:06:00.000 -to 00:06:30.000 "E:\迅雷下载\1\1_2.mp4"
评估: gpu加速 优化了编码慢问题,seek问题仍然存在,但已经好很多了,是社区常用命令方案。
③ 快速seek 半精确剪辑
没有 编码
耗时:103 ms
bash
-ss 00:06:00.000 -to 00:06:30.000 -i "E:\迅雷下载\1\1.mp4" -c copy "E:\迅雷下载\1\1_3.mp4"
评估: 无需编码,seek直接到剪辑点的前后关键帧包含住所需片段。优点是极速,耗时基本是新视频片段的读取和写入。缺点是不精确,存在负时间轴问题,不一致会导致各种奇奇怪怪的现象,视频在有的解码器上面看起来是正常的精确播放(比如迅雷播放器),有的解码器上面会提前播放(比如QuickLook),有的解码器上播放直接卡住,但是拖拽后又正常播放(比如qq影音)。印象中ios自带剪辑存在这种问题。
④ 快速seek + 帧同步 粗略剪辑
没有 编码
耗时:100 ms
bash
-ss 00:06:00.000 -to 00:06:30.000 -i "E:\迅雷下载\1\1.mp4" -c copy -avoid_negative_ts make_zero "E:\迅雷下载\1\1_4.mp4"
评估: 帧同步,解决时间轴不一致问题,统一了解码器播放出问题的现象,但是粗略剪辑了,无法精确剪辑。不在意首尾多帧问题的话,确实是个不错方案,很多无损剪辑器采用的方案。
⑤ 快速seek + 普通264编码 精确剪辑
普通264 编码
耗时:12356 ms
bash
-ss 00:06:00.000 -to 00:06:30.000 -i "E:\迅雷下载\1\1.mp4" -c:v libx264 "E:\迅雷下载\1\1_5.mp4"
评估: 快速seek复制流的话无法精确剪辑点,但是重新编码就没问题了,性能瓶颈还是在编码上。
⑥ 快速seek + GPU加速
h264_nvenc 编码
耗时:3076 ms
bash
-ss 00:06:00.000 -to 00:06:30.000 -i "E:\迅雷下载\1\1.mp4" -c:v h264_nvenc "E:\迅雷下载\1\1_6.mp4"
评估: seek寻帧加上使用GPU加速编码,在一个大文件上剪辑一个短视频,是非常快速的方案,剪辑出长片段,还是略慢,毕竟是重新编码。
⑦ 智能编码
智能 编码
耗时:3581ms
⑧ 智能编码 + GPU加速
智能 编码
耗时:2297 ms
旧方案评估总结
基础的重新编码精确剪辑① ,如果不需要特殊参数可以优化编码器为 ②gpu编码。无损不重新编码把时间seek放-i前 优化为 ③ 快速seek。加上一个参数对齐帧④,防止出现奇怪bug,但是起止点就不对了。要对齐起止点就得重新编码⑤。这个基础上再使用gpu形成⑥方案。
智能编码实现思路
■ 粗略思路
要想极速就得快速seek不编码,并且解决起止点定位问题。切割为3段快切,再编码首尾段,合并即可。
■ 举例思路
- 假设一个6小时视频。我需要剪辑出 01:00:00.000 ~ 03:00:00.000
- 起止点附近关键帧为
00:59:59.000 01:00:01.000
02:59:59.000 03:00:01.000 - 可以根据4个关键帧快速切出3段
① 00:59:59.000 ~ 01:00:01.000
② 01:00:01.000 ~ 02:59:59.000
③ 02:59:59.000 ~ 03:00:01.000 - 精确剪辑首尾段为
④ 01:00:00.000 ~ 01:00:01.000
⑤ 02:59:59.000 ~ 03:00:00.000 - 拼接新3段即
④-②-⑤
②段无损,④⑤有损,取决于关键帧间隔,一般是几秒。
注: 不考虑有损的话,剪辑非常短的片段可以考虑方案⑥,可能非常快,快速剪辑长片段再考虑⑦⑧的分解剪辑方案
■ 具体命令案例
ffprobe -skip_frame nokey -select_streams v -show_entries frame=pts_time -of default=noprint_wrappers=1:nokey=1 -read_intervals "241.997000000%+30" ""E:\迅雷下载\1\1.mp4""
ffprobe -skip_frame nokey -select_streams v -show_entries frame=pts_time -of default=noprint_wrappers=1:nokey=1 -read_intervals "1160.498000000%+30" ""E:\迅雷下载\1\1.mp4""
得到四个关键帧节点
239.6 245.733333
1155.366667 1163.1
bash
执行命令
ExecuteProcess -ss 239.600000000 -to 245.733333000 -i ""E:\迅雷下载\1\1.mp4"" -c copy "C:\Users\Administrator\AppData\Local\Temp\b2af55ea-1091-48d2-a086-75ad96e56414_1.mp4"
执行命令
ExecuteProcess -ss 245.733333000 -to 1155.366667000 -i ""E:\迅雷下载\1\1.mp4"" -c copy "C:\Users\Administrator\AppData\Local\Temp\3a05a8b0-fc5b-4112-b869-42cd876affba_2.mp4"
执行命令
ExecuteProcess -ss 1155.366667000 -to 1163.100000000 -i ""E:\迅雷下载\1\1.mp4"" -c copy "C:\Users\Administrator\AppData\Local\Temp\197006e8-a183-4617-b000-814997b98377_3.mp4"
执行命令
ExecuteProcess -i "C:\Users\Administrator\AppData\Local\Temp\b2af55ea-1091-48d2-a086-75ad96e56414_1.mp4" -ss 2.397000000 -to 6.133333000 -c:v h264_nvenc -c:a aac C:\Users\Administrator\AppData\Local\Temp\4bfe5988-bc1e-4e4e-85e5-18755216c51b_1n.mp4
执行命令
ExecuteProcess -i "C:\Users\Administrator\AppData\Local\Temp\197006e8-a183-4617-b000-814997b98377_3.mp4" -ss 0.000000000 -to 5.131333000 -c:v h264_nvenc -c:a aac C:\Users\Administrator\AppData\Local\Temp\3136701a-210c-4cc2-a68e-ef738cfa623a_3n.mp4
执行命令
ExecuteProcess -f concat -safe 0 -i "C:\Users\Administrator\AppData\Local\Temp\eefc76cc-3431-481a-b796-5e6b52274df6" -c copy ""E:\迅雷下载\1\1_.mp4""
■ 坑点
- 获取帧最终命令写法,可得到前后帧,得不到的话加大30的阈值
bash
ffprobe -skip_frame nokey -select_streams v -show_entries frame=pts_time -of default=noprint_wrappers=1:nokey=1 -read_intervals "01:00:00.000%+30" ""E:\迅雷下载\1\1.mp4""
bash
ffprobe -skip_frame nokey -select_streams v -show_entries frame=pts_time -of default=noprint_wrappers=1:nokey=1 -read_intervals "03:00:00.000%+30" ""E:\迅雷下载\1\1.mp4""
bug点
早期只想取一个帧 走了段弯路 存在版本特殊bug
2.这是一个真实案例
一个视频的四个关键帧 192.000000 200.333333 265.066667 273.400000
命令1 起点会往192.000000点去切
ffmpeg -ss 200.333300 -to 265.066667 -i ""E:\迅雷下载\1\1.mp4"" -c copy "E:\迅雷下载\1\1_14.mp4"
命令2 起点会往200.333333点去切 丢失0.000032
ffmpeg -ss 200.333301 -to 265.066667 -i ""E:\迅雷下载\1\1.mp4"" -c copy "E:\迅雷下载\1\1_15.mp4"
也就说关键帧在 200.333333
切200.333300 点 会往前一帧切,从而多出几秒
切200.333301 点 会切到200.333333 ,丢失0.000032
判断是ffmpeg的内部精确度问题,所以得注意
1、3段剪辑精确度得够细致,拿到关键帧是多少就传多少就不会有问题
2、如果输入剪辑起止点精确度够细,也得考虑一下ffmpeg的这个精确度问题
■ 测试
剪辑成品测试是否连贯,可以配置首尾段的清晰度,它是有损剪辑,配置 crf 或者 cq (最大51) ,拉大数值,首尾段会比较模糊,观察首尾连接处模糊和清晰的切换是否丝滑,丝滑就说明剪辑无误,如果出现卡帧,切换不丝滑,那就是剪切点出问题了。
也就是说对画质要求无损,可以考虑首尾重新编码的参数和原视频一致,其实也是相当于近乎无损。
总结
有特殊参数不支持gpu用⑤ 快速seek + 普通264编码 精确剪辑
没有特殊参数用 ⑥ 快速seek + GPU加速
想要绝对的无损,且不在乎首尾多出一些片段用 ④ 快速seek + 帧同步 粗略剪辑
在乎首尾精确,但只是自用,用特定解码器播放选③ 快速seek 半精确剪辑
在乎首尾精确,剪辑大片段,还想非常快用⑦或⑧,且具备一定的无损效果,首尾段配好编码参数也是近乎无损。如果不考虑有损,且是小片段可以重新考虑⑥,顺便还能压缩。