diff --git a/FAQ.md b/FAQ.md new file mode 100644 index 0000000..03dc205 --- /dev/null +++ b/FAQ.md @@ -0,0 +1,63 @@ +# FAQ + +## Does winnow modify my Immich library? + +No. winnow only reads from Immich (assets, people, face bounding boxes). It never writes back to Immich or deletes anything. + +--- + +## How many images should I upload to Frigate? + +The `auto` strategy decides this for you — it keeps selecting until adding more images would be redundant. In practice this is usually 20–60 per person. You can cap it with `MAX_AUTO_IMAGES` (default 80). + +Quality and diversity matter far more than volume. 30 well-spread images outperform 200 from the same week. + +--- + +## What's the difference between face mode and object mode? + +- **Face mode**: Extracts and aligns face crops, uploads them directly to Frigate's face training API. This is for teaching Frigate to recognize specific people. +- **Object mode**: Runs YOLO detection on full images and saves crops of a target class (dog, cat, car, etc.) to disk. Frigate has no API for object training data, so you place them manually. + +--- + +## Can I run it without Frigate? + +Yes — in object mode, `FRIGATE_URL` is not used and crops are saved to the output volume. In face mode you need Frigate to receive the uploads, but you can use `DRY_RUN=true` to preview selection without uploading. + +--- + +## How does auto-diversity mode work? + +winnow computes a vector embedding for each candidate image (what the face/object actually looks like — angle, lighting, expression). It then clusters those embeddings and picks representatives that are maximally spread across the embedding space. It stops when the next-most-different image is already close to something already selected. See the README for the full pipeline. + +--- + +## Does it support multiple people in one run? + +Yes. By default it processes every named person in your Immich library. Use `ONLY_PEOPLE` to whitelist specific names or `SKIP_PEOPLE` to exclude them. + +--- + +## What GPU is needed? + +Any NVIDIA GPU with CUDA 12.x support. The models (InsightFace Buffalo_L + SigLIP) fit comfortably in 4 GB VRAM. CPU mode works but is significantly slower. + +ARM builds (linux/arm64) use CPU-only — CUDA is not available on ARM. + +--- + +## Does it work on Unraid / Proxmox / bare Docker? + +Yes — the `compose.yml` uses standard Docker volume mounts. Replace the example paths with whatever absolute paths suit your setup. + +--- + +## How do I update winnow? + +```bash +docker compose pull +docker compose up -d +``` + +The `latest` tag on GHCR tracks the `main` branch. Pinning to a version tag (e.g. `ghcr.io/sudolulo/winnow:v0.2.0`) is recommended for stability. diff --git a/Home.md b/Home.md index ab696f9..e6c18b5 100644 --- a/Home.md +++ b/Home.md @@ -1 +1,18 @@ -Welcome to the winnow wiki! +# winnow + +winnow pulls photos from [Immich](https://immich.app), selects diverse high-quality subsets using AI embeddings, and uploads them as face recognition training data to [Frigate](https://frigate.video). + +It runs fully headless in Docker, is configured entirely through environment variables, and can run on a schedule. + +## Pages + +- [[Setup]] — installation, Docker Compose configuration, GPU passthrough, environment variables +- [[Troubleshooting]] — common failures and fixes +- [[FAQ]] — frequently asked questions + +## Quick Links + +- [GitHub Repository](https://github.com/sudolulo/winnow) +- [CHANGELOG](https://github.com/sudolulo/winnow/blob/main/CHANGELOG.md) +- [compose.yml](https://github.com/sudolulo/winnow/blob/main/compose.yml) +- [.env.example](https://github.com/sudolulo/winnow/blob/main/.env.example) diff --git a/Setup.md b/Setup.md new file mode 100644 index 0000000..c0dc64c --- /dev/null +++ b/Setup.md @@ -0,0 +1,95 @@ +# Setup Guide + +## Prerequisites + +- [Immich](https://immich.app) v1.106+ with face recognition enabled and people tagged +- [Frigate](https://frigate.video) v0.16+ (face mode only) +- Docker with the NVIDIA container toolkit (optional but strongly recommended) + +--- + +## 1. Get your Immich API key + +1. Open Immich → **Account Settings** → **API Keys** +2. Click **New API Key**, give it a name (e.g. `winnow`), copy the key + +--- + +## 2. Get your Frigate URL + +This is the base URL of your Frigate instance, e.g. `http://192.168.1.10:5000`. Only needed for face mode — omit it entirely if you're using object mode. + +--- + +## 3. Deploy with Docker Compose + +Copy [`compose.yml`](../compose.yml) and [`.env.example`](../.env.example) to a directory on your host: + +```bash +mkdir winnow && cd winnow +curl -O https://raw.githubusercontent.com/sudolulo/winnow/main/compose.yml +curl -O https://raw.githubusercontent.com/sudolulo/winnow/main/.env.example +cp .env.example .env +``` + +Edit `.env` with your values: + +```bash +IMMICH_URL=http://192.168.1.10:2283 +API_KEY=your-immich-api-key +FRIGATE_URL=http://192.168.1.10:5000 +``` + +Edit the volume paths in `compose.yml` to point to directories on your host where models, cache, and output crops should be stored: + +```yaml +volumes: + - /your/path/to/models:/models + - /your/path/to/cache:/app/.if_cache + - /your/path/to/output:/app/frigate_train +``` + +These directories will be created automatically by Docker if they don't exist. + +Start it: + +```bash +docker compose up -d +``` + +Logs: + +```bash +docker compose logs -f winnow +``` + +--- + +## 4. First run + +On the first run, winnow downloads the embedding models (~1–2 GB) from HuggingFace and InsightFace. This happens once — subsequent runs use the cached models from your mounted volume and start immediately. + +--- + +## 5. Scheduling + +Set `CRON_SCHEDULE` in your `.env` to keep winnow running on a schedule: + +``` +CRON_SCHEDULE=0 3 * * 0 # Every Sunday at 3 AM +``` + +Without `CRON_SCHEDULE`, the container runs once and exits. + +--- + +## GPU passthrough + +To enable GPU acceleration, include the `deploy` block in `compose.yml` (already present in the example) and ensure the NVIDIA container toolkit is installed on your host: + +```bash +# Verify GPU is accessible to Docker +docker run --rm --gpus all nvidia/cuda:12.9.2-base-ubuntu22.04 nvidia-smi +``` + +CPU mode works without any GPU setup — set `FORCE_CPU=true` to disable GPU explicitly. diff --git a/Troubleshooting.md b/Troubleshooting.md new file mode 100644 index 0000000..4e391f4 --- /dev/null +++ b/Troubleshooting.md @@ -0,0 +1,77 @@ +# Troubleshooting + +## Container exits immediately + +Check logs: +```bash +docker compose logs winnow +``` + +Common causes: +- **Missing required env var** — `IMMICH_URL` or `API_KEY` not set +- **Cannot reach Immich** — check the URL and that Immich is running; use `http://` not `https://` unless you have TLS set up + +--- + +## "No people found" / nothing processed + +- Make sure Immich has completed face recognition and you have named people in your library +- `YEARS_FILTER` defaults to 10 years — increase it if your tagged photos are older +- `MIN_FACE_COUNT` skips people with few photos — lower or remove it + +--- + +## Frigate upload fails + +- Confirm `FRIGATE_URL` is reachable from inside the container: `docker exec winnow curl $FRIGATE_URL/api/stats` +- Check Frigate v0.16+ — older versions don't have the face training API +- Set `DRY_RUN=true` to verify selection without uploading + +--- + +## Models fail to download + +winnow downloads InsightFace and HuggingFace (SigLIP) models on first run. + +- Ensure the container has internet access +- Confirm the model volume is mounted and writable +- If behind a proxy, set `HTTP_PROXY` / `HTTPS_PROXY` env vars + +--- + +## Running on CPU (no GPU) + +Set `FORCE_CPU=true`. Everything works but embedding computation is slower — expect several minutes per person instead of seconds. + +If you have a GPU but it's not being used: +- Confirm the NVIDIA container toolkit is installed: `docker run --rm --gpus all nvidia/cuda:12.9.2-base-ubuntu22.04 nvidia-smi` +- Confirm the `deploy.resources.reservations.devices` block is present in `compose.yml` + +--- + +## Same images uploaded every run + +The upload tracker is stored in `CACHE_DIR` (`/app/.if_cache` by default). If this volume isn't persisted between runs, the tracker resets and images are re-uploaded. + +Make sure `/app/.if_cache` is mounted to a persistent host path. + +--- + +## Re-uploading a specific person + +To clear the upload history for one person and start fresh: + +```env +RESET_PERSON=John +``` + +Remove this after one run — it clears the history and then processes normally. + +--- + +## Image quality issues + +- **Too blurry**: Lower `BLUR_THRESHOLD` (default 100) — e.g. `50` accepts more blur +- **Face too small**: Lower `MIN_FACE_WIDTH` (default 50px) +- **Low confidence detections included**: Raise `MIN_CONFIDENCE` (default 0.7) +- **Rejected images being re-tried**: Set `RETRY_REJECTED=true` for one run