BoboTiG / python-mss

An ultra fast cross-platform multiple screenshots module in pure Python using ctypes.
https://pypi.org/project/mss/
MIT License
987 stars 88 forks source link

DEBUG:root:gdi32.GetDIBits() failed. after a couple of minutes of recording #268

Open lorenzopreda opened 10 months ago

lorenzopreda commented 10 months ago

General information:

Description of the warning/error

I'm trying to generate a perpetual screen recorder that splits videos every n minutes. I got the error DEBUG:root:gdi32.GetDIBits() failed. after a couple of minutes that the script is running, like the grab command cannot take screenshots anymore. Here is my code:

import configparser
import ctypes
import time
import cv2 as cv
import mss
import numpy as np
import win32gui
from PIL import Image
import customtkinter as tk
import os
import logging
import sys
import os.path
from threading import Thread

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():
    cursor_img = Image.open(get_path("cursor.png"))

    pixdata = cursor_img.load()

    width, height = cursor_img.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)

    pos_win = (0, 0)
    try:
        pos_win = win32gui.GetCursorPos()
    except Exception as ex:
        logging.debug(ex)
        print(ex)
    ratio = ctypes.windll.shcore.GetScaleFactorForDevice(0) / 100
    cursor_pos = (round(pos_win[0] * ratio), round(pos_win[1] * ratio))
    return cursor_img, cursor_pos

def screenshot():
    global recording, rgb_frame

    monitor = {'top': 0, 'left': 0, 'width': 1920, 'height': 1080}
    while recording:
        time.sleep(0.05)
        with mss.mss() as sct:
            try:
                screen = sct.grab(monitor)
            except Exception as ex:
                logging.debug(ex)
                print(ex)
            else:
                img = Image.frombytes("RGB", screen.size, screen.bgra, "raw", "BGRX")
                cursor, pos = get_cursor()

                img.paste(cursor, pos, cursor)
                frame = np.array(img)
                rgb_frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
            sct.close()

def record():
    global recording, rgb_frame, writer

    start_acq = time.time()
    start_split = time.time()

    while recording:
        if time.time() - start_acq >= spf:
            start_acq = start_acq + spf
            writer.write(rgb_frame)

        if time.time() - start_split >= split:
            start_acq = time.time()
            start_split = time.time()
            writer.release()
            cv.destroyAllWindows()
            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')))
    writer.release()
    cv.destroyAllWindows()

if __name__ == "__main__":
    logging.basicConfig(filename="log.txt", level=logging.DEBUG)

    img_init = Image.open(get_path("cursor.png"))
    frame_init = np.asarray(img_init)
    rgb_frame = cv.cvtColor(frame_init, cv.COLOR_BGR2RGB)

    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)

    t1 = Thread(target=screenshot)
    t2 = Thread(target=record)
    t1.start()
    t2.start()
    while recording:
        window.update()
    t2.join()
    t1.join()
    window.destroy()`

### Full message

    DEBUG:root:gdi32.GetDIBits() failed.

Thank you in advance

Upvote & Fund

Fund with Polar