Package: threaded-videocapture
Threaded-VideoCaptureA direct drop-in replacement for OpenCV'sVideoCapturethat runs in a background thread, allowing the main thread to
do useful work instead of waiting on frames.This library is useful if your code spend a lot of time waiting for new frames, or if you are processing a stream in
realtime and cannot process frames fast enough to keep up with the stream.Threaded-VideoCapturerequiresopencv-python4.0.0.21 or greater. It has been tested on Python 3.6, 3.7, 3.8. 3.9,
3.10, and 3.11, and is thoroughly typed.It is a young library. Therefore bugs may exist, and useful features may be missing. Bug reports,
feature requests, and pull requests are therefore highly appreciated!InstallationThreaded-VideoCaptureis available from PyPi. Run the following in a command line terminal:pip install threaded-videocaptureSimple exampleThreaded-VideoCapturecan be used exactly like the normalVideoCapture:import cv2
from threaded_videocapture import ThreadedVideoCapture

with ThreadedVideoCapture(0) as tvc:  # Open webcam stream
    while True:
        ret, frame = tvc.read()
        if ret:  # ret is True if a frame was obtained with tvc.read()
            cv2.imshow('frame', frame) 
        if ret is None:  # ret is None if tvc has stopped.
            print("End of stream.")
            break
        if cv2.waitKey(1) == ord('q'):
            breakDocumentationThreadedVideoCapturecreates a background thread with aVideoCaptureinstance in it. This instance will
continuously read frames and place them on a FIFO queue. When you callThreadedVideoCapture.read(), the oldest
frame is returned from the queue. If there are no frames in the queue, a(False, None)tuple is returned.An instantiatedThreadedVideoCapturewill eventually stop yielding frames. This is normal, and occurs for example
when:There are no more frames in the video fileA stream times outAn exception occursWhenThreadedVideoCapturestops, it will place a(None, None)tuple on the queue. This signifies thatThreadedVideoCapture.read()will never yield new frames until a new source has been opened withThreadedVideoCapture.open(). This can also be checked withThreadedVideoCapture.is_alive().Instantiation parametersThreadedVideoCapturetakes additional parameters compared toVideoCaptureduring instantiation:frame_queue_size,timeout,poll_rate, andlogger.
They are explained here.Frame queue sizeFrames read by theVideoCaptureinstance in the background thread will be placed on a queue, as explained above. When
the queue becomes full, the oldest item is deleted to make room for the new frame. The length of the queue can be
specified when instantiatingThreadedVideoCaptureto suit your needs. Be default, the queue length is 1, meaning that
only the most recent frame is available.TimeoutIfThreadedVideoCapturedoes not receive a new frame within a specified time, it will time out and quit. This is
useful for example when you are capturing a stream and you do not know when it will end. The timeout value can be
changed at any time. By default, the timeout is set to 1 second. The following example shows how to
start aThreadedVideoCapturethat will wait indefinitely for a single frame, then change its timeout and quit if
no frames are received within the timeout value.with ThreadedVideoCapture(0, timeout=None) as tvc:  # Open webcam stream with timeout disabled.
    # Poll for a single frame for eternity due to no timeout
    while True:
        ret, frame = cap.read() 
        if ret:
            break
    
    tvc.timeout = 2.5 # Set timeout to 2.5 seconds
    # Poll for frames for 2.5 seconds before ThreadedVideoCapture times out
    while True:
        ret, frame = tvc.read() 
        if ret is None:  # ret is only None if tvc has stopped.
            print("ThreadedVideoCapture has timed out.")
            breakPolling rateYou can limit how often theVideoCaptureinstance callsgrab()by specifying the polling rate at instantiation, or
at any other time. By default, it is not limited.LoggerTheThreaded-VideoCapturelibrary uses Pythons excellentlogginglibrary to log events. By defaultThreadedVideoCaptureuses its own logger named 'TVC', but you can provide it with a custom logger object at
instantiation. The logger is found atThreadedVideoCapture.logger.Reusing a ThreadedVideoCapture instanceYou can open a new video source without having to close your originalThreadedVideoCaptureinstance and creating a
new one. Simply callThreadedVideoCapture.open()with your new source parameters. This will release theVideoCaptureinstance for your old source,jointhe background thread, and create a newVideoCapturein its own thread for the
new video source. Example:# Example showing how to switch to a different webcam after 1 second with the same ThreadedVideoCapture instance.

from time import time
with ThreadedVideoCapture(0) as tvc:  # Open webcam 0 stream with default settings
    tick = time()
    while True:
        ret, frame = tvc.read()
        if ret:  # ret is True if a frame was obtained with tvc.read()
            cv2.imshow('frame', frame) 
        if cv2.waitKey(1) == ord('q'):
            break
        # After one second of opening the stream from webcam 0, we switch seamlessly to webcam 1.
        if time() - tick > 1:
            tvc.open(1)StatisticsThe current frames per second (FPS) and actual polling rate can be obtained withThreadedVideoCapture.fpsandThreadedVideoCapture.actual_poll_rate. These values are updated once per second.