使用ffmpeg,帧显示在pts_时间之前0.000057秒

使用ffmpeg,帧显示在pts_时间之前0.000057秒,ffmpeg,h.264,ffprobe,blink,mpeg-4,Ffmpeg,H.264,Ffprobe,Blink,Mpeg 4,使用ffmpeg命令从一系列图像中创建,图像上有数字和预期的时间戳(假设120 fps恒定帧速率): 它应该是恒定的帧速率,所有的帧都是I帧。 我预计第6帧将精确显示在0.05秒[0.05,0.0583333]的时间,如ffmpeg和ffprobe中显示的pts_时间: [Parsed_showinfo_0@0x7fba11404080]n:6分:768分时间:0.05 位置:36021 fmt:yuv444p sar:0/1 s:1552x878 i:P iskey:1类型:i 校验和:2CD

使用ffmpeg命令从一系列图像中创建,图像上有数字和预期的时间戳(假设120 fps恒定帧速率):

它应该是恒定的帧速率,所有的帧都是I帧。 我预计第6帧将精确显示在0.05秒[0.05,0.0583333]的时间,如ffmpeg和ffprobe中显示的pts_时间:

[Parsed_showinfo_0@0x7fba11404080]n:6分:768分时间:0.05 位置:36021 fmt:yuv444p sar:0/1 s:1552x878 i:P iskey:1类型:i 校验和:2CDED07A平面\ U校验和:[A86DBAAD C4CB8EF2 DDC586CC] 平均值:[163 133 121]stdev:[9.0 0.6 0.8]

[FRAME]
media_type=video
stream_index=0
key_frame=1
pkt_pts=768
pkt_pts_time=0.050000
pkt_dts=768
pkt_dts_time=0.050000
best_effort_timestamp=768
best_effort_timestamp_time=0.050000
pkt_duration=128
pkt_duration_time=0.008333
pkt_pos=36021
pkt_size=2531
width=1552
height=878
pix_fmt=yuv444p
sample_aspect_ratio=N/A
pict_type=I
coded_picture_number=6
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
color_range=unknown
color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=left
[/FRAME]
但实际上,它是从0.049943秒开始显示的。我使用ffmpeg以0.0001秒的持续时间提取时间

ffmpeg -ss 00:00:00.049943 -i 120_keyint_1.mp4 -t 00:00:00.0001 out.mp4
得到,显示第6帧

我还尝试在chrome上播放此视频,并设置了videoNode的当前时间。它在0.049943处显示第5帧,但在0.049968(0.05之前!)之后显示第6帧

但是,我尝试了另一种编码方法,得到了另一种:

理论上,第6帧也应该出现在时间范围[0.05,0.0583333]中,但在Chrome中,第6帧在currentTime>=0.051秒之前不会出现。更有趣的是,我使用ffmpeg以0.049943秒的速度获得第6帧,与上面的提取命令相同


这是否意味着在MPEG4 h.264视频中,我们不能依靠ffmpeg中的pts_时间来确定特定帧的确切显示时间,并且它是特定于视频播放器的?

我认为问题在于文件中的电影头标度为1000,这是ffmpeg的硬连线默认值。(libavformat\movenc.h第32行:
\define MOV_TIMESCALE 1000

120 fps的帧速率不能用1/1000秒表示,因此ffmpeg会产生舍入错误

默认时间刻度为1000是一个糟糕的选择,如果不修改ffmpeg的源代码,就无法更改它


我会将
#define MOV_TIMESCALE 1000
更改为
#define MOV_TIMESCALE 600
或其他可被120整除的值,然后重新编译ffmpeg。

我认为问题在于文件中的电影头标度为1000,这是ffmpeg的硬连线默认值。(libavformat\movenc.h第32行:
#定义MOV\u时间刻度1000

120 fps的帧速率不能用1/1000秒表示,因此ffmpeg会产生舍入错误

默认时间刻度为1000是一个糟糕的选择,如果不修改ffmpeg的源代码,就无法更改它


我会将
#define MOV_TIMESCALE 1000
更改为
#define MOV_TIMESCALE 600
或其他可被120整除的值,然后重新编译ffmpeg。

是的,预计会有一些抖动。好奇的是,你的应用程序需要微秒精度吗?我的web应用程序用于在线视频编辑,需要帧精度。我们正在寻找对于具有严格的帧到时间戳映射的视频格式。实际视频播放的不精确性对您在软件或文件数据结构中存储或操作时间戳的方式没有影响。是的,预计会出现一些抖动。好奇,您的应用程序要求微秒精度吗?我的web应用程序用于在线视频编辑,需要帧准确度。我们正在寻找一种可以有严格的帧到时间戳映射的视频格式。实际的视频播放不准确度不会影响您在软件或文件数据结构中存储或操作时间戳的方式。MOV/MP4s存储每个样本的样本持续时间(实际上是块),所以帧速率不在其中,更不用说相关帧的PTS可以精确地以1000的比例表示为50。OP抱怨播放过程中不精确,而不是ffmpeg。@Gyan ffmpeg提取也给出了错误的结果。
ffmpeg-ss 00:00:00.049943-i 120_keyint_1.mp4-t 00:00:00.0001 out。mp4
给出了一个剪辑第6帧,但应该是第5帧为什么应该是第5帧?@Gyan注意,该帧从0开始。根据ffmpeg“showinfo”,第6帧的pts_时间为0.05秒。因此,在0.049943秒时,它应该是第5帧。搜索不会以这种方式工作。相对时间戳和数据包持续时间将作为存储进行解混,而不会针对中间时间间隔进行调整。此外,搜索MP4通常会向后搜索到最近的关键帧。但在您的情况下,它会搜索第6帧,这是KF。这是因为
0。049943
当转换为流时基(1/15360)时,为767.12448,向+无穷大取整,结果为768。第6帧是一个KF,正好位于每个样本的pts 768.MOV/MP4s店样本持续时间(实际上是块),所以帧速率不在其中,更不用说相关帧的PTS可以精确地以1000的比例表示为50。OP抱怨播放过程中不精确,而不是ffmpeg。@Gyan ffmpeg提取也给出了错误的结果。
ffmpeg-ss 00:00:00.049943-i 120_keyint_1.mp4-t 00:00:00.0001 out。mp4
给出了一个剪辑第6帧,但应该是第5帧为什么应该是第5帧?@Gyan注意,该帧从0开始。根据ffmpeg“showinfo”,第6帧的pts_时间为0.05秒。因此,在0.049943秒时,它应该是第5帧。搜索不会以这种方式工作。相对时间戳和数据包持续时间将作为存储进行解混,而不会针对中间时间间隔进行调整。此外,搜索MP4通常会向后搜索到最近的关键帧。但在您的情况下,它会搜索第6帧,这是KF。这是因为
0。049943
当转换为流时基(1/15360)时,其为767.12448,向+无穷大舍入,结果为768。第6帧是正好位于pts 768的KF。
ffmpeg -ss 00:00:00.049943 -i 120_keyint_1.mp4 -t 00:00:00.0001 out.mp4
ffmpeg -framerate 120 -i %03d.png -vcodec libx264 -f mp4 -movflags faststart 120.mp4