You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

原正常录屏代码现输出256KB损坏AVI,VideoWriter问题求助

问题诊断与修复方案

你的核心问题是主线程被阻塞式while循环卡死,导致Qt事件循环无法正常运行,进而让cv2.VideoWriter无法正确写入帧数据,最终生成仅包含文件头的损坏AVI(256KB是典型的无帧数据AVI文件大小)。以下是具体修复步骤:


1. 替换阻塞循环为Qt定时器触发截图

原代码中startRecording里的while循环会彻底阻塞Qt主线程,导致UI响应、定时器更新、甚至视频写入操作全部异常。改用QTimer定时触发截图,避免阻塞:

修改Recording类的初始化与核心方法:

class Recording:
    def __init__(self, main_window):
        self.main_window = main_window
        self.startTimer = 0
        self.timer = QTimer(self.main_window)
        self.timer.timeout.connect(self.updateTimer)
        self.capture_timer = QTimer(self.main_window)  # 新增截图定时器
        self.capture_timer.timeout.connect(self.capture_frame)  # 绑定截图逻辑
        self.out = None

    def startRecording(self):
        self.startTimer = 0
        self.onLive = True

        self.main_window.pushButton.hide()
        self.main_window.pushButton_2.show()

        # 先验证选择的分辨率与实际截图是否匹配
        test_img = pyautogui.screenshot()
        test_frame = np.array(test_img)
        actual_res = (test_frame.shape[1], test_frame.shape[0])
        selected_res = (self.width, self.height)
        if actual_res != selected_res:
            print(f"警告:选择分辨率{selected_res}与实际屏幕不匹配,将使用实际分辨率{actual_res}")
            self.width, self.height = actual_res

        codec = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
        filename = f"{self.prefName}.avi"
        self.out = cv2.VideoWriter(filename, codec, 20.0, (self.width, self.height))

        # 检查VideoWriter是否成功初始化
        if not self.out.isOpened():
            print("错误:无法创建视频写入器,请检查编码器、路径权限或分辨率")
            self.stopRecording()
            return

        self.timer.start(1000)
        self.capture_timer.start(int(1000/20))  # 20FPS,每50ms触发一次截图
        systemTray(self.onLive)

    def capture_frame(self):
        if not self.onLive:
            return
        img = pyautogui.screenshot()
        frame = np.array(img)
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        # 确保帧分辨率与写入器一致再写入
        if (frame.shape[1], frame.shape[0]) == (self.width, self.height):
            self.out.write(frame)
        cv2.imshow('Monitor', frame)
        if cv2.waitKey(1) == ord('p'):
            self.stopRecording()

    def stopRecording(self):
        self.startTimer = 0
        self.onLive = False

        self.main_window.label_2.setText("00:00:00")
        self.timer.stop()
        self.capture_timer.stop()  # 停止截图定时器
        if self.out is not None:
            self.out.release()
        cv2.destroyAllWindows()

        self.main_window.pushButton.show()
        self.main_window.pushButton_2.hide()

        systemTray(self.onLive)

2. 修复倒计时的阻塞问题

原countdown方法用time.sleep阻塞主线程,改用Qt定时器实现:

def countdown(self):
    self.countdown_time = 5
    self.countdown_timer = QTimer(self.main_window)
    self.countdown_timer.timeout.connect(self.update_countdown)
    self.update_countdown()
    self.countdown_timer.start(1000)

def update_countdown(self):
    self.main_window.label_3.setText(str(self.countdown_time))
    if self.countdown_time <= 0:
        self.countdown_timer.stop()
        self.startRecording()
    self.countdown_time -= 1

3. 验证初始化顺序

确保调用startRecording前,已经执行了createFolder、recordLocation、initVideoWriter三个方法,否则self.width、self.height、self.prefName可能未初始化,导致视频写入器创建失败。

4. 额外排查点

  • 尝试更换编码器:比如将MJPG换成cv2.VideoWriter_fourcc(*'XVID')(兼容多数播放器)或cv2.VideoWriter_fourcc(*'MP4V')(生成MP4格式)。
  • 检查输出路径权限:手动确认~/Documents/Records文件夹存在且可写入。
  • 测试单独写入帧:在代码中添加print(self.out.write(frame)),如果返回False,说明帧分辨率与写入器不匹配。

内容的提问来源于stack exchange,提问作者metehangnn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 02:52:25