Files
esports/streamer/ALPHA_TEST.md
Stan Runge 54444a77f0 feat: add native Windows broadcaster and live score modules
- streamer/windows: vash-broadcast.exe (setup/login/start/stop/status/doctor)
  with per-instance OBS, tosu and FFmpeg, a supervised worker, OCR room
  selection and OBS scene reconciliation; built and tested on Linux only
- streamer/relay.ts shared with Vash TV; Cloudflare Access proxy for dev/staging
- worker status validation and live score helpers for the site
- STREAMING_HANDOFF.md and streamer/ALPHA_TEST.md record what is unverified

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:02:25 +00:00

13 KiB

Understanding and testing the broadcaster

Reviewed against the working tree on 2026-09-29, including the existing uncommitted Windows worker. This describes the local implementation; it does not establish what is deployed or installed on the Windows PC.

The intended product is one broadcaster that handles an entire match after initial setup. The current implementation has much of that machinery, but the complete Windows broadcast remains unverified and starting/stopping with match activity is missing.

What runs where

Location Responsibility
Existing Vash VM Website, database, match hosting/refereeing, choosing a match, supplying overlay pages and stream settings
Windows PC Run osu!tourney, capture gameplay and audio, read live scores with tosu, compose the overlay in OBS, encode video, relay to destinations
Streaming destinations and configured storage Receive the stream; storage supplies Vash's live video and recordings

The PC connects to the existing website. It does not need another Vash application server or the server's database/IRC credentials. It needs its channel token and, for a protected dev/staging site, a Cloudflare Access service token.

OBS's hardware encoder is the sensible starting point for the recorded RX 7900 XT configuration. OBS recommends hardware encoding to reduce CPU load; actual resolution, team size, audio and reliability still need measurement. See OBS hardware encoding.

Similar names, different capabilities

Component What it actually does
Broadcast channel and director Choose one match, a tournament's matches, or a match scored by fixed rules. Automatic selection stays through a map and holds the final result for 30 seconds. It is a rules-based director.
Overlay Browser page with scenes that follow match state. An overlay alone contains no captured osu! gameplay.
vash-broadcast.exe New native Windows installer and supervised worker. Intended to manage OBS, osu!tourney room selection, tosu and the local relay. This is the path aligned with unattended broadcasting.
vash-streamer.exe Older agent used with manually prepared tools. It is a different executable with a different setup flow.
Vash TV Container that renders graphics and scores, or relays video supplied by OBS. Screen mode alone is not gameplay broadcasting.
Tourney container Separate Linux/Wine gameplay implementation. The documented path still needs a real host test.
Platform destinations RTMP/RTMPS URLs and stream keys. These are not complete social-platform account or broadcast-event integrations.

The native Windows worker already includes the relay. Following the older WSL/manual OBS setup as well introduces a second workflow that is unnecessary for this path.

Gaps and confusing behavior found

  1. Automatic selection does not mean automatic airtime. The Go live action sets a saved live flag. The worker follows it. There is no match-driven rule here that starts when matches appear and ends after the last result. Leaving the flag on keeps the broadcast requested even when the director is idle.
  2. Go live does not provision a computer or container. A worker must already be running. The Windows installer registers a scheduled task, but the website has no cloud provisioning path.
  3. On air is not proof of video delivery. The Stream page's main label uses a recent broadcast-session heartbeat. The relay opens a session before a video source has successfully started. Worker status is more specific; verify obsStreaming, relayReceiving, the destination and the actual picture/audio.
  4. The Windows path is implemented, not proven on hardware. The handoff records no completed Windows run. Tests use fake desktop/OBS services and cannot validate capture, audio, OCR clicks, real downloads, remembered osu! login, GPU encoding or reboot recovery.
  5. The desktop is part of the system. This worker runs in a signed-in Windows desktop and uses OCR and mouse input to select a room. Keeping the PC powered on alone is insufficient: locked-desktop behavior, display availability and reboot sign-in need testing. The room-selection method also means the PC may be unsuitable for simultaneous personal use.
  6. One gameplay worker per PC. The implementation enforces a host lock because tosu can read another instance's osu!tourney processes. Dev/staging/prod can have separate configurations, but they cannot all broadcast gameplay concurrently on this PC.
  7. Documentation mixes paths. The root README sends Windows users to the manual WSL guide. The Broadcast introduction still describes adding an OBS browser source manually. The Go live action still returns a message telling the user to start Vash TV. The newer Windows section describes the intended automated path.
  8. Cloud is a future host change plus integration work. A persistent Windows GPU VM is a plausible route for this worker; Windows-capable graphics instances exist, for example in EC2's accelerated instance families. The current encoder configuration accepts only AMD or x264, so using an NVIDIA machine requires adding NVENC support. Desktop/capture behavior must also be verified there. No provider, price or instance size has been selected.

Source anchors: director, Go live action, Stream page, worker, relay, encoder configuration, platform definitions.

First test: understand the overlay without broadcasting

  1. Open the dev site's dashboard with a user who can access the simulation lab and manage Broadcast channels.
  2. In Simulation lab, select the simulated lobby and start Bots vs bots → 1v1.
  3. Create a Broadcast channel following One match, select that match, and use Vash only for this browser-only test.
  4. Open the channel's overlay link. Watch the lobby, picks/bans, scores, map results and series result. The match's Sim lab controls can slow it down or finish a map.
  5. In Edit layout, check which components you actually want. Note unwanted features before removing or redesigning them.

No Go live action or OBS setup is needed to inspect the overlay. Simulated bots provide match data, not rendered osu! gameplay. Even in a real-lobby lab match, the simulated opponent has no gameplay client to capture.

Second test: the native Windows worker

Use the Windows setup instructions. Choose one environment and one channel for the test, with Over osu! gameplay, One match, landscape and initially 720p30. This is a conservative test setting, not a measured hardware limit.

One-time prerequisites are a signed-in/unlocked Windows desktop, an existing osu! stable executable to copy, and a usable spectator login with active supporter. The official osu!tourney setup guide requires supporter, a separate installation and a remembered login. Arrange the spectator account separately from the account playing the test match.

Build from the repository root, then transfer the executable to the Windows PC using an available connection:

bun run broadcast:build

In Windows PowerShell, from the folder containing the executable, replace the placeholders with the selected site's actual values:

.\vash-broadcast.exe setup --instance alpha --server https://YOUR_VASH_SITE --channel CHANNEL_ID --token AGENT_TOKEN --no-autostart
.\vash-broadcast.exe login --instance alpha
.\vash-broadcast.exe doctor --instance alpha
.\vash-broadcast.exe start --instance alpha
.\vash-broadcast.exe status --instance alpha
.\vash-broadcast.exe snapshot --instance alpha

For dev/staging behind Access, add --access-id ACCESS_CLIENT_ID --access-secret ACCESS_CLIENT_SECRET to setup. Login prints the instructions for its temporary screen viewer over an SSH tunnel. It is the one-time interactive step; subsequent matches should require no manual OBS scene or room setup. --no-autostart keeps this test instance from starting at Windows sign-in.

Configure OSU_TOURNEY_ACCOUNT on the matching Vash server before creating the real lobby so the host grants the spectator referee access. Use a real player match for the capture test; two real sides are necessary to prove both gameplay views.

Before pressing Go live, verify which destinations are enabled. That button requests transmission to all enabled destinations. With destinations disabled and recording/storage configured, it still uploads video for the site's playback; this is not necessarily a private local recording. First inspect the worker's OBS snapshot while off air.

After deliberately enabling the desired test output, press Go live and check:

Check Passing evidence
Lobby selection Correct lobby ID; spectating, with room confirmation in status
Picture Gameplay beneath the overlay; correct players; control panel cropped out
Scores and scenes tosu scores reach Vash; scenes change with the actual match
Audio Gameplay audio present and in sync; no duplicate or unintended desktop/microphone audio
Encoding Status/log reports AMD AMF hardware encoding, not a software fallback
Delivery OBS streaming, relay receiving, and the destination actually plays moving video with sound
Recording, if enabled Site playback works; ended recording includes the final map and result
Ending End stream stops OBS output and ends the session

For diagnostics:

.\vash-broadcast.exe logs --instance alpha -f
.\vash-broadcast.exe status --instance alpha --json
.\vash-broadcast.exe snapshot --instance alpha
.\vash-broadcast.exe stop --instance alpha

End stream clears the site's request to broadcast. Stopping just the worker does not clear that request, so restarting it while the channel is still armed can resume transmission.

Before calling it unattended

Test two consecutive matches with no manual room selection, a change in team size, an OBS/tosu restart, a temporary network interruption, Windows restart/sign-in, and a run lasting as long as a real event. Observe frame drops, audio sync, memory, destination reconnects and recording continuity. These are acceptance checks still to run, not results already obtained.

Separately decide whether airtime should follow match activity automatically or remain continuously enabled after one Go live action. The current implementation supports the latter behavior; the former needs an explicit policy and implementation.

Verification performed in this review

  • bun run test:streamer: 38 passed, 0 failed, after allowing local test-server sockets outside the sandbox.
  • bun --bun vitest run src/lib/broadcast/director.test.ts src/lib/broadcast/worker.test.ts: 7 passed, 0 failed, outside the sandbox. The sandboxed attempt stalled and was stopped.
  • bun run broadcast:build: passed, producing dist/vash-broadcast.exe.
  • No Windows host run, real gameplay stream, live social-platform transmission, cloud provisioning or long-duration test was performed in this review.

Application behavior was not changed by this review. Existing uncommitted implementation work was preserved.