67 lines
2.8 KiB
Markdown
67 lines
2.8 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project overview
|
|
|
|
A two-component photo booth system running on Raspberry Pi:
|
|
|
|
1. **`camera/`** — Python/Flask camera server using `picamera2` (Raspberry Pi HQ Camera M12). Streams live MJPEG video and exposes a `/capture` endpoint that saves JPEG snapshots to `camera/photos/`.
|
|
2. **`ImmichUploader/`** — Laravel 13 PHP application that watches `camera/photos/` via `inotify`, and uploads new photos to a self-hosted [Immich](https://immich.app) instance via its HTTP API, then adds each asset to a specific album.
|
|
|
|
## Running the camera server
|
|
|
|
```bash
|
|
cd camera
|
|
python main.py
|
|
```
|
|
|
|
The server listens on port 5000 on all interfaces. Endpoints:
|
|
- `GET /` — live MJPEG stream viewer
|
|
- `GET /video_feed` — raw MJPEG stream
|
|
- `GET /capture` — saves current frame to `camera/photos/` and returns JSON
|
|
|
|
## Running the ImmichUploader
|
|
|
|
```bash
|
|
cd ImmichUploader
|
|
composer run setup # first-time: installs deps, generates key, runs migrations
|
|
composer run dev # starts all services: web server + queue worker + log viewer + vite
|
|
```
|
|
|
|
Or run the folder watcher and queue worker individually:
|
|
```bash
|
|
php artisan immich:watch-folder # watches FOLDER_PATH via inotify, dispatches jobs
|
|
php artisan queue:listen --tries=1 --timeout=0 # processes SendToImmichJob
|
|
```
|
|
|
|
Run tests:
|
|
```bash
|
|
composer run test
|
|
```
|
|
|
|
## Environment variables
|
|
|
|
**`ImmichUploader/.env`** (not the root `.env`):
|
|
- `IMMICH_URL` — base URL of the Immich instance (e.g. `https://photos.example.com`)
|
|
- `IMMICH_KEY` — Immich API key
|
|
- `FOLDER_PATH` — absolute path to the photos directory (matches `camera/photos/`)
|
|
|
|
The root `.env` is gitignored and only excluded `camera/photos` from tracking.
|
|
|
|
## Architecture notes
|
|
|
|
**Camera → Uploader flow:**
|
|
1. `camera/main.py` writes a JPEG to `camera/photos/<timestamp>.jpg` on `/capture`
|
|
2. `WatchFolder` artisan command (`inotify_add_watch` on `IN_CLOSE_WRITE | IN_MOVED_TO`) detects the new file
|
|
3. Dispatches `SendToImmichJob` to the database queue
|
|
4. The queue worker runs `SendToImmichJob::handle()` which POSTs the image to `/api/assets` then adds it to the hardcoded album via `PUT /api/albums/{albumId}/assets`
|
|
|
|
**Hardcoded values in `SendToImmichJob.php`:**
|
|
- `$albumId` — Immich album ID where photos are added
|
|
- `$id` (deviceAssetId) — fixed UUID used as the Immich device asset identifier
|
|
|
|
**`camera/` directory structure:** The `camera/` directory is itself a Python venv (has `pyvenv.cfg`), but the actual venv used by the app is `camera/myenv/` (contains Flask). `picamera2` is available from the system Python installation.
|
|
|
|
**ImmichUploader** uses SQLite (default, `database/database.sqlite`) for the queue, cache, and sessions — no separate database process needed.
|