pythonrecordcodecscreen-capturepython-mss

python opencv2 record screen


I am trying to make a screen recorder using python opencv along with the mss library. I can not get it to record a video. Whenever I stop the application - the file size becomes static such as sizes as for example 6kB - depending on the codec I used.

I have read that the capture must be the same size as the screen resolution which it is - but it still does not record.

I have also tried to use various codecs such as *'MP4V' but whatever I try - it does not save a proper recording.

I am using a MAC with a m1 processor if that matters.

import numpy as np
import cv2
import glob
from moviepy.editor import VideoFileClip
from mss import mss
from PIL import Image
import time

fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('outpute.avi', fourcc, 60, (2560,1600))

with mss() as sct:
    
    # Part of the screen to capture
    monitor = {"top": 0, "left": 0, "width": 2560, "height": 1600}

    while "Screen capturing":
        last_time = time.time()

        # Get raw pixels from the screen, save it to a Numpy array
        img = np.array(sct.grab(monitor))

        # Display the picture
        cv2.imshow("OpenCV/Numpy normal", img)

        # Write the image
        out.write(img)
    
        print("fps: {}".format(1 / (time.time() - last_time)))

        # Press "q" to quit
        if cv2.waitKey(25) & 0xFF == ord("q"):
            cv2.destroyAllWindows()
            break

Solution

  • After debugging I noticed that monitor values has to be divided by 2 in order to work. No idea why this is the case - but I debugged it and saw that this was the case.

    I also realized that I had to convert from BGR to RGB before I am writing it to a video file. Otherwise it won't work.

    I also changed the format, but it was not part of the problem I do not believe.

    Here is the working code

    import numpy as np
    import cv2
    import glob
    from moviepy.editor import VideoFileClip
    from mss import mss
    from PIL import Image
    import time
    import pyautogui
    
    SCREEN_SIZE = tuple((2880,1800))
    
    fourcc = cv2.VideoWriter_fourcc(*'MP4V')
    out = cv2.VideoWriter('output.mp4', fourcc, 60, (SCREEN_SIZE))
    
    with mss() as sct:
        
        # Part of the screen to capture
        monitor = {"top": 0, "left": 0, "width": 1440, "height": 900}
        
        while True:
            last_time = time.time()
    
            img = np.array(sct.grab(monitor))
     
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    
            out.write(img)
    
            print("fps: {}".format(1 / (time.time() - last_time)))
    
            if cv2.waitKey(2) & 0xFF == ord("q"):
                cv2.destroyAllWindows()
                break
    

    (Ignore the extra libraries I added)