开源 Linux截图工具闪构(SnapForge)
摘要 :Linux 上从不缺截图工具,缺的是"一个把事做完的工具"。但没有任何一款 Linux 工具能同时做好截图、标注、贴图、录屏、OCR、滚动长截图这六件事。于是有了 SnapForge(闪构),免费开源(GPL-3.0),纯 Python + Qt 实现,零 sudo 依赖,673 个自动化测试护航。本文聊功能,也聊几个有意思的技术决策:为什么用 ctypes 直调 libX11、为什么前端既不用 Electron 也不用 Flutter、滚动长截图为什么"不替你滚"才是正确答案。
一 缘起
- 我的主力系统是 Linux,但每次看到 Windows用 PixPin、Snipaste 行云流水地"截图 → 标注 → 钉在屏幕上对照着写代码",都会酸一下。把 Linux 桌面的截图类工具盘一遍,现状大致是这样:
| 工具 | 截图 | 标注 | 贴图钉屏 | 录屏 | OCR | 滚动长截图 |
|---|---|---|---|---|---|---|
| Flameshot | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Spectacle (KDE) | ✅ | ⚠️ | ❌ | ⚠️ | ❌ | ❌ |
| GNOME Screenshot | ✅ | ❌ | ❌ | ⚠️ | ❌ | ❌ |
| Shutter | ✅ | ✅ | ❌ | ❌ | ⚠️ | ❌ |
| Snipaste(Win/macOS) | ✅ | ✅ | ✅ | ❌ | ⚠️ | ❌ |
| PixPin(Win,闭源) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| SnapForge | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
每家都有自己的杀手锏:Flameshot 的标注体验、Snipaste 的贴图、PixPin 的全家桶。但它们要么功能缺位,要么压根不发布 Linux 版。SnapForge 要做的,就是把这三家的优点集成到一个工具里,为 Linux 桌面补上这块长期缺失的拼图。
二 功能介绍
先一张图看全貌,下面逐个展开:
- 📷 截图:区域 / 窗口 / 全屏 / 单屏 / 延时 / 上次区域重截 / 剪贴板导入
- ✏️ 就地标注:12 种工具,遮罩上直接画,不用先开编辑器
- 🎨 编辑器:裁剪旋转、美化外框(圆角/阴影/渐变背景)、水印、多格式导出
- 📌 贴图钉屏:截图钉在屏幕上当参考,Snipaste 招牌功能
- 🎬 录屏:MP4 / MKV / WebM / GIF,硬件编码探测,系统声音 + 麦克风
- 🎞 GIF 编辑器:帧时间线、删除重复帧、变速、裁剪
- 🧵 滚动长截图:你滚,我拼
- 🔍 OCR 取字:离线本地引擎 + 大模型 Markdown 双模式
- 🗂 截图库:SQLite 历史、全文搜索(连 OCR 文本都能搜)、托盘常驻、15 个全局快捷键、完整 CLI
1. 截图
- 区域截图有放大镜(像素级取色)、边缘吸附;鼠标悬停自动高亮整个窗口,单击即选中 。窗口截图基于 EWMH 枚举窗口,并用 XComposite 抓取未被遮挡的完整窗口内容,目标窗口被别的窗口压住了,照样抓到完整画面。多显示器 + HiDPI 混合缩放下的坐标错位,在架构层面统一到原生像素坐标系一次解决。
2. 标注:12 种工具,每个都记得自己的样式
- 矩形、椭圆、箭头、直线、画笔、荧光笔、文字、序号、马赛克、模糊、色块遮挡、聚光灯。工具条是两级结构:同类工具收进一个按钮,二级属性条只显示当前工具真正用得上的属性。每个工具独立记忆自己的样式,矩形用红色粗线、文字用白色细体,互不干扰(Flameshot 社区为"切工具后粗细被重置"开过多个工单,这里默认就是隔离的)。马赛克/模糊从原图采样,不会把已画的标注再打码。
3. 编辑器:裁剪之外还能"美化"
- 裁剪、旋转、翻转、等比缩放全部可撤销;美化外框 支持圆角 / 内边距 / 阴影 / 背景(渐变、毛玻璃、壁纸),6 套渐变预设;水印支持文字或图片、九宫格定位、平铺防搬运。导出 PNG / JPEG / WebP / BMP / TIFF。

4. 贴图钉屏:把截图"钉"在屏幕上
- 滚轮缩放、
Ctrl+滚轮调透明度、Shift+滚轮旋转、边缘拉伸手柄、鼠标穿透 (钉住的图不挡操作)、多张贴图自动吸附对齐、退出后自动恢复。对照着截图抄配置、写前端还原度的场景,用过就回不去了。

5. 录屏 + GIF 编辑器
-
ffmpeg 驱动,MP4 / MKV / WebM / GIF 四种格式,画质三档,VAAPI / NVENC 硬件编码自动探测 ,系统声音 + 麦克风混音。GIF 走高保真管线(crf 18 + yuv444p 保文字边缘),装了 gifski 自动切换逐帧调色板,体积只有全局调色板的 1/4,默认原始尺寸不缩放------录文档、录代码不糊字。
-
停止录制后自动进入 GIF 编辑器 :帧时间线多选删段、智能删除重复帧(观感不变、体积大降)、0.25×--4× 变速、逐帧延时、预览图上直接拖框裁剪,全部操作可撤销。

6. 滚动长截图
- 不盖全屏遮罩、不注入滚轮事件,目标窗口保持焦点,滚轮自然送达。匹配失败时插入看得见的橙色缺口带 ------宁可让你看见缺失,也不静默少一块。

7. OCR:离线引擎打底,大模型冲高
-
本地引擎(默认,完全离线):RapidOCR 的三个 ONNX 模型直接打进 wheel,共 16MB,装完即用,无需联网、无需系统依赖。
-
多模态大模型(可选) :不只是认字,而是看懂整张图,标题层级、有序/无序列表、表格、代码块、多栏阅读顺序,直接输出规范的 Markdown。本地引擎做的是"检测文本框 → 逐个认字",得到一堆没有结构的行;大模型看的是整张图,所以知道哪一行是标题、哪几行构成一个表格。支持 OpenAI 兼容协议 / Claude / Ollama(本地模型数据不出本机)。
-
隐私设计值得单独说一句 :
auto后端只会在本地引擎里挑 ,配了大模型 Key 它也不会偷偷把截图发出去,要用大模型必须显式选择。大模型失败(断网/Key 失效)时自动回退本地识别,保证"至少能出字"。
8. 截图库、托盘与 CLI
- SQLite 历史库,卡片网格,全文搜索连 OCR 识别出的文字都能搜 ("上次那张有发票号的截图"直接搜号码)。托盘常驻,15 个全局快捷键可自定义(XGrabKey 实现,不依赖 D-Bus)。完整 CLI 且所有命令支持
--json,脚本化无压力:
bash
snapforge capture --region 100,100,800,600 --json # 脚本直接抓指定区域
snapforge ocr --file report.png --markdown # 命令行 OCR 出 Markdown
snapforge scroll --region 0,0,900,420 -o long.png # CLI 长截图

三 几个技术决策
决策一:抓屏用 ctypes 直调 libX11,不走 Python 封装
- 抓屏是截图工具的热点路径。python-xlib、mss 这类封装方便,但多一层 Python 调用就多一层开销,还多一份依赖。SnapForge 用 ctypes 直接调 libX11:原生 X11 抓一张 2560×1440 约 32 ms ,比走 Python 层封装快数倍。代价是要自己处理 Xlib 的内存与错误语义,
XFree必须配对、XClassHint的字段必须是c_void_p而不能是c_char_p,否则直接munmap_chunk崩溃。这些坑都填过了。
决策二:前端为什么是 QML,而不是 Electron / Flutter
-
这不是偏好问题,受截图工具的硬约束限制:截图遮罩必须是 override-redirect 窗口 (绕过窗口管理器,否则 KWin 会按面板 strut 把全屏遮罩压扁,这正是很多工具"任务栏截不到"的成因),而且要逐像素透明。
-
我做过专门调研与实测:
-
Flutter :没有公开的窗口控制 API。官方 issue #66751 里团队成员原话 "Flutter doesn't currently control the window in any way, so making the application transparent is out of scope" ------这个 issue 挂了 5 年还是
c: proposal; -
Electron :连专门做 overlay 的第三方库 electron-overlay-window#48 都自己承认 "On Linux/X11 the overlay is currently a managed window";
-
QtQuick/QML :override-redirect 与逐像素透明实测都支持,而且与 Python 核心同进程、打包零增量(Electron 要多背 150~250MB,Flutter SDK 1.5GB)。
-
既然捕捉面(遮罩/贴图)无论如何必须留在 Qt,那主界面也用 QML,一套技术栈、一种观感。
决策三:长截图滚动
- 市面上的滚动长截图大多替用户合成滚轮事件。在 Windows 上这行得通,在 Linux 上撞到三堵墙:滚动事件语义随工具包而异、全屏遮罩会抢走目标窗口焦点、注入的滚轮未必送达(PixPin 3.5 专门为默认开启"鼠标穿透"发过更新,恰恰说明"事件必须送达目标窗口"是必要条件)。
- SnapForge 的答案是把三个问题一次消掉:不盖全屏遮罩 (只放一个摆在选区外的小控制面板)、不注入事件 (你自己滚)、观测式抓帧(盯着画面变化,静止了才抓)。算法链条大致是:
- 抓帧:画面静止 0.25s 才抓(20fps 巡检抽样)。快滚只是步进变大,每一帧都是干净的整数偏移帧,撕裂/亚像素/模糊帧从物理上不存在;
- 抓帧通道 :XShm 共享内存零拷贝,实测 0.41 ms/帧(对比
XGetImage的 1.91 ms,4.63×),自动降级; - 位移估计 :全范围归一化模板匹配 + 模板级联 (140→70→35px,快滚大步进自动换小模板)+ 多峰候选残差仲裁(周期性内容的同相位假峰骗不过它);
- 固定元素:吸顶/吸底导航栏自动检测,从拼接中裁掉、末尾还原一次------长图里导航栏只出现一次;
- 抗错与回滚:每次拼接前与画布做 BGR 逐像素一致性验证;用户往回滚时画布游标回退,不拼重。
效果如何不是我说了算:合成真值页上 12 个场景(慢滚/快滚/混合 45 帧/周期页/回滚/吸顶/吸底/噪声容差)全部与真值逐像素一致 (平均差 0.000),端到端测试在 tests/test_scroll_engine.py,CI 用虚拟显示跑真实窗口 + 真实 XTest 滚轮。
附:零 sudo 与优雅降级
- 目标用户是桌面用户,不该为装一个截图工具去动系统包管理器。所有核心能力通过 ctypes + 可选 pip 依赖实现:没装 ffmpeg,录屏功能自动隐藏并提示;没装 OCR 引擎,给出安装命令。缺什么降级什么,主流程永远可用。
四 工程质量
- 673 个自动化测试全部通过(1 个跳过),默认 offscreen 运行,无需显示器;
- 83 对前景/背景色的 WCAG 对比度在测试里自算,改错一个色值测试就会红(主按钮白字对比度 3.65 → 4.92,侧栏悬停 4.41 → 12.10);
- 设计令牌构建期确定性生成,运行期零文件 IO;
- 遮罩局部重绘优化:整屏 7.43 ms → 2.52 ms(3.0×),放大镜跟随不卡顿;
- 配置文件原子写入,损坏自动备份回落默认值。
五、安装与 5 分钟上手
- 推荐:用户级安装脚本(零 sudo)
bash
git clone https://gitee.com/kill-life/snapforge.git
cd snapforge
bash packaging/install.sh
- 装到
~/.local,含桌面菜单项与图标。也有 Debian 包、AppImage、pip wheel 三种分发形式(dist/下自行构建),以及可选增强项:ffmpeg(录屏)、numpy + opencv(长截图加速)、rapidocr(离线 OCR),缺了只影响对应功能,不影响主流程。
上手只需 30 秒:
Ctrl+Alt+A→ 屏幕冻结,拖拽选区(悬停自动高亮窗口);- 工具条上直接标注,
Ctrl+Z后悔; Enter复制 /Ctrl+T贴到屏幕 /Ctrl+E进编辑器 /Ctrl+O提取文字;Ctrl+Alt+L滚动长截图,Ctrl+Alt+S区域录屏,Ctrl+Alt+H开截图库。
环境要求:Linux + X11 会话(Wayland 下能力降级),Python 3.10+,PySide6 ≥ 6.5。
六 项目地址
- Gitee 仓库 :https://gitee.com/kill-life/snapforge 。许可证:GPL-3.0-or-later,可自由使用、修改、分发。如果这个项目恰好补上了你工作流里缺的那块拼图,去点个 Star ⭐ 就是最大的支持;遇到 bug 或缺功能,欢迎提 Issue;想一起写,PR 随时欢迎。