Files
speech/app/main.py
du5t 665ff8a659 Rename project from asr-v2 to speech
The project now covers both ASR and TTS, so "asr-v2" no longer fits.
Renames: quadlet (asr-v2.container -> speech.container, container
name, image tag), build.sh, FastAPI/UI title, and the OIDC env var
prefix (ASR_V2_* -> SPEECH_*, matching the renamed Authentik
provider/application slug "speech"). Internal Python packages
(asr/, tts/, core/) were already named generically and don't change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 15:25:56 +09:00

62 lines
2.1 KiB
Python

from __future__ import annotations
from pathlib import Path
from typing import Any, Dict
from fastapi import Depends, FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse, HTMLResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
from starlette.middleware.sessions import SessionMiddleware
from asr.config import ensure_runtime_dirs
from asr.router import router as asr_router
from asr.router import ws_router as asr_ws_router
from core.auth import SESSION_SECRET_KEY, require_login
from core.auth import router as auth_router
from tts.router import router as tts_router
app = FastAPI(title="Speech Gateway", docs_url="/docs", redoc_url="/redoc")
app.add_middleware(
SessionMiddleware,
secret_key=SESSION_SECRET_KEY,
same_site="lax",
https_only=False, # 아직 전용 도메인/TLS가 없어 내부 IP:포트(http)로 접근하기 때문
max_age=14 * 24 * 3600,
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
UI_DIR = Path("/app/ui")
app.include_router(auth_router, prefix="/auth", tags=["auth"])
app.include_router(asr_router, prefix="/asr", tags=["asr"], dependencies=[Depends(require_login)])
app.include_router(asr_ws_router, prefix="/asr", tags=["asr"]) # 인증은 핸들러 내부에서 세션으로 직접 체크
app.include_router(tts_router, prefix="/tts", tags=["tts"], dependencies=[Depends(require_login)])
@app.on_event("startup")
def startup() -> None:
ensure_runtime_dirs()
if UI_DIR.exists():
app.mount("/ui", StaticFiles(directory=str(UI_DIR), html=True), name="ui")
app.mount("/assets", StaticFiles(directory=str(UI_DIR / "assets")), name="assets")
@app.get("/health")
def health() -> Dict[str, Any]:
return {"status": "ok", "ui_installed": UI_DIR.exists(), "api": "/docs"}
@app.get("/", response_class=HTMLResponse, dependencies=[Depends(require_login)])
def root() -> Any:
index = UI_DIR / "index.html"
if index.exists():
return FileResponse(index)
return JSONResponse({"status": "ok", "message": "UI not installed", "api": "/docs"})