mobile: add a phone dashboard on a second port (8443) — Live + Archive

A new mobile dashboard is served on a second host port (8443) mapped to the
same backend, so the recorder/supervisor is not duplicated. main.py detects
the mobile port via the Host header and serves mobile.html instead of the
desktop index. The mobile SPA has two modes: Live (one camera with a selector)
and Archive (camera + date + segment list). Video is delivered as server-side
H.264 (live.mp4 / play.mp4 transcode) so a plain <video> plays on any phone.
Bottom tab bar, dark theme, safe-area aware.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 23:36:50 +05:00
parent 157893b516
commit c91f82bf28
6 changed files with 234 additions and 4 deletions
+11 -2
View File
@@ -28,6 +28,13 @@ logging.basicConfig(
log = logging.getLogger("nvr")
FRONTEND_DIR = os.path.join(os.path.dirname(__file__), "..", "frontend")
# Мобильный dashboard: тот же бэкенд слушает один порт, но в docker проброшен второй
# хост-порт (8443→8090). Запрос на него приходит с Host ".. :8443" → отдаём mobile.html.
MOBILE_PORT = os.environ.get("NVR_MOBILE_PORT", "8443")
def _is_mobile(request: Request) -> bool:
return request.headers.get("host", "").endswith(":" + MOBILE_PORT)
@asynccontextmanager
@@ -109,8 +116,10 @@ app.include_router(ws.router)
# ── фронтенд ────────────────────────────────────────────────────
@app.get("/")
async def index() -> FileResponse:
return FileResponse(os.path.join(FRONTEND_DIR, "index.html"))
async def index(request: Request) -> FileResponse:
# на мобильном порту — мобильный dashboard (Live одной камеры + Архив)
page = "mobile.html" if _is_mobile(request) else "index.html"
return FileResponse(os.path.join(FRONTEND_DIR, page))
@app.get("/archive")