sushilideaclan01's picture
Clean up imports
87bfb33
"""
FastAPI Backend for React Video Editor
Handles video generation, image processing, and API integrations
"""
from fastapi import FastAPI, HTTPException, Request, Response
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
from contextlib import asynccontextmanager
import uvicorn
import os
from dotenv import load_dotenv
from api.video_generation import router as video_router
from api.image_service import router as image_router
from api.frame_extraction import router as frame_router
from api.prompt_generation import router as prompt_router
from api.video_export import router as export_router
from api.replicate_service import router as replicate_router
from api.whisper_service import router as whisper_router
from api.auth import router as auth_router
from utils.storage import cleanup_old_files
# Load environment variables
load_dotenv('.env.local')
# Lifespan context manager for startup/shutdown
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Handle startup and shutdown events"""
# Startup
print("πŸš€ Starting FastAPI server...")
print(f"πŸ“ Storage directory: {os.path.join(os.getcwd(), 'storage')}")
# Create storage directory if it doesn't exist
os.makedirs('storage/images', exist_ok=True)
os.makedirs('storage/videos', exist_ok=True)
# Check for API keys
kie_api_key = os.getenv('KIE_API_KEY')
if not kie_api_key:
print("⚠️ Warning: KIE_API_KEY not set. Video generation will fail.")
print(" Get your API key at: https://kie.ai/api-key")
else:
print("βœ… KIE_API_KEY configured")
gemini_api_key = os.getenv('VITE_GEMINI_API_KEY')
if gemini_api_key:
print("βœ… GEMINI_API_KEY configured")
openai_api_key = os.getenv('OPENAI_API_KEY')
if openai_api_key:
print("βœ… OPENAI_API_KEY configured (GPT-4o prompt generation)")
replicate_api_token = os.getenv('REPLICATE_API_TOKEN')
if replicate_api_token:
print("βœ… REPLICATE_API_TOKEN configured")
else:
print("⚠️ Warning: REPLICATE_API_TOKEN not set. Replicate video generation will fail.")
# Check environment mode
environment = os.getenv('ENVIRONMENT', 'dev').lower()
is_dev_mode = environment == 'dev' or environment == 'development'
if is_dev_mode:
print("πŸ§ͺ DEV MODE: Segment generation limited to 2 segments")
else:
print("πŸš€ PROD MODE: Generating all segments")
yield
# Shutdown
print("πŸ›‘ Shutting down FastAPI server...")
cleanup_old_files()
# Create FastAPI app
app = FastAPI(
title="React Video Editor API",
description="Python backend for video generation and processing",
version="1.0.0",
lifespan=lifespan
)
# CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # In production, specify exact origins
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include routers
app.include_router(auth_router, prefix="/api")
app.include_router(video_router, prefix="/api")
app.include_router(image_router, prefix="/api")
app.include_router(frame_router, prefix="/api")
app.include_router(prompt_router, prefix="/api")
app.include_router(export_router, prefix="/api")
app.include_router(replicate_router, prefix="/api")
app.include_router(whisper_router, prefix="/api")
# Health check endpoints (must be before catch-all route)
@app.get("/health")
async def health_check():
"""Health check endpoint"""
environment = os.getenv('ENVIRONMENT', 'dev').lower()
is_dev_mode = environment == 'dev' or environment == 'development'
return {
"status": "healthy",
"environment": environment,
"is_dev_mode": is_dev_mode,
"max_segments": 2 if is_dev_mode else None,
"kie_api_configured": bool(os.getenv('KIE_API_KEY')),
"replicate_api_configured": bool(os.getenv('REPLICATE_API_TOKEN')),
"gemini_api_configured": bool(os.getenv('VITE_GEMINI_API_KEY')),
"openai_api_configured": bool(os.getenv('OPENAI_API_KEY'))
}
# Serve static files (frontend) in production
frontend_dist_path = os.path.join(os.getcwd(), "frontend", "dist")
if os.path.exists(frontend_dist_path):
# Serve static files
app.mount("/assets", StaticFiles(directory=os.path.join(frontend_dist_path, "assets")), name="assets")
# Root endpoint - serve frontend or API info
@app.get("/")
async def root():
"""Root endpoint - serve frontend in production, API info in dev"""
index_path = os.path.join(frontend_dist_path, "index.html")
if os.path.exists(index_path):
from fastapi.responses import FileResponse
return FileResponse(index_path)
# Fallback if frontend not built
return {
"status": "healthy",
"service": "React Video Editor API",
"version": "1.0.0"
}
# Serve frontend index.html for all non-API routes
# This must be last to not interfere with API routes
@app.get("/{full_path:path}")
async def serve_frontend(full_path: str):
"""Serve frontend for all non-API routes"""
# Don't serve frontend for API routes or docs - let FastAPI handle these
if (full_path.startswith("api/") or
full_path.startswith("docs") or
full_path.startswith("redoc") or
full_path.startswith("openapi.json") or
full_path == "health"):
raise HTTPException(status_code=404, detail="Not found")
# Serve index.html for frontend routes
index_path = os.path.join(frontend_dist_path, "index.html")
if os.path.exists(index_path):
from fastapi.responses import FileResponse
return FileResponse(index_path)
raise HTTPException(status_code=404, detail="Frontend not found")
else:
# Root endpoint when frontend not built
@app.get("/")
async def root():
"""Root endpoint - health check"""
return {
"status": "healthy",
"service": "React Video Editor API",
"version": "1.0.0"
}
if __name__ == "__main__":
# Support both SERVER_PORT and PORT (Hugging Face uses PORT)
port = int(os.getenv('PORT') or os.getenv('SERVER_PORT', 4000))
uvicorn.run(
"main:app",
host="0.0.0.0",
port=port,
reload=True,
log_level="info"
)