Search code examples
pythonimageopencvdetection

Python Opencv control (increase/decrease) the video playback speed as custom


I'm writing a program to control the video playback speed as custom rate.

Is there is anyway to achieve that?

What code should be added to control the playback speed?

import cv2

cap = cv2.VideoCapture('video.mp4')

while(cap.isOpened()):
    ret, frame = cap.read()
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Solution

  • In the docs it is stated:

    Note

    This function should be followed by waitKey function which displays the image for specified milliseconds. Otherwise, it won’t display the image. For example, waitKey(0) will display the window infinitely until any keypress (it is suitable for image display). waitKey(25) will display a frame for 25 ms, after which display will be automatically closed. (If you put it in a loop to read videos, it will display the video frame-by-frame)

    In cv2.waitKey(X) function X means the number of milliseconds for an image to be displayed on the screen. In your case it is set to 1, so theoretically you are able to achieve 1000 fps (frames per seconds). But frame decoding takes time in VideoCapture object and limits your framerate. To change the playback speed you need to declare variable and use it as a parameter in waitKey function.

    import cv2
    
    cap = cv2.VideoCapture('video.mp4')
    frameTime = 10 # time of each frame in ms, you can add logic to change this value.
    while(cap.isOpened()):
        ret, frame = cap.read()
        cv2.imshow('frame',frame)
        if cv2.waitKey(frameTime) & 0xFF == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()
    

    Alternatively, as frame decoding is the most time consuming task you can move it to the second thread and use a queue of decoded frames. See this link for details.

    The third approach is to separate grabbing and decoding process and simply decode every nth frame. That will result in displaying only a subset of frames from the source video but from the user perspective the video will be played faster.

    import cv2
    
    cap = cv2.VideoCapture('video.mp4')
    i=0 #frame counter
    frameTime = 1 # time of each frame in ms, you can add logic to change this value.
    while(cap.isOpened()):
        ret = cap.grab() #grab frame
        i=i+1 #increment counter
        if i % 3 == 0: # display only one third of the frames, you can change this parameter according to your needs
            ret, frame = cap.retrieve() #decode frame
            cv2.imshow('frame',frame)
            if cv2.waitKey(frameTime) & 0xFF == ord('q'):
                break
    cap.release()
    cv2.destroyAllWindows()