Files
SnapOtter/apps/docs/zh-TW/guide/low-resource.md
T
SnapOtterandGitHub d10d0f544f fix: release QA hardening across processing, media, security, and CI gates (#649)
A release-readiness QA pass over the whole product. The commits split into
defects a user would hit and gates that were reporting green while measuring
nothing.

## Fixes that change behaviour

Rate limiting was bypassable on every install: TRUST_PROXY defaulted to true, so
request.ip came from a client-set header and a forged X-Forwarded-For got past
the login limiter. The default is now a private-network trust list.

A transient Postgres outage stranded in-flight jobs, leaving finished output on
disk with no row pointing at it. A reconciler now resolves those rows and adopts
the bytes rather than dropping the work.

A Redis connection that moved to a new address wedged every read-blocked
consumer, so completions stopped signalling while health still answered 200.
Socket timeouts plus subscriber pings recover it.

Installing more than one AI bundle left the shared venv multi-versioned and
silently broke three tools. The installer now reconciles distributions to one
version each.

Converting an image to JXL at quality 1 through 4 returned a 500, because
libjxl 0.7 rejects the distance those values compute. The quality is floored at
what the encoder honours. A missing ffmpeg was also reported to the user as a
corrupt upload; it now says the engine is unavailable.

RAW uploads reached an unpatched LibRaw on arm64, so it is built from source at
0.22.2, and the release scan was split so it can fail on an unfixed critical
instead of hiding it behind ignore-unfixed.

## Gates that could not fail

Two mutation lanes ran zero mutants because Stryker crawled the gitignored docs
build; coverage discarded its whole report on any failing test; the lint gate
skipped root tests, scripts, and two workspaces; and several generated matrices
counted a host missing ffmpeg as a passing tool. Each now measures what it
claims.

Full evidence and the outstanding release items are tracked locally and are not
part of this branch.
2026-07-27 15:37:30 +08:00

6.2 KiB
Raw Blame History

i18n_source_hash, i18n_provenance, i18n_output_hash, i18n_hash_version
i18n_source_hash i18n_provenance i18n_output_hash i18n_hash_version
521c03a6416c machine 26499f05dc2f 2

低資源環境部署

SnapOtter 在小型硬體上運作良好:Raspberry Pi 4 或 5、一台舊筆電,或一台 2 GB 的 VPS。本頁是針對這些機器的實用指南:該有什麼預期、一套可直接複製貼上且帶有合理上限的設定,以及哪些功能應該略過。這些數字背後完整的效能測試資料見硬體需求

先說兩個硬性限制:

  • **僅限 64 位元。**映像檔只為 linux/amd64linux/arm64 建置。不支援 32 位元 ARMarmv7/armhf),因此第一代 Pi 和 Pi Zero 系列不在支援範圍內。
  • **記憶體下限 2 GB。**512 MB 無法啟動整個堆疊,1 GB 在多檔案批次時會失敗。2 GB 加 2 核心是能舒適運作的最小組態。

小型硬體上哪些功能運作良好

所有非 AI 工具都能在 2 GB / 2 核心的機器上運作:整個「影像」與「檔案」區塊、PDF 工具,以及串流複製類的影片和音訊操作(剪輯、靜音、更換容器)。大多數在一秒內完成。

有兩類工作負載是例外:

  • 影片重新編碼(在不同編解碼器之間轉換)受 CPU 限制。一段在高速桌面 CPU 上約 40 秒完成的 1080p 影片,在 Pi 等級的 CPU 上可能需要數分鐘。串流複製操作仍然是即時的。
  • AI 工具需要記憶體(建議 4 GB)和磁碟空間(較大的套件組每個 4-5 GB),其中重型工具(放大、照片修復、背景移除)在 Pi 等級的 CPU 上並不實用。臉部偵測和 OCR 這類輕量 AI 在記憶體足夠時仍可使用。

這兩類負載在你用到之前既不會安裝也不會執行:未安裝任何 AI 套件組時,應用程式閒置時的記憶體佔用約 360 MB,而 AI 套件組只有在管理員啟用時才會下載。

Raspberry Pi / 舊筆電實作教學

這就是快速上手中的標準 Compose 安裝,外加資源限制和保守的上限。它假設使用 64 位元作業系統(在 Pi 上:Raspberry Pi OS 64 位元或 Ubuntu Server arm64)。

services:
  snapotter:
    image: snapotter/snapotter:latest
    ports:
      - "1349:1349"
    volumes:
      - ./snapotter-data:/data
    environment:
      - DATABASE_URL=postgres://snapotter:snapotter@db:5432/snapotter
      - REDIS_URL=redis://redis:6379
      # Small-box profile: see the table below for what each cap does.
      - CONCURRENT_JOBS=1
      - MAX_WORKER_THREADS=2
      - MAX_BATCH_SIZE=5
      - MAX_UPLOAD_SIZE_MB=100
      - MAX_MEGAPIXELS=50
      - MAX_VIDEO_DURATION_S=300
    deploy:
      resources:
        limits:
          cpus: "2"
          memory: 2G
    depends_on:
      - db
      - redis
    restart: unless-stopped

  db:
    image: postgres:17-alpine
    environment:
      - POSTGRES_USER=snapotter
      - POSTGRES_PASSWORD=snapotter     # 針對非本地部署更改此設置
      - POSTGRES_DB=snapotter
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
    restart: unless-stopped

  redis:
    image: redis:8-alpine
    command: redis-server --maxmemory 256mb --maxmemory-policy noeviction
    restart: unless-stopped

Pi 等級機器的注意事項:

  • **資料磁碟區和 Postgres 優先使用 USB SSD 而非 SD 卡。**工作區會產生實際的磁碟 IO,而 SD 卡既慢又容易耗損。
  • 一體式單一容器在這裡同樣適用(未設定 DATABASE_URL/REDIS_URL 時使用嵌入式 Postgres 和 Redis),在記憶體受限的主機上,應透過 REDIS_MAXMEMORY 調低其嵌入式 Redis 的記憶體上限(見設定)。Compose 提供更細緻的逐服務控制,這也是本教學採用它的原因。
  • **在 2 GB 裝置上加入 swap。**它能避免偶發的記憶體尖峰(一個大型 PDF、一個你忘了設上限的批次)以記憶體不足強制終止收場。zram 是對 SD 卡較友善的選擇。
  • arm64 映像檔僅支援 CPUARM 板上沒有 CUDA。

調校參數

所有上限都是環境變數,完整說明見設定0 表示不限制或自動。在小型硬體上重要的有這些:

變數 小型機器建議值 它保護什麼
CONCURRENT_JOBS 1 平行執行的工作數。自動偵測使用 CPU 核心數減一,在大機器上沒問題,但在記憶體吃緊的 2 核心機器上過於積極。
MAX_WORKER_THREADS 2 影像處理執行緒集區。
MAX_BATCH_SIZE 5 批次處理是 1-2 GB 機器最先耗盡記憶體的地方。
MAX_UPLOAD_SIZE_MB 100 防止單一巨大檔案佔滿整個工作區。
MAX_MEGAPIXELS 50 解碼一張 100+ MP 的影像無論檔案大小都要消耗記憶體。
MAX_VIDEO_DURATION_S 300 長時間轉檔會把小型 CPU 獨佔數分鐘到數小時。
PROCESSING_TIMEOUT_S 600 硬性上限,確保失控的工作最終會釋放機器。

這些上限規範的是伺服器接受什麼,所以請依你實際的用途設定,而不是越小越好。如果你從不處理影片,設定 MAX_VIDEO_DURATION_S 上限毫無代價;如果你每天掃描文件,就不要限制 MAX_PDF_PAGES

應該略過什麼

  • **重型 AI 套件組。**放大、照片修復和背景移除需要 GPU 或高速多核心 CPU,而且每個套件組要佔 4-5 GB 磁碟空間。在小型機器上,乾脆不要安裝它們;缺少對應套件組的工具會顯示安裝提示,而不會執行。
  • **把影片重新編碼當作例行負載。**偶爾轉檔沒有問題(只是慢);持續的轉檔佇列需要的是 CPU 核心,而不是一台 Pi。
  • **整體而言,用不到的工具。**管理員可以在 Settings 中關閉個別工具,這會將它們從 UI 中移除並停止註冊其 API 路由。這本身不會節省記憶體,但能避免一台共用的小型執行個體被拿去跑硬體唯一扛不住的那種負載。

如果之後把執行個體移到更強的硬體上,移除這些上限(改回 0),同一個資料磁碟區可以直接沿用。