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
+41 -17
View File
@@ -1,18 +1,26 @@
---
description: "모든 로컬 ML 도구를 다루는 AI 엔진 레퍼런스. 배경 제거, 업스케일링, OCR, 얼굴 감지, 사진 복원 등."
i18n_source_hash: 14728c1dcd05
i18n_provenance: machine
i18n_output_hash: 0345ba8791f7
i18n_output_hash: 534278b9910c
i18n_source_hash: aa9a56cdddc7
i18n_provenance: human
---
# AI 엔진 레퍼런스 {#ai-engine-reference}
`@snapotter/ai` 패키지는 모든 ML 작업을 위해 Node.js와 **상시 실행되는 Python 사이드카**를 연결한다. 디스패처 프로세스는 요청 사이에도 살아 있어 빠른 웜 스타트 성능을 낸다. NVIDIA CUDA는 시작 시 자동으로 감지되어 사용 가능하면 사용되고, 그렇지 않으면 AI 도구가 CPU에서 실행된다.
`@snapotter/ai` 패키지는 로컬 ML 작업을 위해 기본 도구와 Python 런타임을 조정합니다. 대부분의 ML 도구는 빠른 웜 스타트를 위해 영구 Python sidecar 를 사용합니다. OCR 는 의도적으로 분리되어 있습니다. `fast`는 기본 Tesseract 바이너리를 호출하는 반면, `balanced``best``/data/ai/v3` 아래의 활성 불변 RapidOCR 세대에 고정된 전용 영구 JSONL dispatcher 를 사용합니다. 각 요청에는 generation lease 가 포함됩니다. 업그레이드 중에 SnapOtter 는 활성화하기 전에 후보에서 smoke test 를 실행하고 새로운 dispatcher 로 원자적으로 전환한 다음 garbage collection 이전의 이전 세대를 제거합니다.
NVIDIA CUDA 는 이를 지원하는 런타임에서 자동 감지되고 사용됩니다. OCR 는 NVIDIA GPU가 있는 시스템을 포함하여 모든 호스트에서 CPU 를 사용하여 이 도구에 대한 CUDA 및 드라이버 결합을 방지합니다.
VA-API, Quick Sync, OpenCL을 통한 Intel/AMD iGPU 가속은 현재 AI 추론에 지원되지 않는다. CUDA를 지원하는 NVIDIA GPU가 없는 한, 컨테이너에 `/dev/dri`를 매핑해도 이러한 Python 사이드카 도구는 가속되지 않는다.
네 가지 모달리티(이미지, 오디오, 비디오, 문서)에 걸쳐 19개의 Python 사이드카 AI 도구가 있으며, 여기에 선택적 AI 기능을 갖춘 2개의 도구가 추가된다. 모든 모델은 로컬에서 실행되며, 최초 모델 다운로드 이후에는 인터넷이 필요하지 않다.
<!-- 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 -->
## 아키텍처 {#architecture}
```
@@ -22,15 +30,17 @@ Node.js Tool Route
@snapotter/ai bridge.ts
| (stdin/stdout JSON + stderr progress events)
v
Python dispatcher (persistent process, "ai" profile)
+-- Native Tesseract + Ghostscript (fast image/PDF OCR)
|
+-- Isolated OCR runtime (persistent JSONL dispatcher)
| `-- RapidOCR + ONNX Runtime CPU + pinned PP-OCR models
|
`-- Python dispatcher (persistent process, "ai" profile)
|
|-- remove_bg.py (rembg / BiRefNet)
|-- upscale.py (RealESRGAN)
|-- inpaint.py (LaMa ONNX)
|-- outpaint.py (LaMa canvas expansion)
|-- ocr.py (PaddleOCR / Tesseract)
|-- ocr_pdf.py (page-by-page document OCR)
|-- ocr_preprocess.py (image enhancement for OCR)
|-- detect_faces.py (MediaPipe)
|-- face_landmarks.py (MediaPipe landmarks)
|-- enhance_faces.py (GFPGAN / CodeFormer)
@@ -52,7 +62,7 @@ AI 모델은 도구별로 아카이브 하나씩이 아니라 공유 의존성
Docker 이미지는 애플리케이션과 공통 런타임을 함께 제공한다. 대용량 모델 아카이브는 필요할 때 상시 유지되는 `/data/ai` 볼륨으로 다운로드된 뒤, 이를 필요로 하는 모든 도구가 재사용한다. 다른 도구가 이미 필요로 해서 어떤 번들이 이미 설치되어 있다면, 새로 의존하는 도구를 활성화해도 그 번들을 다시 다운로드하지 않는다.
AI 도구 실행되기 전에 하나 이상의 기능 번들이 필요다. 관리 UI는 `POST /api/v1/admin/tools/:toolId/features/install` 통해 도구 단위로 설치하며, 이는 전체 번들 목록을 해석하고, 이미 설치된 번들은 건너뛰며, 누락된 다운로드만 대기열에 넣는다. 예를 들어, 새 인스턴스에서 여권 사진을 활성화하면 `background-removal` `face-detection`가 대기열에 들어가고, 배경 제거가 이미 설치된 상태에서 활성화하면 `face-detection`만 대기열에 들어간다.
대부분의 AI 도구 실행하려면 하나 이상의 기능 번들이 필요합니다. 관리 UI는 전체 번들 목록을 확인하고 이미 설치된 번들을 건너뛰며 누락된 다운로드만 대기열에 추가하는 `POST /api/v1/admin/tools/:toolId/features/install` 통해 도구로 해당 항목을 설치합니다. 예를 들어, 새로운 인스턴스 `background-removal` `face-detection`에서 여권 사진을 활성화합니다. 백그라운드 제거가 이미 설치된 후에 활성화하면 `face-detection`만 대기열에 추가됩니다. OCR 는 예외입니다. `fast`에는 팩이 필요하지 않기 때문입니다. UI 또는 `POST /api/v1/admin/features/ocr/install`를 통해 선택적 정확한 런타임을 설치합니다.
| 번들 | 크기 | 공유 의존성 그룹 | 사용하는 도구 |
|--------|------|-------------------------|-------------------|
@@ -61,7 +71,7 @@ Docker 이미지는 애플리케이션과 공통 런타임을 함께 제공한
| `object-eraser-colorize` | 1-2 GB | LaMa 인페인팅/아웃페인팅 및 DDColor | erase-object, colorize, ai-canvas-expand |
| `upscale-enhance` | 5-6 GB | RealESRGAN, GFPGAN / CodeFormer, 노이즈 제거 | upscale, enhance-faces, noise-removal |
| `photo-restoration` | 4-5 GB | 스크래치 복구 및 복원 파이프라인 | restore-photo |
| `ocr` | 5-6 GB | PaddleOCR / Tesseract OCR 스택 | ocr, ocr-pdf |
| `ocr` | ~208-234 MiB 다운로드 / ~409-488 MiB 설치됨 | 옵션 RapidOCR 3.9.1, ONNX Runtime 1.20.1 및 고정형 PP-OCR 모델 | ocr, ocr-pdf(`balanced``best`에만 해당) |
| `transcription` | ~600 MB | faster-whisper 음성-텍스트 변환 모델 | transcribe-audio, auto-subtitles |
교차 번들 의존성을 갖는 도구:
@@ -71,7 +81,17 @@ Docker 이미지는 애플리케이션과 공통 런타임을 함께 제공한
| `passport-photo` | `background-removal`, `face-detection` | 배경을 제거한 뒤, 얼굴 랜드마크를 사용해 여권 및 신분증 사진 규정에 맞게 크롭 구도를 잡는다. |
| `enhance-faces` | `upscale-enhance`, `face-detection` | 선택된 얼굴 영역에 GFPGAN 또는 CodeFormer 보정을 적용하기 전에 얼굴을 감지한다. |
도구는 필요한 모든 번들이 설치되어 있을 때만 사용할 수 있다. 부분 설치 유효하며 점진적으로 처리다. 설치된 번들은 재사용되고, 누락된 번들은 다운로드로 표시되며, 대기 중인 설치는 한 번에 하나씩 실행되 공유 Python 환경이 동시에 수정되지 않도록 한다.
도구는 OCR 를 제외하고 모든 필수 번들이 설치된 경우에만 사용할 수 있습니다. 내장된 `fast` 계층은 선택적 OCR 팩 없이도 계속 사용할 수 있습니다. 부분 설치 유효하며 증분적으로 처리됩니다. 설치된 번들은 재사용되고, 누락된 번들은 다운로드로 표시되며, 대기 중인 설치는 한 번에 하나씩 실행되므로 공유 Python 환경이 동시에 수정되지 않습니다.
### 정확한 OCR 런타임 설치 {#accurate-ocr-runtime-installation}
정확한 OCR 팩은 공식 Linux amd64 또는 Linux arm64 컨테이너를 위한 플랫폼별 런타임입니다. amd64 빌드는 Python 3.12를 사용하고 arm64 빌드는 Python 3.11을 사용합니다. 두 빌드 모두 ONNX Runtime의 `CPUExecutionProvider`를 통해 RapidOCR를 실행하므로 동일한 팩이 CPU 전용 및 NVIDIA Docker 호스트에서 작동합니다. 정확한 런타임에는 최소 4 GiB의 유효 메모리(구성된 컨테이너 cgroup 제한, 없으면 호스트 메모리)가 필요합니다. 서명된 호환성 최소값 미만의 시스템은 다운로드 전에 거부됩니다. 이 요구 사항은 내장 Fast OCR에는 적용되지 않습니다. Bare-metal 빌드는 libc 및 Python ABI를 안전하게 추론할 수 없으므로 거부됩니다. 호스트가 Tesseract와 Ghostscript를 제공하면 Fast OCR는 계속 사용할 수 있습니다.
선택적 아티팩트는 아키텍처에 따라 약 208-234 MiB 압축 및 409-488 MiB 추출입니다. 서명된 인덱스는 설치 프로그램에서 적용한 정확한 압축 및 추출 바이트 수를 바인딩합니다. 내장된 Tesseract 는 공식 이미지에 약 25개의 MiB 를 추가하며 `/data/ai`에는 파일이 필요하지 않습니다.
온라인 설치는 현재 플랫폼에 대한 서명된 릴리스 색인과 정확한 콘텐츠 주소 지정 아티팩트를 가져옵니다. SnapOtter 는 새로운 세대를 원자적으로 활성화하기 전에 Ed25519 인덱스 서명, 아티팩트 크기, SHA-256 다이제스트, 모델 다이제스트, 경로, 파일 모드 및 스테이지된 smoke test 를 확인합니다. 설치가 실패하면 이전 정상 세대가 활성 상태로 유지됩니다.
에어갭 설치의 경우 `index``archive`라는 다중 부분 필드를 사용하여 릴리스의 `ocr-runtime-index.json` 및 일치하는 OCR 런타임 아카이브를 모두 `POST /api/v1/admin/features/import`에 업로드합니다. 오프라인 가져오기는 온라인 설치와 동일한 서명, 해시, 추출, 호환성 및 스모크 테스트 검사를 적용합니다. 신뢰할 수 있는 서명된 인덱스가 없는 아카이브는 거부됩니다.
---
@@ -143,16 +163,16 @@ Docker 이미지는 애플리케이션과 공통 런타임을 함께 제공한
## OCR / 텍스트 추출 {#ocr-text-extraction}
**도구 경로:** `ocr`
**모델:** Tesseract (빠름), PaddleOCR PP-OCRv5 (균형), PaddleOCR-VL 1.5 (최상)
**모델:** Tesseract(`fast`); RapidOCR(PP-OCRv6 소형 모델 포함)(`balanced`); 보정된 변형 점수가 포함된 PP-OCRv6 중형 모델(`best`)
| 매개변수 | 타입 | 기본값 | 설명 |
|-----------|------|---------|-------------|
| `quality` | `"fast"` \| `"balanced"` \| `"best"` | `"balanced"` | 처리 등급 |
| `quality` | `"fast"` \| `"balanced"` \| `"best"` | 동적 | `quality``engine`을 생략하면 SnapOtter는 `best`, `balanced`, `fast` 순으로 사용 가능한 최상위 등급을 선택합니다. 한국어에서는 `fast`를 선택하지 않으며 `best`, 그다음 `balanced`를 사용하고, 둘 다 없으면 정확한 런타임의 설치 또는 호환성 오류를 반환합니다. |
| `language` | string | `"auto"` | 언어: `auto`, `en`, `de`, `fr`, `es`, `zh`, `ja`, `ko` |
| `enhance` | boolean | `true` | OCR 정확도 향상을 위해 이미지 사전 처리 |
| `engine` | string | - | 사용 중단됨. `tesseract` `fast`로, `paddleocr``balanced` 매핑 |
| `enhance` | 부울 | 계층에 따라 다름 | 로컬 대비를 향상시킵니다. 빠르게 직접 적용합니다. 정확한 계층은 보정된 점수가 OCR 를 향상시키는 경우에만 변형을 유지합니다. 최고에 대한 기본값은 켜져 있습니다. |
| `engine` | | - | 더 이상 사용되지 않는 호환성 별칭입니다. `tesseract` `fast`에 매핑하고 레거시 `paddleocr``balanced` 매핑합니다. PaddlePaddle 를 로드하지 않습니다. |
경계 상자, 신뢰도 점수, 추출된 텍스트 블록을 포함한 구조화된 결과를 반환한다.
추출된 텍스트와 출처 메타데이터(엔진, 요청 및 실제 품질, 장치, 공급자, 성능 저하 상태, 경고, 해당되는 경우 정확한 런타임/모델 버전)를 반환합니다. 명시적인 품질 요청은 다른 계층으로 돌아가지 않습니다. `balanced` 또는 `best`를 사용할 수 없는 경우 API 는 `fast`를 자동으로 실행하는 대신 `FEATURE_NOT_INSTALLED` 또는 `FEATURE_INCOMPATIBLE`를 반환합니다.
## PDF OCR {#pdf-ocr}
@@ -163,9 +183,13 @@ AI 기반 OCR을 사용해 스캔된 PDF 문서에서 페이지별로 텍스트
| 매개변수 | 타입 | 기본값 | 설명 |
|-----------|------|---------|-------------|
| `quality` | `"fast"` \| `"balanced"` \| `"best"` | `"balanced"` | 처리 등급 |
| `quality` | `"fast"` \| `"balanced"` \| `"best"` | 동적 | `quality``engine`을 생략하면 SnapOtter는 `best`, `balanced`, `fast` 순으로 사용 가능한 최상위 등급을 선택합니다. 한국어에서는 `fast`를 선택하지 않으며 `best`, 그다음 `balanced`를 사용하고, 둘 다 없으면 정확한 런타임의 설치 또는 호환성 오류를 반환합니다. |
| `language` | string | `"auto"` | 언어: `auto`, `en`, `de`, `fr`, `es`, `zh`, `ja`, `ko` |
| `pages` | string | `"all"` | 페이지 선택: `"all"`, `"1-3"`, `"1,3,5"` |
| `enhance` | 부울 | 계층에 따라 다름 | 로컬 대비를 향상시킵니다. 빠르게 직접 적용합니다. 정확한 계층은 보정된 점수가 OCR 를 향상시키는 경우에만 변형을 유지합니다. 최고에 대한 기본값은 켜져 있습니다. |
| `engine` | 끈 | - | 더 이상 사용되지 않는 호환성 별칭입니다. `tesseract``fast`에 매핑하고 레거시 `paddleocr` 값을 `balanced`에 매핑합니다. PaddlePaddle 를 로드하지 않습니다. |
PDF OCR 에도 동일한 다운그레이드 금지 규칙이 적용됩니다. PDF 페이지는 인식되기 전에 래스터화되며, 한 요청으로 최대 50페이지를 선택할 수 있습니다.
## 얼굴 / PII 블러 {#face-pii-blur}
+20 -5
View File
@@ -1,8 +1,8 @@
---
description: "전체 REST API 레퍼런스. 도구 엔드포인트, 배치 처리, 파이프라인, 파일 라이브러리, 인증, 팀, 관리 작업."
i18n_source_hash: 8646977f7cc9
i18n_provenance: machine
i18n_output_hash: a4289adc1b56
i18n_source_hash: b89b5df16af5
i18n_provenance: human
---
# REST API 레퍼런스 {#rest-api-reference}
@@ -178,7 +178,7 @@ curl -X POST http://localhost:1349/api/v1/tools/<section>/<toolId>/batch \
| `remove-background` | 배경 제거 | rembg(BiRefNet / U2-Net) | `model`, `backgroundType`(transparent/color/gradient/blur/image), `backgroundColor`, `gradientColor1`, `gradientColor2`, `gradientAngle`, `blurEnabled`, `blurIntensity`, `shadowEnabled`, `shadowOpacity` |
| `upscale` | 이미지 업스케일 | RealESRGAN | `scale`(2/4), `model`, `faceEnhance`, `denoise`, `format`, `quality` |
| `erase-object` | 오브젝트 지우개 | LaMa(ONNX) | 마스크는 두 번째 파일 파트로 전송(필드명 `mask`), `format`, `quality` |
| `ocr` | OCR / 텍스트 추출 | PaddleOCR / Tesseract | `quality`(fast/balanced/best), `language`, `enhance` |
| `ocr` | OCR / 텍스트 추출 | Tesseract(빠름); RapidOCR + PP-OCR ONNX(균형 잡힌/최고) | `quality`(빠름/균형/최고), `language`, `enhance` |
| `blur-faces` | 얼굴 / PII 블러 | MediaPipe | `blurRadius`, `sensitivity` |
| `smart-crop` | 스마트 자르기 | MediaPipe + Sharp | `mode`(subject/face/trim), `strategy`(attention/entropy), `width`, `height`, `padding`, `facePreset`(closeup/head-shoulders/upper-body/half-body), `sensitivity`, `threshold`, `padToSquare`, `padColor`, `targetSize`, `quality` |
| `image-enhancement` | 이미지 향상 | 분석 기반 | `mode`(auto/exposure/contrast/color/sharpness), `strength` |
@@ -425,7 +425,9 @@ curl -X POST http://localhost:1349/api/v1/tools/image/html-to-image \
## 배치 처리 {#batch-processing}
제네릭 배치 지원 도구를 여러 파일에 한 번에 적용합니다. ZIP 아카이브를 반환합니다. PDF 서명, PDF OCR, PDF를 이미지로 변환하는 프리셋 경로와 같은 커스텀 다중 파일 또는 다단계 경로는 제네릭 `/batch` 경로 대신 자체 엔드포인트 계약을 사용합니다.
제네릭 배치 지원 도구를 여러 파일에 한 번에 적용합니다. ZIP 아카이브를 반환합니다. PDF 서명 PDF를 이미지로 변환하는 프리셋 경로와 같은 커스텀 다중 파일 또는 다단계 경로는 제네릭 `/batch` 경로 대신 자체 엔드포인트 계약을 사용합니다.
`ocr-pdf` 도구는 이 제네릭 `/batch` 경로를 지원합니다.
```bash
curl -X POST http://localhost:1349/api/v1/tools/image/compress/batch \
@@ -594,6 +596,8 @@ data: {"jobId":"...","type":"batch","status":"processing","completedFiles":2,"to
AI 기능 번들 관리(Docker 환경에서 AI 모델 패키지 설치/제거). 커스텀 자동화에서 도구를 활성화할 때는 도구 수준 설치 엔드포인트를 선호하세요: 일부 AI 도구는 둘 이상의 공유 번들이 필요하며, 이 엔드포인트는 이미 설치된 번들을 건너뛰고 누락된 번들만 큐에 넣습니다.
OCR 는 하드 종속성이 아닌 선택적 향상 기능입니다. `fast` Tesseract 계층은 팩 없이 작동합니다. `POST /api/v1/admin/features/ocr/install``balanced``best`에 대해 서명된 RapidOCR 팩을 Linux amd64 또는 arm64 에 설치합니다. 정확한 OCR 런타임은 CPU 전용 및 NVIDIA 호스트에서 CPU 를 사용하며 최소 4 GiB 의 유효 메모리(구성된 컨테이너 cgroup 제한, 그렇지 않으면 호스트 메모리)가 필요합니다. SnapOtter 는 `requiredMemoryBytes`, `effectiveMemoryBytes``insufficient-memory` 호환성 이유를 보고하고 다운로드하기 전에 호환되지 않는 설치를 거부합니다. 이 메모리 요구 사항은 `fast`에는 적용되지 않습니다. 팩은 대상에 따라 약 208-234 MiB 를 다운로드하고 409-488 MiB 를 설치합니다. 서명된 인덱스는 설치 중에 적용된 정확한 크기를 바인딩합니다.
| 메서드 | 경로 | 접근 권한 | 설명 |
|--------|------|--------|-------------|
| `GET` | `/api/v1/features` | 인증 | 모든 기능 번들과 설치 상태 목록 |
@@ -601,7 +605,18 @@ AI 기능 번들 관리(Docker 환경에서 AI 모델 패키지 설치/제거).
| `POST` | `/api/v1/admin/tools/:toolId/features/install` | 관리자(`features:manage`) | 도구에 필요한 모든 번들 설치; 번들별 큐잉/건너뜀 상태 반환 |
| `POST` | `/api/v1/admin/features/:bundleId/uninstall` | 관리자(`features:manage`) | 기능 번들 제거 및 모델 파일 정리 |
| `GET` | `/api/v1/admin/features/disk-usage` | 관리자(`features:manage`) | AI 모델의 총 디스크 사용량 획득 |
| `POST` | `/api/v1/admin/features/import` | 관리자(`features:manage`) | 오프라인 AI 번들 아카이브 가져오기 |
| `POST` | `/api/v1/admin/features/import` | 관리자(`features:manage`) | 레거시 AI 번들(`file`) 또는 서명된 오프라인 OCR 릴리스(`index` + `archive`) 가져오기 |
에어 갭 OCR 가져오기에는 릴리스의 서명이 포함되어야 합니다. `ocr-runtime-index.json` 그리고 일치하는 플랫폼 아카이브. SnapOtter 동일하게 적용됩니다 Ed25519 서명, 아티팩트 해시, 호환성, 추출, 온라인 설치에 사용되는 연기 테스트 검사:
```bash
curl -X POST http://localhost:1349/api/v1/admin/features/import \
-H "Authorization: Bearer <admin-token>" \
-F "index=@ocr-runtime-index.json" \
-F "archive=@ocr-linux-amd64-cpu-py312.tar.gz"
```
사용 `linux-arm64-cpu-py311` 에 보관 arm64. 다른 대상에 대해 서명된 아티팩트는 설치되지 않고 거부됩니다.
## 관리 작업 {#admin-operations}