简体   繁体   中英

why my output file of python script is empty

i am creating a python script to record the screen of desktop.

In this i am taking only the selected area by the user and only record the selected area and convert it into a video file.

but while doing this the output of the script is a empty video file(0 bytes)

can anybody tell me where am i doing wrong. As it was working fine without the bbox(x1,x2,y1,y2) .

here is the code: EDIT:

import tkinter as tk
from tkinter import *
from tkinter import ttk ,FLAT
from PIL import Image, ImageTk, ImageGrab, ImageEnhance
import cv2
import numpy as np
import threading
filename="test.avi"
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
frame_rate = 10
root = tk.Tk()


def show_image(image):
    win = tk.Toplevel()
    win.image = ImageTk.PhotoImage(image)
    tk.Label(win, image=win.image).pack()
    win.grab_set()
    win.wait_window(win)

def area_sel():
    x1 = y1 = x2 = y2 = 0
    roi_image = None

    def on_mouse_down(event):
        nonlocal x1, y1
        x1, y1 = event.x, event.y
        canvas.create_rectangle(x1, y1, x1, y1, outline='red', tag='roi')

    def on_mouse_move(event):
        nonlocal roi_image, x2, y2
        x2, y2 = event.x, event.y
        canvas.delete('roi-image') 
        roi_image = image.crop((x1, y1, x2, y2)) 
        canvas.image = ImageTk.PhotoImage(roi_image)
        canvas.create_image(x1, y1, image=canvas.image, tag=('roi-image'), anchor='nw')
        canvas.coords('roi', x1, y1, x2, y2)
        canvas.lift('roi') 

    root.withdraw()  
    image = ImageGrab.grab()  
    bgimage = ImageEnhance.Brightness(image).enhance(0.3)  
    win = tk.Toplevel()
    win.attributes('-fullscreen', 1)
    win.attributes('-topmost', 1)
    canvas = tk.Canvas(win, highlightthickness=0)
    canvas.pack(fill='both', expand=1)
    tkimage = ImageTk.PhotoImage(bgimage)
    canvas.create_image(0, 0, image=tkimage, anchor='nw', tag='images')
    win.bind('<ButtonPress-1>', on_mouse_down)
    win.bind('<B1-Motion>', on_mouse_move)
    win.bind('<ButtonRelease-1>', lambda e: win.destroy())
    win.focus_force()
    win.grab_set()
    win.wait_window(win)
    root.deiconify()  

    if roi_image:
        region = x1, y1, x2, y2

        start_recording(region) #calling main function to record screen
        return region


def recording_screen(x1, y1, x2, y2):
    global recording
    recording = True

    while recording:

        img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
        frame=np.array(img) # for recording
        out.write(cv2.cvtColor(frame,cv2.COLOR_RGB2BGR))

out = cv2.VideoWriter() 
def start_recording(region):
    x1,y1,x2,y2 = region
    if not out.isOpened():

            out.open(filename,fourcc, frame_rate,(x2-x1,y2-y1))
    threading.Thread(target=recording_screen, args=region, daemon=True).start()

def stop_recording():
    global recording
    recording = False
    out.release()

sel_area = ttk.Button(root, text='select area to Record', width=30, command=area_sel)
sel_area.grid(row=0, column=0)

stp_rec = ttk.Button(root, text='Stop Recording', width=30, command=stop_recording)
stp_rec.grid(row=0, column=1)

root.mainloop()

You are using ImageGrab which is macOS and Windows only, so I can't test your complete code on my setup.

The problem in your code is you have coupled the area selection and video recording. Once the area is selected and you have x1 , y1 , x2 , and y2 . Return these values. Initialize the cv2.VideoWriter the first time.

What you can try now is use the arguments pass to start_recording((x1, y1, x2, y2)) .

def start_recording(region):
    x1,y1,x2,y2 = region
    if not out.isOpened():

        out.open(filename,fourcc, frame_rate,(y2-y1,x2-x1)) #given x2 > x1, y2 > y1
    threading.Thread(target=recording_screen, args=region, daemon=True).start()

EDIT:

The issue was wrong shape passed in the following call.

out.open(filename,fourcc, frame_rate,(y2-y1,x2-x1))

The Size value passed is (y2-y1,x2-x1) ie (height, width) . However, the constructor expects (width, height) . See doc here .

Also, the img = ImageGrab.grab(bbox=(x1, y1, x2, y2)) returns an RGB image . But out.write(frame) expects a BGR image . It can be fixed as:

img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
frame = np.array(img)
out.write(cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM