使用 OpenCV 和 PyAutoGUI 构建的我的屏幕录像机只记录一帧

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

我正在 Python 使用 numpy、OpenCV 和 PyAutoGUI 构建屏幕录像机。我已经将 tkinter 用于 GUI 目的。我的屏幕录像机的问题是,当我单击“录制屏幕”按钮时,它只录制一帧,然后屏幕卡住了,我什么也做不了。到目前为止,这是我的代码:

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

resolution = (1366,768)

指定视频编解码器:

codec = cv2.VideoWriter_fourcc(*"XVID")

指定输出文件的名称:

filename = "Recordings.avi"

指定帧率(我们可以选择任何值并进行试验):

fps = 30.0

正在创建一个 VideoWriter 对象:

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

您不能在按钮回调中进行阻塞调用。 正如您所写的那样,startRecording 将永远不会结束,因此会阻塞 tkinter mainloop。录音可能有效,但您的 UI 变得无响应。

最好的方法是安排录制时间(寻找 after 方法):每 x 毫秒录制一帧。

这是一个基于您的原始代码的简化示例(您需要完成它)

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