ffmpeg 处理后视频时长问题

1 天前
 henix

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

问题详细描述:

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

ffmpeg -t 3.971 -i "加载.mp4" -c:v libx264 -tune animation -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 是最后一帧静止画面和静音。

1198 次点击
所在节点    FFmpeg
24 条回复
mumbler
19 小时 23 分钟前
要精确剪辑,首先要增加视频关键帧密度
ffmpeg -i input.mp4 -forced-idr 0.1 -c:v libx264 -keyint_min 10 -g 10 output.mp4
这个命令会将输入视频重新编码,在每 0.1 秒插入一个关键帧,提高视频的关键帧密度。然后你再剪辑就可以精确到 0.1 秒了,这样视频体积会显著增大,当然你也可以每 1 秒增加关键帧
chocotan
10 小时 25 分钟前
-i 放前面去试试
wnpllrzodiac
7 小时 18 分钟前
全部解码成帧,再编码一定没问题。想用 concat 就是会有奇怪问题的概率。非线编全是在操作帧,而不是视频片断,所以很吃资源。
henix
2 小时 27 分钟前
今天研究了一下,确实是最后一步的 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",
```

现在已经正常了,感谢各位的讨论

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

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

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

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

© 2021 V2EX