My Screen Recorder built using OpenCV and PyAutoGUI records only one frame

Viewed 243

I am building a Screen Recorder in Python using numpy, OpenCV and PyAutoGUI. I have used tkinter for GUI Purposes. The problem with my screen recorder is that it records only one frame when I click on the Record Screen Button and then the screen gets jammed and I can't do anything. Here is my code so far:

from tkinter import *
import cv2
import numpy as np
import pyautogui

resolution = (1366,768)

Specify video codec:

codec = cv2.VideoWriter_fourcc(*"XVID")

Specify name of Output file:

filename = "Recordings.avi"

Specify frames rate (we can choose any value and experiment with it):

fps = 30.0

Creating a VideoWriter object:

out = cv2.VideoWriter(filename, codec, fps, resolution)

def startRecording():
  
  window.iconify()
  while True:
    img = pyautogui.screenshot()

    # Convert the screenshot to a numpy array
    frame = np.array(img)

    # Convert it from BGR(Blue, Green, Red) to
    # RGB(Red, Green, Blue)
    
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # Write it to the output file
      out.write(frame)

def stopRecording():
  cv2.destroyAllWindows()
  out.release()
  window.destroy()



window = Tk()
window.title("Screen Recorder")
window.geometry("400x150")
window.config(bg='pink')

recordButton = Button(window,text="Record(F9)",font=("Bell MT",20),width=20,command=startRecording)
recordButton.pack(pady=(10,0))

stopButton = Button(window,text="Stop(F10)",font=("Bell MT",20),width=20,command=stopRecording)
stopButton.pack(pady=(10,0))

mainloop()
1 Answers

You cannot do a blocking call in a button callback. As you wrote it startRecording will never end and will hence block tkinter mainloop. The recording probably works but your UI becomes unresponsive.

Your best shot would be to schedule the recording (look for the after method): record one frame every x millisecond.

Here is a simplified example based on your original code (you need to complete it)

continueRecording = True # must be declared before stopRecording 
window = Tk() # must be declared before recordOneFrame

def stopRecording():
    global continueRecording
    continueRecording = False 

def recordOneFrame():
    global continueRecording
    img = pyautogui.screenshot()

    # Convert the screenshot to a numpy array
    frame = np.array(img)

    # Convert it from BGR(Blue, Green, Red) to
    # RGB(Red, Green, Blue)
    
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # Write it to the output file
    out.write(frame)
    if continueRecording:
        window.after(round(1/25. * 1000),recordOneFrame)
        

def startRecording():
    recordOneFrame()
Related