Reported 2026-11-06: a Release instance crashed when clicking Go Live in test mode, while a Debug
instance was recording its window. The Windows event log gave the cause:
System.IO.IOException: All pipe instances are busy.
at System.IO.Pipes.NamedPipeServerStream.Create(...)
at ytLive.Services.Audio.NamedPipeAudioWriter.Start(...)
at ytLive.Services.Audio.AudioMixer.StartLive(...)
at MainViewModel.StartStreamingSession(...)
at MainViewModel.BeginTestStream(...)
at MainViewModel.StartFromPrimaryButton(...)
at System.Windows.Controls.Button.OnClick()
Two defects, both fixed:
1. **A button click could end the process.** `StartLive` throws when the pipe name is taken, and nothing
on the go-live path caught it. `TryStartAudioPipe` now catches, logs, toasts ("Another copy of
LlamaCasty is already using the audio pipe") and rolls the session back. Recording-only takes the same
path.
2. **The pipe name was a shared constant**, so a second instance could never go live on the same machine.
`InstanceProfile.AudioPipeName` appends the dev instance id (DEBUG only); Release keeps the plain name
so the normal single-instance case is unchanged. The encoder reads the same derived name, so mixer and
ffmpeg cannot disagree.
Tests: `AudioPipeInstanceTests` — a second server on one name throws (the collision is real), dev names
derive per instance, and a writer on a taken name throws rather than silently reusing the pipe.
Debug and Release both build clean.
44 lines
3.0 KiB
Markdown
44 lines
3.0 KiB
Markdown
# HANDOFF — 2026-11-05 (alert stack + media/chroma fixes)
|
|
|
|
## State
|
|
|
|
- `main`. TASK 21 (video layer + soundtrack), TASK 64 (green/blue screen) and TASK 32·4 (fragmented MP4)
|
|
are complete; TASK 49 is retired (YouTube owns chat moderation — we just don't paint tombstones).
|
|
- **Left panel alert stack** shipped: Steam licence indicator pinned at row 1 (`Entitlement 30 fps ·
|
|
Maximum 60 fps`, pin → close once owned, permanent while owned), event rows LIFO beneath, click →
|
|
About or the Logs tab with that event's lines painted. Detail: `docs/ai/ui-surface.md`.
|
|
- Video layer fixes this session: the preview-pane trigger whitelist (a video layer was invisible), a
|
|
quadratic frame copy that capped 1080p playback at 2 fps, and deadline pacing for video *and* audio.
|
|
- Tests: 575 green, 1m50s; `FAST=1 ./scripts/verify.sh` = 527 in ~62s.
|
|
|
|
## Next action
|
|
|
|
- **32·1 + 32·2 shipped**: blip retry (immediate/+1/+2/+3 s), and the RECONNECTING sign driven by the
|
|
status poll (4 s cadence while recovering) with **measured** elapsed/attempt only — the countdown was
|
|
dropped after the creator pointed out YouTube's cutoff depends on variables we cannot see. The
|
|
`chatEndedEvent` in the chat feed now prompts an immediate status check.
|
|
- **32·5 shipped**: ingest pre-flight (TCP, 2 s) aborts go-live before any API call, so a dead
|
|
network leaves no ghost broadcast.
|
|
- Next:
|
|
then 32·2/32·3 (countdown + Back on air) which need YOUR measurement take: pull the network on a
|
|
private stream and time how long YouTube holds the broadcast.
|
|
- Open loop: `32·4` is proven by construction only — kill ffmpeg mid-recording and play the file.
|
|
- Do not push absent a checkpoint request.
|
|
|
|
- **Steam is a wait, not a task:** partner account exists, identity verification pending, tax review in
|
|
Valve's queue (up to 30 business days). No app IDs, no store page, Release entitlement still fails
|
|
closed. Earliest realistic launch early-to-mid February 2027 — see `Distribution.md` §2.
|
|
|
|
## Landmines
|
|
|
|
- **The preview pane draws frame-source layers from a whitelist of DataTriggers.** A layer type with no
|
|
trigger is invisible in the preview while its decode looks healthy (alert box 2026-09-26, scoreboard,
|
|
video layer 2026-11-05). Add the trigger with the layer type; pin it with `MediaPreviewDisplayTests`.
|
|
- Nothing in the suite drives the real cursor any more; the drag arithmetic is pure (`DragReorderMathTests`).
|
|
- Integration tests constructing `MainWindow` must set a temporary `LayoutPathOverride` and clear it in `finally`.
|
|
- Media sessions are keyed by **path + look** (`MainViewModel.MediaSessionKey`); never acquire by raw path.
|
|
- **The audio pipe is one instance per machine.** `NamedPipeAudioWriter` allows a single server, so two
|
|
LlamaCasty processes cannot both go live. A DEBUG instance appends its id (`InstanceProfile.AudioPipeName`),
|
|
Release keeps the plain name; the Go-Live path catches the failure and reports instead of dying.
|
|
- Bundled FFmpeg stays outside the single-file exe (`ExcludeFromSingleFile="true"`).
|