Spaces:
Sleeping
Sleeping
| 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 | |
| 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"} | |
| ) |