SCENE_FONT defaults in config.js point at Debian's font layout, which does not exist in the Alpine runtime image; drawtext only rendered via fontconfig fallback. Pin the Alpine paths in the Dockerfile env. Also add LAST_STATE.md (E2E test results + approved plan for the OBS-style panel rework) and the OBS reference screenshot for the redesign. Co-Authored-By: Claude Code <noreply@anthropic.com>
99 lines
6.3 KiB
Markdown
99 lines
6.3 KiB
Markdown
# LAST_STATE — 2026-09-02
|
||
|
||
Session sign-off snapshot. Read this first when resuming the multistreaming work.
|
||
|
||
## 1. Done: multistreaming E2E test (podman) — all passing
|
||
|
||
Tested the whole app in rootless podman: built `multistreaming:test` from
|
||
`services/multistreaming/Dockerfile`, ran with `--network host`, `AUTH_MODE=local`, volume
|
||
`ms-test-data`.
|
||
|
||
- HTTP API smoke: health, auth config, providers, register/login/session, `/api/me`, `/api/state`.
|
||
- RTMP ingest: published 12s `testsrc2` with host ffmpeg → feed went live in state, cleaned up on unpublish.
|
||
- Passthrough fanout: `-c copy` child pushed to a local `ffmpeg -listen 1` RTMP sink on :1936;
|
||
sink file probed as h264 1280×720, 12.004s — exact copy, 0 restarts.
|
||
- Scene composition: grid scene + text overlay activated → passthrough suspended, composed child
|
||
ran; sink file h264 1920×1080 + aac program audio; drawtext overlay confirmed rendered
|
||
(white-glyph pixel analysis; fanout log shows the correct filter graph).
|
||
- Persistence: accounts/rooms/feeds survived container recreation (volume).
|
||
|
||
Scratch scripts: `/tmp/ms_test/` (passthrough.sh, scene.sh, verify-fix.sh, ids.txt…).
|
||
Test recipe in Claude memory: `memory/multistreaming-podman-test.md`.
|
||
Test container `ms-test` may still be running (panel :8080); teardown:
|
||
`podman rm -f ms-test && podman volume rm -f ms-test-data`.
|
||
|
||
## 2. Done: Dockerfile font path fix (committed)
|
||
|
||
`src/config.js` defaults `SCENE_FONT`/`SCENE_FONT_BOLD` to Debian's
|
||
`/usr/share/fonts/truetype/dejavu/`, which does not exist in the Alpine image (fonts live in
|
||
`/usr/share/fonts/dejavu/`). drawtext only worked via FFmpeg's fontconfig fallback.
|
||
Fixed by setting the Alpine paths as ENV in `services/multistreaming/Dockerfile`. Rebuilt,
|
||
re-verified (fanout log shows the correct fontfile, overlay still renders).
|
||
|
||
## 3. In progress: OBS-style rework of the web panel (`services/multistreaming/web`)
|
||
|
||
Reference image: `reference1.png` (repo root) — an OBS Studio screenshot:
|
||
left dock Scenes+Sources, center program canvas, right dock Audio Mixer + Scene Transitions +
|
||
Controls, bottom status bar. (Image viewing is broken in this environment; the layout was decoded
|
||
via OCR.)
|
||
|
||
**User-approved target layout — variant B:**
|
||
|
||
```
|
||
┌──────────┬──────────────────────┬───────────────┐
|
||
│ SCENES │ │ CONTROLS │
|
||
│ │ PROGRAM PREVIEW │ Start/Stop │
|
||
│ SOURCES │ (live feed) ├───────────────┤
|
||
│ (media) │ │ Rooms/Vaults │
|
||
│ ├──────────────────────┤ User/Members │
|
||
│ │ MIXER │ TRANSITIONS│ │
|
||
└──────────┴──────────────────────┴───────────────┘
|
||
```
|
||
|
||
- **Left dock**: Scenes + Sources (media feeds) + Destinations (output routing) + Images.
|
||
- **Center**: simulated 16:9 program canvas; beneath it Audio Mixer + Scene Transitions panels;
|
||
OBS-style slim status bar at the bottom.
|
||
- **Right sidebar**: Streaming Controls + app nav (rooms/vaults/user, moved from the left) +
|
||
Members. The current left `AppSidebar` and right `RoomSidebar` are both absorbed into this one
|
||
right sidebar.
|
||
- **Simulated program canvas** (no real video pipeline): render from scene data — grid/PiP layout
|
||
math mirroring backend `src/compose.js` (grid cell = floor(W/cols) × floor(H/rows), single live
|
||
feed promoted fullscreen, PiP main fullscreen + 480×270 window top-right); slot boxes with feed
|
||
names + LIVE badges; text/image overlays at their real coordinates scaled to the canvas
|
||
(text: x,y,fontSize,color,bold; image: x,y,width,height,opacity, src `/api/images/:id/file`).
|
||
Passthrough mode (no active scene): live feeds in a simple grid. Scene activate crossfades the
|
||
canvas (CSS transition keyed on `activeSceneId`).
|
||
|
||
**Design decisions already made:**
|
||
|
||
1. **Mixer**: active scene → one channel per scene-output with functional audio-routing control
|
||
(Program/Silent/Feed via `api.updateSceneOutput`) + animated meter when `runtime.running`.
|
||
Passthrough → channels = live feeds, decorative animated meters only (no real levels exist).
|
||
2. **Transitions**: "Fade" + duration slider (localStorage, client-side only) controlling the CSS
|
||
crossfade of the simulated canvas on scene activate. Real video crossfade = future backend work.
|
||
3. **Controls**: Start Streaming (existing `GrantDialog` flow), **Stop Streaming** (wire the
|
||
currently unused `api.stopStream` — zero call sites today), per-account grant/live status.
|
||
No Studio Mode / Recording / Virtual Camera (no backend equivalents).
|
||
4. **Right sidebar**: Controls + NavVaults + NavRooms + NavUser + Members; renders vaults/rooms/user
|
||
even without a room open (Controls/Members room-only).
|
||
5. **HomeView** unchanged, just rendered in the center column without a left sidebar.
|
||
6. Keep prop-drilling + 3s `api.state()` polling (src/lib/use-app.ts); no state rewrite.
|
||
7. SceneEditorDialog / ImageUploader / PromptDialogs stay dialogs; only mounting points move.
|
||
|
||
**Current codebase facts (from exploration):**
|
||
|
||
- Shell: `src/App.tsx` (SidebarProvider > AppSidebar + SidebarInset{header+RoomView|HomeView} +
|
||
RoomSidebar; global dialogs at App level). No router; nav via useApp `screen/roomId`.
|
||
- Components: `app-sidebar.tsx`, `room-sidebar.tsx`, `room-view.tsx` (stacked cards), `scene-panel.tsx`,
|
||
`scene-editor.tsx` (606-line dialog), `dialogs.tsx` (GrantDialog 428-515), `image-upload.tsx`,
|
||
`home-view.tsx`, `nav-*.tsx`, `theme-provider.tsx` (`useTheme` unused in UI).
|
||
- shadcn ui/ has sidebar/card/dialog/select/switch/toggle-group/badge/tooltip etc.
|
||
**Missing: slider** (build `ui/slider.tsx` from the `radix-ui` unified package already in
|
||
dependencies — no new npm deps).
|
||
- `lib/api.ts` has every endpoint needed; `lib/types.ts` covers all state shapes.
|
||
- Dark theme tokens are neutral gray (`src/index.css`); OBS look is dark blue-gray — subtle token
|
||
tint planned.
|
||
|
||
**What remains:** implement the layout (no code written yet). The full implementation plan
|
||
(component-by-component, canvas math, crossfade pattern, styling tokens, order, risks) is in
|
||
`~/.claude/plans/starry-tickling-grove.md`.
|