FastAPI async wrapper for Freepik cloud AI API supporting image generation (Mystic, Flux Dev/Pro, SeedReam), video generation (Kling, MiniMax, Seedance), image editing (upscale, relight, style transfer, expand, inpaint), and utilities (background removal, classifier, audio isolation). Includes async task tracking with polling, Docker containerization, and Gitea CI/CD workflow. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
71 lines
2.4 KiB
Python
71 lines
2.4 KiB
Python
import logging
|
|
from datetime import datetime, timezone
|
|
|
|
from fastapi import APIRouter, HTTPException
|
|
|
|
from app.schemas.common import TaskResponse, TaskStatus
|
|
from app.schemas.video_generation import KlingRequest, MinimaxRequest, SeedanceRequest
|
|
from app.services import freepik_client, task_tracker
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter(prefix='/api/v1/generate/video', tags=['video-generation'])
|
|
|
|
|
|
def _extract_task_id(result: dict) -> str:
|
|
data = result.get('data', result)
|
|
freepik_task_id = str(data.get('task_id') or data.get('id', ''))
|
|
if not freepik_task_id:
|
|
raise HTTPException(status_code=502, detail='No task_id in Freepik response')
|
|
return freepik_task_id
|
|
|
|
|
|
@router.post('/kling', response_model=TaskResponse)
|
|
async def generate_video_kling(request: KlingRequest):
|
|
result = await freepik_client.generate_video_kling(
|
|
image=request.image,
|
|
prompt=request.prompt,
|
|
duration=request.duration,
|
|
aspect_ratio=request.aspect_ratio,
|
|
)
|
|
freepik_id = _extract_task_id(result)
|
|
internal_id = task_tracker.submit(freepik_id, {'model': 'kling'})
|
|
return TaskResponse(
|
|
task_id=internal_id,
|
|
status=TaskStatus.pending,
|
|
created_at=datetime.now(timezone.utc),
|
|
)
|
|
|
|
|
|
@router.post('/minimax', response_model=TaskResponse)
|
|
async def generate_video_minimax(request: MinimaxRequest):
|
|
result = await freepik_client.generate_video_minimax(
|
|
prompt=request.prompt,
|
|
first_frame_image=request.first_frame_image,
|
|
subject_reference=request.subject_reference,
|
|
)
|
|
freepik_id = _extract_task_id(result)
|
|
internal_id = task_tracker.submit(freepik_id, {'model': 'minimax'})
|
|
return TaskResponse(
|
|
task_id=internal_id,
|
|
status=TaskStatus.pending,
|
|
created_at=datetime.now(timezone.utc),
|
|
)
|
|
|
|
|
|
@router.post('/seedance', response_model=TaskResponse)
|
|
async def generate_video_seedance(request: SeedanceRequest):
|
|
result = await freepik_client.generate_video_seedance(
|
|
prompt=request.prompt,
|
|
image=request.image,
|
|
duration=request.duration,
|
|
resolution=request.resolution,
|
|
)
|
|
freepik_id = _extract_task_id(result)
|
|
internal_id = task_tracker.submit(freepik_id, {'model': 'seedance'})
|
|
return TaskResponse(
|
|
task_id=internal_id,
|
|
status=TaskStatus.pending,
|
|
created_at=datetime.now(timezone.utc),
|
|
)
|