# CLAUDE.md ## Overview FaceFusion API - A Python REST API wrapping FaceFusion v3.5.3 for face swapping, enhancement, lip sync, and other face/frame processing. Containerized for CPU-only execution, deployed via Gitea CI/CD at `dev.pivoine.art`. ## Architecture - **FastAPI** async web framework with single uvicorn worker (mandatory due to FaceFusion's global state) - **FaceFusion** included as git submodule at `facefusion/` pinned to tag 3.5.3 - All FaceFusion processing serialized through `threading.Lock` in `facefusion_bridge.py` - Background job queue in `worker.py` for async processing ### Key Integration Points FaceFusion uses global mutable state (`state_manager`) and module-level ONNX inference pools. The bridge (`app/services/facefusion_bridge.py`) replicates the initialization side-effects of `program.py`: 1. Registers all job_keys and step_keys in `job_store` 2. Initializes state defaults via `state_manager.init_item()` 3. Initializes job filesystem via `job_manager.init_jobs()` 4. Symlinks `facefusion/.assets/models/` -> `/data/models/` for model persistence ### Project Structure ``` app/ main.py # FastAPI app, lifespan, sys.path setup config.py # Pydantic BaseSettings (FF_ env prefix) routers/ # API endpoint handlers schemas/ # Pydantic request/response models services/ facefusion_bridge.py # Core FaceFusion integration worker.py # Background job queue file_manager.py # File upload/output handling ``` ## Common Commands ```bash # Development docker compose build docker compose up # Production (CPU VPS) docker compose -f docker-compose.prod.yml up -d # Test endpoints curl http://localhost:8000/api/v1/health curl http://localhost:8000/api/v1/system curl -X POST http://localhost:8000/api/v1/models/download -H 'Content-Type: application/json' -d '["face_swapper"]' # Sync face swap curl -X POST http://localhost:8000/api/v1/process \ -F source=@source.jpg \ -F target=@target.jpg \ -o result.jpg ``` ## API Endpoints - `POST /api/v1/process` - Synchronous processing (returns file) - `POST /api/v1/jobs` - Create async job - `GET /api/v1/jobs/{id}` - Job status - `GET /api/v1/jobs/{id}/result` - Download result - `DELETE /api/v1/jobs/{id}` - Cancel/delete job - `GET /api/v1/processors` - List processors - `GET /api/v1/models` - List downloaded models - `POST /api/v1/models/download` - Download models - `GET /api/v1/health` - Health check - `GET /api/v1/system` - System info (CPU, memory) ## Docker - Base image: `python:3.12-slim` + `onnxruntime` - Models persisted in `/data/models` Docker volume (not baked into image) - Single worker mandatory (`--workers 1`) ## Environment Variables All prefixed with `FF_`: - `FF_EXECUTION_PROVIDERS` - JSON array, e.g. `["cpu"]` - `FF_EXECUTION_THREAD_COUNT` - Default 4 - `FF_VIDEO_MEMORY_STRATEGY` - strict/moderate/tolerant - `FF_MODELS_DIR` - Model storage path - `FF_MAX_UPLOAD_SIZE_MB` - Upload limit (default 500) ## Important Notes - Never run with multiple uvicorn workers - FaceFusion global state will corrupt - Models are 100MB-1GB each; pre-download via `/api/v1/models/download` before processing - The `facefusion/` submodule should not be modified directly if possible - use symlinks for model paths - Git operations: always push with the valknarthing ssh key