feat: add video job cancellation functionality and error tracking in generated videos

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-04-29 20:04:10 +02:00
parent 3d0a08a8ef
commit 299ad7d943
13 changed files with 282 additions and 61 deletions
+29 -16
View File
@@ -65,29 +65,42 @@ Self-service profile management and admin user CRUD.
Operational endpoints for application management.
| Method | Path | Auth required | Admin only | Description |
| ------ | --------------------- | ------------- | ---------- | ------------------------------------- |
| GET | `/admin/stats` | ✓ | ✓ | User counts by role, token activity |
| GET | `/admin/health/db` | ✓ | ✓ | DuckDB connectivity check |
| POST | `/admin/tokens/purge` | ✓ | ✓ | Remove expired/revoked refresh tokens |
| Method | Path | Auth required | Admin only | Description |
| ------ | --------------------------- | ------------- | ---------- | ------------------------------------------ |
| GET | `/admin/stats` | ✓ | ✓ | User counts by role, token activity |
| GET | `/admin/health/db` | ✓ | ✓ | DuckDB connectivity check |
| POST | `/admin/tokens/purge` | ✓ | ✓ | Remove expired/revoked refresh tokens |
| GET | `/admin/videos` | ✓ | ✓ | List all video jobs with user emails |
| POST | `/admin/videos/{id}/cancel` | ✓ | ✓ | Cancel a queued/processing video job |
| POST | `/admin/videos/{id}/retry` | ✓ | ✓ | Retry a failed/cancelled video job |
| DELETE | `/admin/videos/{id}` | ✓ | ✓ | Permanently delete a video job |
| POST | `/admin/videos/purge` | ✓ | ✓ | Delete old completed/failed/cancelled jobs |
| POST | `/admin/videos/timed-out` | ✓ | ✓ | Mark stale processing jobs as failed |
| GET | `/admin/models` | ✓ | ✓ | List cached OpenRouter models |
| POST | `/admin/models/refresh` | ✓ | ✓ | Refresh model cache from OpenRouter |
### White Box AI Service (`/ai`, `/generate`)
Model listing and multi-modal generation via openrouter.ai.
| Method | Path | Auth required | Description |
| ------ | ---------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------- |
| GET | `/ai/models` | ✓ | List available OpenRouter models |
| POST | `/ai/chat` | ✓ | Multi-turn chat completion |
| POST | `/generate/text` | ✓ | Single-prompt text generation (optional system prompt) |
| POST | `/generate/image` | ✓ | Text-to-image (DALL-E via `/images/generations` or FLUX/GPT-5 Image Mini via `/chat/completions` with `modalities`) |
| POST | `/generate/video` | ✓ | Text-to-video (Sora 2 Pro, Veo 3.1 Fast) — returns `polling_url` |
| POST | `/generate/video/from-image` | ✓ | Image-to-video — returns `polling_url` |
| GET | `/generate/video/status` | ✓ | Poll video generation status via `polling_url` |
| Method | Path | Auth required | Description |
| ------ | ------------------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------- |
| GET | `/ai/models` | ✓ | List available OpenRouter models |
| POST | `/ai/chat` | ✓ | Multi-turn chat completion |
| POST | `/generate/text` | ✓ | Single-prompt text generation (optional system prompt) |
| POST | `/generate/image` | ✓ | Text-to-image (DALL-E via `/images/generations` or FLUX/GPT-5 Image Mini via `/chat/completions` with `modalities`) |
| POST | `/generate/video` | ✓ | Text-to-video (Sora 2 Pro, Veo 3.1 Fast) — returns `polling_url` |
| POST | `/generate/video/from-image` | ✓ | Image-to-video — returns `polling_url` |
| GET | `/generate/video/status` | ✓ | Poll video generation status via `polling_url` |
| GET | `/generate/images` | ✓ | List current user's generated images |
| GET | `/generate/images/{id}` | ✓ | Get a single generated image |
| GET | `/generate/videos` | ✓ | List current user's video jobs |
| GET | `/generate/videos/{id}` | ✓ | Get a single video job |
| POST | `/generate/videos/{id}/cancel` | ✓ | Cancel a queued/processing video job |
**Video generation flow:** The `/generate/video` and `/generate/video/from-image` endpoints submit a job to OpenRouter's `/api/v1/videos` endpoint and return immediately with `status: "queued"` and a `polling_url`. Clients poll `/generate/video/status?polling_url=...` every 5 seconds until `status` is `"completed"` (returns `unsigned_urls`) or `"failed"`.
**Video generation flow:** The `/generate/video` and `/generate/video/from-image` endpoints queue a job in the local database and return immediately with `status: "queued"`. A background worker (`video_worker.py`) submits the job to OpenRouter's `/api/v1/videos` endpoint, receives a `polling_url`, and polls it periodically until the job reaches `"completed"` or `"failed"`. The frontend polls `GET /generate/video/{id}/status` every 5 seconds to show live status updates.
**Image generation routing:** The router auto-detects the model type — models containing `"flux"` or `"gpt-5-image-mini"` are routed to `/chat/completions` with `modalities: ["image"]`, while others (e.g. DALL-E 3) use the legacy `/images/generations` endpoint.
**Image generation routing:** The router auto-detects the model type — models containing `"flux"` or `"gpt-5-image-mini"` are routed to `/chat/completions` with `modalities: ["image"]` (or `["image", "text"]` depending on cached output modalities), while others (e.g. DALL-E 3) use the legacy `/images/generations` endpoint.
### White Box DB Service (`db.py`)