ScreenClaw:基于百分比坐标网格的AI视觉自动化中间件实践
1. 项目概述:当AI学会“看”和“点”
最近在折腾AI Agent自动化的时候,我遇到了一个挺普遍的瓶颈:很多老牌桌面软件,比如一些财务系统、工业设计工具,或者公司内部定制的OA,它们压根没有提供API,更别说命令行接口了。想让AI去操作它们,传统的RPA工具要么需要繁琐的录制和元素定位配置,要么对动态界面束手无策。而基于视觉的大模型(VLM)虽然能“看懂”屏幕,但让它精确地“点击”屏幕上的某个按钮,却是个难题——直接告诉它像素坐标?窗口大小一变就全乱套了。
直到我发现了ScreenClaw(睇虾)。这个项目的思路非常巧妙,它没有去训练一个专门的UI识别模型,而是选择做一个“翻译官”。它的核心工作是在截图上面,叠加一层百分比坐标网格。想象一下,把整个窗口区域看作一个100x100的棋盘,无论窗口被拖拽成什么尺寸,棋盘上的每个格子(比如“第50行,第30列”)相对于窗口边缘的位置比例是固定的。这样一来,任何具备基础视觉识别能力的多模态大模型(比如GPT-4V、Claude 3.5 Sonnet),都能轻松地“读出”:“我需要点击棋盘上(50, 30)这个位置”。ScreenClaw收到这个指令后,再将其转换为当前窗口下的实际像素坐标并执行点击。
简单说,ScreenClaw是一个本地运行的中间件。它通过HTTP API提供服务,让外部的AI应用(Agent)能够:
- “看”:获取带坐标网格的窗口截图,供AI分析。
- “操作”:根据AI提供的百分比坐标,执行点击、输入、滚动等鼠标键盘操作。
最让我惊喜的是它的“后台无感操作”模式。它通过向目标窗口进程注入消息(PostMessage/SendMessage)来模拟操作,而不是真的去移动你的物理鼠标光标。这意味着你可以在前台继续写代码、看电影,而AI在后台悄无声息地帮你完成一些重复性的软件操作任务,两者互不干扰。这对于需要长时间在前台工作的自动化场景来说,体验提升巨大。
2. 核心设计思路与方案选型
2.1 为什么是“百分比坐标网格”?
在决定采用百分比坐标之前,项目作者肯定权衡过几种常见的UI自动化定位方案:
- 基于像素的绝对坐标:最简单,但最脆弱。只要窗口位置、大小、显示器分辨率任何一项发生变化,坐标就失效了。完全不具备可移植性。
- 基于图像模板匹配:通过寻找预先截取的小图片(如按钮图标)在屏幕上的位置来定位。这需要为每个操作元素准备模板,且对UI主题、缩放、轻微形变敏感,维护成本高。
- 基于无障碍树(UI Automation/Accessibility):最理想的方式,可以直接获取控件的类型、名称、状态等元信息。但问题是,大量老旧Win32应用、游戏、甚至一些现代Qt/WPF应用的无障碍树信息不完整或根本没有,覆盖率是个大问题。
- 基于OCR的文本定位:对于有文字的按钮有效,但对于纯图标按钮、图形界面就无能为力了,且识别速度和准确率在复杂背景下会下降。
百分比坐标网格方案巧妙地绕开了上述所有问题。它不关心界面具体是什么,只关心“相对位置”。只要窗口的宽高比例不变,(50, 30)这个点永远在窗口水平中点偏右、垂直方向30%的位置。这带来了几个关键优势:
- 普适性:理论上能操作任何“可见”的软件界面,包括游戏、视频播放器、甚至手机投屏的画面。
- 零配置:无需为每个软件预先录制或配置任何信息,开箱即用。
- 对大模型友好:让大模型做它最擅长的事——视觉理解和推理(“那个红色的关闭按钮在大概右下角”),然后输出一个结构化的、标准化的坐标指令,而不是让它去生成一段操作特定API的代码。
2.2 操作注入模式:Background vs. Hijack
ScreenClaw提供了两种底层操作注入方式,对应不同的使用场景和权限需求,这是理解其能力边界的关键。
Background模式(默认推荐):
- 原理:利用Windows的
user32.dll中的PostMessage或SendMessage函数,向目标窗口线程的消息队列发送鼠标、键盘消息。这相当于“内部模拟”,操作系统认为这是来自程序自身的合法输入。 - 特点:不会激活窗口(不会把它带到前台),不会移动物理光标,用户完全无感。非常适合后台自动化。
- 限制:某些应用(特别是采用DirectX/OpenGL渲染的游戏、一些安全软件)可能会屏蔽或忽略这种消息。对于需要“物理”点击才能激活的控件(如某些安全输入框),此模式可能无效。
- 原理:利用Windows的
Hijack模式(需授权):
- 原理:使用
pyautogui等库,调用SendInput等系统级API,模拟真实的物理输入设备事件。这相当于在系统层面“伪造”了一个鼠标键盘的操作。 - 特点:效果最接近真人操作,兼容性最广,能操作几乎所有软件。
- 限制:会真实移动鼠标光标、激活窗口,从而打断用户当前的操作。因此ScreenClaw将其设计为需要用户主动确认(弹窗)或进入“托管模式”后才能使用。
- 原理:使用
选择建议:对于日常办公软件、浏览器、管理系统的自动化,优先使用background模式,体验最好。只有在background模式失效(比如操作游戏、虚拟机)时,再考虑使用hijack模式,并接受其对前台工作的干扰。
2.3 技术栈选型解析:为什么是Python + Tauri?
从项目结构看,这是一个典型的前后端分离的本地桌面应用。
- 后端(Python + FastAPI):承担核心业务逻辑。Python在自动化(
pywin32,pyautogui)、图像处理(Pillow)方面有极其丰富的生态,快速开发验证想法的成本低。FastAPI则能轻松构建高性能、带自动交互文档的API,非常适合与AI Agent进行HTTP通信。 - 前端(Tauri + Vue 3):负责提供用户监控界面。Tauri 2.0相比Electron,最大的优势是使用Rust构建,最终打包的应用体积更小,内存占用更低,启动更快。对于ScreenClaw这种以后台服务为核心、仅需一个轻量级配置/监控界面的应用来说,Tauri是比Electron更优雅的选择。
- 通信:前后端通过Tauri的指令(Commands)和事件(Events)机制通信。Python后端作为独立进程运行,通过HTTP API对外提供服务,同时与Tauri前端进程交互,实现配置管理、状态上报等功能。
这个架构兼顾了开发效率(Python)、性能与体验(Tauri/Rust)、以及外部集成的便利性(HTTP API),是一个经过深思熟虑的务实选择。
3. 从零开始部署与深度配置
3.1 环境准备与源码运行
虽然项目提供了Release打包版,但对于开发者或想定制功能的朋友,从源码运行能获得更灵活的控制。以下是基于Windows环境的详细步骤,我会补充一些官方文档里没细说的坑点。
系统与工具准备:
- Python 3.11+:建议使用Miniconda或官方安装包。务必在安装时勾选“Add Python to PATH”。
- Node.js 18+ & npm:Tauri 2.0的前置依赖。同样需要确保加入系统路径。
- Rust工具链:Tauri底层依赖Rust。安装
rustup(Rust版本管理器)是最佳实践。在PowerShell或CMD中执行:winget install --id Rustlang.Rustup。安装后,可能需要重启终端或手动将%USERPROFILE%\.cargo\bin加入PATH。 - Microsoft Visual Studio Build Tools:这是Windows上编译Rust和Tauri应用最关键的一步。需要安装“使用C++的桌面开发”工作负载。可以通过Visual Studio Installer安装,或者直接下载 Build Tools for Visual Studio 2022 。
克隆与依赖安装:
# 克隆仓库 git clone https://github.com/GinSing1226/ScreenClaw.git cd ScreenClaw # 安装Python依赖(建议使用虚拟环境) python -m venv venv .\venv\Scripts\activate # Windows激活虚拟环境 pip install -r python/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple # 使用国内源加速 # 安装Node.js依赖 npm install # 如果网络慢,可以设置淘宝镜像:npm config set registry https://registry.npmmirror.com注意:
pip install阶段可能会遇到pywin32安装失败。如果报错关于“Microsoft C++ 14.0以上版本”的缺失,那就是上面提到的Visual Studio Build Tools没装好。请务必先完成那一步。
首次运行:
# 以开发模式启动(建议使用管理员权限的终端,部分API需要权限) npm run tauri dev首次运行会编译Rust部分,耗时较长。如果一切顺利,你会看到一个系统托盘图标和一个小控制窗口。点击控制窗口的“启动服务”,后端FastAPI服务就会在http://127.0.0.1:12261运行。
3.2 关键配置项详解
服务启动后,会在项目data/目录下生成config.json。理解并正确配置它,是保证稳定运行和安全的基础。
{ "server": { "host": "0.0.0.0", // 监听地址。0.0.0.0允许局域网内其他设备访问。 "port": 12261, // 服务端口,可按需修改,避免冲突。 "token": "your-generated-secret-token-here", // API调用凭证,务必修改! "local_ip": "192.168.1.100" // 自动检测的局域网IP,用于AI Skill连接。 }, "security": { "process_blacklist": ["taskmgr.exe", "cmd.exe"], // 禁止AI操作的进程 "require_hijack_confirm": true // Hijack操作前是否需要用户确认 }, "screenshot": { "default_grid_density": 5.0, // 默认网格密度(百分比间隔) "default_color_mode": "grayscale" // 默认截图色彩模式,可省带宽 } }token:这是最重要的安全项。绝对不能使用默认值。你可以在Python中运行import secrets; print(secrets.token_urlsafe(32))来生成一个强随机令牌。所有API请求都必须在Header中携带Authorization: Bearer <your-token>。host: 0.0.0.0:如果你想从同一局域网下的另一台电脑(比如你的Macbook)上的AI Agent来调用这台Windows上的ScreenClaw,就必须保持这个设置。同时,可能需要配置Windows防火墙,允许python.exe或该端口的入站连接。process_blacklist:一个非常实用的安全功能。你可以把一些敏感应用(如任务管理器、命令行、密码管理器)加进去,防止AI误操作。支持进程名(.exe)。
3.3 与AI Agent集成:安装Skill
ScreenClaw的价值需要通过AI Agent来释放。项目提供了与Claude Code、OpenClaw等Agent工具的集成Skill。
对于支持npx skills的Agent(如Claude Code):
# 在Agent的对话或终端中执行 npx skills add GinSing1226/ScreenClaw这个命令会将ScreenClaw的API定义和使用指南作为“技能”安装到Agent的知识库中。之后,当你对Agent说“帮我打开记事本并输入一段文字”,它就有可能自动生成调用ScreenClaw API的代码。
手动集成(通用方法):对于其他AI应用或自定义脚本,你需要做的就是向http://<你的IP>:12261发送HTTP请求。本质上,任何能发送HTTP POST请求的工具(curl, Python的requests库,Node.js的axios等)都可以成为ScreenClaw的“大脑”。
这里提供一个最简单的Python测试脚本,验证服务是否通畅:
import requests BASE_URL = "http://127.0.0.1:12261" TOKEN = "your-token-here" # 替换为你的token HEADERS = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json" } # 1. 健康检查 resp = requests.get(f"{BASE_URL}/api/health") print(f"Health Check: {resp.status_code}, {resp.text}") # 2. 查找记事本窗口 payload = { "ai_app_type": "test_script", "session_id": "test_session_001", "keyword": "记事本", # 窗口标题包含“记事本” "include_children": True, "children_filter": "titled" } resp = requests.post(f"{BASE_URL}/api/get_window_list", json=payload, headers=HEADERS) print(f"Window List: {resp.json()}")运行这个脚本,如果返回健康状态和窗口列表,说明你的ScreenClaw服务已经就绪,可以接受AI的调遣了。
4. API核心使用模式与实战案例
ScreenClaw的API设计是RESTful风格的,核心流程可以概括为:找窗口 -> 截图分析 -> 执行操作 -> 验证结果。下面我们通过一个完整的实战案例来串联这些API。
案例目标:让AI自动在Windows自带的“画图”软件中,绘制一个简单的红色矩形。
4.1 第一步:定位目标窗口
任何操作都需要一个目标窗口。get_window_listAPI就是我们的“窗口探测器”。
curl -X POST http://127.0.0.1:12261/api/get_window_list \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "ai_app_type": "claude_code", "session_id": "draw_rectangle_session", "keyword": "画图", "include_children": true, "children_filter": "titled" }'keyword: 用于模糊匹配窗口标题。这里我们找标题含“画图”的窗口。include_children&children_filter: 设为true和"titled"可以获取窗口内所有有标题的子控件句柄,对于复杂应用内部操作很有用。- 返回结果:你会得到一个窗口列表,其中包含每个窗口的
window_id和main_window_id。通常,我们使用main_window_id作为后续操作的window_id参数。记下这个ID,假设是10086。
4.2 第二步:获取带网格的界面快照
现在,让AI“看”一下画图软件的界面。
curl -X POST http://127.0.0.1:12261/api/screenshot \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "ai_app_type": "claude_code", "session_id": "draw_rectangle_session", "window_id": 10086, "main_window_id": 10086, "coordinate_type": "grid", "color_mode": "color", "grid": { "density_x": 10.0, "density_y": 10.0, "opacity": 30, "color": "#00ff00" }, "coordinate": { "number_density": 2, "number_decimal": 0, "number_size": 16, "number_color": "#ff0000", "number_opacity": 80 } }'这个请求会返回一张PNG图片的二进制流(或base64编码,取决于客户端处理)。图片上叠加了绿色的网格线(每10%一条)和红色的坐标数字(每20%一个)。AI模型看到这张图后,就能分析出:“颜料桶工具大概在(15, 85)的位置”,“颜色选择器红色方块在(90, 10)的位置”。
参数解析:
grid.density_x/y: 网格线密度。设为10.0意味着每10%画一条线,形成10x10的网格。密度越高,定位越精确,但图片上的线条也越密,可能干扰AI识别。通常5.0或10.0是个平衡点。coordinate.number_density: 坐标数字的密度。2表示每两条网格线(即每20%)显示一个数字。这能避免图片上数字过于拥挤。
4.3 第三步:执行自动化操作序列
根据AI对截图的分析,它需要规划一系列动作。我们可以使用batchAPI来批量执行,减少网络往返延迟。
curl -X POST http://127.0.0.1:12261/api/batch \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "ai_app_type": "claude_code", "session_id": "draw_rectangle_session", "window_id": 10086, "main_window_id": 10086, "instructions": [ { "action": "click", "params": { "x": 12, "y": 88, "action_method": "background" } }, { "action": "wait", "params": { "duration_ms": 500 } }, { "action": "click", "params": { "x": 90, "y": 12, "action_method": "background" } }, { "action": "wait", "params": { "duration_ms": 300 } }, { "action": "long_press", "params": { "x": 30, "y": 50, "duration_ms": 100, "action_method": "background" } }, { "action": "drag", "params": { "start_x": 30, "start_y": 50, "end_x": 70, "end_y": 70, "duration_ms": 800, "action_method": "background" } }, { "action": "screenshot", "params": { "coordinate_type": "no", "color_mode": "color" } } ] }'这个批量指令序列模拟了以下操作:
- 点击(12, 88):选择“矩形”形状工具(假设AI识别该位置是矩形工具)。
- 等待500ms:给界面一个反应时间。
- 点击(90, 12):选择红色(假设AI识别该位置是红色)。
- 等待300ms。
- 在(30, 50)长按100ms并开始拖拽:在画布上按下鼠标。
- 拖拽到(70, 70):绘制矩形。
- 最后截一张不带网格的图:验证操作结果。
实操心得:
wait操作至关重要:在连续的UI操作之间插入适当的等待(duration_ms),是保证自动化稳定性的关键。网络延迟、软件响应速度、动画效果都会影响时机。random_range参数可以给等待时间增加一个随机偏移,让操作模式更接近人类,避免被简单的反自动化机制检测。batch的原子性:batch中的指令是顺序执行的,但如果中间某一步失败(比如点击没反应),整个批次并不会自动停止。更健壮的做法是,在关键步骤后跟一个screenshot进行验证,由AI判断是否继续。
4.4 高级功能:处理复杂场景
场景一:操作可滚动长页面(如网页)使用scroll_screenshotAPI。它能自动控制滚动条,连续截图并拼接成一张完整的长图。这对于让AI分析超出首屏的内容非常有用。参数scroll_percent控制每次滚动的幅度,scroll_wait控制滚动后的等待时间以确保内容加载。
场景二:精确操作小图标或密集区域即使有网格,对于非常小的按钮,AI也可能读错1-2个格子的坐标。这时可以使用crop_zoom_screenshotAPI。你可以先截一张普通图,AI识别出大致区域(如(55,65)附近),然后请求以该点为中心,裁剪一个20%x20%的区域并放大2倍。AI再分析这张放大图,就能得到更精确的坐标。
场景三:需要连续文本输入对于输入大段文字,使用input_textAPI并配合\n实现换行。注意,复杂的富文本编辑器可能需要模拟Ctrl+A全选、Backspace删除等操作组合,这可以通过batch编排多个press_key动作来实现。
5. 常见问题排查与性能优化
在实际使用中,你可能会遇到以下问题。这里记录了我的排查经验和解决方案。
5.1 操作无反应或报错
| 现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
click或input_text后,目标软件毫无反应。 | 1.目标窗口失去焦点或最小化。 2. background模式不被目标应用支持(常见于游戏、虚拟机、安全软件)。3.坐标计算错误,点击位置是空白区域。 | 1. 确保目标窗口在前台且未被最小化。 2. 尝试将 action_method改为"hijack"(会弹出确认框)。如果hijack有效,则说明该应用不支持后台消息注入。3. 使用 screenshotAPI(coordinate_type: "grid")确认AI识别的坐标点是否准确覆盖了目标按钮。可以临时调高网格密度(density_x/y: 2.0)和数字密度(number_density: 1)辅助肉眼核对。 |
返回错误\"error\": \"Window not found or inaccessible\"。 | 1.窗口已关闭。 2.进程权限不足,无法访问目标窗口(常见于系统级或管理员权限启动的软件)。 | 1. 重新调用get_window_list确认窗口ID。2.以管理员身份重新启动ScreenClaw。这是解决权限问题最直接的方法。在Windows搜索栏找到你的终端(CMD, PowerShell, Windows Terminal),右键选择“以管理员身份运行”,然后cd到项目目录再次执行 npm run tauri dev。 |
screenshot返回全黑或纯色图片。 | 1.硬件加速或特殊渲染:目标应用使用DirectX、OpenGL或GPU加速渲染,标准截图API无法捕获。 2.窗口被遮挡。 | 1. 对于游戏或三维软件,可能需要使用专门的截图模式(如ScreenClaw未来可能支持的DXGI方式)。目前可以尝试切换到“窗口化”或“无边框窗口化”模式,有时能解决。 2. 确保目标窗口完全可见,未被其他窗口覆盖。 |
| 局域网内其他机器无法连接。 | 1.Windows防火墙阻止。 2.ScreenClaw配置未绑定 0.0.0.0。3.IP地址或端口错误。 | 1. 在Windows Defender防火墙中添加入站规则,允许Python(或你打包后的exe)监听12261端口。 2. 检查 data/config.json中host是否为\"0.0.0.0\"。3. 在ScreenClaw运行机器上执行 ipconfig,确认正确的局域网IP,并在调用方使用该IP。 |
5.2 性能与稳定性调优
截图速度优化:
- 使用
color_mode: \"grayscale\":如果AI模型对颜色不敏感,灰度截图可以显著减少传输数据量,提升速度。 - 降低截图频率:不要在每个操作后都截图。只在需要AI重新决策的关键节点(如页面跳转后、等待加载完成后)调用
screenshot。 - 调整截图区域:如果操作始终在一个子窗口内,可以考虑先获取子窗口的
window_id,然后针对该子窗口截图,范围更小,速度更快。
- 使用
坐标识别准确性提升:
- 网格密度与AI提示词配合:在给AI的提示词(Prompt)中明确说明:“你将看到一张带百分比坐标网格的截图。水平(X轴)和垂直(Y轴)范围都是0到100。请描述你需要操作的元素的精确坐标,例如(50.5, 30.2)。” 鼓励AI输出带一位小数的坐标,可以提高精度。
- 多次采样与平均:对于固定按钮,可以让AI在同一个任务中多次识别其坐标,然后取平均值,可以抵消单次识别的偶然偏差。
- 利用
crop_zoom_screenshot:对于难以辨认的小元素,这是提升精度的利器。
自动化流程的健壮性:
- 加入冗余等待和重试逻辑:在AI Agent的代码中,不要假设一次操作100%成功。操作后,通过截图验证结果(如检查某个成功提示是否出现)。如果失败,加入重试机制(例如,重新识别坐标再点一次)。
- 设计状态检查点:将一个长任务分解为多个子阶段,每个阶段结束后都有一个明确的、可通过截图验证的状态。例如,“打开软件”->“验证主界面出现”->“点击登录”->“验证登录成功”。这能让AI更容易定位故障点。
5.3 安全使用建议
- Token管理:API Token相当于密码。不要硬编码在客户端脚本中,更不要上传到公开仓库。可以通过环境变量或配置文件(不纳入版本控制)的方式引入。
- 善用进程黑名单:务必在
config.json的process_blacklist中添加taskmgr.exe(任务管理器)、cmd.exe、powershell.exe以及你的密码管理器、银行客户端等。这能防止AI在“学习”过程中意外关闭关键进程或触发危险操作。 - 理解Hijack模式的风险:
hijack模式会真实控制你的鼠标键盘。仅在受控环境下使用,并确保有快捷退出方式(Ctrl+Alt+Z)。不要在生产环境或进行重要工作时开启长时间的托管模式。 - 网络隔离:如果只在本地使用,可以将
host改为\"127.0.0.1\",仅允许本机访问。如果需局域网访问,确保你的家庭或公司网络是可信的。
ScreenClaw打开了一扇新的大门,它用一种极简而通用的方式,将顶尖多模态大模型的“眼”和“手”与我们的数字世界连接了起来。从我自己的使用体验来看,它的价值不在于替代那些有完善API的自动化工具,而在于填补了“无API软件自动化”这片巨大的空白。从操作古老的客户端软件,到控制手机模拟器里的App,再到辅助进行一些复杂的、需要视觉反馈的GUI测试,它的可能性还有很多等待挖掘。当然,目前的方案高度依赖大模型视觉识别的准确性,对于动态变化极快或元素极其密集的界面,成功率还有提升空间。但正如项目规划里提到的,结合轻量级OCR或辅助技术树来提升坐标精度,是未来一个非常值得期待的方向。如果你也受困于让AI操作那些“顽固”的桌面软件,不妨试试ScreenClaw,它提供的这套基于百分比坐标的“视觉语言”,或许正是你一直在找的解决方案。
