Spaces:
Running
Running
| import os | |
| import shutil | |
| import subprocess | |
| import tempfile | |
| from fastapi import FastAPI, File, UploadFile, Form, HTTPException, BackgroundTasks | |
| from fastapi.responses import FileResponse, RedirectResponse | |
| from fastapi.middleware.cors import CORSMiddleware | |
| app = FastAPI() | |
| # Add CORS middleware (adjust allow_origins for production) | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Ensure the base temporary directory exists. | |
| TEMP_DIR = "temp_files" | |
| os.makedirs(TEMP_DIR, exist_ok=True) | |
| def read_root(): | |
| return {"message": "Video Subtitle Server is running"} | |
| async def burn_subtitles( | |
| background_tasks: BackgroundTasks, | |
| video: UploadFile = File(...), | |
| subtitle: UploadFile = File(...), | |
| font_size: str = Form("20"), | |
| font_color: str = Form("white"), | |
| output_format: str = Form("mp4") | |
| ): | |
| # Create a unique temporary directory for this job. | |
| job_dir = tempfile.mkdtemp(prefix='job_', dir=TEMP_DIR) | |
| try: | |
| # Build file paths. | |
| 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}") | |
| # Save uploaded video file. | |
| with open(video_path, "wb") as video_file: | |
| shutil.copyfileobj(video.file, video_file) | |
| # Save uploaded subtitle file. | |
| with open(subtitle_path, "wb") as subtitle_file: | |
| shutil.copyfileobj(subtitle.file, subtitle_file) | |
| # Format the font color for FFmpeg if provided as hex. | |
| if font_color.startswith('#'): | |
| font_color = font_color.lstrip('#') | |
| 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}&" | |
| # Build the subtitle style string. | |
| 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 | |
| ] | |
| # Run the 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}") | |
| # Schedule cleanup of the job directory after the response is sent. | |
| background_tasks.add_task(shutil.rmtree, job_dir) | |
| return FileResponse( | |
| output_path, | |
| media_type=f"video/{output_format}", | |
| filename=f"processed_video.{output_format}" | |
| ) | |
| except Exception as e: | |
| # Clean up immediately on error. | |
| shutil.rmtree(job_dir, ignore_errors=True) | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| async def convert_srt( | |
| background_tasks: BackgroundTasks, | |
| subtitle: UploadFile = File(...), | |
| ): | |
| job_dir = tempfile.mkdtemp(prefix='job_', dir=TEMP_DIR) | |
| try: | |
| subtitle_path = os.path.join(job_dir, "subtitles.srt") | |
| with open(subtitle_path, "wb") as subtitle_file: | |
| shutil.copyfileobj(subtitle.file, subtitle_file) | |
| background_tasks.add_task(shutil.rmtree, job_dir) | |
| return FileResponse( | |
| subtitle_path, | |
| media_type="text/plain", | |
| filename="subtitles.srt" | |
| ) | |
| except Exception as e: | |
| shutil.rmtree(job_dir, ignore_errors=True) | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| def health_check(): | |
| return {"status": "healthy"} | |
| def redirect_to_docs(): | |
| return RedirectResponse(url="/docs") | |