from __future__ import annotations import logging import os import threading import spaces from gradio import Server from app.config import get_settings from app.factory import create_app logger = logging.getLogger(__name__) GRADIO_DOC_ROUTES = {"/docs", "/openapi.json", "/redoc", "/docs/oauth2-redirect"} @spaces.GPU(duration=1) def _zero_gpu_probe() -> str: """Satisfy the ZeroGPU runtime requirement; the demo itself runs on CPU.""" return "ok" def _warm_whisper(transcriber) -> None: try: transcriber.warm_up() logger.info("Whisper model is loaded and ready") except Exception: logger.exception("Whisper warm-up failed; the first request will retry") settings = get_settings() api = create_app(settings) # Gradio's Server owns the outer FastAPI instance. Mount the real application at # the root so the dashboard, API, WebSocket, and docs are served unchanged. demo = Server(title=settings.app_name) @demo.get("/gradio_api/startup-events") def _gradio_startup_events() -> dict[str, str]: # Gradio's launch() probes this path. The root mount below would otherwise # shadow Gradio's own handler, and the probe would fail with a 404. return {"status": "ok"} demo.mount("/", api) demo.routes[:] = [ route for route in demo.routes if getattr(route, "path", None) not in GRADIO_DOC_ROUTES ] if os.environ.get("SPACE_WARMUP", "1") == "1": threading.Thread( target=_warm_whisper, args=(api.state.transcriber,), name="whisper-warmup", daemon=True, ).start() if __name__ == "__main__": demo.launch(ssr_mode=False)