controller: Phase 6+ — Web UI mini dashboard

Static HTML/JS dashboard в cuda_grid_controller/static/index.html, mounted
на /ui и / FastAPI endpoints. Vanilla JS + HLS.js (CDN) для video player.

Controls:
  Audio source — buttons из /audio/{instance} list, switch через POST
  Intercom — Start (music↓) / End (restore)
  Snapshot — opens PNG в new tab
  Manual overlay — form для rect/text/dim/icon types
  Chat — placeholder (info-toast про mosquitto_pub)
  State — refresh каждые 2 sec, shows layout/overlays_count + raw list

Player consumes HLS на http://server:8888/live/index.m3u8 (mediamtx).
TV не нужен — браузер на любом устройстве в LAN.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
gx
2026-05-21 05:27:27 +01:00
parent d8674e599d
commit d90c139dce
3 changed files with 289 additions and 3 deletions
+12 -1
View File
@@ -3,11 +3,13 @@
from __future__ import annotations
import asyncio
from pathlib import Path
from typing import Any
import structlog
from fastapi import Body, FastAPI, HTTPException
from fastapi.responses import Response
from fastapi.responses import FileResponse, Response
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel, TypeAdapter
from .config import Config
@@ -36,6 +38,15 @@ def create_app(
description="Control plane для vf_cuda_grid FFmpeg filter",
)
# Static UI — http://controller:8080/ui/
static_dir = Path(__file__).parent / "static"
if static_dir.exists():
app.mount("/ui", StaticFiles(directory=str(static_dir), html=True), name="ui")
@app.get("/")
async def root_redirect():
return FileResponse(static_dir / "index.html")
def _check_instance(name: str):
inst = next((i for i in cfg.instances if i.name == name), None)
if inst is None: