# VibeOCR **Repository Path**: felixjii/VibeOCR ## Basic Information - **Project Name**: VibeOCR - **Description**: 本仓库已停止开发并迁移到四个独立仓库。 普通用户请前往 VibeOCR Classic Releases; WinUI 预览版位于 VibeOCR Next; Runtime 实现与公共协议分别位于 vibeocr-backend 和 vibeocr-protocol。 旧版应用不会自动跨仓升级,请手动下载新仓发布包。完整映射见 MIGRATION.md。 - **Primary Language**: Python - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 10 - **Forks**: 3 - **Created**: 2026-06-28 - **Last Updated**: 2026-07-30 ## Categories & Tags **Categories**: cv **Tags**: None ## README > [!IMPORTANT] > **本仓库已停止开发并迁移到四个独立仓库。** > 普通用户请前往 [VibeOCR Classic Releases](https://github.com/FelixJI/vibeocr-classic/releases); > WinUI 预览版位于 [VibeOCR Next](https://github.com/FelixJI/vibeocr-next); > Runtime 实现与公共协议分别位于 [vibeocr-backend](https://github.com/FelixJI/vibeocr-backend) > 和 [vibeocr-protocol](https://github.com/FelixJI/vibeocr-protocol)。 > 旧版应用**不会自动跨仓升级**,请手动下载新仓发布包。完整映射见 [MIGRATION.md](MIGRATION.md)。

VibeOCR

VibeOCR

面向 Windows 的一站式 OCR 与文档处理桌面应用 —— 截图识别、批量识别、PDF 文字层、文档解析、二维码,一站式搞定。

版本 License Python Platform

--- ## 简介 VibeOCR 是一款基于 [PySide6](https://www.qt.io/) + [PaddlePaddle](https://www.paddlepaddle.org.cn/) 的本地化 OCR 桌面应用。 所有识别都在本地完成,**无需联网、不上传任何文件**,适合处理隐私敏感的文档与截图。 支持文字识别、表格识别、公式识别、文档解析(MinerU / PaddleOCR-VL)等多条推理流水线, 并对 GPU(CUDA)与 CPU 双后端做了适配。 ## 🚦 开发状态与两条路线 VibeOCR 目前存在**两条并行的桌面产品路线**,共用同一份 Python 后端(OCR / PDF / 二维码 / 设置), 但前端实现、成熟度和可用性差异巨大。**请先了解现状再选择使用哪一条。** ### 路线一:PySide6 Classic —— ✅ 当前主力,推荐使用 - 基于 [PySide6](https://www.qt.io/) 的成熟 Qt 桌面 UI,是当前发布与日常使用的**默认产品**。 - 功能完整:截图识别、单文件 / 批量识别、PDF 处理与文字层写入、二维码生成与解码、多引擎流水线、设置、托盘、程序内更新等均已落地并通过回归。 - Releases 页的 `VibeOCR-Classic-vX.Y.Z-win64.zip` 即此路线。 - **绝大多数用户应当下载并使用 Classic 版本。** ### 路线二:WinUI Next —— ⚠️ 早期开发阶段,目前基本不可用 - 基于 [WinUI 3](https://learn.microsoft.com/windows/apps/winui/winui3/) 的下一代 UI,目标是长期取代 Classic。 - **当前状态:早期开发中,不可用于日常使用。** 大多数功能页面仍是占位状态或尚未接通后端: - 单次识别页:开发启动时存在**后端不自动拉起**的问题(已修,但尚未在任何已发布版本中体现),区域截图框选刚具备雏形。 - 批量识别 / PDF / 二维码 / 设置等页面:ViewModel 与协议方法已搭建并有单元测试,但实际 UI 交互、文件预览、页面操作、缩略图渲染、导出等**尚未完成对等**。 - 真实 WinUI 运行级验证仍需 .NET 10.0.302 SDK 环境;多数改动目前只通过静态 / 单元测试覆盖。 - Releases 页的 `VibeOCR-Next-vX.Y.Z-win64.zip` **默认不随 tag 发版**——发版流水线默认只产 Classic;需要时由维护者手动 `workflow_dispatch` 选 `winui`/`all` 才会构建,**仅为开发预览,不建议普通用户使用**。 - 适用人群:WinUI / .NET 开发者、愿意参与早期建设或做技术评估的贡献者。 > 两套前端通过 Windows 命名 Mutex **互斥运行**,不能同时启动;架构细节见下方「双前端独占架构」一节。 ## 功能特性 ### 📷 识别能力 - **截图识别** —— 全局快捷键唤起,框选屏幕区域即可识别;内置可标注的内联编辑器(马赛克 / 模糊 / 矩形 / 椭圆 / 填充色等) - **单文件识别** —— 支持打开本地图片(PNG/JPG 等)与 PDF 文件 - **批量识别** —— 拖入多文件批量处理,进度可见 - **多引擎流水线** —— 文字识别(PP-OCRv5 / PP-V3)、表格识别、公式识别、文档解析(MinerU)、多模态文档解析(PaddleOCR-VL) ### 📄 PDF 文档处理 - 页面级操作:旋转 / 删除 / 插入 / 拖拽重排 - **文字层写入**:对无文字层的扫描页执行 OCR 并内嵌可搜索、可复制的中文文字层(子集化 CJK 字体内嵌,跨阅读器兼容) - 文字层删除、逐页状态可视化、独立预览窗口(支持缩放与拖拽平移) - 按 GPU 显存 / 内存自适应的动态批处理大小 ### 🔲 二维码 - 生成:QR 码(含 logo 嵌入、文字标签、颜色反转、SVG 导出)与多种条形码(Code128 / Code39 / EAN-13 等) - 解码:粘贴 / 拖入 / 选择图片识别 QR 码与条形码 ### 🛠 工程化 - **推理后端自适应** —— 首次启动自动检测 GPU/CPU,可在设置页切换后端 - **独占 WorkerHost 隔离** —— 每个前端只拥有一个通过随机 Named Pipe + token 连接的 WorkerHost;OCR、PDF、二维码和业务设置均在该进程内执行,二进制大载荷使用共享内存 - **流水线缓存** —— 按显存分层的重型流水线缓存(FIFO 淘汰 + TTL 回收),减少重复加载 - **程序内更新** —— 自动检查新版本,国内客户端走 gh 代理加速下载;含 `--self-update` 兜底替换通道 - **系统托盘** —— 最小化到托盘,边缘悬浮工具栏快捷唤起 ### 🏗️ 双前端独占架构 VibeOCR 采用**双前端并存**架构,两套 UI 各自独占一个 WorkerHost 后端进程,互斥运行: - **PySide6 Classic** —— 成熟的 Qt 桌面 UI(当前主力) - **WinUI Next** —— 基于 WinUI 3 的下一代 UI 核心设计(详见 `specs/2026-07-14-dual-frontend-exclusive-workerhost-adr.md`): | 约束 | 实现 | |------|------| | 两套产品互斥运行 | Windows 命名 Mutex `Local\VibeOCR.Frontend.Exclusive.v1`(不扫描进程名) | | 单份后端实现 | 两套前端共享同一 WorkerHost 代码库,各自启动独占实例 | | UI 不直接调后端 | 前端只依赖 `BackendClient` + 协议 DTO;架构守卫强制(`tests/architecture/`) | | 协议一致性 | schema / C# / Python 三方方法表一致性测试 | **自动化架构守卫**(`tests/architecture/`): - UI→backend import 零例外门禁(迁移 allowlist 已删除) - WorkerHost UI-free import gate - 后端→UI 禁止反向依赖 - 协议方法表三方一致性 **实施状态**:二维码、单图/批量 OCR、五种导出、PDF open/render/mutate/OCR/save、业务设置、预热/缓存和有界 shutdown 均通过 typed client/RPC;UI→backend import 从基线 90 清零。contracts、Python client、backend、PySide app 已形成真实物理 workspace 包;发布流水线构建并校验五个无文件冲突的 wheel,再把同一组 SHA-256 精确绑定到产品制品。 ## 下载安装 ### 方式一:下载便携版(推荐,无需配置环境) 前往 [Releases](https://github.com/FelixJI/VibeOCR/releases) 下载最新版 **`VibeOCR-Classic-vX.Y.Z-win64.zip`**(即 PySide6 Classic 路线,功能完整、当前主力),解压后运行 `VibeOCR.exe` 即可。 > ⚠️ 部分历史或手动构建的 Release 里可能附带 `VibeOCR-Next-vX.Y.Z-win64.zip`(WinUI Next 路线),**目前处于早期开发阶段、基本不可用**,仅供开发预览,普通用户请勿下载。默认 tag 发版只产 Classic;详见上方「开发状态与两条路线」一节。 > 国内用户访问 GitHub 较慢时,可在程序内检查更新(自动走 gh 代理加速),或使用 gh 代理前缀手动下载。 首次启动时,应用会自动检测 GPU/CPU 并引导安装推理依赖;WebEngine 渲染组件已内置主包。 ### 方式二:安装 Python wheelhouse Release 同时提供 `VibeOCR-Python-wheels-vX.Y.Z.zip`。解压后先安装本地五包, 再由安装器联网选择 CPU 或 CUDA 12.6 官方 wheel 源: ```powershell py -3.13 -m venv .venv $wheels = @(Get-ChildItem .\wheels\*.whl) if ($wheels.Count -ne 5) { throw "wheelhouse 应恰好包含五个 VibeOCR wheel" } $wheelPaths = @($wheels | ForEach-Object { $_.FullName }) .venv\Scripts\python -m pip install @wheelPaths .venv\Scripts\vibeocr-install-backend --profile auto --network domestic .venv\Scripts\vibeocr ``` 显式传入五个 wheel 可避免同版本旧缓存或公开索引候选覆盖本次发布文件。 `vibeocr-install-backend` 默认安装到当前 Python 环境;GPU profile 会显式使用 Paddle cu126 与 PyTorch cu126 index,CPU profile 不安装 GPU Paddle。安装过程需要联网, 但 OCR 运行和用户文件处理仍完全本地进行。 ### 方式三:从源码运行(开发者) 详见下方 [开发指南](#开发指南)。 ## 技术栈 | 领域 | 技术 | |------|------| | GUI 框架 | PySide6(Qt for Python) | | 文字 / 表格 / 公式 OCR | PaddleOCR、PaddlePaddle-GPU(CUDA 12.6) | | 文档解析 | MinerU、PaddleOCR-VL | | 深度学习运行时 | PyTorch(cu126,同时为 Paddle 提供 CUDA DLL) | | PDF 处理 | PyMuPDF、fontTools(CJK 子集化) | | PDF 后端进程 | FastAPI + uvicorn(子进程内 HTTP 服务) | | 进程间通信 | pydantic(共享 schema)、httpx(PDF 后端)、Named Pipe + 共享内存(WorkerHost RPC) | | 条码 | qrcode、python-barcode、pyzbar、OpenCV | | 导出 | python-docx(Word)、openpyxl(Excel) | | 异步集成 | qasync(Qt 事件循环 + asyncio) | | 依赖管理 | [uv](https://github.com/astral-sh/uv) | | 代码质量 | ruff + pyright + pytest | ## 开发指南 ### 环境要求 - Windows 10/11(64 位) - Python **3.13**(仅支持 3.13,见 `pyproject.toml`) - [uv](https://docs.astral.sh/uv/)(推荐)或 pip - .NET SDK **10.0.302**(构建 WinUI 前端,见 `global.json`) > ⚠️ **dotnet 路径陷阱**:若系统同时装了 x86 与 x64 .NET,PATH 里的 `dotnet` 可能解析到 > `C:\Program Files (x86)\dotnet\dotnet.exe`(仅有运行时、**无 SDK**),导致 > `A compatible .NET SDK was not found` / `Requested SDK version: 10.0.302`。 > 验证:`dotnet --list-sdks` 应能看到 `10.0.302`;若为空,说明解析到了 x86 副本。 > 修复:把 `C:\Program Files\dotnet\` 移到 PATH 中 x86 目录**之前**,或在 shell 里: > > ```powershell > # PowerShell:优先使用 x64 dotnet(仅当前会话) > $env:PATH = "$env:ProgramFiles\dotnet;$env:PATH" > dotnet --list-sdks # 应列出 10.0.302 > ``` > > ```bash > # Git Bash:优先使用 x64 dotnet(仅当前会话) > export PATH="/c/Program Files/dotnet:$PATH" > ``` > > 仓库内 `scripts/*.ps1` 已硬编码 `$env:ProgramFiles\dotnet\dotnet.exe`,不受此影响。 ### 安装依赖 ```bash # 克隆仓库 git clone https://github.com/FelixJI/VibeOCR.git cd VibeOCR # 安装四个工作区包与根兼容包 uv sync --all-packages # 联网安装当前机器的推理重依赖;也可显式改为 cpu / gpu-cu126 uv run vibeocr-install-backend --profile auto --network domestic ``` > 说明:PaddlePaddle-GPU 与 PyTorch 均为 CUDA 12.6 构建(cu126)以保持 CUDA DLL 同源。 > `pyproject.toml` 已配置国内镜像(阿里云 / 南大 / PaddlePaddle 官方),无需额外设置。 ### 运行应用 ```bash uv run vibeocr ``` ### 代码质量检查 项目在 `qa/` 目录提供了一套统一的代码质量脚本(详见 [`qa/README.md`](qa/README.md)): ```bash # 交互式选择检查项 uv run python qa/run.py # 一键运行全部检查(格式化 / lint / 类型检查) uv run python qa/run.py --all --quick # 运行测试并生成覆盖率报告 uv run python qa/coverage.py --html ``` 提交前建议执行 `pre-commit install` 配置 Git 钩子。 ### 运行测试 测试按模块组织在 `tests/` 下(`core` / `managers` / `models` / `services` / `views` / `widgets` / `workers` / `integration`),共 134 个: ```bash # 跑全部测试 uv run pytest # 只跑某一层(推荐:改动后定向验证) uv run pytest tests/services uv run pytest tests/views/tabs # 单个测试文件 / 函数 uv run pytest tests/services/test_pdf_service.py uv run pytest tests/services/test_pdf_service.py::test_add_text_layer ``` ### 构建 / 测试 WinUI(.NET)前端 WinUI 前端位于 `src/dotnet/`,解决方案文件为 `src/dotnet/VibeOCR.slnx`(7 个项目: `Contracts` / `Platform` / `App`(WinUI) / `Bootstrapper` + 3 个测试项目)。确保先用上面的 dotnet 路径陷阱说明修正 `dotnet` 解析,然后: ```bash # 还原 + 构建整个解决方案(Debug) dotnet build src/dotnet/VibeOCR.slnx # 跑 .NET 测试(xUnit) dotnet test src/dotnet/VibeOCR.slnx --no-build # 打包 Release 便携版(硬编码 x64 dotnet,无需手动改 PATH) # Version 缺省自动从 pyproject.toml 读取,也可显式传入:-Version pwsh scripts/build_winui_release.ps1 ``` > 也可单独构建:`dotnet build src/dotnet/VibeOCR.App/VibeOCR.App.csproj` ### NuGet 依赖锁文件 仓库将各 .NET 应用 / 测试入口的 `packages.lock.json` 纳入 Git,用于锁定完整的传递依赖图。 `global.json` 固定 .NET SDK 版本,`Directory.Packages.props` 集中声明直接依赖版本;普通 Restore 默认启用 locked mode,只能读取已提交的锁文件。项目声明与锁文件不一致时,Restore 会失败, 不会因 Visual Studio、开发机架构或隐式 Restore 而静默改写锁文件。 ```powershell # 日常还原:严格使用已提交的锁文件 dotnet restore src/dotnet/VibeOCR.slnx # 仅在升级包版本、修改 PackageReference / TFM / RID 时更新锁文件 powershell -ExecutionPolicy Bypass -File scripts/update_dotnet_locks.ps1 # PowerShell 7 也可使用:pwsh -File scripts/update_dotnet_locks.ps1 # 通过 QA 依赖升级入口执行同一脚本(同时升级 Python 依赖) python qa/upgrade_deps.py --dotnet-locks ``` 更新依赖时,应将 `Directory.Packages.props` / `.csproj` 与生成的 `packages.lock.json` 放在同一提交中, 并审查锁文件 diff。当前 WinUI App 及其测试只支持 `win-x64`;若出现 `win-x86` 或 `win-arm64` 依赖图,不应直接提交,应先检查 Restore 命令或 IDE 平台设置。若将来正式支持新架构,应先更新 项目中的 `RuntimeIdentifiers`,再通过上述脚本统一重建并提交锁文件。CI 同样使用 locked mode, 锁文件过期会直接阻止构建。 ## 项目结构 Python 的 `vibeocr.*` 兼容导入由四个物理 source root 共同组成,同一路径只属于 一个 wheel;根 `vibeocr` wheel 不含产品代码,只精确聚合四包。 | 发行包 | 物理源码根 | 主要所有权 | |---|---|---| | `vibeocr-contracts-py` | `packages/vibeocr-contracts-py/src/vibeocr` | 顶层版本、DTO、`protocol/v1` schema/golden | | `vibeocr-client-py` | `packages/vibeocr-client-py/src/vibeocr` | typed client、IPC/model、环境安装器、Qt-free 共享层 | | `vibeocr-backend` | `packages/vibeocr-backend/src/vibeocr` | WorkerHost 服务端、OCR/PDF/二维码实现、推理 worker | | `vibeocr-pyside` | `apps/vibeocr-pyside/src/vibeocr` | `main.py`、Qt managers/views/widgets/ui | ``` vibeocr/(下列为合并后的逻辑命名空间;物理所有权见上表) ├── vibeocr/ │ ├── main.py # 应用入口(环境变量预处理 + 单实例 + 启动 + --self-update 兜底) │ ├── env_manager.py # 环境与依赖管理(python-build-standalone 部署、CUDA DLL 路径) │ ├── pipeline_status.py # 流水线首次成功状态记录(防重复引导) │ ├── machine_cache.py # 机器特征缓存(避免重复探测 GPU/模型源) │ ├── network_detector.py # 国内/海外网络环境探测 │ ├── python_path_manager.py # 打包态内嵌 Python 路径解析 │ ├── core/ # 领域内核(与 Qt/网络无关) │ │ ├── constants.py # 全局常量(共享内存大小、超时等) │ │ ├── base_worker.py # Worker 基类 │ │ ├── singleton_meta.py # 线程安全单例元类 │ │ └── pipelines/ # 推理流水线注册表 + 各管道 spec/选项 │ │ ├── __init__.py # OCRPipeline 枚举 + 元数据(单一事实源) │ │ ├── registry.py # PipelineRegistry / PipelineSpec │ │ ├── pipeline_ocr.py # 通用 OCR │ │ ├── pipeline_pp_structure.py # PP-StructureV3 │ │ ├── pipeline_table.py # 表格识别 │ │ ├── pipeline_formula.py # 公式识别 │ │ ├── pipeline_mineru.py # MinerU 文档解析 │ │ └── pipeline_paddlocr_vl.py # PaddleOCR-VL │ ├── models/ # 数据模型(dataclass,跨进程共享) │ │ ├── ocr_result.py # OCRResult / TextBlock │ │ ├── pdf_document.py # PdfDocument / PdfPageInfo / TextLayerInfo(规范模型) │ │ ├── pdf_session.py # PDF 会话状态 │ │ ├── batch_request.py # 批量请求 + 预处理选项 │ │ ├── ocr_options.py # OCR 选项 │ │ ├── pdf_ocr_options.py # PDF OCR 选项 │ │ ├── export_settings.py # 导出设置 │ │ └── text_block_options.py # 文本块选项 │ ├── ipc/ # PDF 后端进程间通信契约 │ │ ├── schemas.py # pydantic 共享 schema(请求/响应/Mirror/Diff) │ │ └── model_bridge.py # PdfDocumentMirror ↔ PdfDocument 桥接(主进程侧) │ ├── services/ # 业务服务层 │ │ ├── ocr_service_subprocess.py # OCR 子进程服务(主进程侧单例,对外接口) │ │ ├── ocr_worker_process.py # OCR worker 子进程入口(持有 PaddleX) │ │ ├── worker_manager.py # PaddleX WorkerManager 封装(共享内存 IPC) │ │ ├── ocr_service.py / _base.py / _portable.py # 多形态 OCRService │ │ ├── pdf_backend_process.py # PDF 后端 FastAPI 子进程(持有 fitz) │ │ ├── pdf_backend_client.py # 主进程 httpx 客户端 + 进程托管 │ │ ├── pdf_service.py # PDF 操作与文字层写入(在后端进程内调用) │ │ ├── mineru_service.py / _batch.py # MinerU 文档解析 │ │ ├── pipeline_cache_manager.py # 流水线缓存(FIFO + TTL) │ │ ├── export_service.py # 导出 Word/Excel/Markdown │ │ ├── qrcode_service.py # 二维码/条码生成 │ │ ├── qrcode_decode_service.py # 二维码/条码解码 │ │ ├── text_block_processor.py # 文本块后处理 │ │ ├── update_service.py # 程序内更新 │ │ ├── env_config.py # 镜像源、python-build-standalone 配置 │ │ └── log_service.py # 日志初始化 │ ├── workers/ # Qt 后台线程(主进程内) │ │ ├── ocr_worker.py # OCR QRunnable │ │ ├── batch_queue_manager.py # 批量任务队列 │ │ ├── pdf_ipc_worker.py # PDF IPC 请求线程 │ │ └── pdf_render_thumb_ipc_worker.py # PDF 缩略图渲染线程 │ ├── managers/ # 应用级管理器(单例) │ │ ├── config_manager.py # 统一配置 │ │ ├── settings_manager.py # 设置持久化 │ │ ├── dependency_manager.py # 依赖安装/更新 │ │ ├── subprocess_manager.py # OCR 子进程生命周期 │ │ ├── pdf_session_manager.py # PDF 会话编排 │ │ └── layout_manager.py # 窗口布局持久化 │ ├── views/ # 视图层(Controller + 复合页) │ │ ├── main_window.py # 主窗口 │ │ ├── clipboard_controller.py # 剪贴板协调 │ │ ├── settings_page_controller.py │ │ ├── batch_recognition_tab.py # 批量识别页 │ │ ├── pdf_preview_window.py # PDF 独立预览窗 │ │ └── tabs/ # 各功能标签页(单文件 / PDF / 二维码 / 关于) │ ├── widgets/ # 可复用 Qt 组件 │ │ ├── screen_capture_overlay.py # 全屏截图遮罩 │ │ ├── inline_edit_canvas.py # 截图内联编辑器 │ │ ├── editor/ # 编辑器子模块(画布/工具栏/标注项/命令栈) │ │ ├── recognition_panel.py / result_view_widget.py │ │ ├── install_dialog.py / backend_choice_dialog.py │ │ ├── toast_widget.py / toolbar.py / magnifier_overlay.py │ │ └── *_options_widget.py # 各类选项面板 │ ├── ui/ # Qt 自动生成代码 │ │ ├── ui_main_window.py # 由 .ui 编译(见 scripts/compile_ui.py) │ │ └── theme.py # 主题 token(当前禁用,保留) │ └── utils/ # 工具集 │ ├── cpu_info.py / system_memory.py / gpu_memory_monitor.py │ ├── cjk_font_resolver.py # 系统中文字体定位 + 子集化 │ ├── shared_memory_v2.py # 跨进程张量共享内存 │ ├── job_object.py # Windows Job Object 孤儿子进程清理 │ ├── subprocess_log.py # 子进程 stdout → 主进程日志转发 │ ├── single_instance.py # 单实例守卫 │ ├── qt_async.py # qasync 事件循环工厂 │ ├── markdown_converter.py # Markdown → HTML(KaTeX 渲染) │ ├── thumbnail_lru_cache.py # PDF 缩略图 LRU 缓存 │ ├── warmup_utils.py / ocr_preferences.py / app_settings.py │ └── indent_processor.py / pdf_coords.py / mime_types.py / autostart.py ├── resources/ # 应用图标、KaTeX 资源(打包由 --add-data 内嵌) ├── scripts/ # bump_version(打包发版)、compile_ui、update_replacer、updater_main、profile_startup ├── qa/ # 代码质量脚本(lint/format/type_check/coverage/upgrade_deps) ├── tests/ # 单元 + 集成测试(134 个,按模块组织) ├── .github/workflows/release.yml # GitHub Actions 发版(PyInstaller + 镜像 CNB) └── pyproject.toml ``` ## 源码阅读辅助 本章帮助新加入的开发者快速建立对整体架构的心智模型。代码库规模约 **132 个源文件 / 4.5 万行**,按职责分层清晰,但有几处「隔离边界」是阅读时的关键。 ### 架构总览 VibeOCR 是一个 **多进程 + Qt 主线程** 的桌面应用。主进程只跑 GUI 和轻量协调,所有重依赖(PaddlePaddle、PyMuPDF)都下沉到独立子进程,通过 IPC 通信。 > **双前端边界**:PySide Classic 与 WinUI Next 都只通过各自的客户端会话连接独占 WorkerHost;UI 层不再直接 import 后端 service/manager/worker。详见上方「双前端独占架构」。 ``` PySide Classic / WinUI Next(互斥) → BackendClient + contracts DTO → 随机 Named Pipe + session token + shared payload → 独占 WorkerHost ├─ OCR / batch / export ├─ PDF session / render / mutate / OCR / save ├─ QR encode / decode └─ settings / dependency / warmup / cache ``` ### 分层职责 | 层 | 目录 | 职责 | 依赖方向 | |----|------|------|----------| | **入口** | `apps/vibeocr-pyside/.../main.py`, `client/.../env_manager.py` | 单实例、依赖检测、启动 | → client/backend | | **纯契约** | `packages/vibeocr-contracts-py/...` | 协议 DTO、schema、golden | stdlib-only | | **Python 客户端** | `client/`, `worker_host/backend_client.py` | 会话、typed RPC、取消、共享载荷 | → contracts | | **后端** | `worker_host/`, `application/`, `services/` | OCR/PDF/二维码/设置业务实现 | → contracts/models | | **PySide 壳** | `pyside/`, `views/`, `widgets/`, `ui/` | Qt 平台能力、展示与输入采集 | → client/contracts | | **工具** | `utils/` | CPU/GPU 信息、字体、共享内存等纯工具 | 无外部依赖 | > **规则**:前端只能依赖 client/contracts,不能 import 后端实现;Python/C# 方法表、JSON Schema 与 golden fixture 必须同步通过契约门禁。 ### 关键数据流 #### 1. 截图 OCR(最常用路径) ``` 全局快捷键 → widgets/screen_capture_overlay.py(全屏遮罩 + 框选) → widgets/inline_edit_canvas.py(可选标注:马赛克/模糊/矩形) → client/session.py(进程级 BackendSession) │ ↓ Named Pipe RPC + 共享内存 → worker_host(PaddleX 推理、进度、取消、导出) → widgets/recognition_panel.py(渲染结果,支持复制/导出) ``` #### 2. PDF 处理(进程化架构) ``` views/tabs/pdf_tab.py(UI 交互) → pyside/pdf_session_manager.py(Qt 会话/ViewModel) → pyside/pdf_ipc_worker.py(Qt 线程) → client/pdf.py(共享 WorkerHost 兼容客户端) │ ↓ Named Pipe RPC → WorkerHost 内 PDF adapter(不再启动 localhost 子进程) │ → services/pdf_service.py(fitz 操作 + OCR 文字层写入) │ ← 返回 PdfDocumentMirror / ModelDiff / PNG 字节 → ipc/model_bridge.py(Mirror → PdfDocument 只读视图) → widgets(缩略图/预览刷新) ``` > PDF 后端返回的是 `PdfDocumentMirror`(纯数据,可序列化),主进程通过 `ipc/model_bridge.py` 重建为 UI 现有代码熟悉的 `PdfDocument` 只读视图。所有修改操作(旋转/删除/插入/OCR 写层)走 IPC,后端返回增量 `ModelDiff`,主进程 `apply_diff` 刷新视图。 #### 3. 批量识别 ``` views/batch_recognition_tab.py(拖入多文件) → client/batch.py(批量 adapter) → 共享 BackendSession(并发、取消、进度) → WorkerHost ocr.export(Word/Excel/Markdown/HTML/Text) ``` ### 推荐阅读顺序 按以下顺序读,能在最短时间内建立完整心智模型: 1. **`main.py`** —— 启动流程:环境变量预处理 → 单实例守卫 → `ConfigManager` → `MainWindow` → qasync 循环。注意 `--self-update` 兜底通道(抢在 Qt import 之前拦截)。 2. **`packages/vibeocr-contracts-py/src/vibeocr/contracts/` + `protocol/v1/`** —— 纯 Python DTO、JSON Schema、golden fixture 与公开方法表。 3. **`client/session.py` + `worker_host/backend_client.py`** —— PySide 的进程级独占会话与 typed RPC。 4. **`worker_host/main.py` + `composition.py`** —— Named Pipe 生命周期、公开方法注册与 UI-free 生产组合。 5. **`pyside/pdf_session_manager.py` + `client/pdf.py`** —— PDF Qt ViewModel 与 WorkerHost 边界。 6. **`views/main_window.py` → `views/tabs/`** —— 前端如何只经 client/contracts 提交任务并展示结果。 ### 关键设计决策(读码前必知) - **为什么只有一个 WorkerHost?** OCR/PDF 仍与 UI 崩溃域隔离,但统一的父进程 watchdog、随机 pipe/token 和有界 shutdown 能保证一一对应,不再叠加 localhost 子进程。 - **为什么 PDF 在 WorkerHost 内执行?** PyMuPDF session 只能由后端持有;前端只接收 PNG bytes、`PdfDocumentMirror` 与 `ModelDiff`,不会跨进程携带 fitz/Qt 对象。 - **为什么有 `Mirror` 和 `Diff`?** 主进程不能持有 fitz 上下文,但 UI 代码大量直接读 `PdfPageInfo` 字段。`ipc/model_bridge.py` 把后端返回的纯数据 `Mirror` 重建为 UI 熟悉的 `PdfDocument` 只读视图;修改操作返回增量 `ModelDiff` 而非整文档,减少传输。 - **流水线缓存(`pipeline_cache_manager.py`)**:重型流水线(PP-StructureV3 / MinerU / PaddleOCR-VL)按显存分层加载,FIFO 淘汰 + TTL 闲置回收。改流水线相关代码前先读它,理解生命周期边界。 - **CUDA DLL 同源(`env_manager.py` + `pyproject.toml` 注释)**:Paddle cu126 找 `cublas64_12.dll`,由 torch cu126 的 `torch/lib` 提供。所以项目显式依赖 torch 不仅为推理,也为给 paddle 提供 CUDA 运行时 DLL。`OCRService._setup_cuda_dll_path` 负责注册路径。 - **孤儿进程清理(`utils/job_object.py`)**:子进程由 Windows Job Object 托管,主进程崩溃时子进程自动终止,不残留。 ### 常见读码问题 | 问题 | 入口文件 | |------|----------| | 新加一种识别流水线? | `core/pipelines/`(新建 `pipeline_xxx.py` + 注册到 `__init__.py`) | | 改 OCR 选项 UI? | `widgets/backend_options_widget.py` + `models/ocr_options.py` | | 改 PDF 页面操作? | `views/tabs/pdf_tab.py`(UI)→ `pyside/pdf_session_manager.py` | | 新增 PDF 后端 API? | `packages/vibeocr-contracts-py/src/vibeocr/protocol/v1/methods.schema.json` → WorkerHost handler/composition → Python/C# typed client | | 改导出格式? | `services/export_service.py` | | 改快捷键/托盘? | `views/main_window.py` + `main.py` | | 调整流水线缓存策略? | `services/pipeline_cache_manager.py` | ### 开发调试技巧 - **日志**:`services/log_service.py` 统一初始化;子进程 stdout 由 `utils/subprocess_log.py` 转发到主进程日志。三套子进程(OCR worker / PDF 后端 / updater)的日志通道已统一。 - **UI 文件**:`ui/ui_main_window.py` 由 `scripts/compile_ui.py` 从 `.ui` 编译生成,**不要手改**,改 `.ui` 后重新编译。 - **代码质量**:提交前跑 `uv run python qa/run.py --all --quick`(lint + 格式 + 类型检查)。 - **测试**:`tests/` 按模块组织(core/managers/models/services/views/widgets/workers/integration),134 个测试。`uv run pytest tests/<子目录>` 跑某一层。 - **网络环境**:`network_detector.py` 探测国内/海外,影响镜像源选择;调试时可关注 `services/env_config.py`。 ## 发布流程 打包与发版由 [`scripts/bump_version.py`](scripts/bump_version.py) 编排(基于 PyInstaller), 推送到 `v*` 格式的 tag 后,GitHub Actions([`.github/workflows/release.yml`](.github/workflows/release.yml))会: 1. 独立构建 contracts/client/backend/pyside 四包与根兼容 meta wheel 2. 校验 wheel 内容无路径冲突、根 wheel 无代码、CPU/GPU profile 元数据正确 3. 用同一 wheel 集合组合 `VibeOCR-Classic` 与 `VibeOCR-Next`,并生成 Python wheelhouse 4. 分别运行制品 verifier、生成 SHA-256 并上传 GitHub Release ```bash # 本地打包当前版本 uv run python scripts/bump_version.py --build # 升级版本并打包(交互式) uv run python scripts/bump_version.py minor ``` 仓库的 [Release](.github/workflows/release.yml) workflow 同时承担定时发版编排: - 每天北京时间 15:30(GitHub cron 为 UTC 07:30)检查 `main`。 - 若当前版本标签之后没有新提交,直接结束,不消耗完整发版门禁。 - 若有新提交,先复用完整 Quality Gates(调用 ci.yml);全部通过后自动升级 patch 版本,创建 release commit/tag,原子推送二者,再进入 build job 构建发布。 - 若质量门或后续 build 失败,先把修复补丁合入 `main`,再到 GitHub **Actions → Release → Run workflow**,选择 `main` 手动重试。 手动触发时可选择 `patch`、`minor` 或 `major`;流水线会重新执行质量门, 并按所选增量生成新版本。每日定时发版固定使用 `patch`。 - 手动推 `vX.Y.Z` tag 也会触发 Release:跳过版本号编排,直接复用 Quality Gates 后从该 tag 构建发布。 ## 下载渠道 | 渠道 | 地址 | |------|------| | GitHub(主) | | | Gitee(代码仓库) | | | CNB(代码镜像) | | ## 许可证 [MIT License](LICENSE) © 2025–2026 Felix Ji