File size: 1,809 Bytes
8986c3d 0a81ef3 8986c3d 0a81ef3 8986c3d 0a81ef3 8986c3d 0a81ef3 8986c3d 0a81ef3 8986c3d 0a81ef3 8986c3d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | from pathlib import Path
from fastapi import APIRouter, HTTPException, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from app.services.engine_registry import get_engine_registry
from app.services.job_store import get_job, list_jobs
templates = Jinja2Templates(
directory=str(Path(__file__).resolve().parent.parent / "templates")
)
router = APIRouter(prefix="", tags=["ui"])
UI_MODEL_LABELS = {
"supertonic-2": "Supertonic",
"kitten-tts-micro-0.8": "Kitten",
"kokoro": "Kokoro",
"melo-en": "Melo",
}
@router.get("/", response_class=HTMLResponse)
async def index_page(request: Request) -> HTMLResponse:
registry = get_engine_registry()
ui_models: list[dict[str, str]] = []
voice_map: dict[str, list[dict]] = {}
for model, label in UI_MODEL_LABELS.items():
try:
engine = registry.get_engine(model)
ui_models.append({"id": model, "label": label})
voice_map[model] = [
{"alias": b["alias"], "canonical_name": b["canonical_name"]}
for b in engine.list_voice_bindings()
if b.get("source") != "private"
]
except Exception:
continue
return templates.TemplateResponse(
"index.html",
{
"request": request,
"ui_models": ui_models,
"voice_map": voice_map,
"recent_jobs": list_jobs(limit=5),
},
)
@router.get("/jobs/{job_id}", response_class=HTMLResponse)
async def job_page(request: Request, job_id: str) -> HTMLResponse:
job = get_job(job_id)
if job is None:
raise HTTPException(status_code=404, detail="Job not found")
return templates.TemplateResponse("job.html", {"request": request, "job": job})
|