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

如何修改PySimpleGUI录屏代码以解决录制文件无法打开问题

解决PySimpleGUI摄像头应用录制文件无法打开的问题

核心问题是GUI事件循环和视频录制逻辑抢占主线程资源,导致视频文件写入不完整(比如缺少文件头、帧数据中断),最终无法正常打开。以下是具体修改方案:

关键修改思路

  • 将录制逻辑移到独立线程运行,避免阻塞GUI事件循环
  • 确保录制结束时完整释放视频写入器和摄像头资源
  • 避免在GUI事件回调中执行耗时的帧处理/写入操作

修改后的代码示例

1. 封装录制线程类

import threading
import cv2

class RecorderThread(threading.Thread):
    def __init__(self, cap, output_path, fps=20.0, frame_size=None):
        super().__init__()
        self.cap = cap
        self.output_path = output_path
        self.fps = fps
        self.frame_size = frame_size if frame_size else (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
        self.is_recording = False
        self.writer = None

    def run(self):
        self.is_recording = True
        # 选择兼容性好的编码格式,AVI用XVID,MP4用mp4v
        fourcc = cv2.VideoWriter_fourcc(*'XVID')
        self.writer = cv2.VideoWriter(self.output_path, fourcc, self.fps, self.frame_size)
        
        while self.is_recording:
            ret, frame = self.cap.read()
            if ret:
                self.writer.write(frame)
            else:
                break
        # 强制释放写入器,保证文件写入完整
        if self.writer:
            self.writer.release()
        self.is_recording = False

    def stop(self):
        self.is_recording = False

2. 整合GUI主逻辑

import PySimpleGUI as sg

# 初始化摄像头
cap = cv2.VideoCapture(0)
if not cap.isOpened():
    sg.popup_error("无法打开摄像头")
    exit()

# GUI布局
layout = [
    [sg.Image(key='-CAM_FEED-')],
    [sg.Button('开始录制', key='-START-'), sg.Button('停止录制', key='-STOP-'), sg.Button('退出')]
]

window = sg.Window('Camera App.', layout, finalize=True)
recorder = None

while True:
    # 超时读取事件,保证摄像头画面实时刷新
    event, values = window.read(timeout=15)
    
    # 退出逻辑:先停止录制再释放资源
    if event in (sg.WIN_CLOSED, '退出'):
        if recorder and recorder.is_recording:
            recorder.stop()
            recorder.join()  # 等待线程完全结束
        cap.release()
        window.close()
        break
    
    # 更新摄像头画面到GUI
    ret, frame = cap.read()
    if ret:
        img_bytes = cv2.imencode('.png', frame)[1].tobytes()
        window['-CAM_FEED-'].update(data=img_bytes)
    
    # 开始录制
    if event == '-START-':
        if not (recorder and recorder.is_recording):
            recorder = RecorderThread(cap, 'recorded_video.avi')
            recorder.start()
            sg.popup_auto_close("录制已启动", auto_close_duration=1)
    
    # 停止录制
    if event == '-STOP-':
        if recorder and recorder.is_recording:
            recorder.stop()
            recorder.join()
            sg.popup_auto_close("录制已停止", auto_close_duration=1)

重要说明

  1. 编码格式匹配:输出文件后缀要和编码格式对应,比如用XVID编码对应.avi,mp4v对应.mp4,否则文件可能无法播放。
  2. 资源释放顺序:必须先停止录制线程,等待线程执行完释放VideoWriter,再释放摄像头,否则会导致文件损坏。
  3. 线程安全:录制线程只负责读取帧并写入,主线程负责GUI更新和摄像头初始化/释放,避免多线程同时操作摄像头对象引发冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 15:15:46