
Changes: - Enhanced migration 002 with column existence checks to prevent duplicate column errors - Added comprehensive migration 003 that syncs database with current model state - Modified application startup to avoid conflicts between create_all() and Alembic - Added proper table/column existence checking in migrations - Improved migration safety for production environments - Removed automatic table creation when database already exists (relies on migrations) This resolves the 'duplicate column name' error by ensuring migrations check for existing columns before attempting to add them.
99 lines
3.0 KiB
Python
99 lines
3.0 KiB
Python
from pathlib import Path
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from contextlib import asynccontextmanager
|
|
import logging
|
|
|
|
from app.db.session import engine
|
|
from app.db.base import Base
|
|
from app.routes import auth, videos, transcription, translation, voice_cloning, video_processing, profile
|
|
|
|
# Configure logging
|
|
logging.basicConfig(level=logging.INFO)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
try:
|
|
# Create database directory
|
|
logger.info("Starting application initialization...")
|
|
storage_dir = Path("/app/storage/db")
|
|
storage_dir.mkdir(parents=True, exist_ok=True)
|
|
logger.info(f"Created storage directory: {storage_dir}")
|
|
|
|
# Import all models to ensure they're registered with Base
|
|
|
|
# Only create tables if database doesn't exist (for development)
|
|
# In production, use Alembic migrations instead
|
|
db_path = storage_dir / "db.sqlite"
|
|
if not db_path.exists():
|
|
logger.info("Database file doesn't exist, creating initial tables...")
|
|
Base.metadata.create_all(bind=engine)
|
|
else:
|
|
logger.info("Database file exists, skipping table creation (use Alembic for migrations)")
|
|
|
|
logger.info("Database initialization completed")
|
|
yield
|
|
except Exception as e:
|
|
logger.error(f"Error during application startup: {e}")
|
|
raise
|
|
|
|
|
|
app = FastAPI(
|
|
title="AI Video Dubbing API",
|
|
description="Backend API for AI-powered video dubbing with voice cloning and translation",
|
|
version="1.0.0",
|
|
lifespan=lifespan
|
|
)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
|
allow_headers=["*"],
|
|
expose_headers=["*"]
|
|
)
|
|
|
|
# Include routers
|
|
app.include_router(auth.router, prefix="/auth", tags=["Authentication"])
|
|
app.include_router(profile.router, prefix="/profile", tags=["Profile"])
|
|
app.include_router(videos.router, prefix="/videos", tags=["Videos"])
|
|
app.include_router(transcription.router, prefix="/transcription", tags=["Transcription"])
|
|
app.include_router(translation.router, prefix="/translation", tags=["Translation"])
|
|
app.include_router(voice_cloning.router, prefix="/voice", tags=["Voice Cloning"])
|
|
app.include_router(video_processing.router, prefix="/process", tags=["Video Processing"])
|
|
|
|
|
|
@app.get("/")
|
|
async def root():
|
|
return {
|
|
"title": "AI Video Dubbing API",
|
|
"documentation": "/docs",
|
|
"health": "/health"
|
|
}
|
|
|
|
|
|
@app.get("/health")
|
|
async def health_check():
|
|
return {
|
|
"status": "healthy",
|
|
"service": "AI Video Dubbing API",
|
|
"database": "connected"
|
|
}
|
|
|
|
|
|
@app.get("/test")
|
|
async def test_endpoint():
|
|
logger.info("Test endpoint called")
|
|
return {
|
|
"message": "API is working correctly",
|
|
"timestamp": "2024-01-01T00:00:00Z",
|
|
"status": "success"
|
|
}
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import uvicorn
|
|
uvicorn.run(app, host="0.0.0.0", port=8000) |