Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
lorenzopreda opened this issue Oct 11, 2023 · 0 comments

Comments

@lorenzopreda
Copy link

lorenzopreda commented Oct 11, 2023

General information:

  • OS name: Windows
  • OS version: 10
  • OS architecture: 64 bits
  • Resolutions:
    • Monitor 1: 1920x1080
  • Python version: 3.10
  • MSS version: 9.1.0

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants