Files
LlamaCasty/HANDOFF.md
T
gramps 0f4a035376 fix(preview): draw video layers, unlink Play from Loop, geometry last
Three reports from the creator, plus two bugs the real clip exposed.

1. A video layer was INVISIBLE in the preview. The pane's per-layer Image is Collapsed by
   default and switched on by a whitelist of DataTriggers; MediaSource matched none, so the clip
   decoded into a bitmap that nothing displayed. Same defect the alert box hit on 2026-09-26 and
   the scoreboard after it — now recorded at the top of docs/ai/ui-surface.md with a test that
   asserts the bound Image is Visible (`MediaPreviewDisplayTests`).

2. Play is no longer tied to Loop: the button is always enabled (creator ruling — Loop must not
   toggle Play). Loop still restarts a finished clip, which is the behaviour that was broken.

3. Geometry is now the LAST section of the properties list for every draggable element, with
   opacity at the top; the web source's duplicate geometry block is gone (it now uses the shared
   one, which had been sitting above the media panel).

4. The physical mouse-drag test is deleted. It injected real cursor movement, hijacked whatever
   machine ran it, and failed whenever the desktop was busy. The arithmetic it covered now lives
   in `Helpers/DragReorderMath.cs` — pure, and covered by `DragReorderMathTests` (threshold,
   up/down moves, no-op and out-of-range). The two persistence tests were already synthetic.

5. Real-clip check (creator's `test_greenscreen_moving_subject.mp4`, 1920×1080): the detector
   REJECTED it — a fully saturated green sits at value 1.0 and the detector's 0.98 brightness
   ceiling threw it away. White highlights are excluded by the saturation floor, which is the
   property that actually separates them, so the ceiling is gone. With it fixed, the clip is
   detected as green (high confidence), and keyed through our own pipe 97.8% of pixels go
   transparent. Measured: keying with the canonical #00B140 keys 0.0% of this clip — which is why
   the key colour comes from the measured screen.

Tests: 567 passed, 0 failed, clean build 0 warnings. The gate's scope check flags
`Assets/Videos/test_greenscreen_moving_subject.mp4` — the creator's working copy, deliberately not
committed; the fixture lives under ytLive.Tests/Fixtures.
2026-11-05 09:38:18 -08:00

2.7 KiB
Raw Blame History

HANDOFF — 2026-11-05 (TASK 64 — green/blue screen for clips)

State

  • main. TASK 21 complete (video file layer + its soundtrack). TASK 64 shipped through slice E: a clip with a green or blue backdrop is offered a key on add ("Looks like a green screen — Remove it"), accepting it keys the background inside the decode pipe (bundled ffmpeg colorkey/despill), with Amount/Softness/Fringe in the panel and the settings persisted. Sessions are keyed by path + look, so identical looks share one decoder.
  • Detection stays silent on lawns/pitches (confidence = coverage × hue tightness) and ignores letterbox bars. It never acts on its own.
  • Slice F shipped too: App Settings → Video clips → "Auto Green/Blue Screen" (off by default, high confidence only, and the panel states when a key was automatic) and alert clips key through the same settings block (one alert box per layout).
  • Tests: ChromaKeyDetectorTests + ChromaKeyApplyTests (pipe asks ffmpeg to key; offer → accept → keyed session feeds the resolver; survives save; auto-apply; alert clip keyed). App build 0 warnings.
  • TASK 49 retired (creator ruling): YouTube owns chat moderation — blocked words and hold-for-review run before the API. What we owed it was not a wordlist but not painting what YouTube removed: the chat parser now skips tombstone (a deleted message's text is never sent) and hasDisplayContent:false. Same commit fixed a live bug: Super Chat read displayString instead of amountDisplayString, so every amount fell back to a recomposed string.

Next action

  • TASK 64 is complete. Next queued: TASK 49 (chat profanity filter). Day 3's TASK 32/33 resilience slices remain outstanding — 32·4 (fragmented MP4) is the smallest.
  • Do not push absent a checkpoint request.

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, the scoreboard, and the video layer 2026-11-05). Add the trigger with the layer type; pin it with a test that asserts the bound Image is Visible (MediaPreviewDisplayTests).
  • The old physical mouse-drag test is deleted; the drag arithmetic it covered is now pure and tested in DragReorderMathTests. Nothing in the suite drives the real cursor any more.
  • 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, and release through ReleaseMediaIfUnused.
  • Bundled FFmpeg stays outside the single-file exe (ExcludeFromSingleFile="true").