Writing the webcam feed to a lossless, 1080p 30FPS video

Hello. I am trying to save the webcam feed acquired by the camera as a lossless, 30 FPS and 1080p video. This is what I’ve got so far:

from timeit import default_timer as timer
import time
import cv2

vid = cv2.VideoCapture(1, cv2.CAP_DSHOW)

# cv2.namedWindow("Webcam Feed", cv2.WND_PROP_FULLSCREEN)
# cv2.setWindowProperty("Webcam Feed", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

prev_frame_time = 0
new_frame_time = 0


timer_start = timer()

vid.set(3, 1920)
vid.set(4, 1080)

frame_w = int(vid.get(3))
frame_h = int(vid.get(4))
size = (frame_w, frame_h)


output = cv2.VideoWriter('kayit3.avi',
                         cv2.VideoWriter_fourcc(*'RGBA'),
                         30, size)

while vid.isOpened():
    ret, frame = vid.read()
    if ret == True:
        new_frame_time = time.time()
        fps = 1/(new_frame_time-prev_frame_time)
        prev_frame_time = new_frame_time
        fps = int(fps)
        fps = str(fps)
        
        # cv2.putText(frame, , (7, 210), 5, 3, (100, 255, 0), 3, cv2.LINE_AA)
        cv2.putText(frame, "FPS: "+fps, (7, 70), cv2.FONT_HERSHEY_PLAIN, 3, (100, 255, 0), 3, cv2.LINE_AA)

        cv2.imshow("Webcam", frame)
        output.write(frame)
    
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
    
timer_stop = timer()
vid.release()
output.release()
cv2.destroyAllWindows()

# print the duration
print("Seconds: {:.2f}".format(timer_stop-timer_start))
duration = int(timer_stop - timer_start)

This results in a 1080p video but the FPS averages 5 during recording.

If I don’t set any width & height values and go

frame_w = int(vid.get(3))
frame_h = int(vid.get(4))
size = (frame_w, frame_h)

then the recording & output video is smooth; FPS is 30, but the output resolution is 640x480.

OpenCV version: 4.6.0
Spyder version: 3.8.5
Webcam: Logitech C920s Pro, capable of 1080p and 30 FPS recording.

Any help is appreciated. Thanks in advance!

please show your understanding of the data rate required by an uncompressed 1080p video.

yes, you’re likely causing VideoWriter to write an uncompressed video stream to file.

you should just use ffmpeg, and request MJPEG from the webcam itself (C920 do MJPEG) and store that. this doesn’t require OpenCV, which is for computer vision, not for moving video data.

you won’t be getting 1080p uncompressed from a USB 2.0 webcam. maybe at 5 fps, but not more.

Hmm. A couple of questions, please indulge me:

From what I could gather from the internet, C920s is USB 3.0 ready, so it has a 5 Gbit/s bitrate, whereas an uncompressed, 1080p @ 60 FPS video has roughly 3 Gbit/s bitrate. So from the surface, it sounds possible, no?

Also, correct me if I’m wrong, but motion jpeg isn’t lossless, no?
I will try out FFMPEG again but more in-depth this time.
Thank you for your reply, and please note that I’m not at all familiar with this field.

no.

what makes you think that?

correct, but if that’s the only format the camera can emit that makes the data fit on USB 2.0, then you might as well capture that bitstream and save it, instead of decompressing it, which merely inflates the data with no gain at all.