The creator is DHH and lipreads their own recordings, so a webcam that judders is an accessibility defect, not a polish item. Take ty-20261005-1001-821-0001.mp4 holds 25.6 distinct webcam images/s against the camera's 30fps with 281 gaps of 50-100ms - roughly one hitch in five - in a file that muxes flawlessly. Nothing in the app could see that: rawvideo carries no per-frame timestamps (ffmpeg stamps by ARRIVAL at the declared 60fps), and the stats line divided every average by the number of frames SUBMITTED, which deadline padding always fills to the full target. So the pump reported "300/300 frames, avg render 12.4ms" while producing 60 distinct composites. Helpers/FrameCadence.cs is one pure counter fed from three points: MediaCaptureFrameSource logs the device's own SystemRelativeTime stamps against our arrival times (TryAcquireLatestFrame keeps only the LATEST frame, so falling behind is silent by design), and FramePump logs the distinct webcam Epoch values that reached a composite. Read together they name the culprit - device/USB, our reader, or our compositor - instead of guessing. Render/resolve/wait now divide by the real render count, and "frames per 5s from R renders" is the duplicate-on-lag ratio stated honestly. An out-of-order timestamp counts as a frame but produces no gap and does not become the next interval's reference, so one bad stamp cannot invent a multi-second hitch twice. Also corrects a stale ai.md line (the "webcam renders at ~18fps" figure came from a different session and counted every newly rendered layer) and re-records the background-removal ruling as permanently out. Records the agreed-but-unbuilt Units 1-2, the no-fallback-camera ruling, and the SetFormatAsync dead end found by probing the 19041 projection. Suite 402/402, 0 warnings. The one red, LayerReorderPersistenceTests' RealMouseDrag, fails identically on a stashed clean tree - it needs an interactive desktop session this shell lacks.
2.1 KiB
2.1 KiB
Helpers — index
Cross-cutting utilities. See schema.md for the memory-map conventions.
| File | Purpose |
|---|---|
ViewModelBase.cs |
INotifyPropertyChanged + SetProperty<T>() — base for all ViewModels |
RelayCommand.cs |
ICommand implementation for all button actions |
AppLog.cs |
File logger to %APPDATA%\ytLlive\startup.log; startup checkpoints + unhandled-exception capture (the crash this map is named for) |
FocusPreservingListBox.cs |
ListBox subclass that keeps selection/focus coherent when the selected item is deleted; IsSelectable predicate skips hidden scenes; drag-reorder guard |
OAuthCredentials.cs |
Baked-in Google OAuth client ID/secret (desktop app; loopback callback) |
TokenStore.cs |
DPAPI-protected OAuth session persistence (%APPDATA%\ytLlive\ytLlive.auth, CurrentUser scope); Save/Load/Clear — sign-in survives restarts |
ImageCache.cs |
Image byte caching (assets live in the DB) |
InverseBoolToVisibilityConverter.cs / NotNullToVisibilityConverter.cs |
XAML value converters for visibility bindings |
AllTrueToVisibilityConverter.cs |
Multi-value AND-gate → Visible; gates the layer-row capture menu items on row-IsBackground + staged-scene-is-Live (TASK 25) |
CameraConflictProbe.cs |
Best-effort diagnostic: when a camera won't start, enumerates running processes known to hold cameras (OBS, Zoom, Teams, NVIDIA Broadcast, browsers, etc.) — Windows doesn't expose "which process has this device" via any public API, so this is a suspect list, not a verdict |
FrameCadence.cs |
Pure arrival-cadence counter (FrameCadence + FrameCadenceSummary.Describe): frames, gaps, hitches, longest/avg gap for a window of a timestamped stream. Fed by MediaCaptureFrameSource (camera stamps vs our arrivals) and FramePump (distinct webcam Epochs that reached the output) — UNIT 0, see ai.md "Frame cadence" |
Related: Themes/Controls.xaml styles the lists this
class backs; Models/index.md and
ViewModels/index.md for the objects it works on.