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: "Monorepo-structuur, app- en package-architectuur, request-levenscyclus en resourcegebruik van SnapOtter."
i18n_source_hash: 9e8f80499a37
i18n_provenance: human
i18n_output_hash: 5122b85d1d84
i18n_source_hash: 733cb3c10884
i18n_provenance: human
---
# Architectuur {#architecture}
@@ -36,13 +36,13 @@ Dit package heeft geen netwerkafhankelijkheden en draait volledig in-process.
### `@snapotter/ai` {#snapotter-ai}
Een brugjlaag die Python-scripts aanroept voor ML-bewerkingen. Bij het eerste gebruik start de brug een persistent Python-dispatcherproces dat zware bibliotheken (PIL, NumPy, MediaPipe, rembg) vooraf importeert, zodat latere AI-aanroepen de importoverhead overslaan. Als de dispatcher nog niet klaar is, valt de brug terug op het opstarten van een verse Python-subprocess per verzoek.
Een bruglaag die native en Python ML runtimes aanroept. De meeste Python-tools gebruiken een persistente dispatcher die zware bibliotheken (PIL, NumPy, MediaPipe, rembg) vooraf importeert, zodat daaropvolgende oproepen de importoverhead overslaan. OCR is geïsoleerd van die veranderlijke gedeelde omgeving: `fast` roept native Tesseract op, terwijl `balanced` en `best` een speciale persistente JSONL dispatcher gebruiken die is vastgemaakt aan de actieve onveranderlijke RapidOCR/ONNX-generatie. Elk verzoek bevat een generation lease. Bij activering wordt eerst een smoke test op een kandidaat uitgevoerd en vervolgens atomair overgeschakeld naar de dispatcher. De eerdere dispatcher loopt leeg voordat het afval wordt opgehaald.
**Modellen worden niet vooraf geladen.** Elk toolscript laadt zijn modelgewichten bij het verzoek van schijf en verwijdert ze zodra het verzoek klaar is. Zie [Resourcegebruik](#resource-footprint) voor het volledige geheugenprofiel.
Ondersteunde bewerkingen: achtergrondverwijdering (rembg/BiRefNet), upscaling (RealESRGAN), gezichtsvervaging (MediaPipe), gezichtsverbetering (GFPGAN/CodeFormer), objecten wissen (LaMa ONNX), OCR (PaddleOCR/Tesseract), inkleuren (DDColor), ruisverwijdering, rode-ogenverwijdering, fotorestauratie, generatie van pasfoto's, transparantie herstellen (BiRefNet HR-matting) en contentbewust vergroten/verkleinen (Go caire-binary).
Ondersteunde bewerkingen: achtergrondverwijdering (rembg/BiRefNet), opschaling (RealESRGAN), gezichtsvervaging (MediaPipe), gezichtsverbetering (GFPGAN/CodeFormer), object wissen (LaMa ONNX), OCR (Tesseract en RapidOCR met PP-OCR ONNX-modellen), inkleuring (DDColor), ruisverwijdering, verwijdering van rode ogen, fotoherstel, pasfoto generatie, transparantiefixatie (BiRefNet HR-matting) en inhoudsbewust formaat wijzigen (Go caire binary).
De Python-scripts staan in `packages/ai/python/`. De Docker-image downloadt alle modelgewichten vooraf tijdens de build, zodat de container volledig offline werkt.
Python-scripts zijn live in `packages/ai/python/`. Grote optionele modelpakketten worden op aanvraag geïnstalleerd in het permanente `/data/ai`-volume. Nauwkeurige OCR maakt gebruik van ondertekende, platformspecifieke artefacten; Voor de ingebouwde Tesseract-laag is geen download van een modelpakket vereist.
### `@snapotter/shared` {#snapotter-shared}
@@ -87,7 +87,7 @@ Deze VitePress-site. Wordt automatisch uitgerold naar Cloudflare Pages bij een p
2. De frontend stuurt een multipart POST naar `/api/v1/tools/:section/:toolId` met het bestand en de instellingen.
3. De API-route valideert de invoer met Zod en start vervolgens de verwerking.
4. Voor standaardtools wordt de taak in de juiste BullMQ-pool geplaatst (image, media of docs op basis van modaliteit). De in-process BullMQ-worker oriënteert de afbeelding automatisch op basis van EXIF-metadata, voert de procesfunctie van de tool uit en geeft het resultaat terug.
5. Voor AI-tools stuurt de TypeScript-brug een verzoek naar de persistent Python-dispatcher (of start een verse subprocess als fallback), wacht tot deze klaar is en leest het uitvoerbestand.
5. Voor de meeste AI-tools stuurt de TypeScript-bridge een verzoek naar de persistente Python dispatcher. Snelle OCR roept in plaats daarvan Tesseract aan, en nauwkeurige OCR start het vastgezette uitvoerbare bestand vanaf de actieve onveranderlijke OCR-generatie. De aangevraagde OCR-laag wordt vastgesteld bij binnenkomst en wordt tijdens de uitvoering nooit stilzwijgend gewijzigd.
6. Taakvoortgang wordt vastgelegd in de `jobs`-tabel in PostgreSQL, zodat de state herstarts van de container overleeft. Realtime-updates worden geleverd via SSE op `/api/v1/jobs/:jobId/progress`.
7. De API retourneert een `jobId` en `downloadUrl`. De gebruiker downloadt het verwerkte bestand vanaf `/api/v1/download/:jobId/:filename`.
+42 -10
View File
@@ -1,8 +1,8 @@
---
description: "Implementeer SnapOtter in productie met Docker. Hardwarevereisten, GPU-installatie en reverse-proxyconfiguraties voor Nginx, Traefik en Cloudflare."
i18n_source_hash: 6b6957060fa6
i18n_provenance: machine
i18n_output_hash: 6fdbf01d5c9a
i18n_output_hash: 21ff542fcb0c
i18n_source_hash: e0d8d5f6fc87
i18n_provenance: human
---
# Implementatie {#deployment}
@@ -11,6 +11,12 @@ SnapOtter wordt geïmplementeerd als een Docker Compose-stack met 3 containers:
Zie [Docker Image](./docker-tags) voor GPU-installatie, Docker Compose-voorbeelden en versievastlegging.
<!-- korean-ocr-contract:start -->
::: info Compatibiliteit voor Koreaanse OCR
Snelle OCR ondersteunt `auto`, `en`, `de`, `es`, `fr`, `zh` en `ja`, maar geen Koreaans (`ko`). Koreaans vereist het nauwkeurige OCR-pakket en `balanced` of `best`. Het pakket werkt in officiële Linux amd64- en arm64-containers, ook op NVIDIA-hosts waar OCR op de CPU blijft draaien. Niet-ondersteunde systemen krijgen een expliciete compatibiliteitsfout en vallen nooit stil terug op `fast`. Koreaans met `fast` of de oude alias `tesseract` wordt vóór het in de wachtrij plaatsen geweigerd met `FEATURE_INCOMPATIBLE` en `fast-korean-unsupported`.
:::
<!-- korean-ocr-contract:end -->
## Snelstart (CPU) {#quick-start-cpu}
```yaml
@@ -113,7 +119,7 @@ De app is daarna beschikbaar op `http://localhost:1349`.
## Snelstart (NVIDIA CUDA) {#quick-start-nvidia-cuda}
Voor NVIDIA CUDA-versnelling op AI-tools (achtergrond verwijderen, upscalen, gezichtsverbetering, OCR):
Voor NVIDIA CUDA-versnelling op ondersteunde AI-tools (achtergrondverwijdering, opschaling, gezichtsverbetering):
```yaml
# docker-compose-gpu.yml - Requires: NVIDIA GPU + nvidia-container-toolkit
@@ -251,10 +257,10 @@ deploy:
|---|---|
| CPU | 4 cores |
| RAM | 4 GB |
| Schijf | 3 GB (image) + 24 GB (AI-modellen) + werkruimte |
| Disk | 3 GB (afbeelding) + ongeveer 20 GB (alle optionele AI-pakketten) + werkruimte |
| GPU | Niet vereist (CPU-terugval) |
**Het installeren van de AI-bundels is wat het RAM naar 4 GB duwt.** Zonder geïnstalleerde AI blijft de app rond 360 MB in ruststand; met alle zeven bundels geïnstalleerd houdt hij ~2.6 GB resident, omdat de Python-AI-sidecar zijn modellen (achtergrond verwijderen, upscalen, OCR, transcriptie, gezichtsdetectie, restauratie) bij het opstarten vooraf laadt. Niet-AI-installaties blijven licht; AI-installaties hebben ≥4 GB nodig.
**Het installeren en uitvoeren van de grotere AI-bundels is wat de aanbeveling naar 4 GB RAM duwt.** Als er geen optionele pakketten zijn geïnstalleerd, is de app ongeveer 360 MB inactief. Oudere Python-tools delen een sidecar, terwijl de nauwkeurige OCR een speciale, langlevende dispatcher gebruikt die is vastgemaakt aan de actieve onveranderlijke generatie. Vóór activering voert het installatieprogramma een smoke test uit op de kandidaat. Vervolgens schakelt hij atomair over naar de nieuwe dispatcher en leegt de eerdere dispatcher vóór garbage collection. Elk officieel nauwkeurig OCR-artefact moet de release suite in het slechtste geval passeren in een 4 GiB cgroup, terwijl de hostaanbeveling van 4 GB ruimte laat voor de Node.js-applicatie, Postgres, Redis, wachtrijen en gelijktijdig werk.
De meeste AI-tools zijn prima bruikbaar op CPU; een paar willen echt een GPU. Gemeten op een moderne 4-core CPU:
@@ -271,7 +277,7 @@ SnapOtter bakt deze modeldownloads bewust niet in de Docker-image. AI-bundels wo
Sommige tools zijn afhankelijk van meer dan één gedeelde bundel. Zo heeft Pasfoto zowel `background-removal` als `face-detection` nodig; als `background-removal` al is geïnstalleerd, downloadt het inschakelen van Pasfoto alleen de ontbrekende `face-detection`-bundel. Hetzelfde hergebruik geldt voor alle AI-tools.
Downloadgroottes van AI-modellen:
Schattingen van optionele AI-pakketopslag:
| Bundel | Schijfgrootte |
|---|---|
@@ -279,9 +285,16 @@ Downloadgroottes van AI-modellen:
| Upscale + Gezichtsverbetering + Ruisverwijdering | 5-6 GB |
| Gezichtsdetectie | 200-300 MB |
| Objectgom + Inkleuren | 1-2 GB |
| OCR | 5-6 GB |
| Nauwkeurige OCR (`balanced`/`best`) | ~208-234 MiB downloaden / ~409-488 MiB geïnstalleerd |
| Fotorestauratie | 4-5 GB |
| **Alle bundels** | **~24 GB** |
| Transcriptie | ~600 MB |
| **Alle bundels** | **~20 GB geïnstalleerd** |
Snelle OCR is in het beeld ingebouwd via Tesseract, voegt ongeveer 25 MiB toe en vereist niet het optionele OCR-pakket of de 4 GiB-geheugenvereiste. Het nauwkeurige pakket is beschikbaar in de officiële Linux amd64- en arm64-containers en draait ONNX Runtime op CPU. NVIDIA-hosts gebruiken dezelfde CPU OCR-runtime, dus OCR is niet afhankelijk van de CUDA-versie of GPU-architectuur. De nauwkeurige runtime vereist minimaal 4 GiB effectief geheugen: de geconfigureerde container cgroup-limiet, anders hostgeheugen. SnapOtter wijst systemen af die lager zijn dan het ondertekende compatibiliteitsminimum voordat het pakket wordt gedownload. Nauwkeurige pakketinstallatie wordt ook afgewezen op bare-metal/voorafgebouwde archieven waarvan libc en Python ABI niet kunnen worden gegarandeerd.
Replica's die dezelfde `DATA_DIR` delen, moeten dezelfde CPU-architectuur gebruiken; zet deployments met meerdere replica's via node-affiniteit vast op compatibele nodes. Gemengde amd64/arm64-replica's hebben afzonderlijke datavolumes en onafhankelijke SnapOtter-deployments nodig.
De nauwkeurige runtime houdt één actieve generatie aan en wist de downloadcache na activering. Voor deze release heeft een eerste installatie tijdelijk ongeveer 620-720 MiB nodig voor het archief plus staging, en een upgrade kan pieken in de buurt van 1.2 GiB terwijl de oude generatie actief blijft. Het installatieprogramma berekent de exacte vereisten op basis van de ondertekende index en de huidige generaties voordat het wordt gedownload of geëxtraheerd, en mislukt vroegtijdig als het gegevensvolume te klein is.
```yaml
deploy:
@@ -353,7 +366,6 @@ Zie de [volledige formaatlijst](/nl/guide/supported-formats) voor details over e
- **Content-aware resize** loopt vast op grote afbeeldingen (>5 MP) door een beperking in de caire-binary. Werkt prima met kleinere afbeeldingen.
- **HEIF-decodering** duurt 13-23 seconden. HEIC (Apples variant) is veel sneller met 0.3-0.9 seconden.
- **OCR Japans** faalt op CPU door een PaddlePaddle MKLDNN-bug. Werkt op GPU.
- **Upscale** verloopt via time-out op CPU voor alles boven kleine afbeeldingen. GPU vereist voor praktisch gebruik.
- **CodeFormer**-gezichtsverbetering is aanzienlijk trager dan GFPGAN (53s versus 2s op GPU). GFPGAN wordt voor de meeste gebruikssituaties aanbevolen.
@@ -434,6 +446,26 @@ De opstartfout noemt de exacte UID die je moet gebruiken, dus de snelste weg is
| `SESSION_DURATION_HOURS` | `168` | Levensduur van inlogsessie (7 dagen) |
| `CORS_ORIGIN` | (leeg) | Komma-gescheiden toegestane origins, of leeg voor same-origin |
### Uitgaande proxy en privé-CA {#outbound-proxy-and-private-ca}
De officiële container maakt Node's omgevingsproxy-ondersteuning mogelijk. Als SnapOtter de OCR runtime repository of andere HTTPS-services moet bereiken via een bedrijfsproxy, stelt u `HTTPS_PROXY` in (en `HTTP_PROXY` indien nodig). Stel `NO_PROXY` in op een door komma's gescheiden lijst met hosts die rechtstreeks moeten worden bereikt, zoals Postgres, Redis en interne objectopslag.
Als de proxy of een interne service is ondertekend door een particuliere certificeringsinstantie, koppelt u het CA-certificaat alleen-lezen en verwijst u `NODE_EXTRA_CA_CERTS` ernaar. Het bestand moet bestaan wanneer het knooppuntproces start:
```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
```
Bewaar de proxyreferenties buiten het Compose-bestand (bijvoorbeeld in een beveiligd `.env`-bestand of geheim). Schakel TLS-verificatie niet uit: de ondertekende OCR-index verifieert de metagegevens van de release, terwijl normale TLS-validatie nog steeds het transport en elk ander uitgaand verzoek beschermt.
## Health check {#health-check}
De container bevat een ingebouwde health check:
+4 -4
View File
@@ -1,8 +1,8 @@
---
description: "SnapOtter Docker-image-tags, GPU-benchmarks, versievastzetting en multiplatformondersteuning voor AMD64 en ARM64."
i18n_source_hash: 148b3608e11a
i18n_provenance: human
i18n_output_hash: ae5482dbdd3c
i18n_source_hash: fda322e78b4b
i18n_provenance: human
---
# Docker-image {#docker-image}
@@ -41,7 +41,6 @@ Getest op een NVIDIA RTX 4070 (12 GB VRAM) met een 572x1024 JPEG-portret.
| Achtergrond verwijderen (isnet) | 2.457ms | 1.137ms | 2,2x |
| Upscalen 2x | 350ms | 309ms | 1,1x |
| Upscalen 4x | 910ms | 310ms | 2,9x |
| OCR (PaddleOCR) | 137ms | 94ms | 1,5x |
| Gezicht vervagen | 139ms | 122ms | 1,1x |
#### Koude start (eerste verzoek na containerstart) {#cold-start-first-request-after-container-start}
@@ -50,7 +49,8 @@ Getest op een NVIDIA RTX 4070 (12 GB VRAM) met een 572x1024 JPEG-portret.
|------|-----|-----|---------|
| Achtergrond verwijderen | 22.286ms | 4.792ms | 4,7x |
| Upscalen 2x | 3.957ms | 2.318ms | 1,7x |
| OCR (PaddleOCR) | 1.469ms | 1.090ms | 1,3x |
OCR is niet opgenomen in de CUDA-vergelijking. Zowel de ingebouwde Tesseract-laag als de optionele RapidOCR/ONNX-lagen gebruiken CPU, ook wanneer de container NVIDIA GPU-toegang heeft.
### CUDA-gezondheidscontrole {#cuda-health-check}
+3 -3
View File
@@ -1,8 +1,8 @@
---
description: "Installeer SnapOtter met Docker in één commando. Inclusief Docker Compose-installatie, bouwen vanaf broncode en een volledig functieoverzicht."
i18n_source_hash: 4536d4558b8e
i18n_provenance: machine
i18n_output_hash: d29d27e8097b
i18n_source_hash: 24724b5595b2
i18n_provenance: human
---
# Aan de slag {#getting-started}
@@ -32,7 +32,7 @@ Zie [Wat SnapOtter verzamelt](/nl/guide/telemetry) voor details over wat er word
:::
::: tip NVIDIA CUDA-versnelling
Voeg `--gpus all` toe voor NVIDIA CUDA-versnelde achtergrondverwijdering, upscaling, OCR, gezichtsverbetering en restauratie:
Voeg `--gpus all` toe voor NVIDIA CUDA-versnelde achtergrondverwijdering, opschaling, gezichtsverbetering en restauratie. OCR blijft CPU-gebaseerd en werkt in dezelfde afbeelding met of zonder GPU-toegang:
```bash
docker run -d --name SnapOtter -p 1349:1349 --gpus all -v SnapOtter-data:/data snapotter/snapotter:latest