Webcam resource validation + first-frame proof + CameraConflictProbe: MediaCaptureFrameSource validates post-init (VideoDeviceId match, stream properties, reader StartAsync status), subscribes Failed/CameraStreamStateChanged → SourceFailed; CameraManager.AcquireAsync requires first-frame proof (4s timeout) — silent empty box impossible; MainViewModel surfaces WebcamError chip + MessageBox with suspect-app names; fallback ladder VideoPreview → VideoRecord; 19041 SDK projection gaps documented; AGENTS.md + schema.md + HANDOFF.md memory-map rules added; 81 tests passing, 0 warnings

This commit is contained in:
2026-08-12 07:21:15 -07:00
parent 60259c08c2
commit 3f7f1880c5
11 changed files with 203 additions and 25 deletions
+47
View File
@@ -0,0 +1,47 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ytLive.Helpers;
/// <summary>
/// Best-effort diagnostic: when a camera won't start, lists other running
/// processes known to hold cameras (OBS, Zoom, Teams, NVIDIA Broadcast, etc.).
/// Windows doesn't expose "which process has this device" via any public API,
/// so this is a suspect list, not a verdict — but it's far better than
/// "maybe in use by another app" with no idea which one.
/// </summary>
public static class CameraConflictProbe
{
private static readonly HashSet<string> KnownCameraApps = new()
{
"obs64", "obs32", "zoom", "teams", "ms-teams", "discord",
"nvidia broadcast", "skype", "webex", "slack",
"streamlabs obs", "restream studio", "manycam", "snap camera",
"logitech capture", "logitune", "facerig", "animaze",
"camera", "vmix", "xsplit broadcaster", "xsplit gamecaster",
"droidcam", "ivcam", "epoccam", "camo",
"chrome", "msedge", "firefox", "brave",
};
/// <summary>
/// Returns the friendly names of known camera apps currently running, or an
/// empty list if none are found (or the probe itself fails).
/// </summary>
public static List<string> GetRunningCameraApps()
{
try
{
return Process.GetProcesses()
.Where(p => KnownCameraApps.Contains(p.ProcessName.ToLowerInvariant()))
.Select(p => p.ProcessName)
.Distinct()
.OrderBy(n => n)
.ToList();
}
catch
{
return new List<string>();
}
}
}
+1
View File
@@ -12,6 +12,7 @@ Cross-cutting utilities. See [`schema.md`](../schema.md) for the memory-map conv
| `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 |
| `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 |
Related: [`Themes/Controls.xaml`](../Themes/Controls.xaml) styles the lists this
class backs; [`Models/index.md`](../Models/index.md) and