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

macOS下Python钢琴块脚本如何实现更快的截图?

macOS下优化钢琴块脚本截图速度方案

你的核心问题是macOS上全屏截图效率太低,且你只需要检测几个固定坐标的像素,完全没必要截整个屏幕。以下是两种能把截图耗时压到0.1秒内的方案:

方案一:使用mss模块(推荐,代码改动小)

mss是专门针对快速屏幕捕获的库,支持多平台,在macOS上效率远高于PIL的ImageGrab,而且可以只截取你需要的小区域,进一步减少耗时。

首先安装mss:

pip install mss

修改后的代码:

from pynput.keyboard import Listener, KeyCode
from pynput.mouse import Controller as MouseController, Button
import mss
import time

mouse = MouseController()
pixel_coords = [(590, 490), (492, 490), (678, 490), (766, 490)]
running = True

# 计算需要截取的最小区域:包含所有检测点的矩形
min_x = min(coord[0] for coord in pixel_coords)
max_x = max(coord[0] for coord in pixel_coords)
min_y = min(coord[1] for coord in pixel_coords)
max_y = max(coord[1] for coord in pixel_coords)
# 稍微扩大一点避免边缘问题
monitor = {"top": min_y - 2, "left": min_x - 2, "width": max_x - min_x + 4, "height": max_y - min_y + 4}

def click(x, y):
    mouse.position = (x, y)
    mouse.click(Button.left)

def play():
    global running
    with mss.mss() as sct:
        while running:
            x = time.time()
            # 只截取指定区域
            screen = sct.grab(monitor)
            # 转换坐标:检测点相对于截图区域的位置
            for coord in pixel_coords:
                rel_x = coord[0] - monitor["left"]
                rel_y = coord[1] - monitor["top"]
                # 获取像素值,mss的像素是(x,y)顺序,返回(r,g,b)
                value = screen.pixel(rel_x, rel_y)
                # 注意mss返回的是3通道,所以去掉原判断里的alpha通道值
                if value in [(0, 0, 0), (15, 20, 19), (13, 32, 41), (0, 161, 201)]:
                    click(coord[0], coord[1])
            print(f"Time taken: {round(time.time() - x, 4)}")

def on_press(key):
    global running
    if key == KeyCode(char="q"):
        running = False
        print("Stopped")
        quit()

with Listener(on_press=on_press) as listener:
    play()
    listener.join()

这个方案通过只截取包含所有检测点的小区域,加上mss的高效捕获,耗时能降到0.02秒以内,完全满足要求。

方案二:使用macOS原生Quartz框架(极致速度)

直接调用macOS的Quartz API读取单个像素,不需要截取任何图像区域,速度是最快的,适合只需要检测少量像素的场景。

首先安装pyobjc(用于调用Objective-C框架):

pip install pyobjc-framework-Quartz

修改后的代码:

from pynput.keyboard import Listener, KeyCode
from pynput.mouse import Controller as MouseController, Button
import Quartz
import time

mouse = MouseController()
pixel_coords = [(590, 490), (492, 490), (678, 490), (766, 490)]
running = True

def get_pixel_color(x, y):
    # 获取主屏幕
    screen = Quartz.CGMainDisplayID()
    # 创建上下文
    context = Quartz.CGDisplayCreateImage(screen)
    # 获取像素数据
    data = Quartz.CGDataProviderCopyData(Quartz.CGImageGetDataProvider(context))
    # 计算像素在数据中的位置(macOS屏幕是RGBA格式,每行字节数是宽度*4)
    width = Quartz.CGImageGetWidth(context)
    byte_pos = (y * width + x) * 4
    # 读取RGBA值
    r = data[byte_pos]
    g = data[byte_pos+1]
    b = data[byte_pos+2]
    a = data[byte_pos+3]
    # 释放资源
    Quartz.CGImageRelease(context)
    return (r, g, b, a)

def click(x, y):
    mouse.position = (x, y)
    mouse.click(Button.left)

def play():
    global running
    while running:
        x = time.time()
        for coord in pixel_coords:
            value = get_pixel_color(coord[0], coord[1])
            if value in [(0, 0, 0, 255), (15, 20, 19, 255), (13, 32, 41, 255), (0, 161, 201, 255)]:
                click(coord[0], coord[1])
        print(f"Time taken: {round(time.time() - x, 4)}")

def on_press(key):
    global running
    if key == KeyCode(char="q"):
        running = False
        print("Stopped")
        quit()

with Listener(on_press=on_press) as listener:
    play()
    listener.join()

这个方案直接读取每个指定点的像素,不需要生成图像对象,耗时大概在0.01秒左右,极致高效。注意每次调用CGDisplayCreateImage会捕获整个屏幕的像素数据,但因为只读取几个点,整体还是很快。

关键优化点总结

  • 避免全屏截图:只截取需要的区域,减少数据处理量
  • 使用更高效的捕获库/API:放弃PIL的ImageGrab,改用专门的快速截图工具或系统原生API
  • 减少不必要的图像操作:直接读取像素值,避免生成完整的图像对象

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 04:30:08