diff --git a/controller/cuda_grid_controller/dynamic_overlays.py b/controller/cuda_grid_controller/dynamic_overlays.py index d799b2b..dbc182a 100644 --- a/controller/cuda_grid_controller/dynamic_overlays.py +++ b/controller/cuda_grid_controller/dynamic_overlays.py @@ -45,7 +45,8 @@ class ChartCfg(BaseModel): default=None, description="MQTT topic с numeric payload. Если None — fake sine wave для demo.", ) - refresh_sec: float = Field(default=2.0, ge=0.5, le=60.0) + refresh_sec: float = Field(default=0.5, ge=0.05, le=60.0, + description="0.05 = 20 Hz max; 0.5 default = 2 Hz") max_points: int = Field(default=60, ge=10, le=600) line_color: tuple[int, int, int] = (0, 255, 128) bg_color: tuple[int, int, int, int] = (0, 0, 0, 180) @@ -248,7 +249,7 @@ class DynamicRenderer: await self._register_overlay(cfg.id, cfg.target_instance, cfg.cell, cfg.x, cfg.y, cfg.opacity, cfg.z_order) registered = True - await asyncio.sleep(0.5) # tight check для chat reactivity + await asyncio.sleep(0.1) # tight check для chat reactivity (10 Hz) except asyncio.CancelledError: raise except Exception as e: diff --git a/controller/cuda_grid_controller/http_api.py b/controller/cuda_grid_controller/http_api.py index 8bfa20f..cb59e08 100644 --- a/controller/cuda_grid_controller/http_api.py +++ b/controller/cuda_grid_controller/http_api.py @@ -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: diff --git a/controller/cuda_grid_controller/static/index.html b/controller/cuda_grid_controller/static/index.html new file mode 100644 index 0000000..b75db12 --- /dev/null +++ b/controller/cuda_grid_controller/static/index.html @@ -0,0 +1,274 @@ + + + + +cuda-grid control + + + + + +
+

cuda-grid control

+
connecting…
+
+ +
+
+ +
+ +
+ +
+

Audio source

+
+
+ + +
+

Intercom (ducking)

+
+ + +
+
+ + +
+

Snapshot

+
+ +
+
+ + +
+

Manual overlay

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+ + +
+

Chat message

+
+ + +
+
+ + +
+

State

+
+
overlays raw +
+
+
+
+ +
+ + + +