Why does cv2.VideoCapture.read() return the same frame from a camera

Hi, I’m using python api to read images from an usb camera on win11. Here is my code:

import time

import cv2
import numpy as np
from multiprocessing import Queue, Process

def collect_frames(que):
    # camera settings
    cap = cv2.VideoCapture(0)
    cap.set(cv2.CAP_PROP_BUFFERSIZE, 0)
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
    cap.set(cv2.CAP_PROP_FPS, 30)

    while cap.isOpened():
        res, frame = cap.read()
        if res:
            time.sleep(1 / 30)

if __name__ == '__main__':
    que = Queue()
    collect_process = Process(target=collect_frames, args=(que,))

    prev_frame = None
    while True:
        if not que.empty():
            frame_que = que.get()
            if np.all(prev_frame == frame_que):
                print("get the same frame!")
            prev_frame = frame_que
            cv2.imshow("cam", frame_que)
            c = cv2.waitKey(1)
            if c == 27:


I expect cv2.VideoCapture.read() to return a new frame every time it gets called, but it turns out that a lot of frames are the same as the previous one. WHY?
Besides, multithreading implementation of above codes meets the same problem.
FYI, I’m trying to save specified number of frames from the camera, but I found there are same images saved. This is how I found this problem.

guessing here…

your room is dark. the camera compensates by extending the exposure beyond a single frame. it then emits frames at the originally requested frame rate, but the picture only changes once every exposure. this appears as “duplicates”.

or the webcam can’t move the data over the USB cable at the requested frame rate, so the driver compensates by duplicating some frames. it’s possible but unlikely. the video mode would have been rejected and a lesser one chosen automatically by the driver.

you should actually see a “stuttering” video from any program that reads your webcam.

also, time.sleep has no business being called there. the read() call already waits for a fresh frame from the device.