Windows登出/关机时Python录屏MP4无法播放如何解决
问题根因
你遇到的MP4文件损坏问题,核心原因是进程被强制终止时,OpenCV的VideoWriter没有执行release()方法,MP4的文件头、帧索引信息没有写入到文件尾部,导致播放器无法识别文件结构。
你做的对照测试已经验证了这点:通过Ctrl+C、IDE停止按钮终止脚本时,Python进程会触发常规退出流程,隐式执行资源释放,文件可以正常播放;而强制关闭CMD窗口、系统登出/关机时,系统会直接终止进程,不会走常规的资源释放流程,因此文件损坏。
实现方案
核心目标是在所有进程退出场景下,保证VideoWriter.release()被执行,具体实现分两步:
1. 注册Windows系统信号处理函数
Windows在控制台关闭、用户登出、系统关机时,会给所有运行中的控制台进程发送对应控制信号,提前注册信号处理函数即可在进程被终止前拿到执行权,完成文件收尾。
需要处理的信号包括:
CTRL_C_EVENT:Ctrl+C终止CTRL_BREAK_EVENT:Ctrl+Break终止CTRL_CLOSE_EVENT:点击控制台窗口关闭按钮CTRL_LOGOFF_EVENT:用户登出系统CTRL_SHUTDOWN_EVENT:系统关机
完整可运行代码示例:
import cv2 import numpy as np import mss import win32api import sys # 全局资源实例 video_writer = None screen_capture = None def release_resource(): """统一的资源释放逻辑,保证MP4文件正确封装""" global video_writer, screen_capture if video_writer is not None and video_writer.isOpened(): video_writer.release() if screen_capture is not None: screen_capture.close() def console_signal_handler(signal_type): """Windows控制台信号处理回调""" if signal_type in [ win32api.CTRL_C_EVENT, win32api.CTRL_BREAK_EVENT, win32api.CTRL_CLOSE_EVENT, win32api.CTRL_LOGOFF_EVENT, win32api.CTRL_SHUTDOWN_EVENT ]: release_resource() return True return False # 注册信号处理 win32api.SetConsoleCtrlHandler(console_signal_handler, True) # 原有初始化逻辑 screen_capture = mss.mss() fourcc = cv2.VideoWriter_fourcc(*'mp4v') video_writer = cv2.VideoWriter( recording_file_name_location, fourcc, 20.0, (1920, 1080) ) # 录制主循环,加finally做双保险 try: while True: frame = screen_capture.grab(screen_resolution) video_writer.write(np.array(frame)) except KeyboardInterrupt: pass finally: release_resource()
注意:系统关机/登出场景下,Windows只会给每个进程预留最多5秒的清理时间,release()操作仅写入文件元数据,耗时在毫秒级,完全可以在时间窗口内完成。
2. 高鲁棒性优化(可选)
如果需要应对极端场景下信号处理失效的问题,可以采用分段录制方案:
- 不要把所有帧写入单个MP4文件,每1~2分钟生成一个独立的小MP4文件
- 进程意外终止时,已经完成写入的小文件都是完整可播放的,不会出现整个录像全损的情况
- 录制结束后可以调用ffmpeg或者OpenCV把所有分段文件拼接成完整视频
如果你的脚本是通过pythonw.exe无窗口后台运行的,没有附加控制台,无法收到上述控制台信号,需要创建一个隐藏的顶层窗口,监听WM_ENDSESSION窗口消息来触发资源释放。
内容的提问来源于stack exchange,提问作者Belphegor
相关产品推荐
相关产品推荐

