i'm trying to create a perpetual screen recorder that just split videos after a certain time. It seems to work fine, but after 10/15 minutes the command for taking screenshots just stop working and the script is no longer capable to create videos.
I tried using both ImageGrab.grab() and pyautogui.screenshot() but they have the same behaviour.
Here is my code, if someone has already faced the problem and can help me. Thank you in advance.
import configparser
import ctypes
import time
import cv2 as cv
import numpy as np
import pyautogui
import win32gui
import win32ui
from PIL import Image, ImageGrab
import customtkinter as tk
import os
import logging
import sys
import os.path
def get_path(filename):
if hasattr(sys, "_MEIPASS"):
return os.path.join(sys._MEIPASS, filename)
else:
return filename
def stoprec():
global recording
recording = False
def get_cursor():
try:
hcursor = win32gui.GetCursorInfo()[1]
hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
hbmp = win32ui.CreateBitmap()
hbmp.CreateCompatibleBitmap(hdc, 36, 36)
hdc = hdc.CreateCompatibleDC()
hdc.SelectObject(hbmp)
hdc.DrawIcon((0, 0), hcursor)
bmpinfo = hbmp.GetInfo()
bmpstr = hbmp.GetBitmapBits(True)
cursor = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0,
1).convert("RGBA")
win32gui.DestroyIcon(hcursor)
win32gui.DeleteObject(hbmp.GetHandle())
hdc.DeleteDC()
pixdata = cursor.load()
width, height = cursor.size
for y in range(height):
for x in range(width):
if pixdata[x, y] == (0, 0, 0, 255):
pixdata[x, y] = (0, 0, 0, 0)
(hotspotx, hotspoty) = win32gui.GetIconInfo(hcursor)[1:3]
ratio = ctypes.windll.shcore.GetScaleFactorForDevice(0) / 100
pos_win = win32gui.GetCursorPos()
pos = (round(pos_win[0] * ratio - hotspotx), round(pos_win[1] * ratio - hotspoty))
return cursor, pos
except Exception as ex:
logging.debug(ex)
cursor = Image.open(get_path("cursor.png"))
return cursor, (0, 0)
def record():
global start_split, writer, spf
try:
img = pyautogui.screenshot()
except Exception as ex:
logging.debug(ex)
else:
cursor, pos = get_cursor()
img.paste(cursor, pos, cursor)
frame = np.array(img)
rgb_frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
writer.write(rgb_frame)
if __name__ == "__main__":
logging.basicConfig(filename="log.txt", level=logging.DEBUG)
start_acq = time.time()
start_split = time.time()
recording = True
config = configparser.ConfigParser()
config.read_file(open('config.txt'))
save_path = config.get('data', 'save_path')
label = config.get('data', 'label')
fps = float(config.get('data', 'fps'))
codec = config.get('data', 'codec')
ext = config.get('data', 'extension')
split = float(config.get('data', 'split'))
spf = 1 / fps
screensize = (1920, 1080)
four_char_code = cv.VideoWriter_fourcc(*str(codec))
writer = cv.VideoWriter(str(save_path) + '\\' + str(label) + ' ' + str(time.strftime('%d-%m-%Y_%H-%M')) + '.' +
str(ext), four_char_code, fps, screensize)
tk.set_appearance_mode("System") # Modes: system (default), light, dark
tk.set_default_color_theme("blue") # Themes: blue (default), dark-blue, green
window = tk.CTk()
window.title('ScreenVideo')
window.geometry('350x300')
stop = tk.CTkButton(master=window, text="Stop Recording", width=150, height=50, command=stoprec)
stop.place(relx=0.5, rely=0.5, anchor='center')
window.protocol('WM_DELETE_WINDOW', stoprec)
while recording:
window.update()
if time.time() - start_acq >= spf:
start_acq = start_acq + spf
record()
if time.time() - start_split >= split:
start_acq = time.time()
start_split = time.time()
writer.release()
print('Video Split ' + str(time.strftime('%d/%m/%Y - %H:%M')))
writer = cv.VideoWriter(
str(save_path) + '\\' + str(label) + ' ' + str(time.strftime('%d-%m-%Y_%H-%M')) +
'.' + str(ext), four_char_code, fps, screensize)
print('Video Ended ' + str(time.strftime('%d/%m/%Y - %H:%M')))
window.destroy()
writer.release()
cv.destroyAllWindows()