mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
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:
@@ -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 ONNX)、OCR(PaddleOCR/Tesseract)、上色(DDColor)、噪點移除、紅眼移除、相片修復、護照相片產生、透明度修正(BiRefNet HR-matting),以及內容感知縮放(Go caire 二進位檔)。
|
||||
支援的操作: 背景去除(rembg/BiRefNet), 升級(RealESRGAN), 臉部模糊(MediaPipe), 人臉增強(GFPGAN/CodeFormer), 物件擦除(LaMa ONNX), OCR(Tesseract 和 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 pool(image、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` 下載處理後的檔案。
|
||||
|
||||
|
||||
@@ -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 GB(AI 模型)+ 工作空間 |
|
||||
| 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 秒。HEIC(Apple 的變體)快得多,僅需 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}
|
||||
|
||||
容器內建健康檢查:
|
||||
|
||||
@@ -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 |
|
||||
| OCR(PaddleOCR) | 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 |
|
||||
| OCR(PaddleOCR) | 1,469ms | 1,090ms | 1.3x |
|
||||
|
||||
OCR 不包含在 CUDA 比較中。內建 Tesseract 圖層和選購的 RapidOCR/ONNX 層都使用 CPU,包括當容器具有 NVIDIA GPU 存取權時。
|
||||
|
||||
### CUDA 健康檢查 {#cuda-health-check}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user