Skip to content

fix: reopen capture cards that come up dark, and keep a week of logs - #311

Open
BernardJen wants to merge 1 commit into
mainfrom
fix/capture-card-health
Open

BernardJen wants to merge 1 commit into
mainfrom
fix/capture-card-health

Conversation

@BernardJen

@BernardJen BernardJen commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The wall (Windows 11, two PCIe Elgato 4K60 Pro MK.2 cards) sometimes boots with a card showing black while a live source is plugged in. Restarting the app fixes it: today it was started at 12:12:27 and restarted by hand at 12:22:35.

Nothing in the app noticed:

  • the stream opened fine, and the wall has no no-signal references (removed on purpose), so the split-flap never shows
  • nothing was logged anywhere persistent, so afterwards there was no record of what happened
  • the Elgato driver exposes no signal-lock state (registry and services checked), so the picture is the only evidence

Changes

Capture-card health (stream-health.js, sampled from renderer.js every 2s)

Status Evidence Reopen schedule
open-failed / ended / no-frames / stalled getUserMedia, track state, frame counter 2s, 5s, 15s, 30s, then 60s
dark 32x18 luma thumbnail is one flat colour for 6s 5s ... then every 10 min
  • It counts frames and never measures motion. A held slide still arrives at 60fps, so it stays ok (feat: detect a frozen feed (no motion), not just a known no-signal image #159). A feed only counts as stalled if frames were flowing first, so a static virtual camera isn't reopened in a loop.
  • A reopen releases every side on the device before opening it again. Chromium shares one capture session per device, and the wall shows the same card on both panels.
  • If no capture devices were found at startup, enumeration is retried. A devicechange event retries a faulted side straight away.
  • __health() in DevTools prints the current state.

Persistent log (src/main/file-log.js): writes <userData>/logs/input-viewer-YYYY-MM-DD.log and keeps 7 days. Limits are a 20 MB/day cap and 600 lines/min. It records main and renderer console output, renderer, GPU and utility process crashes, and the OS uptime at launch.

The startup script (Mosaic, then Warp, then the cards, then Input Viewer) lives in LAB271/labs-videowall-config, not in this repo.

Testing

  • npm run lint is clean.
  • npm test: 844 passed, 26 of them new (stream-health, file-log).
  • I ran the built app with --mock=2, driving it over the DevTools protocol:
    • a stopped track: ended, reopened, back to ok in about 1.8s
    • a flat black stream: dark, reopened
    • the log file was written and the frame counter read 15fps (the mock's rate)

Not verified

  • What a stuck card actually shows (black, or Elgato's no-signal graphic). The dark trigger assumes a flat picture. The new log will say after the first bad boot.

Deploying

The changes reach the wall through a release.

🤖 Generated with Claude Code

The wall sometimes boots with an Elgato 4K60 Pro MK.2 showing black while
a live source is plugged in, until someone restarts the app. The stream had
opened fine and the wall has no no-signal references, so nothing noticed.

- stream-health.js: per-side status from a frame counter, track state and
  a 32x18 luma thumbnail (open-failed / no-frames / stalled / ended / dark),
  with backoff for reopens. Counts frames rather than measuring motion, so a
  held slide is healthy (#159).
- renderer: samples every 2s, reopens a card by releasing every side on it
  first (Chromium shares one capture session per device), retries device
  enumeration when none were found, and logs status changes plus a
  10-minute baseline.
- main: daily log file in <userData>/logs, 7 days kept, 20 MB/day cap,
  rate-limited; captures renderer console and process crashes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@BernardJen
BernardJen force-pushed the fix/capture-card-health branch from ae79806 to f9c1c92 Compare September 23, 2026 20:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant