| from fastapi import FastAPI, Request, HTTPException, Security, BackgroundTasks |
| from fastapi.middleware.cors import CORSMiddleware |
| from fastapi.security import APIKeyHeader |
| from fastapi.responses import StreamingResponse |
| from pydantic import BaseModel |
| import comfy_engine |
| import httpx |
| import os |
|
|
| app = FastAPI(title="Sparkling Vision Pro API - Backend Engine") |
|
|
| |
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins=["*"], |
| allow_credentials=True, |
| allow_methods=["*"], |
| allow_headers=["*"], |
| ) |
|
|
| |
| API_KEY = os.getenv("VIVEN_API_KEY", "your_default_password") |
| header_scheme = APIKeyHeader(name="X-API-Key") |
|
|
| async def verify_key(key: str = Security(header_scheme)): |
| if key != API_KEY: |
| raise HTTPException(status_code=403, detail="Access Denied! Invalid API Key.") |
| return key |
|
|
| class VideoRequest(BaseModel): |
| prompt: str |
| aspect_ratio: str = "16:9" |
| quality: str = "480p" |
| frames: int = 81 |
| fps: int = 16 |
|
|
| |
| |
| |
| @app.post("/api/generate") |
| async def generate(req: VideoRequest, bg_tasks: BackgroundTasks, auth: str = Security(verify_key)): |
| try: |
| task_id, client_id, token, total_nodes = await comfy_engine.queue_prompt(req.dict()) |
| comfy_engine.init_task(task_id, req.prompt) |
| bg_tasks.add_task(comfy_engine.background_watcher, task_id, client_id, token, total_nodes) |
| return {"status": "queued", "task_id": task_id, "message": "Task is running in the background."} |
| except Exception as e: |
| raise HTTPException(status_code=500, detail=str(e)) |
|
|
| |
| |
| |
| @app.get("/api/history") |
| async def get_history(): |
| return comfy_engine.load_history() |
|
|
| @app.get("/api/video") |
| async def proxy_video(request: Request): |
| q = request.query_params |
| target = f"http://{comfy_engine.COMFY_HOST}/view?{q}" |
| async def stream(): |
| async with httpx.AsyncClient() as client: |
| async with client.stream("GET", target, timeout=60.0) as r: |
| async for chunk in r.aiter_bytes(): |
| yield chunk |
| return StreamingResponse(stream(), media_type="video/mp4") |
|
|
| @app.delete("/api/history/{task_id}") |
| async def delete_history_item(task_id: str): |
| import json, os |
| if os.path.exists("history.json"): |
| with open("history.json", "r", encoding="utf-8") as f: |
| data = json.load(f) |
| data = [item for item in data if item["id"] != task_id] |
| with open("history.json", "w", encoding="utf-8") as f: |
| json.dump(data, f, indent=4) |
| return {"status": "deleted"} |
| return {"status": "not found"} |
|
|
| if __name__ == "__main__": |
| import uvicorn |
| uvicorn.run(app, host="0.0.0.0", port=7860) |
|
|