V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
xiaopenyou
V2EX  ›  问与答

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

  •  
  •   xiaopenyou · 2019-01-16 17:41:25 +08:00 · 5224 次点击
    这是一个创建于 2136 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一句话说

    多个帧率(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. 大佬可能说,不改变时间长度就必须丢弃帧,那怎么可能不重编码?是这样吗?菜鸟不懂,说错求科普,谢谢😛

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

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

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

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

    另外帧率不同其实只需要合并一下 timecode 就行了。
    35korea
        20
    35korea  
       2019-01-17 08:34:03 +08:00 via Android
    final cut 不是可以改参数统一 fps 吗
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5278 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 08:15 · PVG 16:15 · LAX 00:15 · JFK 03:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.