Rust+AI构建本地化屏幕活动分析器:从原理到实战部署
1. 项目概述:一个真正属于你的屏幕活动智能分析器
最近在折腾一个挺有意思的东西,一个用 Rust 写的屏幕时间监控工具,叫 ScreenTime。这玩意儿和市面上那些单纯统计应用使用时长的工具不太一样,它的核心是“理解”,而不是“计时”。它通过定期截取你的屏幕,然后调用 AI 视觉模型来分析你此刻到底在干什么——是在写代码、看文档、刷网页,还是在摸鱼看视频。
最吸引我的点是它的“Own Your Data”理念。所有数据——截图、分析日志、系统上下文——都老老实实待在你指定的本地目录里,没有云端同步,没有数据上报(除非你主动配置)。它集成了 MCP 服务,意味着你可以通过标准协议远程控制它,也支持将分析摘要推送到像 OpenClaw 这样的智能体网关,让你的 AI 助手能“看到”你的工作状态。对于我这种既想量化自己的工作流,又对隐私比较在意的开发者来说,算是找到了一个平衡点。如果你也厌倦了商业软件的数据黑洞,想自己动手搭建一个透明、可控的屏幕活动分析系统,这个项目值得你花时间研究一下。
2. 核心设计思路:为什么是 Rust + AI + 本地优先?
2.1 技术栈选型的深层考量
当我第一次看到这个项目时,我就在想,为什么是 Rust?为什么用 AI 分析截图?这套组合拳背后其实有很实际的工程考量。
首先,Rust 保证了核心监控服务的稳定与高效。屏幕截图和分析是一个需要长时间在后台运行的服务,对内存安全和并发性能要求很高。Rust 的所有权系统和零成本抽象,能有效避免内存泄漏和并发数据竞争,这对于一个 7x24 小时运行的后台守护进程至关重要。用tokio做异步运行时,处理截图、网络请求、日志写入这些 IO 密集型任务游刃有余,不会卡住主线程。
其次,AI 视觉模型提供了超越传统规则的“理解”能力。传统的活动监控要么基于简单的窗口标题关键字匹配(比如检测到“Chrome”就算“浏览”),要么需要复杂的规则引擎。而像 GLM-4V、LLaVA 这样的多模态大模型,能真正“看懂”截图内容。它不仅能识别出你在用 VS Code,还能进一步判断你是在写代码、调试,还是在看文档。这种语义层面的理解,让后续的分析和统计维度丰富了很多。
最后,本地优先与开放协议构成了可扩展的架构。数据默认全在本地,通过 MCP 协议暴露控制接口,再通过可选的 Webhook 与外部系统(如 OpenClaw)联动。这个设计非常巧妙:基础功能自闭环,满足隐私需求;同时又通过标准协议打开了扩展性,允许你将其接入更复杂的自动化工作流中。你不是被锁死在一个固定功能里,而是获得了一个可以随意组合的“乐高积木”。
2.2 数据流与核心模块拆解
整个工具的工作流可以概括为“采集 -> 处理 -> 分析 -> 记录 -> 上报”五个核心环节,每个环节都由独立的模块负责,耦合度很低。
- 采集层(
screenshot.rs,context.rs): 由定时器驱动,负责截取屏幕原始图像,并同步收集当前系统的上下文信息(活跃进程、内存、网络等)。这里的关键是权限处理 (permissions.rs),在 macOS 和 Windows 上如何优雅地引导用户授权,是第一个要跨过的坑。 - 处理层(集成在
screenshot.rs): 对原始截图进行预处理。这是v0.2.2版本的重大改进,加入了智能缩放和灰度转换。默认将图片缩放到 1440px 宽并转灰度,这并非随意设定。缩放是为了减少传输和模型处理的数据量,1440p 在清晰度和大小间取得了平衡;转灰度则是为了剥离无关的颜色信息,让 AI 模型更专注于内容和布局,实践证明这能提升分析准确率并降低 Token 消耗。 - 分析层(
siliconflow.rs): 将处理后的图片和系统上下文,按照预设的 Prompt 模板,构造请求发送给 AI 服务。这里支持 SiliconFlow 云服务、私有化部署以及 Ollama 本地模型,灵活性很强。v0.3.0加入的 Token 统计功能非常实用,让你能清晰掌握每次分析的成本。 - 记录层(
logger.rs): 将 AI 返回的分析结果、Token 使用量、系统上下文和截图路径,以结构化的 JSON 格式按日期写入本地日志文件。按天分割日志的设计,便于后期按时间范围进行数据检索和归档。 - 上报层(
openclaw.rs): 这是一个可选模块。它会定期(默认30分钟)汇总过去一段时间内的活动日志,生成一份摘要,并通过 HTTP POST 发送到你配置的 OpenClaw Gateway 的/hooks/agent端点。这样,你的 AI 助手就能在对话中了解到你过去半小时在电脑上做了什么,实现跨设备的上下文感知。
这种模块化设计使得每个部分都可以独立替换或升级。比如,你可以很容易地把分析后端从 SiliconFlow 换成其他支持视觉的 API,或者自定义日志的存储方式。
3. 从零开始的部署与配置实战
3.1 环境准备与项目构建
假设你已经在本地安装了 Rust 工具链(通过rustup)。如果没有,一行命令就能搞定。这个项目对 Rust 版本要求并不苛刻,稳定的最新版即可。
# 1. 克隆仓库 git clone https://github.com/shadowcz007/ScreenTime.git cd ScreenTime # 2. 进行发布构建。推荐使用 `--release`,这会进行大量优化,虽然编译时间稍长,但运行时性能好得多。 cargo build --release编译完成后,可执行文件screen_time(Windows 上是screen_time.exe)会出现在target/release/目录下。我建议你把它复制到一个方便的地方,或者将其所在路径加入系统的PATH环境变量。
注意:第一次编译可能会花费一些时间,因为需要下载和编译所有的依赖项,包括图像处理、HTTP 客户端等库。这是正常现象。
3.2 基础配置与首次运行
运行前,你需要一个 AI 服务的 API Key。项目默认支持 SiliconFlow,你可以去其官网注册获取。当然,我们也完全可以使用免费的本地方案,后面会讲。
最基本的启动命令如下:
./target/release/screen_time --api-key your_siliconflow_api_key_here运行这行命令,你会遇到第一个也是最重要的环节:权限申请。程序会自动检测并弹出系统提示,引导你授予“屏幕录制”和“辅助功能”权限(macOS)。请务必点击“允许”或“打开系统偏好设置”进行授权。没有这些权限,截图和获取窗口信息的功能将无法工作。
授权成功后,程序就会在后台静默运行起来。默认每 60 秒截屏一次,调用 AI 分析,然后将结果记录到默认的数据目录中。
数据目录在哪?
- macOS:
~/Library/Application Support/ScreenTime/ - Linux:
~/.local/share/screentime/ - Windows:
%APPDATA%\ScreenTime\
你可以通过--data-dir参数指定一个你喜欢的路径,比如放在一个同步盘里。
3.3 核心配置参数详解
ScreenTime 的配置非常灵活,主要通过命令行参数和环境变量控制。理解这几个核心参数,你就能驾驭它的大部分功能。
1. 控制分析行为:
--interval: 截图间隔,单位秒。默认 60 秒。不建议设置得太短(如小于30秒),以免对系统性能和 API 配额造成不必要的压力。对于专注工作流分析,2-5分钟间隔可能更合理。--prompt: 发送给 AI 模型的指令。这是决定分析质量的关键!默认的 Prompt 要求模型按“【类型】【软件】【主要工作摘要】”格式输出。你可以根据需求修改,比如让它分析“用户的专注程度”或“可能遇到的卡点”。--model: 指定使用的 AI 模型。SiliconFlow 上有很多选择,如Qwen/Qwen2-VL-7B-Instruct可能比默认的THUDM/GLM-4.1V-9B-Thinking更快或更便宜。如果使用 Ollama,则指定如llava:7b。
2. 控制数据处理:
--keep-screenshots: 默认情况下,为了节省空间,AI 分析完成后截图文件会被删除。启用此标志将保留所有截图。注意:这会快速占用大量磁盘空间,请谨慎使用,或定期手动清理screenshots目录。--image-target-width和--image-grayscale: 控制图片预处理。如前所述,调整宽度和启用灰度能优化性能与效果。如果你需要分析界面颜色信息(比如设计工作),则可以禁用灰度--no-image-grayscale。
3. 服务与集成:
--mcp: 以 MCP 服务器模式启动,监听127.0.0.1:8000。这样你就可以通过兼容 MCP 的客户端(如某些 AI 助手 IDE 插件)来远程查询日志或控制监控开关。--openclaw-url和--openclaw-token:必须同时提供才会启用 OpenClaw 上报功能。这让你可以将屏幕活动摘要集成到更广阔的智能体工作流中。
一个综合性的启动示例,使用了环境变量来配置:
# 将配置写入 shell 配置文件(如 .bashrc 或 .zshrc)中,方便复用 export SILICONFLOW_API_KEY="sk-xxxxxx" export SCREENTIME_DATA_DIR="$HOME/Documents/ScreenTimeData" export SCREENSHOT_INTERVAL_SECONDS=120 export IMAGE_TARGET_WIDTH=1024 export KEEP_SCREENSHOTS=0 # 0 为 false,1 为 true # 启动 ./target/release/screen_time4. 高级玩法与定制化指南
4.1 拥抱本地大模型:Ollama 集成实战
使用云端 API 总有网络、成本和隐私的顾虑。ScreenTime 很贴心地支持了 Ollama,让你在本地就能跑通整个流程。
第一步:搭建 Ollama 环境去 Ollama 官网下载安装,然后拉取一个支持视觉的模型。llava系列是首选。
# 安装后,拉取模型(7B版本对大多数显卡比较友好) ollama pull llava:7b # 如果显存充足,可以尝试 13B 或 34B 版本以获得更好效果 # ollama pull llava:13b第二步:配置并启动 ScreenTime启动 Ollama 服务(通常安装后会自动运行),然后使用以下配置启动 ScreenTime:
./target/release/screen_time \ --api-key "ollama" \ # 这里填任意非空字符串即可,通常用 "ollama" 或 "local" --api-url "http://localhost:11434/v1/chat/completions" \ --model "llava:7b" \ --data-dir "$HOME/.local/screentime-ollama"关键点与踩坑记录:
--api-key参数不能省略:虽然 Ollama 不需要密钥,但程序逻辑需要这个参数。填ollama或local都行。- 注意 Ollama 的 API 兼容性:Ollama 提供了与 OpenAI 兼容的
/v1/chat/completions端点,ScreenTime 正是利用这一点实现了无缝切换。确保你的 Ollama 版本支持此端点。 - 性能与显存:
llava:7b在 8GB 显存的 GPU 上运行尚可,但分析一张处理后的截图仍需数秒。CPU 模式会非常慢。启动后观察token_usage,如果prompt_tokens异常高(比如几十万),可能是图片 Base64 编码过大,尝试降低--image-target-width(如 800)。 - Prompt 适配:为本地模型优化 Prompt 可能有必要。有些小模型对指令格式更敏感。你可以在默认 Prompt 基础上微调,并通过
--test-prompt功能进行对比测试。
4.2 深入 MCP 服务器模式:远程控制与集成
MCP 模式让 ScreenTime 从一个后台工具变成了一个可交互的服务。
启动 MCP 服务器:
./target/release/screen_time --mcp --api-key your_key启动后,它会在127.0.0.1:8000提供一个标准的 MCP 服务端点。
如何与之交互?你需要一个支持 MCP 客户端的工具。例如,在某些 AI 编程助手的设置中,你可以添加一个 MCP 服务器,配置其地址。之后,你就可以在对话中直接使用它提供的工具:
monitor: 向助手说“帮我启动屏幕时间监控”,助手内部会调用monitor工具的start动作。read_logs: 询问“我今天上午都干了什么?”,助手可以调用此工具查询日志并总结给你。take_screenshot: “现在立刻截一张屏看看我在干嘛”。
实操心得:MCP 的潜力MCP 的价值在于标准化。一旦 ScreenTime 以 MCP 服务器形式运行,任何兼容 MCP 的客户端(不限于某个特定的 IDE 或助手)都能使用它的功能。你可以想象将其集成到一个自动化工作流中:当监测到你长时间处于“社交娱乐”类型时,自动让智能音箱提醒你休息;或者在你开始“编程”时,自动为你打开音乐播放列表。
4.3 利用 OpenClaw 实现跨应用上下文感知
这是我认为最酷的功能之一。OpenClaw 是一个智能体网关,ScreenTime 可以将你的活动摘要推送过去。
配置步骤:
- 确保你有一个正在运行的 OpenClaw Gateway,并知道其
hooks.token配置。 - 启动 ScreenTime 时加上两个参数:
./target/release/screen_time \ --api-key your_key \ --openclaw-url http://你的网关地址:端口/hooks/agent \ --openclaw-token 你的Webhook令牌
发生了什么?ScreenTime 会每隔 30 分钟(可通过--openclaw-report-interval-minutes调整)将过去这段时间内的活动日志汇总成一段文本摘要,然后以“智能体”的身份 POST 到 OpenClaw Gateway。
在 OpenClaw 主会话中,你可能会看到这样的消息:
ScreenTime: 用户电脑设备在过去30分钟内的活动摘要:12:00-12:30,主要进行【工作】类活动,使用【VS Code】编辑 Rust 项目配置文件;12:30-13:00,活动切换为【沟通】,使用【Slack】进行团队技术讨论。
于是,你的 AI 助手在和你对话时,就拥有了“知道你刚才在干什么”的上下文。你可以问它:“基于我刚刚在写的代码,帮我解释一下这个错误?” 这种体验的连贯性会大大提升。
重要安全提示:
--openclaw-token必须与 Gateway 配置中的hooks.token完全一致,包括任何首尾空格。建议直接从配置文件中复制。同时,确保 Gateway 的/hooks/agent端点不直接暴露在公网,应置于内网、Tailscale 网络或受信任的反向代理之后。
4.4 Prompt 工程与测试模式:让 AI 更懂你
默认的 Prompt 可能不适合所有人。也许你更关心“是否在会议中”,或者“是否遇到阻塞”。ScreenTime 的--test-prompt模式就是为你优化 Prompt 准备的。
使用方法:
- 先让程序以正常模式运行一段时间,在
screenshots目录下积累一些截图样本。 - 停止程序。
- 使用测试模式,指定一个新的 Prompt 对旧截图重新分析:
./target/release/screen_time \ --api-key your_key \ --test-prompt "请分析用户当前是否处于深度专注状态。如果是,判断依据是什么(如全屏、特定工具)?如果不是,有哪些干扰因素(如多窗口、通讯软件)?请输出格式:【专注状态】【依据/因素】" \ --test-log-path ./focus_analysis_test.json - 程序会读取最新的截图和其对应的历史系统上下文,用新 Prompt 请求 AI 重新分析,并将结果保存到
focus_analysis_test.json,而不会影响原有的按日日志。 - 打开
test_log.json,对比新旧 Prompt 的分析结果,评估哪个更符合你的需求。
Prompt 设计技巧:
- 明确任务:告诉 AI 你要它做什么。“描述图片”不如“分析用户的工作活动类型”明确。
- 规定格式:像默认 Prompt 那样要求固定格式(【类型】【软件】【摘要】),极大方便了后续的日志解析和自动化处理。
- 提供上下文:ScreenTime 已经附带了丰富的系统上下文(进程、窗口等),你可以在 Prompt 中提醒 AI 参考这些信息,例如:“结合当前活跃的进程列表,判断用户的主要任务是什么”。
- 迭代优化:用
--test-prompt多试几次,观察不同表述下 AI 输出的稳定性和准确性。
5. 问题排查与效能优化指南
5.1 常见运行问题与解决方案
在部署和使用过程中,你可能会遇到以下问题。这里是我踩过坑后总结的排查清单。
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 启动后立即退出,无任何截图 | 1. 缺少 API Key。 2. 权限未正确授予。 | 1. 检查--api-key参数或SILICONFLOW_API_KEY环境变量是否设置。2. 重新运行程序,仔细查看启动日志,按照提示前往系统设置授予“屏幕录制”和“辅助功能”权限。macOS 可能需要重启应用。 |
日志中description字段为“截图分析失败”或类似错误 | 1. 网络问题,API 调用失败。 2. API Key 无效或额度不足。 3. 模型不支持或不存在。 4. 图片预处理或传输出错。 | 1. 检查网络连接。 2. 验证 API Key 有效性。对于 SiliconFlow,可访问其控制台查看余额和调用记录。 3. 确认 --model参数拼写正确,且在当前 API 端点可用。4. 查看程序输出的更详细的错误日志。尝试启用 --keep-screenshots保留截图,手动检查screenshots/目录下图片是否正常生成。 |
| 使用 Ollama 时分析速度极慢或 Token 数异常高 | 1. 图片尺寸过大,导致编码后 Token 数爆炸。 2. 在 CPU 模式下运行大型模型。 | 1.强烈建议启用--image-grayscale并设置较小的--image-target-width(如 800)。这将大幅减少输入 Token。2. 确保 Ollama 正确识别并使用 GPU。运行 ollama ps查看模型运行情况。考虑换用更小的模型,如llava:7b。 |
| OpenClaw 上报失败,返回 401 | --openclaw-token与 Gateway 配置中的hooks.token不匹配。 | 1. 仔细核对 Token,确保完全一致,包括大小写和任何特殊字符。 2. 使用 curl命令手动测试(如项目文档所示),确认 Token 和 URL 正确。 |
| 磁盘空间快速被占满 | 启用了--keep-screenshots且未定期清理。 | 1. 如果不需保留原始截图,请移除--keep-screenshots参数。2. 如需保留,可编写定时任务(cron 或 systemd timer)定期清理 screenshots/目录中过期的文件。 |
| MCP 客户端无法连接 | 1. MCP 服务器未启动。 2. 防火墙或端口冲突。 | 1. 确认启动时加了--mcp参数,并检查日志是否显示在 8000 端口监听。2. 尝试用 curl http://127.0.0.1:8000测试服务是否可达。检查是否有其他程序占用 8000 端口。 |
5.2 性能调优与成本控制
对于长期运行的服务,效率和成本是需要持续关注的。
1. 平衡分析频率与资源消耗
- 截图间隔 (
--interval): 这是最重要的调节阀。对于全天候监控,120-300 秒(2-5分钟)的间隔通常能很好地平衡时效性与资源消耗。间隔太短(如30秒)会产生大量截图和 API 调用,成本激增且可能触发速率限制。 - 图片预处理:
--image-target-width 1024 --image-grayscale这个组合是我测试后的甜点。在保证 AI 能看清文字和界面元素的前提下,将输入 Token 降低了约 60-70%,显著降低了每次分析的成本和时间。
2. 模型选择策略
- 云端服务 (SiliconFlow): 关注不同模型的定价和速度。
Qwen/Qwen2-VL系列通常是性价比之选。在控制台设置预算告警。 - 本地模型 (Ollama): 零 API 成本,但需要硬件投入。
llava:7b是入门首选。如果你的活动场景复杂(如频繁切换专业软件),llava:13b的理解能力会更强,但需要更多显存。关键指标是token_usage.prompt_tokens,它直接对应处理时间。如果这个值持续很高,一定要优化图片输入。
3. 日志管理与数据维护
- 日志文件按日生成,默认不会自动轮转或删除。你需要定期手动或通过脚本清理旧的日志文件(例如,保留最近30天的数据)。
- 如果你启用了
--keep-screenshots,务必设置一个自动清理策略。一个简单的 bash 脚本就能搞定:# 每周一凌晨3点,删除7天前的截图 0 3 * * 1 find /path/to/your/data/screenshots -type f -mtime +7 -delete
5.3 深入日志分析:从数据到洞察
日志文件 (logs/YYYY-MM-DD.json) 是宝库。每个条目都是一个结构化的记录。你可以用jq这样的命令行工具进行快速分析。
# 查看今天所有的活动类型分布 cat logs/$(date +%Y-%m-%d).json | jq -r '.description' | grep -oP '【\K[^】]+' | head -1 | sort | uniq -c | sort -nr # 提取今天使用 VS Code 的所有记录及其时间 cat logs/$(date +%Y-%m-%d).json | jq -r 'select(.description | contains("VSCode")) | "\(.timestamp): \(.description)"' # 统计今日总 Token 消耗(假设使用 SiliconFlow) cat logs/$(date +%Y-%m-%d).json | jq '.token_usage.total_tokens' | awk '{sum+=$1} END {print sum}'更进一步,你可以将日志导入到 SQLite 甚至 Grafana 中,生成可视化的仪表盘,查看你的“工作类型”随时间的变化趋势,或者分析不同软件对你的时间占用情况。ScreenTime 提供了原始数据,如何利用这些数据创造价值,就看你的想象力了。
这个项目给我最大的启发是,通过将成熟的 AI 能力与注重隐私的本地化设计相结合,我们完全可以构建出比商业软件更贴合个人需求、更值得信赖的数字工具。它不是一个终点,而是一个强大的起点。你可以基于它记录的数据,构建自己的生产力分析系统,或者将其作为智能体感知现实世界的一个可靠感官。
