Automatic photo processing: Fuji X-H2 → FTP → Synology NAS → resize → Immich - PollingObserver watches /incoming/ for new JPEGs - Moves originals to /originals/YYYY/MM/ - Creates resized copies (1080x1920 @ 85%) with EXIF preserved - SQLite tracking to prevent duplicate processing - Deploy script for Synology NAS (docker run) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
112 lines
5.8 KiB
Markdown
112 lines
5.8 KiB
Markdown
# Fuji Photo Processor
|
|
|
|
Automatic photo processing pipeline for Fuji X-H2 photos: camera uploads via FTP to Synology NAS, files are automatically resized and organized, then picked up by Immich for library management.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────┐ FTP ┌──────────────────┐ watchdog ┌─────────────┐
|
|
│ Fuji X-H2 │ ──────────→ │ Synology NAS │ ────────────→ │ Processor │
|
|
│ (camera) │ port 21 │ /volume2/photos/ │ polling │ container │
|
|
└─────────────┘ │ incoming/ │ └──────┬──────┘
|
|
└──────────────────┘ │
|
|
│ resize + move
|
|
┌─────────────┴─────────────┐
|
|
│ │
|
|
┌─────▼─────┐ ┌───────▼───────┐
|
|
│ /originals │ │ /processed │
|
|
│ YYYY/MM/ │ │ YYYY/MM/ │
|
|
│ (full-res) │ │ (1080px max) │
|
|
└────────────┘ └───────┬───────┘
|
|
│
|
|
┌───────▼───────┐
|
|
│ Immich │
|
|
│ external lib │
|
|
└───────────────┘
|
|
```
|
|
|
|
## Prerequisites
|
|
|
|
- Synology NAS with Docker (Container Manager) installed
|
|
- FTP server enabled on DSM
|
|
- Immich running (for photo management)
|
|
|
|
## Setup
|
|
|
|
### 1. FTP Server (DSM)
|
|
|
|
1. Open **Control Panel → File Services → FTP**
|
|
2. Enable FTP service on port **21**
|
|
3. Set passive port range: **50000-50100**
|
|
4. Create a dedicated user `fujiftp` with write access to `/volume2/photos/incoming`
|
|
|
|
### 2. Camera Configuration (Fuji X-H2)
|
|
|
|
Configure an FTP profile on the camera:
|
|
|
|
| Setting | Value |
|
|
|-----------------|--------------------------|
|
|
| Server IP | `192.168.175.141` |
|
|
| Port | `21` |
|
|
| Passive Mode | **ON** |
|
|
| Username | `fujiftp` |
|
|
| Password | *(your password)* |
|
|
| Upload Dir | `/incoming` |
|
|
| Auto Transfer | ON (or manual trigger) |
|
|
|
|
### 3. Deploy
|
|
|
|
```bash
|
|
./deploy.sh
|
|
```
|
|
|
|
The deploy script will:
|
|
- Create required directories on the NAS
|
|
- Transfer and build the Docker image on the NAS
|
|
- Start the container with appropriate volume mounts
|
|
|
|
### 4. Immich Integration
|
|
|
|
1. In Immich, go to **Administration → External Libraries**
|
|
2. Add a new library with import path: `/volume2/photos/processed`
|
|
3. Set scan interval (e.g., every 15 minutes)
|
|
4. Mount `/volume2/photos/processed` into the Immich container as a read-only volume
|
|
|
|
## Container Details
|
|
|
|
### Volumes
|
|
|
|
| Container Path | Host Path | Purpose |
|
|
|----------------|----------------------------------------|---------------------------|
|
|
| `/incoming` | `/volume2/photos/incoming` | FTP upload landing zone |
|
|
| `/originals` | `/volume2/photos/originals` | Full-resolution originals |
|
|
| `/processed` | `/volume2/photos/processed` | Resized copies for Immich |
|
|
| `/data` | `/volume2/docker/photo-processor/data` | SQLite tracking database |
|
|
|
|
### Environment Variables
|
|
|
|
| Variable | Default | Description |
|
|
|-----------------|---------|--------------------------------------|
|
|
| `POLL_INTERVAL` | `30` | Filesystem poll interval in seconds |
|
|
| `JPEG_QUALITY` | `85` | JPEG compression quality (1-100) |
|
|
| `MAX_WIDTH` | `1080` | Maximum width for resized images |
|
|
| `MAX_HEIGHT` | `1920` | Maximum height for resized images |
|
|
| `TZ` | `Europe/Amsterdam` | Container timezone |
|
|
|
|
## Troubleshooting
|
|
|
|
### Check container logs
|
|
|
|
```bash
|
|
ssh -i ../SynologyDocker/synology_ssh_key ssh@192.168.175.141 \
|
|
'sudo /usr/local/bin/docker logs -f photo-processor'
|
|
```
|
|
|
|
### Common Issues
|
|
|
|
- **Files not detected**: Check that the FTP user has write permissions to `/volume2/photos/incoming`. The processor uses polling (not inotify) so there may be up to a 30-second delay.
|
|
- **Permission denied on originals/processed**: Ensure the directories exist and are writable. The deploy script creates them automatically.
|
|
- **Duplicate filenames**: The processor tracks files by filename in SQLite. If you re-upload a file with the same name, it will be skipped. Delete the entry from `/volume2/docker/photo-processor/data/processed.db` to reprocess.
|
|
- **Container keeps restarting**: Check logs for Python errors. Common cause: missing directories or permission issues on volume mounts.
|
|
- **EXIF data lost**: The processor preserves EXIF data from the original. If EXIF is missing, the original file may not have contained it (check camera settings).
|