原正常录屏代码现输出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
相关产品推荐
相关产品推荐

