zergon321/reisen

interesting observation regarding framerates

Closed this issue · 1 comments

I found a small issue with your player example code:

videoFPS, _ := media.Streams()[0].FrameRate()
spf := 1.0 / float64(videoFPS)
frameDuration, err := time.ParseDuration(fmt.Sprintf("%fs", spf)) 

You are ignoring the denominator here which is fine for your sample video but it should be considered for the general case.

But it gets more interesting yet. Some videos come with valid frame rate of 29.97. In this case the nominator will be 30000 and the denominator will be 1001 (which again is correct). However, if I play a video with that frame rate I observe the increasing drift between video and audio I reported in a previous issue. It gets better: If I manually force the frame rate to 30 instead of 29.97 the drift between audio and video is gone!

I observed the same for videos with 23.98 frame rate: There is a drift unless I force the player to play at 24 frames per second.

Currently, I'm working with mp4 snippets I download from youtube. Of course there is a possibility that the metadata is wrong in my mp4s but I don't think so. Other video players play those videos correctly - but then again those other players may do a better job syncing audio and video and ignore the possibly flawed frame rate data in my videos.

Anyways, just wanted to bring this to your attention and see if you have any insight why I have to "round up" 29.97 to 30 and 23.98 to 24. Thanks!

stream.FrameRate() uses r_frame_rate() from ffmpeg. And as the documentation for the latter function says:

Real base framerate of the stream.

This is the lowest framerate with which all
timestamps can be represented accurately
(it is the least common multiple of all framerates
in the stream). Note, this value is just a guess!
For example, if the time base is 1/90000 and
all frames have either approximately 3600 or
1800 timer ticks, then r_frame_rate will be 50/1.

So yeah, there is no consistent framerate across video frames. That's why each frame has a PTS (or presentation offset in Reisen).

Also there's another function in ffmpeg called avg_frame_rate(). I wanted to simplify things and didn't include this function in the library API, but I could if you'd like me to do that.