from fastapi import FastAPI, File, UploadFile, HTTPException from fastapi.responses import StreamingResponse import tempfile import subprocess import os import io app = FastAPI() from fastapi.middleware.cors import CORSMiddleware app.add_middleware( CORSMiddleware, allow_origins=["*"], # or specific origin(s) allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) def process_video(input_bytes, speed=1.5): """ Process video to change playback speed and compress. """ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_input: tmp_input.write(input_bytes) input_path = tmp_input.name output_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4").name video_speed = 1 / speed audio_speed = speed cmd = [ "ffmpeg", "-i", input_path, "-filter_complex", f"[0:v]setpts={video_speed}*PTS[v];[0:a]atempo={audio_speed}[a]", "-map", "[v]", "-map", "[a]", "-vcodec", "libx264", "-crf", "28", "-preset", "fast", "-movflags", "+faststart", "-y", output_path ] process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) process.wait() if process.returncode != 0: os.remove(input_path) os.remove(output_path) raise HTTPException(status_code=500, detail="Video processing failed.") with open(output_path, "rb") as f: output_data = f.read() os.remove(input_path) os.remove(output_path) return output_data @app.post("/process_video") async def upload_video(file: UploadFile = File(...), speed: float = 1.5): """ Upload a video file and return processed video. """ if not (0.25 <= speed <= 4.0): raise HTTPException(status_code=400, detail="Speed must be between 0.25x and 4x.") video_bytes = await file.read() processed_video = process_video(video_bytes, speed) return StreamingResponse( io.BytesIO(processed_video), media_type="video/mp4", headers={"Content-Disposition": "attachment; filename=processed_video.mp4"} )