Skip to content

HomeKit: require fresh snapshots by default to prevent misleading preview ages - #2171

Closed
dougasimpson wants to merge 1 commit into
koush:mainfrom
dougasimpson:codex/homekit-fresh-snapshots
Closed

dougasimpson wants to merge 1 commit into
koush:mainfrom
dougasimpson:codex/homekit-fresh-snapshots

Conversation

@dougasimpson

Copy link
Copy Markdown

This change adds a global Require Fresh HomeKit Snapshots setting, enabled by default. When enabled, failed snapshot acquisition is reported as a request error, allowing Home to control its preview and age counter in order to present accurate information to the user.

The Snapshot plugin can supply HomeKit with a cached image up to one hour old for an ordinary camera. In testing, when a camera went offline, Home repeatedly displayed that cached image with a counter progressing from “Now” to approximately 11 seconds. Each successful refresh returned the same old image and reset the counter. A camera that had been offline for 45 minutes therefore appeared to have a preview only 0–11 seconds old, rather than showing its actual age.

Caching can also make the displayed age inaccurate while a camera is online: Home receives an older image successfully and treats that response as a new preview. The desired behavior is for Home's preview counter to reflect the age of its last successfully acquired image, without stale cache responses continually resetting it. The observed 11-second refresh cycle is client behavior, not a guaranteed HomeKit interval.

Fresh requests reject acquisition failures instead of returning stale images or generated “Snapshot Failed” JPEGs. Home controls whether it retains the previous preview, clears it, or displays an error.

  • Add RequestPictureOptions.requireFresh and its generated Python type.
  • Share in-progress captures, but do not reuse completed source snapshots or resize results in strict mode.
  • Propagate capture, timeout, crop, resize, and privacy failures instead of stale-image or generated-error-image fallback.
  • Request current video frames for providers advertising cached snapshots; do not return the last image of a sleeping camera. Strict requests may wake sleeping cameras.
  • Preserve legacy behavior when the setting is disabled and for callers that do not request freshness.
  • Document camera/provider freshness limits and Home's control over its UI.

Validation:

  • 15 focused regression tests pass (node --test plugins/snapshot/test/fresh-snapshots.test.cjs). Host and media boundaries are mocked; actual Snapshot and HomeKit snapshot-handler sources are exercised.
  • SDK generation/build and Snapshot/HomeKit type checks pass.
  • Both plugin bundles build using repository-locked SDK/HomeKit dependencies. Snapshot used Rollup's supported --forceExit option to complete after output generation on Node 24.
  • Deployed both test bundles to a local Scrypted installation with rollback copies of the original bundles and settings. HomeKit pairing fingerprints remained unchanged.
  • With the global setting enabled, four online ONVIF cameras returned valid JPEGs; one disconnected camera rejected the snapshot request.
  • A temporary snapshot-only endpoint failure on an online camera rejected in strict mode, returned the exact last-good image for a non-strict caller, and recovered to fresh snapshots after restoring the original settings.
  • User confirmed correct preview and live-view operation in both iOS and macOS Home. The disconnected camera recovered after physical reconnection. After unplugging it again, Home retained the real image received before the outage with a correctly aging counter, following an initial blank preview.

Live-view startup latency was not benchmarked; this change does not modify the live-stream handler.

Both HomeKit and Snapshot must include this change. Other camera providers must honor requireFresh; the setting cannot establish the exposure time of imagery supplied by a camera or an unsupported provider.

@koush koush closed this Oct 9, 2026
@dougasimpson

Copy link
Copy Markdown
Author

Would you prefer this is submitted as a discussion? Submitted here: #2172

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.

2 participants