from fastapi import FastAPI, UploadFile, File from fastapi.responses import FileResponse, JSONResponse import os, subprocess, logging app = FastAPI() JOBS_DIR = "/tmp/jobs" os.makedirs(JOBS_DIR, exist_ok=True) logging.basicConfig(level=logging.INFO) job_status = { "status": "idle", "error": None, } def run_ffmpeg(base_file, overlay_file, output_file): cmd = [ "ffmpeg", "-y", "-i", base_file, "-i", overlay_file, "-filter_complex", "[0:v][1:v]overlay=10:10:format=auto", "-c:a", "copy", output_file ] logging.info(f"Running FFmpeg: {' '.join(cmd)}") result = subprocess.run(cmd, capture_output=True, text=True) logging.info(f"FFmpeg stdout: {result.stdout}") logging.info(f"FFmpeg stderr: {result.stderr}") return result.returncode == 0 @app.post("/generate-video/") async def generate_video(video: UploadFile = File(...), overlay: UploadFile = File(...)): base_file = os.path.join(JOBS_DIR, "current_base.mp4") overlay_file = os.path.join(JOBS_DIR, "current_overlay.mp4") output_file = os.path.join(JOBS_DIR, "current_output.mp4") # Clear old files for f in [base_file, overlay_file, output_file]: if os.path.exists(f): os.remove(f) with open(base_file, "wb") as f: f.write(await video.read()) with open(overlay_file, "wb") as f: f.write(await overlay.read()) job_status["status"] = "processing" job_status["error"] = None try: success = run_ffmpeg(base_file, overlay_file, output_file) if success and os.path.exists(output_file): job_status["status"] = "completed" else: job_status["status"] = "failed" job_status["error"] = "FFmpeg failed or output missing." except Exception as e: job_status["status"] = "failed" job_status["error"] = str(e) return {"status": job_status["status"]} @app.get("/status/") async def check_status(): return JSONResponse(job_status) @app.get("/download/") async def download_video(): output_file = os.path.join(JOBS_DIR, "current_output.mp4") if job_status["status"] != "completed" or not os.path.exists(output_file): return JSONResponse({"error": "No completed video to download."}, status_code=404) return FileResponse(output_file, media_type="video/mp4", filename="output.mp4")