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