0
votes

This video is created using ffmpeg command from a series of images with number and expected timestamp on it (assuming 120 fps constant frame rate):

ffmpeg -framerate 120 -i %03d.png -crf 0 -x264opts keyint=1:min-keyint=1 120.mp4

It's supposed to be constant frame rate, and all the frames are I frames. I expect frame 6 will show up exactly at time 0.05 second [0.05, 0.0583333), as the pts_time shown in ffmpeg and ffprobe:

[Parsed_showinfo_0 @ 0x7fba11404080] n: 6 pts: 768 pts_time:0.05 pos: 36021 fmt:yuv444p sar:0/1 s:1552x878 i:P iskey:1 type:I checksum:2CDED07A plane_checksum:[A86DBAAD C4CB8EF2 DDC586CC] mean:[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]

But in reality, it shows up since 0.049943 second. I use ffmpeg to extract that time with 0.0001 second duration

ffmpeg -ss 00:00:00.049943 -i 120_keyint_1.mp4 -t 00:00:00.0001 out.mp4

and get this video, which shows frame 6.

I also tried playing this video on chrome, and set the currentTime of videoNode. It shows frame 5 at 0.049943, but shows frame 6 since 0.049968 (before 0.05!).

However, I tried another encoding method and get another constant frame rate video:

ffmpeg -framerate 120 -i %03d.png -vcodec libx264 -f mp4 -movflags faststart 120.mp4

theoretically frame 6 should also appear in time range [0.05, 0.0583333), but in Chrome frame 6 will not show up until currentTime >= 0.051 second. More interestingly, I get frame 6 at 0.049943 second using ffmpeg, the same extraction command above.

Does this mean in MPEG4 h.264 video, we cannot rely on pts_time from ffmpeg to determine exact show time of a specific frame and it's video player specific?

1
Yes, some jitter is expected. Curious, what's your application that requires microsecond precision?Gyan
My web app is for online video editing and require frame accuracy. We're looking for a video format that can have strict frame to timestamp mapping.Lincolnhuj
Actual video playback imprecision has no impact on how you store or manipulate timestamps in software or file data structures.Gyan

1 Answers

2
votes

I think the issue is the Movie Header scale of 1000 in your file which is the hard wired default of ffmpeg. (libavformat\movenc.h line 32: #define MOV_TIMESCALE 1000)

Your frame rate of 120 fps can't be express in 1/1000s - so ffmpeg produces rounding errors.

1000 as default time scale is a poor choice and it can't be changed without modifying ffmpeg's source code.

I would change #define MOV_TIMESCALE 1000 to #define MOV_TIMESCALE 600 or some other value that is divisible by 120 and recompile ffmpeg.