cpu-tts / app /api /ui.py
grimshaw's picture
Improve storage fallback and UI source editor
0a81ef3 verified
Raw
History Blame Contribute Delete
1.81 kB
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})