Performing pip install python-opencv fixed the problem and the FPS is correctly detected.
EDIT: tested with python 3.8 and indeed it is pip install opencv-python. Cannot remember two years ago what python I was using.
EDIT November 2022: please also check Perry's answer below, if you are using a newer opencv-python version
python - Understanding the function CAP_PROP_FPS in cv2 - Stack Overflow
set property of cv2.VideoCapture is returning false for cv2.CAP_PROP_FPS
opencv - python cv2.CAP_PROP_FRAME_COUNT get wrong result, and also the cv2.CAP_PROP_FPS get wrong fps - Stack Overflow
python - OpenCV gives incorrect FPS and frame count of a video - Stack Overflow
Performing pip install python-opencv fixed the problem and the FPS is correctly detected.
EDIT: tested with python 3.8 and indeed it is pip install opencv-python. Cannot remember two years ago what python I was using.
EDIT November 2022: please also check Perry's answer below, if you are using a newer opencv-python version
The recent versions of opencv-python will give an error called AttributeError because cv2 doesn't have any attribute named cv.
Instead use the following
import cv2
vidcap = cv2.VideoCapture('some_video.avi')
fps = vidcap.get(cv2.CAP_PROP_FPS)
print(f"{fps} frames per second")
This will give the frames per second value
I know this thread is old however people still experiencing this, it seems like it is an ongoing issue: https://github.com/opencv/opencv/issues/16821. I ran into this same issue with .mp4 and what solved it for me was exporting to .mov instead. Not sure why .mp4 is having issues but seems to be a common trend in the github issue
I had the same issue, i fixed it by fixing presentation timestamp of the video in python, you have to install ffmpeg to run the command below, here is the command:
ffmpeg_command = [
'ffmpeg',
'-fflags', '+genpts', # Fix presentation timestamps
'-i', renamed_path,
'-c:v', 'copy', # Copy the video stream without re-encoding
'-ignore_unknown', # Ignore unknown streams or errors
'-y', # Overwrite the output file if it exists
output_path
]
subprocess.run(ffmpeg_command, check=True)
In OpenCV 3.2, drop the CV in front of the flag.
This should work just fine
videoCapture = cv2.VideoCapture(file_path)
fps = videoCapture.get(cv2.CAP_PROP_FPS)
size = (int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),
int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
Eshirima answer solved the problem. But just for reference i want to show you one more way of performing these operations as mentioned in docs: https://docs.opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html#videocapture-get
videoCapture = cv2.VideoCapture(file_path)
width = int(videoCapture.get(3))
height = int(videoCapture.get(4))
fps = int(videoCapture.get(5))
The get() for CAP_PROP_FRAME_COUNT is never supposed to be accurate! If you check the opencv source code. You can find this:
int64_t CvCapture_FFMPEG::get_total_frames() const
{
int64_t nbf = ic->streams[video_stream]->nb_frames;
if (nbf == 0)
{
nbf = (int64_t)floor(get_duration_sec() * get_fps() + 0.5);
}
return nbf;
}
This means it will first look into the stream header for nb_frames, which you can check with ffprobe. If there is no such field, then there is no better way to get frame number than directly decoding the video. The opencv did a rough estimation by get_duration_sec() * get_fps() + 0.5 which surely not mean for accuracy.
Thus, to obtain the correct frame number you have to decode and read through the entire stream, or you have to ask the video generator to generate correct stream header with nb_frames field.
It is unfortunately to see after almost 10 years opencv still does not correct the implementation: we should use av_read_frame(fmt_ctx, &pkt) to read and parse all packet without actual decode them.
I personally stopped relies on opencv for video decoding more than 10 years ago, but recently I have to collaborate with some project using opencv to do so. I have to call ffprobe in a subprocess to get the correct frame counts:
ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 input.mp4
CV_CAP_PROP_FRAME_COUNT gives the property of 'number of frames', that comes from the video header. The other number is basically "How many frames can I read from this video file?".
If the video contains frames that cannot be read/decoded (e.g., due to being corrupted), OpenCV skips those frames (after trying to read them) and gives you the next valid frame. So the difference between your two numbers is the number of frames that couldn't be read.
Also, if your video header is corrupted and/or cannot be parsed by the underlying codecs that OpenCV uses, then those numbers can be different too.