📸 photo-pipeline

Overview Review queue Pipeline Upload How To

What this system does

An automated photo ingestion pipeline: it downloads Google Takeout exports, fingerprints every image (deduplication), audits quality (blurry/dark/etc), and imports approved photos into your Immich library — with notifications and a review dashboard at every step.

Core safety rule: nothing is ever deleted automatically. Rejected photos go to a holding folder (03_delete) and stay there until you confirm.

The pipeline at a glance

StepFlowWhat happens
1. Export— (manual)You create a Google Takeout export
2. Feedupload / scpDrop manifest or archives into incoming/
3. Fetchtakeout-fetchDownloads archives (resumable), tracks them, extracts
4. Ingestphoto-ingestHashes every file, flags exact + near duplicates
5. Qualityphoto-quality-scanCleanVision flags blurry/dark/odd images
6. NotifyAppriseYou get a message with counts + dashboard link
7. Reviewthis dashboardYou Keep or Reject images in the review queue
8. Stageprocess-stagingApproved → 01_keep, Rejected → 03_delete
9. Importimmich-importApproved photos uploaded to Immich

How to add photos — 4 ways

A. From Google Takeout (bulk)

  1. Go to takeout.google.com and create an export (Photos, batched by year so each archive is <10GB). Google has no API for this — it's the one manual step.
  2. When it's ready, copy the download URLs into a text file (one per line) — call it urls.txt.
  3. Drop it in incoming/ — via the Upload page, or from a terminal: scp urls.txt sam@100.114.62.46:/mnt/data/takeout/incoming/ (Tailscale IP).
  4. The watch flow picks it up within 15 minutes and runs the whole pipeline. You get an Apprise notification with results.

B. An already-downloaded archive

If you already have Takeout archives (.zip/.tgz), drop them in incoming/ the same way. The pipeline extracts and processes them.

C. A folder already on .13 (like your archive)

For folders already on the server (e.g. archive/03_photos), run the ingest flow directly — it scans in batches (1000 at a time) with checkpoints, so it's safe to interrupt:

export PREFECT_API_URL=http://localhost:4200/api
~/photo-pipeline/.venv/bin/prefect deployment run "photo-ingest/ingest" \
  --param base_dir=/mnt/ubuntu_storage_3TB/archive/03_photos/Pictures \
  --param source=archive-pictures --param batch_size=1000

D. From your phone

Install the Immich app on your phone and enable auto-backup — photos upload straight to your Immich library, bypassing Google entirely. This is the recommended phone path.

How to review

  1. Open the Review queue. It shows 200 images per page, newest first.
  2. Click a photo to see it full-size (opens in a new tab).
  3. Keep = approved for Immich. Reject = moves to the delete-holding folder. = undo back to unscanned.
  4. Use the checkbox + Select all + Bulk Keep/Reject for large batches.
  5. Filter by status or source with the controls above the grid.
  6. Track progress on the Pipeline page (auto-refreshes every 30s).
Remember: review decisions are instant DB updates. Files physically move only when the process-staging flow runs. Nothing is deleted without your explicit confirmation.

How to check on work

Common operations

Run a flow manually

export PREFECT_API_URL=http://localhost:4200/api
~/photo-pipeline/.venv/bin/prefect deployment run "photo-watch/watch"

Replace photo-watch/watch with any deployment name: takeout-fetch/fetch, photo-ingest/ingest, photo-quality-scan/quality, process-staging/staging, immich-import/import.

Restart the dashboard

systemctl --user restart photo-dashboard.service

See recent actions

Open the Pipeline page — the lower table shows your last 20 review decisions.

How it's built (for the curious)

Prefect 3 orchestrates everything on photo-pool; a SQLite database (photo_pipeline.db) is the source of truth for every image's hash, path and status. imagehash detects duplicates (exact sha256 + perceptual phash/dhash), CleanVision audits quality, FastAPI+htmx powers this dashboard, and Apprise sends notifications. Everything runs on your .13 server as Docker + systemd services. Code lives in the photo-pipeline repo on your Gitea.