@camstack/types 1.2.42 → 1.2.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon.js +8 -2
- package/dist/addon.mjs +8 -2
- package/dist/cap-call-context.d.ts +26 -0
- package/dist/capabilities/index.d.ts +8 -5
- package/dist/capabilities/osd-manager.cap.d.ts +900 -0
- package/dist/capabilities/pipeline-analytics.cap.d.ts +171 -4
- package/dist/capabilities/pipeline-orchestrator.cap.d.ts +36 -0
- package/dist/capabilities/privacy-mask.cap.d.ts +69 -9
- package/dist/capabilities/recording.cap.d.ts +27 -0
- package/dist/capabilities/schemas/streaming-shared.d.ts +2 -0
- package/dist/capabilities/server-management.cap.d.ts +3 -3
- package/dist/capabilities/snapshot.cap.d.ts +1 -1
- package/dist/capabilities/stream-broker.cap.d.ts +36 -0
- package/dist/capabilities/stream-params.cap.d.ts +8 -4
- package/dist/device/device-profile.d.ts +12 -4
- package/dist/device/system-mirror.d.ts +11 -0
- package/dist/ffmpeg/encode-defaults.d.ts +18 -0
- package/dist/ffmpeg/fmp4-box-splitter.d.ts +113 -0
- package/dist/ffmpeg/fmp4-fragment-child.d.ts +85 -0
- package/dist/ffmpeg/fmp4-fragment-plane.d.ts +142 -0
- package/dist/ffmpeg/invocation.d.ts +102 -2
- package/dist/ffmpeg/sharing-key.d.ts +54 -2
- package/dist/fmp4-box-splitter-B53u9-Nu.mjs +615 -0
- package/dist/fmp4-box-splitter-BkWH7O3L.js +686 -0
- package/dist/generated/addon-api.d.ts +117 -0
- package/dist/generated/cap-input-defaults.d.ts +1 -1
- package/dist/generated/capability-router-map.d.ts +5 -2
- package/dist/generated/device-proxy.d.ts +4 -2
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/system-proxy.d.ts +2 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1264 -394
- package/dist/index.mjs +1217 -385
- package/dist/interfaces/camera-switches.d.ts +211 -5
- package/dist/interfaces/inference-engine.d.ts +24 -3
- package/dist/interfaces/stream-broker.d.ts +18 -0
- package/dist/node.d.ts +4 -0
- package/dist/node.js +509 -3
- package/dist/node.mjs +507 -3
- package/dist/notification/schedule.d.ts +20 -0
- package/dist/pipeline/native-lease.d.ts +150 -0
- package/dist/{sleep-BmNKsY7v.mjs → sleep-cC4Fuup8.mjs} +59 -3
- package/dist/{sleep-Cvi1JxZp.js → sleep-eiC10_cX.js} +64 -2
- package/dist/types/pipeline-step.d.ts +1 -1
- package/dist/utils/addon-id.d.ts +30 -0
- package/package.json +1 -1
- package/dist/canonical-hash-7nfBbEqR.mjs +0 -35
- package/dist/canonical-hash-BcZHRHIx.js +0 -40
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as EventCategory } from "./event-category-41fKf-q9.mjs";
|
|
2
|
-
import { $ as
|
|
3
|
-
import {
|
|
2
|
+
import { $ as FrameHandleSchema, A as method, B as readinessKey, C as DeviceType, Ct as collectHydratedFieldEntries, D as event, E as DEVICE_STATUS_METHOD, Et as resolveHydratedFieldValue, F as readNodePin, G as CamProfileSchema, H as BrokerStatsSchema, I as toNodeId, J as CameraStreamSchema, K as CamStreamKindSchema, L as ReadinessRegistry, M as systemMethod, N as CAP_NODE_PIN_CONTEXT_KEY, O as expandCapMethods, P as nodePin, Q as FrameHandleFormatSchema, R as ReadinessTimeoutError, S as DeviceRole, St as WELL_KNOWN_TAB_MAP, T as DEVICE_SETTINGS_CONTRIBUTION_METHODS, Tt as hydrateSchema, U as BrokerStatusSchema, V as scopeKey, W as CAM_PROFILE_ORDER, X as DecodedFrameSchema, Y as DecodedAudioChunkSchema, Z as EncodedPacketSchema, _ as RawStateResultSchema, _t as createDurableState, a as asJsonObject, at as SubscribeAudioChunksInputSchema, b as ChargingStatus, bt as isEvent, c as parseJsonArray, ct as SubscribeFramesResultSchema, d as DEVICE_SCOPED_CAPS, dt as parseProfileBrokerId, et as ProfileRtspEntrySchema, f as isDeviceScopedCap, ft as selectAssignedProfileSlots, g as createSliceHandle, gt as normalizeAddonInitResult, h as createMirrorSource, ht as BaseAddon, i as asJsonArray, it as StreamSourceSchema, j as resolveCapMount, k as isDeviceConfigCap, l as parseJsonObject, lt as makeProfileBrokerId, m as createLazyTrpcSource, mt as DisposerChain, n as sleepCancellable, nt as ProfileSlotStatusSchema, o as asNumber, ot as SubscribeAudioChunksResultSchema, p as createDeviceProxy, pt as DATAPLANE_SECRET_HEADER, q as CamStreamResolutionSchema, r as asBoolean, rt as StreamSourceEntrySchema, s as asString, st as SubscribeFramesInputSchema, t as sleep, tt as ProfileSlotSchema, u as parseJsonUnknown, ut as makeSourceBrokerId, v as deviceOpsCapability, vt as createEvent, w as adminUiCapability, wt as collectHydratedFieldValues, x as DeviceFeature, xt as WELL_KNOWN_TABS, y as viewerUiCapability, yt as emitReadiness, z as emitDownForOwnedCaps } from "./sleep-cC4Fuup8.mjs";
|
|
3
|
+
import { a as buildAudioArgs, c as buildVideoArgs, d as logBannerArgs, f as pickVideoEncoder, i as audioPlanFromEncodeProfile, l as invocationFromEncodeProfile, n as canonicalHash, o as buildFfmpegArgs, r as AUDIO_PRESETS, s as buildInputArgs, t as Fmp4BoxSplitter, u as isSoftwareDecode } from "./fmp4-box-splitter-B53u9-Nu.mjs";
|
|
4
4
|
import { EventSourceType } from "./enums.mjs";
|
|
5
5
|
import { t as errMsg } from "./err-msg-IQTHeDzc.mjs";
|
|
6
6
|
import { z } from "zod";
|
|
@@ -230,335 +230,6 @@ function encodeProfileFromStreamShape(stream) {
|
|
|
230
230
|
};
|
|
231
231
|
}
|
|
232
232
|
//#endregion
|
|
233
|
-
//#region src/ffmpeg/invocation.ts
|
|
234
|
-
var AUDIO_ENCODER_BY_CODEC = {
|
|
235
|
-
opus: "libopus",
|
|
236
|
-
aac: "aac",
|
|
237
|
-
pcmu: "pcm_mulaw",
|
|
238
|
-
pcma: "pcm_alaw"
|
|
239
|
-
};
|
|
240
|
-
/**
|
|
241
|
-
* Camera-microphone audio, per codec. Lives HERE rather than in
|
|
242
|
-
* `encode-defaults.ts` only to avoid an import cycle (`encode-defaults` depends
|
|
243
|
-
* on these types); it is re-exported from there, which is where to read it.
|
|
244
|
-
*
|
|
245
|
-
* Every source in this repo is a mono camera mic. The former broker preset
|
|
246
|
-
* encoded Opus at `channels: 2`, spending bitrate duplicating one channel —
|
|
247
|
-
* that is the value this consolidation changed.
|
|
248
|
-
*/
|
|
249
|
-
var AUDIO_PRESETS = {
|
|
250
|
-
aac: {
|
|
251
|
-
kind: "encode",
|
|
252
|
-
codec: "aac",
|
|
253
|
-
bitrateKbps: 128,
|
|
254
|
-
sampleRateHz: 48e3,
|
|
255
|
-
channels: 1
|
|
256
|
-
},
|
|
257
|
-
opus: {
|
|
258
|
-
kind: "encode",
|
|
259
|
-
codec: "opus",
|
|
260
|
-
bitrateKbps: 64,
|
|
261
|
-
sampleRateHz: 48e3,
|
|
262
|
-
channels: 1
|
|
263
|
-
},
|
|
264
|
-
pcmu: {
|
|
265
|
-
kind: "encode",
|
|
266
|
-
codec: "pcmu",
|
|
267
|
-
sampleRateHz: 8e3,
|
|
268
|
-
channels: 1
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
/** `-hide_banner -loglevel <level>` — every ffmpeg site opens with this. */
|
|
272
|
-
function logBannerArgs(level) {
|
|
273
|
-
return [
|
|
274
|
-
"-hide_banner",
|
|
275
|
-
"-loglevel",
|
|
276
|
-
level
|
|
277
|
-
];
|
|
278
|
-
}
|
|
279
|
-
/** `true` when the resolved value means "decode in software" (⇒ no `-hwaccel`). */
|
|
280
|
-
function isSoftwareDecode(decodeHwAccel) {
|
|
281
|
-
return !decodeHwAccel || decodeHwAccel === "none" || decodeHwAccel === "copy";
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Every INPUT option, in order, terminated by `-i <url>`. Nothing may be
|
|
285
|
-
* appended to this list by a caller — that is the whole point of the function.
|
|
286
|
-
*/
|
|
287
|
-
function buildInputArgs(input, decodeHwAccel) {
|
|
288
|
-
const args = [];
|
|
289
|
-
if (!isSoftwareDecode(decodeHwAccel)) args.push("-hwaccel", String(decodeHwAccel));
|
|
290
|
-
if (input.extraArgs?.length) args.push(...input.extraArgs);
|
|
291
|
-
if (input.fflags?.length) for (const flag of input.fflags) args.push("-fflags", flag);
|
|
292
|
-
if (input.rtspTransport) args.push("-rtsp_transport", input.rtspTransport);
|
|
293
|
-
args.push("-i", input.url);
|
|
294
|
-
return args;
|
|
295
|
-
}
|
|
296
|
-
/** The `-vf` filter args, or `[]` when a consumer `-vf` already claims the slot. */
|
|
297
|
-
function buildVideoFilterArgs(scale, outputArgs) {
|
|
298
|
-
if (!scale) return [];
|
|
299
|
-
if (outputArgs.some((a) => a === "-vf")) return [];
|
|
300
|
-
if (scale.mode === "exact") return ["-vf", `scale=${scale.width}:${scale.height}`];
|
|
301
|
-
return ["-vf", `scale='min(${scale.width},iw)':'min(${scale.height},ih)':force_original_aspect_ratio=decrease:force_divisible_by=2`];
|
|
302
|
-
}
|
|
303
|
-
/** Rate-control args for an encode plan. */
|
|
304
|
-
function buildRateControlArgs(video) {
|
|
305
|
-
const kbps = video.bitrateKbps;
|
|
306
|
-
if (kbps === void 0) return [];
|
|
307
|
-
const rc = video.rateControl ?? {
|
|
308
|
-
kind: "cap",
|
|
309
|
-
vbvSeconds: 2
|
|
310
|
-
};
|
|
311
|
-
const bufsize = Math.max(1, Math.round(kbps * rc.vbvSeconds));
|
|
312
|
-
return [
|
|
313
|
-
...rc.kind === "cbr" ? ["-b:v", `${kbps}k`] : [],
|
|
314
|
-
"-maxrate",
|
|
315
|
-
`${kbps}k`,
|
|
316
|
-
"-bufsize",
|
|
317
|
-
`${bufsize}k`
|
|
318
|
-
];
|
|
319
|
-
}
|
|
320
|
-
/** The whole video block (`-vf` … `-c:v` … knobs), after `-i`. */
|
|
321
|
-
function buildVideoArgs(video, outputArgs) {
|
|
322
|
-
if (video.kind === "copy") return [
|
|
323
|
-
"-c:v",
|
|
324
|
-
"copy",
|
|
325
|
-
...video.bitstreamFilter ? ["-bsf:v", video.bitstreamFilter] : []
|
|
326
|
-
];
|
|
327
|
-
const args = [
|
|
328
|
-
...buildVideoFilterArgs(video.scale, outputArgs),
|
|
329
|
-
"-c:v",
|
|
330
|
-
video.encoder
|
|
331
|
-
];
|
|
332
|
-
if (video.preset !== void 0) args.push("-preset", video.preset);
|
|
333
|
-
if (video.tune !== void 0) args.push("-tune", video.tune);
|
|
334
|
-
if (video.profile !== void 0) args.push("-profile:v", video.profile);
|
|
335
|
-
if (video.level !== void 0) args.push("-level", video.level);
|
|
336
|
-
if (video.pixelFormat !== void 0) args.push("-pix_fmt", video.pixelFormat);
|
|
337
|
-
if (video.fps !== void 0) args.push("-r", String(video.fps));
|
|
338
|
-
if (video.gopFrames !== void 0) args.push("-g", String(video.gopFrames));
|
|
339
|
-
if (video.bf !== void 0) args.push("-bf", String(video.bf));
|
|
340
|
-
args.push(...buildRateControlArgs(video));
|
|
341
|
-
if (video.bitstreamFilter !== void 0) args.push("-bsf:v", video.bitstreamFilter);
|
|
342
|
-
return args;
|
|
343
|
-
}
|
|
344
|
-
/** The whole audio block, after `-i`. */
|
|
345
|
-
function buildAudioArgs(audio) {
|
|
346
|
-
if (audio.kind === "none") return ["-an"];
|
|
347
|
-
if (audio.kind === "copy") return ["-c:a", "copy"];
|
|
348
|
-
const args = [];
|
|
349
|
-
if (audio.filter !== void 0) args.push("-af", audio.filter);
|
|
350
|
-
args.push("-c:a", AUDIO_ENCODER_BY_CODEC[audio.codec]);
|
|
351
|
-
if (audio.application !== void 0) args.push("-application", audio.application);
|
|
352
|
-
if (audio.frameDurationMs !== void 0) args.push("-frame_duration", String(audio.frameDurationMs));
|
|
353
|
-
if (audio.globalHeader === true) args.push("-flags", "+global_header");
|
|
354
|
-
if (audio.sampleRateHz !== void 0) args.push("-ar", String(audio.sampleRateHz));
|
|
355
|
-
if (audio.bitrateKbps !== void 0) args.push("-b:a", `${audio.bitrateKbps}k`);
|
|
356
|
-
if (audio.vbvBufferKbits !== void 0) args.push("-bufsize", `${audio.vbvBufferKbits}k`);
|
|
357
|
-
if (audio.channels !== void 0) args.push("-ac", String(audio.channels));
|
|
358
|
-
return args;
|
|
359
|
-
}
|
|
360
|
-
/** RTP output-leg args (`-payload_type`, `-ssrc`, `-sdp_file`, `-f rtp <url>`). */
|
|
361
|
-
function buildRtpOutputArgs(out) {
|
|
362
|
-
const args = [];
|
|
363
|
-
if (out.payloadType !== void 0) args.push("-payload_type", String(out.payloadType));
|
|
364
|
-
if (out.ssrc !== void 0) args.push("-ssrc", String(out.ssrc));
|
|
365
|
-
if (out.sdpFile !== void 0) args.push("-sdp_file", out.sdpFile);
|
|
366
|
-
args.push("-f", "rtp", out.url);
|
|
367
|
-
return args;
|
|
368
|
-
}
|
|
369
|
-
/** `true` when the sink is a raw elementary bytestream that cannot mux audio. */
|
|
370
|
-
function isElementaryVideoSink(sink) {
|
|
371
|
-
return sink.kind === "stdout" && (sink.container === "h264" || sink.container === "hevc");
|
|
372
|
-
}
|
|
373
|
-
/**
|
|
374
|
-
* A second output mapping source audio to RTP-over-UDP. `0:a:0?` makes the
|
|
375
|
-
* audio optional so a source with no audio skips it instead of failing the
|
|
376
|
-
* whole invocation.
|
|
377
|
-
*/
|
|
378
|
-
function buildAudioSidecarArgs(sidecar) {
|
|
379
|
-
return [
|
|
380
|
-
"-map",
|
|
381
|
-
"0:a:0?",
|
|
382
|
-
...buildAudioArgs(sidecar.codec === "pcma" ? {
|
|
383
|
-
kind: "encode",
|
|
384
|
-
codec: "pcma",
|
|
385
|
-
sampleRateHz: 8e3,
|
|
386
|
-
channels: 1
|
|
387
|
-
} : AUDIO_PRESETS[sidecar.codec]),
|
|
388
|
-
...buildRtpOutputArgs({
|
|
389
|
-
url: sidecar.rtpUrl,
|
|
390
|
-
sdpFile: sidecar.sdpFile
|
|
391
|
-
})
|
|
392
|
-
];
|
|
393
|
-
}
|
|
394
|
-
/**
|
|
395
|
-
* Assemble the full ffmpeg argument list. Layout:
|
|
396
|
-
*
|
|
397
|
-
* -hide_banner -loglevel <level>
|
|
398
|
-
* [-hwaccel <backend|auto>] ─┐ INPUT options — strictly before -i.
|
|
399
|
-
* [<input.extraArgs>] │
|
|
400
|
-
* [-fflags <flag>…] │
|
|
401
|
-
* [-rtsp_transport tcp] │
|
|
402
|
-
* -i <url> ─┘
|
|
403
|
-
* <video block> <threads> <audio block> ─┐ OUTPUT options.
|
|
404
|
-
* <consumer outputArgs verbatim> │
|
|
405
|
-
* <sink> ─┘ terminal
|
|
406
|
-
*/
|
|
407
|
-
function buildFfmpegArgs(inv) {
|
|
408
|
-
const head = [...logBannerArgs(inv.logLevel), ...buildInputArgs(inv.input, inv.decodeHwAccel)];
|
|
409
|
-
const threadArgs = inv.threadCount > 0 ? ["-threads", String(inv.threadCount)] : [];
|
|
410
|
-
if (inv.sink.kind === "rtp-outputs") {
|
|
411
|
-
const videoLeg = inv.sink.video ? [
|
|
412
|
-
"-an",
|
|
413
|
-
"-map",
|
|
414
|
-
"0:v:0",
|
|
415
|
-
...buildVideoArgs(inv.video, inv.outputArgs),
|
|
416
|
-
...threadArgs,
|
|
417
|
-
...inv.outputArgs,
|
|
418
|
-
...buildRtpOutputArgs(inv.sink.video)
|
|
419
|
-
] : [];
|
|
420
|
-
const audioLeg = inv.sink.audio ? [
|
|
421
|
-
"-vn",
|
|
422
|
-
"-map",
|
|
423
|
-
"0:a:0?",
|
|
424
|
-
...buildAudioArgs(inv.audio),
|
|
425
|
-
...buildRtpOutputArgs(inv.sink.audio)
|
|
426
|
-
] : [];
|
|
427
|
-
return [
|
|
428
|
-
...head,
|
|
429
|
-
...videoLeg,
|
|
430
|
-
...audioLeg
|
|
431
|
-
];
|
|
432
|
-
}
|
|
433
|
-
const audioArgs = isElementaryVideoSink(inv.sink) ? ["-an"] : buildAudioArgs(inv.audio);
|
|
434
|
-
const sinkArgs = inv.sink.kind === "stdout" ? [
|
|
435
|
-
"-f",
|
|
436
|
-
inv.sink.container,
|
|
437
|
-
"pipe:1"
|
|
438
|
-
] : [
|
|
439
|
-
"-f",
|
|
440
|
-
"rtsp",
|
|
441
|
-
"-rtsp_transport",
|
|
442
|
-
"tcp",
|
|
443
|
-
"-rtsp_flags",
|
|
444
|
-
"listen",
|
|
445
|
-
inv.sink.url
|
|
446
|
-
];
|
|
447
|
-
return [
|
|
448
|
-
...head,
|
|
449
|
-
...buildVideoArgs(inv.video, inv.outputArgs),
|
|
450
|
-
...threadArgs,
|
|
451
|
-
...audioArgs,
|
|
452
|
-
...inv.outputArgs,
|
|
453
|
-
...sinkArgs,
|
|
454
|
-
...inv.audioSidecar ? buildAudioSidecarArgs(inv.audioSidecar) : []
|
|
455
|
-
];
|
|
456
|
-
}
|
|
457
|
-
/**
|
|
458
|
-
* Hardware ENCODER ids per decode-hwaccel backend — a static, deterministic
|
|
459
|
-
* map (the same shape the reference NVR uses: platform → encoder, no probe).
|
|
460
|
-
*/
|
|
461
|
-
var ENCODER_IDS_BY_BACKEND = {
|
|
462
|
-
videotoolbox: {
|
|
463
|
-
h264: "h264_videotoolbox",
|
|
464
|
-
h265: "hevc_videotoolbox"
|
|
465
|
-
},
|
|
466
|
-
vaapi: {
|
|
467
|
-
h264: "h264_vaapi",
|
|
468
|
-
h265: "hevc_vaapi"
|
|
469
|
-
},
|
|
470
|
-
qsv: {
|
|
471
|
-
h264: "h264_qsv",
|
|
472
|
-
h265: "hevc_qsv"
|
|
473
|
-
},
|
|
474
|
-
cuda: {
|
|
475
|
-
h264: "h264_nvenc",
|
|
476
|
-
h265: "hevc_nvenc"
|
|
477
|
-
},
|
|
478
|
-
nvdec: {
|
|
479
|
-
h264: "h264_nvenc",
|
|
480
|
-
h265: "hevc_nvenc"
|
|
481
|
-
},
|
|
482
|
-
amf: {
|
|
483
|
-
h264: "h264_amf",
|
|
484
|
-
h265: "hevc_amf"
|
|
485
|
-
}
|
|
486
|
-
};
|
|
487
|
-
/**
|
|
488
|
-
* The hardware encoder for a target codec on `backend`, or the software one.
|
|
489
|
-
* `'auto'` is NOT a backend identity (it is an instruction to ffmpeg), so it
|
|
490
|
-
* maps to software encoding.
|
|
491
|
-
*/
|
|
492
|
-
function pickVideoEncoder(target, backend, useHardware) {
|
|
493
|
-
const software = target === "h264" ? "libx264" : "libx265";
|
|
494
|
-
if (!useHardware || backend === null || isSoftwareDecode(backend) || backend === "auto") return software;
|
|
495
|
-
const ids = ENCODER_IDS_BY_BACKEND[backend.toLowerCase()];
|
|
496
|
-
if (!ids) return software;
|
|
497
|
-
return target === "h264" ? ids.h264 : ids.h265;
|
|
498
|
-
}
|
|
499
|
-
/** Map an `EncodeProfile.audio` to an audio plan. */
|
|
500
|
-
function audioPlanFromEncodeProfile(audio) {
|
|
501
|
-
if (audio === "passthrough") return { kind: "none" };
|
|
502
|
-
if (audio.codec === "copy") return { kind: "copy" };
|
|
503
|
-
return {
|
|
504
|
-
kind: "encode",
|
|
505
|
-
codec: audio.codec,
|
|
506
|
-
...audio.bitrateKbps !== void 0 ? { bitrateKbps: audio.bitrateKbps } : {},
|
|
507
|
-
...audio.sampleRateHz !== void 0 ? { sampleRateHz: audio.sampleRateHz } : {},
|
|
508
|
-
...audio.channels !== void 0 ? { channels: audio.channels } : {}
|
|
509
|
-
};
|
|
510
|
-
}
|
|
511
|
-
/**
|
|
512
|
-
* Adapt an `EncodeProfile` (the operator/consumer-facing shape) into an
|
|
513
|
-
* {@link FfmpegInvocation}. This is the ONLY bridge between the two models —
|
|
514
|
-
* a second one is how the repo grew two argv builders that disagreed about
|
|
515
|
-
* hardware.
|
|
516
|
-
*
|
|
517
|
-
* Smart video copy: when the source already speaks the requested codec the
|
|
518
|
-
* encode block is elided entirely and ffmpeg runs as a re-muxer on the video
|
|
519
|
-
* plane. Width / height / fps / bitrate in the profile are a downstream BUDGET,
|
|
520
|
-
* not a forced rescale.
|
|
521
|
-
*/
|
|
522
|
-
function invocationFromEncodeProfile(input) {
|
|
523
|
-
const v = input.profile.video;
|
|
524
|
-
const shouldCopy = v.codec === "copy" || input.forceReencode !== true && v.codec === input.sourceCodec;
|
|
525
|
-
const scale = v.width !== void 0 && v.height !== void 0 ? {
|
|
526
|
-
mode: "fit",
|
|
527
|
-
width: v.width,
|
|
528
|
-
height: v.height
|
|
529
|
-
} : null;
|
|
530
|
-
const target = v.codec === "h265" ? "h265" : "h264";
|
|
531
|
-
const video = shouldCopy ? { kind: "copy" } : {
|
|
532
|
-
kind: "encode",
|
|
533
|
-
encoder: pickVideoEncoder(target, input.decodeHwAccel, input.hardwareEncoders === true),
|
|
534
|
-
scale,
|
|
535
|
-
...v.preset !== void 0 ? { preset: v.preset } : {},
|
|
536
|
-
...v.tune !== void 0 ? { tune: v.tune } : {},
|
|
537
|
-
...v.profile !== void 0 ? { profile: v.profile } : {},
|
|
538
|
-
...v.level !== void 0 ? { level: v.level } : {},
|
|
539
|
-
...v.fps !== void 0 ? { fps: v.fps } : {},
|
|
540
|
-
...v.gopFrames !== void 0 ? { gopFrames: v.gopFrames } : {},
|
|
541
|
-
...v.bf !== void 0 ? { bf: v.bf } : {},
|
|
542
|
-
...v.bitrateKbps !== void 0 ? { bitrateKbps: v.bitrateKbps } : {}
|
|
543
|
-
};
|
|
544
|
-
return {
|
|
545
|
-
logLevel: input.logLevel ?? "error",
|
|
546
|
-
decodeHwAccel: input.decodeHwAccel,
|
|
547
|
-
input: {
|
|
548
|
-
url: input.sourceUrl,
|
|
549
|
-
rtspTransport: "tcp",
|
|
550
|
-
fflags: ["+discardcorrupt"],
|
|
551
|
-
...input.profile.inputArgs?.length ? { extraArgs: input.profile.inputArgs } : {}
|
|
552
|
-
},
|
|
553
|
-
video,
|
|
554
|
-
audio: audioPlanFromEncodeProfile(input.profile.audio),
|
|
555
|
-
threadCount: input.threadCount ?? 0,
|
|
556
|
-
outputArgs: input.profile.outputArgs ?? [],
|
|
557
|
-
sink: input.sink,
|
|
558
|
-
...input.audioSidecar !== void 0 ? { audioSidecar: input.audioSidecar } : {}
|
|
559
|
-
};
|
|
560
|
-
}
|
|
561
|
-
//#endregion
|
|
562
233
|
//#region src/ffmpeg/encode-defaults.ts
|
|
563
234
|
/**
|
|
564
235
|
* The shape every live egress starts from: H.264 Baseline 3.1 at 720p25.
|
|
@@ -603,9 +274,27 @@ var WEBRTC_EGRESS_PROFILE = {
|
|
|
603
274
|
* audio plane (out-of-band), so this is `passthrough` exactly like the browser
|
|
604
275
|
* — see the ADR for why the previous in-band Opus was encoded and discarded.
|
|
605
276
|
*/
|
|
277
|
+
/**
|
|
278
|
+
* Alexa's egress asks for OPUS, and that is a change with a history.
|
|
279
|
+
*
|
|
280
|
+
* The previous profile encoded Opus IN-BAND into an MPEG-TS, where it was
|
|
281
|
+
* discarded: Opus is `stream_type 0x06` and the broker's demuxer maps only
|
|
282
|
+
* `0x0f` (aac), `0x03`/`0x04` (mp2) and `0x81` (ac3). Every frame it produced
|
|
283
|
+
* died at the demuxer, so the encode was replaced with `passthrough` — correct,
|
|
284
|
+
* because paying libopus for nothing is worse than silence.
|
|
285
|
+
*
|
|
286
|
+
* But `passthrough` means the egress emits NO audio at all, and Alexa's audio
|
|
287
|
+
* does not arrive by magic: it rides the published stream, which is what the
|
|
288
|
+
* WebRTC session dials. So the Echo had video and silence either way.
|
|
289
|
+
*
|
|
290
|
+
* Opus here now reaches the egress AUDIO SIDECAR — a separate RTP leg the
|
|
291
|
+
* restreamer grafts onto its SDP — which never touches the MPEG-TS demuxer that
|
|
292
|
+
* killed the in-band attempt. Same codec, different plane, and this one the
|
|
293
|
+
* consumer can actually negotiate.
|
|
294
|
+
*/
|
|
606
295
|
var ALEXA_EGRESS_PROFILE = {
|
|
607
296
|
...BASE_LIVE_EGRESS_PROFILE,
|
|
608
|
-
audio: "
|
|
297
|
+
audio: { codec: "opus" }
|
|
609
298
|
};
|
|
610
299
|
/** VBV window for a consumer whose budget is enforced per second (HomeKit). */
|
|
611
300
|
var RATE_CONTROL_TIGHT = {
|
|
@@ -726,6 +415,14 @@ async function resolveEgressDecodeHwAccel(deps) {
|
|
|
726
415
|
* Here every knob is a named field, and defaults are APPLIED before hashing so
|
|
727
416
|
* an omitted field and its explicit default land on the same key.
|
|
728
417
|
*/
|
|
418
|
+
/**
|
|
419
|
+
* The transport a CAP request describes. `fragments` is deliberately
|
|
420
|
+
* unreachable from here — the request schema has no way to ask for it, so the
|
|
421
|
+
* cap path can never be handed a fragment child by accident.
|
|
422
|
+
*/
|
|
423
|
+
function egressTransportFromRequest(request) {
|
|
424
|
+
return { transport: request.publishLocally === true ? "push" : "dial" };
|
|
425
|
+
}
|
|
729
426
|
/** Absent optional ⇒ this sentinel, so `undefined` and "not set" agree. */
|
|
730
427
|
var UNSET = "\0unset";
|
|
731
428
|
function canonicalVideo(video) {
|
|
@@ -757,10 +454,12 @@ function canonicalAudio(audio) {
|
|
|
757
454
|
* future operator-facing "why are these two not sharing?" surface — can diff
|
|
758
455
|
* two requests without reversing a hash.
|
|
759
456
|
*/
|
|
760
|
-
function canonicalEgressPlan(request) {
|
|
457
|
+
function canonicalEgressPlan(request, delivery = egressTransportFromRequest(request)) {
|
|
761
458
|
return {
|
|
762
459
|
deviceId: request.deviceId,
|
|
763
460
|
source: request.source.kind === "profile" ? `profile:${request.source.profile}` : `cam-stream:${request.source.camStreamId}`,
|
|
461
|
+
transport: delivery.transport,
|
|
462
|
+
fragmentMs: delivery.fragmentMs ?? -1,
|
|
764
463
|
video: canonicalVideo(request.encode.video),
|
|
765
464
|
audio: canonicalAudio(request.encode.audio),
|
|
766
465
|
rateControl: request.rateControl ?? "relaxed",
|
|
@@ -780,8 +479,8 @@ function canonicalEgressPlan(request) {
|
|
|
780
479
|
* exactly a mutable shared object, where one consumer's downgrade dragged
|
|
781
480
|
* every other consumer to 360p.
|
|
782
481
|
*/
|
|
783
|
-
function egressTranscodeSharingKey(request) {
|
|
784
|
-
return `egress:${canonicalHash(canonicalEgressPlan(request))}`;
|
|
482
|
+
function egressTranscodeSharingKey(request, delivery = egressTransportFromRequest(request)) {
|
|
483
|
+
return `egress:${canonicalHash(canonicalEgressPlan(request, delivery))}`;
|
|
785
484
|
}
|
|
786
485
|
//#endregion
|
|
787
486
|
//#region src/health/wiring-health.ts
|
|
@@ -901,7 +600,7 @@ var DEFAULT_RETENTION = {
|
|
|
901
600
|
* ## This file adds no state
|
|
902
601
|
*
|
|
903
602
|
* Every switch here is a VIEW onto an authority that already existed
|
|
904
|
-
* ([
|
|
603
|
+
* ([D62](../../../../docs/decisions/adr-0062.md)). The whole point of the
|
|
905
604
|
* group is that there is exactly one place each function is turned off, and
|
|
906
605
|
* the group routes to it:
|
|
907
606
|
*
|
|
@@ -912,6 +611,53 @@ var DEFAULT_RETENTION = {
|
|
|
912
611
|
* | `audio-analysis` | `deviceManager.setWrapperActive('audio-analysis')` | `AudioSubscriptionController.subscribeAudioStream` returns `null` before opening the stream |
|
|
913
612
|
* | `recording` | `recording.setDeviceConfig` → `RecordingConfig.enabled` | `band-decision.shouldRecord` returns false; the controller detaches the device |
|
|
914
613
|
* | `notifications` | `notificationRules.setDeviceMuted` | `NotificationCenter.evaluateAndEnqueue` returns before any rule is evaluated |
|
|
614
|
+
* | `privacy-mask` | `privacyMask.setMask({ enabled })` → the CAMERA | the camera blanks the masked regions itself; every stream and recording carries the black boxes |
|
|
615
|
+
* | `device-audio` | `privacyMask.setAudioEnabled` → the CAMERA | the camera stops encoding an audio track at all; every consumer sees silent video |
|
|
616
|
+
* | `broker-audio` | `streamBroker.setDeviceAudioMute` → `DeviceOverride.audioMuted` | `StreamBroker.setAudioMuted` drops the audio plane at the source: no `type:'audio'` packet leaves `fanOutEncoded`, no RTP reaches the restreamer, and the restreamer serves the video-only SDP |
|
|
617
|
+
*
|
|
618
|
+
* ## `device-audio` and `broker-audio` are two functions, not two knobs
|
|
619
|
+
*
|
|
620
|
+
* They look adjacent and they are not the same control ([D83](../../../../docs/decisions/adr-0083.md)):
|
|
621
|
+
* `device-audio` writes the CAMERA, so it is hardware privacy — the microphone
|
|
622
|
+
* genuinely stops, it survives CamStack entirely, and it costs a multi-second
|
|
623
|
+
* encoder restart on every flip. `broker-audio` writes THIS server, so it is
|
|
624
|
+
* instant, vendor-independent and reversible without touching the camera, and
|
|
625
|
+
* a camera that ignores or lacks the ISAPI/Reolink control is still silenced.
|
|
626
|
+
* D62 forbids a second switch that *disagrees* with the first; these two
|
|
627
|
+
* cannot disagree, because neither reads the other's store — the camera holds
|
|
628
|
+
* one, the broker holds the other, and each reports its own fact.
|
|
629
|
+
*
|
|
630
|
+
* ## The two switches whose authority is not on this server
|
|
631
|
+
*
|
|
632
|
+
* `privacy-mask` and `device-audio` write the CAMERA. That is not a loophole
|
|
633
|
+
* in "the group stores nothing" — it is the purest form of it: the camera
|
|
634
|
+
* holds the fact, every read is a read-through, and there is no server-side
|
|
635
|
+
* copy that could drift. Their availability therefore cannot come from
|
|
636
|
+
* `listBindableCapsForDeviceType` (a device-NATIVE cap carries no wrappers and
|
|
637
|
+
* is filtered out there); it comes from the cap's own camera-probed
|
|
638
|
+
* `privacyMask.getOptions()`, which is strictly more honest — it answers for
|
|
639
|
+
* THIS camera rather than for the device type
|
|
640
|
+
* ([D74](../../../../docs/decisions/adr-0074.md)).
|
|
641
|
+
*
|
|
642
|
+
* ## `privacy-mask` is the one row whose ON is not "the function is working"
|
|
643
|
+
*
|
|
644
|
+
* Every other switch means *this camera's function is doing its job*, so
|
|
645
|
+
* `enabled: false` is a thing an operator took away. `privacy-mask` means **the
|
|
646
|
+
* MASK is active** — `enabled: true` is video deliberately obscured. The
|
|
647
|
+
* polarity is not a choice made here: `addon-export-hap`'s privacy `Switch`
|
|
648
|
+
* (`builders/privacy-switch.ts`) already mirrors `patch.enabled` verbatim, and
|
|
649
|
+
* a HomeKit toggle that disagreed with the app's toggle for the same camera is
|
|
650
|
+
* worse than either surface not having one.
|
|
651
|
+
*
|
|
652
|
+
* Two consequences follow and both are load-bearing:
|
|
653
|
+
*
|
|
654
|
+
* - **It never counts as `switchedOff`.** `countsAsSwitchedOff` is `false` for
|
|
655
|
+
* exactly this row. With the polarity above, every camera that has NOT drawn
|
|
656
|
+
* a privacy mask would otherwise report `switchedOff: ['privacy-mask']` — the
|
|
657
|
+
* normal, healthy state of most cameras rendered as an operator disablement.
|
|
658
|
+
* - **Its cost line names BOTH directions.** `costWhenOff` is rendered
|
|
659
|
+
* unconditionally by both clients, so for this row it has to read correctly
|
|
660
|
+
* whichever way the switch is sitting.
|
|
915
661
|
*
|
|
916
662
|
* The wrapper-binding pair is not a new idea: `legacy-migrations.ts` already
|
|
917
663
|
* migrated the legacy `audioEnabled` / `pipelineEnabled` /
|
|
@@ -930,22 +676,44 @@ var DEFAULT_RETENTION = {
|
|
|
930
676
|
* `CameraStatus.switchedOff`.
|
|
931
677
|
*/
|
|
932
678
|
/**
|
|
933
|
-
* The
|
|
934
|
-
*
|
|
679
|
+
* The functions the operator named — five on 2026-08-05, plus the camera's own
|
|
680
|
+
* microphone on 2026-08-07. Deliberately NOT one id per pipeline step: face
|
|
681
|
+
* recognition and plate/LPR are per-step toggles on
|
|
935
682
|
* `pipelineOrchestrator.setCameraStepToggle` and belong in the pipeline
|
|
936
|
-
* editor, not in a
|
|
683
|
+
* editor, not in a safety group.
|
|
937
684
|
*/
|
|
938
685
|
var CameraSwitchIdSchema = z.enum([
|
|
939
686
|
"stream-broker",
|
|
940
687
|
"object-detection",
|
|
688
|
+
"privacy-mask",
|
|
689
|
+
"device-audio",
|
|
690
|
+
"broker-audio",
|
|
941
691
|
"audio-analysis",
|
|
942
692
|
"recording",
|
|
943
693
|
"notifications"
|
|
944
694
|
]);
|
|
945
|
-
/**
|
|
695
|
+
/**
|
|
696
|
+
* Stable render order — broadest blast radius first, and a source before the
|
|
697
|
+
* thing that consumes it. `device-audio` sits ABOVE `audio-analysis` because
|
|
698
|
+
* turning the microphone off leaves the analyzer with nothing to analyse; the
|
|
699
|
+
* reverse is not true.
|
|
700
|
+
*
|
|
701
|
+
* `privacy-mask` sits directly ABOVE `device-audio` because they are literal
|
|
702
|
+
* siblings — one cap, one device plane, video then audio — and NOT above
|
|
703
|
+
* `object-detection` despite feeding it: a mask blanks REGIONS, so its blast
|
|
704
|
+
* radius is partial, and the "broadest first" rule does not rank a partial
|
|
705
|
+
* control above a whole-function one.
|
|
706
|
+
*
|
|
707
|
+
* `broker-audio` sits directly BELOW `device-audio` by the same source-first
|
|
708
|
+
* rule: the camera's microphone feeds the broker, so silencing the camera
|
|
709
|
+
* leaves the broker's mute with nothing to suppress; the reverse is not true.
|
|
710
|
+
*/
|
|
946
711
|
var CAMERA_SWITCH_ORDER = [
|
|
947
712
|
"stream-broker",
|
|
948
713
|
"object-detection",
|
|
714
|
+
"privacy-mask",
|
|
715
|
+
"device-audio",
|
|
716
|
+
"broker-audio",
|
|
949
717
|
"audio-analysis",
|
|
950
718
|
"recording",
|
|
951
719
|
"notifications"
|
|
@@ -963,14 +731,27 @@ var CameraSwitchAuthoritySchema = z.discriminatedUnion("kind", [
|
|
|
963
731
|
capName: z.string()
|
|
964
732
|
}),
|
|
965
733
|
z.object({ kind: z.literal("recording-config") }),
|
|
966
|
-
z.object({ kind: z.literal("notification-mute") })
|
|
734
|
+
z.object({ kind: z.literal("notification-mute") }),
|
|
735
|
+
z.object({
|
|
736
|
+
kind: z.literal("camera-audio"),
|
|
737
|
+
capName: z.string()
|
|
738
|
+
}),
|
|
739
|
+
z.object({
|
|
740
|
+
kind: z.literal("camera-mask"),
|
|
741
|
+
capName: z.string()
|
|
742
|
+
}),
|
|
743
|
+
z.object({ kind: z.literal("broker-audio-mute") })
|
|
967
744
|
]);
|
|
968
745
|
/**
|
|
969
746
|
* Why a switch is not offered for this camera. Rendered instead of the
|
|
970
747
|
* control, never as a dead control — an absent function and a broken one must
|
|
971
748
|
* not look the same.
|
|
972
749
|
*/
|
|
973
|
-
var CameraSwitchUnavailableReasonSchema = z.enum([
|
|
750
|
+
var CameraSwitchUnavailableReasonSchema = z.enum([
|
|
751
|
+
"no-provider",
|
|
752
|
+
"source-unreachable",
|
|
753
|
+
"not-configured"
|
|
754
|
+
]);
|
|
974
755
|
/**
|
|
975
756
|
* One switch, resolved for one camera.
|
|
976
757
|
*
|
|
@@ -1010,6 +791,13 @@ var CameraSwitchGroupSchema = z.object({
|
|
|
1010
791
|
var DETECTION_PIPELINE_CAP_NAME = "detection-pipeline";
|
|
1011
792
|
var AUDIO_ANALYSIS_CAP_NAME = "audio-analysis";
|
|
1012
793
|
/**
|
|
794
|
+
* The device-NATIVE cap that owns what the camera does not capture — masked
|
|
795
|
+
* video regions and, since 2026-08-07, the microphone. Named here because the
|
|
796
|
+
* `camera-audio` authority, the orchestrator's gather and the fake harness all
|
|
797
|
+
* have to agree on it.
|
|
798
|
+
*/
|
|
799
|
+
var PRIVACY_MASK_CAP_NAME = "privacy-mask";
|
|
800
|
+
/**
|
|
1013
801
|
* THE catalog. One entry per switch; the cost lines are the operator-facing
|
|
1014
802
|
* contract and are written to be true rather than reassuring.
|
|
1015
803
|
*/
|
|
@@ -1018,7 +806,8 @@ var CAMERA_SWITCH_CATALOG = {
|
|
|
1018
806
|
id: "stream-broker",
|
|
1019
807
|
label: "Camera",
|
|
1020
808
|
costWhenOff: "Off: the whole camera stops. No live view, no recording, no detection and no notifications — its streams are released and nothing dials it again until you turn it back on.",
|
|
1021
|
-
authority: { kind: "device-disabled" }
|
|
809
|
+
authority: { kind: "device-disabled" },
|
|
810
|
+
countsAsSwitchedOff: true
|
|
1022
811
|
},
|
|
1023
812
|
"object-detection": {
|
|
1024
813
|
id: "object-detection",
|
|
@@ -1027,7 +816,35 @@ var CAMERA_SWITCH_CATALOG = {
|
|
|
1027
816
|
authority: {
|
|
1028
817
|
kind: "wrapper-binding",
|
|
1029
818
|
capName: DETECTION_PIPELINE_CAP_NAME
|
|
1030
|
-
}
|
|
819
|
+
},
|
|
820
|
+
countsAsSwitchedOff: true
|
|
821
|
+
},
|
|
822
|
+
"privacy-mask": {
|
|
823
|
+
id: "privacy-mask",
|
|
824
|
+
label: "Privacy mask",
|
|
825
|
+
costWhenOff: "On: the zones you drew on this camera are blacked out by the camera itself — live view, playback, exports and detection all see the black boxes, and nothing behind them was ever recorded. Off: the camera captures the whole frame, and your zones are kept for when you turn it back on.",
|
|
826
|
+
authority: {
|
|
827
|
+
kind: "camera-mask",
|
|
828
|
+
capName: PRIVACY_MASK_CAP_NAME
|
|
829
|
+
},
|
|
830
|
+
countsAsSwitchedOff: false
|
|
831
|
+
},
|
|
832
|
+
"device-audio": {
|
|
833
|
+
id: "device-audio",
|
|
834
|
+
label: "Camera microphone",
|
|
835
|
+
costWhenOff: "Off: the camera captures no sound at all. Live view and recordings become silent video, and audio detection and classification have nothing left to analyse — turning them back on will not recover it. The picture, motion and object detection are unaffected, and two-way talk still works. Applies at the camera, so every consumer sees the same silence.",
|
|
836
|
+
authority: {
|
|
837
|
+
kind: "camera-audio",
|
|
838
|
+
capName: PRIVACY_MASK_CAP_NAME
|
|
839
|
+
},
|
|
840
|
+
countsAsSwitchedOff: true
|
|
841
|
+
},
|
|
842
|
+
"broker-audio": {
|
|
843
|
+
id: "broker-audio",
|
|
844
|
+
label: "Audio distribution",
|
|
845
|
+
costWhenOff: "Off: this server distributes no sound for this camera — live view is silent and everything recorded while it is off is silent FOREVER, even after you turn it back on. Audio detection and classification also have nothing to analyse. The camera keeps capturing sound, so nothing about the camera changes and turning this back on is instant, with no interruption to the picture.",
|
|
846
|
+
authority: { kind: "broker-audio-mute" },
|
|
847
|
+
countsAsSwitchedOff: true
|
|
1031
848
|
},
|
|
1032
849
|
"audio-analysis": {
|
|
1033
850
|
id: "audio-analysis",
|
|
@@ -1036,19 +853,22 @@ var CAMERA_SWITCH_CATALOG = {
|
|
|
1036
853
|
authority: {
|
|
1037
854
|
kind: "wrapper-binding",
|
|
1038
855
|
capName: AUDIO_ANALYSIS_CAP_NAME
|
|
1039
|
-
}
|
|
856
|
+
},
|
|
857
|
+
countsAsSwitchedOff: true
|
|
1040
858
|
},
|
|
1041
859
|
recording: {
|
|
1042
860
|
id: "recording",
|
|
1043
861
|
label: "Recording",
|
|
1044
862
|
costWhenOff: "Off: nothing new is written to disk. Footage already recorded stays, but retention keeps deleting it — so this camera’s history shrinks and is not replaced. Your recording schedule is kept and resumes when you turn it back on.",
|
|
1045
|
-
authority: { kind: "recording-config" }
|
|
863
|
+
authority: { kind: "recording-config" },
|
|
864
|
+
countsAsSwitchedOff: true
|
|
1046
865
|
},
|
|
1047
866
|
notifications: {
|
|
1048
867
|
id: "notifications",
|
|
1049
868
|
label: "Notifications",
|
|
1050
869
|
costWhenOff: "Off: this camera never notifies anyone, on any rule, with no expiry. Detection, events and recording carry on exactly as before — you simply stop being told about them.",
|
|
1051
|
-
authority: { kind: "notification-mute" }
|
|
870
|
+
authority: { kind: "notification-mute" },
|
|
871
|
+
countsAsSwitchedOff: true
|
|
1052
872
|
}
|
|
1053
873
|
};
|
|
1054
874
|
/** Resolve one switch's `{ available, enabled }` pair. */
|
|
@@ -1095,6 +915,67 @@ function resolveState(descriptor, input) {
|
|
|
1095
915
|
available: true,
|
|
1096
916
|
enabled: !input.notificationsMuted
|
|
1097
917
|
};
|
|
918
|
+
case "camera-audio": {
|
|
919
|
+
const audio = input.deviceAudio;
|
|
920
|
+
if (audio === null) return {
|
|
921
|
+
available: false,
|
|
922
|
+
enabled: true,
|
|
923
|
+
unavailableReason: "source-unreachable"
|
|
924
|
+
};
|
|
925
|
+
if (!audio.supported) return {
|
|
926
|
+
available: false,
|
|
927
|
+
enabled: true,
|
|
928
|
+
unavailableReason: "no-provider"
|
|
929
|
+
};
|
|
930
|
+
if (audio.enabled === null) return {
|
|
931
|
+
available: false,
|
|
932
|
+
enabled: true,
|
|
933
|
+
unavailableReason: "source-unreachable"
|
|
934
|
+
};
|
|
935
|
+
return {
|
|
936
|
+
available: true,
|
|
937
|
+
enabled: audio.enabled
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
case "camera-mask": {
|
|
941
|
+
const mask = input.privacyMask;
|
|
942
|
+
if (mask === null) return {
|
|
943
|
+
available: false,
|
|
944
|
+
enabled: false,
|
|
945
|
+
unavailableReason: "source-unreachable"
|
|
946
|
+
};
|
|
947
|
+
if (!mask.supported) return {
|
|
948
|
+
available: false,
|
|
949
|
+
enabled: false,
|
|
950
|
+
unavailableReason: "no-provider"
|
|
951
|
+
};
|
|
952
|
+
if (mask.configuredRegions === null || mask.enabled === null) return {
|
|
953
|
+
available: false,
|
|
954
|
+
enabled: false,
|
|
955
|
+
unavailableReason: "source-unreachable"
|
|
956
|
+
};
|
|
957
|
+
if (mask.configuredRegions === 0) return {
|
|
958
|
+
available: false,
|
|
959
|
+
enabled: false,
|
|
960
|
+
unavailableReason: "not-configured"
|
|
961
|
+
};
|
|
962
|
+
return {
|
|
963
|
+
available: true,
|
|
964
|
+
enabled: mask.enabled
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
case "broker-audio-mute": {
|
|
968
|
+
const broker = input.brokerAudio;
|
|
969
|
+
if (broker === null) return {
|
|
970
|
+
available: false,
|
|
971
|
+
enabled: true,
|
|
972
|
+
unavailableReason: "source-unreachable"
|
|
973
|
+
};
|
|
974
|
+
return {
|
|
975
|
+
available: true,
|
|
976
|
+
enabled: !broker.muted
|
|
977
|
+
};
|
|
978
|
+
}
|
|
1098
979
|
}
|
|
1099
980
|
}
|
|
1100
981
|
/**
|
|
@@ -1128,9 +1009,15 @@ function deriveCameraSwitches(input) {
|
|
|
1128
1009
|
* `switchedOff: ['object-detection']` was turned off; the same camera with an
|
|
1129
1010
|
* empty list is broken. Unavailable switches never appear — a function nobody
|
|
1130
1011
|
* provides was not switched off by anyone.
|
|
1012
|
+
*
|
|
1013
|
+
* `privacy-mask` never appears either, whichever way it is sitting, because its
|
|
1014
|
+
* ON means "the mask is active" rather than "the function works"
|
|
1015
|
+
* ({@link CameraSwitchDescriptor.countsAsSwitchedOff}). Without that filter the
|
|
1016
|
+
* ordinary state of every camera nobody has masked would carry a
|
|
1017
|
+
* "switched off" badge, and the badge that matters would be lost in it.
|
|
1131
1018
|
*/
|
|
1132
1019
|
function switchedOffIds(switches) {
|
|
1133
|
-
return switches.filter((s) => s.available && !s.enabled).map((s) => s.id);
|
|
1020
|
+
return switches.filter((s) => CAMERA_SWITCH_CATALOG[s.id].countsAsSwitchedOff && s.available && !s.enabled).map((s) => s.id);
|
|
1134
1021
|
}
|
|
1135
1022
|
//#endregion
|
|
1136
1023
|
//#region src/interfaces/device-capabilities/camera.ts
|
|
@@ -4166,6 +4053,26 @@ var EgressTranscodeRequestSchema = z.object({
|
|
|
4166
4053
|
"h264_mp4toannexb",
|
|
4167
4054
|
"hevc_mp4toannexb"
|
|
4168
4055
|
]).optional(),
|
|
4056
|
+
/**
|
|
4057
|
+
* Publish the transcode as a LOCAL push cam stream, instead of leaving the
|
|
4058
|
+
* consumer to dial the returned url. The broker picks the id and returns it
|
|
4059
|
+
* as `camStreamId` — a caller-supplied one would be circular, since the
|
|
4060
|
+
* sharing key is computed FROM this request.
|
|
4061
|
+
*
|
|
4062
|
+
* The url is still returned and still the contract for a transcode pinned to
|
|
4063
|
+
* another node. But dialling it locally costs an RTSP round trip that changes
|
|
4064
|
+
* the transport underneath the consumer: a dialled stream is an RTP source,
|
|
4065
|
+
* so `isRtpSource()` is true and the session takes the RTP-passthrough +
|
|
4066
|
+
* repacketizer branch. The push branch — the one the derived mechanism has
|
|
4067
|
+
* live hours on — is never reached. Measured on Alexa: broker registered, RTP
|
|
4068
|
+
* arriving, key frame arriving, black screen, on a chain healthy at every
|
|
4069
|
+
* other point.
|
|
4070
|
+
*
|
|
4071
|
+
* Same idea the transport already applies to CALLS, where `classifyCapRoute`
|
|
4072
|
+
* gives priority to `hub-in-process` so a local call never leaves the node.
|
|
4073
|
+
* This is that rule for media.
|
|
4074
|
+
*/
|
|
4075
|
+
publishLocally: z.boolean().optional(),
|
|
4169
4076
|
pixelFormat: z.enum(["yuv420p", "nv12"]).optional(),
|
|
4170
4077
|
/**
|
|
4171
4078
|
* Operator/consumer override for decode hardware. ABSENT is the normal case
|
|
@@ -4210,7 +4117,13 @@ var EgressTranscodeSchema = z.object({
|
|
|
4210
4117
|
* Returned rather than assumed: a consumer that asked for hardware and got
|
|
4211
4118
|
* software needs to be able to see that without reading the broker's logs.
|
|
4212
4119
|
*/
|
|
4213
|
-
decodeHwAccel: z.string().nullable()
|
|
4120
|
+
decodeHwAccel: z.string().nullable(),
|
|
4121
|
+
/**
|
|
4122
|
+
* Set when `publishLocally` was honoured: attach to THIS instead of dialling
|
|
4123
|
+
* `url`, and the session takes the push/deframe transport rather than the
|
|
4124
|
+
* RTP-passthrough one. `null` means the consumer must dial.
|
|
4125
|
+
*/
|
|
4126
|
+
camStreamId: z.string().nullable()
|
|
4214
4127
|
});
|
|
4215
4128
|
var streamBrokerCapability = {
|
|
4216
4129
|
name: "stream-broker",
|
|
@@ -4504,7 +4417,44 @@ var streamBrokerCapability = {
|
|
|
4504
4417
|
kind: "mutation",
|
|
4505
4418
|
auth: "admin"
|
|
4506
4419
|
}),
|
|
4507
|
-
isRtspEnabled: method(z.object({ brokerId: z.string() }), z.boolean())
|
|
4420
|
+
isRtspEnabled: method(z.object({ brokerId: z.string() }), z.boolean()),
|
|
4421
|
+
/**
|
|
4422
|
+
* ── Per-device audio-plane policy (D83) ───────────────────────────
|
|
4423
|
+
*
|
|
4424
|
+
* The BROKER-side mute: while `muted`, this node distributes none of
|
|
4425
|
+
* the device's audio, on any plane it serves — live (WebRTC / encoded
|
|
4426
|
+
* subscribers) AND recording (the RTSP restreamer the recorder pulls,
|
|
4427
|
+
* which additionally serves the video-only SDP so the recorder's ffmpeg
|
|
4428
|
+
* never declares an audio stream it will not receive).
|
|
4429
|
+
*
|
|
4430
|
+
* Keyed by `deviceId`, not `brokerId`: every one of a camera's streams
|
|
4431
|
+
* carries the same microphone, and a per-stream answer would let main
|
|
4432
|
+
* and sub disagree about whether the camera is silent.
|
|
4433
|
+
*
|
|
4434
|
+
* The state lives in the broker's existing `DeviceOverride` blob — no
|
|
4435
|
+
* new store — and the mute is applied to a fresh broker at creation, so
|
|
4436
|
+
* a restart, a re-dial or a catalog republish never un-mutes a camera.
|
|
4437
|
+
*/
|
|
4438
|
+
getDeviceAudioMute: method(z.object({ deviceId: z.number().int() }), z.object({
|
|
4439
|
+
muted: z.boolean(),
|
|
4440
|
+
/**
|
|
4441
|
+
* How many live non-derived brokers currently hold the mute. Purely
|
|
4442
|
+
* diagnostic: `muted` is the policy and is authoritative on its own
|
|
4443
|
+
* (it applies to brokers that do not exist yet), while this says
|
|
4444
|
+
* whether anything is presently being silenced.
|
|
4445
|
+
*/
|
|
4446
|
+
appliedBrokers: z.number().int().nonnegative()
|
|
4447
|
+
})),
|
|
4448
|
+
setDeviceAudioMute: method(z.object({
|
|
4449
|
+
deviceId: z.number().int(),
|
|
4450
|
+
muted: z.boolean()
|
|
4451
|
+
}), z.object({
|
|
4452
|
+
muted: z.boolean(),
|
|
4453
|
+
appliedBrokers: z.number().int().nonnegative()
|
|
4454
|
+
}), {
|
|
4455
|
+
kind: "mutation",
|
|
4456
|
+
auth: "admin"
|
|
4457
|
+
})
|
|
4508
4458
|
},
|
|
4509
4459
|
events: {
|
|
4510
4460
|
onCamStreamDemand: event(z.object({
|
|
@@ -12351,6 +12301,30 @@ var TrackSourceSchema = z.enum([
|
|
|
12351
12301
|
"audio"
|
|
12352
12302
|
]);
|
|
12353
12303
|
/**
|
|
12304
|
+
* Where a track sits in the RETRAIN lifecycle (D81).
|
|
12305
|
+
*
|
|
12306
|
+
* - `none` — never marked, or un-marked. Evictable.
|
|
12307
|
+
* - `staging` — the operator wants this track as training material and has not
|
|
12308
|
+
* finished with it. **This is the only state retention holds**: the track and
|
|
12309
|
+
* everything it owns (object events, crops, keyframes, CLIP vector) survive
|
|
12310
|
+
* the device's age window.
|
|
12311
|
+
* - `trained` — the retrain page has taken what it needed. The frames it chose
|
|
12312
|
+
* were COPIED into the retrain dataset at selection time, so the dataset no
|
|
12313
|
+
* longer depends on the track's media and the track becomes EVICTABLE again.
|
|
12314
|
+
* Terminal for the plain `markForTrain` toggle: returning it to `staging` is
|
|
12315
|
+
* a deliberate action of the retrain page, not a side effect of a checkbox.
|
|
12316
|
+
*
|
|
12317
|
+
* There is no `null`. The state is stored `TEXT NOT NULL DEFAULT 'none'` because
|
|
12318
|
+
* the store's filter language has only positive equality and `whereIn` — no
|
|
12319
|
+
* negation, no IS NULL — so a NULL would be unselectable by ANY predicate and
|
|
12320
|
+
* would make the entire pre-column history immortal in one deploy.
|
|
12321
|
+
*/
|
|
12322
|
+
var RetrainStatusSchema = z.enum([
|
|
12323
|
+
"none",
|
|
12324
|
+
"staging",
|
|
12325
|
+
"trained"
|
|
12326
|
+
]);
|
|
12327
|
+
/**
|
|
12354
12328
|
* Per-track OPERATOR flags — set by hand from the admin UI or the viewer, never
|
|
12355
12329
|
* by the pipeline. Spread into `TrackSchema` and `KeyEventSchema` from one place
|
|
12356
12330
|
* so the two surfaces cannot drift.
|
|
@@ -12360,18 +12334,31 @@ var TrackSourceSchema = z.enum([
|
|
|
12360
12334
|
* columns existed read as absent, and a consumer that needs a boolean should say
|
|
12361
12335
|
* `flag === true`, not `flag !== false`.
|
|
12362
12336
|
*
|
|
12363
|
-
*
|
|
12364
|
-
*
|
|
12365
|
-
*
|
|
12366
|
-
* `
|
|
12337
|
+
* `markForTrain` is the WIRE FACE of {@link RetrainStatusSchema}, not a column:
|
|
12338
|
+
* it is exactly `retrainStatus === 'staging'`, in both directions. Writing
|
|
12339
|
+
* `true` moves `none → staging`, writing `false` moves `staging → none`, and a
|
|
12340
|
+
* `trained` track reports `false` while refusing both writes. The boolean is
|
|
12341
|
+
* kept because three surfaces drive a toggle off it; anything that needs to tell
|
|
12342
|
+
* "never marked" from "already trained" must read `retrainStatus`.
|
|
12343
|
+
*
|
|
12344
|
+
* `debug` does NOT pin; it is attention, not durability.
|
|
12367
12345
|
*/
|
|
12368
12346
|
var TrackFlagFields = {
|
|
12369
|
-
/** Operator marked this track as training material.
|
|
12347
|
+
/** Operator marked this track as training material — i.e. `retrainStatus` is
|
|
12348
|
+
* `'staging'`. */
|
|
12370
12349
|
markForTrain: z.boolean().optional(),
|
|
12371
12350
|
/** Operator marked this track for diagnostic attention. */
|
|
12372
12351
|
debug: z.boolean().optional()
|
|
12373
12352
|
};
|
|
12374
12353
|
/**
|
|
12354
|
+
* The lifecycle field itself, on the READ surfaces only (`Track`, `KeyEvent`).
|
|
12355
|
+
* Deliberately NOT part of {@link TrackFlagFields}: that group also builds the
|
|
12356
|
+
* write patch, and the status is not something the toggle sets — it is what the
|
|
12357
|
+
* toggle's boolean is derived from. Absent on an in-RAM track never touched;
|
|
12358
|
+
* always present on a persisted row (the column default materialises `'none'`).
|
|
12359
|
+
*/
|
|
12360
|
+
var TrackRetrainFields = { retrainStatus: RetrainStatusSchema.optional() };
|
|
12361
|
+
/**
|
|
12375
12362
|
* The write half: a PARTIAL patch. An omitted key is left untouched, so setting
|
|
12376
12363
|
* one flag can never clear the other — the toggles are independent and are
|
|
12377
12364
|
* driven from three surfaces that do not know about each other.
|
|
@@ -12385,7 +12372,32 @@ var TrackFlagsPatchSchema = z.object(TrackFlagFields);
|
|
|
12385
12372
|
var TrackFlagsSchema = z.object({
|
|
12386
12373
|
trackId: z.string(),
|
|
12387
12374
|
markForTrain: z.boolean(),
|
|
12388
|
-
debug: z.boolean()
|
|
12375
|
+
debug: z.boolean(),
|
|
12376
|
+
/** The lifecycle state the boolean was derived from. Required here (unlike on
|
|
12377
|
+
* a track row) because this shape is only ever produced by the write body,
|
|
12378
|
+
* which always knows it — and a surface that has just written needs to render
|
|
12379
|
+
* `trained` without a re-fetch. */
|
|
12380
|
+
retrainStatus: RetrainStatusSchema
|
|
12381
|
+
});
|
|
12382
|
+
/** Per-camera slice of a training-export estimate. */
|
|
12383
|
+
var TrainingExportDeviceTotalsSchema = z.object({
|
|
12384
|
+
deviceId: z.number(),
|
|
12385
|
+
tracks: z.number().int(),
|
|
12386
|
+
files: z.number().int(),
|
|
12387
|
+
bytes: z.number().int()
|
|
12388
|
+
});
|
|
12389
|
+
/**
|
|
12390
|
+
* What a training export WOULD contain. Computed from media index rows only —
|
|
12391
|
+
* no blob is read to produce this.
|
|
12392
|
+
*/
|
|
12393
|
+
var TrainingExportSummarySchema = z.object({
|
|
12394
|
+
generatedAt: z.number(),
|
|
12395
|
+
trackCount: z.number().int(),
|
|
12396
|
+
fileCount: z.number().int(),
|
|
12397
|
+
byteCount: z.number().int(),
|
|
12398
|
+
/** More marked tracks exist than a single pass carries. */
|
|
12399
|
+
truncated: z.boolean(),
|
|
12400
|
+
devices: z.array(TrainingExportDeviceTotalsSchema).readonly()
|
|
12389
12401
|
});
|
|
12390
12402
|
var TrackSchema = z.object({
|
|
12391
12403
|
trackId: z.string(),
|
|
@@ -12430,7 +12442,8 @@ var TrackSchema = z.object({
|
|
|
12430
12442
|
* Populated from the persisted envelope columns on historical reads;
|
|
12431
12443
|
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
12432
12444
|
envelope: TrackEnvelopeSchema.optional(),
|
|
12433
|
-
...TrackFlagFields
|
|
12445
|
+
...TrackFlagFields,
|
|
12446
|
+
...TrackRetrainFields
|
|
12434
12447
|
});
|
|
12435
12448
|
var BaseEventFields = {
|
|
12436
12449
|
id: z.string(),
|
|
@@ -12652,7 +12665,8 @@ var KeyEventSchema = z.object({
|
|
|
12652
12665
|
bestEventId: z.string(),
|
|
12653
12666
|
/** Track lifetime in ms (lastSeen - firstSeen). */
|
|
12654
12667
|
windowMs: z.number().optional(),
|
|
12655
|
-
...TrackFlagFields
|
|
12668
|
+
...TrackFlagFields,
|
|
12669
|
+
...TrackRetrainFields
|
|
12656
12670
|
});
|
|
12657
12671
|
var TrackedDetectionSchema = z.object({
|
|
12658
12672
|
trackId: z.string(),
|
|
@@ -13014,11 +13028,29 @@ var pipelineAnalyticsCapability = {
|
|
|
13014
13028
|
*
|
|
13015
13029
|
* `auth: 'protected'` (the default), NOT `admin`: the viewer is an
|
|
13016
13030
|
* authenticated non-admin surface and two of the three call sites are
|
|
13017
|
-
* there.
|
|
13018
|
-
*
|
|
13031
|
+
* there. The note that used to sit here said to revisit this the day a flag
|
|
13032
|
+
* gained an effect that costs storage, and D81 is that day — `markForTrain`
|
|
13033
|
+
* now pins. It STAYS protected, and the reason is that the alternative
|
|
13034
|
+
* makes the feature pointless: marking a track is something you do while
|
|
13035
|
+
* looking at it, on the surface you were already looking at it on, and that
|
|
13036
|
+
* surface is the viewer. What the storage cost gets instead is a BOUND — a
|
|
13037
|
+
* per-device pin budget enforced in the body, refusing a new pin past the
|
|
13038
|
+
* limit while always allowing un-marking. `deleteTracks` next door is still
|
|
13039
|
+
* admin, because destroying evidence and preserving it are not symmetric.
|
|
13040
|
+
*
|
|
13041
|
+
* `markForTrain` writes the retrain LIFECYCLE, not a boolean column: `true`
|
|
13042
|
+
* is `none → staging`, `false` is `staging → none`. A track already
|
|
13043
|
+
* `trained` refuses BOTH — its frames are copies inside the retrain dataset
|
|
13044
|
+
* and re-staging it from a generic toggle is how the same material gets
|
|
13045
|
+
* annotated twice under two ground truths. Returning a trained track to
|
|
13046
|
+
* staging is a deliberate action of the retrain page, which is also the only
|
|
13047
|
+
* thing that produces `trained` in the first place.
|
|
13019
13048
|
*
|
|
13020
|
-
* Returns the RESOLVED state of both flags (absent → `false`)
|
|
13021
|
-
*
|
|
13049
|
+
* Returns the RESOLVED state of both flags (absent → `false`) plus the
|
|
13050
|
+
* `retrainStatus` they were derived from, so a caller can drive its toggle
|
|
13051
|
+
* — and render a `trained` badge — without a re-fetch. Rejects an unknown
|
|
13052
|
+
* track, a new staging mark on a device already holding its full budget, and
|
|
13053
|
+
* any `markForTrain` write against a trained track.
|
|
13022
13054
|
*/
|
|
13023
13055
|
setTrackFlags: method(z.object({
|
|
13024
13056
|
/** Log/audit scope only — the trackId is globally unique on its own. */
|
|
@@ -13082,6 +13114,42 @@ var pipelineAnalyticsCapability = {
|
|
|
13082
13114
|
kind: "query",
|
|
13083
13115
|
auth: "admin"
|
|
13084
13116
|
}),
|
|
13117
|
+
/**
|
|
13118
|
+
* The CHEAP QUESTION, asked before any media moves: how big is the dataset
|
|
13119
|
+
* the marked (`markForTrain`) tracks would produce?
|
|
13120
|
+
*
|
|
13121
|
+
* Answered from media INDEX rows only — key, kind, size, timestamp — so it
|
|
13122
|
+
* costs ~2 KB of reads per track and no blob reads at all. The measured harm
|
|
13123
|
+
* behind D56 was a bulk pass that read and base64'd every blob a track owned
|
|
13124
|
+
* before deciding anything, taking hub-main to 82 s busy out of 120; an
|
|
13125
|
+
* export is that same I/O shape, so it inherits the same discipline: know
|
|
13126
|
+
* the size, then decide.
|
|
13127
|
+
*
|
|
13128
|
+
* `truncated` reports that more marked tracks exist than one pass carries.
|
|
13129
|
+
* Empty `deviceIds` ⇒ every device that has marked tracks.
|
|
13130
|
+
*/
|
|
13131
|
+
getTrainingExportSummary: method(z.object({ deviceIds: z.array(z.number()).optional() }), TrainingExportSummarySchema, {
|
|
13132
|
+
kind: "query",
|
|
13133
|
+
auth: "admin"
|
|
13134
|
+
}),
|
|
13135
|
+
/**
|
|
13136
|
+
* Where to download the dataset archive.
|
|
13137
|
+
*
|
|
13138
|
+
* The BYTES do not come back through this cap — they come from the returned
|
|
13139
|
+
* data-plane URL, which streams a tar built entry by entry. A multi-gigabyte
|
|
13140
|
+
* archive base64'd through a unary RPC envelope would be held whole in
|
|
13141
|
+
* memory twice on a hub this repo has already OOM'd once (D9/D18 are the
|
|
13142
|
+
* same lesson about frames). `getDownloadUrl` on `recordingExport` is the
|
|
13143
|
+
* precedent, and this follows it deliberately.
|
|
13144
|
+
*
|
|
13145
|
+
* The archive contains a `manifest.json` FIRST, then the stored media
|
|
13146
|
+
* VERBATIM under `tracks/<deviceId>/<trackId>/…`. No crop is derived and no
|
|
13147
|
+
* model is run: a training set's pixels must be the pixels the pipeline saw.
|
|
13148
|
+
*/
|
|
13149
|
+
getTrainingExportUrl: method(z.object({ deviceIds: z.array(z.number()).optional() }), z.object({ url: z.string() }), {
|
|
13150
|
+
kind: "query",
|
|
13151
|
+
auth: "admin"
|
|
13152
|
+
}),
|
|
13085
13153
|
getEventMedia: method(z.object({
|
|
13086
13154
|
eventId: z.string(),
|
|
13087
13155
|
kind: MediaFileKindEnum.optional()
|
|
@@ -15862,9 +15930,15 @@ var snapshotCapability = {
|
|
|
15862
15930
|
* Bypass the cache freshness check and fetch directly from the
|
|
15863
15931
|
* native (or stream-broker fallback). Triggered by the UI's
|
|
15864
15932
|
* "refresh" button so an operator can force a fresh frame
|
|
15865
|
-
* even when the cache is well within
|
|
15866
|
-
*
|
|
15867
|
-
*
|
|
15933
|
+
* even when the cache is well within the device's
|
|
15934
|
+
* `snapshotMaxAgeS` window.
|
|
15935
|
+
*
|
|
15936
|
+
* **`force` is an OPERATOR signal, not a freshness preference.** On a
|
|
15937
|
+
* battery camera it is the one thing that walks past the wrapper's
|
|
15938
|
+
* sleep gate and wakes the camera, so a background caller — a poller,
|
|
15939
|
+
* an event handler, a thumbnail — must NEVER set it. Every such caller
|
|
15940
|
+
* gets the cached frame, which on a sleeping battery camera is the
|
|
15941
|
+
* correct answer: stale but honest beats woken.
|
|
15868
15942
|
*/
|
|
15869
15943
|
force: z.boolean().optional()
|
|
15870
15944
|
}), SnapshotImageSchema.nullable()),
|
|
@@ -21840,6 +21914,216 @@ setOverlay: method(z.object({
|
|
|
21840
21914
|
}] }
|
|
21841
21915
|
};
|
|
21842
21916
|
//#endregion
|
|
21917
|
+
//#region src/capabilities/osd-manager.cap.ts
|
|
21918
|
+
/**
|
|
21919
|
+
* `osd-manager` — the ORCHESTRATOR over the device-scope `osd` cap.
|
|
21920
|
+
*
|
|
21921
|
+
* The `osd` cap is the firmware contract: it probes a camera's overlay
|
|
21922
|
+
* SLOTS and writes literal text into one. It has no idea WHERE that text
|
|
21923
|
+
* comes from, and it must not — a driver that grew a "show the temperature
|
|
21924
|
+
* here" feature would grow it once per vendor.
|
|
21925
|
+
*
|
|
21926
|
+
* This cap owns the other half: a per-(camera, slot) BINDING that says
|
|
21927
|
+
* which value feeds the slot, how it is formatted, and under which
|
|
21928
|
+
* conditions it is shown at all. One addon renders every binding on every
|
|
21929
|
+
* camera, so a new source costs zero driver code.
|
|
21930
|
+
*
|
|
21931
|
+
* Three deliberate choices, each with a rejected alternative:
|
|
21932
|
+
*
|
|
21933
|
+
* 1. A source is `(capName, valuePath)` over the kernel's device
|
|
21934
|
+
* runtime-state mirror — NOT a closed enum of source kinds. Every
|
|
21935
|
+
* cap-keyed slice a device publishes is bindable the day the cap
|
|
21936
|
+
* ships. The rejected alternative (one enum member per source, with
|
|
21937
|
+
* a resolver branch each) is what makes "add the humidity too" a
|
|
21938
|
+
* code change.
|
|
21939
|
+
* 2. The display gate reuses `NcConditionsSchema` verbatim — the
|
|
21940
|
+
* notification centre's condition vocabulary — rather than a parallel
|
|
21941
|
+
* model. An operator who has learned one condition editor has learned
|
|
21942
|
+
* both.
|
|
21943
|
+
* 3. Because the renderer's facts are device STATE and not a detection
|
|
21944
|
+
* record, only a SUBSET of that vocabulary can be answered here.
|
|
21945
|
+
* `setSlotBinding` REJECTS the rest at write time (see
|
|
21946
|
+
* `getConditionSupport`). It does not accept-then-fail-closed: a
|
|
21947
|
+
* condition that can never be true renders a permanently blank
|
|
21948
|
+
* overlay, and a blank overlay looks exactly like a broken camera.
|
|
21949
|
+
*/
|
|
21950
|
+
/** Where a slot's value comes from. */
|
|
21951
|
+
var OsdSourceSchema = z.discriminatedUnion("kind", [
|
|
21952
|
+
z.object({
|
|
21953
|
+
kind: z.literal("static"),
|
|
21954
|
+
text: z.string().max(64)
|
|
21955
|
+
}),
|
|
21956
|
+
z.object({
|
|
21957
|
+
kind: z.literal("clock"),
|
|
21958
|
+
/** Token pattern: `YYYY MM DD HH mm ss`. Everything else is literal. */
|
|
21959
|
+
pattern: z.string().min(1).max(32).default("HH:mm"),
|
|
21960
|
+
/** IANA zone. Omitted = the server's zone. */
|
|
21961
|
+
timezone: z.string().min(1).max(64).optional()
|
|
21962
|
+
}),
|
|
21963
|
+
z.object({
|
|
21964
|
+
kind: z.literal("device-state"),
|
|
21965
|
+
deviceId: z.number().int().optional(),
|
|
21966
|
+
capName: z.string().min(1).max(64),
|
|
21967
|
+
/** Dot path inside the slice, e.g. `detected`, `value`, `mode`. */
|
|
21968
|
+
valuePath: z.string().min(1).max(64)
|
|
21969
|
+
})
|
|
21970
|
+
]);
|
|
21971
|
+
var OsdSlotBindingSchema = z.object({
|
|
21972
|
+
/** Off = the manager stops driving this slot. It does NOT clear it. */
|
|
21973
|
+
enabled: z.boolean().default(true),
|
|
21974
|
+
source: OsdSourceSchema,
|
|
21975
|
+
/** `${value}` and `${unit}` are substituted; every occurrence. */
|
|
21976
|
+
template: z.string().max(96).default("${value}"),
|
|
21977
|
+
/** Truncate with an ellipsis past this length. Absent = no limit. */
|
|
21978
|
+
maxCharacters: z.number().int().min(4).max(64).optional(),
|
|
21979
|
+
/**
|
|
21980
|
+
* Decimal places for a numeric value. `0` yields an integer — the
|
|
21981
|
+
* documented workaround for firmwares that reject `.` in overlay text.
|
|
21982
|
+
*/
|
|
21983
|
+
maxDecimals: z.number().int().min(0).max(4).default(1),
|
|
21984
|
+
/** Appended via `${unit}`. The state mirror does not carry units. */
|
|
21985
|
+
unitLabel: z.string().max(8).optional(),
|
|
21986
|
+
/** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
|
|
21987
|
+
valueMap: z.record(z.string(), z.string()).optional(),
|
|
21988
|
+
/** Time windows in which the slot is shown. Absent = always. */
|
|
21989
|
+
schedule: NcScheduleSchema.optional(),
|
|
21990
|
+
/**
|
|
21991
|
+
* Display gate, in the notification centre's condition vocabulary.
|
|
21992
|
+
* Only the keys reported by `getConditionSupport` are accepted.
|
|
21993
|
+
*/
|
|
21994
|
+
conditions: NcConditionsSchema.optional(),
|
|
21995
|
+
/** Rendered when the gate is closed or the value unreadable. Empty = hide. */
|
|
21996
|
+
fallbackText: z.string().max(64).default("")
|
|
21997
|
+
});
|
|
21998
|
+
/** One camera slot, as the operator sees it: firmware truth + our binding. */
|
|
21999
|
+
var OsdSlotViewSchema = z.object({
|
|
22000
|
+
slotId: z.string(),
|
|
22001
|
+
kind: OsdOverlayKindEnum,
|
|
22002
|
+
/** Firmware refuses text edits (a timestamp, the channel name). */
|
|
22003
|
+
readOnly: z.boolean(),
|
|
22004
|
+
cameraEnabled: z.boolean(),
|
|
22005
|
+
cameraText: z.string().optional(),
|
|
22006
|
+
binding: OsdSlotBindingSchema.nullable()
|
|
22007
|
+
});
|
|
22008
|
+
/**
|
|
22009
|
+
* What happened to one slot on one render pass. `unchanged` exists so the
|
|
22010
|
+
* operator can tell "we are driving this and the value is steady" from
|
|
22011
|
+
* "we never got there" — and so the loop can prove it is not rewriting
|
|
22012
|
+
* identical text to the camera every tick.
|
|
22013
|
+
*/
|
|
22014
|
+
var OsdRenderOutcomeEnum = z.enum([
|
|
22015
|
+
"written",
|
|
22016
|
+
"unchanged",
|
|
22017
|
+
"gated",
|
|
22018
|
+
"unreadable",
|
|
22019
|
+
"disabled",
|
|
22020
|
+
"unbound",
|
|
22021
|
+
"failed"
|
|
22022
|
+
]);
|
|
22023
|
+
var OsdRenderResultSchema = z.object({
|
|
22024
|
+
slotId: z.string(),
|
|
22025
|
+
outcome: OsdRenderOutcomeEnum,
|
|
22026
|
+
/** The text the slot should carry. Empty = the slot is switched off. */
|
|
22027
|
+
text: z.string(),
|
|
22028
|
+
/** Why, whenever the outcome is not a plain write. Never silent. */
|
|
22029
|
+
reason: z.string().optional()
|
|
22030
|
+
});
|
|
22031
|
+
var OsdSourceValueTypeEnum = z.enum([
|
|
22032
|
+
"number",
|
|
22033
|
+
"boolean",
|
|
22034
|
+
"string",
|
|
22035
|
+
"enum"
|
|
22036
|
+
]);
|
|
22037
|
+
/**
|
|
22038
|
+
* One bindable value, derived from a cap's `runtimeState` schema — never
|
|
22039
|
+
* hand-listed. The editor renders from this, so a cap that ships a new
|
|
22040
|
+
* state field becomes bindable with no UI change.
|
|
22041
|
+
*/
|
|
22042
|
+
var OsdSourceOptionSchema = z.object({
|
|
22043
|
+
deviceId: z.number().int(),
|
|
22044
|
+
deviceName: z.string(),
|
|
22045
|
+
capName: z.string(),
|
|
22046
|
+
valuePath: z.string(),
|
|
22047
|
+
label: z.string(),
|
|
22048
|
+
valueType: OsdSourceValueTypeEnum,
|
|
22049
|
+
/** Present for `enum`; the editor offers these as `valueMap` keys. */
|
|
22050
|
+
enumValues: z.array(z.string()).readonly().optional()
|
|
22051
|
+
});
|
|
22052
|
+
var osdManagerCapability = {
|
|
22053
|
+
name: "osd-manager",
|
|
22054
|
+
scope: "system",
|
|
22055
|
+
mode: "singleton",
|
|
22056
|
+
methods: {
|
|
22057
|
+
/**
|
|
22058
|
+
* The camera's slots, each with its binding. `supported: false` when
|
|
22059
|
+
* the camera publishes no `osd` cap — the page then says so instead
|
|
22060
|
+
* of rendering an empty list that reads as "no overlays configured".
|
|
22061
|
+
*/
|
|
22062
|
+
getDeviceOsd: method(z.object({ deviceId: z.number().int() }), z.object({
|
|
22063
|
+
supported: z.boolean(),
|
|
22064
|
+
slots: z.array(OsdSlotViewSchema)
|
|
22065
|
+
}), { auth: "admin" }),
|
|
22066
|
+
/**
|
|
22067
|
+
* Every value bindable on this camera: its own state leaves first,
|
|
22068
|
+
* then every other device's. Derived from the cap definitions, so it
|
|
22069
|
+
* cannot drift from what the resolver can actually read.
|
|
22070
|
+
*/
|
|
22071
|
+
getSourceCatalog: method(z.object({ deviceId: z.number().int() }), z.object({ sources: z.array(OsdSourceOptionSchema) }), { auth: "admin" }),
|
|
22072
|
+
/**
|
|
22073
|
+
* The condition ids this gate can answer, alongside the FULL notification
|
|
22074
|
+
* condition catalog. Both, in one call, on purpose: an editor that showed
|
|
22075
|
+
* the catalog without the supported set would offer conditions that
|
|
22076
|
+
* `setSlotBinding` then rejects.
|
|
22077
|
+
*/
|
|
22078
|
+
getConditionSupport: method(z.object({}), z.object({
|
|
22079
|
+
supported: z.array(z.string()),
|
|
22080
|
+
catalog: z.array(NcConditionDescriptorSchema)
|
|
22081
|
+
}), { auth: "admin" }),
|
|
22082
|
+
/**
|
|
22083
|
+
* Persist a binding and render it immediately, returning the slot as
|
|
22084
|
+
* it now stands. Throws when the binding names an unsupported
|
|
22085
|
+
* condition, an unknown cap, or a value path that cap does not have.
|
|
22086
|
+
*/
|
|
22087
|
+
setSlotBinding: method(z.object({
|
|
22088
|
+
deviceId: z.number().int(),
|
|
22089
|
+
slotId: z.string().min(1),
|
|
22090
|
+
binding: OsdSlotBindingSchema
|
|
22091
|
+
}), z.object({
|
|
22092
|
+
slot: OsdSlotViewSchema,
|
|
22093
|
+
render: OsdRenderResultSchema
|
|
22094
|
+
}), {
|
|
22095
|
+
kind: "mutation",
|
|
22096
|
+
auth: "admin"
|
|
22097
|
+
}),
|
|
22098
|
+
/** Forget the binding. The slot keeps whatever text it last carried. */
|
|
22099
|
+
clearSlotBinding: method(z.object({
|
|
22100
|
+
deviceId: z.number().int(),
|
|
22101
|
+
slotId: z.string().min(1)
|
|
22102
|
+
}), z.object({ success: z.literal(true) }), {
|
|
22103
|
+
kind: "mutation",
|
|
22104
|
+
auth: "admin"
|
|
22105
|
+
}),
|
|
22106
|
+
/**
|
|
22107
|
+
* Render without writing. `binding` overrides the stored one so an
|
|
22108
|
+
* editor can preview an unsaved change. Mutation kind only to carry
|
|
22109
|
+
* the binding object safely; no side effects.
|
|
22110
|
+
*/
|
|
22111
|
+
previewSlot: method(z.object({
|
|
22112
|
+
deviceId: z.number().int(),
|
|
22113
|
+
slotId: z.string().min(1),
|
|
22114
|
+
binding: OsdSlotBindingSchema.optional()
|
|
22115
|
+
}), OsdRenderResultSchema, {
|
|
22116
|
+
kind: "mutation",
|
|
22117
|
+
auth: "admin"
|
|
22118
|
+
}),
|
|
22119
|
+
/** Force a render pass over one camera now, instead of at the next tick. */
|
|
22120
|
+
renderDevice: method(z.object({ deviceId: z.number().int() }), z.object({ results: z.array(OsdRenderResultSchema) }), {
|
|
22121
|
+
kind: "mutation",
|
|
22122
|
+
auth: "admin"
|
|
22123
|
+
})
|
|
22124
|
+
}
|
|
22125
|
+
};
|
|
22126
|
+
//#endregion
|
|
21843
22127
|
//#region src/capabilities/pet-feeder.cap.ts
|
|
21844
22128
|
/**
|
|
21845
22129
|
* PetKit pet-feeder cap. Models the control + telemetry surface of a
|
|
@@ -22487,12 +22771,30 @@ var pressureSensorCapability = {
|
|
|
22487
22771
|
//#endregion
|
|
22488
22772
|
//#region src/capabilities/privacy-mask.cap.ts
|
|
22489
22773
|
/**
|
|
22490
|
-
*
|
|
22491
|
-
*
|
|
22492
|
-
*
|
|
22493
|
-
*
|
|
22494
|
-
*
|
|
22495
|
-
*
|
|
22774
|
+
* PRIVACY — what the camera deliberately does not capture. Two planes:
|
|
22775
|
+
*
|
|
22776
|
+
* - **video**: up to `maxRegions` SHAPES the camera blanks out (NOT a cell
|
|
22777
|
+
* grid). Reolink `<shelterList>` zones are rectangles; Hikvision ISAPI
|
|
22778
|
+
* `<RegionCoordinatesList>` zones are free polygons (this camera: exactly
|
|
22779
|
+
* 4 vertices, not necessarily axis-aligned). The cap composes the shared
|
|
22780
|
+
* rect|polygon subset of the MaskShape vocabulary. All coords are
|
|
22781
|
+
* normalized 0..1 (top-left origin).
|
|
22782
|
+
* - **audio**: the camera's microphone. `setAudioEnabled(false)` stops the
|
|
22783
|
+
* camera encoding an audio track at all, so EVERY consumer — live view,
|
|
22784
|
+
* recording, the audio analyzer, an export — sees silent video. There is
|
|
22785
|
+
* no server-side copy of this fact; the camera is the store and every read
|
|
22786
|
+
* is a read-through, which is why a switch over it cannot drift
|
|
22787
|
+
* ([D62](../../../../docs/decisions/adr-0062.md)).
|
|
22788
|
+
*
|
|
22789
|
+
* Both belong here for one reason: they are the two things an operator turns
|
|
22790
|
+
* off when the answer to "what is this camera allowed to record" changes, and
|
|
22791
|
+
* both are applied ON the device, before anything leaves it.
|
|
22792
|
+
*
|
|
22793
|
+
* **The audio flag has exactly one writer.** `stream-params` used to carry a
|
|
22794
|
+
* per-profile `audio` in its patch schema — reachable from no UI and honoured
|
|
22795
|
+
* by one provider — and it was removed when this landed. A second writer onto
|
|
22796
|
+
* one device register is the shape of every knob this repo has shipped that
|
|
22797
|
+
* disagreed with the one the reader read.
|
|
22496
22798
|
*/
|
|
22497
22799
|
/** A privacy-mask region's geometry — rectangle or free polygon. */
|
|
22498
22800
|
var PrivacyMaskShapeSchema = z.discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
|
|
@@ -22504,21 +22806,45 @@ var PrivacyMaskRegionSchema = z.object({
|
|
|
22504
22806
|
enabled: z.boolean(),
|
|
22505
22807
|
shape: PrivacyMaskShapeSchema
|
|
22506
22808
|
});
|
|
22507
|
-
/** Current on-camera privacy
|
|
22809
|
+
/** Current on-camera privacy state — mask master enable + zones + microphone. */
|
|
22508
22810
|
var PrivacyMaskStatusSchema = z.object({
|
|
22509
22811
|
enabled: z.boolean(),
|
|
22510
22812
|
/** Active zones (normalized 0..1). Length ≤ maxRegions. */
|
|
22511
22813
|
regions: z.array(PrivacyMaskRegionSchema),
|
|
22814
|
+
/**
|
|
22815
|
+
* Is the camera capturing sound right now? Read from the camera, never from
|
|
22816
|
+
* a server-side mirror.
|
|
22817
|
+
*
|
|
22818
|
+
* `null` means "no answer" — either this camera exposes no controllable
|
|
22819
|
+
* microphone (`getOptions().supportsAudioMute === false`) or the read
|
|
22820
|
+
* failed. A consumer must render `null` as UNKNOWN and never as `false`:
|
|
22821
|
+
* "the microphone is off" and "we could not ask" look identical to an
|
|
22822
|
+
* operator only until one of them is wrong.
|
|
22823
|
+
*
|
|
22824
|
+
* On a camera whose profiles carry the flag independently (Reolink writes
|
|
22825
|
+
* it per stream), `true` means AT LEAST ONE profile still carries audio —
|
|
22826
|
+
* privacy is only satisfied when every one of them is silent.
|
|
22827
|
+
*/
|
|
22828
|
+
audioEnabled: z.boolean().nullable(),
|
|
22512
22829
|
lastFetchedAt: z.number()
|
|
22513
22830
|
});
|
|
22514
|
-
/** Per-camera availability. */
|
|
22831
|
+
/** Per-camera availability. Probed, never assumed from the model name. */
|
|
22515
22832
|
var PrivacyMaskOptionsSchema = z.object({
|
|
22516
22833
|
/** Maximum number of supported zones. */
|
|
22517
22834
|
maxRegions: z.number(),
|
|
22518
22835
|
/** Shape kinds this camera accepts — Reolink: ['rect']; Hikvision: ['rect','polygon']. */
|
|
22519
22836
|
supportedShapes: z.array(MaskShapeKindSchema),
|
|
22520
22837
|
/** Polygon vertex bounds when 'polygon' is supported (Hikvision: {min:4,max:4}). */
|
|
22521
|
-
polygonVertices: MaskPolygonVerticesSchema.optional()
|
|
22838
|
+
polygonVertices: MaskPolygonVerticesSchema.optional(),
|
|
22839
|
+
/**
|
|
22840
|
+
* Does this camera expose a microphone switch we can actually write?
|
|
22841
|
+
*
|
|
22842
|
+
* Camera-probed: `true` only when the firmware answered with an audio flag
|
|
22843
|
+
* we know how to patch. A camera that never answered is `false` — a control
|
|
22844
|
+
* the operator can press that changes nothing is worse than no control, and
|
|
22845
|
+
* the switch group renders "not available" instead.
|
|
22846
|
+
*/
|
|
22847
|
+
supportsAudioMute: z.boolean()
|
|
22522
22848
|
});
|
|
22523
22849
|
/** Partial change — every field optional. */
|
|
22524
22850
|
var PrivacyMaskPatchSchema = z.object({
|
|
@@ -22545,6 +22871,27 @@ var privacyMaskCapability = {
|
|
|
22545
22871
|
}), z.void(), {
|
|
22546
22872
|
kind: "mutation",
|
|
22547
22873
|
auth: "admin"
|
|
22874
|
+
}),
|
|
22875
|
+
/**
|
|
22876
|
+
* Turn the camera's microphone on or off, at the camera.
|
|
22877
|
+
*
|
|
22878
|
+
* Deliberately its OWN mutation rather than a field on
|
|
22879
|
+
* {@link PrivacyMaskPatchSchema}: `patch.enabled` already means "the video
|
|
22880
|
+
* mask master switch", and overloading it would make one boolean mean two
|
|
22881
|
+
* unrelated things on the same call. It is also the only method here whose
|
|
22882
|
+
* write leaves the device in a state a later `getStatus` reads back
|
|
22883
|
+
* verbatim, which is what makes it safe as a switch authority.
|
|
22884
|
+
*
|
|
22885
|
+
* A camera whose `getOptions().supportsAudioMute` is false must REJECT
|
|
22886
|
+
* this rather than silently accept it — a write nothing applies is exactly
|
|
22887
|
+
* what the switch group exists to remove.
|
|
22888
|
+
*/
|
|
22889
|
+
setAudioEnabled: method(z.object({
|
|
22890
|
+
deviceId: z.number(),
|
|
22891
|
+
enabled: z.boolean()
|
|
22892
|
+
}), z.void(), {
|
|
22893
|
+
kind: "mutation",
|
|
22894
|
+
auth: "admin"
|
|
22548
22895
|
})
|
|
22549
22896
|
},
|
|
22550
22897
|
status: {
|
|
@@ -22553,6 +22900,26 @@ var privacyMaskCapability = {
|
|
|
22553
22900
|
},
|
|
22554
22901
|
runtimeState: PrivacyMaskStatusSchema
|
|
22555
22902
|
};
|
|
22903
|
+
/**
|
|
22904
|
+
* Collapse a camera's PER-PROFILE audio flags into the one answer
|
|
22905
|
+
* {@link PrivacyMaskStatusSchema.shape.audioEnabled} promises.
|
|
22906
|
+
*
|
|
22907
|
+
* Both firmwares this cap talks to store the flag per stream profile, and
|
|
22908
|
+
* both let those profiles disagree. The rule is `some`, not `every`: privacy
|
|
22909
|
+
* is only satisfied when NOTHING is carrying sound, so a camera whose sub
|
|
22910
|
+
* stream is still audible must read as `true` and be switchable off — not as
|
|
22911
|
+
* `false` because the main stream happens to be muted already.
|
|
22912
|
+
*
|
|
22913
|
+
* An empty list is `null` ("this camera reported no audio flag at all"),
|
|
22914
|
+
* never `false`.
|
|
22915
|
+
*
|
|
22916
|
+
* Lives here rather than in each provider so the rule the schema documents
|
|
22917
|
+
* and the rule the providers apply cannot drift apart.
|
|
22918
|
+
*/
|
|
22919
|
+
function summarisePrivacyAudio(profiles) {
|
|
22920
|
+
if (profiles.length === 0) return null;
|
|
22921
|
+
return profiles.some((p) => p.audioEnabled);
|
|
22922
|
+
}
|
|
22556
22923
|
//#endregion
|
|
22557
22924
|
//#region src/capabilities/ptz.cap.ts
|
|
22558
22925
|
var PtzPresetSchema = z.object({
|
|
@@ -22937,6 +23304,21 @@ var LocateSegmentResultSchema = z.discriminatedUnion("kind", [z.object({
|
|
|
22937
23304
|
})]);
|
|
22938
23305
|
/** Raw bytes of one finalized footage segment (read off disk on the recording node). */
|
|
22939
23306
|
var ReadSegmentBytesResultSchema = z.object({ data: z.instanceof(Uint8Array) });
|
|
23307
|
+
/**
|
|
23308
|
+
* One GOP of a finalized segment, cut by byte range through the segment's own
|
|
23309
|
+
* `mfra` (D31 on the D42 feeder path). `data` is the `ftyp`+`moov` head plus
|
|
23310
|
+
* the single `moof`+`mdat` covering the requested instant — standalone-
|
|
23311
|
+
* demuxable, never the whole file. When the segment's index cannot be parsed
|
|
23312
|
+
* the provider degrades INSIDE the mechanism to the whole segment (still one
|
|
23313
|
+
* `data`, `gopStartMs` = the segment start) — a worse read, not another path.
|
|
23314
|
+
*/
|
|
23315
|
+
var ReadGopBytesResultSchema = z.object({
|
|
23316
|
+
data: z.instanceof(Uint8Array),
|
|
23317
|
+
/** Absolute epoch ms of the returned fragment's first sample. */
|
|
23318
|
+
gopStartMs: z.number(),
|
|
23319
|
+
/** Media ms the returned fragment covers. */
|
|
23320
|
+
gopDurMs: z.number()
|
|
23321
|
+
});
|
|
22940
23322
|
var recordingCapability = {
|
|
22941
23323
|
name: "recording",
|
|
22942
23324
|
scope: "system",
|
|
@@ -23004,6 +23386,18 @@ var recordingCapability = {
|
|
|
23004
23386
|
kind: "query",
|
|
23005
23387
|
auth: "admin"
|
|
23006
23388
|
}),
|
|
23389
|
+
/** Read the single GOP of segment `startMs` covering `epochMs`, by mfra
|
|
23390
|
+
* byte range — the scrub-granular read (D31 letter on the feeder path).
|
|
23391
|
+
* See {@link ReadGopBytesResultSchema} for the degradation contract. */
|
|
23392
|
+
readGopBytes: method(z.object({
|
|
23393
|
+
deviceId: z.number(),
|
|
23394
|
+
profile: z.string(),
|
|
23395
|
+
startMs: z.number(),
|
|
23396
|
+
epochMs: z.number()
|
|
23397
|
+
}), ReadGopBytesResultSchema, {
|
|
23398
|
+
kind: "query",
|
|
23399
|
+
auth: "admin"
|
|
23400
|
+
}),
|
|
23007
23401
|
setDeviceConfig: method(z.object({
|
|
23008
23402
|
deviceId: z.number(),
|
|
23009
23403
|
config: RecordingConfigSchema
|
|
@@ -23665,6 +24059,16 @@ var StreamProfileConfigSchema = z.object({
|
|
|
23665
24059
|
"baseline"
|
|
23666
24060
|
]).optional(),
|
|
23667
24061
|
gop: z.number().optional(),
|
|
24062
|
+
/**
|
|
24063
|
+
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
24064
|
+
*
|
|
24065
|
+
* There is no matching field on {@link StreamProfilePatchSchema}: the
|
|
24066
|
+
* camera's microphone is owned by `privacy-mask` (`setAudioEnabled`), which
|
|
24067
|
+
* writes every profile at once so "audio off" means silent everywhere. A
|
|
24068
|
+
* per-profile writer beside it would let a camera be half-muted and would be
|
|
24069
|
+
* a second knob onto one device register — the failure D62 exists to
|
|
24070
|
+
* prevent. Absent when the firmware does not report the flag.
|
|
24071
|
+
*/
|
|
23668
24072
|
audio: z.boolean().optional()
|
|
23669
24073
|
});
|
|
23670
24074
|
var StreamParamsStatusSchema = z.object({
|
|
@@ -23705,7 +24109,13 @@ var StreamParamsOptionsSchema = z.object({
|
|
|
23705
24109
|
ext: StreamProfileOptionsSchema.optional()
|
|
23706
24110
|
});
|
|
23707
24111
|
/** A partial change to one profile — every field optional; a provider
|
|
23708
|
-
* ignores fields it doesn't support.
|
|
24112
|
+
* ignores fields it doesn't support.
|
|
24113
|
+
*
|
|
24114
|
+
* There is deliberately NO `audio` here. It existed until 2026-08-07,
|
|
24115
|
+
* reachable from no form and honoured by exactly one provider, while the
|
|
24116
|
+
* camera's microphone is a whole-device fact. It now has one writer,
|
|
24117
|
+
* `privacyMask.setAudioEnabled`, which writes every profile — see
|
|
24118
|
+
* `privacy-mask.cap.ts`. */
|
|
23709
24119
|
var StreamProfilePatchSchema = z.object({
|
|
23710
24120
|
width: z.number().optional(),
|
|
23711
24121
|
height: z.number().optional(),
|
|
@@ -23718,8 +24128,7 @@ var StreamProfilePatchSchema = z.object({
|
|
|
23718
24128
|
"main",
|
|
23719
24129
|
"baseline"
|
|
23720
24130
|
]).optional(),
|
|
23721
|
-
gop: z.number().optional()
|
|
23722
|
-
audio: z.boolean().optional()
|
|
24131
|
+
gop: z.number().optional()
|
|
23723
24132
|
});
|
|
23724
24133
|
var streamParamsCapability = {
|
|
23725
24134
|
name: "stream-params",
|
|
@@ -26638,10 +27047,7 @@ var BATTERY_DEVICE_PROFILE = {
|
|
|
26638
27047
|
audioMode: "disabled",
|
|
26639
27048
|
detectionMode: "on-motion"
|
|
26640
27049
|
},
|
|
26641
|
-
settings: {
|
|
26642
|
-
"snapshot.minRefreshIntervalSec": 3600,
|
|
26643
|
-
"streamBroker.preBufferEnabled": false
|
|
26644
|
-
}
|
|
27050
|
+
settings: {}
|
|
26645
27051
|
};
|
|
26646
27052
|
/**
|
|
26647
27053
|
* Profile registry — order matters when multiple profiles match the
|
|
@@ -27493,7 +27899,7 @@ var SystemMirror = class {
|
|
|
27493
27899
|
}
|
|
27494
27900
|
async refreshDeviceMetadata(deviceId, kind) {
|
|
27495
27901
|
try {
|
|
27496
|
-
const info =
|
|
27902
|
+
const info = await this.api.deviceManager.getDevice.query({ deviceId });
|
|
27497
27903
|
if (!info) return;
|
|
27498
27904
|
const wasNew = !this.devices.has(deviceId);
|
|
27499
27905
|
this.devices.set(deviceId, info);
|
|
@@ -27805,6 +28211,7 @@ var CAPABILITY_NAMES = {
|
|
|
27805
28211
|
numericSensor: "numeric-sensor",
|
|
27806
28212
|
oauthIntegration: "oauth-integration",
|
|
27807
28213
|
osd: "osd",
|
|
28214
|
+
osdManager: "osd-manager",
|
|
27808
28215
|
petFeeder: "pet-feeder",
|
|
27809
28216
|
pipelineAnalytics: "pipeline-analytics",
|
|
27810
28217
|
pipelineExecutor: "pipeline-executor",
|
|
@@ -28236,6 +28643,10 @@ var CAPABILITY_ROUTER_KEYS = [
|
|
|
28236
28643
|
key: "osd",
|
|
28237
28644
|
name: "osd"
|
|
28238
28645
|
},
|
|
28646
|
+
{
|
|
28647
|
+
key: "osdManager",
|
|
28648
|
+
name: "osd-manager"
|
|
28649
|
+
},
|
|
28239
28650
|
{
|
|
28240
28651
|
key: "petFeeder",
|
|
28241
28652
|
name: "pet-feeder"
|
|
@@ -28549,6 +28960,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
|
|
|
28549
28960
|
numericSensorCapability,
|
|
28550
28961
|
oauthIntegrationCapability,
|
|
28551
28962
|
osdCapability,
|
|
28963
|
+
osdManagerCapability,
|
|
28552
28964
|
petFeederCapability,
|
|
28553
28965
|
pipelineAnalyticsCapability,
|
|
28554
28966
|
pipelineExecutorCapability,
|
|
@@ -31467,6 +31879,48 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
31467
31879
|
addonId: null,
|
|
31468
31880
|
access: "create"
|
|
31469
31881
|
},
|
|
31882
|
+
"osdManager.clearSlotBinding": {
|
|
31883
|
+
capName: "osd-manager",
|
|
31884
|
+
capScope: "system",
|
|
31885
|
+
addonId: null,
|
|
31886
|
+
access: "delete"
|
|
31887
|
+
},
|
|
31888
|
+
"osdManager.getConditionSupport": {
|
|
31889
|
+
capName: "osd-manager",
|
|
31890
|
+
capScope: "system",
|
|
31891
|
+
addonId: null,
|
|
31892
|
+
access: "view"
|
|
31893
|
+
},
|
|
31894
|
+
"osdManager.getDeviceOsd": {
|
|
31895
|
+
capName: "osd-manager",
|
|
31896
|
+
capScope: "system",
|
|
31897
|
+
addonId: null,
|
|
31898
|
+
access: "view"
|
|
31899
|
+
},
|
|
31900
|
+
"osdManager.getSourceCatalog": {
|
|
31901
|
+
capName: "osd-manager",
|
|
31902
|
+
capScope: "system",
|
|
31903
|
+
addonId: null,
|
|
31904
|
+
access: "view"
|
|
31905
|
+
},
|
|
31906
|
+
"osdManager.previewSlot": {
|
|
31907
|
+
capName: "osd-manager",
|
|
31908
|
+
capScope: "system",
|
|
31909
|
+
addonId: null,
|
|
31910
|
+
access: "create"
|
|
31911
|
+
},
|
|
31912
|
+
"osdManager.renderDevice": {
|
|
31913
|
+
capName: "osd-manager",
|
|
31914
|
+
capScope: "system",
|
|
31915
|
+
addonId: null,
|
|
31916
|
+
access: "create"
|
|
31917
|
+
},
|
|
31918
|
+
"osdManager.setSlotBinding": {
|
|
31919
|
+
capName: "osd-manager",
|
|
31920
|
+
capScope: "system",
|
|
31921
|
+
addonId: null,
|
|
31922
|
+
access: "create"
|
|
31923
|
+
},
|
|
31470
31924
|
"petFeeder.callPet": {
|
|
31471
31925
|
capName: "pet-feeder",
|
|
31472
31926
|
capScope: "device",
|
|
@@ -31629,6 +32083,18 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
31629
32083
|
addonId: null,
|
|
31630
32084
|
access: "view"
|
|
31631
32085
|
},
|
|
32086
|
+
"pipelineAnalytics.getTrainingExportSummary": {
|
|
32087
|
+
capName: "pipeline-analytics",
|
|
32088
|
+
capScope: "device",
|
|
32089
|
+
addonId: null,
|
|
32090
|
+
access: "view"
|
|
32091
|
+
},
|
|
32092
|
+
"pipelineAnalytics.getTrainingExportUrl": {
|
|
32093
|
+
capName: "pipeline-analytics",
|
|
32094
|
+
capScope: "device",
|
|
32095
|
+
addonId: null,
|
|
32096
|
+
access: "view"
|
|
32097
|
+
},
|
|
31632
32098
|
"pipelineAnalytics.listEventKinds": {
|
|
31633
32099
|
capName: "pipeline-analytics",
|
|
31634
32100
|
capScope: "device",
|
|
@@ -32385,6 +32851,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
32385
32851
|
addonId: null,
|
|
32386
32852
|
access: "view"
|
|
32387
32853
|
},
|
|
32854
|
+
"privacyMask.setAudioEnabled": {
|
|
32855
|
+
capName: "privacy-mask",
|
|
32856
|
+
capScope: "device",
|
|
32857
|
+
addonId: null,
|
|
32858
|
+
access: "create"
|
|
32859
|
+
},
|
|
32388
32860
|
"privacyMask.setMask": {
|
|
32389
32861
|
capName: "privacy-mask",
|
|
32390
32862
|
capScope: "device",
|
|
@@ -32553,6 +33025,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
32553
33025
|
addonId: null,
|
|
32554
33026
|
access: "create"
|
|
32555
33027
|
},
|
|
33028
|
+
"recording.readGopBytes": {
|
|
33029
|
+
capName: "recording",
|
|
33030
|
+
capScope: "system",
|
|
33031
|
+
addonId: null,
|
|
33032
|
+
access: "view"
|
|
33033
|
+
},
|
|
32556
33034
|
"recording.readSegmentBytes": {
|
|
32557
33035
|
capName: "recording",
|
|
32558
33036
|
capScope: "system",
|
|
@@ -33093,6 +33571,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
33093
33571
|
addonId: null,
|
|
33094
33572
|
access: "view"
|
|
33095
33573
|
},
|
|
33574
|
+
"streamBroker.getDeviceAudioMute": {
|
|
33575
|
+
capName: "stream-broker",
|
|
33576
|
+
capScope: "system",
|
|
33577
|
+
addonId: null,
|
|
33578
|
+
access: "view"
|
|
33579
|
+
},
|
|
33096
33580
|
"streamBroker.getPreBufferInfo": {
|
|
33097
33581
|
capName: "stream-broker",
|
|
33098
33582
|
capScope: "system",
|
|
@@ -33213,6 +33697,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
33213
33697
|
addonId: null,
|
|
33214
33698
|
access: "create"
|
|
33215
33699
|
},
|
|
33700
|
+
"streamBroker.setDeviceAudioMute": {
|
|
33701
|
+
capName: "stream-broker",
|
|
33702
|
+
capScope: "system",
|
|
33703
|
+
addonId: null,
|
|
33704
|
+
access: "create"
|
|
33705
|
+
},
|
|
33216
33706
|
"streamBroker.setPreBufferDuration": {
|
|
33217
33707
|
capName: "stream-broker",
|
|
33218
33708
|
capScope: "system",
|
|
@@ -33928,6 +34418,7 @@ var KNOWN_CAP_NAMES = [
|
|
|
33928
34418
|
"notifier",
|
|
33929
34419
|
"oauth-integration",
|
|
33930
34420
|
"osd",
|
|
34421
|
+
"osd-manager",
|
|
33931
34422
|
"pet-feeder",
|
|
33932
34423
|
"pipeline-analytics",
|
|
33933
34424
|
"pipeline-executor",
|
|
@@ -34075,6 +34566,7 @@ var SYSTEM_CAP_NAMES = [
|
|
|
34075
34566
|
"notification-output",
|
|
34076
34567
|
"notification-rules",
|
|
34077
34568
|
"oauth-integration",
|
|
34569
|
+
"osd-manager",
|
|
34078
34570
|
"pipeline-executor",
|
|
34079
34571
|
"pipeline-orchestrator",
|
|
34080
34572
|
"pipeline-runner",
|
|
@@ -34533,6 +35025,7 @@ function createSystemProxy(api) {
|
|
|
34533
35025
|
deleteTarget: (input) => dispatch("notificationOutput", "deleteTarget", "mutation", input),
|
|
34534
35026
|
setTargetEnabled: (input) => dispatch("notificationOutput", "setTargetEnabled", "mutation", input)
|
|
34535
35027
|
},
|
|
35028
|
+
osdManager: { getConditionSupport: (input) => dispatch("osdManager", "getConditionSupport", "query", input) },
|
|
34536
35029
|
pipelineExecutor: {
|
|
34537
35030
|
getAvailableEngines: (input) => dispatch("pipelineExecutor", "getAvailableEngines", "query", input),
|
|
34538
35031
|
getSelectedEngine: (input) => dispatch("pipelineExecutor", "getSelectedEngine", "query", input),
|
|
@@ -35074,6 +35567,68 @@ function prepareNotification(caps, n) {
|
|
|
35074
35567
|
};
|
|
35075
35568
|
}
|
|
35076
35569
|
//#endregion
|
|
35570
|
+
//#region src/notification/schedule.ts
|
|
35571
|
+
var WEEKDAY_TO_DAY = {
|
|
35572
|
+
Sun: 0,
|
|
35573
|
+
Mon: 1,
|
|
35574
|
+
Tue: 2,
|
|
35575
|
+
Wed: 3,
|
|
35576
|
+
Thu: 4,
|
|
35577
|
+
Fri: 5,
|
|
35578
|
+
Sat: 6
|
|
35579
|
+
};
|
|
35580
|
+
/** Resolve (weekday, minute-of-day) of `atMs` in the schedule's timezone.
|
|
35581
|
+
* An invalid/unknown IANA name falls back to the host timezone. */
|
|
35582
|
+
function localDayMinute(atMs, timezone) {
|
|
35583
|
+
const d = new Date(atMs);
|
|
35584
|
+
if (timezone !== void 0) try {
|
|
35585
|
+
const parts = new Intl.DateTimeFormat("en-US", {
|
|
35586
|
+
timeZone: timezone,
|
|
35587
|
+
weekday: "short",
|
|
35588
|
+
hour: "numeric",
|
|
35589
|
+
minute: "numeric",
|
|
35590
|
+
hourCycle: "h23"
|
|
35591
|
+
}).formatToParts(d);
|
|
35592
|
+
let weekday;
|
|
35593
|
+
let hour;
|
|
35594
|
+
let minute;
|
|
35595
|
+
for (const p of parts) if (p.type === "weekday") weekday = p.value;
|
|
35596
|
+
else if (p.type === "hour") hour = Number(p.value);
|
|
35597
|
+
else if (p.type === "minute") minute = Number(p.value);
|
|
35598
|
+
const day = weekday !== void 0 ? WEEKDAY_TO_DAY[weekday] : void 0;
|
|
35599
|
+
if (day !== void 0 && hour !== void 0 && minute !== void 0) return {
|
|
35600
|
+
day,
|
|
35601
|
+
minute: hour * 60 + minute
|
|
35602
|
+
};
|
|
35603
|
+
} catch {}
|
|
35604
|
+
return {
|
|
35605
|
+
day: d.getDay(),
|
|
35606
|
+
minute: d.getHours() * 60 + d.getMinutes()
|
|
35607
|
+
};
|
|
35608
|
+
}
|
|
35609
|
+
/**
|
|
35610
|
+
* Is the schedule active at `atMs`? No schedule = always active. Windows
|
|
35611
|
+
* are OR'd; a window with `startMinute > endMinute` crosses midnight (it
|
|
35612
|
+
* starts on a listed day and spills into the next). `invert` flips the
|
|
35613
|
+
* result (active OUTSIDE the windows).
|
|
35614
|
+
*/
|
|
35615
|
+
function isScheduleActive(schedule, atMs) {
|
|
35616
|
+
if (schedule === void 0) return true;
|
|
35617
|
+
const { day, minute } = localDayMinute(atMs, schedule.timezone);
|
|
35618
|
+
const prevDay = (day + 6) % 7;
|
|
35619
|
+
let inside = false;
|
|
35620
|
+
for (const w of schedule.windows) if (w.startMinute <= w.endMinute) {
|
|
35621
|
+
if (w.days.includes(day) && minute >= w.startMinute && minute < w.endMinute) {
|
|
35622
|
+
inside = true;
|
|
35623
|
+
break;
|
|
35624
|
+
}
|
|
35625
|
+
} else if (w.days.includes(day) && minute >= w.startMinute || w.days.includes(prevDay) && minute < w.endMinute) {
|
|
35626
|
+
inside = true;
|
|
35627
|
+
break;
|
|
35628
|
+
}
|
|
35629
|
+
return schedule.invert === true ? !inside : inside;
|
|
35630
|
+
}
|
|
35631
|
+
//#endregion
|
|
35077
35632
|
//#region src/notification/timelapse-rule.ts
|
|
35078
35633
|
/**
|
|
35079
35634
|
* TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
|
|
@@ -35571,6 +36126,44 @@ function bestLocationMatch(externalName, existing, threshold = .8) {
|
|
|
35571
36126
|
return best;
|
|
35572
36127
|
}
|
|
35573
36128
|
//#endregion
|
|
36129
|
+
//#region src/utils/addon-id.ts
|
|
36130
|
+
/**
|
|
36131
|
+
* The addon id as the REGISTRY, the wire and the durable stores spell it.
|
|
36132
|
+
*
|
|
36133
|
+
* `AddonContext.id` does not agree with itself across the two context
|
|
36134
|
+
* factories:
|
|
36135
|
+
*
|
|
36136
|
+
* - a FORKED addon gets the bare manifest id
|
|
36137
|
+
* (`kernel/moleculer/addon-context-factory.ts` → `id: addonId`);
|
|
36138
|
+
* - an addon co-located in hub-main gets it PREFIXED
|
|
36139
|
+
* (`server/backend/src/core/addon/addon-registry.service.ts` →
|
|
36140
|
+
* ``id: `addon:${addonId}` ``).
|
|
36141
|
+
*
|
|
36142
|
+
* Everything an addon might compare `ctx.id` AGAINST carries the bare form:
|
|
36143
|
+
* `DeviceBindingEntry.providerAddonId`, the `device-manager` bindings store's
|
|
36144
|
+
* `wrapperAddonId`, `CapabilityRegistry` provider keys, manifest ids.
|
|
36145
|
+
*
|
|
36146
|
+
* So `entry.providerAddonId === this.ctx.id` is silently, permanently false
|
|
36147
|
+
* for a builtin — and only for a builtin, which is why it survives a green
|
|
36148
|
+
* suite whose fake supplies the bare id. That is exactly how camera 615's
|
|
36149
|
+
* virtual doorbell latched `unbound` for twelve hours on 2026-08-07 while its
|
|
36150
|
+
* binding was intact ([D72](../../../../docs/decisions/adr-0072.md)).
|
|
36151
|
+
*
|
|
36152
|
+
* Route every comparison between `ctx.id` and a registry/store addon id
|
|
36153
|
+
* through {@link isSameAddonId}. `scripts/check-addon-id-comparison.ts`
|
|
36154
|
+
* enforces it in the processes where the prefix exists.
|
|
36155
|
+
*/
|
|
36156
|
+
/** The prefix the hub-main context factory prepends to the manifest id. */
|
|
36157
|
+
var ADDON_ID_PREFIX = "addon:";
|
|
36158
|
+
/** The manifest id, whichever spelling of `ctx.id` you were handed. */
|
|
36159
|
+
function bareAddonId(id) {
|
|
36160
|
+
return id.startsWith(ADDON_ID_PREFIX) ? id.slice(6) : id;
|
|
36161
|
+
}
|
|
36162
|
+
/** True when both ids name the same addon, prefixed or not. */
|
|
36163
|
+
function isSameAddonId(a, b) {
|
|
36164
|
+
return bareAddonId(a) === bareAddonId(b);
|
|
36165
|
+
}
|
|
36166
|
+
//#endregion
|
|
35574
36167
|
//#region src/utils/cosine-similarity.ts
|
|
35575
36168
|
/** Cosine similarity between two embedding vectors */
|
|
35576
36169
|
function cosineSimilarity(a, b) {
|
|
@@ -36297,7 +36890,7 @@ function readDetailCropConvention(config) {
|
|
|
36297
36890
|
square: square.success ? square.data : DEFAULT_DETAIL_CROP_CONVENTION.square
|
|
36298
36891
|
};
|
|
36299
36892
|
}
|
|
36300
|
-
function isHydratedField(entry) {
|
|
36893
|
+
function isHydratedField$1(entry) {
|
|
36301
36894
|
return typeof entry === "object" && entry !== null && "key" in entry;
|
|
36302
36895
|
}
|
|
36303
36896
|
/**
|
|
@@ -36312,7 +36905,7 @@ function pickDetailCropConvention(view) {
|
|
|
36312
36905
|
if (view === null) return DEFAULT_DETAIL_CROP_CONVENTION;
|
|
36313
36906
|
const flat = {};
|
|
36314
36907
|
for (const section of view.sections) for (const entry of section.fields) {
|
|
36315
|
-
if (!isHydratedField(entry) || typeof entry.key !== "string") continue;
|
|
36908
|
+
if (!isHydratedField$1(entry) || typeof entry.key !== "string") continue;
|
|
36316
36909
|
if (entry.key === "detailCropPaddingRatio" || entry.key === "detailCropSquare") flat[entry.key] = entry.value;
|
|
36317
36910
|
}
|
|
36318
36911
|
return readDetailCropConvention(flat);
|
|
@@ -36399,6 +36992,245 @@ function slideInsideFrame(rect, frameWidth, frameHeight) {
|
|
|
36399
36992
|
};
|
|
36400
36993
|
}
|
|
36401
36994
|
//#endregion
|
|
36995
|
+
//#region src/pipeline/native-lease.ts
|
|
36996
|
+
/**
|
|
36997
|
+
* THE native-frame **lease** knobs — TTL, RAM budget and demand window for the
|
|
36998
|
+
* decode worker's native-resolution frame retention.
|
|
36999
|
+
*
|
|
37000
|
+
* ## Why they live here and not in the addon that reads them
|
|
37001
|
+
*
|
|
37002
|
+
* The WRITER is `pipeline-orchestrator` (the cluster-wide settings authority);
|
|
37003
|
+
* the READER is a private child process of `addon-pipeline`'s pipeline-runner.
|
|
37004
|
+
* Addons never import each other, so a key owned by either side would have to
|
|
37005
|
+
* be hand-copied by the other — and a hand-copied key is how a setting silently
|
|
37006
|
+
* stops arriving while both sides still look correct. Same reasoning, same
|
|
37007
|
+
* placement as `detail-crop.ts` (D52's "one cluster-wide orchestrator setting").
|
|
37008
|
+
*
|
|
37009
|
+
* ## Why cluster-wide and not per-node
|
|
37010
|
+
*
|
|
37011
|
+
* The lease is a per-decode-worker RAM window. Its purpose — the late
|
|
37012
|
+
* cross-process native crop landing on a full-resolution frame rather than the
|
|
37013
|
+
* ≤640 detection fallback — is a property of the PIPELINE, not of a node's
|
|
37014
|
+
* hardware: a per-node TTL would mean the same camera produces different crop
|
|
37015
|
+
* quality depending on which node the balancer placed it on, and nobody could
|
|
37016
|
+
* tell that from the stored media. Node-level RAM pressure is already handled
|
|
37017
|
+
* by the per-session budget ceiling, which is itself one of these knobs.
|
|
37018
|
+
*
|
|
37019
|
+
* ## What each knob costs
|
|
37020
|
+
*
|
|
37021
|
+
* A retained frame is a full NATIVE-resolution copy in system RAM. With the
|
|
37022
|
+
* default pinned-RGB24 lease path (`CAMSTACK_SESSION_PINNED_RGB_CROP`, on):
|
|
37023
|
+
* 4K ≈ 24.9 MB/frame, 1080p ≈ 6.2 MB/frame. On the YUV420P path (flag off, and
|
|
37024
|
+
* for software-decoded sessions): 4K ≈ 12.4 MB, 1080p ≈ 3.1 MB. Worst-case
|
|
37025
|
+
* resident RAM for ONE busy camera ≈ frameBytes × deliveredFps × ttlSeconds,
|
|
37026
|
+
* clamped by the budget ceiling. See `docs/design/decode-path.md` → "Lease
|
|
37027
|
+
* admission" for what actually gets admitted.
|
|
37028
|
+
*/
|
|
37029
|
+
/**
|
|
37030
|
+
* Store identity of the lease knobs in `pipeline-orchestrator`'s GLOBAL
|
|
37031
|
+
* (cluster-wide) settings. Keys are unique across that addon's whole schema, so
|
|
37032
|
+
* the reader can walk every section instead of trusting the section id.
|
|
37033
|
+
*/
|
|
37034
|
+
var NATIVE_LEASE_SECTION_ID = "native-lease";
|
|
37035
|
+
var NATIVE_LEASE_TTL_KEY = "nativeLeaseTtlMs";
|
|
37036
|
+
var NATIVE_LEASE_BUDGET_KEY = "nativeLeaseBudgetMb";
|
|
37037
|
+
var NATIVE_LEASE_ACTIVITY_KEY = "nativeLeaseActivityMs";
|
|
37038
|
+
var NATIVE_LEASE_ADMISSION_KEY = "nativeLeaseAdmission";
|
|
37039
|
+
/**
|
|
37040
|
+
* WHICH delivered frames the decode worker retains a native copy of.
|
|
37041
|
+
*
|
|
37042
|
+
* - `all` — every frame the worker delivered to the runner. The shipped
|
|
37043
|
+
* behaviour, and the only correct one if something can ask for a crop of a
|
|
37044
|
+
* frame the runner never sent to inference.
|
|
37045
|
+
* - `inferred` — only the frames the runner ADMITTED to its detection queue.
|
|
37046
|
+
* A native-crop request always names a `frameId` that rode an inference
|
|
37047
|
+
* result, so that is the only set a request can name. How much it drops is
|
|
37048
|
+
* the two-plane governor's admit ratio and nothing else: measured at ~50% on
|
|
37049
|
+
* this cluster, not the ~80% the design sketch assumed, because the governor
|
|
37050
|
+
* was not throttling as hard as the sketch supposed. Read
|
|
37051
|
+
* `leaseAdmitted`/`leaseOffered` off the metrics line for the camera in front
|
|
37052
|
+
* of you rather than quoting a number from here. The newest delivered frame is
|
|
37053
|
+
* croppable regardless — it is still the worker's reserved slot, not a lease —
|
|
37054
|
+
* which covers the one-frame race between a mark and the supersede that
|
|
37055
|
+
* consumes it.
|
|
37056
|
+
*/
|
|
37057
|
+
var NativeLeaseAdmissionSchema = z.enum(["all", "inferred"]);
|
|
37058
|
+
/**
|
|
37059
|
+
* Operator-tunable native-lease settings. Bounds are enforced HERE (not only in
|
|
37060
|
+
* the slider) because the value also travels to a forked child process, where a
|
|
37061
|
+
* junk number would silently become a 0-length or unbounded retention window.
|
|
37062
|
+
*/
|
|
37063
|
+
var NativeLeaseSettingsSchema = z.object({
|
|
37064
|
+
/**
|
|
37065
|
+
* How long a retained native frame is served before it counts as a miss.
|
|
37066
|
+
*
|
|
37067
|
+
* Must cover the FULL late-crop horizon: detection inference + the
|
|
37068
|
+
* cross-process inference-result hop to hub post-analysis + tracking + the
|
|
37069
|
+
* tRPC crop round-trip back. Below ~500 ms the busiest cameras' subject crops
|
|
37070
|
+
* outrun it and fall back to the ≤640 detection frame; above ~3 s the resident
|
|
37071
|
+
* RAM per busy camera grows linearly with no measured hit-rate gain.
|
|
37072
|
+
*/
|
|
37073
|
+
ttlMs: z.number().int().min(250).max(1e4),
|
|
37074
|
+
/**
|
|
37075
|
+
* Hard per-decode-worker RAM ceiling for retained native frames, in MB.
|
|
37076
|
+
*
|
|
37077
|
+
* Intended as a SAFETY ceiling with the TTL as the effective cap — but check
|
|
37078
|
+
* which one is actually binding before reasoning from that. At the shipped
|
|
37079
|
+
* 1024 MB and a 2 800 ms TTL, a 4K camera hits the CEILING first (~43 frames
|
|
37080
|
+
* at ~24 MB each) and the TTL never gets to expire anything; `leaseMb` /
|
|
37081
|
+
* `leaseFrames` on the metrics line say which. When the ceiling binds, a
|
|
37082
|
+
* change that admits fewer frames buys retention WINDOW at constant RAM
|
|
37083
|
+
* rather than giving RAM back — lower this knob if RAM is what you wanted.
|
|
37084
|
+
* `0` DISABLES the lease entirely and falls the worker back to the tiny
|
|
37085
|
+
* leak-prone GPU surface ring (~85% crop miss; that is what the lease exists
|
|
37086
|
+
* to replace).
|
|
37087
|
+
*/
|
|
37088
|
+
budgetMb: z.number().int().min(0).max(4096),
|
|
37089
|
+
/**
|
|
37090
|
+
* Demand window: eager per-frame native retention runs only within this many
|
|
37091
|
+
* ms of the last native-crop request (or of the dial starting).
|
|
37092
|
+
*
|
|
37093
|
+
* `0` means ALWAYS ON — it disables the gate, it does not disable retention.
|
|
37094
|
+
* That is the legacy behaviour that saturated an N100 (24 native-4K downloads
|
|
37095
|
+
* per second on a camera with zero crop demand), so leave it non-zero unless
|
|
37096
|
+
* you are reproducing that.
|
|
37097
|
+
*/
|
|
37098
|
+
activityMs: z.number().int().min(0).max(12e4),
|
|
37099
|
+
/**
|
|
37100
|
+
* Which delivered frames are retained at all — see
|
|
37101
|
+
* {@link NativeLeaseAdmissionSchema}. This is the only knob of the four that
|
|
37102
|
+
* changes WHAT is kept rather than for how long, so it is also the only one
|
|
37103
|
+
* that can turn a crop that used to hit into a miss. The worker counts every
|
|
37104
|
+
* crop request naming a frame it did NOT see marked
|
|
37105
|
+
* (`leaseUnmarkedCrops` on the session-decode metrics line): a non-zero value
|
|
37106
|
+
* there is the signal that some caller names frames outside the inference set
|
|
37107
|
+
* and that this must go back to `all`.
|
|
37108
|
+
*/
|
|
37109
|
+
admission: NativeLeaseAdmissionSchema
|
|
37110
|
+
});
|
|
37111
|
+
/**
|
|
37112
|
+
* The values in force when the operator has set nothing — byte-for-byte the
|
|
37113
|
+
* constants the decode worker shipped with as env-var defaults, so making these
|
|
37114
|
+
* settings changed no behaviour on the day it landed.
|
|
37115
|
+
*/
|
|
37116
|
+
var DEFAULT_NATIVE_LEASE_SETTINGS = {
|
|
37117
|
+
ttlMs: 1200,
|
|
37118
|
+
budgetMb: 1024,
|
|
37119
|
+
activityMs: 15e3,
|
|
37120
|
+
admission: "inferred"
|
|
37121
|
+
};
|
|
37122
|
+
/** Slider bounds for the operator-facing knobs (orchestrator settings UI). */
|
|
37123
|
+
var NATIVE_LEASE_TTL_FIELD = {
|
|
37124
|
+
min: 250,
|
|
37125
|
+
max: 1e4,
|
|
37126
|
+
step: 50,
|
|
37127
|
+
default: DEFAULT_NATIVE_LEASE_SETTINGS.ttlMs
|
|
37128
|
+
};
|
|
37129
|
+
var NATIVE_LEASE_BUDGET_FIELD = {
|
|
37130
|
+
min: 0,
|
|
37131
|
+
max: 4096,
|
|
37132
|
+
step: 64,
|
|
37133
|
+
default: DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb
|
|
37134
|
+
};
|
|
37135
|
+
var NATIVE_LEASE_ACTIVITY_FIELD = {
|
|
37136
|
+
min: 0,
|
|
37137
|
+
max: 12e4,
|
|
37138
|
+
step: 1e3,
|
|
37139
|
+
default: DEFAULT_NATIVE_LEASE_SETTINGS.activityMs
|
|
37140
|
+
};
|
|
37141
|
+
/** Select options for the admission knob (orchestrator settings UI). */
|
|
37142
|
+
var NATIVE_LEASE_ADMISSION_FIELD = {
|
|
37143
|
+
options: [{
|
|
37144
|
+
value: "all",
|
|
37145
|
+
label: "Every delivered frame"
|
|
37146
|
+
}, {
|
|
37147
|
+
value: "inferred",
|
|
37148
|
+
label: "Only frames sent to inference"
|
|
37149
|
+
}],
|
|
37150
|
+
default: DEFAULT_NATIVE_LEASE_SETTINGS.admission
|
|
37151
|
+
};
|
|
37152
|
+
/**
|
|
37153
|
+
* Parse one knob, reporting `null` for absent, junk, out-of-bounds — AND for a
|
|
37154
|
+
* value equal to the shipped default.
|
|
37155
|
+
*
|
|
37156
|
+
* That last rule is not tidiness, it is the difference between the documented
|
|
37157
|
+
* precedence being true and being a lie. `addon-settings.getGlobalSettings`
|
|
37158
|
+
* returns a HYDRATED payload, and `hydrateField` fills an unstored field with
|
|
37159
|
+
* the schema's own `default` (verified live on the hub: a cluster that has never
|
|
37160
|
+
* opened the form still reports `nativeLeaseTtlMs = 1200`). A reader that took
|
|
37161
|
+
* that at face value would report all three knobs as "set" on every cluster on
|
|
37162
|
+
* the day this shipped, permanently retiring the `CAMSTACK_SESSION_NATIVE_LEASE_*`
|
|
37163
|
+
* emergency override that the precedence promises. There is no raw-store read on
|
|
37164
|
+
* this cap to distinguish the two, so the default value itself is treated as
|
|
37165
|
+
* "the operator has expressed no preference" — which is also what leaving a
|
|
37166
|
+
* slider untouched means.
|
|
37167
|
+
*
|
|
37168
|
+
* The cost is one honest edge: an operator who deliberately selects the default
|
|
37169
|
+
* value in order to overrule an env var does not get it. Clear the env var
|
|
37170
|
+
* instead; the worker's spawn line names the source, so this is visible rather
|
|
37171
|
+
* than mysterious.
|
|
37172
|
+
*/
|
|
37173
|
+
function readKnob(knob, raw) {
|
|
37174
|
+
const parsed = NativeLeaseSettingsSchema.shape[knob].safeParse(raw);
|
|
37175
|
+
if (!parsed.success) return null;
|
|
37176
|
+
return parsed.data === DEFAULT_NATIVE_LEASE_SETTINGS[knob] ? null : parsed.data;
|
|
37177
|
+
}
|
|
37178
|
+
/** {@link readKnob} for the one non-numeric knob. Same default-means-unset rule. */
|
|
37179
|
+
function readAdmissionKnob(raw) {
|
|
37180
|
+
const parsed = NativeLeaseAdmissionSchema.safeParse(raw);
|
|
37181
|
+
if (!parsed.success) return null;
|
|
37182
|
+
return parsed.data === DEFAULT_NATIVE_LEASE_SETTINGS.admission ? null : parsed.data;
|
|
37183
|
+
}
|
|
37184
|
+
/**
|
|
37185
|
+
* Narrow a FLAT settings record to the knobs the operator set.
|
|
37186
|
+
*
|
|
37187
|
+
* Per-FIELD parse, deliberately: a junk TTL must not also discard a valid
|
|
37188
|
+
* budget. An absent, out-of-bounds or default-valued knob is OMITTED (not
|
|
37189
|
+
* clamped, not defaulted) so the caller can still fall through to the env
|
|
37190
|
+
* override — clamping here would turn a typo into a value nobody chose. See
|
|
37191
|
+
* {@link readKnob} for why the default counts as unset.
|
|
37192
|
+
*/
|
|
37193
|
+
function readNativeLeaseOverride(config) {
|
|
37194
|
+
const ttlMs = readKnob("ttlMs", config[NATIVE_LEASE_TTL_KEY]);
|
|
37195
|
+
const budgetMb = readKnob("budgetMb", config[NATIVE_LEASE_BUDGET_KEY]);
|
|
37196
|
+
const activityMs = readKnob("activityMs", config[NATIVE_LEASE_ACTIVITY_KEY]);
|
|
37197
|
+
const admission = readAdmissionKnob(config[NATIVE_LEASE_ADMISSION_KEY]);
|
|
37198
|
+
return {
|
|
37199
|
+
...ttlMs === null ? {} : { ttlMs },
|
|
37200
|
+
...budgetMb === null ? {} : { budgetMb },
|
|
37201
|
+
...activityMs === null ? {} : { activityMs },
|
|
37202
|
+
...admission === null ? {} : { admission }
|
|
37203
|
+
};
|
|
37204
|
+
}
|
|
37205
|
+
function isHydratedField(entry) {
|
|
37206
|
+
return typeof entry === "object" && entry !== null && "key" in entry;
|
|
37207
|
+
}
|
|
37208
|
+
var LEASE_KEYS = [
|
|
37209
|
+
NATIVE_LEASE_TTL_KEY,
|
|
37210
|
+
NATIVE_LEASE_BUDGET_KEY,
|
|
37211
|
+
NATIVE_LEASE_ACTIVITY_KEY,
|
|
37212
|
+
NATIVE_LEASE_ADMISSION_KEY
|
|
37213
|
+
];
|
|
37214
|
+
/**
|
|
37215
|
+
* Extract the operator's lease overrides from an
|
|
37216
|
+
* `addon-settings.getGlobalSettings` payload.
|
|
37217
|
+
*
|
|
37218
|
+
* Walks EVERY section rather than looking inside {@link NATIVE_LEASE_SECTION_ID}
|
|
37219
|
+
* alone: the keys are unique across the addon's schema, and a section rename
|
|
37220
|
+
* must not silently revert the whole cluster to the defaults. A `null` payload
|
|
37221
|
+
* (addon mid-boot) means "operator set nothing" — the env/default fallback then
|
|
37222
|
+
* applies, which is the correct read of "I could not ask".
|
|
37223
|
+
*/
|
|
37224
|
+
function pickNativeLeaseOverride(view) {
|
|
37225
|
+
if (view === null) return {};
|
|
37226
|
+
const flat = {};
|
|
37227
|
+
for (const section of view.sections) for (const entry of section.fields) {
|
|
37228
|
+
if (!isHydratedField(entry) || typeof entry.key !== "string") continue;
|
|
37229
|
+
if (LEASE_KEYS.includes(entry.key)) flat[entry.key] = entry.value;
|
|
37230
|
+
}
|
|
37231
|
+
return readNativeLeaseOverride(flat);
|
|
37232
|
+
}
|
|
37233
|
+
//#endregion
|
|
36402
37234
|
//#region src/helpers/bind-addon-actions.ts
|
|
36403
37235
|
/**
|
|
36404
37236
|
* Bind an addon's custom-action catalog to its tRPC surface, returning a
|
|
@@ -36650,4 +37482,4 @@ function enumerateInferenceDevices(hw) {
|
|
|
36650
37482
|
return out;
|
|
36651
37483
|
}
|
|
36652
37484
|
//#endregion
|
|
36653
|
-
export { ACCESSORY_LABEL, ALEXA_EGRESS_PROFILE, ALL_CAPABILITY_DEFINITIONS, APPLE_SA_TO_MACRO, AUDIO_ANALYSIS_CAP_NAME, AUDIO_BACKEND_CHOICES, AUDIO_MACRO_LABELS, AUDIO_PRESETS, AccessoriesStatusSchema, AccessoryKind, AddBrokerInputSchema, AddonAutoUpdateSchema, AddonListItemSchema, AddonPageDeclarationSchema, AddonPageInfoSchema, AdoptInputSchema as AdoptionAdoptInputSchema, AdoptResultSchema as AdoptionAdoptResultSchema, AdoptionFilterSchema, GetCandidateInputSchema as AdoptionGetCandidateInputSchema, ListCandidatesInputSchema as AdoptionListCandidatesInputSchema, ListCandidatesOutputSchema as AdoptionListCandidatesOutputSchema, ReleaseInputSchema as AdoptionReleaseInputSchema, AdoptionStatusSchema, AgentLoadSummarySchema, AirQualitySensorStatusSchema, AlarmArmModeSchema, AlarmPanelStatusSchema, AlarmStateSchema, AlertSchema, AlertSeveritySchema, AlertSourceSchema, AlertStatusSchema, AmbientLightSensorStatusSchema, ApiKeyRecordSchema, ApiKeySummarySchema, ArchiveEntrySchema, ArchiveManifestSchema, AttachmentMediaTypeSchema, AttachmentSchema, AudioAnalysisResultSchema, AudioAnalysisSettingsSchema, AudioChunkInputSchema, AudioClassSummarySchema, AudioClassificationLabelSchema, AudioClassificationResultSchema, AudioCodecInfoSchema, AudioDecodeSessionConfigSchema, AudioEncodeSchema, AudioEncodeSessionConfigSchema, AudioEncodedChunkSchema, AudioEventSchema, AudioLevelSchema, AudioMetricsHistoryPointSchema, AudioMetricsHistorySchema, AudioMetricsSnapshotSchema, AudioPcmChunkSchema, AuthResultSchema, AutoUpdateSettingsSchema, AutomationControlStatusSchema, AvailableIntegrationTypeSchema, BACKEND_TO_FORMAT, BASE_LIVE_EGRESS_PROFILE, BATTERY_DEVICE_PROFILE, BacklightModeSchema, BackupDestinationInfoSchema, BackupEntrySchema, BaseAddon, BaseDevice, BaseDeviceProvider, BatteryStatusSchema, BinaryStatusSchema, BoundingBoxSchema, BrightnessStatusSchema, AddInputSchema as BrokerAddInputSchema, BrokerAudioClientSchema, BrokerClientsSchema, BrokerConnectionDetailsSchema, BrokerConsumerAttributionSchema, BrokerConsumerKindSchema, BrokerDecodedClientSchema, BrokerEncodedClientSchema, GetStateInputSchema as BrokerGetStateInputSchema, BrokerInfoSchema, BrokerProviderInfoSchema, PublishInputSchema as BrokerPublishInputSchema, RegistryStatusSchema as BrokerRegistryStatusSchema, BrokerRtspClientSchema, BrokerStatsSchema, BrokerStatusEnum, BrokerStatusSchema, SubscribeInputSchema as BrokerSubscribeInputSchema, SubscribeResultSchema as BrokerSubscribeResultSchema, TestConnectionResultSchema as BrokerTestConnectionResultSchema, UnsubscribeInputSchema as BrokerUnsubscribeInputSchema, CAMERA_SWITCH_CATALOG, CAMERA_SWITCH_ORDER, CAM_PROFILE_ORDER, CAPABILITY_NAMES, CAPABILITY_ROUTER_KEYS, CAP_NAMES_WITH_STATUS, CAP_NODE_PIN_CONTEXT_KEY, CAP_PROVIDER_KIND_MAP, COCO_80_LABELS, COCO_TO_MACRO, CamProfileSchema, CamStreamDescriptorSchema, CamStreamKindSchema, CamStreamResolutionSchema, CameraAssignmentStatusSchema, CameraAudioStatusSchema, CameraBrokerProfileSchema, CameraBrokerStatusSchema, CameraCredentialsSchema, CameraCredentialsStatusSchema, CameraDecoderShmSchema, CameraDecoderStatusSchema, CameraDetectionPhaseSchema, CameraDetectionProvisioningSchema, CameraDetectionProvisioningStateSchema, CameraDetectionStatusSchema, CameraMetricsSchema, CameraMetricsWithDeviceIdSchema, CameraMotionStatusSchema, CameraRecordingModeSchema, CameraRecordingStatusSchema, CameraSourceStatusSchema, CameraSourceStreamSchema, CameraStatusSchema, CameraStreamSchema, CameraSwitchAuthoritySchema, CameraSwitchGroupSchema, CameraSwitchIdSchema, CameraSwitchSchema, CameraSwitchUnavailableReasonSchema, CandidateQueryFilterSchema, CapScopeSchema, CapabilityBindingsSchema, CarbonMonoxideStatusSchema, ChargingStatus, ClientNetworkStatsSchema, ClimateControlStatusSchema, ClipPlaybackSchema, ClipSchema, ClusterAddonNodeDeploymentSchema, ClusterAddonStatusEntrySchema, CollectionColumnSchema, CollectionIndexSchema, ColorStatusSchema, ConfigEntrySchema, ConfigSectionWithValuesSchema, ConfigTabDeclarationSchema, ConnectivityStatusSchema, ConsumableItemSchema, ConsumablesStatusSchema, ContactStatusSchema, ControlKindSchema, ControlStatusSchema, ConvertArtifactSchema, ConvertResultSchema, ConvertTargetSchema, CoreBlockCompileResultSchema, CoreBlockInputSchema, CoreBlockPlacementSchema, CoreBlockSchema, CoreBlockStatusSchema, CoverStateSchema, CoverStatusSchema, CreateApiKeyInputSchema, CreateApiKeyResultSchema, CreateIntegrationInputSchema, CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, CreateUserInputSchema, CustomActionInputSchema, CustomModelDescriptorSchema, DATAPLANE_SECRET_HEADER, DEFAULT_ADDON_PLACEMENT, DEFAULT_AUDIO_ANALYZER_CONFIG, DEFAULT_DECODER_HWACCEL_CONFIG, DEFAULT_DETAIL_CROP_CONVENTION, DEFAULT_EVENT_COLOR, DEFAULT_FEATURES, DEFAULT_RETENTION, DEFAULT_SCRUB_THUMBNAIL_PRESET, DETAIL_CROP_PADDING_FIELD, DETAIL_CROP_PADDING_KEY, DETAIL_CROP_SECTION_ID, DETAIL_CROP_SQUARE_KEY, DETECTION_PIPELINE_CAP_NAME, DEVICE_BACKEND_TO_FORMAT, DEVICE_CAP_NAMES, DEVICE_PROFILES, DEVICE_SCOPED_CAPS, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATE_READERS, DEVICE_STATUS_METHOD, DEVICE_TYPE_CONTROL_KIND, DEVICE_TYPE_INFO, EngineInfoSchema as DataStoreEngineInfoSchema, DayNightModeSchema, DayNightOptionsSchema, DayNightSettingsPatchSchema, DayNightStatusSchema, DecodedAudioChunkSchema, DecodedFrameSchema, DecoderSessionConfigSchema, DecoderStatsSchema, DeleteIntegrationResultSchema, DetailCropConventionSchema, DetectionSourceSchema, DeviceCodeSeveritySchema, DeviceConfig, DeviceDiscoveryStatusSchema, ExposeInputSchema as DeviceExportExposeInputSchema, DeviceExportStatusSchema, UnexposeInputSchema as DeviceExportUnexposeInputSchema, DeviceFeature, DeviceInfoSchema, DeviceLinkModeSchema, DeviceNetworkStatsSchema, DeviceRole, DeviceRuntimeState, DeviceStatusSchema, DeviceType, DiscoveredChildDeviceSchema, DiscoveredChildStatusSchema, DiscoveredDeviceSchema, DiscoveredTargetSchema, DisposerChain, DoorbellPressEventSchema, DoorbellStatusSchema, EVENTFUL_CAP_NAMES, EVENT_KIND_BY_CAP, EVENT_PAD_MS, EVENT_TAXONOMY, EXPRESSION_BUILTINS, EXPRESSION_BUILTIN_NAMES, EXPRESSION_COMPILE_CACHE_CAPACITY, EXPRESSION_IDENTIFIER_RE, EXPRESSION_INJECTED_NOW, ElementConfigStore, EmbeddingInfoSchema, EmbeddingResultSchema, EncodeProfileSchema, EncodedPacketSchema, EnrichedWidgetMetadataSchema, EnumSensorDateTimeFormatSchema, EnumSensorStatusSchema, EventCategory, EventEmitterStatusSchema, EventFireSchema, EventItemSchema, EventKindCategorySchema, EventKindDescriptorSchema, EventKindIconSchema, EventKindSchema, EventKindsForDeviceSchema, EventSourceType, ExportDownloadSchema, ExportOptionsSchema, ExportRecordSchema, ExportSetupFieldSchema, ExportSetupSchema, ExportSpeedSchema, ExportStateSchema, ExportTimelapseSchema, ExposedDeviceSchema, ExposureModeSchema, ExpressionEvalError, ExpressionParseError, FanControlStatusSchema, FanDirectionSchema, FeatureManifestSchema, FeatureProbeStatusSchema, FloodStatusSchema, FrameHandleFormatSchema, FrameHandleSchema, FrameInputSchema, GasStatusSchema, GetStreamWithCodecInputSchema, GlobalMetricsSchema, HAP_AUDIO_BASE, HAP_AUDIO_BITRATE_KBPS, HAP_AUDIO_VBV_KBITS, HAP_KEYFRAME_INTERVAL_SEC, HF_BASE_URL, HF_REPO, HWACCEL_OPTIONS, HealthStatusSchema, HistoryPointSchema, HistoryResolutionEnum, HumidifierStatusSchema, HumiditySensorStatusSchema, HvacModeSchema, ImageContractSchema, ImageContractStateSchema, ImageRotateSchema, ImageSettingsOptionsSchema, ImageSettingsPatchSchema, ImageSettingsStatusSchema, ImageStatusSchema, IngestOwnerSchema, InstalledPackageSchema, IntegrationLiteSchema, IntegrationWithStateSchema, IntercomAbilitySchema, IntercomStatusSchema, KNOWN_CAP_NAMES, KeyEventSchema, LOG_LEVEL_RANK, LabelDefinitionSchema, LawnMowerActivitySchema, LawnMowerControlStatusSchema, LinkedDeviceSchema, LlmDefaultSchema, LlmDefaultSelectorSchema, LlmErrorCodeSchema, LlmGenerateBaseInputSchema, LlmGenerateErrSchema, LlmGenerateOkSchema, LlmGenerateResultSchema, LlmImageSchema, LlmNodeModelSchema, LlmProfileKindDescriptorSchema, LlmProfileKindSchema, LlmProfileSchema, LlmRuntimeCompleteInputSchema, LlmRuntimeDiskUsageSchema, LlmRuntimeNodeSchema, LlmRuntimeStatusSchema, LlmUsageRollupSchema, LlmUsageSchema, LocateSegmentResultSchema, LocationStatSchema, LockControlStatusSchema, LockStateSchema, LogEntrySchema, LogLevelSchema, LogStreamEntrySchema, LoginMethodContributionSchema, LoginStageEnum, MACRO_LABELS, MAX_EXPRESSION_AST_NODES, MAX_EXPRESSION_BINDINGS, MAX_EXPRESSION_CALL_ARGS, MAX_EXPRESSION_EVAL_STEPS, MAX_EXPRESSION_SOURCE_LENGTH, METHOD_ACCESS_MAP, MODEL_FORMATS, MOTION_TRIGGER_FEATURE, ManagedModelCatalogEntrySchema, ManagedModelRefSchema, ManagedRuntimeConfigSchema, MaskGridDimsSchema, MaskGridShapeSchema, MaskLineShapeSchema, MaskPointSchema, MaskPolygonShapeSchema, MaskPolygonVerticesSchema, MaskRectShapeSchema, MaskShapeKindSchema, MaskShapeSchema, MediaFileInfoSchema, MediaFileSchema, MediaPlayerRepeatSchema, MediaPlayerStateSchema, MediaPlayerStatusSchema, MeshPeerSchema, MeshStatusSchema, MethodAccessSchema, ModelCatalogEntrySchema, ModelConvertInputSchema, ModelConvertMetadataSchema, ModelDistributeInputSchema, ModelDistributeResultSchema, ModelExtraFileSchema, ModelFormatEntrySchema, ModelFormatsSchema, ModelSubstitutionSchema, ModelVariantGroupSchema, MotionAnalysisResultSchema, MotionEventSchema, MotionOnMotionChangedDataSchema, MotionRegionSchema, MotionSourceEnum, MotionSourcesSchema, MotionStatusSchema, MotionTriggerRuntimeStateSchema, MotionTriggerStatusSchema, MotionZoneOptionsSchema, MotionZonePatchSchema, MotionZoneRegionSchema, MotionZoneStatusSchema, StatusSchema as MqttBrokerStatusSchema, MutationFilterSchema, NC_BASE_CONDITION_KEYS, NC_CONDITION_CATALOG, NC_HISTORY_LIMIT_DEFAULT, NC_HISTORY_LIMIT_MAX, NC_MAX_PER_TRACK_IMMEDIATE, NC_SNOOZE_MAX_MINUTES, NC_TAXONOMY, NativeCropBboxSchema, NativeCropRefSchema, NativeCropResultSchema, NativeDetectionSchema, NativeObjectClassEnum, NativeObjectDetectionRuntimeStateSchema, NativeObjectDetectionStatusSchema, NcAlarmConfigSchema, NcAlarmModeCoverageSchema, NcAlarmSettingsPatchSchema, NcAlarmSettingsSchema, NcConditionDescriptorSchema, NcConditionsSchema, NcCrossingSchema, NcDeliverySchema, NcDeviceStateConditionSchema, NcHistoryEntrySchema, NcHistoryFilterSchema, NcHistoryRecordKindSchema, NcHistoryStatusSchema, NcHistorySubjectSchema, NcMediaFrameSchema, NcMediaPolicySchema, NcOccupancyConditionSchema, NcPlateMatcherSchema, NcRuleActionSchema, NcRuleActionSequenceSchema, NcRuleActionsSchema, NcRuleInputSchema, NcRuleNotificationButtonSchema, NcRulePatchSchema, NcRuleSchema, NcRuleTargetSchema, NcScheduleSchema, NcScheduleWindowSchema, NcSnoozeInputSchema, NcSnoozeSchema, NcSnoozeScopeSchema, NcSnoozeSuppressedSchema, NcTaxonomyEntrySchema, NcTaxonomySchema, NcTestResultSchema, NcThrottleGranularitySchema, NcThrottleSchema, NcZoneConditionSchema, NetworkAccessStatusSchema, NetworkAddressSchema, NetworkEndpointSchema, NotificationActionIconSchema, NotificationActionSchema, NotificationFormatSchema, NotificationSchema, NotifierStatusSchema, NumericSensorStatusSchema, OPS_LOG_DEFAULT_LIMIT, OPS_LOG_RING_DEFAULT_MAX, OauthIntegrationDescriptorSchema, ObjectEventSchema, OpsLogDomainSchema, OpsLogEntrySchema, OpsLogOpSchema, OpsLogQueryInputSchema, OpsLogReasonSchema, OrchestratorMetricsSchema, OsdOverlayKindEnum, OsdOverlayPatchSchema, OsdOverlaySchema, OsdPositionEnum, OsdStatusSchema, PET_FEEDER_MANUAL_FEED_MAX, PET_FEEDER_MANUAL_FEED_MIN, PIPELINE_FLOW_CAPABILITY_NAMES, PIPELINE_OWNER_CAPABILITY_NAMES, PROVIDER_KIND_CAP_NAMES, PYTHON_SCRIPT, PackageUpdateSchema, PackageVersionInfoSchema, PasskeyLoginMethodSchema, PasskeySummarySchema, PcmSampleFormatSchema, PerScopeBreakdownSchema, PetFeederStatusSchema, PickStreamPreferencesSchema, PickStreamRequirementsSchema, PickedCamStreamSchema, PipelineAssignmentSchema, PipelineDefaultStepSchema, PipelineEngineChoiceSchema, PipelineRunResultBridge, PipelineStepInputSchema, PipelineValidationIssueSchema, PipelineValidationResultSchema, PlaceholderReasonSchema, PolygonPointSchema, PowerMeterStatusSchema, PresenceStatusSchema, PressureSensorStatusSchema, PrivacyMaskOptionsSchema, PrivacyMaskPatchSchema, PrivacyMaskRegionSchema, PrivacyMaskShapeSchema, PrivacyMaskStatusSchema, ProfileRtspEntrySchema, ProfileSlotSchema, ProfileSlotStatusSchema, ProviderStatusSchema, PtzAutotrackRuntimeStateSchema, PtzAutotrackSettingsSchema, PtzAutotrackStatusSchema, PtzAutotrackTargetOptionSchema, PtzMoveCommandSchema, PtzOptionsSchema, PtzPositionSchema, PtzPresetSchema, PtzStatusSchema, QueryFilterSchema, RATE_CONTROL_RELAXED, RATE_CONTROL_TIGHT, REACHABILITY_FAILURES_TO_OFFLINE, REACHABILITY_POLL_INTERVAL_MS, REACHABILITY_PROBE_TIMEOUT_MS, RECOGNITION_TYPES, RESERVED_BINDING_NAMES, RUNTIME_DEFAULTS, RUNTIME_TO_FORMAT, RawStateResultSchema, ReadSegmentBytesResultSchema, ReadinessRegistry, ReadinessTimeoutError, RecentTracksPageSchema, RecentTracksQueryInput, RecordingAvailabilitySchema, RecordingBandModeSchema, RecordingBandSchema, RecordingBandTriggersSchema, RecordingConfigSchema, RecordingDaysSchema, RecordingDeviceUsageSchema, RecordingLocationUsageSchema, RecordingManifestSchema, RecordingRangeSchema, RecordingRetentionSchema, RecordingStatusSchema, RecordingStorageModeSchema, RecordingStorageUsageSchema, RecordingTriggersSchema, RecordingWeekdaySchema, RedirectLoginMethodSchema, RelocateFootageInputSchema, RelocateJobSchema, RelocateJobStateSchema, RelocateMediaInputSchema, RenderedAsSchema, ReportMotionInputSchema, RingBuffer, RtpSourceSchema, RtspRestreamEntrySchema, RunnerCameraConfigSchema, RunnerCameraDeviceUIFields, RunnerFrameSourceSchema, RunnerInferenceDeviceSchema, RunnerLocalLoadSchema, RunnerLocalMetricsSchema, SCOPE_PRESETS, SCRUB_THUMBNAIL_PRESETS, SCRUB_THUMBNAIL_PRESET_LABELS, SCRUB_THUMBNAIL_PRESET_ORDER, SENSOR_FEATURES, SENSOR_MAP, SOURCE_INFO_METADATA_KEY, STREAM_PROFILE_META, STREAM_QUALITY_LABELS, SUB_DETECTION_TYPES, SYSTEM_CAP_NAMES, SceneCheckSchema, SceneConditionSchema, SceneMonitorSchema, SceneMonitorStateSchema, SceneMonitorStatusSchema, SceneReferenceSchema, ScopedTokenSchema, ScopedTokenSummarySchema, ScoredObjectEventSchema, ScriptRunnerStatusSchema, ScrubThumbnailPresetSchema, SearchResultSchema, SendEmailInputSchema, SendEmailResultSchema, SendResultSchema, SensorEventSchema, ServerBootModeSchema, ServerPackageStatusSchema, ServerRollbackInfoSchema, ServerUpdateActionResultSchema, ServerUpdateCheckResultSchema, ServerUpdateStateSchema, SettingsPatchSchema, SettingsRecordSchema, SettingsSchemaWithValuesSchema, SettingsUpdateResultSchema, ShmRingStatsSchema, SmokeStatusSchema, SmtpStatusSchema, SnapshotImageSchema, SourceInfoSchema, SpatialDetectionSchema, SsoBridgeClaimsSchema, StartEmbeddedInputSchema, StationaryObjectSchema, AbortUploadInputSchema as StorageAbortUploadInputSchema, BeginDownloadInputSchema as StorageBeginDownloadInputSchema, BeginDownloadResultSchema as StorageBeginDownloadResultSchema, BeginUploadInputSchema as StorageBeginUploadInputSchema, BeginUploadResultSchema as StorageBeginUploadResultSchema, EndDownloadInputSchema as StorageEndDownloadInputSchema, FinalizeUploadInputSchema as StorageFinalizeUploadInputSchema, StorageLocationDeclarationSchema, StorageLocationRefSchema, StorageLocationSchema, StorageLocationTypeSchema, ProviderInfoSchema as StorageProviderInfoSchema, ReadChunkInputSchema as StorageReadChunkInputSchema, TestLocationResultSchema as StorageTestLocationResultSchema, WriteChunkInputSchema as StorageWriteChunkInputSchema, StreamCodecSchema, StreamFormatSchema, StreamNetworkStatsSchema, StreamParamsOptionsSchema, StreamParamsStatusSchema, StreamProfileConfigSchema, StreamProfileOptionsSchema, StreamProfilePatchSchema, StreamProfileSchema, StreamSourceEntrySchema, StreamSourceSchema, SubscribeAudioChunksInputSchema, SubscribeAudioChunksResultSchema, SubscribeFramesInputSchema, SubscribeFramesResultSchema, SwitchStatusSchema, SystemMetricsSchema, SystemMirror, TAXONOMY_COLORS, TIMEZONES, TRANSCODE_DOWN_MAX_BITRATE_KBPS, TRANSCODE_DOWN_MAX_HEIGHT, TamperStatusSchema, TankStatusSchema, TargetKindCapsSchema, TargetKindLevelSchema, TargetKindSchema, TargetSchema, TemperatureSensorStatusSchema, TerminalProfileInfoSchema, TerminalSessionInfoSchema, TestConnectionResultSchema$1 as TestConnectionResultSchema, TestResultSchema, TimelapseRuleInputSchema, TimelapseRulePatchSchema, TimelapseRuleSchema, TimelapseTemplateSchema, ToastSchema, TokenScopeSchema, TopologyNodeSchema, TopologyProcessSchema, TopologyServiceSchema, TrackCascadeCountsSchema, TrackEnvelopeSchema, TrackFlagsPatchSchema, TrackFlagsSchema, TrackProjectionSchema, TrackSchema, TrackSourceSchema, TrackStateSchema, TrackZoneFilterSchema, TrackedDetectionSchema, TurnServerSchema, UNIT_TABLE, BrokerInfoSchema$1 as UnifiedBrokerInfoSchema, UnitConversionError, UpdateIntegrationInputSchema, UpdateStatusSchema, UpdateUserInputSchema, UserRecordSchema, UserSummarySchema, VacuumControlStatusSchema, VacuumStateSchema, ValveStateSchema, ValveStatusSchema, VectorDeclareIndexInputSchema, VectorDeleteByFilterInputSchema, VectorDeleteInputSchema, VectorDeleteResultSchema, VectorFilterSchema, VectorGetInputSchema, VectorGetResultSchema, VectorItemSchema, VectorMatchSchema, VectorMetadataSchema, VectorMetricSchema, VectorQueryInputSchema, VectorQueryResultSchema, VectorStatsInputSchema, VectorStatsResultSchema, VectorUpsertInputSchema, VectorUpsertResultSchema, VibrationStatusSchema, VideoEncodeSchema, WEBRTC_EGRESS_PROFILE, WELL_KNOWN_TABS, WELL_KNOWN_TAB_MAP, WaterHeaterStatusSchema, WeatherStatusSchema, WebrtcStreamChoiceSchema, WebrtcStreamTargetSchema, WhiteBalanceModeSchema, WidgetHostEnum, WidgetLoginMethodSchema, WidgetMetadataSchema, WidgetRemoteSchema, WidgetSizeEnum, YAMNET_TO_MACRO, ZoneCrossingDirectionSchema, ZoneCrossingSchema, ZoneKindEnum, ZoneRuleModeEnum, ZoneRuleSchema, ZoneRuleStageEnum, ZoneRulesArraySchema, ZoneSchema, ZoneScopeBreakdownSchema, accessoriesCapability, accessoryStableId, addonPagesCapability, addonPagesSourceCapability, addonRoutesCapability, addonSettingsCapability, addonWidgetsCapability, addonWidgetsSourceCapability, addonsCapability, adminUiCapability, airQualitySensorCapability, alarmPanelCapability, alertsCapability, ambientLightSensorCapability, applyTransform, asBoolean, asJsonArray, asJsonObject, asNumber, asString, audioAnalysisCapability, audioAnalyzerCapability, audioCodecCapability, audioMetricsCapability, audioPlanFromEncodeProfile, authProviderCapability, autoAssignProfiles, automationControlCapability, backupCapability, batteryCapability, bestLocationMatch, binaryCapability, bindAddonActions, brightnessCapability, brokerCapability, buildAddonRouteProvider, buildAudioArgs, buildEventKindDescriptor, buildFfmpegArgs, buildInputArgs, buildModelVariantGroups, buildNcTaxonomy, buildStreamParamsConfigSchema, buildVideoArgs, buttonCapability, cameraCredentialsCapability, cameraPipelineConfigCapability, cameraStreamsCapability, canConvertUnit, canonicalEgressPlan, carbonMonoxideCapability, cellsToRects, classifyStream, classifyStreams, climateControlCapability, collectHydratedFieldEntries, collectHydratedFieldValues, colorCapability, colorForKind, compileExpression, compileExpressionSafe, connectivityCapability, consumablesCapability, contactCapability, controlCapability, convertUnit, coreBlocksCapability, cosineSimilarity, coverCapability, createDeviceProxy, createDurableState, createEvent, createExpressionScope, createHwAccelCache, createLazyTrpcSource, createMirrorSource, createRuntimeStateBridge, createSliceHandle, createSystemProxy, customAction, customModelRegistryCapability, dataStoreProviderCapability, dayNightCapability, decodeVectorBase64, decoderCapability, defaultDeviceFor, defineCustomActions, deriveCameraSwitches, deriveDetailCropRect, deriveRecordingMode, describeModelVariant, detectionPipelineCapability, deviceAdoptionCapability, deviceBackendToFormat, deviceCustomAction, deviceDiscoveryCapability, deviceExportCapability, deviceManagerCapability, deviceMatchesProfile, deviceOpsCapability, deviceProviderCapability, deviceStateCapability, deviceStatusCapability, doorbellCapability, egressTranscodeSharingKey, embeddingEncoderCapability, emitDownForOwnedCaps, emitReadiness, encodeProfileFromStreamShape, encodeVectorBase64, enumSensorCapability, enumerateInferenceDevices, enumerateItemArrayFields, enumerateSchemaFields, errMsg, evaluateAst, evaluateLinkExpression, evaluateZoneRules, event, eventEmitterCapability, eventsCapability, expandCapMethods, extractNestedAddonId, extractSourceInfoFromMetadata, faceGalleryCapability, fanControlCapability, featureProbeCapability, filesystemBrowseCapability, findTimezone, floodCapability, formatForBackend, formatForRuntime, gasCapability, getAudioMacroClassIds, getByPath, getCapsByProviderKind, getTaxonomyEntry, hasMotionTrigger, hfModelUrl, htmlToText, humidifierCapability, humiditySensorCapability, hydrateSchema, imageCapability, imageSettingsCapability, integrationsCapability, intercomCapability, invocationFromEncodeProfile, isAgentOnlyPlacement, isArrayOutputSchema, isBaseConditionKey, isCollectionArrayMethod, isDeployableToAgent, isDeviceConfigCap, isDeviceScopedCap, isEvent, isNode, isObjectInput, isSoftwareDecode, isVoidInput, jobKindSchema, kebabToCamel, knownValues, lawnMowerControlCapability, lifecycleJobSchema, lifecycleJobScopeSchema, lifecycleJobStateSchema, lifecycleTaskSchema, llmCapability, llmRuntimeCapability, localNetworkCapability, locationSimilarity, lockControlCapability, logBannerArgs, logDestinationCapability, logLevelAtMost, loginMethodCapability, looseSchema, makeProfileBrokerId, makeSourceBrokerId, mapAudioLabelToMacro, markdownToHtmlLite, markdownToText, maskUrlCredentials, mediaPlayerCapability, mergeSourceInfo, meshNetworkCapability, method, metricsProviderCapability, modelConvertCapability, modelDistributorCapability, modelFormatForRuntime, motionCapability, motionDetectionCapability, motionTriggerCapability, motionZonesCapability, mqttBrokerCapability, nativeObjectDetectionCapability, networkAccessCapability, networkQualityCapability, nodePin, nodesCapability, normalizeAddonInitResult, normalizeUnit, notificationOutputCapability, notificationRulesCapability, notifierCapability, numericSensorCapability, oauthIntegrationCapability, objectInputDeclaresAddonId, osdCapability, parseCameraStreamConfig, parseExpression, parseJsonArray, parseJsonObject, parseJsonUnknown, parseProfileBrokerId, parseStreamParamsFormPatch, petFeederCapability, pickAccessoryControl, pickDetailCropConvention, pickPreferredRtspEntry, pickVideoEncoder, pickerForCondition, pipelineAnalyticsCapability, pipelineExecutorCapability, pipelineOrchestratorCapability, pipelineRunnerCapability, plateGalleryCapability, platformProbeCapability, powerMeterCapability, prepareNotification, presenceCapability, pressureSensorCapability, privacyMaskCapability, procedureAuthKey, ptzAutotrackCapability, ptzCapability, pythonScriptForBackend, readDetailCropConvention, readDeviceStateFrom, readNodePin, readinessKey, rebootCapability, recordingCapability, recordingExportCapability, rectsToCells, requiresPython, resolveAddonExecution, resolveAddonGroup, resolveAddonPlacement, resolveAddonRuntime, resolveCapMount, resolveDetectionRuntime, resolveDeviceControlKind, resolveDeviceProfile, resolveEgressDecodeHwAccel, resolveFormat, resolveHydratedFieldValue, resolveModelFormat, resolveMutate, resolveRunnerId, resolveScrubThumbnailGeometry, resolveVariantModelId, runInferenceStep, runtimeDevices, sceneMonitorCapability, scopeKey, scoreRuntimes, scriptRunnerCapability, selectAssignedProfileSlots, serverManagementCapability, setByPath, settingsStoreCapability, sleep, sleepCancellable, smokeCapability, smtpProviderCapability, snapshotCapability, ssoBridgeCapability, startReachabilityPoll, stateVocabularyFor, storageCapability, storageEvictableCapability, storageProviderCapability, streamBrokerCapability, streamCatalogCapability, streamParamsCapability, streamPixels, streamQualityLabel, subKindsOf, supportedRuntimes, switchCapability, switchedOffIds, synthesizeSourceInfo, systemCapability, tamperCapability, taskLogEntrySchema, taskPhaseSchema, taskTargetSchema, temperatureSensorCapability, terminalSessionCapability, textToHtml, toDeviceSummary, toExpressionValue, toStreamSourceEntry, toastCapability, tokenize, transcodeBody, tryConvertUnit, turnProviderCapability, unitDimension, unitsForDimension, updateCapability, userManagementCapability, userPasskeysCapability, vacuumControlCapability, validateExpressionSource, valveCapability, vectorDimFromBase64, vectorStoreCapability, vibrationCapability, videoclipsCapability, viewerUiCapability, waterHeaterCapability, weatherCapability, webrtcClientHintsSchema, webrtcSessionCapability, wiringAddonHealthSchema, wiringHealthSnapshotSchema, wiringNodeHealthSchema, wiringProbeKindSchema, wiringProbeResultSchema, zodEntriesToConfigUI, zoneAnalyticsCapability, zoneRulesCapability, zonesCapability };
|
|
37485
|
+
export { ACCESSORY_LABEL, ALEXA_EGRESS_PROFILE, ALL_CAPABILITY_DEFINITIONS, APPLE_SA_TO_MACRO, AUDIO_ANALYSIS_CAP_NAME, AUDIO_BACKEND_CHOICES, AUDIO_MACRO_LABELS, AUDIO_PRESETS, AccessoriesStatusSchema, AccessoryKind, AddBrokerInputSchema, AddonAutoUpdateSchema, AddonListItemSchema, AddonPageDeclarationSchema, AddonPageInfoSchema, AdoptInputSchema as AdoptionAdoptInputSchema, AdoptResultSchema as AdoptionAdoptResultSchema, AdoptionFilterSchema, GetCandidateInputSchema as AdoptionGetCandidateInputSchema, ListCandidatesInputSchema as AdoptionListCandidatesInputSchema, ListCandidatesOutputSchema as AdoptionListCandidatesOutputSchema, ReleaseInputSchema as AdoptionReleaseInputSchema, AdoptionStatusSchema, AgentLoadSummarySchema, AirQualitySensorStatusSchema, AlarmArmModeSchema, AlarmPanelStatusSchema, AlarmStateSchema, AlertSchema, AlertSeveritySchema, AlertSourceSchema, AlertStatusSchema, AmbientLightSensorStatusSchema, ApiKeyRecordSchema, ApiKeySummarySchema, ArchiveEntrySchema, ArchiveManifestSchema, AttachmentMediaTypeSchema, AttachmentSchema, AudioAnalysisResultSchema, AudioAnalysisSettingsSchema, AudioChunkInputSchema, AudioClassSummarySchema, AudioClassificationLabelSchema, AudioClassificationResultSchema, AudioCodecInfoSchema, AudioDecodeSessionConfigSchema, AudioEncodeSchema, AudioEncodeSessionConfigSchema, AudioEncodedChunkSchema, AudioEventSchema, AudioLevelSchema, AudioMetricsHistoryPointSchema, AudioMetricsHistorySchema, AudioMetricsSnapshotSchema, AudioPcmChunkSchema, AuthResultSchema, AutoUpdateSettingsSchema, AutomationControlStatusSchema, AvailableIntegrationTypeSchema, BACKEND_TO_FORMAT, BASE_LIVE_EGRESS_PROFILE, BATTERY_DEVICE_PROFILE, BacklightModeSchema, BackupDestinationInfoSchema, BackupEntrySchema, BaseAddon, BaseDevice, BaseDeviceProvider, BatteryStatusSchema, BinaryStatusSchema, BoundingBoxSchema, BrightnessStatusSchema, AddInputSchema as BrokerAddInputSchema, BrokerAudioClientSchema, BrokerClientsSchema, BrokerConnectionDetailsSchema, BrokerConsumerAttributionSchema, BrokerConsumerKindSchema, BrokerDecodedClientSchema, BrokerEncodedClientSchema, GetStateInputSchema as BrokerGetStateInputSchema, BrokerInfoSchema, BrokerProviderInfoSchema, PublishInputSchema as BrokerPublishInputSchema, RegistryStatusSchema as BrokerRegistryStatusSchema, BrokerRtspClientSchema, BrokerStatsSchema, BrokerStatusEnum, BrokerStatusSchema, SubscribeInputSchema as BrokerSubscribeInputSchema, SubscribeResultSchema as BrokerSubscribeResultSchema, TestConnectionResultSchema as BrokerTestConnectionResultSchema, UnsubscribeInputSchema as BrokerUnsubscribeInputSchema, CAMERA_SWITCH_CATALOG, CAMERA_SWITCH_ORDER, CAM_PROFILE_ORDER, CAPABILITY_NAMES, CAPABILITY_ROUTER_KEYS, CAP_NAMES_WITH_STATUS, CAP_NODE_PIN_CONTEXT_KEY, CAP_PROVIDER_KIND_MAP, COCO_80_LABELS, COCO_TO_MACRO, CamProfileSchema, CamStreamDescriptorSchema, CamStreamKindSchema, CamStreamResolutionSchema, CameraAssignmentStatusSchema, CameraAudioStatusSchema, CameraBrokerProfileSchema, CameraBrokerStatusSchema, CameraCredentialsSchema, CameraCredentialsStatusSchema, CameraDecoderShmSchema, CameraDecoderStatusSchema, CameraDetectionPhaseSchema, CameraDetectionProvisioningSchema, CameraDetectionProvisioningStateSchema, CameraDetectionStatusSchema, CameraMetricsSchema, CameraMetricsWithDeviceIdSchema, CameraMotionStatusSchema, CameraRecordingModeSchema, CameraRecordingStatusSchema, CameraSourceStatusSchema, CameraSourceStreamSchema, CameraStatusSchema, CameraStreamSchema, CameraSwitchAuthoritySchema, CameraSwitchGroupSchema, CameraSwitchIdSchema, CameraSwitchSchema, CameraSwitchUnavailableReasonSchema, CandidateQueryFilterSchema, CapScopeSchema, CapabilityBindingsSchema, CarbonMonoxideStatusSchema, ChargingStatus, ClientNetworkStatsSchema, ClimateControlStatusSchema, ClipPlaybackSchema, ClipSchema, ClusterAddonNodeDeploymentSchema, ClusterAddonStatusEntrySchema, CollectionColumnSchema, CollectionIndexSchema, ColorStatusSchema, ConfigEntrySchema, ConfigSectionWithValuesSchema, ConfigTabDeclarationSchema, ConnectivityStatusSchema, ConsumableItemSchema, ConsumablesStatusSchema, ContactStatusSchema, ControlKindSchema, ControlStatusSchema, ConvertArtifactSchema, ConvertResultSchema, ConvertTargetSchema, CoreBlockCompileResultSchema, CoreBlockInputSchema, CoreBlockPlacementSchema, CoreBlockSchema, CoreBlockStatusSchema, CoverStateSchema, CoverStatusSchema, CreateApiKeyInputSchema, CreateApiKeyResultSchema, CreateIntegrationInputSchema, CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, CreateUserInputSchema, CustomActionInputSchema, CustomModelDescriptorSchema, DATAPLANE_SECRET_HEADER, DEFAULT_ADDON_PLACEMENT, DEFAULT_AUDIO_ANALYZER_CONFIG, DEFAULT_DECODER_HWACCEL_CONFIG, DEFAULT_DETAIL_CROP_CONVENTION, DEFAULT_EVENT_COLOR, DEFAULT_FEATURES, DEFAULT_NATIVE_LEASE_SETTINGS, DEFAULT_RETENTION, DEFAULT_SCRUB_THUMBNAIL_PRESET, DETAIL_CROP_PADDING_FIELD, DETAIL_CROP_PADDING_KEY, DETAIL_CROP_SECTION_ID, DETAIL_CROP_SQUARE_KEY, DETECTION_PIPELINE_CAP_NAME, DEVICE_BACKEND_TO_FORMAT, DEVICE_CAP_NAMES, DEVICE_PROFILES, DEVICE_SCOPED_CAPS, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATE_READERS, DEVICE_STATUS_METHOD, DEVICE_TYPE_CONTROL_KIND, DEVICE_TYPE_INFO, EngineInfoSchema as DataStoreEngineInfoSchema, DayNightModeSchema, DayNightOptionsSchema, DayNightSettingsPatchSchema, DayNightStatusSchema, DecodedAudioChunkSchema, DecodedFrameSchema, DecoderSessionConfigSchema, DecoderStatsSchema, DeleteIntegrationResultSchema, DetailCropConventionSchema, DetectionSourceSchema, DeviceCodeSeveritySchema, DeviceConfig, DeviceDiscoveryStatusSchema, ExposeInputSchema as DeviceExportExposeInputSchema, DeviceExportStatusSchema, UnexposeInputSchema as DeviceExportUnexposeInputSchema, DeviceFeature, DeviceInfoSchema, DeviceLinkModeSchema, DeviceNetworkStatsSchema, DeviceRole, DeviceRuntimeState, DeviceStatusSchema, DeviceType, DiscoveredChildDeviceSchema, DiscoveredChildStatusSchema, DiscoveredDeviceSchema, DiscoveredTargetSchema, DisposerChain, DoorbellPressEventSchema, DoorbellStatusSchema, EVENTFUL_CAP_NAMES, EVENT_KIND_BY_CAP, EVENT_PAD_MS, EVENT_TAXONOMY, EXPRESSION_BUILTINS, EXPRESSION_BUILTIN_NAMES, EXPRESSION_COMPILE_CACHE_CAPACITY, EXPRESSION_IDENTIFIER_RE, EXPRESSION_INJECTED_NOW, EgressEncodeSchema, EgressRateControlSchema, EgressTranscodeRequestSchema, EgressTranscodeSchema, ElementConfigStore, EmbeddingInfoSchema, EmbeddingResultSchema, EncodeProfileSchema, EncodedPacketSchema, EnrichedWidgetMetadataSchema, EnumSensorDateTimeFormatSchema, EnumSensorStatusSchema, EventCategory, EventEmitterStatusSchema, EventFireSchema, EventItemSchema, EventKindCategorySchema, EventKindDescriptorSchema, EventKindIconSchema, EventKindSchema, EventKindsForDeviceSchema, EventSourceType, ExportDownloadSchema, ExportOptionsSchema, ExportRecordSchema, ExportSetupFieldSchema, ExportSetupSchema, ExportSpeedSchema, ExportStateSchema, ExportTimelapseSchema, ExposedDeviceSchema, ExposureModeSchema, ExpressionEvalError, ExpressionParseError, FanControlStatusSchema, FanDirectionSchema, FeatureManifestSchema, FeatureProbeStatusSchema, FloodStatusSchema, Fmp4BoxSplitter, FrameHandleFormatSchema, FrameHandleSchema, FrameInputSchema, GasStatusSchema, GetStreamWithCodecInputSchema, GlobalMetricsSchema, HAP_AUDIO_BASE, HAP_AUDIO_BITRATE_KBPS, HAP_AUDIO_VBV_KBITS, HAP_KEYFRAME_INTERVAL_SEC, HF_BASE_URL, HF_REPO, HWACCEL_OPTIONS, HealthStatusSchema, HistoryPointSchema, HistoryResolutionEnum, HumidifierStatusSchema, HumiditySensorStatusSchema, HvacModeSchema, ImageContractSchema, ImageContractStateSchema, ImageRotateSchema, ImageSettingsOptionsSchema, ImageSettingsPatchSchema, ImageSettingsStatusSchema, ImageStatusSchema, IngestOwnerSchema, InstalledPackageSchema, IntegrationLiteSchema, IntegrationWithStateSchema, IntercomAbilitySchema, IntercomStatusSchema, KNOWN_CAP_NAMES, KeyEventSchema, LOG_LEVEL_RANK, LabelDefinitionSchema, LawnMowerActivitySchema, LawnMowerControlStatusSchema, LinkedDeviceSchema, LlmDefaultSchema, LlmDefaultSelectorSchema, LlmErrorCodeSchema, LlmGenerateBaseInputSchema, LlmGenerateErrSchema, LlmGenerateOkSchema, LlmGenerateResultSchema, LlmImageSchema, LlmNodeModelSchema, LlmProfileKindDescriptorSchema, LlmProfileKindSchema, LlmProfileSchema, LlmRuntimeCompleteInputSchema, LlmRuntimeDiskUsageSchema, LlmRuntimeNodeSchema, LlmRuntimeStatusSchema, LlmUsageRollupSchema, LlmUsageSchema, LocateSegmentResultSchema, LocationStatSchema, LockControlStatusSchema, LockStateSchema, LogEntrySchema, LogLevelSchema, LogStreamEntrySchema, LoginMethodContributionSchema, LoginStageEnum, MACRO_LABELS, MAX_EXPRESSION_AST_NODES, MAX_EXPRESSION_BINDINGS, MAX_EXPRESSION_CALL_ARGS, MAX_EXPRESSION_EVAL_STEPS, MAX_EXPRESSION_SOURCE_LENGTH, METHOD_ACCESS_MAP, MODEL_FORMATS, MOTION_TRIGGER_FEATURE, ManagedModelCatalogEntrySchema, ManagedModelRefSchema, ManagedRuntimeConfigSchema, MaskGridDimsSchema, MaskGridShapeSchema, MaskLineShapeSchema, MaskPointSchema, MaskPolygonShapeSchema, MaskPolygonVerticesSchema, MaskRectShapeSchema, MaskShapeKindSchema, MaskShapeSchema, MediaFileInfoSchema, MediaFileSchema, MediaPlayerRepeatSchema, MediaPlayerStateSchema, MediaPlayerStatusSchema, MeshPeerSchema, MeshStatusSchema, MethodAccessSchema, ModelCatalogEntrySchema, ModelConvertInputSchema, ModelConvertMetadataSchema, ModelDistributeInputSchema, ModelDistributeResultSchema, ModelExtraFileSchema, ModelFormatEntrySchema, ModelFormatsSchema, ModelSubstitutionSchema, ModelVariantGroupSchema, MotionAnalysisResultSchema, MotionEventSchema, MotionOnMotionChangedDataSchema, MotionRegionSchema, MotionSourceEnum, MotionSourcesSchema, MotionStatusSchema, MotionTriggerRuntimeStateSchema, MotionTriggerStatusSchema, MotionZoneOptionsSchema, MotionZonePatchSchema, MotionZoneRegionSchema, MotionZoneStatusSchema, StatusSchema as MqttBrokerStatusSchema, MutationFilterSchema, NATIVE_LEASE_ACTIVITY_FIELD, NATIVE_LEASE_ACTIVITY_KEY, NATIVE_LEASE_ADMISSION_FIELD, NATIVE_LEASE_ADMISSION_KEY, NATIVE_LEASE_BUDGET_FIELD, NATIVE_LEASE_BUDGET_KEY, NATIVE_LEASE_SECTION_ID, NATIVE_LEASE_TTL_FIELD, NATIVE_LEASE_TTL_KEY, NC_BASE_CONDITION_KEYS, NC_CONDITION_CATALOG, NC_HISTORY_LIMIT_DEFAULT, NC_HISTORY_LIMIT_MAX, NC_MAX_PER_TRACK_IMMEDIATE, NC_SNOOZE_MAX_MINUTES, NC_TAXONOMY, NativeCropBboxSchema, NativeCropRefSchema, NativeCropResultSchema, NativeDetectionSchema, NativeLeaseAdmissionSchema, NativeLeaseSettingsSchema, NativeObjectClassEnum, NativeObjectDetectionRuntimeStateSchema, NativeObjectDetectionStatusSchema, NcAlarmConfigSchema, NcAlarmModeCoverageSchema, NcAlarmSettingsPatchSchema, NcAlarmSettingsSchema, NcConditionDescriptorSchema, NcConditionsSchema, NcCrossingSchema, NcDeliverySchema, NcDeviceStateConditionSchema, NcHistoryEntrySchema, NcHistoryFilterSchema, NcHistoryRecordKindSchema, NcHistoryStatusSchema, NcHistorySubjectSchema, NcMediaFrameSchema, NcMediaPolicySchema, NcOccupancyConditionSchema, NcPlateMatcherSchema, NcRuleActionSchema, NcRuleActionSequenceSchema, NcRuleActionsSchema, NcRuleInputSchema, NcRuleNotificationButtonSchema, NcRulePatchSchema, NcRuleSchema, NcRuleTargetSchema, NcScheduleSchema, NcScheduleWindowSchema, NcSnoozeInputSchema, NcSnoozeSchema, NcSnoozeScopeSchema, NcSnoozeSuppressedSchema, NcTaxonomyEntrySchema, NcTaxonomySchema, NcTestResultSchema, NcThrottleGranularitySchema, NcThrottleSchema, NcZoneConditionSchema, NetworkAccessStatusSchema, NetworkAddressSchema, NetworkEndpointSchema, NotificationActionIconSchema, NotificationActionSchema, NotificationFormatSchema, NotificationSchema, NotifierStatusSchema, NumericSensorStatusSchema, OPS_LOG_DEFAULT_LIMIT, OPS_LOG_RING_DEFAULT_MAX, OauthIntegrationDescriptorSchema, ObjectEventSchema, OpsLogDomainSchema, OpsLogEntrySchema, OpsLogOpSchema, OpsLogQueryInputSchema, OpsLogReasonSchema, OrchestratorMetricsSchema, OsdOverlayKindEnum, OsdOverlayPatchSchema, OsdOverlaySchema, OsdPositionEnum, OsdRenderOutcomeEnum, OsdRenderResultSchema, OsdSlotBindingSchema, OsdSlotViewSchema, OsdSourceOptionSchema, OsdSourceSchema, OsdSourceValueTypeEnum, OsdStatusSchema, PET_FEEDER_MANUAL_FEED_MAX, PET_FEEDER_MANUAL_FEED_MIN, PIPELINE_FLOW_CAPABILITY_NAMES, PIPELINE_OWNER_CAPABILITY_NAMES, PRIVACY_MASK_CAP_NAME, PROVIDER_KIND_CAP_NAMES, PYTHON_SCRIPT, PackageUpdateSchema, PackageVersionInfoSchema, PasskeyLoginMethodSchema, PasskeySummarySchema, PcmSampleFormatSchema, PerScopeBreakdownSchema, PetFeederStatusSchema, PickStreamPreferencesSchema, PickStreamRequirementsSchema, PickedCamStreamSchema, PipelineAssignmentSchema, PipelineDefaultStepSchema, PipelineEngineChoiceSchema, PipelineRunResultBridge, PipelineStepInputSchema, PipelineValidationIssueSchema, PipelineValidationResultSchema, PlaceholderReasonSchema, PolygonPointSchema, PowerMeterStatusSchema, PresenceStatusSchema, PressureSensorStatusSchema, PrivacyMaskOptionsSchema, PrivacyMaskPatchSchema, PrivacyMaskRegionSchema, PrivacyMaskShapeSchema, PrivacyMaskStatusSchema, ProfileRtspEntrySchema, ProfileSlotSchema, ProfileSlotStatusSchema, ProviderStatusSchema, PtzAutotrackRuntimeStateSchema, PtzAutotrackSettingsSchema, PtzAutotrackStatusSchema, PtzAutotrackTargetOptionSchema, PtzMoveCommandSchema, PtzOptionsSchema, PtzPositionSchema, PtzPresetSchema, PtzStatusSchema, QueryFilterSchema, RATE_CONTROL_RELAXED, RATE_CONTROL_TIGHT, REACHABILITY_FAILURES_TO_OFFLINE, REACHABILITY_POLL_INTERVAL_MS, REACHABILITY_PROBE_TIMEOUT_MS, RECOGNITION_TYPES, RESERVED_BINDING_NAMES, RUNTIME_DEFAULTS, RUNTIME_TO_FORMAT, RawStateResultSchema, ReadGopBytesResultSchema, ReadSegmentBytesResultSchema, ReadinessRegistry, ReadinessTimeoutError, RecentTracksPageSchema, RecentTracksQueryInput, RecordingAvailabilitySchema, RecordingBandModeSchema, RecordingBandSchema, RecordingBandTriggersSchema, RecordingConfigSchema, RecordingDaysSchema, RecordingDeviceUsageSchema, RecordingLocationUsageSchema, RecordingManifestSchema, RecordingRangeSchema, RecordingRetentionSchema, RecordingStatusSchema, RecordingStorageModeSchema, RecordingStorageUsageSchema, RecordingTriggersSchema, RecordingWeekdaySchema, RedirectLoginMethodSchema, RelocateFootageInputSchema, RelocateJobSchema, RelocateJobStateSchema, RelocateMediaInputSchema, RenderedAsSchema, ReportMotionInputSchema, RetrainStatusSchema, RingBuffer, RtpSourceSchema, RtspRestreamEntrySchema, RunnerCameraConfigSchema, RunnerCameraDeviceUIFields, RunnerFrameSourceSchema, RunnerInferenceDeviceSchema, RunnerLocalLoadSchema, RunnerLocalMetricsSchema, SCOPE_PRESETS, SCRUB_THUMBNAIL_PRESETS, SCRUB_THUMBNAIL_PRESET_LABELS, SCRUB_THUMBNAIL_PRESET_ORDER, SENSOR_FEATURES, SENSOR_MAP, SOURCE_INFO_METADATA_KEY, STREAM_PROFILE_META, STREAM_QUALITY_LABELS, SUB_DETECTION_TYPES, SYSTEM_CAP_NAMES, SceneCheckSchema, SceneConditionSchema, SceneMonitorSchema, SceneMonitorStateSchema, SceneMonitorStatusSchema, SceneReferenceSchema, ScopedTokenSchema, ScopedTokenSummarySchema, ScoredObjectEventSchema, ScriptRunnerStatusSchema, ScrubThumbnailPresetSchema, SearchResultSchema, SendEmailInputSchema, SendEmailResultSchema, SendResultSchema, SensorEventSchema, ServerBootModeSchema, ServerPackageStatusSchema, ServerRollbackInfoSchema, ServerUpdateActionResultSchema, ServerUpdateCheckResultSchema, ServerUpdateStateSchema, SettingsPatchSchema, SettingsRecordSchema, SettingsSchemaWithValuesSchema, SettingsUpdateResultSchema, ShmRingStatsSchema, SmokeStatusSchema, SmtpStatusSchema, SnapshotImageSchema, SourceInfoSchema, SpatialDetectionSchema, SsoBridgeClaimsSchema, StartEmbeddedInputSchema, StationaryObjectSchema, AbortUploadInputSchema as StorageAbortUploadInputSchema, BeginDownloadInputSchema as StorageBeginDownloadInputSchema, BeginDownloadResultSchema as StorageBeginDownloadResultSchema, BeginUploadInputSchema as StorageBeginUploadInputSchema, BeginUploadResultSchema as StorageBeginUploadResultSchema, EndDownloadInputSchema as StorageEndDownloadInputSchema, FinalizeUploadInputSchema as StorageFinalizeUploadInputSchema, StorageLocationDeclarationSchema, StorageLocationRefSchema, StorageLocationSchema, StorageLocationTypeSchema, ProviderInfoSchema as StorageProviderInfoSchema, ReadChunkInputSchema as StorageReadChunkInputSchema, TestLocationResultSchema as StorageTestLocationResultSchema, WriteChunkInputSchema as StorageWriteChunkInputSchema, StreamCodecSchema, StreamFormatSchema, StreamNetworkStatsSchema, StreamParamsOptionsSchema, StreamParamsStatusSchema, StreamProfileConfigSchema, StreamProfileOptionsSchema, StreamProfilePatchSchema, StreamProfileSchema, StreamSourceEntrySchema, StreamSourceSchema, SubscribeAudioChunksInputSchema, SubscribeAudioChunksResultSchema, SubscribeFramesInputSchema, SubscribeFramesResultSchema, SwitchStatusSchema, SystemMetricsSchema, SystemMirror, TAXONOMY_COLORS, TIMEZONES, TRANSCODE_DOWN_MAX_BITRATE_KBPS, TRANSCODE_DOWN_MAX_HEIGHT, TamperStatusSchema, TankStatusSchema, TargetKindCapsSchema, TargetKindLevelSchema, TargetKindSchema, TargetSchema, TemperatureSensorStatusSchema, TerminalProfileInfoSchema, TerminalSessionInfoSchema, TestConnectionResultSchema$1 as TestConnectionResultSchema, TestResultSchema, TimelapseRuleInputSchema, TimelapseRulePatchSchema, TimelapseRuleSchema, TimelapseTemplateSchema, ToastSchema, TokenScopeSchema, TopologyNodeSchema, TopologyProcessSchema, TopologyServiceSchema, TrackCascadeCountsSchema, TrackEnvelopeSchema, TrackFlagsPatchSchema, TrackFlagsSchema, TrackProjectionSchema, TrackSchema, TrackSourceSchema, TrackStateSchema, TrackZoneFilterSchema, TrackedDetectionSchema, TrainingExportDeviceTotalsSchema, TrainingExportSummarySchema, TurnServerSchema, UNIT_TABLE, BrokerInfoSchema$1 as UnifiedBrokerInfoSchema, UnitConversionError, UpdateIntegrationInputSchema, UpdateStatusSchema, UpdateUserInputSchema, UserRecordSchema, UserSummarySchema, VacuumControlStatusSchema, VacuumStateSchema, ValveStateSchema, ValveStatusSchema, VectorDeclareIndexInputSchema, VectorDeleteByFilterInputSchema, VectorDeleteInputSchema, VectorDeleteResultSchema, VectorFilterSchema, VectorGetInputSchema, VectorGetResultSchema, VectorItemSchema, VectorMatchSchema, VectorMetadataSchema, VectorMetricSchema, VectorQueryInputSchema, VectorQueryResultSchema, VectorStatsInputSchema, VectorStatsResultSchema, VectorUpsertInputSchema, VectorUpsertResultSchema, VibrationStatusSchema, VideoEncodeSchema, WEBRTC_EGRESS_PROFILE, WELL_KNOWN_TABS, WELL_KNOWN_TAB_MAP, WaterHeaterStatusSchema, WeatherStatusSchema, WebrtcStreamChoiceSchema, WebrtcStreamTargetSchema, WhiteBalanceModeSchema, WidgetHostEnum, WidgetLoginMethodSchema, WidgetMetadataSchema, WidgetRemoteSchema, WidgetSizeEnum, YAMNET_TO_MACRO, ZoneCrossingDirectionSchema, ZoneCrossingSchema, ZoneKindEnum, ZoneRuleModeEnum, ZoneRuleSchema, ZoneRuleStageEnum, ZoneRulesArraySchema, ZoneSchema, ZoneScopeBreakdownSchema, accessoriesCapability, accessoryStableId, addonPagesCapability, addonPagesSourceCapability, addonRoutesCapability, addonSettingsCapability, addonWidgetsCapability, addonWidgetsSourceCapability, addonsCapability, adminUiCapability, airQualitySensorCapability, alarmPanelCapability, alertsCapability, ambientLightSensorCapability, applyTransform, asBoolean, asJsonArray, asJsonObject, asNumber, asString, audioAnalysisCapability, audioAnalyzerCapability, audioCodecCapability, audioMetricsCapability, audioPlanFromEncodeProfile, authProviderCapability, autoAssignProfiles, automationControlCapability, backupCapability, bareAddonId, batteryCapability, bestLocationMatch, binaryCapability, bindAddonActions, brightnessCapability, brokerCapability, buildAddonRouteProvider, buildAudioArgs, buildEventKindDescriptor, buildFfmpegArgs, buildInputArgs, buildModelVariantGroups, buildNcTaxonomy, buildStreamParamsConfigSchema, buildVideoArgs, buttonCapability, cameraCredentialsCapability, cameraPipelineConfigCapability, cameraStreamsCapability, canConvertUnit, canonicalEgressPlan, carbonMonoxideCapability, cellsToRects, classifyStream, classifyStreams, climateControlCapability, collectHydratedFieldEntries, collectHydratedFieldValues, colorCapability, colorForKind, compileExpression, compileExpressionSafe, connectivityCapability, consumablesCapability, contactCapability, controlCapability, convertUnit, coreBlocksCapability, cosineSimilarity, coverCapability, createDeviceProxy, createDurableState, createEvent, createExpressionScope, createHwAccelCache, createLazyTrpcSource, createMirrorSource, createRuntimeStateBridge, createSliceHandle, createSystemProxy, customAction, customModelRegistryCapability, dataStoreProviderCapability, dayNightCapability, decodeVectorBase64, decoderCapability, defaultDeviceFor, defineCustomActions, deriveCameraSwitches, deriveDetailCropRect, deriveRecordingMode, describeModelVariant, detectionPipelineCapability, deviceAdoptionCapability, deviceBackendToFormat, deviceCustomAction, deviceDiscoveryCapability, deviceExportCapability, deviceManagerCapability, deviceMatchesProfile, deviceOpsCapability, deviceProviderCapability, deviceStateCapability, deviceStatusCapability, doorbellCapability, egressTranscodeSharingKey, egressTransportFromRequest, embeddingEncoderCapability, emitDownForOwnedCaps, emitReadiness, encodeProfileFromStreamShape, encodeVectorBase64, enumSensorCapability, enumerateInferenceDevices, enumerateItemArrayFields, enumerateSchemaFields, errMsg, evaluateAst, evaluateLinkExpression, evaluateZoneRules, event, eventEmitterCapability, eventsCapability, expandCapMethods, extractNestedAddonId, extractSourceInfoFromMetadata, faceGalleryCapability, fanControlCapability, featureProbeCapability, filesystemBrowseCapability, findTimezone, floodCapability, formatForBackend, formatForRuntime, gasCapability, getAudioMacroClassIds, getByPath, getCapsByProviderKind, getTaxonomyEntry, hasMotionTrigger, hfModelUrl, htmlToText, humidifierCapability, humiditySensorCapability, hydrateSchema, imageCapability, imageSettingsCapability, integrationsCapability, intercomCapability, invocationFromEncodeProfile, isAgentOnlyPlacement, isArrayOutputSchema, isBaseConditionKey, isCollectionArrayMethod, isDeployableToAgent, isDeviceConfigCap, isDeviceScopedCap, isEvent, isNode, isObjectInput, isSameAddonId, isScheduleActive, isSoftwareDecode, isVoidInput, jobKindSchema, kebabToCamel, knownValues, lawnMowerControlCapability, lifecycleJobSchema, lifecycleJobScopeSchema, lifecycleJobStateSchema, lifecycleTaskSchema, llmCapability, llmRuntimeCapability, localNetworkCapability, locationSimilarity, lockControlCapability, logBannerArgs, logDestinationCapability, logLevelAtMost, loginMethodCapability, looseSchema, makeProfileBrokerId, makeSourceBrokerId, mapAudioLabelToMacro, markdownToHtmlLite, markdownToText, maskUrlCredentials, mediaPlayerCapability, mergeSourceInfo, meshNetworkCapability, method, metricsProviderCapability, modelConvertCapability, modelDistributorCapability, modelFormatForRuntime, motionCapability, motionDetectionCapability, motionTriggerCapability, motionZonesCapability, mqttBrokerCapability, nativeObjectDetectionCapability, networkAccessCapability, networkQualityCapability, nodePin, nodesCapability, normalizeAddonInitResult, normalizeUnit, notificationOutputCapability, notificationRulesCapability, notifierCapability, numericSensorCapability, oauthIntegrationCapability, objectInputDeclaresAddonId, osdCapability, osdManagerCapability, parseCameraStreamConfig, parseExpression, parseJsonArray, parseJsonObject, parseJsonUnknown, parseProfileBrokerId, parseStreamParamsFormPatch, petFeederCapability, pickAccessoryControl, pickDetailCropConvention, pickNativeLeaseOverride, pickPreferredRtspEntry, pickVideoEncoder, pickerForCondition, pipelineAnalyticsCapability, pipelineExecutorCapability, pipelineOrchestratorCapability, pipelineRunnerCapability, plateGalleryCapability, platformProbeCapability, powerMeterCapability, prepareNotification, presenceCapability, pressureSensorCapability, privacyMaskCapability, procedureAuthKey, ptzAutotrackCapability, ptzCapability, pythonScriptForBackend, readDetailCropConvention, readDeviceStateFrom, readNativeLeaseOverride, readNodePin, readinessKey, rebootCapability, recordingCapability, recordingExportCapability, rectsToCells, requiresPython, resolveAddonExecution, resolveAddonGroup, resolveAddonPlacement, resolveAddonRuntime, resolveCapMount, resolveDetectionRuntime, resolveDeviceControlKind, resolveDeviceProfile, resolveEgressDecodeHwAccel, resolveFormat, resolveHydratedFieldValue, resolveModelFormat, resolveMutate, resolveRunnerId, resolveScrubThumbnailGeometry, resolveVariantModelId, runInferenceStep, runtimeDevices, sceneMonitorCapability, scopeKey, scoreRuntimes, scriptRunnerCapability, selectAssignedProfileSlots, serverManagementCapability, setByPath, settingsStoreCapability, sleep, sleepCancellable, smokeCapability, smtpProviderCapability, snapshotCapability, ssoBridgeCapability, startReachabilityPoll, stateVocabularyFor, storageCapability, storageEvictableCapability, storageProviderCapability, streamBrokerCapability, streamCatalogCapability, streamParamsCapability, streamPixels, streamQualityLabel, subKindsOf, summarisePrivacyAudio, supportedRuntimes, switchCapability, switchedOffIds, synthesizeSourceInfo, systemCapability, tamperCapability, taskLogEntrySchema, taskPhaseSchema, taskTargetSchema, temperatureSensorCapability, terminalSessionCapability, textToHtml, toDeviceSummary, toExpressionValue, toNodeId, toStreamSourceEntry, toastCapability, tokenize, transcodeBody, tryConvertUnit, turnProviderCapability, unitDimension, unitsForDimension, updateCapability, userManagementCapability, userPasskeysCapability, vacuumControlCapability, validateExpressionSource, valveCapability, vectorDimFromBase64, vectorStoreCapability, vibrationCapability, videoclipsCapability, viewerUiCapability, waterHeaterCapability, weatherCapability, webrtcClientHintsSchema, webrtcSessionCapability, wiringAddonHealthSchema, wiringHealthSnapshotSchema, wiringNodeHealthSchema, wiringProbeKindSchema, wiringProbeResultSchema, zodEntriesToConfigUI, zoneAnalyticsCapability, zoneRulesCapability, zonesCapability };
|