Python录屏程序帧率异常、实际时长与设置不符的问题求助
Python录屏程序帧率异常、实际时长与设置不符的问题求助
我最近在做一个Python录屏程序,目标是能指定录制时长(比如10秒)和帧率(比如30FPS),但遇到了两个头疼的问题:
- 录出来的视频要么快进5倍,要么帧率特别低,明明设置的是30FPS
- 时长完全不对,设置10秒实际只有6秒左右
这是我目前用的代码:
import pyautogui import cv2 import numpy as np import time screen_width, screen_height = pyautogui.size() fps = 30 duration = 10 # Set duration to 10 seconds fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter('output.avi', fourcc, fps, (screen_width, screen_height)) start_time = time.time() while True: screenshot = pyautogui.screenshot() frame = np.array(screenshot) frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) out.write(frame) if time.time() - start_time > duration: break out.release() cv2.destroyAllWindows()
遇到的具体问题:
- 帧率/播放速度异常:播放时要么快得离谱(5倍速),要么帧率很低,和设置的30FPS完全不符
- 时长不匹配:设置10秒的录制时长,实际视频只有约6秒
我已经尝试过的方法:
- 调整fps参数,没用
- 更换视频编码格式,没效果
- 在帧之间加sleep延迟,也没改善
问题原因分析
其实核心问题是你没有控制每帧的捕获间隔:pyautogui.screenshot()和后续的帧转换、写入操作是需要时间的,比如假设每帧处理耗时0.05秒,那实际每秒只能捕获20帧,但你告诉cv2.VideoWriter要按30FPS来编码。播放器会用30FPS的速度播放实际只有20帧的内容,10秒录制周期内你只捕获了200帧,200÷30≈6.7秒,所以播放时长就变短了,内容也会显得快进。
解决方案:控制帧间隔+固定总帧数
我们可以通过计算每帧的理想间隔,同时限制总帧数(fps × duration)来解决这个问题,这样既能保证录制时长准确,又能让实际帧率接近设置值。
修改后的代码如下:
import pyautogui import cv2 import numpy as np import time screen_width, screen_height = pyautogui.size() fps = 30 duration = 10 # 目标录制时长 total_frames = fps * duration # 总帧数 frame_interval = 1.0 / fps # 每帧的理想间隔时间 fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter('output.avi', fourcc, fps, (screen_width, screen_height)) start_time = time.time() for _ in range(total_frames): # 记录当前帧开始的时间 frame_start = time.time() # 捕获并处理帧 screenshot = pyautogui.screenshot() frame = np.array(screenshot) frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) out.write(frame) # 计算需要等待的时间,确保每帧间隔符合设置 elapsed = time.time() - frame_start sleep_time = frame_interval - elapsed if sleep_time > 0: time.sleep(sleep_time) out.release() cv2.destroyAllWindows()
代码改动说明:
- 固定总帧数:通过
total_frames = fps * duration计算出需要录制的总帧数,循环固定次数,从根本上保证录制的内容对应目标时长 - 控制帧间隔:计算每帧的理想间隔
frame_interval = 1.0 / fps,然后减去当前帧处理耗时,用time.sleep()补足剩余时间,确保每秒捕获的帧数尽可能接近设置的30FPS - 避免无限循环的误差:原来的
while True循环会因为判断时间的微小误差导致多录或少录,固定循环次数更准确
如果你的电脑性能有限,pyautogui.screenshot()耗时超过frame_interval,那sleep时间会是负数,这时候就不会sleep,这种情况下实际帧率会低于设置值,但播放时长还是会和目标一致(因为总帧数是固定的),不会出现快进的情况。
备注:内容来源于stack exchange,提问作者Philip Neumair
相关产品推荐
相关产品推荐

