vishal
vishal

Reputation: 472

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()

Upvotes: 3

Views: 26956

Answers (2)

Q2Learn
Q2Learn

Reputation: 323

You can use ffmpeg to speed up (or slow down) your video like fast forwarding by using "presentation time stamps".

For speed up an example would be:

ffmpeg -i YOUR_INPUT_MOVIE.mp4 -vf  "setpts=0.20*PTS" YOUR_OUTPUT_MOVIE.mp4

which will speed up your movie by 5x.

For slow down an example would be:

ffmpeg -i YOUR_INPUT_MOVIE.mp4 -vf  "setpts=5*PTS" YOUR_OUTPUT_MOVIE.mp4

which will slow down your movie by 5x.

Note: this method will drop frames.

Upvotes: 2

Piotr Siekański
Piotr Siekański

Reputation: 1715

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()

Upvotes: 5

Related Questions