import os import shutil import uuid from pathlib import Path from fastapi import APIRouter, UploadFile, HTTPException, BackgroundTasks from fastapi.responses import FileResponse import ffmpeg router = APIRouter() TEMP_DIR = Path("temp_uploads") TEMP_DIR.mkdir(exist_ok=True) def cleanup_file(path: Path): try: if path.exists(): path.unlink() except Exception as e: print(f"Error cleaning up file {path}: {e}") @router.post("/gif") async def convert_video_to_gif(file: UploadFile, background_tasks: BackgroundTasks): if not (file.content_type or "").startswith("video/"): raise HTTPException(status_code=400, detail="File must be a video") file_id = str(uuid.uuid4()) input_path = TEMP_DIR / f"{file_id}_{file.filename}" output_filename = f"{file_id}.gif" output_path = TEMP_DIR / output_filename try: with input_path.open("wb") as buffer: shutil.copyfileobj(file.file, buffer) stream = ffmpeg.input(str(input_path)) stream = ffmpeg.filter(stream, 'fps', fps=10) stream = ffmpeg.filter(stream, 'scale', 320, -1) stream = ffmpeg.output(stream, str(output_path)) ffmpeg.run(stream, capture_stdout=True, capture_stderr=True) background_tasks.add_task(cleanup_file, input_path) background_tasks.add_task(cleanup_file, output_path) return FileResponse( output_path, media_type="image/gif", filename="converted.gif" ) except ffmpeg.Error as e: cleanup_file(input_path) if output_path.exists(): cleanup_file(output_path) print(e.stderr.decode('utf8')) raise HTTPException(status_code=500, detail="FFmpeg conversion failed") except Exception as e: cleanup_file(input_path) if output_path.exists(): cleanup_file(output_path) raise HTTPException(status_code=500, detail=str(e))