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
+20 -9
View File
@@ -48,20 +48,31 @@ Describes concrete behavior and interactions of the system's building blocks in
1. User submits video generation form with prompt, model, aspect ratio, resolution, and duration
2. Flask POSTs to `POST /generate/video` with JWT header
3. Auth Service validates JWT
4. Backend calls OpenRouter `POST /api/v1/videos` with model, prompt, aspect_ratio, resolution, duration_seconds
5. OpenRouter returns `{"id": "...", "polling_url": "..."}` with `status: "queued"`
6. FastAPI returns `VideoResponse` with `polling_url` to Flask
7. Flask renders result page with polling UI
8. Frontend JavaScript polls `GET /generate/video/status?polling_url=...` every 5 seconds
9. When `status` becomes `"completed"`, the response includes `unsigned_urls` — the video is displayed in a `<video>` element
10. If `status` becomes `"failed"`, an error message is shown
4. Backend inserts a row into `generated_videos` with `status: "queued"` and returns the DB job ID
5. Flask renders result page with polling UI
6. Background worker (`video_worker.py`) picks up queued jobs every 15 seconds:
- Calls OpenRouter `POST /api/v1/videos` with model, prompt, and parameters
- Receives `{"id": "...", "polling_url": "..."}` and updates the DB row to `status: "processing"`
- Polls the `polling_url` every 15 seconds until `status` is `"completed"` or `"failed"`
- Updates the DB row with the final status and video URL
7. Frontend JavaScript polls `GET /generate/video/{db_id}/status` every 5 seconds
8. When `status` becomes `"completed"`, the response includes `video_url` — the video is displayed in a `<video>` element
9. If `status` becomes `"failed"`, an error message is shown
10. User can click "Cancel Job" to mark the job as `"cancelled"` (stops local polling, does not stop the provider job)
## Scenario 4a: Video Generation (Image-to-Video)
1. User provides an image URL, motion prompt, model, aspect ratio, resolution, and duration
2. Flask POSTs to `POST /generate/video/from-image` with JWT header
3. Backend calls OpenRouter `POST /api/v1/videos` with `image_url`, prompt, and parameters
4. Same polling flow as Scenario 4
3. Same background worker flow as Scenario 4, with `generation_type: "image_to_video"`
## Scenario 4b: Video Job Cancellation
1. User clicks "Cancel Job" on the video detail page or gallery pending card
2. Frontend POSTs to `/generate/video/{id}/cancel`
3. Backend verifies the job belongs to the user and is not in a terminal state
4. Backend updates the DB row `status` to `"cancelled"`
5. Frontend stops polling and updates the UI to show "Job cancelled"
## Scenario 5: Token Refresh