这次我们来看一个很轻量的 macOS 小项目:Monkey see, monkey do。名字很直白,意思就是“猴子看见什么就做什么”,放到这个项目里就是——用 macOS 原生 OCR 能力,把屏幕上显示的文字原样复现出来。
项目思路不复杂,但它踩中了一个很实用的点:macOS 系统自带的 OCR 能力平时被很多人忽略,真正要用的时候又不知道去哪里调。这个项目把它封装成一个可以直接使用的工具,解决的就是“屏幕上这段文字怎么快速复制出来”“PDF 扫描件怎么转成可编辑文本”这类日常问题。
最值得关注的特点是它完全走系统原生框架,不需要额外下载大模型,不需要训练,也不需要 GPU。只要你的 Mac 系统版本够新,基本开箱即用。相比 Tesseract、PaddleOCR 这类需要配置环境的方案,它的部署成本低很多。
这篇文章会用实操视角带你把项目跑起来,内容包括:核心能力梳理、环境要求、部署步骤、功能测试、命令行调用、批量任务思路、资源占用观察和常见问题排查。如果你平时经常处理截图、扫描件、PDF 文档,这篇文章可以直接收藏。
1. 核心能力速览
先看项目的基本信息,方便快速判断它适不适合你。
| 能力项 | 说明 |
|---|---|
| 项目类型 | macOS 原生 OCR 工具,从屏幕或图片中识别文字并复现 |
| 底层能力 | macOS 系统原生 OCR 框架,非三方模型 |
| 主要功能 | 屏幕区域文字识别、图片文字提取、文本复制输出 |
| 适合场景 | 截图文字提取、PDF 扫描件复用、屏幕取词、快速整理资料 |
| 支持平台 | macOS,依赖系统版本和硬件兼容性,需按实际环境确认 |
| 显存占用 | 无 GPU 依赖,不涉及显存 |
| 启动方式 | 命令行启动 |
| 是否支持 API | 可封装为命令行调用,能嵌入脚本流程 |
| 是否支持批量任务 | 可以,通过脚本遍历目录完成批量识别 |
| 部署难度 | 低,不依赖大体积模型文件 |
从能力定位来说,它不是一个重型 OCR 服务,而是一个“够用就好”的原生工具。优势在于零模型、零训练、零网络依赖,隐私性也更好,因为识别过程在本地完成。
2. 适用场景与使用边界
2.1 适合谁用
平时需要频繁处理屏幕信息的人最适合这个项目。典型场景包括:
- 截图文字提取:看到网页、文档、视频里的一段文字,不想手动敲,直接框选识别。
- PDF 扫描件处理:扫描版 PDF 或图片 PDF 无法直接选取文字,用 OCR 转成文本。
- 演示文稿资料整理:从网课截图、会议录屏里批量抽取文字。
- 轻量自动化流程:在 shell 脚本里调用 OCR 命令,自动处理一批图片。
- 隐私敏感环境:文字内容不想上传到云端 OCR 服务,本地识别更稳妥。
2.2 不适合什么场景
- 超高精度复杂排版:原生 OCR 对复杂表格、公式、图文混排的还原能力有限。
- 中文古籍、手写体、生僻字:这类内容识别效果不稳定,需要专门模型。
- 大规模生产级 OCR:如果要一天处理几十万张图片,原生方案不是最优选择。
- 跨平台需求:项目绑定 macOS,Windows 和 Linux 需要用其他方案。
2.3 使用边界与合规提醒
屏幕 OCR 本质上是捕捉屏幕上显示的文字内容,使用时要特别注意:
- 只对自己有权限访问的内容做识别,不要抓取他人设备、非公开聊天记录、加密内容。
- 涉及商业文档、客户资料、个人隐私信息时,先确认是否有复制和使用权限。
- 不要用屏幕 OCR 绕过付费内容、版权保护或访问限制。
- 识别出来的文字如果用于发布、商用或训练,必须核对版权和授权。
这是一个工具,本身没有问题,但怎么用是使用者自己的责任。
3. 环境准备与前置条件
3.1 系统版本
项目依赖 macOS 原生 OCR 能力,所以第一件事是确认系统版本。从项目定位来看,它面向的是较新版本的 macOS,具体最低版本要求没有在源码里标注的话,建议优先在 macOS 12 Monterey 及以上版本测试。更稳妥的判断是:用你的日常系统跑一次,能识别就说明兼容。
查看系统版本:
sw_vers输出类似:
ProductName: macOS ProductVersion: 14.5 BuildVersion: 23F79如果你的系统版本比较旧,比如 macOS 10.15 或更早,需要先确认原生 OCR 是否可用。部分老版本系统对原生识别框架的支持不完整,可能出现识别结果为空或直接报错。
3.2 开发工具链
项目如果用 Swift 编写,需要安装 Xcode Command Line Tools。打开终端执行:
xcode-select --install如果已经安装过,会提示“already installed”。
确认 Swift 编译器版本:
swift --version输出类似:
Apple Swift version 5.9.23.3 磁盘空间与内存
这个项目不依赖大型模型文件,磁盘占用很小,主要就是编译产物和临时文件。内存方面,OCR 识别过程会短暂占用一定内存,但不会像大模型推理那样吃满资源。普通 8GB 内存的 Mac 跑起来没有压力。
3.4 权限准备
如果项目需要读取屏幕内容,需要在“系统设置 -> 隐私与安全性 -> 屏幕录制”中把对应的终端应用或 IDE 勾选允许。这一步容易漏,漏了之后识别结果就是空白。
4. 安装部署与启动方式
4.1 获取源码
项目是 GitHub 上常见的工程结构。先克隆到本地:
git clone https://github.com/your-project/monkey-see-monkey-do.git cd monkey-see-monkey-do注意:这里仓库地址是示例,实际地址以项目页面为准。如果你是从 Show HN 页面进入,直接点击项目链接即可。
4.2 查看项目结构
建议先看一遍目录,确认入口文件、源码文件和说明文件:
ls -la find . -name "*.swift"常见结构包括:
MonkeySeeMonkeyDo/ ├── Package.swift ├── Sources/ │ └── MonkeySeeMonkeyDo/ │ └── main.swift ├── Tests/ ├── README.md └── .gitignore4.3 编译与运行
Swift Package Manager 项目可以直接编译:
swift build编译成功后在.build/debug/目录下会生成可执行文件。运行方式:
swift run MonkeySeeMonkeyDo如果项目是纯脚本形式,可能直接这样运行:
swift main.swift第一次编译会下载依赖,耗时取决于网络状况。项目如果依赖少,一般几十秒内能完成。
4.4 配置路径与环境变量
如果项目支持自定义图片路径、输出路径或识别语言,通常会通过命令行参数或者配置文件传入。典型的用法是:
swift run MonkeySeeMonkeyDo --input path/to/image.png --output result.txt具体参数名需要看 README 或源码中的参数定义。没有明确参数时,先不带参数运行一次,看默认行为是什么。
4.5 验证启动成功
运行后如果出现以下迹象,说明服务或命令正常:
- 终端输出识别到的文本内容。
- 指定输出文件生成,内容非空。
- 没有报错信息。
如果项目会进入监听模式或提供交互界面,终端会显示提示语,比如“Waiting for screenshot”之类。
5. 功能测试与效果验证
5.1 测试素材准备
准备一组不同类型的测试图片,覆盖以下情况:
- 纯英文截图,字体清晰。
- 中文截图,区分简体与繁体。
- 包含数字和标点符号的图片。
- 屏幕截图,包含窗口标题、菜单栏、正文。
- 手机拍摄的文档照片。
- PDF 导出成图片后的页面截图。
建议用系统自带截图工具生成一张:
screencapture -x test.png这条命令会截取整个屏幕到test.png。
5.2 单张图片识别测试
用项目命令对单张图片做识别:
swift run MonkeySeeMonkeyDo --input test.png预期结果是终端输出图片中所有可识别文字。判断成功的标准:
- 输出文字和图片内容匹配。
- 英文单词完整。
- 中文句子没有明显乱码。
- 数字和字母识别正确。
如果结果为空,先检查屏幕录制权限,再检查图片清晰度。
5.3 屏幕区域识别测试
有些 OCR 工具支持直接框选屏幕区域。如果项目提供交互模式,运行后按住鼠标拖拽选中区域,松开后自动识别。这种模式更符合“Monkey see, monkey do”的定位——看见哪里,识别哪里。
测试步骤:
- 在屏幕上打开一段明显文字,比如一篇新闻网页。
- 运行屏幕区域识别命令。
- 框选网页正文区域。
- 查看输出是否与网页文字一致。
5.4 输出文件测试
如果项目支持输出到文件,可以这样测试:
swift run MonkeySeeMonkeyDo --input test.png --output result.txt cat result.txt检查文件内容:
- 文件是否生成。
- 编码是否为 UTF-8。
- 内容是否和终端输出一致。
- 中文是否正常显示,没有乱码。
5.5 识别语言测试
macOS 原生 OCR 通常支持系统语言和常见语言。如果项目支持语言参数,可以尝试:
swift run MonkeySeeMonkeyDo --input chinese.png --language zh-Hans如果当前系统语言是中文,默认可能已经识别中文。如果不支持中文,需要先确认系统安装了对应的语言支持。
判断标准:
- 中文句子完整识别。
- 特殊符号“@”“#”“%”等正确输出。
- 中英文混排时切换正确。
5.6 失败场景测试
测试几种容易失败的输入:
- 纯图片、无文字。
- 模糊截图。
- 旋转 90 度的文字。
- 手写文字。
- 白字黑底反白文字。
- 带水印背景的半透明文字。
这些场景能帮你了解项目的真实能力边界。原生 OCR 对正常屏幕文字效果好,对复杂背景、艺术字体、手写内容效果会明显下降。
6. 命令行接口与脚本集成
这个项目最有价值的点在于它可以通过命令行调用,能直接嵌入到自动化脚本里。
6.1 命令行参数设计
典型的命令行参数设计可能包括:
--input 输入图片路径 --output 输出文本文件路径 --language 识别语言代码 --region 识别区域,如 "0,0,100,100" --help 显示帮助没有现成参数文档的话,先运行:
swift run MonkeySeeMonkeyDo --help查看支持参数。
6.2 单文件处理脚本
写一个简单的 shell 包装脚本,方便反复调用:
#!/bin/bash # ocr_helper.sh - 调用 MonkeySeeMonkeyDo 识别单张图片 INPUT_FILE="$1" OUTPUT_FILE="${2:-result.txt}" if [ -z "$INPUT_FILE" ]; then echo "用法: ./ocr_helper.sh <图片路径> [输出文件]" exit 1 fi swift run MonkeySeeMonkeyDo --input "$INPUT_FILE" --output "$OUTPUT_FILE" if [ $? -eq 0 ]; then echo "识别完成: $OUTPUT_FILE" else echo "识别失败: $INPUT_FILE" >&2 exit 1 fi保存后加上执行权限:
chmod +x ocr_helper.sh ./ocr_helper.sh test.png output.txt6.3 Python 调用示例
如果要在 Python 项目里调用,可以用subprocess:
import subprocess import sys def ocr_image(image_path, output_path="result.txt"): cmd = [ "swift", "run", "MonkeySeeMonkeyDo", "--input", image_path, "--output", output_path ] result = subprocess.run(cmd, capture_output=True, text=True, timeout=60) if result.returncode != 0: print(f"OCR 识别失败: {result.stderr}") return None with open(output_path, "r", encoding="utf-8") as f: return f.read() if __name__ == "__main__": text = ocr_image(sys.argv[1] if len(sys.argv) > 1 else "test.png") print(text)运行:
python3 ocr_demo.py test.png6.4 API 服务封装思路
如果项目本身不提供 HTTP API,也可以自己封装一个轻量服务,把 OCR 能力暴露给局域网内其他工具使用。这里给一个 FastAPI 的通用示例,需要按实际情况调整:
from fastapi import FastAPI, UploadFile, File import subprocess import tempfile import os app = FastAPI() @app.post("/ocr") async def ocr_endpoint(file: UploadFile = File(...)): with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmp: tmp.write(await file.read()) tmp_path = tmp.name output_path = tmp_path + ".txt" cmd = [ "swift", "run", "MonkeySeeMonkeyDo", "--input", tmp_path, "--output", output_path ] subprocess.run(cmd, timeout=30) with open(output_path, "r", encoding="utf-8") as f: text = f.read() os.unlink(tmp_path) os.unlink(output_path) return {"text": text}启动服务:
uvicorn ocr_api:app --host 127.0.0.1 --port 8000调用:
curl -X POST http://127.0.0.1:8000/ocr \ -H "Content-Type: multipart/form-data" \ -F "file=@test.png"需要注意,swift run每次调用都会检查编译状态,实际做接口服务时,更合理的方案是直接调用编译后的二进制文件,减少启动开销。
7. 资源占用与性能观察
7.1 观察 CPU 与内存占用
识别过程中可以在另一个终端窗口用top观察:
top -o cpu -l 1或者用更直观的方式,先开启持续监控:
top -o cpu -n 5重点看:
- 识别瞬间 CPU 占用率是否升高。
- 内存占用是否有明显增长。
- 识别完成后资源是否回落。
由于不涉及 GPU 和模型推理,资源占用通常很低。如果你观察到内存持续不释放,可能是项目本身存在内存管理问题。
7.2 处理速度观察
单张图片识别速度受以下因素影响:
- 图片分辨率越高,耗时越长。
- 图片中文字越多,耗时越长。
- 系统负载越高,耗时越长。
测试方法:
time swift run MonkeySeeMonkeyDo --input test.png输出的real时间就是总耗时。如果几十秒甚至几分钟都没有结果,需要检查是否有死循环或权限弹窗等待。
7.3 批量识别性能
批量识别时,如果每次都用swift run启动,会因为编译检查引入额外开销。更高效的做法是编译一次,然后直接调用可执行文件:
swift build -c release ./.build/release/MonkeySeeMonkeyDo --input test.png这样能明显提高批处理速度。
7.4 如何降低资源占用
- 识别前先裁剪图片,只保留包含文字的区域。
- 降低图片分辨率,不需要用 4K 原图。
- 关闭不必要的后台应用,减少系统负载。
- 批量任务中控制并发数,避免同时启动太多进程。
8. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 运行后无输出 | 屏幕录制权限未开启 | 到系统设置检查权限 | 给终端或 IDE 开启屏幕录制权限 |
| 输出乱码 | 图片编码问题或语言不支持 | 换一张标准 PNG 图片测试 | 转换图片格式,检查系统语言支持 |
| 中文识别失败 | 系统语言包缺失 | 用英文图片对比测试 | 到系统设置添加中文语言支持 |
| 编译报错 | Swift 版本过旧或依赖缺失 | 执行swift --version | 安装最新 Xcode Command Line Tools |
| 图片路径找不到 | 路径写错或包含空格 | 检查文件是否存在 | 用pwd确认当前目录,路径加双引号 |
| 识别结果乱序 | 原生 OCR 对多栏排版支持有限 | 裁剪成单栏图片测试 | 手动裁剪后再识别 |
| 批量处理慢 | 每次都重新编译运行 | 查看进程列表 | 编译 release 版本后直接调用二进制 |
| 屏幕框选无响应 | 权限弹窗被忽略 | 检查系统设置权限列表 | 重启终端应用后重新授权 |
| 输出文件为空 | 图片中没有可识别文字 | 打开图片确认文字可见 | 换一张文字清晰的图片 |
| 端口被占用 | 自建 API 服务端口冲突 | 执行lsof -i :8000 | 更换端口号 |
9. 最佳实践与使用建议
9.1 先跑最小测试
拿到项目后不要直接处理复杂 PDF,先用一张截屏图跑通整个流程,确认权限、编译、输出三个环节都正常。
9.2 建立固定的目录结构
建议保持这样的目录组织:
ocr-workdir/ ├── input/ # 原始图片、截图 ├── output/ # 识别结果文本 ├── logs/ # 运行日志 └── scripts/ # 封装脚本这样批量任务跑完,结果文件不会散落一地。
9.3 写日志与失败重试
批量处理时,一定要给每个文件记录成功或失败状态。简单做法是在 shell 脚本里追加日志:
echo "$(date) - $INPUT_FILE - SUCCESS" >> logs/ocr.log失败时:
echo "$(date) - $INPUT_FILE - FAILED" >> logs/ocr_error.log重试时只处理 error 日志中的文件即可。
9.4 识别后用文本工具二次处理
OCR 出的文本往往存在多余换行、空格错乱、全半角混用问题。可以接一个文本清洗步骤:
cat result.txt | sed 's/ */ /g' > cleaned.txt更复杂的清洗可以直接在 Python 中做。
9.5 接口服务限制访问
如果你自己封装了 HTTP API,至少要限制在本地访问,不要用0.0.0.0暴露到公网。默认绑定127.0.0.1是最稳妥的方式。
9.6 合规使用提醒
再强调一次:OCR 本身是中立技术,但对他人文档、聊天记录、受版权保护的电子书、付费课程截图进行识别并二次传播,可能涉及版权和隐私问题。请确保你处理的材料是自己有权使用的。
10. 总结与下一步
Monkey see, monkey do 这类项目的价值不在于算法多先进,而在于把 macOS 原生 OCR 能力变成一条可复用的命令。对开发者和效率工具爱好者来说,它提供了几个可以直接用的方向:
- 把屏幕截图自动转成文字,替代手动抄录。
- 把 PDF 扫描件批量转成可搜索文本。
- 在 shell 或 Python 脚本中集成 OCR 能力。
- 快速验证 macOS 原生 OCR 在自己业务场景下的效果。
建议拿到项目后先完成三件事:编译通过、单图识别成功、命令行参数确认。这三步跑通,后面怎么扩展都顺。
最容易踩的坑是屏幕录制权限没开,导致识别结果始终为空。其次是用swift run跑批量任务太重,编译一次后直接用 release 二进制才是正确做法。
后续可以扩展的方向包括:对接剪贴板实现“截图即识别”、封装成菜单栏小工具、把识别结果自动写入 Obsidian 或 Notion、配合 AppleScript 自动化工作流。
这个项目很适合作为 macOS 效率工具链里的一个基础组件,代码量不大,逻辑清晰,值得拉下来读一遍源码,顺便看看苹果原生 OCR 接口到底怎么调用。