# HANDOFF — 2026-09-10 ## Branch / Commit State `main` HEAD = `1a39b09`, ahead of origin by 12, working tree carries THE recording-timing fix (uncommitted): count-based CFR emission in `FramePump.cs` + `-re` removal in `FfmpegArgs.cs`, plus this handoff / `ai.md` slice 9 / `MyMistakes.md` recipe correction. `tools/` holds `ticker.c` + the built `ticker` (WSL, unused by git yet). ## Recording TIMING — the fix (the "plays too fast" saga) **Root cause, proven by measurement (not guessed):** the pump's take-3 "rebase on overrun" reset `nextTick` to wall-now every time it fell behind, silently erasing missed slots. The pump delivered `215-219/300 per 5s` (~43fps) but ffmpeg muxes rawvideo by frame count at `-framerate 60` — no per-frame timestamps — so every recording played ~1.4x fast with stats that looked honest (a rebased frame is never "late"). `-re` on the demux was a second fighting pacer ("Resumed reading … after a lag" grew 0.79s→4.82s). **Fix (the OBS `video-io.c` shape — one frame per interval slot, deadline never reset):** 1. `FramePump.PumpAsync`: `while (now >= nextTick) { SubmitFrame(frame); nextTick += intervalTicks; }` — one submit per crossed slot; a slow render re-writes the current composite (judder, never a skip). `nextTick` NEVER rebases to wall-now. 2. `FfmpegArgs`: `-re` deleted from the rawvideo input; the pump is the pacer. **Verified:** build 0 warnings; full suite 288/289 — the sole failure (`Composite_FullScene_MasterPixels` line 109, pixel (1380,700) cyan vs magenta) ALSO fails with this fix stashed, i.e. pre-existing and untouched by it. DO NOT fix it here; it is a separate compositor investigation. ## NEXT STEP (ONE user run required) Record ~30s with the WSL ticker visible in the preview (`cd tools && ./ticker` in a terminal, Ctrl-C to stop), then check: - recording duration ≈ wall time (should be, by frame-count construction) - `%APPDATA%\ytLlive\startup.log` "FramePump stats:" shows ≈ n/n per 5s, n = 300 @60fps - NO "Resumed reading … after a lag" lines remain - ticker advances ~1s per second of footage ## Still Open - Web overlay: the pre-parse transparency injection (committed `1a39b09`) is NOT yet proven — both recorded diagnostic PNGs (`%TEMP%\ytLive-web-.png`) were 100% alpha=0 AND RGB=0 (an EMPTY capture, not an opaque one). Diagnosis "capture is empty" needs a fresh run; the first-capture dump may be the pre-load about:blank frame. Frozen pending the timing verification. - Audio silence: `no audio.mp4` measured -91dB (digital silence), 3KiB muxed audio stream — the named-pipe audio delivered ~nothing. Separate from timing; not yet touched. - Pre-existing: `Composite_FullScene_MasterPixels` (see above). ## Landmines - testhost shares startup.log with app — filter by time when triaging - testhost/exe lock DLLs: `taskkill /F /IM testhost.exe /IM ytLive.exe` before rebuild - Build via the Windows dotnet host: `/mnt/c/Program Files/dotnet/dotnet.exe build …` - Kill app before build: `/mnt/c/Windows/System32/taskkill.exe /F /IM ytLive.exe` - No Linux ffmpeg / no sudo on this box — probing uses `/mnt/c/Program Files/Krita (x64)/bin/ffmpeg.exe` via WSL interop; frames landed in `/mnt/c/Users/gramp/AppData/Local/Temp/ylf/` - `tools/ticker`: constant ~+982ms offset on the FIRST line is cosmetic (t0 captured a beat late)