from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from fastapi.responses import FileResponse import logging from pathlib import Path import sys # Import config and routers from config import config from routers import api from video_creator.libraries.tts_client import TTSClient from video_creator.libraries.whisper_client import WhisperClient from video_creator.libraries.pexels_client import PexelsClient from video_creator.music_manager import MusicManager from video_creator.short_creator import ShortCreator # Setup logging logging.basicConfig( level=config.log_level.upper(), format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[logging.StreamHandler(sys.stdout)] ) logger = logging.getLogger(__name__) # Create FastAPI app app = FastAPI( title="Short Video Maker API", description=""" # Short Video Maker REST API Create engaging short-form videos for TikTok, Instagram Reels, and YouTube Shorts. ## Features - 🎙️ Text-to-speech narration (Kokoro) - 📝 Automatic caption generation (Whisper) - 🎥 Background videos from Pexels - 🎵 Background music with mood selection - 📱 Portrait & landscape support ## Workflow 1. **Create Video**: POST to `/api/short-video` with scenes and config 2. **Check Status**: GET `/api/short-video/{id}/status` to monitor progress 3. **Download**: GET `/api/short-video/{id}` when status is "ready" ## Environment Setup Required environment variables: - `PEXELS_API_KEY` - Get from https://www.pexels.com/api/ - `HF_TTS` - Your TTS service endpoint URL """, version="2.0.0", contact={ "name": "Short Video Maker", "url": "https://huggingface.co/spaces" } ) # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.on_event("startup") async def startup_event(): """Initialize services on startup""" logger.info("Starting Short Video Maker on Hugging Face Spaces...") # Ensure directories exist config.ensure_directories() # Validate environment variables # Validate environment variables if not config.pexels_api_key: logger.warning("PEXELS_API_KEY is missing! Video generation will fail.") if not config.hf_tts: logger.warning("HF_TTS is missing! TTS will fail.") # Initialize components logger.info("Initializing TTS client...") tts_client = TTSClient(config.hf_tts) logger.info("Initializing Whisper client...") whisper_client = WhisperClient( model_name=config.whisper_model, model_dir=config.whisper_model_dir ) logger.info("Initializing Pexels client...") pexels_client = PexelsClient(config.pexels_api_key) logger.info("Initializing music manager...") music_manager = MusicManager(config.music_dir_path) try: music_manager.ensure_music_files_exist() except FileNotFoundError as e: logger.error(f"Music setup error: {e}") logger.warning("Creating empty music directory - you'll need to add music files") config.music_dir_path.mkdir(parents=True, exist_ok=True) logger.info("Initializing short creator...") short_creator = ShortCreator( config=config, tts_client=tts_client, whisper_client=whisper_client, pexels_client=pexels_client, music_manager=music_manager ) # Set the global short creator in the router api.set_short_creator(short_creator) logger.info("Short Video Maker started successfully!") logger.info(f"Server running on port {config.port}") @app.get("/health") async def health_check(): """Health check endpoint""" return {"status": "ok"} @app.get("/") async def read_root(): """Serve the web UI""" static_path = Path(__file__).parent / "static" / "index.html" if static_path.exists(): return FileResponse(static_path) return {"message": "Short Video Maker API", "docs": "/docs"} # Include API router app.include_router(api.router) # Mount static files if they exist static_dir = Path(__file__).parent / "static" if static_dir.exists(): app.mount("/static", StaticFiles(directory=str(static_dir)), name="static") if __name__ == "__main__": import uvicorn uvicorn.run( "app:app", host="0.0.0.0", port=config.port, log_level=config.log_level.lower() )