AI 项目

LensTrans · 原生屏幕翻译

不弹第二个窗口,在原位置识别、翻译并覆盖屏幕文字。

LensTrans · 原生屏幕翻译 项目封面或真实界面
C++主要技术栈
0GitHub Stars
1Forks
121索引文件
MIT License许可标记
2026-08-31最近更新

01 / PROJECT OVERVIEW

项目研究解读

LensTrans 使用 Windows Graphics Capture 获取选区像素,通过系统 OCR 和本地 Qwen 模型或用户自配兼容端点完成翻译,再用原生分层窗口覆盖原文。没有 Electron、Tauri 或 WebView 壳,也不注入其他进程。多选区状态机、帧差分与 WCAG 对比度处理体现了桌面工具的细节。

02 / CORE CAPABILITIES

值得关注的能力

  1. 01

    原生 Windows 低依赖实现与点击穿透选区

  2. 02

    系统 OCR + 本地 Qwen 或用户自带兼容 API

  3. 03

    沉浸覆盖、贴纸与对比模式

  4. 04

    多选区独立状态和托盘快捷操作

03 / ENGINEERING

工程与仓库结构

仓库以 C++ 为主要实现语言,研究快照包含 121 个文件、14 个主要顶层入口。已提供 README 作为使用与能力说明。 项目最近更新时间为 2026-08-31,许可标记为 MIT License。

01CMakeLists.txt

项目文件与实现资料

02LICENSE

项目文件与实现资料

03README.ja.md

项目文件与实现资料

04README.ko.md

项目文件与实现资料

05README.md

项目文件与实现资料

06README.zh-CN.md

项目文件与实现资料

04 / USE CASES

适合用在哪里

  • 游戏与软件实时翻译
  • 本地模型桌面应用
  • 隐私敏感屏幕翻译

05 / QUICK START

从仓库开始

以下命令摘自项目 README 或根据仓库地址生成。请先阅读源仓库的安装要求、许可和脚本,再在自己的环境中运行。

git clone https://github.com/suifei/LensTrans.git
cd LensTrans

06 / REPOSITORY MAP

目录证据导览

这里列出快照中的前 121 个索引文件中的代表路径,帮助你快速定位源码、文档、测试与资源。

  • .github/workflows/ci.yml
  • .gitignore
  • CMakeLists.txt
  • LICENSE
  • README.ja.md
  • README.ko.md
  • README.md
  • README.zh-CN.md
  • core/include/lenstrans/autostart.hpp
  • core/include/lenstrans/batch_translation.hpp
  • core/include/lenstrans/boxes.hpp
  • core/include/lenstrans/cache.hpp
  • core/include/lenstrans/cloud_http.hpp
  • core/include/lenstrans/dispatch.hpp
  • core/include/lenstrans/engine.hpp
  • core/include/lenstrans/frame_diff.hpp
  • core/include/lenstrans/geom.hpp
  • core/include/lenstrans/model_meta.hpp
  • core/include/lenstrans/ocr_block.hpp
  • core/include/lenstrans/paths.hpp
  • core/include/lenstrans/pipeline.hpp
  • core/include/lenstrans/present.hpp
  • core/include/lenstrans/present_layout.hpp
  • core/include/lenstrans/router.hpp
  • core/include/lenstrans/settings.hpp
  • core/include/lenstrans/sha1.hpp
  • core/include/lenstrans/text.hpp
  • core/include/lenstrans/translation.hpp
  • core/include/lenstrans/ui_state.hpp
  • core/src/engine_cloud.cpp
  • core/src/engine_fake.cpp
  • core/src/engine_local.cpp
  • core/src/pipeline.cpp
  • docs/M0-model-eval.md
  • docs/M0-poc-structure.md
  • docs/goal-verify-latest.md
  • docs/installer.md
  • docs/mac-dev-status.md
  • mac/App.swift
  • mac/Capture.swift
  • mac/CoreBridge.swift
  • mac/E2e.swift
  • mac/Engine.swift
  • mac/Info.plist
  • mac/Logic/PureLogic.swift
  • mac/Native/CoreBridge.cpp
  • mac/Native/LlamaBridge.cpp
  • mac/Native/include/LenstransCoreBridge.h
  • mac/Native/include/LlamaBridge.h
  • mac/Ocr.swift
  • mac/Onboarding.swift
  • mac/OverlayPanel.swift
  • mac/Package.swift
  • mac/Pipeline.swift
  • mac/Present.swift
  • mac/README.md
  • mac/Secrets.swift
  • mac/Settings.swift
  • mac/Tests/LogicTests.swift
  • mac/Tray.swift
  • mac/UNIMPLEMENTED.md
  • models/README.md
  • tests/README.md
  • tests/e2e_target.cpp
  • tests/test_core.cpp
  • tests/test_hotkey.cpp
  • tests/test_llama.cpp
  • tests/wgc_probe.cpp
  • third_party/README.md
  • tools/eval/click-through.ps1
  • tools/eval/fixtures/mac-desktop.txt
  • tools/eval/flores50.ps1
  • tools/eval/goal-verify.py
  • tools/eval/hotkey-ctrl-e.ps1
  • tools/eval/hotkey-probe.ps1
  • tools/eval/idle-5min.ps1
  • tools/eval/idle-after-sleep.ps1
  • tools/eval/idle-wake.ps1
  • tools/eval/licenses/Qwen2.5-0.5B-Instruct-LICENSE.txt
  • tools/eval/mac-desktop-e2e.sh
  • tools/eval/mac-e2e.sh
  • tools/eval/mac-logic-verify.py
  • tools/eval/mac-ocr-smoke.swift
  • tools/eval/mac-runtime-desktop-e2e.sh
  • tools/eval/mac-runtime-screenshot-check.swift
  • tools/eval/mac-smoke.sh
  • tools/eval/mvp-auto-checklist.cn.md
  • tools/eval/mvp-auto.ps1
  • tools/eval/overlay-contrast-e2e.ps1
  • tools/eval/overlay-e2e.ps1

07 / SOURCE NOTES

README 原文摘录

保留原始说明便于复核。中文研究结论以当前快照为依据,后续变化请以 GitHub 仓库为准。

LensTrans

English · 简体中文 · 日本語 · 한국어

[[图片] License: MIT](LICENSE) [[图片] Platform](#platform) [[图片] macOS](#platform) [[图片] C++](CMakeLists.txt) [[图片] UI](#what-it-is) [[图片] Engine](#features)

A native Windows live screen translator. Draw a layered, click-through box over any window; LensTrans captures pixels with Windows Graphics Capture (WGC), reads them with system OCR, translates locally (Qwen2.5-1.5B) or through a user-supplied OpenAI-compatible endpoint, and covers the source with immersive fill or a sticker. No Electron, no Tauri, no WebView shell.

What it is

On-screen text is pixels, not a DOM. LensTrans does not inject hooks or read another process's private memory. It captures only the pixels inside its own boxes, OCRs them, and paints the translation on the same rectangle.

  ┌─ other app ──────────────────────────────────────────┐
  │  File   Edit   View                                  │
  │                                                      │
  │    ┌─ LensTrans box (Watching, click-through) ────┐  │
  │    │                                              │  │
  │    │   Settings          →    设置                │  │
  │    │   Cancel            →    取消                │  │
  │    │   Please wait…      →    请稍等              │  │
  │    │                                              │  │
  │    └──────────────────────────────────────────────┘  │
  └──────────────────────────────────────────────────────┘
         tray  ·  right click start/stop  ·  double-click display mode

The box is a WS_POPUP layered HWND (WS_EX_LAYERED | TOPMOST | TOOLWINDOW) with no taskbar entry. In Watching it sets WS_EX_TRANSPARENT so clicks reach the window underneath. In Editing it clears passthrough; you drag the title bar and resize with eight 12 px handles. Multiple boxes are supported, each with its own state machine:

Hidden → Editing → Watching ⇄ Translating
              Paused ← any state (hotkey; capture stops, overlay keeps the last frame)

Presentation is two honest modes: fill the glyph rectangle with the sampled background majority color and write the translation (immersive), or cover the source with an opaque sticker. Semi-transparent ghost text on top of the original is a bug. Contrast mode is a sticker plus the source at 60% size underneath — not stacked glyphs. If the glyph color fails WCAG AA 4.5:1 against the fill, it is inverted against that fill.

There are no product screenshots in this repository. The diagram above is structural so we do not hang a fake image URL.

Most screen translators grab a bitmap and open a separate result window. LensTrans stays on the region: pin the box, follow the pixels, cover the source.

Typical popup toolLensTrans
WhereA second window, away from the sourceA frame pinned to the pixels you drew
WhenOne-shot hotkeyUpdates as the box contents change
OfflineOften needs the networkDefault local Qwen2.5-1.5B
How it looksSource and translation both visibleImmersive fill or a sticker covering the source

Features

AreaWhat ships on Windows
OverlayMulti-box, topmost, edit / click-through, full tray menu
CaptureWGC (window session / monitor crop); GDI BitBlt / PrintWindow fallback
Change detect1/4 downsample + 8×8 SSD; idle sleep after ~2 s of no DIFF so CPU does not spin
OCRWindows.Media.OCR on an STA thread → unified OcrBlock (text, bbox, sampled color)
StabilizeTwo matching frames (bbox+text) plus 300 ms debounce before commit
PresentImmersive replace / sticker (~92% opaque) / sticker + contrast. Pure transparent overlay text is forbidden
Local engineQwen2.5-1.5B Instruct Q4_K_M via llama.cpp b10688 (in-process link or llama-cli)
Cloud engineWinHTTP POST {base}/chat/completions. Base URL / model / API key all empty; empty disables cloud
SecretsDPAPI on disk; settings serialization must not contain api_key (unit-tested)
UI5-tab settings, 3-step first-run (does not start WGC during onboarding)
MouseRight click start/stop · left double-click overlay/bilingual · interior drag move · edge drag resize

Quick start

Requires Windows 10 21H2+ or Windows 11, x64, Visual Studio 2022, and a Windows 10/11 SDK.

  1. Clone this repo. Fetch llama.cpp b10688 per Build, and the GGUF per models/README.md.
  2. Build lenstrans_overlay and run build\Release\lenstrans_overlay.exe.
  3. Allow screen recording if Windows asks. Draw a box over UI text, then right-click inside it to start translating.
  4. Optional cloud: open Settings and paste your Base URL, model id, and key. Nothing is pre-filled.

A scripted zip (not Inno / NSIS / a store-signed package) is documented in docs/installer.md. There is no production-signed MSIX in this tree.

Build

cmake -S . -B build -G "Visual Studio 17 2022" -A x64
cmake --build build --config Release --target lenstrans_test lenstrans_overlay
.\build\Release\lenstrans_test.exe
.\build\Release\lenstrans_overlay.exe

In-process llama.cpp (required for the local engine inside the overlay):

git clone --depth 1 --branch b10688 https://github.com/ggml-org/llama.cpp.git third_party\llama.cpp

Build that tree Release x64, then reconfigure LensTrans. CMake turns on LENSTRANS_WITH_LLAMA=ON when it finds third_party/llama.cpp/build/src/Release/llama.lib. Pin details: third_party/README.md.

tag:    b10688
commit: c589f0ed10c643678c4707dd160c21ac7633ebc0
remote: https://github.com/ggml-org/llama.cpp.git

Ninja + MSVC also works. Do not add vcpkg, and do not replace the UI with a cross-platform shell.

Tests
TargetRole
lenstrans_testCore: cache, router, present, settings; injected-frame pipeline (no WGC)
lenstrans_test_hotkeyDefault four RegisterHotKey bindings
lenstrans_test_llamaOptional; needs the GGUF (--quality-10, --quality-30, --flores50)
lenstrans_e2e_targetFixture HWND (white HELLO Settings) for overlay scripts
lenstrans_wgc_probeWGC permission + OCR smoke

PowerShell helpers live in tools/eval/ (they write reports under tools/eval/out/, gitignored). See tests/README.md.

Packaging
powershell -File tools\pack\pack-windows.ps1
powershell -File tools\pack\pack-windows.ps1 -Offline
powershell -File tools\pack\install-windows.ps1

The base pack does not include the GGUF. The offline pack is base + models/*.gguf. The script fails if a size cap is exceeded. Install lands in %LOCALAPPDATA%\LensTrans\app by default; it does not write keys, and it does not copy a GGUF unless you built the offline pack.

Size and memory (product budgets)

These are the numbers the project is held to — not marketing claims. Acceptance uses Working Set (WS), not Private Bytes reported as “peak memory”.

BudgetLimitNotes
Base pack≤ 30 MBOverlay + llama/ggml DLLs; no GGUF
Offline pack≤ 520 MBBase + official Q4_K_M (~491 MB) + installer headroom
Inference peakWS ≤ 550 MBIncludes GGUF mmap
Local idle resident≤ 600 MB (typical ~520 MB)After the Q4_K_M lock-in
Main process, no model≤ 80 MBOverlay without weights
Cloud resident≤ 120 MBCloud engine only
First token (≤100 chars, warm, greedy)≤ 800 msTarget on a modern CPU; not a published SLO

A local measurement of the scripted base tree was about 4.5 MB uncompressed / 1.8 MB zip, offline total about 496 MB — under the caps. That is one machine’s artifact; toolchains change the number, the budget does not.

Default weights: qwen2.5-1.5b-instruct-q4_k_m.gguf, 1117320736 bytes, SHA256 6a1a2eb6d15622bf3c96857206351ba97e1af16c30d7a74ee38970e434e9407e. Download steps: models/README.md. It is the default because Apache-2.0 allows redistribution including EU/UK/KR, not because 0.5B already matches a dedicated MT model.

Privacy

  • Default path is local. Pixels stay on the machine; OCR is Windows.Media.OCR; translation is llama.cpp + the GGUF you downloaded.
  • No baked-in cloud gateway. Source does not ship a default Base URL, model name, or API key. Cloud is off until all three fields are set, plus a “test connection” action.
  • The key is stored with DPAPI, not in the settings file. Settings serialization is tested to omit api_key.
  • Capture uses system APIs (WGC / GDI). No injection into other processes, no reading foreign private memory.
  • Git blocks *.gguf, *.pfx, dist/*.cer, the whole third_party/llama.cpp tree, build/, .cache/, .env, and secret-like files. Do not push them.

Platform

Status
Windows 10/11 x64Native C++20 + Win32. This is the product.
macOSSwift AppKit interface stubs under mac/ — see mac/UNIMPLEMENTED.md. ScreenCaptureKit / Vision / Metal are not wired. No Xcode project in this repo. Windows is finished first.

Limitations (read this)

  • The default local model is 0.5B. Short UI strings often come out usable; long sentences and idioms frequently go literal or scramble. That is a capacity limit, not “tune the prompt and it becomes dedicated MT”. Formal FLORES / COMET acceptance is still open.
  • Production / Store code signing is not in this repository. The test-sign path in tools/pack/pack-msix.ps1 stays on the local machine; certificates are not committed.
  • macOS is not a shipping build.
  • Hunyuan / HY-MT community licenses exclude EU/UK/KR. They are not the default engine and do not go into the installer.

Layout

core/           shared C++: OcrBlock, frame diff, local/cloud engines, present, pipeline, settings
win/            overlay, WGC capture, WinRT OCR, tray/settings, DPAPI
mac/            Swift stubs (not compiled on Windows)
tests/          unit + e2e fixture + WGC probe
tools/pack/     zip / MSIX scripts
tools/eval/     probes and quality scripts (out/ gitignored)
docs/           installer + M0 notes
models/         GGUF goes here (weights gitignored)
third_party/    clone llama.cpp b10688 here (tree gitignored)

Module map and hard constraints: docs/M0-poc-structure.md. Model license and eval plan: docs/M0-model-eval.md.

License

MIT © 2026 flynn (suifei).

The optional Qwen2.5-1.5B GGUF is Apache-2.0 (Alibaba Cloud). You must keep that license with any redistributed weights. Review copy: tools/eval/licenses/. llama.cpp has its own license; clone it from upstream.

Contributing

Issues and PRs that match the native-Windows design are welcome.

  • Keep the UI on Win32 / AppKit. Do not introduce Electron, Tauri, Qt, Flutter, or WebView as the shell.
  • Do not add a default cloud host, sample API key, or gateway constant.
  • Do not commit *.gguf, *.pfx, dist/*.cer, third_party/llama.cpp, build/, .cache/, or secrets.
  • Present path: if the source is still visible under translucent translated glyphs, that is a regression.
  • Run lenstrans_test before sending a core change.

Do not bump the llama.cpp commit mid-eval. The pin is in third_party/README.md.