怎样“无缝”拼接多个“帧率不同”的 mp4 文件?

2019-01-16 17:41:25 +08:00
 xiaopenyou

一句话说

多个帧率(fps)不同的 mp4 片段,怎样无缝、不重编码(without re-encode)地拼接(concat)回一个文件,且不改变时间长度?

关键词:帧率不同、无缝拼接、不重编码、不改变时间长度

如果 4 个定语无法同时满足,无缝拼接可以去掉


详细说

定期收到的视频,每个视频总被剪成 N 段片段,现想合并回 1 个文件。试了下面的方案,都不满意:

  1. fps 不同的文件,直接 ffmpeg concat demuxer 会各种问题,大佬肯定知道,不细说了

  2. 即使 fps 相同,用如下命令直接 concat demuxer,在合并的分界处,也会有卡屏停顿。相反用 Boilsoft Video Joiner 合并,就没有卡屏、真正无缝。所以不知道 ffmpeg 想无缝拼接,应该怎么写命令?
    (echo file 'first file.mp4' & echo file 'second file.mp4' )>list.txt
    ffmpeg -safe 0 -f concat -i list.txt -c copy output.mp4

  3. 试了如下命令,虽然不重编码,但会改变时间长度:
    ffmpeg -y -i seeing_noaudio.mp4 -c copy -f h264 seeing_noaudio.h264
    ffmpeg -y -r 29.97 -i seeing_noaudio.h264 -c copy seeing.mp4

  4. 试了如下命令,会重编码(有损转换,丢视频质量): ffmpeg -i input.mp4 -r 29.97 -y output.mp4

所以这种需求,有办法实现么?

  1. 求助前提:只有剪辑后的片段。不聊能拿到未剪辑视频源的情况

  2. 大佬可能说,不改变时间长度就必须丢弃帧,那怎么可能不重编码?是这样吗?菜鸟不懂,说错求科普,谢谢😛

5222 次点击
所在节点    问与答
20 条回复
d3vil
2019-01-16 17:43:29 +08:00
此帖仅限大佬盖楼,请楼下慎重。
xiaopenyou
2019-01-16 17:46:22 +08:00
@d3vil #1 热切期盼回帖呀,虚心求教,求大家帮帮忙😂😘
xiaopenyou
2019-01-16 17:54:24 +08:00
目前采用的,是先重编码把所有片段转成帧率一致,然后再调用 Boilsoft Video Joiner 合并,但唯一缺点就是会重编码、丢视频质量,所以发帖,请教下见多识广的 v 友们,有没更优良的方案……
kokutou
2019-01-16 17:55:47 +08:00
搞个 m3u8 播放列表?
xiaopenyou
2019-01-16 17:59:34 +08:00
@kokutou #4 “合并”主要是为了二次分发,以及导入到专业工具中管理
实在无奈没辙的话,这也是个方法啦,谢谢😘
cest
2019-01-16 18:08:12 +08:00
你要的 vfr 只在规格上存在,还没看过那个工具真的做出来
Elethom
2019-01-16 18:12:46 +08:00
不可能完全不重编码,能想到的成本最低的方式就是无脑型插帧或丢帧,比如说 24 转 30 就每隔 4 帧插一个不变的 P 帧进去,30 转 24 就每 5 帧丢掉一帧(遇到 I 帧 B 帧还是要涉及一点点编码)不过效果会比较奇怪就是了。
xiaopenyou
2019-01-16 18:14:22 +08:00
@cest #6 那作为“ vfr 当前实践尚做不到”的推论,是不是要拼接就必须先“帧率一致化”?
那问题就转换成“能否不重编码地转换帧率”,请教大神这一点目前可以做到吗?
俺对视频编码这块一窍不通,问的蠢的话见谅
Elethom
2019-01-16 18:14:25 +08:00
@Elethom
@Livid,移动端折行样式有点奇怪。
xiaopenyou
2019-01-16 18:18:07 +08:00
@Elethom #7 是的,上面第 4 条用的 ffmpeg -i input.mp4 -r 29.97 -y output.mp4 命令,就是无脑丢帧的方法
咨询个蠢问题:是不是理论上,“无脑丢帧”就必然等于要“重编码”啊?如果是这样,就不折腾了……
Elethom
2019-01-16 18:18:27 +08:00
@Elethom
纠正 #7,P 帧也需要编码。
Elethom
2019-01-16 18:24:03 +08:00
@xiaopenyou
无脑丢帧的话,重编码也不是整个重编码,只是被操作的帧会重编码(比如说 I、P、P 三帧丢掉了中间的 P 帧会把两个 P 帧的变化量合并到一个 P 帧里),理论上不会影响视频的清晰度,只是会在时间上有一点时快时慢的感觉。我没看过 ffmpeg 的源码所以不能回答你它的 behaviour 具体是什么样的。
zhs227
2019-01-16 18:31:41 +08:00
需要重新做转码成一致的帧率,要不然你放到各种软件中能正常处理的占少数
xiaopenyou
2019-01-16 18:31:55 +08:00
@Elethom #12 原来这样啊,看来目前最极限的方案,也只能要么 m3u8,要么重编码了
知道不会丢太多清晰度,吃了颗定心丸,谢谢非常感激科普
fgodt
2019-01-16 18:49:26 +08:00
你这种就只能动态插入 sps pps ,现在默认的 mp4 格式又是全局 sps pps 很多解码器都不支持所以无解,但理论上是可以支持的
EridanusSora
2019-01-16 18:54:00 +08:00
理论上可以,实际上研究过找不到工具能做……感觉做出来能不能播也是问题
annoy1309
2019-01-16 23:48:57 +08:00
@Elethom p 不一定需要编码,有“可能”不需要编码
worldGM
2019-01-17 00:44:22 +08:00
播放,录屏....这个思路不知道行不行 QAQ
msg7086
2019-01-17 05:39:25 +08:00
首先第一个问题是就不应该考虑 ffmpeg 的 concat。ffmpeg 的 concat 是非常原始的连接,对于容器格式不是很适用。
然后要合并文件,要考虑的是目标文件格式支持哪些特性。
比如说你要合并成 mp4,那么流的格式就有限定(比如 ass 字幕就不可能合并),流本身也有限定,比如把一个 avc 的视频和一个 hevc 的视频接在一起大概率是要崩的。不同参数编码出来的视频放在一起也有很大概率会崩。

最有希望合并的情况是,这些片段原本就是从一个源上切下来的,或者是从多个相同参数编码的片段上切下来的。
这种情况直接用 mp4box 合并大概就行了。

mp4box -cat part1.mp4 -cat part2.mp4 output.mp4

就是要注意一下这样合并出来的视频,中间可能会有多余的 VPS SPS SEI 帧,如果你介意的话还得手动编辑流去去掉。

另外帧率不同其实只需要合并一下 timecode 就行了。
35korea
2019-01-17 08:34:03 +08:00
final cut 不是可以改参数统一 fps 吗

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

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

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

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

© 2021 V2EX