程序 FFmpeg 准确切割视频问题,请大神指教?

2021-11-30 09:58:49 +08:00
 qin20

如题,我在项目开发过程中,使用 FFmpeg 来批量处理视频,但是发现 FFmpeg 剪切的视频并不能按照传参的开始时间和结束时间去切割视频,原因是关键帧的问题,比如我需要切割 5 到 7 秒的视频片段

ffmpeg -i a.mp4 -ss 00:00:05 -to 00:00:07 -c copy -o out.mp4

FFmpeg 会自动寻找5秒和7秒附近的关键帧,并从关键帧的位置去切割,导致视频最终的时间可能是00:00:04 ~ 00:00:06这种,导致切出来的视频有时候声音被切了一半

我知道在切割的时候使用重新编码可以准确切割,但是重新编码遇到几个 G 的视频文件时,切割两秒的视频,就需要处理好几分钟,在批量切割的需求下(几百个视频片段),完全达不到性能要求

我想知道这几个问题:

  1. 有没有一款软件可以替代 FFmpeg 实现准确切割的功能
  2. 如果使用 FFmpeg ,能不能拿到 FFmpeg 它实际切割的关键帧的时间,这样方便我快速重新编码调整切割的误差
8733 次点击
所在节点    FFmpeg
67 条回复
Rheinmetal
2021-11-30 12:17:38 +08:00
patch ffmpeg 只重新编码两头关键帧以外的地方
misdake
2021-11-30 12:23:41 +08:00
1. 先找到关键帧
网上找的命令,比如
>ffprobe -loglevel error -skip_frame nokey -select_streams v:0 -show_entries frame=pkt_pts_time -of csv=print_section=0 input.mp4
得到关键帧的时间戳,只是感觉输出不是很稳定,会有数字之外的数据,可能要多调试兼容

2. 粗切
ffmpeg 用 -c copy 的时候,手动指定前后的关键帧的时间戳,这样应该就会从指定的帧开始。至少我实验下来开始的关键帧是准的,结束的关键帧不稳定,可能还会多几帧。

3. 精切
接着就可以用重编码的方法来切到指定帧了。
qin20
2021-11-30 12:54:50 +08:00
@vanton 因为粗切也无法控制时间,然后就没有办法去实行精确切,不知道我这样说你理解吗,只要不知道切出来的实际时间,就无法去控制
qin20
2021-11-30 12:55:28 +08:00
重新编码耗时太久了
qin20
2021-11-30 12:56:16 +08:00
@JerryV2 我把所有的帧信息都解出来了,仍然无法找出是哪个关键帧,其实我也是初学。。。很多东西没有理解
qin20
2021-11-30 12:57:00 +08:00
@wszgrcy 能不能帮忙给个链接
qin20
2021-11-30 12:57:08 +08:00
@zouri ok ,我试试
qin20
2021-11-30 12:59:05 +08:00
@3dwelcome 我知道无损压缩算法,现在就是要解决这个引发的问题
qin20
2021-11-30 12:59:56 +08:00
@ksword 不一定是要 copy ,只要可以完成,并且耗时不这么长,就 ok
qin20
2021-11-30 13:03:21 +08:00
@misdake 谢谢,这个我试过了,关键帧信息不稳定,比如现在我要从 10s 开始切,那么我要去算出离 10s 最近的一个关键帧。。。
记录下这个误差,最后在调整,太难了,而且那个命令输出的关键帧感觉不是很准确
所以我说 ffmpeg 能不能再切的时候把它实际切割的关键帧的时间返回给我,我拿到这时间,在做一个调整,就可以得到精确的视频,这样最方便
misdake
2021-11-30 13:08:23 +08:00
@qin20 可以试试拉 loglevel ,然后监听类似于 [mov,mp4,m4a,3gp,3g2,mj2 @ 000001f53b1ae8c0] stream 0, sample 450, dts 14933333 的数据,就能知道他在复制那些帧
misdake
2021-11-30 13:40:17 +08:00
“重新编码遇到几个 G 的视频文件时,切割两秒的视频,就需要处理好几分钟,在批量切割的需求下(几百个视频片段),完全达不到性能要求”

这个问题我没有遇到哦,我从一个 13 分钟长、平均码率 4.5Mbps 的视频中,截取比较靠后的 1 秒钟
ffmpeg -ss 700 -to 701 -i a.mp4 out.mp4
用 measure-command 测了一下运行时间不到 0.7 秒
hazardous
2021-11-30 13:52:23 +08:00
我的思路是:其实只有开头和结尾与关键帧不对齐的那两个 gop 是需要重编码的,而中间的绝大部分直接 copy 就可以。具体就是把视频分成三段,第一段是开始点到下一个关键帧,第三段是结束点前的一个关键帧到结束点,这两段重编码,中间的 copy ,最后三段合并。
Natsumoku
2021-11-30 14:04:02 +08:00
@coderluan lossless-cut 绕不过关键帧的限制,在 UI 上把时间轴放大是可以看到一个个关键帧的,输出的时候不管怎么设置都没法精确到两个关键帧之间。
事实上有一个官方 issue 跟踪的就是如何解决这个问题: https://github.com/mifi/lossless-cut/issues/126
qin20
2021-11-30 14:19:33 +08:00
@misdake 我把日志全都拉出来了,loglevel 全开,然而没有找到,太多了,所以想问问有没有知道是 log 里面的哪个信息,能拿到实际的切割的关键帧。。。
qin20
2021-11-30 14:27:53 +08:00
@misdake 你测试的命令只有 0.7 秒确实比我电脑上运行的快,但是你这个只是使用的 copy 模式,得出的开始时间和结束时间就是刚开始说的那个不准确问题,我说的久的情况,是为了得到准确的开始和结束,而用的重新编码模式,要加上输出命令 ffmpeg -i a.mp4 -ss 700 -to 701 -c:v libx264 -c:a copy out.mp4 ,这样就会比较慢
qin20
2021-11-30 14:30:28 +08:00
@Natsumoku 你了解剪映之类的软件是如何切割的吗?他们切割起来好像挺准确的啊,而且他们的视频感觉导入的速度非常快,一下子就解码然后放到视频轨道上了
qin20
2021-11-30 14:32:12 +08:00
@hazardous 思路不错,如何取得这三段视频的信息呢,有没有好的思路
xuhaoyangx
2021-11-30 14:32:43 +08:00
copy 不可能准确切的,比如 26x 的预测帧怎么切,切不了,只能找关键帧。

@qin20 剪映切割只是记录了,你切的位置,并没有对原视频进行切割,只有最后输出的时候,根据操作记录去进行合成输出
xuhaoyangx
2021-11-30 14:33:55 +08:00
建议你出门搜 I 帧、P 帧、B 帧、GOP 、IDR 和 PTS, DTS 之间的关系

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/818943

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX