@mega-yfue/eufy-sdk / SharedLiveSourceOptions
Interface: SharedLiveSourceOptions
Properties
batteryBudgetMs?
batteryBudgetMs?: number;Battery/solar continuous-stream budget before the budget notice fires (default 45000ms).
budgetGraceMs?
budgetGraceMs?: number;Grace after the budget notice to call extend() before the source auto-stops (default 10000ms).
label?
label?: string;Prefix label for log lines (e.g. the parentSn:channel key), for multi-source disambiguation.
lingerMs?
lingerMs?: number;No-consumer grace before teardown (default 8000ms; 0 schedules teardown next tick). Distinct from the stream's keepalive.
logger?
logger?: Logger;Diagnostics sink. Omit for silence.
makeStream
makeStream: (ctx) => LiveStreamHandle;Factory that builds a fresh, un-started LiveStreamHandle. Called on every (re)warm so a reconnect rebuilds the stream rather than reusing a dead one. SharedLiveSource calls .start() itself.
ctx.reassertWanted answers whether this pull still has anyone attached. A stream that re-asserts a channel to hold it open should consult it, so a pull nothing is watching stops competing for a session that serves one camera at a time.
Parameters
ctx
reassertWanted
() => boolean
Returns
maxQueue?
maxQueue?: number;Per-consumer bounded queue depth; overflow → drop-to-keyframe (default 900 ≈ 30s @ 30fps).
onActive?
onActive?: () => void;Called when the FIRST consumer attaches (0→1). The router uses this to register the source as a "user" of the station's P2P session (so an active stream cancels the session's idle-detach). Paired with onIdle. Optional — omit if the caller doesn't manage session lifecycle.
Returns
void
onIdle?
onIdle?: () => void;Called when the LAST consumer detaches (1→0) — the router releases its session user. See onActive.
Returns
void
onSessionUnreachable?
onSessionUnreachable?: () => boolean;This session is not serving the warm-up: a media start was abandoned unacknowledged, or forced starts went unanswered by any media, before anything was delivered. The owner answers whether it is replacing the session, and calls SharedLiveSource.rewarm once it has the replacement.
Asked at most once per warm-up: further evidence is the same session saying the same thing.
Returns
boolean
onStartFailed?
onStartFailed?: () => void;Called when a stream is torn down having never delivered a keyframe, AFTER consumers have been told.
A source can only rebuild its stream; it holds a factory, not the session that stream rides on. When the session — or the per-device state carried on it — is what has stopped serving this device, every rebuild starts another stream over the same session and dies the same way, so the owner of the session has to hear about it to do anything else.
The condition is deliberately "no keyframe ever arrived", not "the warm-up deadline fired". A start can fail without that deadline being reached — an upstream error or stop can arrive first, the battery budget can stop the pull, and a caller that gives up before the deadline cancels it on the way out (clearWarmWatch) — and all of those are the same dead start. Enumerating the ways instead of naming the condition is how the case that actually happens gets left out.
Not called by SharedLiveSource.dispose: the owner asked for that one, and it is the very thing an owner does in response to this callback.
Returns
void
onStopped?
onStopped?: () => void;The pull has ended and will not resume: the linger elapsed, the battery budget ran out, or the source was torn down. A later attach builds a fresh stream rather than reviving this one.
Distinct from onIdle by what is still running. onIdle fires at the last detach, while the linger is still holding the pull open so a quick re-attach costs nothing; between the two the pull is alive. This fires when it is not.
Returns
void
powered?
powered?: "wired" | "battery";Power source, a runtime device fact ("battery" incl. solar, or "wired") — NOT a device family trait; the model derives it from the resolved capability set and passes it through. "wired" (default) streams unbounded; "battery" bounds a continuous stream to batteryBudgetMs.
preBufferSeconds?
preBufferSeconds?: number;Rolling prebuffer window in seconds, 0 = off (default 0).
warmRetryMs?
warmRetryMs?: number;Warm-up start retry interval (default 2000ms). After warming, if no keyframe has arrived, the source re-issues the start (LiveStreamHandle.nudge) every interval — self-healing a start that raced the level-2 key negotiation, independent of any caller keepalive.
warmTimeoutMs?
warmTimeoutMs?: number;Warm-up deadline (default 20000ms). If no keyframe arrives within it, the source emits error to consumers ("failed to start") and tears down, so live() never hangs silently on a dead start.