ffmpeg 要么丢帧,要么写入无效的 PTS 时间戳:是 Bug 还是我的错误?

ffmpeg 要么丢帧,要么写入无效的 PTS 时间戳:是 Bug 还是我的错误?

我注意到,ffmpeg-t在 M2TS 输入上使用时有时会写入无效的 PTS 时间戳。这是我的错误还是 ffmpeg 中的错误?

重现步骤:

下载此 M2TS 文件并将其另存为1.m2ts。此文件包含一个视频流25 fps(即一个视频帧正好占用0.04 s40 ms))和一个音频流(对于本文的目的而言,该音频流并不重要)。

打开终端,导航到包含该文件的目录,然后执行以下命令:

ffmpeg.exe -i 1.m2ts -codec copy -map 0 -t 2 2.m2ts

现在检查输出文件,,2.m2ts并观察到最新视频帧的 PTS 是3.560,并且前一个视频帧的 PTS 是3.480

这显然是错误的。在 处的帧之后3.480,下一帧应该出现在 处3.520,而不是 处3.560。要么是 ffmpeg 丢弃了应该出现在 处的视频帧,要么是它向最后一个视频帧(而不是)3.520写入了错误的 PTS 。3.5603.520

当然,当谈到“最后”或“之前”时,我指的是时间上的帧顺序(更准确地说,我已经按 PTS 排列了视频帧),而不是文件中帧的顺序。

问题:

这是ffmpeg的一个bug,还是我上面的命令有错误?

ffmpeg 版本:

ffmpeg version 2024-01-14-git-34a47b97de-full_build-www.gyan.dev在 Windows 10 x64 企业版上

进一步说明:

我注意到我的几个 M2TS 文件有问题;我没有时间测试其他格式。不幸的是,我无法提供我的文件供下载。这就是我链接到另一个文件的原因。

换句话说:问题并不只存在于我链接的文件中。相反,我在不同来源的各种 M2TS 文件中遇到过各种视频帧速率和音轨的问题。

我还没有调查过与类似差距有关的音轨。

答案1

这不是一个错误,只是 B 帧依赖的结果。

视频流有 3 种类型的帧:

  • I-Frame-不依赖于任何帧。
  • P 帧 - 仅依赖于它之前的帧。
  • B 帧 - 依赖于编码帧之前的帧和之后的帧。

最后一个与 2 秒持续时间相匹配的编码视频帧是B 帧。2.m2ts
中的第一帧有pts_time=1.48。2.m2ts
中的最后一帧应该有pts_time=3.48

由于 为pts_time=3.48B 帧,因此它依赖于在其后编码的 P 帧。
后面的 P 帧具有pts_time=3.56
没有该 P 帧,就无法解码 B 帧,因此复用器会保留最后一个额外的 P 帧。


使用 FFprobe 分析视频帧:

我们可以使用 FFprobe 来获取这两个文件的视频流的 pts_time 和 pict_type。

ffprobe -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries frame=pts_time,pict_type 1.m2ts > 1.txt

ffprobe -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries frame=pts_time,pict_type 2.m2ts > 2.txt

使用比较工具比较文件,得到以下结果:

1.txt       2.txt
------      ------

1.480000    1.480000
I           I
...
B           B
3.040000    3.040000
B           B
3.080000    3.080000
P           P
3.120000    3.120000
B           B
3.160000    3.160000
B           B
3.200000    3.200000
B           B
3.240000    3.240000
P           P
3.280000    3.280000
B           B
3.320000    3.320000
B           B
3.360000    3.360000
B           B
3.400000    3.400000
P           P
3.440000    3.440000
B           B
3.480000    3.480000
B           B
3.520000    
B           
3.560000    3.560000
P           P

pts_time=3.52请注意,解码不需要B 帧3.483.48依赖于3.56P 帧但不依赖于3.52B 帧),因此3.52被跳过。

相关内容