Some checks failed
Build and Push Docker Image / build (push) Failing after 9s
The original implementation used guessed endpoint paths that don't match
the actual Freepik API. Key fixes based on their OpenAPI spec:
- Task polling is per-endpoint (e.g. GET /v1/ai/text-to-image/flux-dev/{task-id})
not a generic /v1/ai/tasks/{id}. freepik_client now returns TaskResult
with status_path, and task_tracker polls using that path.
- Fixed endpoint paths: flux-pro -> flux-pro-v1-1, upscale -> image-upscaler,
relight -> image-relight, style-transfer -> image-style-transfer,
expand -> image-expand/flux-pro, inpaint -> ideogram-image-edit,
remove-background -> beta/remove-background, classifier -> classifier/image,
audio-isolate -> audio-isolation, icon -> text-to-icon
- Fixed video paths: kling -> kling-o1-pro with kling-o1 status path,
minimax -> minimax-hailuo-02-1080p, seedance -> seedance-pro-1080p
- Fixed request schemas to match actual API params (e.g. scale_factor
not scale, reference_image not style_reference, image_url for bg removal)
- Fixed response parsing: status is uppercase (COMPLETED not completed),
results in data.generated[] array, classifier returns [{class_name, probability}]
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
81 lines
2.7 KiB
Python
81 lines
2.7 KiB
Python
import logging
|
|
from datetime import datetime, timezone
|
|
|
|
from fastapi import APIRouter, HTTPException
|
|
|
|
from app.schemas.common import TaskResponse, TaskStatus
|
|
from app.schemas.utilities import (
|
|
ClassificationResponse,
|
|
IconRequest,
|
|
RemoveBackgroundRequest,
|
|
RemoveBackgroundResponse,
|
|
)
|
|
from app.services import freepik_client, task_tracker
|
|
from app.services.freepik_client import _extract_task_id
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter(prefix='/api/v1/util', tags=['utilities'])
|
|
|
|
|
|
@router.post('/remove-background', response_model=RemoveBackgroundResponse)
|
|
async def remove_background(request: RemoveBackgroundRequest):
|
|
"""Remove background from an image. Takes a URL, returns result URLs."""
|
|
result = await freepik_client.remove_background(request.image_url)
|
|
return RemoveBackgroundResponse(**result)
|
|
|
|
|
|
@router.post('/classify', response_model=ClassificationResponse)
|
|
async def classify_image(request: dict):
|
|
"""Classify whether an image is AI-generated."""
|
|
image = request.get('image')
|
|
if not image:
|
|
raise HTTPException(status_code=400, detail='image field is required')
|
|
|
|
result = await freepik_client.classify_image(image)
|
|
return result
|
|
|
|
|
|
@router.post('/audio-isolate', response_model=TaskResponse)
|
|
async def audio_isolate(request: dict):
|
|
"""Isolate audio tracks from an audio file."""
|
|
audio = request.get('audio')
|
|
if not audio:
|
|
raise HTTPException(status_code=400, detail='audio field is required')
|
|
|
|
result = await freepik_client.isolate_audio(audio)
|
|
freepik_task_id = _extract_task_id(result.data)
|
|
if not freepik_task_id:
|
|
raise HTTPException(status_code=502, detail='No task_id in Freepik response')
|
|
|
|
internal_id = task_tracker.submit(freepik_task_id, result.status_path, {'operation': 'audio-isolate'})
|
|
return TaskResponse(
|
|
task_id=internal_id,
|
|
status=TaskStatus.pending,
|
|
created_at=datetime.now(timezone.utc),
|
|
)
|
|
|
|
|
|
# Icon generation lives under /api/v1/generate/ but is simple enough to keep here
|
|
icon_router = APIRouter(prefix='/api/v1/generate', tags=['utilities'])
|
|
|
|
|
|
@icon_router.post('/icon', response_model=TaskResponse)
|
|
async def generate_icon(request: IconRequest):
|
|
result = await freepik_client.generate_icon(
|
|
prompt=request.prompt,
|
|
color=request.color,
|
|
shape=request.shape,
|
|
style=request.style,
|
|
)
|
|
freepik_task_id = _extract_task_id(result.data)
|
|
if not freepik_task_id:
|
|
raise HTTPException(status_code=502, detail='No task_id in Freepik response')
|
|
|
|
internal_id = task_tracker.submit(freepik_task_id, result.status_path, {'operation': 'icon'})
|
|
return TaskResponse(
|
|
task_id=internal_id,
|
|
status=TaskStatus.pending,
|
|
created_at=datetime.now(timezone.utc),
|
|
)
|