Python Screen recorder stops working after a while

24 views Asked by At

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

There are 0 answers