Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams
import os
import cv2
path='/home/nlpr4/video-data/UCF-101/GolfSwing/v_GolfSwing_g24_c06.avi'
cap=cv2.VideoCapture(path)
video_length=int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT))
success=True
count=0
while success:
    success,image=cap.read()
    if success==False:
        break
    count=count+1
print video_length,count

output:

why the two numbers different? what's wrong?

Not sure, but I think read FRAME COUNT would require reading total number of frames from file metadata, but count variable needs actual decoding of frame. if decoding of 147th frame failed, this would cause the issue. – saurabheights Jan 15, 2017 at 15:14 2 years has passed. And there is no more new answers. Is it possible to accept my answer? – Wang Jun 25, 2019 at 11:49

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.

This answer is incorrect and misleading. There is nothing wrong with OpenCV's calculation here; it takes the expected number of frames and rounds it to the nearest integer. There is nothing inaccurate about this rounding because the duration of a video is always a multiple of 1/FPS. The answer by @ilke444 is the true answer. – Vic Jan 15, 2020 at 5:18 Even though the answer is not 100% precise, sharing the implementation details makes it easy to understand what is going on under the hood - and makes it obvious where potential errors can occur (nb_frames not present, inaccurate fps, rounding errors ...) – Joma Jun 15, 2021 at 6:35

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.

video_capture = cv2.VideoCapture(video) video_length = int(video_capture.get(cv2.CAP_PROP_FRAME_COUNT)) count = 0 while(True): # Capture frame-by-frame ret, frame = video_capture.read() if not ret: break count += 1 print video_length, count # When everything done, release the capture video_capture.release() cv2.destroyAllWindows()

On my machine it gives me:

$ ./openstack_video_frames.py 
1232 1232
                i had the same question, it gives the correct video_length for some videos, but fails for others, All the videos are the same format, same compression, there can be a difference of 0, 1, 2, 3, up to 3 after i tested 20 videos. I dont know if that is a bug of opencv....
– shelper
                May 24, 2016 at 14:43