screenpipe:把AI记忆刻进本地的Rust实践

6 次阅读 0 点赞 0 评论 10 分钟原创开源项目

screenpipe用Rust重写「数字记忆」基础设施:事件驱动捕获(5–10% CPU)、SQLite FTS5语义搜索、MCP协议直连Claude、OS级权限隔离的Pipe插件系统。不上传、不依赖云、不妥协隐私——所有AI能力运行在你MacBook的内存里。

#Rust # AI # local-first # privacy # desktop-app # automation # MCP # screen-recording # knowledge-management
screenpipe:把AI记忆刻进本地的Rust实践

嘿,各位Java老战友,我是周小码——一个被Spring Boot自动配置折磨到怀疑人生的后端老兵,最近却在Rust项目里喝到了一口清冽的山泉。今天聊的不是JVM调优,也不是K8s YAML写到手抽筋,而是这个让我凌晨三点关掉IDEA、打开屏幕录像反复验证的项目:screenpipe

痛点不是“录不到”,是“录了也找不到”

我们每天产生的数字痕迹,比自己记得的多十倍:Zoom会议里一闪而过的报错截图、IntelliJ控制台滚屏消失的堆栈、Slack里同事发的那条关键配置命令……它们真实存在,却像沉入深海的碎片——没有索引、没有上下文、没有时间锚点。传统录屏工具只负责“存”,不解决“找”;云笔记要手动复制粘贴,漏掉音频、窗口状态、光标位置这些隐性上下文;而所谓“AI助手”,往往只是把你的数据喂给远端大模型,再把结果吐回来——你既不知道它记了什么,也不知道它忘了什么。

screenpipe 不是又一个录屏软件,它是你电脑的「海马体」——那个负责把短期记忆转成长期记忆的大脑结构。它不靠云、不求人,就在你本地默默运行,把你的每一次窗口切换、每一段Zoom会议、每一行敲下的代码、甚至你自言自语的吐槽,都变成可搜索、可编程、可AI理解的「数字记忆」。

架构即哲学:三层乐高,全部本地化

它的架构不是炫技堆叠,而是对「本地优先」的工程具象:

  • 底层采集层(Rust + Tauri):不走ffmpeg全帧抓取,而是监听系统事件(AXUIElement, CGWindowListCopyWindowInfo, uinput等),仅在窗口切换、按键释放、鼠标悬停、滚动停止等「认知锚点时刻」触发快照+Accessibility Tree抓取。README实测CPU占用稳定在5–10%,MacBook M2 Air跑满24小时无风扇狂转。

  • 中间存储层(SQLite + FTS5):所有数据落地为本地SQLite DB,启用WAL模式+PRAGMA mmap_size=268435456(256MB内存映射)+零拷贝BLOB读取。FTS5全文检索不仅支持MATCH 'error AND stacktrace',更通过rank=bm25(10.0, 5.0)加权标题与OCR文本,并预留fts5vocab表供后续接入Sentence-BERT做向量相似度补全——但注意:默认不启向量库,纯FTS5已足够应对90%知识检索场景

  • 上层交互层(MCP Server + Pipes):HTTP API是入口,但真正灵魂是MCP(Model Context Protocol)服务。它不是RESTful,而是基于JSON-RPC 2.0定义的上下文感知协议,让Claude/Cursor等AI客户端能以{"method":"search_context","params":{"q":"NullPointerException in UserService","time_window":"last_2h"}}方式精准提问。而所有回答背后,都是本地SQLite的JOIN查询+Whisper本地ASR结果拼接——没有token外泄,没有请求日志上传。

核心代码解析:从CLI到Pipe,全是硬核细节

先看最狠的一行安装命令:

bash 复制代码
npx screenpipe@latest record

这行命令背后藏着三重设计:

  1. npx绕过Rust环境依赖,实际执行的是预编译的Tauri二进制(macOS: .app, Windows: .exe, Linux: ELF);
  2. record子命令直接调用Rust主函数cli::run_record(),跳过GUI初始化,启动纯后台采集;
  3. 所有配置(如OCR开关、采样间隔、窗口白名单)由~/.screenpipe/config.json驱动,支持热重载——改完配置不用重启进程。

再看最关键的搜索API,它暴露的不只是关键词匹配:

bash 复制代码
GET http://localhost:3030/search?q=meeting+notes&content_type=ocr&limit=10

这个/search端点实际路由到Rust的axum handler:

rust 复制代码
// src/api/search.rs
async fn handle_search(
    State(db): State<DbPool>,
    Query(params): Query<SearchQuery>,
) -> Result<Json<Vec<SearchResult>>, StatusCode> {
    let mut query = format!("SELECT * FROM segments WHERE content MATCH ?");
    // 关键:根据content_type动态JOIN不同表
    if params.content_type == "ocr" {
        query.push_str(" AND segments.id IN (SELECT segment_id FROM ocr_results)");
    }
    // 时间范围用SQLite内置datetime处理,非应用层过滤
    if let Some(t) = &params.start_time {
        query.push_str(&format!(" AND datetime(timestamp) >= datetime('{}')", t));
    }
    // 使用FTS5 bm25排序,而非简单ORDER BY
    query.push_str(" ORDER BY rank MATCH ?");
    
    let rows = sqlx::query(&query)
        .bind(&params.q)
        .bind(&params.q)
        .fetch_all(&*db)
        .await?;
    Ok(Json(rows.into_iter().map(|r| r.into()).collect()))
}

最后是Pipe插件系统的灵魂——pipe.md文件:

markdown 复制代码
---
## 权限声明:OS级硬隔离,非AI自觉守规矩
permissions:
  - read: ["chrome", "vscode"]
  - ocr: ["chrome"]
  - audio: false
  - write: false
---

当检测到VS Code中出现"ERROR"字样时:
1. 截取当前编辑器窗口内容
2. 提取其中堆栈跟踪(正则匹配java.lang.*Exception)
3. 将错误摘要和时间戳写入Obsidian vault的"errors/"目录
4. 向飞书机器人发送告警(需提前配置webhook)

这个YAML前言会被Rust解析器pipe::parse_permissions()校验:若Pipe试图读取微信窗口,内核级accessibility_api::is_allowed()直接返回Err(PermissionDenied),根本不会进入OCR流程——权限不是运行时检查,是编译期+OS API双锁死

实战演示:5分钟构建你的AI站会助理

假设你每天10:00开站会,录音+共享屏幕。用screenpipe自动化:

  1. 创建standup.pipe.md
markdown 复制代码
---
permissions:
  - audio: true
  - ocr: ["zoom"]
  - write: true
---

当检测到Zoom会议开始且麦克风开启时:
- 录制音频流(Whisper.cpp本地转录)
- 每30秒抓取Zoom窗口OCR文本(识别共享PPT中的Action Items)
- 将转录文本+OCR结果合并,用Ollama llama3生成会议纪要
- 保存为`daily/standup_20260320.md`并推送到Git
  1. 启动监听:
bash 复制代码
screenpipe pipe watch --file ./standup.pipe.md
  1. 查看结果(毫秒级响应):
javascript 复制代码
import { pipe } from "@screenpipe/js";

const results = await pipe.queryScreenpipe({
  q: "assign to me",
  contentType: "all",
  limit: 5,
  startTime: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),
});
// 返回结构包含:timestamp, window_title, ocr_text, audio_transcript, embedding_vector(可选)

踩坑指南:现实骨感,但可控

  • Apple Intelligence仅限M系列芯片:因为依赖AVFoundation的硬件加速编码,Intel Mac需降级使用ffmpeg软编,CPU占用升至15–20%;
  • Linux需源码编译:官方未提供预编译二进制,但README的cargo build --release --features linux步骤清晰,关键是安装libx11-dev libxtst-dev libasound2-dev等头文件;
  • Whisper模型首次加载慢:默认下载ggml-base.en.bin约170MB,建议提前screenpipe model download --name base.en
  • SQLite WAL冲突:多进程写入时可能触发database is locked,解决方案是PRAGMA journal_mode=WAL; PRAGMA synchronous=NORMAL;已内置,无需手动干预。

个人评价:这不是工具,是新契约

作为Java人,我酸了——我们还在为Spring Cloud Gateway的路由配置掉头发时,screenpipe已经用Tauri(Rust+TS)把桌面应用、CLI、HTTP服务、MCP服务器全塞进一个二进制里。它没用gRPC,没上Kafka,却靠SQLite WAL模式+内存映射+零拷贝IO实现了毫秒级搜索响应。

值不值得学?必须。不是学它怎么录屏,而是学它如何用Rust重写「信任契约」:把隐私承诺变成编译期约束,把AI能力封装成Markdown语法,把复杂系统拆解成可插拔、可审计、可离职交接的Pipe文件。这,才是下一代开发者该有的基础设施思维。

P.S. 我刚试完,它真的记住了我刚才吐槽这段话时皱的眉——虽然还没学会给我递杯咖啡 😅

最后更新:2026-03-20T10:01:42

评论 (0)

发表评论

blog.comments.form.loading
0/500
加载评论中...