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

Python mss多进程截屏仅30FPS 如何优化至稳定60FPS

结论

你的硬件配置(AMD Ryzen 5 4500U、8GB内存)完全可以支撑1366768分辨率下60FPS的屏幕捕获与实时展示,帧率稳定在30FPS不是硬件限制,是代码逻辑和依赖库默认配置导致的。
你统计的单帧0.033s耗时,是屏幕采集+跨进程全尺寸帧传输的总耗时,不是纯采集的耗时——纯mss采集1366
768分辨率画面在你的CPU上单帧耗时通常在10ms以内,剩下的23ms基本都是跨进程传输大体积原始帧的开销。

具体优化点

  • 把缩放、格式转换逻辑移回采集进程
    你现在把未做任何处理的1366768 BGRA原始帧直接放入跨进程队列,单帧体积约4MB,跨进程的序列化、内存拷贝开销极高。你之前注释掉的「采集后直接resize到目标分辨率、转格式再入队」的逻辑是正确方向,处理完的640480帧单帧体积仅900KB左右,IPC开销能降低75%以上。
  • 砍掉冗余的颜色空间转换
    你现在用cv2把BGRA格式转成BGR再给pygame渲染完全是多余操作,pygame原生支持BGRA/BGRX格式的buffer输入,直接把pygame.image.frombuffer的格式参数从'BGR'改成'BGRA'即可,每帧能省掉几毫秒的转码耗时。
  • 给队列加限长和丢帧逻辑
    你现在用的是无界队列,一旦展示端消费速度暂时跟不上采集端,队列里会堆积大量过时帧,展示端会一直处理旧帧,进一步拉低实际显示帧率。初始化队列时设置maxsize=2,采集端入队前如果队列已满就先丢弃最旧的帧,保证队列里永远存的是最新的画面,避免堆积。
  • 调整mss捕获参数
    初始化mss时关闭鼠标捕获(不需要显示鼠标的场景下):with mss(with_cursor=False) as sct,能省掉每帧绘制鼠标指针的开销,Windows平台下这个调整通常能让采集耗时直接降低一半。
  • 优化pygame渲染逻辑
    开启双缓冲的情况下,用pygame.display.flip()替代pygame.display.update()渲染效率更高;非调试场景下去掉每帧调用queue.qsize()的逻辑,这个方法在多进程队列下会加锁,有额外开销。

优化后的核心代码参考

SCR_SIZE = (640, 480)

def grabber(queue, isRunning):
  from mss import mss
  from time import time
  from numpy import asarray
  from cv2 import resize
  global SCR_SIZE
  # 关闭鼠标捕获降低开销
  with mss(with_cursor=False) as sct:
    monitor = sct.monitors[1]
    while isRunning.value:
      t0 = time()
      # 采集后直接缩放到目标分辨率,不做多余颜色转换,直接传BGRA格式
      raw_frame = asarray(sct.grab(monitor))
      resized_frame = resize(raw_frame, SCR_SIZE)
      # 队列满就丢旧帧,避免堆积
      if queue.full():
        try:
          queue.get_nowait()
        except:
          pass
      queue.put(resized_frame)
  print('P1 Finished!')

def displayer(queue, isRunning):
  import pygame
  import pygame.display
  import pygame.image
  import pygame.time
  import pygame.font
  import pygame.event
  from pygame.locals import DOUBLEBUF
  global SCR_SIZE
  pygame.init()
  SCR = pygame.display.set_mode(SCR_SIZE, DOUBLEBUF)
  SCR.set_alpha(None)
  clock = pygame.time.Clock()
  FONT_COMIC = pygame.font.SysFont('Cambria Math', 20)
  while isRunning.value:
    for EVENT in pygame.event.get():
      if EVENT.type == pygame.QUIT:
        print('Quit')
        isRunning.value = 0
    currentFrame = queue.get()
    if currentFrame is not None:
      # 直接读BGRA格式,去掉cv2转色步骤
      SCR.blit(pygame.image.frombuffer(currentFrame, SCR_SIZE, 'BGRA'), (0,0))
    else:
      break
    clock.tick(60)
    SCR.blit(FONT_COMIC.render('FPS:'+str(clock.get_fps())[:5], False, (0,255,0)),(10,10))
    # 双缓冲下用flip替代update
    pygame.display.flip()
  print('P2 Finished!')


if __name__ == "__main__":
  from multiprocessing import Process, Queue, Value
  from time import sleep
  # 队列限长2,避免帧堆积
  queue = Queue(maxsize=2)
  isGameRunning = Value('i', 1)
  p1 = Process(target=grabber, args=(queue,isGameRunning, ))
  p2 = Process(target=displayer, args=(queue,isGameRunning, ))
  p1.start()
  p2.start()
  while isGameRunning.value:
    sleep(5)
  p1.terminate()
  p2.terminate()

调整完之后,正常情况下稳定帧率可以跑到60FPS。

内容的提问来源于stack exchange,提问作者Muhammad Ikhwan Perwira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:48:22