import os import uuid import shutil import subprocess from fastapi import FastAPI, File, UploadFile, Form, HTTPException from fastapi.responses import FileResponse from fastapi.middleware.cors import CORSMiddleware import tempfile app = FastAPI() # Add CORS middleware to allow requests from your frontend app.add_middleware( CORSMiddleware, allow_origins=["*"], # Set this to your frontend URL in production allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Create a directory to store temporary files TEMP_DIR = "temp_files" os.makedirs(TEMP_DIR, exist_ok=True) @app.get("/") def read_root(): return {"message": "Video Subtitle Server is running"} @app.post("/burn-subtitles") async def burn_subtitles( video: UploadFile = File(...), subtitle: UploadFile = File(...), font_size: str = Form("20"), font_color: str = Form("white"), output_format: str = Form("mp4") ): # Create unique ID for this job job_id = str(uuid.uuid4()) job_dir = os.path.join(TEMP_DIR, job_id) os.makedirs(job_dir, exist_ok=True) try: # Save uploaded files video_path = os.path.join(job_dir, f"input{os.path.splitext(video.filename)[1]}") subtitle_path = os.path.join(job_dir, "subtitles.srt") output_path = os.path.join(job_dir, f"output.{output_format}") # Write the files to disk with open(video_path, "wb") as video_file: shutil.copyfileobj(video.file, video_file) with open(subtitle_path, "wb") as subtitle_file: shutil.copyfileobj(subtitle.file, subtitle_file) # Ensure font color is in the correct format for FFmpeg if font_color.startswith('#'): # Convert hex to FFmpeg compatible format font_color = font_color.lstrip('#') # Convert RGB to BGR which is what FFmpeg expects if len(font_color) == 6: r, g, b = font_color[0:2], font_color[2:4], font_color[4:6] font_color = f"&H{b}{g}{r}&" # Run FFmpeg command to burn subtitles subtitle_style = f"FontSize={font_size},PrimaryColour={font_color}" command = [ "ffmpeg", "-i", video_path, "-vf", f"subtitles={subtitle_path}:force_style='{subtitle_style}'", "-c:a", "copy", output_path ] # Execute FFmpeg command process = subprocess.run(command, capture_output=True, text=True) if process.returncode != 0: raise HTTPException(status_code=500, detail=f"FFmpeg Error: {process.stderr}") # Return the processed video return FileResponse( output_path, media_type=f"video/{output_format}", filename=f"processed_video.{output_format}" ) except Exception as e: # Clean up in case of errors if os.path.exists(job_dir): shutil.rmtree(job_dir) raise HTTPException(status_code=500, detail=str(e)) finally: # Clean up temporary files (you might want to do this after a delay in production) if os.path.exists(job_dir): shutil.rmtree(job_dir) @app.post("/convert-srt") async def convert_srt( subtitle: UploadFile = File(...), ): # Create unique ID for this job job_id = str(uuid.uuid4()) job_dir = os.path.join(TEMP_DIR, job_id) os.makedirs(job_dir, exist_ok=True) try: # Save uploaded file subtitle_path = os.path.join(job_dir, "subtitles.srt") # Write the file to disk with open(subtitle_path, "wb") as subtitle_file: shutil.copyfileobj(subtitle.file, subtitle_file) # Return the SRT file return FileResponse( subtitle_path, media_type="text/plain", filename="subtitles.srt" ) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) finally: # Clean up temporary files if os.path.exists(job_dir): shutil.rmtree(job_dir) # Add a health check endpoint @app.get("/health") def health_check(): return {"status": "healthy"}