fix: make OCR portable and reliable across AMD64 and ARM64 (#519)

* fix: make OCR portable and reliable

* fix: harden OCR installation portability

* fix: pin OCR partials across downloads

* fix: make OCR execution reliably asynchronous

* fix: harden OCR portability and docs routes

* fix: preserve decoder and docs safeguards
This commit is contained in:
SnapOtter
2026-07-15 03:34:24 +08:00
committed by GitHub
parent 58121f205f
commit 991c981529
409 changed files with 67151 additions and 8076 deletions
+6 -6
View File
@@ -1,8 +1,8 @@
---
description: "SnapOtter 的 monorepo 結構、app 與套件架構、請求生命週期,以及資源占用。"
i18n_source_hash: 9e8f80499a37
i18n_provenance: human
i18n_output_hash: 733f35af8cb1
i18n_source_hash: 733cb3c10884
i18n_provenance: human
---
# 架構 {#architecture}
@@ -36,13 +36,13 @@ snapotter/
### `@snapotter/ai` {#snapotter-ai}
一個橋接層,呼叫 Python 指令碼進行 ML 操作。首次使用時,橋接層會啟動一個常駐的 Python 分派器程序,預先匯入沉重的程式庫(PIL、NumPy、MediaPipe、rembg),使後續的 AI 呼叫可略過匯入負擔。若分派器尚未就緒,橋接層會退回為每個請求產生一個全新的 Python 子程序
呼叫本機和 Python ML 運作時的橋接層。 大多數 Python 工具使用持久性 dispatcher 來預先匯入重型庫(PIL、NumPy、MediaPipe、rembg),因此後續呼叫會跳過匯入開銷。 OCR 與此可變共享環境隔離: `fast` 呼叫原生 Tesseract`balanced``best` 使用專用的持久性 JSONL dispatcher,固定到活動的不可變 RapidOCR/ONNX 世代。 每個請求都包含一個 generation lease。 啟動首先在候選者上運行 smoke test,然後自動切換到其 dispatcher。 先前的 dispatcher 在其生成被垃圾收集之前耗盡
**模型不會預先載入。** 每個工具指令碼會在請求時從磁碟載入其模型權重,並在請求結束時捨棄。完整的記憶體剖析請參閱[資源占用](#resource-footprint)。
支援的操作:背景除(rembg/BiRefNet、放大RealESRGAN臉部模糊(MediaPipe、臉部強化GFPGAN/CodeFormer物件擦除(LaMa ONNXOCRPaddleOCR/Tesseract)、上色(DDColor)、噪點移除、紅眼移除、相片修復、護照相片產生、透明度修正BiRefNet HR-matting),以及內容感知縮放Go caire 二進位)。
支援的操作: 背景除(rembg/BiRefNet 升級RealESRGAN 臉部模糊(MediaPipe 人臉增強GFPGAN/CodeFormer 物件擦除(LaMa ONNX OCRTesseract 和 RapidOCR 以及 PP-OCR ONNX 機型), 著色(DDColor), 消除噪音, 消除紅眼, 照片修復、 護照照片生成, 透明度固定BiRefNet HR-matting),內容感知調整大小Go caire 二進位)。
Python 指令碼位於 `packages/ai/python/`。Docker 映像檔會在建置期間預先下載所有模型權重,因此容器可完全離線運作
Python 腳本位於 `packages/ai/python/` 中。大型可選模型包根據需要安裝到持久性 `/data/ai` 卷中。準確的 OCR 使用簽署的、特定於平台的工件;內建 Tesseract 圖層無需下載模型包
### `@snapotter/shared` {#snapotter-shared}
@@ -87,7 +87,7 @@ Python 指令碼位於 `packages/ai/python/`。Docker 映像檔會在建置期
2. 前端將含檔案與設定的 multipart POST 送往 `/api/v1/tools/:section/:toolId`
3. API 路由以 Zod 驗證輸入,然後分派處理。
4. 對於標準工具,工作會依模態排入適當的 BullMQ poolimage、media 或 docs)。程序內的 BullMQ worker 會根據 EXIF 中繼資料自動校正影像方向、執行工具的處理函式,並回傳結果。
5. 對於 AI 工具,TypeScript 橋接層會將請求送往常駐的 Python 分派器(或退回產生一個全新的子程序),等待其完成,並讀取輸出檔案
5. 對於大多數 AI 工具,TypeScript 橋會向持久性 Python dispatcher 發送請求。 快速 OCR 而是呼叫 Tesseract,而準確的 OCR 從活動的不可變 OCR 產生中啟動固定的執行檔。 請求的 OCR 層在入口處固定,並且在執行期間永遠不會默默更改
6. 工作進度會持久化至 PostgreSQL 中的 `jobs` 資料表,因此狀態可在容器重新啟動後保留。即時更新透過位於 `/api/v1/jobs/:jobId/progress` 的 SSE 傳遞。
7. API 回傳一個 `jobId``downloadUrl`。使用者從 `/api/v1/download/:jobId/:filename` 下載處理後的檔案。
+42 -10
View File
@@ -1,8 +1,8 @@
---
description: "使用 Docker 將 SnapOtter 部署到正式環境。硬體需求、GPU 設定,以及 Nginx、Traefik 和 Cloudflare 的反向代理設定。"
i18n_source_hash: 6b6957060fa6
i18n_provenance: machine
i18n_output_hash: 2877802ecaa6
i18n_output_hash: d1dc1e293c3a
i18n_source_hash: e0d8d5f6fc87
i18n_provenance: human
---
# 部署 {#deployment}
@@ -11,6 +11,12 @@ SnapOtter 以 3 個容器的 Docker Compose 堆疊部署:SnapOtter 應用程
關於 GPU 設定、Docker Compose 範例與版本鎖定,請參閱 [Docker Image](./docker-tags)。
<!-- korean-ocr-contract:start -->
::: info 韓語 OCR 相容性
快速 OCR 支援 `auto``en``de``es``fr``zh``ja`,但不支援韓語 (`ko`)。韓語需要精確 OCR 套件以及 `balanced``best`。此套件可在官方 Linux amd64 和 arm64 容器上執行;即使是 NVIDIA 主機,OCR 仍使用 CPU。不受支援的系統會傳回明確的相容性錯誤,絕不會靜默回退至 `fast`。韓語搭配 `fast` 或舊版 `tesseract` 別名時,會在排入佇列前以 `FEATURE_INCOMPATIBLE``fast-korean-unsupported` 拒絕。
:::
<!-- korean-ocr-contract:end -->
## 快速開始(CPU {#quick-start-cpu}
```yaml
@@ -113,7 +119,7 @@ docker compose up -d
## 快速開始(NVIDIA CUDA {#quick-start-nvidia-cuda}
若要在 AI 工具(去背、放大、臉部強化、OCR)上使用 NVIDIA CUDA 加速:
對於支援的 AI 工具上的 NVIDIA CUDA 加速(背景去除、放大、臉部增強)
```yaml
# docker-compose-gpu.yml - Requires: NVIDIA GPU + nvidia-container-toolkit
@@ -251,10 +257,10 @@ deploy:
|---|---|
| CPU | 4 核心 |
| RAM | 4 GB |
| 磁碟 | 3 GB映像檔)+ 24 GBAI 模型+ 工作空間 |
| Disk | 3 GB影像)+ 約 20 GB(所有選用 AI 套件+ 工作 |
| GPU | 非必要(CPU 後備) |
**安裝 AI 套件組是把 RAM 推升到 4 GB 的原因** 未安裝 AI 時,應用程式閒置時約佔用 360 MB;安裝全部七個套件組後,常駐記憶體維持在 ~2.6 GB,因為 Python AI sidecar 會在啟動時預先載入其模型(去背、放大、OCR、轉錄、臉部偵測、修復)。非 AI 安裝維持輕量;AI 安裝則需要 ≥4 GB
**安裝和運行更大的 AI 捆綁包將 RAM 的建議量推至 4 GB。** 如果未安裝可選包,則應用程式空閒時間約為 360 MB。 舊版 Python 工具共享 sidecar,而精確的 OCR 使用固定到活動不可變產生的專用長壽命 dispatcher。 在啟動之前,安裝程式會在候選程式上執行 smoke test。 然後,它會自動切換到新的 dispatcher,並在 garbage collection 之前耗盡先前的 dispatcher。 每個官方準確的 OCR 工件都必須通過 4 GiB cgroup 內最壞情況的 release suite 雖然 4 GB 主機建議為 Node.js 應用程式留出了空間, Postgres, Redis, 隊列, 並同時進行工作
多數 AI 工具在 CPU 上完全可用;少數確實需要 GPU。在現代 4 核心 CPU 上測得:
@@ -271,7 +277,7 @@ SnapOtter 刻意不將這些模型下載內建於 Docker 映像檔中。AI 套
有些工具依賴不只一個共用套件組。舉例來說,證件照同時需要 `background-removal``face-detection`;如果 `background-removal` 已安裝,啟用證件照只會下載缺少的 `face-detection` 套件組。相同的重用機制適用於所有 AI 工具。
AI 模型下載大小
可選 AI 包儲存估算
| 套件組 | 磁碟大小 |
|---|---|
@@ -279,9 +285,16 @@ AI 模型下載大小:
| 放大 + 臉部強化 + 雜訊移除 | 5-6 GB |
| 臉部偵測 | 200-300 MB |
| 物件消除 + 上色 | 1-2 GB |
| OCR | 5-6 GB |
| 精確 OCR`balanced`/`best` | ~208-234 MiB 下載 / ~409-488 MiB 安裝 |
| 相片修復 | 4-5 GB |
| **全部套件組** | **~24 GB** |
| 轉錄 | 〜600MB |
| **所有捆綁包** | **已安裝~20 GB** |
Fast OCR 透過 Tesseract 內建到映像中,增加約 25 個 MiB,並且不需要選購的 OCR 套件或其 4 個 GiB 記憶體需求。 準確的包可以在官方找到 Linux amd64 和 arm64 容器和運行 ONNX Runtime 在 CPU。 NVIDIA 主機使用相同的 CPU OCR 執行時,因此 OCR 不依賴 CUDA 版本或 GPU 架構。 準確的運行時需要至少 4 GiB 的有效記憶體:配置的容器 cgroup 限制,否則為主機記憶體。 在下載套件之前,SnapOtter 拒絕低於簽章相容性最低值的系統。 在無法保證 libc 和 Python ABI 的 bare-metal/預建檔案上,也會拒絕準確的套件安裝。
共用同一個 `DATA_DIR` 的複本必須使用相同的 CPU 架構;請透過節點親和性將多複本部署固定在相容的節點上。混合使用 amd64/arm64 的複本需要各自獨立的資料磁碟區和 SnapOtter 部署。
精確的運行時保持一代處於活動狀態,並在啟動後清除其下載快取。 對於此版本,首次安裝暫時需要大約 620-720 MiB 用於存檔和暫存,升級可以在老一代保持活動狀態時達到接近 1.2 GiB 的峰值。 安裝程式在下載或提取之前根據簽章索引和當前代計算確切的要求,如果資料量太小,安裝程式會提前失敗。
```yaml
deploy:
@@ -353,7 +366,6 @@ SnapOtter 支援 **55+ 種輸入格式** 與 **14 種輸出格式**,包括來
- **內容感知調整大小**在大型影像(>5 MP)上會因 caire 二進位檔的限制而當機。對較小的影像運作正常。
- **HEIF 解碼**需要 13-23 秒。HEICApple 的變體)快得多,僅需 0.3-0.9 秒。
- **OCR 日文**在 CPU 上會因 PaddlePaddle MKLDNN 的錯誤而失敗。在 GPU 上可運作。
- **放大**在 CPU 上對超出小圖的任何影像都會逾時。實務使用需要 GPU。
- **CodeFormer** 臉部強化明顯比 GFPGAN 慢(GPU 上 53 秒對比 2 秒)。多數使用情境建議使用 GFPGAN。
@@ -434,6 +446,26 @@ securityContext:
| `SESSION_DURATION_HOURS` | `168` | 登入工作階段存留期(7 天) |
| `CORS_ORIGIN` | (空白) | 以逗號分隔的允許來源,或留空表示同源 |
### 出站代理程式和私人 CA {#outbound-proxy-and-private-ca}
官方容器啟用了 Node 的環境代理支援。 如果 SnapOtter 必須透過企業代理程式到達 OCR 執行階段儲存庫或其他 HTTPS 服務,請設定 `HTTPS_PROXY`(並在需要時設定 `HTTP_PROXY`)。 將 `NO_PROXY` 設定為必須直接存取的以逗號分隔的主機列表,例如 Postgres、Redis 和內部物件儲存。
如果代理程式或內部服務由私有憑證授權單位簽署,請將 CA 憑證掛載為唯讀並將 `NODE_EXTRA_CA_CERTS` 指向它。 Node進程啟動時該檔案必須存在:
```yaml
services:
app:
environment:
HTTPS_PROXY: http://proxy.example.internal:3128
HTTP_PROXY: http://proxy.example.internal:3128
NO_PROXY: postgres,redis,minio,localhost,127.0.0.1
NODE_EXTRA_CA_CERTS: /etc/snapotter/custom-ca.pem
volumes:
- ./company-ca.pem:/etc/snapotter/custom-ca.pem:ro
```
將代理憑證保留在 Compose 檔案外部(例如,在受保護的 `.env` 檔案或機密中)。不要停用 TLS 驗證:簽署的 OCR 索引對發布元資料進行身份驗證,而正常的 TLS 驗證仍然保護傳輸和所有其他出站請求。
## 健康檢查 {#health-check}
容器內建健康檢查:
+4 -4
View File
@@ -1,8 +1,8 @@
---
description: "SnapOtter Docker 映像標籤、GPU 效能基準、版本鎖定,以及 AMD64 與 ARM64 的多平台支援。"
i18n_source_hash: 148b3608e11a
i18n_provenance: human
i18n_output_hash: 8b69b4ed0e1b
i18n_source_hash: fda322e78b4b
i18n_provenance: human
---
# Docker 映像 {#docker-image}
@@ -41,7 +41,6 @@ docker run -d --name SnapOtter --gpus all -p 1349:1349 -v SnapOtter-data:/data s
| 背景移除(isnet | 2,457ms | 1,137ms | 2.2x |
| 放大 2x | 350ms | 309ms | 1.1x |
| 放大 4x | 910ms | 310ms | 2.9x |
| OCRPaddleOCR | 137ms | 94ms | 1.5x |
| 臉部模糊 | 139ms | 122ms | 1.1x |
#### 冷啟動(容器啟動後的第一次請求) {#cold-start-first-request-after-container-start}
@@ -50,7 +49,8 @@ docker run -d --name SnapOtter --gpus all -p 1349:1349 -v SnapOtter-data:/data s
|------|-----|-----|---------|
| 背景移除 | 22,286ms | 4,792ms | 4.7x |
| 放大 2x | 3,957ms | 2,318ms | 1.7x |
| OCRPaddleOCR | 1,469ms | 1,090ms | 1.3x |
OCR 不包含在 CUDA 比較中。內建 Tesseract 圖層和選購的 RapidOCR/ONNX 層都使用 CPU,包括當容器具有 NVIDIA GPU 存取權時。
### CUDA 健康檢查 {#cuda-health-check}
+3 -3
View File
@@ -1,8 +1,8 @@
---
description: "用一道 Docker 指令安裝 SnapOtter。包含 Docker Compose 設定、從原始碼建置,以及完整功能總覽。"
i18n_source_hash: 4536d4558b8e
i18n_provenance: machine
i18n_output_hash: 4e12779bd211
i18n_source_hash: 24724b5595b2
i18n_provenance: human
---
# 快速上手 {#getting-started}
@@ -32,7 +32,7 @@ SnapOtter 預設包含匿名產品分析。若要關閉它,請開啟 **Setting
:::
::: tip NVIDIA CUDA 加速
`--gpus all`取得 NVIDIA CUDA 加速的去背、放大、OCR、臉部強化與修復
`--gpus all`實現 NVIDIA CUDA 加速的背景移除、放大、臉部增強和恢復。 OCR 仍然基於 CPU,並且在有或沒有 GPU 存取的情況下在相同映像中工作
```bash
docker run -d --name SnapOtter -p 1349:1349 --gpus all -v SnapOtter-data:/data snapotter/snapotter:latest