Spaces:
Sleeping
Sleeping
| 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=["*"], | |
| ) | |
| 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}") | |
| async def health_check(): | |
| """Health check endpoint""" | |
| return {"status": "ok"} | |
| 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() | |
| ) | |