Go Live: state the Windows-only window-audio limitation in the UI and docs

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 01:47:45 -05:00
parent b634413773
commit f737fc6289
4 changed files with 6 additions and 5 deletions

View File

@@ -205,7 +205,7 @@ asked by `configure.py --full`) can post when a stream starts.
embedded outpost → group policy (e.g. everyone in the server, or `streamers`+`editors`+`admins`). embedded outpost → group policy (e.g. everyone in the server, or `streamers`+`editors`+`admins`).
3. Dev box: `./deployLive.sh` builds `live/` and copies `dist/` to `/srv/live` (Caddy serves it directly). 3. Dev box: `./deployLive.sh` builds `live/` and copies `dist/` to `/srv/live` (Caddy serves it directly).
**Go Live** button (Chrome/Edge 141+ for window audio): broadcast a window from the browser (no OBS) as `<user>/HelmetCam-<date>` — key comes **Go Live** button (window audio: Windows + Chrome/Edge 141+; Linux/Mac get video only): broadcast a window from the browser (no OBS) as `<user>/HelmetCam-<date>` — key comes
from `/me/stream-key` (dumpd reads `/etc/vanguard/streamers.json`, identity from the Authentik header), so a from `/me/stream-key` (dumpd reads `/etc/vanguard/streamers.json`, identity from the Authentik header), so a
streamer's Authentik username must equal their MediaMTX name. streamer's Authentik username must equal their MediaMTX name.

View File

@@ -31,7 +31,7 @@ Source of truth: this repo, `techy/Media-Server-Setup` on the stack's own Gitea
| Editor | Mount the library as a drive | WebDAV, same URL | same | | Editor | Mount the library as a drive | WebDAV, same URL | same |
| Anyone in the Discord server | Watch recordings and clips by streamer and season | Jellyfin `https://watch.…/` | Discord (Authentik) | | Anyone in the Discord server | Watch recordings and clips by streamer and season | Jellyfin `https://watch.…/` | Discord (Authentik) |
| Anyone in the Discord server | Watch live: all active streams in dockable windows, audio follows focus, per-window mute/volume | Live portal `https://live.…/` | Discord (Authentik, domain-level) — live; viewer side not yet exercised during a stream | | Anyone in the Discord server | Watch live: all active streams in dockable windows, audio follows focus, per-window mute/volume | Live portal `https://live.…/` | Discord (Authentik, domain-level) — live; viewer side not yet exercised during a stream |
| Streamer | **Go Live** from the browser: pick the WarDogs window (+audio), streams as `<user>/HelmetCam-<date>`; no OBS needed | Live portal → Go Live | Discord; key fetched for the logged-in user — **verified end to end** (publish → `.live` → sweep → title folder) | | Streamer (Windows) | **Go Live** from the browser: pick the WarDogs window (+audio on Windows Chrome 141+; Linux/Mac video only), streams as `<user>/HelmetCam-<date>`; no OBS needed | Live portal → Go Live | Discord; key fetched for the logged-in user — **verified end to end** (publish → `.live` → sweep → title folder) |
| Devs | Host code, review, CI | Gitea `https://git.…/`, ssh 2222 | **local account** (Discord later) | | Devs | Host code, review, CI | Gitea `https://git.…/`, ssh 2222 | **local account** (Discord later) |
| Bot dev | Push code, restart container, read logs; web UI at `https://bot.…/` | Gitea + compose; `bot/AGENT.md` | web UI behind Discord (Authentik), once its provider exists | | Bot dev | Push code, restart container, read logs; web UI at `https://bot.…/` | Gitea + compose; `bot/AGENT.md` | web UI behind Discord (Authentik), once its provider exists |
| Admin | Add/remove streamers & editors, hostnames, bot token | `./configure.py` | ssh | | Admin | Add/remove streamers & editors, hostnames, bot token | `./configure.py` | ssh |

View File

@@ -22,6 +22,6 @@ Toolbar → **Go Live**: closes all viewer windows, fetches the logged-in user's
`/me/stream-key` (dumpd, identity from Authentik's header), opens Chrome's window picker (windows only, `/me/stream-key` (dumpd, identity from Authentik's header), opens Chrome's window picker (windows only,
audio requested), and publishes over WebRTC/WHIP to `<user>/HelmetCam-<date>` at ≤12 Mbps, H.264, up to audio requested), and publishes over WebRTC/WHIP to `<user>/HelmetCam-<date>` at ≤12 Mbps, H.264, up to
1440p60. Recording, the "is live" post, the sweep and Jellyfin follow exactly as for an OBS stream. 1440p60. Recording, the "is live" post, the sweep and Jellyfin follow exactly as for an OBS stream.
Window audio: Chrome/Edge 141+ (`windowAudio: "window"`); older browsers share the window without sound. Window audio: Windows only, Chrome/Edge 141+ (`windowAudio: "window"`). Linux/Mac Chrome captures tab audio only → window without sound; use OBS there.
Requires the Authentik username to equal the MediaMTX streamer name (configure.py keeps them in sync via Requires the Authentik username to equal the MediaMTX streamer name (configure.py keeps them in sync via
`/etc/vanguard/streamers.json`). `/etc/vanguard/streamers.json`).

View File

@@ -66,8 +66,9 @@ export default function GoLive({ onExit }) {
<input value={title} onChange={e => setTitle(e.target.value)} disabled={phase === 'capturing'} /> <input value={title} onChange={e => setTitle(e.target.value)} disabled={phase === 'capturing'} />
<div className="hint"> <div className="hint">
Click <b>Start</b>, then pick the <b>WarDogs</b> window in Chrome's dialog and tick <b>Share audio</b>. Click <b>Start</b>, then pick the <b>WarDogs</b> window in Chrome's dialog and tick <b>Share audio</b>.
Window audio needs <b>Chrome or Edge 141 or newer</b> (chrome://version). Older browsers capture the window Window audio needs <b>Windows</b> with <b>Chrome or Edge 141 or newer</b>. On Linux and Mac, Chrome can only
without sound. Capped at {MAX_KBPS / 1000} Mbps, up to 1440p60, H.264. capture audio from a browser tab, so the window comes through without sound — use OBS with the dock there.
Capped at {MAX_KBPS / 1000} Mbps, up to 1440p60, H.264.
</div> </div>
{err && <div className="err">{err}</div>} {err && <div className="err">{err}</div>}
<button className="primary" disabled={!key || phase === 'capturing'} onClick={start}>{phase === 'capturing' ? 'Waiting for the window picker…' : 'Start'}</button> <button className="primary" disabled={!key || phase === 'capturing'} onClick={start}>{phase === 'capturing' ? 'Waiting for the window picker…' : 'Start'}</button>