译镜:基于 Rust 与 llama.cpp 的 Windows 屏幕英文翻译项目

按键触发的离线屏幕英文翻译浮层:截图 → 本地 OCR → 本地大模型 → 贴原文|作者个人站:https://softwarescience.top/projects/translens

分支1Tags1
文件最后提交记录最后更新时间
1 个月前
1 个月前
1 个月前
1 个月前
1 个月前
1 个月前
1 个月前
1 个月前
20 天前

译镜 TransLens

作者个人站:https://softwarescience.top/ · 本项目主页:https://softwarescience.top/projects/translens(版本、截图与下载都在那儿)

按键触发的屏幕英文翻译工具:按下快捷键 → 截屏 → 识别屏幕上的英文 → 用离线模型翻译成中文 → 把译文以透明、点击穿透的浮层画在原文附近,字体颜色按背景自动取黑/白。

不弹窗、不抢焦点,翻译结果直接叠在屏幕内容上,用户可以继续操作下方的界面。

献给娜娜

功能

功能 实现
全局快捷键 RegisterHotKey,默认 Ctrl+Alt+T 翻译、Ctrl+Alt+H 隐藏(可在设置里改)
屏幕截取 GDI BitBlt(主显示器,物理像素)
OCR 系统自带 Windows.Media.Ocr(en-US),零模型、零额外体积;1080p 约 60–90 ms
翻译 离线 GGUF 模型 Hy-MT2-1.8B-Q4_K_M + 自建 llama.cpp 引擎(进程内 FFI,无子进程)
叠加显示 分层窗口 + UpdateLayeredWindow(逐像素 alpha)+ cosmic-text 排版
自适应字色 取原文区域背景亮度算 WCAG 对比度 → 黑字/白字;对比度不足时加半透明衬底
点击穿透 WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE
位置 优先画在原文下方,其次上方、右侧,都放不下才覆盖原文;不越出屏幕
托盘 左键翻译一次,右键菜单:翻译一次 / 显示·隐藏译文 / 设置… / 退出
设置界面 原生 Win32 设置窗口(快捷键、模型路径、引擎目录、目标语言、字号、上下文、线程)
配置 可执行文件旁的 config.toml,首次运行自动生成
诊断 --selftest(截屏+OCR)、--engine-check(加载引擎翻固定例句)、--once(跑完整流水线并显示浮层)、translens.log 运行日志

为什么是这套组合

在本机(Ryzen 9 9900X / 32 GB+ / RTX 3060)实测:

方案 磁盘 峰值内存 显存 生成速度 结论
Hy-MT2-1.8B-Q4_K_M + llama.cpp(本项目) 1.06 GB ~1.9 GB 0 ~34 tok/s 质量、速度、可维护性最平衡
Hy-MT2-1.8B-1.25Bit + 未合并的 STQ 内核 440 MB 0.53 GB 0 ~8 tok/s 需自维护 llama.cpp 分支且要改模型文件头,不采用
1.25Bit 纯 Rust 解码 440 MB 1.45 GB 0 ~17 tok/s 需自维护 STQ 解码器补丁,不采用
1.25Bit/2Bit GGUF + 官方 llama.cpp — — — 无法加载 类型 id 与上游冲突

盲评(42 句 + 31 句数字/实体密集样本,双评委、A/B 顺序对调)显示 1.25Bit 与 Q4_K_M 质量差异低于评测分辨率,所以按"速度/内存/磁盘"选型,而不是按"质量"选型。

初始化(必读)

仓库里只有代码。模型权重(1.06 GB)与 llama.cpp 引擎 DLL(约 4 MB)体积大、且可由脚本重建,所以被 .gitignore 排除,需要你在本地生成一次:

目录 内容 体积 怎么来
models/ Hy-MT2-1.8B-Q4_K_M.gguf 1.06 GB tools/fetch-model.ps1(从 ModelScope 下载并校验大小)
engine/ llama.dll、ggml.dll、ggml-base.dll、ggml-cpu.dll 约 4.2 MB tools/build-engine.ps1(CMake + MSVC 构建钉住的 llama.cpp revision)
dist/ 便携版(exe + engine + models + config) 约 1.07 GB 可选,见下方"打包"
.build/ llama.cpp 源码 + cmake 工具 + 编译中间产物 约 400 MB build-engine.ps1 的缓存,可随时删除

前置条件

  • Windows 10/11 x64
  • Rust 1.82+(rustup;edition 2021)
  • VS 2022 的 "使用 C++ 的桌面开发" 工作负载(即 MSVC 工具链)——只有构建引擎 DLL 需要;构建本程序本身不需要
  • 不需要 CUDA / Vulkan 工具包:引擎默认按 CPU 构建,显存占用为 0
  • 需要联网一次:下载模型(ModelScope)与 llama.cpp 源码(github codeload)+ cmake(若系统没有 cmake,脚本会从 cmake.org 下到 .build/cmake/)

三步跑起来

# 1) 下载模型(约 1.06 GB,带断点续传与大小校验)
pwsh -File tools/fetch-model.ps1
#    换量化档位:pwsh -File tools/fetch-model.ps1 -File Hy-MT2-1.8B-Q6_K.gguf

# 2) 构建推理引擎到 engine/(CPU 版;首次约 1–3 分钟,之后走 .build 缓存)
pwsh -File tools/build-engine.ps1
#    有 NVIDIA 显卡且装了 CUDA 工具包时:pwsh -File tools/build-engine.ps1 -Cuda

# 3) 编译并运行
cargo build --release
.\target\release\translens.exe --engine-check   # 自检:加载引擎并翻译 4 句固定英文
.\target\release\translens.exe                  # 常驻:托盘图标 + 全局快捷键

注意:target\release\translens.exe 会去自己所在目录找 models/ 与 engine/,所以直接跑它需要先把这两样放到 target\release\ 下,或者用下面的 dist/ 布局。--engine-check / --selftest / --once 会明确告诉你缺哪个文件。

打包便携版(zip 分发,免安装)

cargo build --release
mkdir dist\engine, dist\models
copy target\release\translens.exe dist\
copy engine\*.dll dist\engine\
copy models\*.gguf dist\models\

dist\ 里 translens.exe + engine\ + models\ 即完整程序(约 1.07 GB),首次运行自动生成 config.toml。

启动后托盘出现图标:按 Ctrl+Alt+T 翻译当前屏幕,Ctrl+Alt+H 隐藏译文;右键托盘图标可打开设置或退出。

配置(config.toml,与 exe 同目录)

键 默认值 说明
hotkey "Ctrl+Alt+T" 翻译快捷键;支持 F1–F24、A–Z、0–9、Space/Esc/Tab/方向键等,前缀 Ctrl+ Alt+ Shift+ Win+
hotkey_hide "Ctrl+Alt+H" 隐藏译文;留空则不注册
target_lang "Chinese" 提示词里的目标语言(模型支持 33 种语言,写英文全名)
model_path "models/Hy-MT2-1.8B-Q4_K_M.gguf" 相对路径按 exe 所在目录解析
engine_dir "engine" 存放 llama.dll/ggml*.dll 的目录
n_ctx 2048 上下文长度。别调大:模型自带 262144,默认值会分配十几 GB 的 KV cache
n_threads 0 0 = 自动(逻辑核数的一半,约等于物理核)
max_tokens 256 单条译文的最大生成 token 数
font_family "Microsoft YaHei UI" 浮层字体(需含中文字形)
font_size / min_font_size 22 / 12 起始字号与自动缩小下限

快捷键也可以写成单键(如 F1),但单键会被前台程序(尤其是游戏)抢走,默认用组合键就是为了避免这一点。

工作原理

快捷键 ──► 截屏(BitBlt) ──► OCR(Windows.Media.Ocr)
                               │  按行合并成"文本块"(换行的整句、双行字幕会并成一块,翻译上下文更好)
                               ▼
                        引擎(进程内 llama.cpp FFI, 贪婪解码, 上下文复用)
                               │  每翻好一块就立刻画出来(渐进显示,不用等整屏翻完)
                               ▼
                 浮层(取背景亮度 → 定字色/衬底 → 排版 → UpdateLayeredWindow)
  • 引擎在首次翻译时才加载(启动是瞬时的),之后常驻;每次请求复用同一个上下文,KV 每次清空。
  • 没有英文文本的屏幕(纯中文/图片)不会弹窗,只会在托盘提示里说明。
  • 只允许一个实例:重复启动会提示并退出。

诊断

.\translens.exe --selftest      # 截屏 + OCR,打印识别到的每一行及坐标,不加载模型
.\translens.exe --engine-check  # 加载引擎并翻译 4 句固定英文(装了没装好,一眼就能看出来)
.\translens.exe --once          # 完整跑一次:截屏 → OCR → 翻译 → 显示浮层,20 秒后退出
.\translens.exe --settings      # 直接打开设置窗口

运行日志写在 exe 同目录的 translens.log(可用环境变量 TRANSLENS_LOG 指定其它路径),每次翻译都会记录每块的位置、字号、背景亮度、选中的字色、对比度与衬底,便于排查"为什么这里显示黑字/白字"。

验证

verify/ 保留了开发时真正用过的端到端验证脚本:注入真实按键/鼠标、截真实屏幕、枚举窗口 style/exstyle、在浮层覆盖处点击验证穿透、打开设置改配置并检查落盘与热应用;verify/evidence/ 是三张证据截图(浮层的自适应字色、托盘菜单、设置窗口)。跑法与注意事项见 verify/README.md。

这些脚本会移动真实光标并抢前台,机器有人用时不要跑。

已知限制

  • 仅主显示器:截屏与浮层都按主屏尺寸处理,多屏/负坐标屏暂不支持。
  • BitBlt 抓不到的内容:受保护视频(DRM)与部分独占全屏 3D 画面可能截成黑帧;窗口化或无边框窗口化游戏正常。
  • 只做英译中:OCR 使用 en-US 识别器;target_lang 可以改,但源语言固定按英文识别。
  • 文本块上限:单次最多翻译 60 块,避免整屏都是文字时长时间占用。
  • 许可证提醒:模型为 Apache-2.0(Hy-MT2),llama.cpp 为 MIT,本项目代码 MIT。

版本与发版

每次代码改动落地后先判断:这次要不要升版本? 要升就一路做完——绝不停在「代码改了、版本号没动、 标签没打」;判断不用升的,在交付说明里写明理由。

  • 版本号唯一来源:Cargo.toml 的 [package].version(单 crate)。
  • 标签与版本同号,前缀跟随本仓库既有习惯:v 前缀(如 v0.1.0);一个仓库里不得混用两种写法。
  • 要升的完整序列(缺一步都算没做完):
    1. 在版本号唯一来源处改号;仓库里还有别处重复写了版本(前端 package.json、tauri.conf.json、 README 里的版本引用)的,同一提交里一起改;
    2. 重新构建并验证:cargo build --release,并按 README「初始化三步」确认引擎 DLL 与模型路径可用(--selftest / --engine-check / --once);
    3. 提交、git push 当前分支;
    4. 打附注标签(git tag -a <标签> -m "译镜 TransLens <版本号>")并 git push origin <标签>;
    5. 对外发布的版本要在本仓库留下可查的记录:在 README 的版本历史 / CHANGELOG(没有就新建一节) 写清这一版改了什么、为什么改;并确认分发物(安装包 / 便携包 / 镜像等)的文件名与版本号一致。
  • 判断口径:用户可见的行为 / 界面 / 协议 / 只读数据格式变了,或修了用户能踩到的缺陷 → 升 (补丁位修缺陷,小版本位加能力);纯内部重构、注释、测试、脚本、文档 → 不升。
  • 交付说明里写清两件事:这次要不要升版本(要升就写升到哪个号),以及版本号 / 标签 / 推送 三件事是否都做完;不升就写「不升 + 理由」,不许留白。

关于

这个项目由 CodeLife Leon 独立开发与维护。更多项目、各项目发版信息、赞赏与联系方式都在个人站:

问题反馈与需求建议:优先在仓库提 Issue,也可以邮件 virgil_lgp@163.com。

项目介绍

按键触发的离线屏幕英文翻译浮层:截图 → 本地 OCR → 本地大模型 → 贴原文|作者个人站:https://softwarescience.top/projects/translens

https://softwarescience.top/projects/translens定制我的领域