我注意到 ffmpeg-t
在 M2TS 输入上使用时有时会写入无效的 PTS 时间戳。这是我的错误还是 ffmpeg 的错误?
重现步骤:
下载此 M2TS 文件并将其另存为1.m2ts
. 该文件包含一个视频流25 fps
(即,一个视频帧恰好占用0.04 s
( 40 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.560
而不是3.520
)。
当然,当谈论“最后”或“之前”时,我指的是时间上的帧的顺序(更准确地说,我已经按PTS对视频帧进行了排序),而不是文件中的帧的顺序。
问题:
这是 ffmpeg 中的错误,还是我上面的命令有错误?
ffmpeg版本:
ffmpeg version 2024-01-14-git-34a47b97de-full_build-www.gyan.dev
在 Windows 10 x64 企业版上
进一步说明:
我注意到我的几个 M2TS 文件存在问题;我没有时间测试其他格式。不幸的是,我无法提供我的文件供下载。这就是我链接到另一个文件的原因。
换句话说:问题并非特定于我链接的文件。相反,我在不同来源的各种 M2TS 文件中遇到过各种视频帧速率和音轨。
我还没有调查音轨的类似间隙。
这不是一个错误,只是 B 帧依赖性的结果。
视频流有 3 种类型的帧:
最后一个与 2 秒持续时间匹配的编码视频帧是B 帧。
2.m2ts 中的第一帧具有
pts_time=1.48
.2.m2ts 中的最后一帧应该有
pts_time=3.48
.由于 的帧
pts_time=3.48
是 B 帧,因此它取决于在其之后编码的 P 帧。之后的 P 帧有
pts_time=3.56
.如果没有该 P 帧,就不可能解码 B 帧,因此复用器保留最后一个额外的 P 帧。
使用 FFprobe 分析视频帧:
我们可以使用FFprobe来获取这2个文件的视频流的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
使用比较工具比较文件,得到以下结果:
pts_time=3.52
请注意,解码不需要B 帧3.48
(3.48
取决于3.56
P 帧,但不依赖于该3.52
B 帧),因此3.52
被跳过。