OpenCV Python录制Windows屏幕视频播放过快问题排查
问题描述
在Windows系统下使用OpenCV结合pyautogui录制屏幕,录制功能正常,但播放录制的视频时速度过快。例如录制时长为60秒的内容,播放时被压缩到更短时间内快速播放。尝试调整不同的fps参数,但效果不明显。
原代码如下:
import cv2 import numpy as np import pyautogui time = 10 # display screen resolution, get it using pyautogui itself SCREEN_SIZE = tuple(pyautogui.size()) # define the codec fourcc = cv2.VideoWriter_fourcc(*"XVID") # frames per second fps = 30.0 # create the video write object out = cv2.VideoWriter("output.avi", fourcc, fps, (SCREEN_SIZE)) for i in range(int(time * fps)): # make a screenshot img = pyautogui.screenshot() # convert these pixels to a proper numpy array to work with OpenCV frame = np.array(img) # convert colors from BGR to RGB frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # write the frame out.write(frame) # make sure everything is closed when exited cv2.destroyAllWindows() out.release()
问题原因
核心问题是用固定循环次数控制录制时长,而非基于实际时间。pyautogui.screenshot()、图像格式转换、视频写入这些操作本身需要耗时,每次循环执行的时间会超过1/fps(比如30fps下每帧理论耗时约33ms)。这就导致设定时长内实际录制的帧数远少于time*fps,但视频文件仍按你设置的fps参数播放——用更少的帧填充了预设的播放时长,自然出现快进效果。
举个例子:设置录制10秒、30fps,理论需要300帧,但实际循环300次可能花了15秒。播放器按30fps播放时,10秒就播完了这300帧,相当于把15秒的内容压缩到10秒播放,速度自然变快。
解决方案
需要基于实际时间控制录制时长,同时尽量保证每帧的间隔接近目标fps的时间间隔。借助time模块实现:
修改后的代码:
import cv2 import numpy as np import pyautogui import time record_duration = 10 # 录制时长(秒) SCREEN_SIZE = tuple(pyautogui.size()) fourcc = cv2.VideoWriter_fourcc(*"XVID") target_fps = 30.0 frame_interval = 1.0 / target_fps # 每帧的目标间隔时间 out = cv2.VideoWriter("output.avi", fourcc, target_fps, SCREEN_SIZE) start_time = time.time() last_frame_time = start_time while time.time() - start_time < record_duration: current_time = time.time() # 计算需要等待的时间,保证每帧间隔接近目标值 time.sleep(max(0, frame_interval - (current_time - last_frame_time))) img = pyautogui.screenshot() frame = np.array(img) frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) out.write(frame) last_frame_time = current_time out.release() cv2.destroyAllWindows()
额外优化建议:
- 如果高分辨率屏幕下
pyautogui.screenshot()耗时过长,可以改用mss库,它的截图速度远快于pyautogui默认实现,能更接近目标帧率。 - 可在循环内添加帧率监控,方便调整参数:
print(f"实际帧率: {1/(current_time - last_frame_time):.2f}fps")
内容的提问来源于stack exchange,提问作者Digitas Merero
相关产品推荐
相关产品推荐

