docs: Live Control Room — multiview, switcher, audio, overlays

The engineering guide still called the control room 'planned' while it
ships: multiview grid (2x1-4x4/custom, 4 live HLS tiles, tap-to-focus,
adaptive preview polling), broadcast switcher (PST/TAKE/CUT semantics,
lock, override modes), per-slot + master audio, overlay editor
(lower_third/chyron/logo/clock, layers, rendered revisions), signed
previews and the transactional director behind it. User manual gets the
operator walkthrough (§7.1); engineering guide documents the media-
control architecture and corrects the Level-2 status section; admin
guide gets permissions, PUBLIC_ORIGIN, capacity and tally notes.
This commit is contained in:
glass beadian 2026-10-14 12:17:24 +00:00
parent b8671113f5
commit ced5e5da63
3 changed files with 59 additions and 5 deletions

View file

@ -127,7 +127,7 @@ Route: `PATCH /connections/:id/publish-governance` (requires `chatgov.manage`).
## 6. Frontend (apps/web)
Tailwind v4 `@theme` tokens (dark-first OKLCH, `@theme inline` brand hook for tenant theming), hand-rolled primitives, cmdk palette, TanStack Virtual streams (500+ items/column, scroll-into-view), Tiptap compose with per-platform char counters/previews. **Streams flagship:** capability-gated amplify bars, keyboard `j/k` navigate, `r` repost, `q` quote. All data from `src/lib/` mock-registry (fixtures are seeded-deterministic). QA: `apps/web/scripts/visual-qa.mjs` — 14 states, 0 console errors; byte-diff confirms every interaction renders.
Tailwind v4 `@theme` tokens (dark-first OKLCH, `@theme inline` brand hook for tenant theming), hand-rolled primitives, cmdk palette, TanStack Virtual streams (500+ items/column, scroll-into-view), Tiptap compose with per-platform char counters/previews. **Streams flagship:** capability-gated amplify bars, keyboard `j/k` navigate, `r` repost, `q` quote. The Control Room (`app/(main)/control-room/`) runs on the live API — signed preview taps, realtime tally over the websocket client, fixture fallback when offline. QA: `apps/web/scripts/visual-qa.mjs`.
## 7. Testing strategy
@ -150,9 +150,17 @@ pnpm --filter @tactical-media-broadcast-hub/api test
`/healthz` (liveness), `/readyz` (TCP probes: postgres/redis/temporal with per-component status). OTel OTLP tracing skeleton (disabled-safe without collector). Structured pino logs with credential-key redaction. Grafana (3001) provisioned against Prometheus (9090). Full metrics rollout is WP14.
## 9. Level 2 systems *(planned — designs in proposal.md §4.4)*
## 9. Level 2 systems — status
Live Source Monitor (adaptive polling, anti-flapping, per-host budgets); media engine (persistent encoder, graph-rewire switching, GStreamer decision gate); Auto Director (policies/rules/override/program-lock); control room (Preview/Program, TAKE/CUT); archive/grabber/crosspost (S3-mandated, encrypted, content-deduped).
Shipped and wired end-to-end:
- **Media control / director** (`apps/api/src/media-control/`, `apps/api/src/production/`): the `PUT desired` / `take` / `cut` / `pst-select` / `lock` / `override` surface. Each command is a single PostgreSQL transaction — channel row `FOR UPDATE`, idempotency receipt lookup, director-state fold (locked/override), bus moves, capacity admission (§4.4 quota; over-quota rolls back everything, a stop drains the pending queue), desired-version floor across DB+Redis, and an `audit_append` receipt (`director.<op>`, the transactional outbox). The worker observes desired snapshots over signed channels and reports the **realized version**; tally in the UI is worker-observed state, never optimistic.
- **Production spec** (`production.ts`, mirrored in `apps/media-worker`): scenes (`single/pip/2x1/2x2/3x3/4x4/custom`, per-slot `fit`, per-slot audio `off/on/primary` + gain, ≤1 primary slot), sources (HLS URL or video-asset playlist), overlays (`lower_third/chyron/logo/clock`, layers 0–7, rendered revisions as content-addressed PNGs, chyron speed/strip params, server clock), transitions (`cut` or `fade` 300–2000 ms), program master gain. Strict parsers reject injectable strings (`;`, `[`, `,`, `'`, `movie=`) so nothing rides along into FFmpeg graphs.
- **Control Room UI** (`apps/web/src/app/(main)/control-room/`): multiview grid (2x1–4x4/custom, up to 4 live HLS tiles, tap-to-focus, visibility-gated 1 s/2 s preview polling), switcher bar (PST/TAKE-at-frame-boundary/CUT-immediate, lock, override modes `until_released/five_minutes/until_source_offline/until_next_event`), PST preview, audio monitor, overlay editor (`director.change_layout`), fixture mode when offline. Permission gates: `media.view`, `director.view`, `director.take`, `director.lock_program`, `director.override_auto`, `director.change_layout`, `media.manage`.
- **Signed previews** (`production/preview.ts` + controller): capability URLs (expires+HMAC) minted by the authenticated endpoint; the public read route is same-origin only, serves plaintext renders, never redirects encrypted S3 objects, ETag/304-aware.
- **Worker fence** (`apps/api/src/director/`): internal `state/fence/apply` endpoints the worker uses to apply desired snapshots under a fencing token; web ingest, PeerTube and the transcode pool per their own docs.
Still planned: media-engine graph rewiring beyond the current FFmpeg-normalize path, LLM video AI (design only), content search rollout.
## 10. Key file map
@ -165,6 +173,8 @@ Live Source Monitor (adaptive polling, anti-flapping, per-host budgets); media e
| RBAC guard | `apps/api/src/rbac/rbac.guard.ts` |
| Audit chain | `migrations/001_tenants.sql` (SQL) + `apps/api/src/audit/` |
| Publishing + publish governance + amplify | `apps/api/src/publishing/`, `apps/scheduler/src/activities/dispatch-gate.ts` |
| Media control / director / production spec | `apps/api/src/media-control/`, `apps/api/src/production/`, `apps/media-worker/src/production.ts` |
| Control Room UI | `apps/web/src/app/(main)/control-room/`, `apps/web/src/components/control-room/` |
| Matrix SSO broker | `apps/api/src/matrix-sso/` |
| Connector SDK | `packages/connector-sdk/src/` |
| Frontend mock-registry | `apps/web/src/lib/` |