0

I trying to record a 30 seconds video, but the output video are with just 15 seconds and accelerated.

import numpy as np
import os
import cv2
import time

filename = 'video.avi'
frames_per_second = 30.0
res = '480p'

def change_res(cap, width, height):
    cap.set(3, width)
    cap.set(4, height)

STD_DIMENSIONS =  {
    "480p": (640, 480),
    "720p": (1280, 720),
    "1080p": (1920, 1080),
    "4k": (3840, 2160),
}

def get_dims(cap, res='1080p'):
    width, height = STD_DIMENSIONS["480p"]
    if res in STD_DIMENSIONS:
        width,height = STD_DIMENSIONS[res]
    change_res(cap, width, height)
    return width, height

VIDEO_TYPE = {
    'avi': cv2.VideoWriter_fourcc(*'XVID'),
    'mp4': cv2.VideoWriter_fourcc(*'XVID'),
}

def get_video_type(filename):
    filename, ext = os.path.splitext(filename)
    if ext in VIDEO_TYPE:
      return  VIDEO_TYPE[ext]
    return VIDEO_TYPE['avi']

cap = cv2.VideoCapture(0)
fps = cap.get(cv2.CAP_PROP_FPS)
print(fps)

out = cv2.VideoWriter(filename, get_video_type(filename), 30, get_dims(cap, res))

stop_time = time.time() + 30.0
while stop_time >= time.time():
    ret, frame = cap.read()
    out.write(frame)

cap.release()
out.release()
cv2.destroyAllWindows()

I'm printed the FPS coming from video capture, and it's return 30.0. The camera is the Logitech C920.

Any help would be awesome.

  • 1
    This is because the `cv::VideoWriter` fps is greater than `cv::VideoCapture`. In other words your camera is not capturing frames at 30 FPS. – zindarod Jun 17 '18 at 20:35

1 Answers1

0

You are reading from your camera with VideoCapture and writing to your VideoWriter. You expect that the reading time will coincide with the writing time of your VideoWriter but obviously that's not the case.

I guess you are reading a number of frames in 30 sec (the time you specified for your loop) and since these number of frames is not big enough to create a 30-second video a smaller one is created. Roughly from your saying it would be you need 30*30 = 900 frames and you only got half of them let's say 450 frames. So, when you pass them to the writer they correspond to a 15-sec video. Since on the other hand you provided a 30-sec span for recording they correspond to 30-sec real action and that's why you see an accelerated version of only 15 seconds.

My guess is you can try some things to accelerate your video capturing or your video writing since you are applying them sequentially (one after the other that is). Your camera supports 30fps@1080p so I guess you can achieve your goal some how.

My first thought is to just record your images for 30 seconds and then write them in your video. This way you focus only in capturing the images at first. You can accomplish this by using a container like a list or a dict to hold your images. Then, after finishing the recording write them down. You can check the number you can catch in 30 seconds to see the actual fps for recording. If you get a value of let's say 850 frames you can create a 30-sec video of 850/30 = 28.33 fps which does not make much difference in practice instead of 30fps to represent a video that is not accelerated. Of course you should create a suitable VideoWriter in that case (pass a suitable 3rd parameter in constructor).

Eypros
  • 5,370
  • 6
  • 42
  • 75