screen-reader 屏幕阅读助手
是什么
给 AI 一双眼睛(截屏 + 帧差检测)和一双手(真实鼠标键盘事件)。
AI 读图判断"这是什么、该点哪",脚本负责把物理动作做准。判断永远在 AI,动作永远在脚本——
脚本不知道"该点哪",只知道"点这个坐标、翻页、报告帧差"。
三个典型场景:
- 自主阅读:AI 自己翻页看完整个文档/网页,边翻边把内容缝成笔记,读完输出整篇理解
- 引导操作:用户不会装某个软件,AI 看安装向导的每一步,告诉用户点什么、哪些捆绑勾选要取消
- 逐页审阅:几百页扫描件/流水/账本,AI 逐页翻、逐页读、定位差异页,全程留痕
环境要求
- Windows(用了 Win32 API)
- Python 3 + Pillow(
pip install pillow) - 目标软件能响应真实键鼠事件(几乎所有桌面软件都可以;纯自绘游戏内界面可能不响应)
快速开始
# 环境自检:列出当前所有窗口
python scripts/screen.py windows
# 截全屏 / 按标题截窗口 / 窗口内局部放大
python scripts/screen.py shot out.png
python scripts/screen.py shot out.png --title 记事本
python scripts/screen.py shot out.png --title 计算器 --rect 95,320,215,420 --zoom 3
# 自主阅读:开始 → 一步步翻 → 查进度
python scripts/reader.py begin --title "文档标题" --dir out
python scripts/reader.py step --dir out # 翻一屏,输出 JSON(帧差/页号/是否到底)
python scripts/reader.py status --dir out
# 精准点击(先截图读图报坐标,再点)
python scripts/screen.py clickpx 128 367 --title 计算器
CLI 速查
screen.py
| 命令 | 作用 |
|---|---|
windows |
列出全部可见窗口(hwnd/标题/位置) |
shot <路径> [--title T] [--hwnd N] |
截全屏或指定窗口 |
shot ... --rect l,t,r,b --zoom 3 |
窗口内局部放大截图(精读小按钮/小字) |
key <键名> [--title T] |
真实键盘(pagedown/pageup/down/up/enter/esc/tab…) |
click X Y |
真实鼠标点击(屏幕绝对坐标) |
clickpx X Y --title T |
按"截图内像素坐标"点击,自动换算,自适应窗口大小和分辨率 |
clicktry X Y --title T |
点击+帧差验证+网格微调重试(适合打开对话框/翻页这类有可见变化的操作) |
wheel N |
滚轮,正数向上负数向下,单位格(浏览器/滚动页面用) |
diff a.png b.png |
两图帧差均值(0=没变化,越大变化越大) |
scrollpos |
读标准滚动条位置(自绘滚动条的软件读不到) |
reader.py(自主阅读闭环)
| 命令 | 作用 |
|---|---|
begin --title T --dir D |
定位窗口(多候选拒绝猜测)、激活、翻页可逆性预检、截首屏 |
step --dir D |
翻一页→截图→帧差检测→JSON 报告;连续 2 次帧差<1.2 且备用翻页方式全部无效才判定看完 |
status --dir D |
当前页数、是否读完 |
begin ... --resume |
断点续跑:阅读器崩过/窗口重开过,只重建绑定不重置页号 |
begin ... --max-pages N |
页数上限,到顶强制收尾(无限滚动页面/视频页面必须设,否则帧差永远非 0 会永远翻下去) |
翻页模式:默认 --mode key(记事本/Word/PDF 阅读器,pagedown);浏览器等滚动界面用
--mode wheel --clicks 3。
begin 的翻页可逆性预检(自动执行,看返回的 precheck 字段):翻过去再翻回来对比首屏,
回不去就说明这个键在改文档内容而不是翻页(真实场景:焦点在输入框时 pagedown/tab 会往
文档里打字,笔记会被静默污染)。返回 "ok": "warn" 时必须按 warning 的提示处理
(把焦点移出输入框、或换 --mode wheel),不要硬着头皮 step。
step 的三道防误判保险(都不增加调用方成本,step 自动完成):
1. 翻页键无效时自动依次尝试 备用方式(方向键→空格→滚轮),任一生效即切换并报告
switched_to——避免把"没翻动"误判成"看完了"
2. 黑/白/未渲染画面检测(SCREEN_BLANK)与锁屏检测(SCREEN_LOCKED,读前台窗口
类名)——夜间长任务中途锁屏会在这里被拦住,不会把锁屏画面当成读完
3. --max-pages 页数上限——无限滚动/动画页面帧差永远非 0,没上限会永远翻下去
使用范式(AI 怎么用好这个技能)
- 先 windows 列窗口,再 shot 截图,读图判断,最后才动作——每个动作后必截图验证,不假设成功
- 坐标标定用单键校准法:不确定按钮位置时,先点一个"安全的"键(如计算器的 C)看反应,
比整体估算可靠得多。目测报点误差 ±20px 通常都在按钮上(按钮普遍 40-80px) - 阅读笔记写文件,不靠脑子记:每翻一屏,把"这一屏有什么"追加进 notes.md;
到最后一屏时带着前面全部笔记回答"整篇讲了什么"(增量缝合,不是只看最后一屏) - 粗读/精读分工:几百页材料先粗读抓结构和标题定位重点,精读才逐页细看,省调用量
- 读完的判定信 reader 的帧差信号,不信自己的感觉
- 长任务开跑前先报成本:先翻两三屏估出总页数,告诉用户"约 N 屏=N 次读图",
问"全读还是先粗读"再动手——几百页闷头全读是对用户积分的不负责任 - 向导类操作(装软件)分两档:默认每步截图报告"我要点哪、这个选项什么意思",
等用户确认再点;用户明确说"后面的你看着办"才切连贯模式,且只在黑名单按钮停 - 屏幕上有无关的私人内容时,复述要克制:只回应用户问的那部分,
不主动朗读屏幕上无关的聊天记录、账户信息——看到了不等于要说出来
安全铁律(不可绕过)
- 危险按钮必须停下来问人:看到"删除""支付""提交""格式化""确认转账"这类按钮,
无论任务进行到哪,立刻停下向用户确认,绝不自动点 - 绝不盲点:每次点击/翻页前强制校验目标窗口在前台(ensure_foreground),
用户切窗了当场中止,不把操作发到不确定的窗口 - 标题匹配到多个窗口时拒绝猜测:列出候选让调用方显式 --index 指定
- 交互契约:长任务开跑前明确告知用户"接下来别动键鼠,说停我就停"
对账/逐页审阅模式(完整工作流)
几百页银行流水扫描页、财务账本扫描页这类任务,核心矛盾是:AI 单字识别不是 100%,
而审计容错是零。解法不是假装全自动,而是一套"机器干粗活、纠错长出规则、人只在
刀刃上确认"的闭环。分四层,从便宜到贵:
第 1 层:交叉自校验(零成本,先行)
账目的数字之间自带算术关系:余额=上笔余额+发生额、小计=明细相加、借贷相等。
每读一屏,先在笔记里把这些验算跑一遍,算不平的地方自动标红。
这一层不依赖字迹识别,靠逻辑抓错,能拦住相当一部分识别错误,比问用户便宜得多。
校验关系不成立的页面(如纯文字页)跳过本层。
第 2 层:置信度标记
每个关键数字/字段分三级记录,写进每屏的笔记:
- 高置信:字迹清晰、印刷体、与上下文自洽
- 中置信:略有模糊但可推断,记录推断依据
- 低置信:认不出或存疑,必须连同局部放大截图一起存档(--rect --zoom),
不丢原始证据
第 3 层:分批人工确认(不逐个蹦问)
低置信项和中置信项攒着,翻完一节或若干页后一次性列给用户:
"第 3 屏这个数我认的是 8,450.00 但字迹糊;第 5 屏这个像 3 又像 8;第 7 屏这里算术对不上……"
用户批量纠正。效率比逐个问答高一个数量级。
第 4 层:揪偏——纠错本沉淀为规则(本模式的灵魂)
用户的每次纠正都写进纠错本 corrections.md(放在输出目录),记录:
我认的 / 正确的是 / 什么场景 / 截图位置。攒几条后主动总结出本材料的识别规则,
例如"这家银行手写 7 带一横别认成 1""金额栏千分位点偶尔糊",后续所有页按规则读,
只报规则之外的新情况。任务结束后纠错本归档——下次遇到同一家银行的流水、
同一个会计的字迹,规则直接加载,第一遍就准。标记越来越少、确认越来越快,
这才是"越用越准"的回路。
终局出报告(三档说清,不含糊过关)
- 全部高置信且交叉校验通过 —— 正常采信
- 经用户确认的 —— 标注"经人工确认"
- 仍有存疑未确认的 —— 单列"待确认项",绝不混进结论
铁律与边界
- 精确数字优先走文件直读:PDF/Excel 里的数字不过屏幕,零识别误差;
只有纯纸质扫描件才走屏幕。谁拿屏幕识别的数字直接对账不留复核,谁负责。 - 手写体/模糊老化件的单字识别不可靠:这是模型能力边界,不是参数问题,
所以本模式从设计上就假设"一定有认不准的",用上面的闭环消化,而不是假设全能认对。 - 成本:每屏分析是一次读图调用,几百页就是几百次。粗读定位、精读细看要分工。
- 危险动作:审阅过程中绝不点击任何按钮;只翻页、只截图、只读。
已知短板
- 手写体/模糊字的单字识别不可靠(见上节),这是模型能力边界,不是参数问题
- 翻页键可能是在改文档而不是翻页:焦点在输入框时按 pagedown/tab 会往文档里打字,
diff 忽大忽小。begin 的预检能抓到大部分,但预检的 turn_diff 恰好很小时会漏报——
看到窗口标题出现未保存标记(*)要警觉 - clicktry 的自动帧差验证对"小变化"不敏感(如计算器数字变化被全图摊薄),
精细确认仍要靠读图;有可见大变化的操作才适合 clicktry - 自绘滚动条(很多专业软件)读不到位置,终点判定只能靠帧差
- 少数自绘界面(游戏、部分 Qt 软件)可能不响应合成/真实的翻页消息
- 折叠菜单、悬停才出现的提示,需要用户先操作出来
- UAC 弹窗在安全桌面上,截图可能截不到内容——遇到屏幕突然变暗,
提示用户亲自处理,不要继续自动点击
踩坑记录(都是实测踩过的)
- DPI 感知:
SetProcessDpiAwareness必须在任何窗口操作前执行,否则 125%/150%
缩放的机器上逻辑坐标与截图像素错位,点击全歪 - 后台进程 SetForegroundWindow 会被 Windows 前台锁拒绝:用 AttachThreadInput
附着前台线程的输入队列再激活(screen.activate 已内置) - Windows 11 新记事本标题去掉扩展名:
_reader_test.txt显示为_reader_test - 记事本,
按文件名匹配窗口时注意 - Git Bash 起带参数进程会被 MSYS 转换破坏路径:
cmd //c "start notepad \"C:\...\""
会报"找不到文件",用 Python subprocess 起进程绕开 - 坐标没标定准≠机制有问题:计算器点歪先做单键校准,别急着改代码
- 翻页键可能在改文档:实测记事本里 tab 不是翻页是插字符,diff 忽大忽小
(4.11/0.39/5.31),笔记缝合会被静默污染。begin 的可逆性预检就是为这个加的 - 锁屏检测不能用均一性:锁屏画面是壁纸/登录页,对比度正常,is_blank 抓不到;
可靠信号是前台窗口类名(Windows.Logon 等),见 is_locked() - 长任务截图必须存 JPEG:300 页全屏 PNG 约 600-900MB,JPEG 质量 85 读图无差别,
体积降到 1/6。reader.py 默认已用 jpg - UAC 安全桌面:装软件点"安装"后屏幕突然变暗是 UAC 弹了,截图可能截不到内容。
检测到整体变暗/画面异常就停下让用户亲自处理,别继续自动点