I want to check the frame rate of many videos to double it. I use ffprobe to get r_frame_rate which is evaluated to a decimal, then fed into ffmpeg as rscale -r {2*fps}, or into mkvmerge as 0:{2*fps}fps.
And so, I start with:
ffprobe -v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=r_frame_rate faulty.mkv
500/21
That can't be right, what kind of fps is 500/21? Turns out saving it with 500/21 desync with audio, which doesn't happen for 24000/1001. This value is definitely wrong.
At least ffprobe 4 read the correct codec timescale i.e. 23.98 tbc (default):
ffprobe faulty.mkv (version 4.3.5-0+deb11u1+rpt3)
Stream #0:0: Video: (...), 23.81 fps, 23.81 tbr, 1k tbn, 23.98 tbc (default)
but in later versions tbc has been deprecated:
Stream #0:0: Video: (...), 23.81 fps, 23.81 tbr, 1k tbn (default)
However, MediaInfo simply gets it right:
mediainfo faulty.mkv =
(...)
Frame rate mode : Constant
Frame rate : 23.976 (24000/1001) FPS
(...)
I tried using -count_packets to then divide nb_read_packets of the stream by the duration of the file, I'm getting 1 second per hour error. This is much better compared to 23,8095, but packets are not frames. Only the prohibitively, unusably slow -count_frames gets me the exact value.
My workflow has to use ffprobe one way or another, so I'm reluctant to always run mediainfo on top of that for performance reasons. I get that the file is, well, faulty, but if mediainfo can do it, is there a way to make sure the correct frame rate is read with ffprobe without decoding the entire file as -count_frames seems to do?