#1 - 2022-3-21 18:49
萌豚豚
ffmpeg -ss start_time -to end_time -i input.mp4 output.mp4

FFmpeg "-c copy" 切割视频快速又无损,但是只精确到关键帧;普通切割视频精确到帧但需要整段全部重新编码,既耗时又损失了点画质。
那么有没有办法能只重新编码两头分割点到最近的关键帧而中段直接复制呢?合并视频不太用重新编码,这样既精准又省时又不用全部重新编码,我想这是能手动做到的,那么有没有方便快捷的方法能做到这点呢?我没有搜索到相关的方法,所以在此请教各位程序员大佬,谢谢!
#2 - 2022-3-21 19:33
#2-1 - 2022-3-21 20:09
萌豚豚
我希望用 FFmpeg 和命令行来解决(bgm39)
#3 - 2022-3-21 20:33
(Make Bangumi Great Again!)
MP4只切割无法精准到帧。H264的机制问题
而你一旦视频头尾重编码了,想要和中间段另一个压制参数的视频拼一起,大概率会产生马赛克之类的问题。
#3-1 - 2022-3-21 20:58
萌豚豚
感谢解答!那能不能识别出原视频的压制参数然后设置成一样的切出来再拼?(bgm39)
#3-2 - 2022-3-21 21:02
chitanda@Lv2
萌豚豚 说: 感谢解答!那能不能出别出原视频的压制参数然后设置成一样的?
没尝试过,但实际来说应该没这么简单。虽然x264压制的视频会留参数在视频信息里,但你ffmpeg能不能调用是一回事,调用了能不能用又是另一回事。
不如说你到底什么视频?这种情况下我一般建议直接从源入手,就是mp4之前更原生的档来剪
#3-3 - 2022-3-21 21:06
萌豚豚
chitanda@Lv2 说: 没尝试过,但实际来说应该没这么简单。虽然x264压制的视频会留参数在视频信息里,但你ffmpeg能不能调用是一回事,调用了能不能用又是另一回事。
不如说你到底什么视频?这种情况下我一般建议直接从源入手...
多是B站下下来的视频,更具体说的话是虚拟主播的录播,做切片,网站的压制参数是固定的吧?
#3-4 - 2022-3-21 21:09
chitanda@Lv2
萌豚豚 说: 多是B站下下来的网络视频,更具体说的话是虚拟主播的录播,做切片,网站的压制参数是固定的吧?
但b站的压制参数显然也不会公开给你呀。。
#3-5 - 2022-3-21 21:23
萌豚豚
chitanda@Lv2 说: 但b站的压制参数显然也不会公开给你呀。。
感谢解答,那我还是继续慢慢切吧(bgm39)
顺便问下其他的编码格式比如VP9、AV1也会出现这样的情况吗?
#3-6 - 2022-3-21 21:36
chitanda@Lv2
萌豚豚 说: 感谢解答,那我还是继续慢慢切吧
顺便问下其他的编码格式比如VP9、AV1也会出现这样的情况吗?
VP9、AV1不清楚,我也很久没研究这方面东西了。。
#3-7 - 2022-3-21 22:03
萌豚豚
chitanda@Lv2 说: VP9、AV1不清楚,我也很久没研究这方面东西了。。
你好,我试了三个不同的B站 H.264 视频,用 FFmpeg 将无损切割和普通切割切切出来的视频直接拼起来都没有出现马赛克或其他的问题,可能是因为 FFmpeg 进化了或其他的原因吧,那我的原来的想法好实现吗?我感觉挺容易想到这个思路的,没搜到实现方法可能是我搜索能力差或不好实现吧(bgm39)
#3-8 - 2022-3-26 13:21
橘枳橼
h.264 解码是基于前几帧的,前几帧没花后面接上的也不会花(
花的情况通常是因为丢了帧,尤其在丢了屏幕大变的关键帧的情况下,就会把后一段的运动套上前一段的画面
#3-9 - 2022-3-26 14:24
lhb5883-吹冈王♛⑩
Εκκολαπτήριο 说: h.264 解码是基于前几帧的,前几帧没花后面接上的也不会花(
花的情况通常是因为丢了帧,尤其在丢了屏幕大变的关键帧的情况下,就会把后一段的运动套上前一段的画面
+1
#4 - 2022-3-21 20:38
(AE@Recording)
有点好奇这个问题但是懒得动手,马克一下。
简单搜索了一下,说是新的 ffmpeg 和播放器支持 edit list ,如果你的切割起点不是关键帧,它会向前找关键帧然后用 edit list 告诉播放器从你的起点开始播放。
#4-1 - 2022-3-21 20:55
萌豚豚
我剪出来后不止播放,还有和其他片段拼在一起的需求,所以要剪得准确(bgm39)
#4-2 - 2022-3-21 22:33
Aeroblast
萌豚豚 说: 我剪出来后不止播放,还有和其他片段拼在一起的需求,所以要剪得准确
我看有个东西叫advanced_editlist,大概不只是一个偏移,如果全套工具支持,拼剪应该也没问题。
退一步说,如果你最后没找到ffmpeg的简单操作,可以曲线救国,读取第一次操作产生的edit list偏移然后手动重编码……
#5 - 2022-3-21 21:26
重新看了一下 op 的问题,发现之前自己的理解有些问题。感觉上是可以做的,首先用 ffmpeg 找到视频中的所有关键帧,然后选取所需区间前后最近的两个关键帧,这样只有头尾需要重新编码,中间可以直接流复制...
#5-1 - 2022-3-21 22:07
萌豚豚
是这个意思,好实现吗?我感觉挺容易想到这个思路的,没搜到实现方法可能是我搜索能力差或不好实现吧(bgm39)
#5-2 - 2022-3-21 23:16
NekoNull
萌豚豚 说: 是这个意思,好实现吗?我感觉挺容易想到这个思路的,没搜到实现方法可能是我搜索能力差或不好实现吧
我也没有找到太多东西,于是干脆自己动手写了一个:
https://gist.github.com/jerrylus ... 24af3f1461cf907f140

但问题是似乎依然没法正常工作,就算找出了最近的关键帧,用 ffmpeg 切的时候依然不精确,导致最后拼起来的片段拼接的地方会有问题
#5-3 - 2022-3-21 23:49
萌豚豚
NekoNull 说: 我也没有找到太多东西,于是干脆自己动手写了一个:
https://gist.github.com/jerrylus ... 24af3f1461cf907f140

但问题是似乎依然没法正常工作,就算...
我试了几个视频都提示"Exception: too few keyframe..."(bgm41)
'/home/xx/script/python/cut.py' '/home/xx/video/979695752.P1.548021386.mp4'  03:51.87 09:00.13
hello world
executing:  ffprobe -v error -select_streams v:0 -skip_frame nokey -show_entries frame=pkt_pts_time -of csv=p=0 /home/xx/video/979695752.P1.548021386.mp4
Traceback (most recent call last):
  File "/home/xx/script/python/cut.py", line 91, in <module>
    main()
  File "/home/xx/script/python/cut.py", line 88, in main
    do_cut(sys.argv[1], sys.argv[2], sys.argv[3])
  File "/home/xx/script/python/cut.py", line 74, in do_cut
    start_frame, end_frame = find_closest_range(keyframes, start_sec, end_sec)
  File "/home/xx/script/python/cut.py", line 28, in find_closest_range
    raise Exception("too few keyframe...")
Exception: too few keyframe...
#5-4 - 2022-3-22 01:29
NekoNull
萌豚豚 说: 我试了几个视频都提示"Exception: too few keyframe..."
'/home/xx/script/python/cut.py' '/home/xx/video/979695752...
那就很奇怪了...因为我设定的似乎是2个或以下的关键帧才算太少...你要不直接运行报错上方 executing 后面的命令看看?来源是 hthttps://stackoverflow.com/questi ... l-video-using-ffpme
#5-5 - 2022-3-22 02:09
萌豚豚
NekoNull 说: 那就很奇怪了...因为我设定的似乎是2个或以下的关键帧才算太少...你要不直接运行报错上方 executing 后面的命令看看?来源是 hthttps://stackoverflow.com/ques...
ffprobe -v error -select_streams v:0 -skip_frame nokey -show_entries frame=pkt_pts_time -of csv=p=0 input.mp4

这个列出关键帧时间列表的代码我跑出来的是空的换行符(bgm38)
The Windows/cross-platform command provided did NOT work properly, had to change frame=pkt_pts_time to frame=pts_time, as nothing was showing up. The field may have changed the name since the original post? –
Francois Bertrand
其他地方看到解答了,"frame=pkt_pts_time" 改成 "frame=pts_time"就有输出了,但不知为何会多个逗号和换行,还是会提示出错"ValueError: could not convert string to float: '0.000000,'"(bgm41)
0.000000,

8.333333
16.666667
25.000000
#5-6 - 2022-3-22 02:14
烈之斩
NekoNull 说: 我也没有找到太多东西,于是干脆自己动手写了一个:
https://gist.github.com/jerrylus ... 24af3f1461cf907f140

但问题是似乎依然没法正常工作,就算...
这个技术上虽然没有大的“难点”但是要实现细节还是很多的,不是几行代码就能搞定的
pts, dts, start time、key帧/I帧区别之类的,外加各种格式的各自的兼容等,乱七八糟的问题非常多,
切完了concat也有一堆事情要注意,不是深耕视频多年不推荐碰(bgm38)

我粗略看了下你的脚本,在ffmpeg_encode_cut是用的先-i后-ss应该问题不大,但是为啥ffmpeg_stream_copy_cut变成了先-ss再-i了。这两种seek方式在ffmpeg里的实现是不太一样的,平时区别不大但是如果要逐帧切割可能会导致问题,推荐统一成先读取再seek的方式试试(另外ffmpeg记得用最新版否则有bug)

很多收费软件也不是白收费的,楼主如果刚需推荐直接购买 TMPGEnc MPEG Smart Renderer
#5-7 - 2022-3-22 02:25
NekoNull
烈之斩 说: 这个技术上虽然没有大的“难点”但是要实现细节还是很多的,不是几行代码就能搞定的
pts, dts, start time、key帧/I帧区别之类的,外加各种格式的各自的兼容等,乱七八糟的问题非常多,
...
多谢回复,写的时候比较直接,但是跑的时候就发现不对劲了 (bgm38)
对视频编码只有一些基础了解,stream_copy 那里似乎是因为我本地测试的时候,如果先 -i 再 -ss (output seeking),似乎会导致第一个关键帧提取不到,行为有些诡异。但是反过来(input seeking)行为就符合预期了。但无论如何,拼接起来的时候还是会有问题(存在部分重叠),更别提交界处码率差异导致的画质显著变化了。我本地测试的版本是 4.3.2,似乎已经是一年前的版本了。
可能 op 的确还是直接上商业的解决方案更好一些。
#5-8 - 2022-3-22 02:33
萌豚豚
烈之斩 说: 这个技术上虽然没有大的“难点”但是要实现细节还是很多的,不是几行代码就能搞定的
pts, dts, start time、key帧/I帧区别之类的,外加各种格式的各自的兼容等,乱七八糟的问题非常多,
...
感谢回答!不过我对现在的状态还挺满意的,只是想着能不能改进得更好点,所以暂时没有换其他工具的打算(bgm38)
#5-9 - 2022-7-1 12:57
Rivers
NekoNull 说: 多谢回复,写的时候比较直接,但是跑的时候就发现不对劲了
对视频编码只有一些基础了解,stream_copy 那里似乎是因为我本地测试的时候,如果先 -i 再 -ss (output seeking)...
对于-ss在前还是在后可以看看http://trac.ffmpeg.org/wiki/Seeking
#6 - 2022-3-21 21:42
(いつでも微笑みを)
搭车铜球
#7 - 2022-3-21 23:15
Smart Cutter 据说是只有头尾重编码中间直接流复制的,支持关键帧,多年前使用时体验很好,主要用来剪 TS 电视录像档中间的广告。(不过也是有遇到过爆格的,主要还是要看原档的质素,太烂的怎么搞都还是很烂。)

如果你头尾不重编码直接用 ffmpeg 拼接在一起,那么如果两段视频的交接处的码率相差太多就会出现爆格。

比如说前段是静止画面,那么码率就会很小,后段是剧烈运动的画面,那么码率就会很大,强行拼接就会爆格,因为码率过渡不平稳。没爆格那说明是运气好,正好交接处的码率相差不大,不求完美的话,图省事是可以这么处理的。

但如果条件允许,建议还是在剪了需要的画面出来后,用 ffmpeg two-pass vbv 重编码一遍,尤其是有很多片段的话。
#7-1 - 2022-3-21 23:25
萌豚豚
感谢提醒,不过因为我主要剪的是虚拟主播的视频,所以很少会出现码率相差很大的情况(bgm39)
#7-2 - 2022-3-22 02:37
烈之斩
这个剪辑ts还可以,拼mp4(或者mpeg4,不清楚是容器还是编码哪个导致)拼接处会卡帧

另外还有经典的崩溃问题(bgm40)
#7-3 - 2022-3-22 04:41
弥御水Scyiki
烈之斩 说: 这个剪辑ts还可以,拼mp4(或者mpeg4,不清楚是容器还是编码哪个导致)拼接处会卡帧

另外还有经典的崩溃问题
你不说我都忘了……是挺经常崩溃的(bgm38)
怪不得我很久都没用这软件了(我自己都忘记原因了
#8 - 2022-3-26 14:26
(BGMのTrinitas<=>婊冈妈<=>补冈妈<=>拜冈妈 三位一体 ...)
关键帧之间会差很长时间么?我都是直接拼,长一点就长一点呗。
#9 - 2022-3-26 14:39
(人生五十年 如梦亦如幻 有生斯有死 壮士何所憾 ... ...)
我都是先转码成全关键帧的再切,或者AE之类。
#10 - 2022-6-30 17:19
(。´-д-)
今天碰巧看到了篇文章,给你参考 https://zhuanlan.zhihu.com/p/423444166
#11 - 2022-6-30 20:37
(什么都看,什么都不懂)
TMPGEnc MPEG Smart Renderer
没找到破解版,可以用虚拟机之类的方法无限试用就是了。
#12 - 2022-7-1 01:03
(‮rettiw‭t)
删除了回复