feat: implement video job management with retry and delete functionality, enhance video generation status tracking
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
"""Generate router: text, image, video, and image-to-video generation."""
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import httpx
|
||||
@@ -209,54 +210,32 @@ async def generate_video(
|
||||
body: VideoRequest,
|
||||
current_user: dict = Depends(get_current_user),
|
||||
) -> VideoResponse:
|
||||
"""Generate a video from a text prompt."""
|
||||
try:
|
||||
result = await openrouter.generate_video(
|
||||
model=body.model,
|
||||
prompt=body.prompt,
|
||||
duration_seconds=body.duration_seconds,
|
||||
aspect_ratio=body.aspect_ratio,
|
||||
resolution=body.resolution,
|
||||
)
|
||||
except httpx.HTTPStatusError as exc:
|
||||
detail = (
|
||||
f"OpenRouter API error: {exc.response.status_code} - {exc.response.text}"
|
||||
)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_502_BAD_GATEWAY, detail=detail)
|
||||
except Exception as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_502_BAD_GATEWAY, detail=f"OpenRouter error: {exc}"
|
||||
)
|
||||
|
||||
"""Queue a text-to-video generation job for background processing."""
|
||||
user_id = current_user.get("id") or current_user.get("sub")
|
||||
job_id = result.get("id", "")
|
||||
polling_url = result.get("polling_url")
|
||||
job_status = result.get("status", "pending")
|
||||
now = datetime.now(timezone.utc).replace(tzinfo=None)
|
||||
request_params = json.dumps({
|
||||
"model": body.model,
|
||||
"prompt": body.prompt,
|
||||
"duration_seconds": body.duration_seconds,
|
||||
"aspect_ratio": body.aspect_ratio,
|
||||
"resolution": body.resolution,
|
||||
})
|
||||
db_id = None
|
||||
async with get_write_lock():
|
||||
conn = get_conn()
|
||||
row = conn.execute(
|
||||
"""INSERT INTO generated_videos (user_id, job_id, model_id, prompt, polling_url, status, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING id""",
|
||||
[user_id, job_id, body.model, body.prompt,
|
||||
polling_url, job_status, now, now],
|
||||
"""INSERT INTO generated_videos
|
||||
(user_id, job_id, model_id, prompt, status, request_params, generation_type, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, 'queued', ?, 'text_to_video', ?, ?) RETURNING id""",
|
||||
[user_id, "", body.model, body.prompt, request_params, now, now],
|
||||
).fetchone()
|
||||
if row:
|
||||
db_id = str(row[0])
|
||||
|
||||
urls = result.get("unsigned_urls") or result.get("video_urls")
|
||||
return VideoResponse(
|
||||
id=job_id,
|
||||
id="",
|
||||
db_id=db_id,
|
||||
model=body.model,
|
||||
status=job_status,
|
||||
polling_url=polling_url,
|
||||
video_urls=urls,
|
||||
video_url=(urls or [None])[0],
|
||||
error=result.get("error"),
|
||||
metadata=result.get("metadata"),
|
||||
status="queued",
|
||||
)
|
||||
|
||||
|
||||
@@ -265,55 +244,33 @@ async def generate_video_from_image(
|
||||
body: VideoFromImageRequest,
|
||||
current_user: dict = Depends(get_current_user),
|
||||
) -> VideoResponse:
|
||||
"""Generate a video from an image and a text prompt."""
|
||||
try:
|
||||
result = await openrouter.generate_video_from_image(
|
||||
model=body.model,
|
||||
image_url=body.image_url,
|
||||
prompt=body.prompt,
|
||||
duration_seconds=body.duration_seconds,
|
||||
aspect_ratio=body.aspect_ratio,
|
||||
resolution=body.resolution,
|
||||
)
|
||||
except httpx.HTTPStatusError as exc:
|
||||
detail = (
|
||||
f"OpenRouter API error: {exc.response.status_code} - {exc.response.text}"
|
||||
)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_502_BAD_GATEWAY, detail=detail)
|
||||
except Exception as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_502_BAD_GATEWAY, detail=f"OpenRouter error: {exc}"
|
||||
)
|
||||
|
||||
"""Queue an image-to-video generation job for background processing."""
|
||||
user_id = current_user.get("id") or current_user.get("sub")
|
||||
job_id = result.get("id", "")
|
||||
polling_url = result.get("polling_url")
|
||||
job_status = result.get("status", "pending")
|
||||
now = datetime.now(timezone.utc).replace(tzinfo=None)
|
||||
request_params = json.dumps({
|
||||
"model": body.model,
|
||||
"image_url": body.image_url,
|
||||
"prompt": body.prompt,
|
||||
"duration_seconds": body.duration_seconds,
|
||||
"aspect_ratio": body.aspect_ratio,
|
||||
"resolution": body.resolution,
|
||||
})
|
||||
db_id = None
|
||||
async with get_write_lock():
|
||||
conn = get_conn()
|
||||
row = conn.execute(
|
||||
"""INSERT INTO generated_videos (user_id, job_id, model_id, prompt, polling_url, status, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING id""",
|
||||
[user_id, job_id, body.model, body.prompt,
|
||||
polling_url, job_status, now, now],
|
||||
"""INSERT INTO generated_videos
|
||||
(user_id, job_id, model_id, prompt, status, request_params, generation_type, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, 'queued', ?, 'image_to_video', ?, ?) RETURNING id""",
|
||||
[user_id, "", body.model, body.prompt, request_params, now, now],
|
||||
).fetchone()
|
||||
if row:
|
||||
db_id = str(row[0])
|
||||
|
||||
urls = result.get("unsigned_urls") or result.get("video_urls")
|
||||
return VideoResponse(
|
||||
id=job_id,
|
||||
id="",
|
||||
db_id=db_id,
|
||||
model=body.model,
|
||||
status=job_status,
|
||||
polling_url=polling_url,
|
||||
video_urls=urls,
|
||||
video_url=(urls or [None])[0],
|
||||
error=result.get("error"),
|
||||
metadata=result.get("metadata"),
|
||||
status="queued",
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user