Spaces:
Sleeping
Sleeping
| import os | |
| import uuid | |
| import asyncio | |
| from typing import Dict, Any | |
| import replicate | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import FileResponse | |
| import httpx | |
| REPLICATE_API_TOKEN = os.getenv("REPLICATE_API_TOKEN") | |
| if not REPLICATE_API_TOKEN: | |
| raise RuntimeError("Missing REPLICATE_API_TOKEN env var") | |
| os.environ["REPLICATE_API_TOKEN"] = REPLICATE_API_TOKEN | |
| VIDEO_OUTPUT_DIR = "video_outputs" | |
| os.makedirs(VIDEO_OUTPUT_DIR, exist_ok=True) | |
| app = FastAPI(title="nexus-video-api", version="2.0.0") | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| VIDEO_MODELS = { | |
| "tiktok": "minimax/video-01", | |
| "social": "minimax/video-01", | |
| "cinematic": "minimax/video-01", | |
| "ads": "minimax/video-01", | |
| "music": "minimax/video-01", | |
| "music_long": "minimax/video-01", | |
| "experimental": "minimax/video-01", | |
| "avatar": "minimax/video-01", | |
| } | |
| TASKS: Dict[str, Dict[str, Any]] = {} | |
| TASKS_LOCK = asyncio.Lock() | |
| def create_task(mode: str) -> str: | |
| task_id = str(uuid.uuid4()) | |
| TASKS[task_id] = {"mode": mode, "status": "queued", "error": None, "video_path": None} | |
| return task_id | |
| async def set_task(task_id: str, **updates: Any) -> None: | |
| async with TASKS_LOCK: | |
| if task_id in TASKS: | |
| TASKS[task_id].update(updates) | |
| async def run_model(task_id: str, model_id: str, payload: Dict[str, Any]) -> None: | |
| await set_task(task_id, status="processing", error=None) | |
| try: | |
| output = await asyncio.to_thread( | |
| replicate.run, | |
| model_id, | |
| input={"prompt": payload.get("prompt", "")}, | |
| ) | |
| video_url = output[0] if isinstance(output, list) else str(output) | |
| async with httpx.AsyncClient(timeout=120) as client: | |
| resp = await client.get(video_url) | |
| resp.raise_for_status() | |
| video_bytes = resp.content | |
| if not video_bytes: | |
| raise RuntimeError("Empty video output") | |
| out_path = os.path.join(VIDEO_OUTPUT_DIR, f"{task_id}.mp4") | |
| with open(out_path, "wb") as f: | |
| f.write(video_bytes) | |
| await set_task(task_id, status="done", video_path=out_path) | |
| except Exception as e: | |
| await set_task(task_id, status="error", error=str(e), video_path=None) | |
| def root(): | |
| return {"status": "ok", "service": "nexus-video-api", "version": "2.0.0"} | |
| def health(): | |
| return {"ok": True} | |
| async def video_status(task_id: str): | |
| task = TASKS.get(task_id) | |
| if not task: | |
| raise HTTPException(status_code=404, detail="task_not_found") | |
| return {"task_id": task_id, "mode": task["mode"], "status": task["status"], "error": task["error"], "ready": bool(task["video_path"]) and task["status"] == "done"} | |
| async def get_video(task_id: str): | |
| task = TASKS.get(task_id) | |
| if not task: | |
| raise HTTPException(status_code=404, detail="task_not_found") | |
| if not task.get("video_path") or task.get("status") != "done": | |
| return {"error": "video_not_ready"} | |
| return FileResponse(task["video_path"], media_type="video/mp4") | |
| async def video_tiktok(data: dict): | |
| task_id = create_task("tiktok") | |
| asyncio.create_task(run_model(task_id, VIDEO_MODELS["tiktok"], data)) | |
| return {"task_id": task_id} | |
| async def video_social(data: dict): | |
| task_id = create_task("social") | |
| asyncio.create_task(run_model(task_id, VIDEO_MODELS["social"], data)) | |
| return {"task_id": task_id} | |
| async def video_cinematic(data: dict): | |
| task_id = create_task("cinematic") | |
| asyncio.create_task(run_model(task_id, VIDEO_MODELS["cinematic"], data)) | |
| return {"task_id": task_id} | |
| async def video_ads(data: dict): | |
| task_id = create_task("ads") | |
| asyncio.create_task(run_model(task_id, VIDEO_MODELS["ads"], data)) | |
| return {"task_id": task_id} | |
| async def video_music(data: dict): | |
| task_id = create_task("music") | |
| asyncio.create_task(run_model(task_id, VIDEO_MODELS["music"], data)) | |
| return {"task_id": task_id} | |
| async def video_music_long(data: dict): | |
| task_id = create_task("music_long") | |
| asyncio.create_task(run_model(task_id, VIDEO_MODELS["music_long"], data)) | |
| return {"task_id": task_id} | |
| async def video_experimental(data: dict): | |
| task_id = create_task("experimental") | |
| asyncio.create_task(run_model(task_id, VIDEO_MODELS["experimental"], data)) | |
| return {"task_id": task_id} |