ffmpeg 处理后视频时长问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
henix
V2EX    FFmpeg

ffmpeg 处理后视频时长问题

  •  
  •   henix 2024-11-20 18:37:25 +08:00 4007 次点击
    这是一个创建于 389 天前的主题,其中的信息可能已经有所发展或是发生改变。

    用 ffmpeg -t 将一个 10s 的视频剪裁到 3s 后,播放时长没问题,但是放进 concat 过滤器,这个视频片段占用的长度仍为原长度 10s ,后面 7s 表现为最后一帧静止画面。尝试了各种方法都不行,还望大神赐教。

    问题详细描述:

    1. 用完全重编码的方法将一个 10s 的视频转换为 3.971s 并去掉音频:

    ffmpeg -t 3.971 -i "加载.mp4" -c:v libx264 -tune animatin -crf 1 -an loading.mp4

    ffprobe 结果文件 loading.mp4 如下:

    Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'loading.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf61.7.100 Duration: 00:00:03.98, start: 0.000000, bitrate: 49072 kb/s Stream #0:0[0x1](eng): Video: h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1920x1080, 49068 kb/s, 60 fps, 60 tbr, 15360 tbn (default) Metadata: handler_name : ?Mainconcept Video Media Handler vendor_id : [0][0][0][0] encoder : Lavc61.19.100 libx264 

    疑点:时长为 3.98 ,已经不精确?

    原始视频的 ffprobe ,是不是原始视频有什么不正常:

    Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '加载.mp4': Metadata: major_brand : mp42 minor_version : 0 compatible_brands: mp42mp41 creation_time : 2022-03-26T12:31:39.000000Z Duration: 00:00:10.00, start: 0.000000, bitrate: 9763 kb/s Stream #0:0[0x1](eng): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1920x1080, 9395 kb/s, 60 fps, 60 tbr, 60k tbn (default) Metadata: creation_time : 2022-03-26T12:31:39.000000Z handler_name : ?Mainconcept Video Media Handler vendor_id : [0][0][0][0] encoder : AVC Coding Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 317 kb/s (default) Metadata: creation_time : 2022-03-26T12:31:40.000000Z handler_name : #Mainconcept MP4 Sound Media Handler vendor_id : [0][0][0][0] 

    2. 将一个 webm 视频 overlay 到上述视频上,并加入音频,且音视频都重编码:

    疑点:webm 视频的时长显示为 N/A ,但实际为 3.5s 左右

    用了 -filter_complex chromakey,scale;overlay

    结果的 ffprobe 如下:

    Input #0, matroska,webm, from 'opening.mkv': Metadata: COMPATIBLE_BRANDS: isomiso2avc1mp41 MAJOR_BRAND : isom MINOR_VERSION : 512 ENCODER : Lavf61.7.100 Duration: 00:00:03.98, start: 0.000000, bitrate: 70572 kb/s Stream #0:0: Video: h264 (High 4:4:4 Predictive), yuv420p(tv, bt709, progressive), 1920x1080, 60 fps, 60 tbr, 1k tbn Metadata: ENCODER : Lavc61.19.100 libx264 DURATION : 00:00:03.984000000 Stream #0:1: Audio: flac, 44100 Hz, stereo, s16 Metadata: ENCODER : Lavc61.19.100 flac DURATION : 00:00:03.970000000 

    这一步结果视频长度 3.984s

    3. 将上一步的结果用 concat 加到另外两个视频流的中间:

    -filter_complex "[10:v]trim=0:3.97[t10v]", "[10:a]atrim=0:3.97[t10a]", "[fv1t][fa1t][t10v][t10a][fv2t][fa2t]cOncat=3:1:1", 

    其中 "[10]" 代表上一步结果的视频流和音频流,已经用 trim 处理

    结果:在生成的文件中,这一段的实际占用时间为 10s ,而不是我需要的 3.971s ,后面 7s 是最后一帧静止画面和静音。

    24 条回复    2024-11-21 17:51:28 +08:00
    lovelylain
        1
    lovelylain  
       2024-11-20 18:47:29 +08:00 via Android
    ffprobe -loglevel trace "加载.mp4"
    msg7086
        2
    msg7086  
       2024-11-20 18:59:12 +08:00
    238 帧是 3.967s
    239 帧是 3.983s
    怎么可能出现 3.971s ?

    至于把一个不兼容的段塞到原来的流里,炸锅概率本来就非常大,能正常播放才是奇迹。VPS/SPS/PPS 都不一样的,timecode 也没处理吧大概。
    henix
        3
    henix  
    OP
       2024-11-20 19:07:06 +08:00
    @lovelylain ffprobe -loglevel trace "加载.mp4" 贴到这里了: https://gist.github.com/henix/0ae8a97aeb78fc60206e4b75464fcfbd
    这个原始视频是别人给我的,估计应该是用 Adobe 的软件做出来的
    shintendo
        4
    shintendo  
       2024-11-20 19:09:41 +08:00
    我,看到这贴猛然想起一个困扰我多年的问题:
    我用剪映剪视频的时候,会用小丸工具箱( ffmpeg 封装的工具)从原始视频素材(多为 mkv 的影视剧)里剪出几十秒的片段,这些片段文件大小没问题,直接用播放器播放也没问题,但是一旦拖进剪映里面,那个素材的长度就变成了原始 mkv 的几小时长度,其中前几十秒是我要的,后面都是最后一帧的静止。
    我一直不知道是什么原因!
    henix
        5
    henix  
    OP
       2024-11-20 19:13:25 +08:00
    @msg7086 初学视频编辑,还不知道你说的这些名词啥意思...但最后 concat 那一步我对齐了分辨率都是 1920x1080 ,帧率都是 60 fps ,还有啥需要注意的吗
    confi
        6
    confi  
       2024-11-20 19:21:08 +08:00 via iPhone
    之前用 ffmpeg 或其他套壳软件,用关键帧方式裁剪视频,也出现这个问题,未解决
    lslqtz
        7
    lslqtz  
       2024-11-20 19:28:26 +08:00
    @msg7086 238/59.94=3.9706=3.971

    另外部分设备拍摄的视频很小的概率会丢帧.
    tool2dx
        8
    tool2dx  
       2024-11-20 19:34:01 +08:00 via Android
    @confi “用关键帧方式裁剪视频”,把关键字三个字去掉,就解决了。
    lslqtz
        9
    lslqtz  
       2024-11-20 19:34:35 +08:00
    但就我印象中, 59.94fps 应该是单独一档, 不会按 60fps 来显示. 也许, 这只是一个巧合.

    一个最简单的 workaround 是, 你描述到最后是静帧持续, 那么可以在处理完成后再次尝试进行一次裁切.
    lslqtz
        10
    lslqtz  
       2024-11-20 19:35:21 +08:00
    @confi 关键帧通常几秒甚至几十秒一次, 因此不能用关键帧来精确裁剪和定位视频.
    lslqtz
        11
    lslqtz  
       2024-11-20 19:41:07 +08:00
    另外, 引用这个答案: https://stackoverflow.com/a/63357242
    ```
    ffmpeg -i vid1.mp4 -i vid2.mp4 -filter_complex "[0:v]trim=0:2,setpts=PTS-STARTPTS[v1];[1:v]trim=3:6,setpts=PTS-STARTPTS[v2];[0:a]atrim=0:2,asetpts=PTS-STARTPTS[a1];[1:a]atrim=3:6,asetpts=PTS-STARTPTS[a2];[v1][a1][v2][a2]cOncat=n=2:v=1:a=1" out.mp4
    ```
    msg7086
        12
    msg7086  
       2024-11-20 19:45:09 +08:00
    @lslqtz
    59.94 fps, 59.94 tbr, 59.94 tbn
    我这边 60/1.001 的都是这么显示的,不会显示 60 。
    msg7086
        13
    msg7086  
       2024-11-20 19:47:44 +08:00
    @henix #5 压制参数有很多,然后其中很多是互相不兼容的,也就是一个视频里不能同时出现一段用这个参数另一段用那个参数。比如说 ref ,假如你前面片段用 ref3 ,然后解码器为 ref3 开了对应大小的帧缓冲区,然后你后面的片段用了 ref4 ,那跑的时候就会出现缓冲区读不到帧的情况,因为解码器是按照前面的设置 3 来初始化的。
    lslqtz
        14
    lslqtz  
       2024-11-20 19:48:13 +08:00
    @msg7086 那我只能推测是丢帧, 因为最后生成的 ffprobe 有一个 metadata DURATION: 00:00:03.984000000, 它既不符合 59.94 也不符合 60fps.
    msg7086
        15
    msg7086  
       2024-11-20 19:49:40 +08:00   1
    @lslqtz 239 帧 60fps 是 3.983333 ,考虑到 timebase 精度,3.984 算是正常范围。
    henix
        16
    henix  
    OP
       2024-11-20 19:50:31 +08:00
    感谢各位回复!
    我刚才发现在完全不使用原始的 加载.mp4 的情况下依然会出现这个问题,可能是我的思考方向错了,今天被这个问题心态搞得有点绷不住。。。
    目前初步怀疑是最后一步 concat 之前会把一个大视频拆分成前后两段,后面那段 trim 之后没加 setpts 导致的(因为前面一段正好是 7s ,让我误以为是原始视频的 7s )
    有后续进展再更新
    yinmin
        17
    yinmin  
       2024-11-20 20:10:07 +08:00
    试试下面这条切视频的指令:
    ffmpeg -ss 00:01:00 -to 00:10:00 -i in.mp4 -c copy out.mp4
    234ygg
        18
    234ygg  
       2024-11-20 22:11:04 +08:00 via iPhone
    ffmpeg 有时候改变一下 option 的前后顺序,都能剪出来点略微不一样的东西 很烦
    emonber
        19
    emonber  
       2024-11-20 23:14:01 +08:00
    -ss -to 放在 -i <input> 后面,这样时间似乎会精确一些。
    另外,可以查看下转码后的视频时间戳:ffmpeg -i <input> -vf showinfo -f null -
    512357301
        20
    512357301  
       2024-11-20 23:33:11 +08:00 via Android
    遇事不决用 PR ,真的省心,个人无所谓正版盗版,先解决问题
    mumbler
        21
    mumbler  
       2024-11-21 00:55:37 +08:00   1
    要精确剪辑,首先要增加视频关键帧密度
    ffmpeg -i input.mp4 -forced-idr 0.1 -c:v libx264 -keyint_min 10 -g 10 output.mp4
    这个命令会将输入视频重新编码,在每 0.1 秒插入一个关键帧,提高视频的关键帧密度。然后你再剪辑就可以精确到 0.1 秒了,这样视频体积会显著增大,当然你也可以每 1 秒增加关键帧
    chocotan
        22
    chocotan  
       2024-11-21 09:52:54 +08:00
    -i 放前面去试试
    wnpllrzodiac
        23
    wnpllrzodiac  
       2024-11-21 13:00:10 +08:00 via Android
    全部解码成帧,再编码一定没问题。想用 concat 就是会有奇怪问题的概率。非线编全是在操作帧,而不是视频片断,所以很吃资源。
    henix
        24
    henix  
    OP
       2024-11-21 17:51:28 +08:00
    今天研究了一下,确实是最后一步的 concat 用的片段是 trim 之后没加 setpts ,之前有个回复提醒了我。

    最后一步修正之后的 filter_complex:

    ```
    "[fv]split[fv1][fv2]",
    "[fv1]trim=0:7[fv1t]",
    "[fv2]trim=7,setpts=PTS-STARTPTS[fv2t]",
    "[fa]asplit[fa1][fa2]",
    "[fa1]atrim=0:7[fa1t]",
    "[fa2]atrim=7,asetpts=PTS-STARTPTS[fa2t]",
    "[fv1t][fa1t][10:v][10:a][fv2t][fa2t]cOncat=3:1:1",
    ```

    现在已经正常了,感谢各位的讨论
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3872 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 05:22 PVG 13:22 LAX 21:22 JFK 00:22
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86