feat: expose all interactive CLI options via env vars
- config.py: wire BLUR_THRESHOLD, MIN_CONFIDENCE, MAX_AUTO_IMAGES, FACE_MARGIN, USE_FULL_RESOLUTION, ENABLE_FACE_ALIGNMENT to env vars (were hardcoded class defaults, inaccessible in AUTO_MODE) - jobs.py: add LIMIT env var for custom image count in auto mode; overrides STRATEGY preset (mirrors interactive Custom Count option) - compose.yml: document all env vars with inline comments grouped by concern — mode/strategy, people filtering, image quality, caching, tracker overrides, scheduling Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+31
-10
@@ -3,27 +3,49 @@ services:
|
||||
image: ghcr.io/sudolulo/if-curator-headless:latest
|
||||
container_name: if-curator
|
||||
environment:
|
||||
# ── Required ──────────────────────────────────────────────────────────
|
||||
- IMMICH_URL=${IMMICH_URL}
|
||||
- API_KEY=${API_KEY}
|
||||
- AUTO_MODE=true
|
||||
- FRIGATE_URL=${FRIGATE_URL}
|
||||
|
||||
# ── Mode & Strategy ───────────────────────────────────────────────────
|
||||
- AUTO_MODE=true
|
||||
# TRAINING_MODE: face = upload to Frigate face recognition API
|
||||
# object = save crops to output dir for manual Frigate placement
|
||||
- TRAINING_MODE=face
|
||||
# STRATEGY: auto = objective diversity (recommended), standard = 30 imgs, broad = 100 imgs
|
||||
- STRATEGY=auto
|
||||
# - LIMIT=50 # Custom image count; overrides STRATEGY preset
|
||||
# - OBJECT_CLASS=dog # Object label for object mode (e.g. dog, cat, car)
|
||||
|
||||
# ── People Filtering ──────────────────────────────────────────────────
|
||||
# - ONLY_PEOPLE=John,Jane # Comma-separated; process only these people
|
||||
# - SKIP_PEOPLE=Unknown # Comma-separated; skip these people
|
||||
# - MIN_FACE_COUNT=5 # Skip people with fewer than N assets in Immich
|
||||
# - YEARS_FILTER=10 # Only include images from the last N years (default: 10)
|
||||
|
||||
# ── Image Quality ─────────────────────────────────────────────────────
|
||||
# - MIN_FACE_WIDTH=50 # Minimum face width in pixels (default: 50)
|
||||
# - FACE_MARGIN=0.15 # Padding around face crop as fraction (default: 0.15)
|
||||
# - ENABLE_FACE_ALIGNMENT=true # Align face before cropping (default: true)
|
||||
# - USE_FULL_RESOLUTION=true # Use full-res images vs thumbnails (default: true)
|
||||
# - MIN_CONFIDENCE=0.7 # Minimum face detection confidence (default: 0.7)
|
||||
# - BLUR_THRESHOLD=100.0 # Laplacian blur threshold; lower = accept more blur (default: 100.0)
|
||||
# - MAX_AUTO_IMAGES=80 # Hard cap on auto-diversity selection (default: 80)
|
||||
|
||||
# ── Caching & Models ──────────────────────────────────────────────────
|
||||
- FORCE_CPU=false
|
||||
- ENABLE_CACHE=true
|
||||
- CACHE_DIR=/app/.if_cache
|
||||
- HF_HOME=/models/huggingface
|
||||
- INSIGHTFACE_HOME=/models
|
||||
# - ONLY_PEOPLE=John,Jane
|
||||
# - SKIP_PEOPLE=Unknown
|
||||
# - MIN_FACE_COUNT=5
|
||||
|
||||
# ── Tracker overrides (one-shot, remove after use) ──
|
||||
# - DRY_RUN=true # Preview selection without downloading/uploading
|
||||
# - RETRY_REJECTED=true # Re-attempt previously rejected images
|
||||
# - RESET_PERSON=John # Clear uploaded+rejected history for one person
|
||||
# ── Tracker overrides (one-shot, remove after use) ────────────────────
|
||||
# - DRY_RUN=true # Preview selection without downloading/uploading
|
||||
# - RETRY_REJECTED=true # Re-attempt previously rejected images
|
||||
# - RESET_PERSON=John # Clear uploaded+rejected history for one person
|
||||
|
||||
# ── Scheduling ──
|
||||
# ── Scheduling ────────────────────────────────────────────────────────
|
||||
# Cron expression (unset = run once and exit)
|
||||
# Every Sunday at 3 AM:
|
||||
- CRON_SCHEDULE=0 3 * * 0
|
||||
@@ -44,4 +66,3 @@ services:
|
||||
- driver: nvidia
|
||||
count: all
|
||||
capabilities: [gpu]
|
||||
|
||||
|
||||
@@ -58,6 +58,12 @@ class _Config:
|
||||
self.YEARS_FILTER = int(os.getenv("YEARS_FILTER", "10"))
|
||||
self.MIN_FACE_WIDTH = int(os.getenv("MIN_FACE_WIDTH", "50"))
|
||||
self.MIN_FACE_COUNT = int(os.getenv("MIN_FACE_COUNT", "0"))
|
||||
self.BLUR_THRESHOLD = float(os.getenv("BLUR_THRESHOLD", "100.0"))
|
||||
self.MIN_CONFIDENCE = float(os.getenv("MIN_CONFIDENCE", "0.7"))
|
||||
self.MAX_AUTO_IMAGES = int(os.getenv("MAX_AUTO_IMAGES", "80"))
|
||||
self.FACE_MARGIN = float(os.getenv("FACE_MARGIN", "0.15"))
|
||||
self.USE_FULL_RESOLUTION = os.getenv("USE_FULL_RESOLUTION", "true").lower() in ("true", "1", "yes")
|
||||
self.ENABLE_FACE_ALIGNMENT = os.getenv("ENABLE_FACE_ALIGNMENT", "true").lower() in ("true", "1", "yes")
|
||||
self.ENABLE_CACHE = os.getenv("ENABLE_CACHE", "false").lower() in ("true", "1", "yes")
|
||||
self.CACHE_DIR = os.getenv("CACHE_DIR", ".if_cache")
|
||||
|
||||
|
||||
+7
-1
@@ -63,8 +63,14 @@ def _get_strategy_choice(has_embedding: bool, entity_type: str) -> tuple[int | s
|
||||
|
||||
def _resolve_strategy(strategy: str, has_embedding: bool) -> tuple[int | str, str]:
|
||||
"""Resolve env var strategy to (limit, selection_mode) without prompts."""
|
||||
custom_limit = os.environ.get("LIMIT", "").strip()
|
||||
|
||||
if not has_embedding:
|
||||
return 30, "time"
|
||||
limit = int(custom_limit) if custom_limit else 30
|
||||
return limit, "time"
|
||||
|
||||
if custom_limit:
|
||||
return int(custom_limit), "smart"
|
||||
|
||||
strategy_map = {
|
||||
"auto": ("auto", "smart"),
|
||||
|
||||
Reference in New Issue
Block a user