fix(media): pace clip audio to a deadline too, and prove the keyed layer in the OUTPUT

Two follow-ups from the creator's lip-sync observation.

1. Audio still slept a fixed 50 ms per chunk — the same "sleep on top of the work" fault fixed for
   video an hour ago, left in place. Every chunk's read cost was added, so a clip's audio fell
   progressively behind its picture: small per chunk, unbounded over a long clip. It now uses the
   same deadline pacer, so audio and video advance on the same wall clock.

2. The preview pane is NOT the compositor. "Preview looks great" proves the decode and the preview
   bitmap; the recording and stream are blitted by SceneCompositor. `MediaCompositeOutputTests`
   renders a keyed video layer over a background through the real compositor and asserts the two
   things that matter: keyed (alpha 0) pixels let the background through, and the subject half
   covers it. So "green screen removed" is now proven in the output path, not just the pane.

Also: a round-clipped video layer had no preview trigger (only webcam+Round existed), so it would
render in the output and be invisible in the pane. Same unit-circle path now covers it.

Tests: 16 scoped (pacer, real-clip rate + keying, composite output, decode pacing, alert pacing)
green. FULL SUITE NOT RUN — the machine is in use: two runs under load aborted in the WPF test host
(HWND subclass crash) and one hit the 15-minute cap. Re-run scripts/verify.sh in a quiet window.
This commit is contained in:
2026-11-05 10:40:25 -08:00
parent 5577aaaf91
commit 3a56807ee3
3 changed files with 99 additions and 5 deletions
+9
View File
@@ -208,6 +208,15 @@
<Condition Binding="{Binding ClipShape}" Value="Round"/>
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Visible"/>
<!-- A round-clipped video layer uses the same unit-circle path, or it would render in the
output and be invisible in the preview (2026-11-05). -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsMediaSource}" Value="True"/>
<Condition Binding="{Binding IsRoundShape}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Visible"/>
</MultiDataTrigger>
</MultiDataTrigger>
</Style.Triggers>
</Style>