60 lines
1.5 KiB
Python
60 lines
1.5 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Optional
|
|
|
|
from pydantic import BaseModel, Field, field_validator
|
|
|
|
from app.config import settings
|
|
|
|
|
|
# --- Request ---
|
|
|
|
class GenerateForm(BaseModel):
|
|
prompt: Optional[str] = Field(None, max_length=1000)
|
|
width: int = Field(768, ge=256, le=2048, multiple_of=32)
|
|
height: int = Field(512, ge=256, le=2048, multiple_of=32)
|
|
num_frames: int = Field(65, ge=9, le=settings.max_frame_count)
|
|
fps: float = Field(24.0, gt=0, le=60)
|
|
seed: Optional[int] = Field(None)
|
|
|
|
model_config = {"extra": "forbid"}
|
|
|
|
@field_validator("num_frames")
|
|
@classmethod
|
|
def check_frames(cls, v: int) -> int:
|
|
if v % 8 != 1:
|
|
n = v // 8
|
|
candidates = sorted(
|
|
8 * i + 1
|
|
for i in range(max(1, n - 2), n + 3)
|
|
if 8 * i + 1 <= settings.max_frame_count
|
|
)
|
|
raise ValueError(f"num_frames must be 8n+1. Got {v}. Closest valid: {candidates}")
|
|
return v
|
|
|
|
|
|
# --- Job Status ---
|
|
|
|
class JobStatusResponse(BaseModel):
|
|
job_id: str
|
|
status: str # pending, processing, completed, failed
|
|
prompt: Optional[str] = None
|
|
params: Optional[dict] = None
|
|
error: Optional[str] = None
|
|
created_at: Optional[str] = None
|
|
completed_at: Optional[str] = None
|
|
|
|
|
|
# --- Submission Response ---
|
|
|
|
class JobSubmitResponse(BaseModel):
|
|
job_id: str
|
|
status: str = "pending"
|
|
message: str = "Job submitted. Poll GET /jobs/{job_id} for status."
|
|
|
|
|
|
# --- Error ---
|
|
|
|
class ErrorResponse(BaseModel):
|
|
error: str
|