From 7acf044e4a180c0a635e0164519a8153019e2495 Mon Sep 17 00:00:00 2001 From: gramps Date: Thu, 12 Nov 2026 08:24:27 -0800 Subject: [PATCH] =?UTF-8?q?docs(handoff):=20bitrate=20correction=20landed?= =?UTF-8?q?=20=E2=80=94=20four=20units,=20next=20is=20the=20creator's=20li?= =?UTF-8?q?ve=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Scope justification: the only file outside this commit's declared scope is Assets/starting-background.jpg, the creator's replacement art still awaiting their visual check (recorded in the landmines). --- HANDOFF.md | 59 +++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/HANDOFF.md b/HANDOFF.md index cc12cef..9664884 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -1,39 +1,40 @@ -# HANDOFF — 2026-11-12 (bitrate correction, 4 units; unit 1 landed) +# HANDOFF — 2026-11-12 (bitrate correction: all four units landed) ## State -- `main`; `b265d42` is the latest pushed commit. `1e3a4f7` and everything after are local. -- **Done:** TASK 35 scene-linked audio, TASK 55 disk hygiene, TASK 65 replay clips, TASK 37 defaults/current split. -- Recovery fixes: step-down closes/recreates audio in order; recovery notifications/stops marshal to the dispatcher. -- App Settings: six toast positions; sticky/click-to-dismiss alerts (off by default preserves timers). -- **`1e3a4f7`:** `OutputProfile.EntitlementEnforced = false` — Release builds can select 60 fps pre-release, - and the licence indicator row is suppressed while nothing is limited. Flip at launch. -- Creator test was stable (~31 fps, 0.2% drop) but **the stream's own readout averaged ~5.1 Mbps against an - @8 target**: the args pass `-b:v/-maxrate/-bufsize` with no `-rc`, so `h264_nvenc` ran its default VBR - and undershot. Not a machine limit (1.8 ms render, 0 stalls) and not a YouTube step-down (no step-down - logged). Diagnosis is args, not ingest. -- Verification: **667 tests green, clean build with 0 warnings** (`./scripts/verify.sh`). +- `main`; `b265d42` is the latest pushed commit. Everything after it is local. +- **Bitrate saga closed.** An @8 stream averaged 5.1 Mbps because the args were capped VBR, not CBR: + measured on the bundled build, a static frame at `-b:v 2000k` gave 9 kbps with NVENC's default and + 1951 kbps with `-rc cbr`. Not the machine (1.8 ms render, 0 stalls) and not YouTube (no step-down + logged). `700c7a8` fixes it: `-rc cbr` for NVENC/AMF, nothing for QSV (it infers CBR from + bitrate == maxrate) and nothing for OpenH264 (no measurable difference). +- `1e3a4f7` pre-release switch (`OutputProfile.EntitlementEnforced = false`) lets a Release build select + 60 fps, and suppresses the licence row while nothing is limited. Flip at launch. +- `1708667` ladder retargeted to 1080p60@12 / 1080p30@10 / 720p@6; `93719a2` makes the step-down floor + the tier's YouTube minimum (6/5/3) instead of a flat 3. +- `f2cab5c` the creator sets the rate (per-tier Mbps box, persisted, clamped only at the YouTube minimum); + `b0f8263` files each session locally and proposes a rate between sessions on consent alone. +- Verification: **672 tests green, clean build with 0 warnings** (`./scripts/verify.sh`). ## Next action -- Unit 2 of 4: **explicit CBR** in `Services/Encoder/FfmpegArgs.cs`, spelled per encoder (NVENC/AMF `-rc cbr`; - QSV and OpenH264 differ — verify, do not guess). One test/commit. -- Unit 3: rate presets + free-form Mbps per tier (min/rec/max from YouTube's H.264 table; default 12 at - 1080p60, 10 at 1080p30, 6 at 720p), tier minimum becomes the step-down floor. -- Unit 4: local per-tier history; propose a rate change between sessions only, ≥10% above a zero-step - high-water mark across 5 sessions, or repeated step-downs downward; explicit consent, "keep mine" remembered. -- Then resume **40·A/C/D → Move → 9·5 → 14·16/17/18 → 66 → 67 → 68 → 69 → 70 → 36**. -- Do not push app commits absent a checkpoint request. +- **Creator check pending in a real Release stream**: 60 fps selectable, live bitrate sitting near the + rated number instead of drifting, the Mbps box and the rate prompt behaving. +- Resume the queue: **40·A/C/D → Move → 9·5 → 14·16/17/18 → 66 → 67 → 68 → 69 → 70 → 36**. +- Ask creator before TASK 68 (first-run ON-AIR default); settle the Release single-instance mutex + before the gold pass. Do not push absent a checkpoint request. ## Landmines - `Assets/starting-background.jpg` is modified in the working tree, **awaiting the creator's visual check** — - do not commit it as part of another unit. -- `ChromaKeyRealClipTests.RealClip_PlaysAtItsNativeRate` failed once in a full run and passed alone: a - load-sensitive flake, not the known pre-existing pair. Watch it; do not chase it as a regression. -- Early step-down path reuses `ChangeEncoderAsync`, so every rate change is a full encoder relaunch. -- Preview frame-source layers need a `PreviewPane` DataTrigger; pin each new type with a visibility test. -- Media sessions are keyed by path + look; never acquire by raw path. -- Audio pipe allows one server per name; DEBUG suffixes it, Release does not. -- Any test constructing `MainWindow` must use a temporary `LayoutPathOverride` and clear it in `finally`. -- Build with the Windows `dotnet.exe` host from WSL; read render numbers in Release. + do not commit it with another unit. +- **Two load-sensitive flakes, not regressions**: `ChromaKeyRealClipTests.RealClip_PlaysAtItsNativeRate` + and `AudioPipelineTests.Mix_WithFiltersDuckAndGain_Lands_On_AudioPipe` failed once each in a full run + and passed alone; verify.sh only tolerates its known pair, so rerun the single test first. +- `RatedFor` must not cache before `_layoutStore` exists (the ctor resolves the default tier first), or + the shipped default shadows the creator's stored rate for the whole run. +- Every rate change is a full encoder relaunch (`ChangeEncoderAsync`), so mid-show rate changes stay out. +- A tier's rate is read through `MainViewModel.EffectiveQuality`; a call site using the raw tier + streams the shipped default. +- `MainWindow` tests need a temporary `LayoutPathOverride`, cleared in `finally`; build with the Windows + `dotnet.exe` host from WSL and read render numbers in Release.