clove1002/ZHSAPI
0
1from fastapi import FastAPI, UploadFile, File, Form2from fastapi.responses import FileResponse, JSONResponse3from gradio_client import Client, handle_file4from gradio_client.exceptions import AppError5import tempfile6import os7import shutil8 9HF_TOKEN = os.getenv("HF_TOKEN")10 11app = FastAPI(title="ZHSAPI")12 13 14@app.get("/health")15def health():16 return {"status": "ok"}17 18 19@app.post("/timelapse")20async def generate_timelapse(21 start_frame: UploadFile = File(...),22 end_frame: UploadFile = File(...),23 prompt: str = Form(default="a construction timelapse"),24):25 with tempfile.TemporaryDirectory() as tmpdir:26 start_path = os.path.join(tmpdir, start_frame.filename)27 end_path = os.path.join(tmpdir, end_frame.filename)28 29 with open(start_path, "wb") as f:30 shutil.copyfileobj(start_frame.file, f)31 with open(end_path, "wb") as f:32 shutil.copyfileobj(end_frame.file, f)33 34 # Try diffusion model first, fall back to CPU FILM interpolation on quota error35 try:36 client = Client("linoyts/LTX-2-3-First-Last-Frame", token=HF_TOKEN)37 result = client.predict(38 first_image=handle_file(start_path),39 last_image=handle_file(end_path),40 input_audio=None,41 prompt=prompt,42 api_name="/generate_video",43 )44 output_path = result[0] if isinstance(result, (list, tuple)) else result45 except AppError as e:46 if "GPU quota" not in str(e):47 return JSONResponse(status_code=502, content={"error": str(e)})48 49 # Fallback: CPU-based FILM interpolation (no GPU quota)50 film = Client("freealise/video_frame_interpolation")51 loaded = film.predict(52 f=[handle_file(start_path), handle_file(end_path)],53 r_bg=False,54 api_name="/loadf",55 )56 frames = loaded[0]57 result = film.predict(58 f_in=frames,59 interpolation=4,60 fps_output=0,61 api_name="/infer",62 )63 output_path = result[0]["video"] if isinstance(result[0], dict) else result[0]64 65 return FileResponse(output_path, media_type="video/mp4", filename="timelapse.mp4")66 