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

12,118

Solution 1

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

Solution 2

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.

Share:
12,118
vishal
Author by

vishal

Updated on July 21, 2022

Comments

  • vishal
    vishal almost 2 years

    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()
    
  • vishal
    vishal over 4 years
    Yeah but that's for to decrease the speed. What i need is increase the video speed to 6x .
  • Piotr Siekański
    Piotr Siekański over 4 years
    Could you post the length, resolution and fps of the video?
  • vishal
    vishal over 4 years
    Actually, I wanna to create program which takes video as a input and play it in 6x or a custom playback speed. All I need is to play a video in fast forward , that's all.
  • vishal
    vishal over 4 years
    i changed the frametime to 1 its working but the speed is not enough , is there any other way to increase the playback speed more effectively. Anyway i really appreciate your help.
  • Piotr Siekański
    Piotr Siekański over 4 years
    Glad to hear that. If it answers your question, accept my answer.
  • vishal
    vishal over 4 years
    But its has one big problem friend, i want all frames to be shown. In the script it skips the frame and showing it means i'm losing a some frames while increase the framerate. I don't wanna to skip frame each and every frame is important to me so , any other ways. What i want is fast forward the video like the media player has it. just increase the frame shows rate without the skipping the frames
  • ENBYSS
    ENBYSS almost 4 years
    One thing to note is that audio is not sped up. If you'd like to do that you can add -af "atempo=2.0", for example to speed up the audio by 2x