@camstack/types 1.2.40 → 1.2.42
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 +1 -1
- package/dist/addon.mjs +1 -1
- package/dist/canonical-hash-7nfBbEqR.mjs +35 -0
- package/dist/canonical-hash-BcZHRHIx.js +40 -0
- package/dist/capabilities/index.d.ts +2 -2
- package/dist/capabilities/notification-rules.cap.d.ts +41 -0
- package/dist/capabilities/pipeline-analytics.cap.d.ts +93 -6
- package/dist/capabilities/pipeline-orchestrator.cap.d.ts +123 -0
- package/dist/capabilities/pipeline-runner.cap.d.ts +143 -7
- package/dist/capabilities/platform-probe.cap.d.ts +3 -3
- package/dist/capabilities/recording.cap.d.ts +3 -0
- package/dist/capabilities/stream-broker.cap.d.ts +300 -0
- package/dist/encode-profile.d.ts +2 -0
- package/dist/ffmpeg/encode-defaults.d.ts +89 -0
- package/dist/ffmpeg/hwaccel.d.ts +98 -0
- package/dist/ffmpeg/invocation.d.ts +250 -0
- package/dist/ffmpeg/process.d.ts +135 -0
- package/dist/ffmpeg/sharing-key.d.ts +39 -0
- package/dist/generated/addon-api.d.ts +56 -0
- package/dist/generated/device-proxy.d.ts +1 -1
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/system-proxy.d.ts +2 -2
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1595 -28
- package/dist/index.mjs +1548 -29
- package/dist/interfaces/camera-switches.d.ts +217 -0
- package/dist/interfaces/ops-log.d.ts +4 -0
- package/dist/interfaces/pipeline-runner-capability.d.ts +9 -1
- package/dist/node.d.ts +2 -0
- package/dist/node.js +270 -36
- package/dist/node.mjs +269 -36
- package/dist/pipeline/detail-crop.d.ts +122 -0
- package/dist/{sleep-CXimb854.mjs → sleep-BmNKsY7v.mjs} +5 -0
- package/dist/{sleep-DTce7-ch.js → sleep-Cvi1JxZp.js} +5 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { t as EventCategory } from "./event-category-41fKf-q9.mjs";
|
|
2
|
-
import { $ as ProfileRtspEntrySchema, A as method, B as scopeKey, C as DeviceType, Ct as collectHydratedFieldValues, D as event, E as DEVICE_STATUS_METHOD, F as readNodePin, G as CamStreamKindSchema, H as BrokerStatusSchema, I as ReadinessRegistry, J as DecodedAudioChunkSchema, K as CamStreamResolutionSchema, L as ReadinessTimeoutError, M as systemMethod, N as CAP_NODE_PIN_CONTEXT_KEY, O as expandCapMethods, P as nodePin, Q as FrameHandleSchema, R as emitDownForOwnedCaps, S as DeviceRole, St as collectHydratedFieldEntries, T as DEVICE_SETTINGS_CONTRIBUTION_METHODS, Tt as resolveHydratedFieldValue, U as CAM_PROFILE_ORDER, V as BrokerStatsSchema, W as CamProfileSchema, X as EncodedPacketSchema, Y as DecodedFrameSchema, Z as FrameHandleFormatSchema, _ as RawStateResultSchema, _t as createEvent, a as asJsonObject, at as SubscribeAudioChunksResultSchema, b as ChargingStatus, bt as WELL_KNOWN_TABS, c as parseJsonArray, ct as makeProfileBrokerId, d as DEVICE_SCOPED_CAPS, dt as selectAssignedProfileSlots, et as ProfileSlotSchema, f as isDeviceScopedCap, ft as DATAPLANE_SECRET_HEADER, g as createSliceHandle, gt as createDurableState, h as createMirrorSource, ht as normalizeAddonInitResult, i as asJsonArray, it as SubscribeAudioChunksInputSchema, j as resolveCapMount, k as isDeviceConfigCap, l as parseJsonObject, lt as makeSourceBrokerId, m as createLazyTrpcSource, mt as BaseAddon, n as sleepCancellable, nt as StreamSourceEntrySchema, o as asNumber, ot as SubscribeFramesInputSchema, p as createDeviceProxy, pt as DisposerChain, q as CameraStreamSchema, r as asBoolean, rt as StreamSourceSchema, s as asString, st as SubscribeFramesResultSchema, t as sleep, tt as ProfileSlotStatusSchema, u as parseJsonUnknown, ut as parseProfileBrokerId, v as deviceOpsCapability, vt as emitReadiness, w as adminUiCapability, wt as hydrateSchema, x as DeviceFeature, xt as WELL_KNOWN_TAB_MAP, y as viewerUiCapability, yt as isEvent, z as readinessKey } from "./sleep-
|
|
2
|
+
import { $ as ProfileRtspEntrySchema, A as method, B as scopeKey, C as DeviceType, Ct as collectHydratedFieldValues, D as event, E as DEVICE_STATUS_METHOD, F as readNodePin, G as CamStreamKindSchema, H as BrokerStatusSchema, I as ReadinessRegistry, J as DecodedAudioChunkSchema, K as CamStreamResolutionSchema, L as ReadinessTimeoutError, M as systemMethod, N as CAP_NODE_PIN_CONTEXT_KEY, O as expandCapMethods, P as nodePin, Q as FrameHandleSchema, R as emitDownForOwnedCaps, S as DeviceRole, St as collectHydratedFieldEntries, T as DEVICE_SETTINGS_CONTRIBUTION_METHODS, Tt as resolveHydratedFieldValue, U as CAM_PROFILE_ORDER, V as BrokerStatsSchema, W as CamProfileSchema, X as EncodedPacketSchema, Y as DecodedFrameSchema, Z as FrameHandleFormatSchema, _ as RawStateResultSchema, _t as createEvent, a as asJsonObject, at as SubscribeAudioChunksResultSchema, b as ChargingStatus, bt as WELL_KNOWN_TABS, c as parseJsonArray, ct as makeProfileBrokerId, d as DEVICE_SCOPED_CAPS, dt as selectAssignedProfileSlots, et as ProfileSlotSchema, f as isDeviceScopedCap, ft as DATAPLANE_SECRET_HEADER, g as createSliceHandle, gt as createDurableState, h as createMirrorSource, ht as normalizeAddonInitResult, i as asJsonArray, it as SubscribeAudioChunksInputSchema, j as resolveCapMount, k as isDeviceConfigCap, l as parseJsonObject, lt as makeSourceBrokerId, m as createLazyTrpcSource, mt as BaseAddon, n as sleepCancellable, nt as StreamSourceEntrySchema, o as asNumber, ot as SubscribeFramesInputSchema, p as createDeviceProxy, pt as DisposerChain, q as CameraStreamSchema, r as asBoolean, rt as StreamSourceSchema, s as asString, st as SubscribeFramesResultSchema, t as sleep, tt as ProfileSlotStatusSchema, u as parseJsonUnknown, ut as parseProfileBrokerId, v as deviceOpsCapability, vt as emitReadiness, w as adminUiCapability, wt as hydrateSchema, x as DeviceFeature, xt as WELL_KNOWN_TAB_MAP, y as viewerUiCapability, yt as isEvent, z as readinessKey } from "./sleep-BmNKsY7v.mjs";
|
|
3
|
+
import { t as canonicalHash } from "./canonical-hash-7nfBbEqR.mjs";
|
|
3
4
|
import { EventSourceType } from "./enums.mjs";
|
|
4
5
|
import { t as errMsg } from "./err-msg-IQTHeDzc.mjs";
|
|
5
6
|
import { z } from "zod";
|
|
@@ -146,6 +147,14 @@ var VideoEncodeSchema = z.object({
|
|
|
146
147
|
"main",
|
|
147
148
|
"high"
|
|
148
149
|
]).optional(),
|
|
150
|
+
/**
|
|
151
|
+
* `-level`, e.g. `'3.1'`. A consumer that ADVERTISES a level in its SDP
|
|
152
|
+
* (`profile-level-id=42e01f` is Baseline 3.1) must constrain the encoder to
|
|
153
|
+
* it, or it ships a stream that does not match its own advertisement — the
|
|
154
|
+
* defect class that kept HomeKit black for a year and that Alexa carried
|
|
155
|
+
* silently. Optional because a browser negotiates the level itself.
|
|
156
|
+
*/
|
|
157
|
+
level: z.string().optional(),
|
|
149
158
|
width: z.number().int().positive().optional(),
|
|
150
159
|
height: z.number().int().positive().optional(),
|
|
151
160
|
fps: z.number().positive().optional(),
|
|
@@ -221,6 +230,560 @@ function encodeProfileFromStreamShape(stream) {
|
|
|
221
230
|
};
|
|
222
231
|
}
|
|
223
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
|
+
//#region src/ffmpeg/encode-defaults.ts
|
|
563
|
+
/**
|
|
564
|
+
* The shape every live egress starts from: H.264 Baseline 3.1 at 720p25.
|
|
565
|
+
* Baseline because it is the one profile every consumer in this repo decodes
|
|
566
|
+
* (Echo, iOS, an old browser); 3.1 because that is what the SDPs advertise.
|
|
567
|
+
*/
|
|
568
|
+
var BASE_LIVE_EGRESS_PROFILE = {
|
|
569
|
+
video: {
|
|
570
|
+
codec: "h264",
|
|
571
|
+
profile: "baseline",
|
|
572
|
+
level: "3.1",
|
|
573
|
+
width: 1280,
|
|
574
|
+
height: 720,
|
|
575
|
+
fps: 25,
|
|
576
|
+
bitrateKbps: 2500,
|
|
577
|
+
gopFrames: 25,
|
|
578
|
+
bf: 0,
|
|
579
|
+
preset: "veryfast",
|
|
580
|
+
tune: "zerolatency"
|
|
581
|
+
},
|
|
582
|
+
audio: "passthrough"
|
|
583
|
+
};
|
|
584
|
+
/**
|
|
585
|
+
* The browser WebRTC viewer's transcode profile. Used only when the broker
|
|
586
|
+
* MUST spawn ffmpeg (source codec ∉ the browser-accepted set — an H.265 source
|
|
587
|
+
* on an H.264-only browser). Audio is `passthrough` because werift carries the
|
|
588
|
+
* audio plane out-of-band; putting it in the video pipeline would encode a
|
|
589
|
+
* track nothing reads.
|
|
590
|
+
*/
|
|
591
|
+
var WEBRTC_EGRESS_PROFILE = {
|
|
592
|
+
...BASE_LIVE_EGRESS_PROFILE,
|
|
593
|
+
video: {
|
|
594
|
+
...BASE_LIVE_EGRESS_PROFILE.video,
|
|
595
|
+
bitrateKbps: 3e3,
|
|
596
|
+
gopFrames: 30,
|
|
597
|
+
preset: "ultrafast"
|
|
598
|
+
},
|
|
599
|
+
audio: "passthrough"
|
|
600
|
+
};
|
|
601
|
+
/**
|
|
602
|
+
* Alexa's egress profile. Alexa's audio ALSO rides the WebRTC session's own
|
|
603
|
+
* audio plane (out-of-band), so this is `passthrough` exactly like the browser
|
|
604
|
+
* — see the ADR for why the previous in-band Opus was encoded and discarded.
|
|
605
|
+
*/
|
|
606
|
+
var ALEXA_EGRESS_PROFILE = {
|
|
607
|
+
...BASE_LIVE_EGRESS_PROFILE,
|
|
608
|
+
audio: "passthrough"
|
|
609
|
+
};
|
|
610
|
+
/** VBV window for a consumer whose budget is enforced per second (HomeKit). */
|
|
611
|
+
var RATE_CONTROL_TIGHT = {
|
|
612
|
+
kind: "cbr",
|
|
613
|
+
vbvSeconds: 1
|
|
614
|
+
};
|
|
615
|
+
/** VBV window for a consumer that tolerates a keyframe spike (browser, Echo). */
|
|
616
|
+
var RATE_CONTROL_RELAXED = {
|
|
617
|
+
kind: "cap",
|
|
618
|
+
vbvSeconds: 2
|
|
619
|
+
};
|
|
620
|
+
/**
|
|
621
|
+
* Transcode-DOWN ceiling: the shape a remote/unhealthy WebRTC session is
|
|
622
|
+
* reduced to. 360p / 400 kbps is the `low` rung of the adaptive ladder — a
|
|
623
|
+
* session steered here is already failing, so the ceiling is chosen to survive
|
|
624
|
+
* a bad link, not to look good.
|
|
625
|
+
*/
|
|
626
|
+
var TRANSCODE_DOWN_MAX_HEIGHT = 360;
|
|
627
|
+
var TRANSCODE_DOWN_MAX_BITRATE_KBPS = 400;
|
|
628
|
+
/**
|
|
629
|
+
* HomeKit's two-way audio leg. `lowdelay` + a short frame duration because the
|
|
630
|
+
* leg is interactive; `globalHeader` because HAP owns the SDP and ffmpeg must
|
|
631
|
+
* not put extradata in-band. `sampleRateHz` and `frameDurationMs` are
|
|
632
|
+
* NEGOTIATED per session — the controller picks them — so they are absent here
|
|
633
|
+
* and filled in by the caller.
|
|
634
|
+
*/
|
|
635
|
+
var HAP_AUDIO_BITRATE_KBPS = 24;
|
|
636
|
+
var HAP_AUDIO_BASE = {
|
|
637
|
+
kind: "encode",
|
|
638
|
+
codec: "opus",
|
|
639
|
+
bitrateKbps: 24,
|
|
640
|
+
channels: 1,
|
|
641
|
+
application: "lowdelay",
|
|
642
|
+
globalHeader: true,
|
|
643
|
+
filter: "aresample=async=1000:first_pts=0"
|
|
644
|
+
};
|
|
645
|
+
/** HomeKit's `-bufsize` for the audio plane — four seconds of its 24 kbps. */
|
|
646
|
+
var HAP_AUDIO_VBV_KBITS = 96;
|
|
647
|
+
/** Seconds between forced IDRs on a HomeKit transcode. */
|
|
648
|
+
var HAP_KEYFRAME_INTERVAL_SEC = 4;
|
|
649
|
+
//#endregion
|
|
650
|
+
//#region src/ffmpeg/hwaccel.ts
|
|
651
|
+
function createHwAccelCache(options) {
|
|
652
|
+
const now = options.now ?? (() => Date.now());
|
|
653
|
+
let value = null;
|
|
654
|
+
let writtenAt = Number.NEGATIVE_INFINITY;
|
|
655
|
+
return {
|
|
656
|
+
read() {
|
|
657
|
+
return now() - writtenAt < options.ttlMs ? value : void 0;
|
|
658
|
+
},
|
|
659
|
+
write(next) {
|
|
660
|
+
value = next;
|
|
661
|
+
writtenAt = now();
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
/** `true` when a value means "decode in software". */
|
|
666
|
+
function meansSoftware(value) {
|
|
667
|
+
return !value || value === "none" || value === "copy";
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Resolve the `-hwaccel` value for an egress transcode. Hardware is the
|
|
671
|
+
* DEFAULT — an egress that decodes in software on a hub with working vaapi is
|
|
672
|
+
* paying for nothing — and every software outcome is announced.
|
|
673
|
+
*
|
|
674
|
+
* Returns a concrete backend name, the literal `'auto'`, or `null` for
|
|
675
|
+
* software decode (⇒ {@link buildFfmpegArgs} emits no `-hwaccel` at all).
|
|
676
|
+
*/
|
|
677
|
+
async function resolveEgressDecodeHwAccel(deps) {
|
|
678
|
+
const override = deps.override;
|
|
679
|
+
if (override !== void 0 && override !== null && override !== "") return meansSoftware(override) ? null : override;
|
|
680
|
+
const cached = deps.cache?.read();
|
|
681
|
+
if (cached !== void 0) return cached;
|
|
682
|
+
let backend;
|
|
683
|
+
try {
|
|
684
|
+
backend = await deps.readDecoderBackend();
|
|
685
|
+
} catch (err) {
|
|
686
|
+
const kernelPreferred = await deps.readKernelPreferred().catch(() => []);
|
|
687
|
+
deps.onFallback({
|
|
688
|
+
reason: "decoder-unreadable",
|
|
689
|
+
kernelPreferred,
|
|
690
|
+
error: err instanceof Error ? err.message : String(err)
|
|
691
|
+
});
|
|
692
|
+
deps.cache?.write(null);
|
|
693
|
+
return null;
|
|
694
|
+
}
|
|
695
|
+
if (backend === "") {
|
|
696
|
+
const kernelPreferred = await deps.readKernelPreferred().catch(() => []);
|
|
697
|
+
deps.onFallback({
|
|
698
|
+
reason: "decoder-unprobed",
|
|
699
|
+
kernelPreferred
|
|
700
|
+
});
|
|
701
|
+
deps.cache?.write(null);
|
|
702
|
+
return null;
|
|
703
|
+
}
|
|
704
|
+
const resolved = meansSoftware(backend) ? null : backend;
|
|
705
|
+
deps.cache?.write(resolved);
|
|
706
|
+
return resolved;
|
|
707
|
+
}
|
|
708
|
+
//#endregion
|
|
709
|
+
//#region src/ffmpeg/sharing-key.ts
|
|
710
|
+
/**
|
|
711
|
+
* The sharing key for `streamBroker.acquireEgressTranscode`.
|
|
712
|
+
*
|
|
713
|
+
* **Two requesters asking for exactly the same argument set reach the same
|
|
714
|
+
* process.** Exact match, never fuzzy: a quantised ladder that merged
|
|
715
|
+
* NEARLY-identical requests would make the stream a consumer receives depend
|
|
716
|
+
* on who else is watching and in what order they arrived — unpredictable in
|
|
717
|
+
* precisely the way a debugging session cannot tolerate. Same arguments ⇒ same
|
|
718
|
+
* process. Different arguments ⇒ different process, and that is fine; the
|
|
719
|
+
* operator accepted the cost ("it's fine to have several processes").
|
|
720
|
+
*
|
|
721
|
+
* Derived from the STRUCTURED plan, not from a flag array. `pipelineKeyFor`
|
|
722
|
+
* (`transcode-pipeline.ts`) folds `getStreamWithCodec`'s raw `outputArgs` into
|
|
723
|
+
* its key, so that method's extensibility hatch and its sharing key are the
|
|
724
|
+
* same field — a consumer needing one extra flag silently forks the child, and
|
|
725
|
+
* two consumers that want the same thing but spell it differently never share.
|
|
726
|
+
* Here every knob is a named field, and defaults are APPLIED before hashing so
|
|
727
|
+
* an omitted field and its explicit default land on the same key.
|
|
728
|
+
*/
|
|
729
|
+
/** Absent optional ⇒ this sentinel, so `undefined` and "not set" agree. */
|
|
730
|
+
var UNSET = "\0unset";
|
|
731
|
+
function canonicalVideo(video) {
|
|
732
|
+
return {
|
|
733
|
+
codec: video.codec,
|
|
734
|
+
profile: video.profile ?? UNSET,
|
|
735
|
+
level: video.level ?? UNSET,
|
|
736
|
+
width: video.width ?? -1,
|
|
737
|
+
height: video.height ?? -1,
|
|
738
|
+
fps: video.fps ?? -1,
|
|
739
|
+
bitrateKbps: video.bitrateKbps ?? -1,
|
|
740
|
+
gopFrames: video.gopFrames ?? -1,
|
|
741
|
+
bf: video.bf ?? -1,
|
|
742
|
+
preset: video.preset ?? UNSET,
|
|
743
|
+
tune: video.tune ?? UNSET
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
function canonicalAudio(audio) {
|
|
747
|
+
if (audio === "passthrough") return { codec: "passthrough" };
|
|
748
|
+
return {
|
|
749
|
+
codec: audio.codec,
|
|
750
|
+
bitrateKbps: audio.bitrateKbps ?? -1,
|
|
751
|
+
sampleRateHz: audio.sampleRateHz ?? -1,
|
|
752
|
+
channels: audio.channels ?? -1
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* The normalised plan a key is computed from. Exported so a test — and a
|
|
757
|
+
* future operator-facing "why are these two not sharing?" surface — can diff
|
|
758
|
+
* two requests without reversing a hash.
|
|
759
|
+
*/
|
|
760
|
+
function canonicalEgressPlan(request) {
|
|
761
|
+
return {
|
|
762
|
+
deviceId: request.deviceId,
|
|
763
|
+
source: request.source.kind === "profile" ? `profile:${request.source.profile}` : `cam-stream:${request.source.camStreamId}`,
|
|
764
|
+
video: canonicalVideo(request.encode.video),
|
|
765
|
+
audio: canonicalAudio(request.encode.audio),
|
|
766
|
+
rateControl: request.rateControl ?? "relaxed",
|
|
767
|
+
bitstreamFilter: request.bitstreamFilter ?? UNSET,
|
|
768
|
+
pixelFormat: request.pixelFormat ?? UNSET,
|
|
769
|
+
decodeHwAccel: request.decodeHwAccel ?? UNSET
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* The refcount / dedup key. `canonicalHash` sorts object keys at every depth,
|
|
774
|
+
* so a request built with a different field order produces the same digest.
|
|
775
|
+
*
|
|
776
|
+
* The handle this keys is IMMUTABLE: there is no `reconfigure`. A consumer
|
|
777
|
+
* whose requirements change RELEASES and re-acquires; the refcount does the
|
|
778
|
+
* rest. That is what stops co-tenants disturbing each other — the co-tenant
|
|
779
|
+
* hazard that made Alexa's shared `derived:alexa-<id>` stream a hazard was
|
|
780
|
+
* exactly a mutable shared object, where one consumer's downgrade dragged
|
|
781
|
+
* every other consumer to 360p.
|
|
782
|
+
*/
|
|
783
|
+
function egressTranscodeSharingKey(request) {
|
|
784
|
+
return `egress:${canonicalHash(canonicalEgressPlan(request))}`;
|
|
785
|
+
}
|
|
786
|
+
//#endregion
|
|
224
787
|
//#region src/health/wiring-health.ts
|
|
225
788
|
/**
|
|
226
789
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
@@ -330,6 +893,246 @@ var DEFAULT_RETENTION = {
|
|
|
330
893
|
snapshotsDays: 14
|
|
331
894
|
};
|
|
332
895
|
//#endregion
|
|
896
|
+
//#region src/interfaces/camera-switches.ts
|
|
897
|
+
/**
|
|
898
|
+
* Per-camera FUNCTION SWITCHES — the one coherent on/off surface over the
|
|
899
|
+
* pipeline functions an operator thinks in terms of.
|
|
900
|
+
*
|
|
901
|
+
* ## This file adds no state
|
|
902
|
+
*
|
|
903
|
+
* Every switch here is a VIEW onto an authority that already existed
|
|
904
|
+
* ([D61](../../../../docs/decisions/adr-0062.md)). The whole point of the
|
|
905
|
+
* group is that there is exactly one place each function is turned off, and
|
|
906
|
+
* the group routes to it:
|
|
907
|
+
*
|
|
908
|
+
* | Switch | Authority | Proven "off stops the work" gate |
|
|
909
|
+
* | --- | --- | --- |
|
|
910
|
+
* | `stream-broker` | `deviceManager.setDisabled` | `StreamBrokerManager.reconcileAllCatalogs` releases the brokers; `ensureBroker` refuses re-creation |
|
|
911
|
+
* | `object-detection` | `deviceManager.setWrapperActive('detection-pipeline')` | `PipelineSettingsStore.resolvePipelineForDevice` returns `{ steps: [], audio: null }` |
|
|
912
|
+
* | `audio-analysis` | `deviceManager.setWrapperActive('audio-analysis')` | `AudioSubscriptionController.subscribeAudioStream` returns `null` before opening the stream |
|
|
913
|
+
* | `recording` | `recording.setDeviceConfig` → `RecordingConfig.enabled` | `band-decision.shouldRecord` returns false; the controller detaches the device |
|
|
914
|
+
* | `notifications` | `notificationRules.setDeviceMuted` | `NotificationCenter.evaluateAndEnqueue` returns before any rule is evaluated |
|
|
915
|
+
*
|
|
916
|
+
* The wrapper-binding pair is not a new idea: `legacy-migrations.ts` already
|
|
917
|
+
* migrated the legacy `audioEnabled` / `pipelineEnabled` /
|
|
918
|
+
* `motionDetectionEnabled` booleans ONTO `setWrapperActive`. The group is the
|
|
919
|
+
* surface that decision never got.
|
|
920
|
+
*
|
|
921
|
+
* ## Two rules that are load-bearing
|
|
922
|
+
*
|
|
923
|
+
* - **Recording's switch is `enabled`, never the bands.** `bands` is the only
|
|
924
|
+
* authored intent and `mode` is derived from it (`deriveRecordingMode`).
|
|
925
|
+
* Expressing "off" by clearing bands destroys the operator's schedule and
|
|
926
|
+
* turning the camera back on would then silently record nothing.
|
|
927
|
+
* - **A switch that is off must be reported as off**, not merely produce
|
|
928
|
+
* nothing. {@link CameraSwitch.enabled} is what a status surface renders as
|
|
929
|
+
* "disabled by an operator" instead of "broken" — see
|
|
930
|
+
* `CameraStatus.switchedOff`.
|
|
931
|
+
*/
|
|
932
|
+
/**
|
|
933
|
+
* The five functions the operator named (2026-08-05). Deliberately NOT one id
|
|
934
|
+
* per pipeline step: face recognition and plate/LPR are per-step toggles on
|
|
935
|
+
* `pipelineOrchestrator.setCameraStepToggle` and belong in the pipeline
|
|
936
|
+
* editor, not in a five-button safety group.
|
|
937
|
+
*/
|
|
938
|
+
var CameraSwitchIdSchema = z.enum([
|
|
939
|
+
"stream-broker",
|
|
940
|
+
"object-detection",
|
|
941
|
+
"audio-analysis",
|
|
942
|
+
"recording",
|
|
943
|
+
"notifications"
|
|
944
|
+
]);
|
|
945
|
+
/** Stable render order — broadest blast radius first. */
|
|
946
|
+
var CAMERA_SWITCH_ORDER = [
|
|
947
|
+
"stream-broker",
|
|
948
|
+
"object-detection",
|
|
949
|
+
"audio-analysis",
|
|
950
|
+
"recording",
|
|
951
|
+
"notifications"
|
|
952
|
+
];
|
|
953
|
+
/**
|
|
954
|
+
* WHERE the switch's state actually lives. A discriminated union rather than a
|
|
955
|
+
* string so both the writer (the orchestrator's `setCameraSwitch`) and any
|
|
956
|
+
* reader can exhaustively narrow — and so "the group added a parallel map" is
|
|
957
|
+
* a compile error rather than a review comment.
|
|
958
|
+
*/
|
|
959
|
+
var CameraSwitchAuthoritySchema = z.discriminatedUnion("kind", [
|
|
960
|
+
z.object({ kind: z.literal("device-disabled") }),
|
|
961
|
+
z.object({
|
|
962
|
+
kind: z.literal("wrapper-binding"),
|
|
963
|
+
capName: z.string()
|
|
964
|
+
}),
|
|
965
|
+
z.object({ kind: z.literal("recording-config") }),
|
|
966
|
+
z.object({ kind: z.literal("notification-mute") })
|
|
967
|
+
]);
|
|
968
|
+
/**
|
|
969
|
+
* Why a switch is not offered for this camera. Rendered instead of the
|
|
970
|
+
* control, never as a dead control — an absent function and a broken one must
|
|
971
|
+
* not look the same.
|
|
972
|
+
*/
|
|
973
|
+
var CameraSwitchUnavailableReasonSchema = z.enum(["no-provider", "source-unreachable"]);
|
|
974
|
+
/**
|
|
975
|
+
* One switch, resolved for one camera.
|
|
976
|
+
*
|
|
977
|
+
* `label` and `costWhenOff` travel ON THE WIRE rather than being looked up
|
|
978
|
+
* client-side: the viewer is a separate repository that does not import
|
|
979
|
+
* `@camstack/types`, and a cost line duplicated in two clients is a cost line
|
|
980
|
+
* that will disagree with itself. Five rows per camera is nothing.
|
|
981
|
+
*/
|
|
982
|
+
var CameraSwitchSchema = z.object({
|
|
983
|
+
id: CameraSwitchIdSchema,
|
|
984
|
+
label: z.string(),
|
|
985
|
+
/**
|
|
986
|
+
* What the operator LOSES while this is off, in one sentence. Required, not
|
|
987
|
+
* optional: a switch that cannot say what it costs should not ship.
|
|
988
|
+
*/
|
|
989
|
+
costWhenOff: z.string(),
|
|
990
|
+
/** False = do not render a control. `unavailableReason` says why. */
|
|
991
|
+
available: z.boolean(),
|
|
992
|
+
unavailableReason: CameraSwitchUnavailableReasonSchema.optional(),
|
|
993
|
+
/** Current state. Meaningless when `available` is false — read it as `true`. */
|
|
994
|
+
enabled: z.boolean(),
|
|
995
|
+
authority: CameraSwitchAuthoritySchema
|
|
996
|
+
});
|
|
997
|
+
/** The whole group for one camera. */
|
|
998
|
+
var CameraSwitchGroupSchema = z.object({
|
|
999
|
+
deviceId: z.number().int(),
|
|
1000
|
+
switches: z.array(CameraSwitchSchema).readonly(),
|
|
1001
|
+
/** Unix ms when the group was composed server-side. */
|
|
1002
|
+
fetchedAt: z.number()
|
|
1003
|
+
});
|
|
1004
|
+
/**
|
|
1005
|
+
* The wrapper capability each wrapper-backed switch controls. Named constants
|
|
1006
|
+
* because the same strings appear in `legacy-migrations.ts`, in
|
|
1007
|
+
* `isCapActiveForDevice` call sites and in the fake harness — a typo in any of
|
|
1008
|
+
* them is a switch that silently writes a binding nobody reads.
|
|
1009
|
+
*/
|
|
1010
|
+
var DETECTION_PIPELINE_CAP_NAME = "detection-pipeline";
|
|
1011
|
+
var AUDIO_ANALYSIS_CAP_NAME = "audio-analysis";
|
|
1012
|
+
/**
|
|
1013
|
+
* THE catalog. One entry per switch; the cost lines are the operator-facing
|
|
1014
|
+
* contract and are written to be true rather than reassuring.
|
|
1015
|
+
*/
|
|
1016
|
+
var CAMERA_SWITCH_CATALOG = {
|
|
1017
|
+
"stream-broker": {
|
|
1018
|
+
id: "stream-broker",
|
|
1019
|
+
label: "Camera",
|
|
1020
|
+
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" }
|
|
1022
|
+
},
|
|
1023
|
+
"object-detection": {
|
|
1024
|
+
id: "object-detection",
|
|
1025
|
+
label: "Object detection & tracking",
|
|
1026
|
+
costWhenOff: "Off: nothing is detected or tracked on this camera, so it produces no events — and with no events there are no object notifications and no event-triggered recording. Live view and continuous recording are unaffected.",
|
|
1027
|
+
authority: {
|
|
1028
|
+
kind: "wrapper-binding",
|
|
1029
|
+
capName: DETECTION_PIPELINE_CAP_NAME
|
|
1030
|
+
}
|
|
1031
|
+
},
|
|
1032
|
+
"audio-analysis": {
|
|
1033
|
+
id: "audio-analysis",
|
|
1034
|
+
label: "Audio detection & classification",
|
|
1035
|
+
costWhenOff: "Off: no audio is decoded or classified for this camera. Tracks carry no audio labels and no audio-triggered rule can fire. Audio recorded alongside video is unaffected.",
|
|
1036
|
+
authority: {
|
|
1037
|
+
kind: "wrapper-binding",
|
|
1038
|
+
capName: AUDIO_ANALYSIS_CAP_NAME
|
|
1039
|
+
}
|
|
1040
|
+
},
|
|
1041
|
+
recording: {
|
|
1042
|
+
id: "recording",
|
|
1043
|
+
label: "Recording",
|
|
1044
|
+
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" }
|
|
1046
|
+
},
|
|
1047
|
+
notifications: {
|
|
1048
|
+
id: "notifications",
|
|
1049
|
+
label: "Notifications",
|
|
1050
|
+
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" }
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
/** Resolve one switch's `{ available, enabled }` pair. */
|
|
1055
|
+
function resolveState(descriptor, input) {
|
|
1056
|
+
switch (descriptor.authority.kind) {
|
|
1057
|
+
case "device-disabled": return {
|
|
1058
|
+
available: true,
|
|
1059
|
+
enabled: !input.deviceDisabled
|
|
1060
|
+
};
|
|
1061
|
+
case "wrapper-binding": {
|
|
1062
|
+
const capName = descriptor.authority.capName;
|
|
1063
|
+
if (input.bindableCapNames === null || input.activeWrapperCapNames === null) return {
|
|
1064
|
+
available: false,
|
|
1065
|
+
enabled: true,
|
|
1066
|
+
unavailableReason: "source-unreachable"
|
|
1067
|
+
};
|
|
1068
|
+
if (!input.bindableCapNames.includes(capName)) return {
|
|
1069
|
+
available: false,
|
|
1070
|
+
enabled: true,
|
|
1071
|
+
unavailableReason: "no-provider"
|
|
1072
|
+
};
|
|
1073
|
+
return {
|
|
1074
|
+
available: true,
|
|
1075
|
+
enabled: input.activeWrapperCapNames.includes(capName)
|
|
1076
|
+
};
|
|
1077
|
+
}
|
|
1078
|
+
case "recording-config":
|
|
1079
|
+
if (input.recordingEnabled === null) return {
|
|
1080
|
+
available: false,
|
|
1081
|
+
enabled: true,
|
|
1082
|
+
unavailableReason: "source-unreachable"
|
|
1083
|
+
};
|
|
1084
|
+
return {
|
|
1085
|
+
available: true,
|
|
1086
|
+
enabled: input.recordingEnabled
|
|
1087
|
+
};
|
|
1088
|
+
case "notification-mute":
|
|
1089
|
+
if (input.notificationsMuted === null) return {
|
|
1090
|
+
available: false,
|
|
1091
|
+
enabled: true,
|
|
1092
|
+
unavailableReason: "source-unreachable"
|
|
1093
|
+
};
|
|
1094
|
+
return {
|
|
1095
|
+
available: true,
|
|
1096
|
+
enabled: !input.notificationsMuted
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* Pure derivation of the whole group. No I/O — the orchestrator gathers, this
|
|
1102
|
+
* decides, so the decision is testable without a hub.
|
|
1103
|
+
*
|
|
1104
|
+
* Order is {@link CAMERA_SWITCH_ORDER}; unavailable switches are RETURNED
|
|
1105
|
+
* rather than filtered out, so a client can explain the gap instead of
|
|
1106
|
+
* silently rendering four buttons where another camera shows five.
|
|
1107
|
+
*/
|
|
1108
|
+
function deriveCameraSwitches(input) {
|
|
1109
|
+
return CAMERA_SWITCH_ORDER.map((id) => {
|
|
1110
|
+
const descriptor = CAMERA_SWITCH_CATALOG[id];
|
|
1111
|
+
const state = resolveState(descriptor, input);
|
|
1112
|
+
return {
|
|
1113
|
+
id: descriptor.id,
|
|
1114
|
+
label: descriptor.label,
|
|
1115
|
+
costWhenOff: descriptor.costWhenOff,
|
|
1116
|
+
available: state.available,
|
|
1117
|
+
...state.unavailableReason !== void 0 ? { unavailableReason: state.unavailableReason } : {},
|
|
1118
|
+
enabled: state.enabled,
|
|
1119
|
+
authority: descriptor.authority
|
|
1120
|
+
};
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1123
|
+
/**
|
|
1124
|
+
* The ids an operator has switched OFF, for a status surface.
|
|
1125
|
+
*
|
|
1126
|
+
* This is the answer to "a disabled function must be visible as DISABLED, not
|
|
1127
|
+
* merely quiet": a camera reporting zero detections with
|
|
1128
|
+
* `switchedOff: ['object-detection']` was turned off; the same camera with an
|
|
1129
|
+
* empty list is broken. Unavailable switches never appear — a function nobody
|
|
1130
|
+
* provides was not switched off by anyone.
|
|
1131
|
+
*/
|
|
1132
|
+
function switchedOffIds(switches) {
|
|
1133
|
+
return switches.filter((s) => s.available && !s.enabled).map((s) => s.id);
|
|
1134
|
+
}
|
|
1135
|
+
//#endregion
|
|
333
1136
|
//#region src/interfaces/device-capabilities/camera.ts
|
|
334
1137
|
/** Friendly display labels for stream quality IDs. */
|
|
335
1138
|
var STREAM_QUALITY_LABELS = {
|
|
@@ -525,14 +1328,16 @@ var OpsLogOpSchema = z.enum([
|
|
|
525
1328
|
"manual-delete",
|
|
526
1329
|
"rescan",
|
|
527
1330
|
"retention-run",
|
|
528
|
-
"relocate"
|
|
1331
|
+
"relocate",
|
|
1332
|
+
"orphan-audit"
|
|
529
1333
|
]);
|
|
530
1334
|
/** Why the operation ran. */
|
|
531
1335
|
var OpsLogReasonSchema = z.enum([
|
|
532
1336
|
"retention",
|
|
533
1337
|
"quota",
|
|
534
1338
|
"manual",
|
|
535
|
-
"operator"
|
|
1339
|
+
"operator",
|
|
1340
|
+
"maintenance"
|
|
536
1341
|
]);
|
|
537
1342
|
/** One audit row, shared verbatim by both domains. */
|
|
538
1343
|
var OpsLogEntrySchema = z.object({
|
|
@@ -3313,6 +4118,100 @@ var RtpSourceSchema = z.object({
|
|
|
3313
4118
|
encoder: z.string(),
|
|
3314
4119
|
pipelineKey: z.string()
|
|
3315
4120
|
});
|
|
4121
|
+
/**
|
|
4122
|
+
* The encode request — **structured and serialisable, with NO raw-flag escape
|
|
4123
|
+
* hatch.** This is deliberate and it is the one lesson taken from
|
|
4124
|
+
* `getStreamWithCodec`: that method's `outputArgs: string[]` is simultaneously
|
|
4125
|
+
* its extensibility mechanism AND part of `pipelineKeyFor`'s sharing key, so
|
|
4126
|
+
* adding a flag silently forks the shared child, and two consumers that mean
|
|
4127
|
+
* the same thing but spell it differently never share. Here every knob is a
|
|
4128
|
+
* NAMED field: a new requirement becomes a schema field (and a codegen run),
|
|
4129
|
+
* never an opaque array.
|
|
4130
|
+
*
|
|
4131
|
+
* `inputArgs` / `outputArgs` are omitted from the profile for the same reason.
|
|
4132
|
+
* The operator-facing derived-stream transform editor still has them — that is
|
|
4133
|
+
* a different surface (`publishCameraStream({ kind: 'derived' })`) with a
|
|
4134
|
+
* different purpose (reshaping a badly-behaved SOURCE), and it is unchanged.
|
|
4135
|
+
*/
|
|
4136
|
+
var EgressEncodeSchema = EncodeProfileSchema.omit({
|
|
4137
|
+
inputArgs: true,
|
|
4138
|
+
outputArgs: true
|
|
4139
|
+
});
|
|
4140
|
+
/**
|
|
4141
|
+
* How the encoder is bounded. `'tight'` is a one-second VBV window for a
|
|
4142
|
+
* consumer whose budget is enforced per second (HomeKit); `'relaxed'` is two
|
|
4143
|
+
* seconds, letting a keyframe spike borrow from the next second (a browser,
|
|
4144
|
+
* an Echo). Named rather than numeric so the INTENT survives.
|
|
4145
|
+
*/
|
|
4146
|
+
var EgressRateControlSchema = z.enum(["tight", "relaxed"]);
|
|
4147
|
+
var EgressTranscodeRequestSchema = z.object({
|
|
4148
|
+
deviceId: z.number().int().nonnegative(),
|
|
4149
|
+
/** Which published stream to read. */
|
|
4150
|
+
source: z.discriminatedUnion("kind", [z.object({
|
|
4151
|
+
kind: z.literal("profile"),
|
|
4152
|
+
profile: CamProfileSchema
|
|
4153
|
+
}), z.object({
|
|
4154
|
+
kind: z.literal("cam-stream"),
|
|
4155
|
+
camStreamId: z.string().min(1)
|
|
4156
|
+
})]),
|
|
4157
|
+
encode: EgressEncodeSchema,
|
|
4158
|
+
rateControl: EgressRateControlSchema.optional(),
|
|
4159
|
+
/**
|
|
4160
|
+
* `-bsf:v`. A consumer that negotiates its OWN SDP (HomeKit) cannot carry
|
|
4161
|
+
* out-of-band extradata and needs `dump_extra` on both the copy and encode
|
|
4162
|
+
* branches. Enumerated, not free text.
|
|
4163
|
+
*/
|
|
4164
|
+
bitstreamFilter: z.enum([
|
|
4165
|
+
"dump_extra",
|
|
4166
|
+
"h264_mp4toannexb",
|
|
4167
|
+
"hevc_mp4toannexb"
|
|
4168
|
+
]).optional(),
|
|
4169
|
+
pixelFormat: z.enum(["yuv420p", "nv12"]).optional(),
|
|
4170
|
+
/**
|
|
4171
|
+
* Operator/consumer override for decode hardware. ABSENT is the normal case
|
|
4172
|
+
* and the one that matters: the broker then resolves the backend from the
|
|
4173
|
+
* DECODER ADDON's per-node `probedBestHwaccel` (see
|
|
4174
|
+
* `@camstack/types` `ffmpeg/hwaccel.ts`), which is the ranking known to work
|
|
4175
|
+
* on this hardware — never the raw kernel resolver's qsv-first order.
|
|
4176
|
+
*/
|
|
4177
|
+
decodeHwAccel: z.enum([
|
|
4178
|
+
"auto",
|
|
4179
|
+
"none",
|
|
4180
|
+
"videotoolbox",
|
|
4181
|
+
"vaapi",
|
|
4182
|
+
"qsv",
|
|
4183
|
+
"cuda"
|
|
4184
|
+
]).optional(),
|
|
4185
|
+
/**
|
|
4186
|
+
* Host to embed in the returned restream `url`. The broker mints hub-local
|
|
4187
|
+
* `127.0.0.1` URLs; a consumer on another node passes a cluster-resolvable
|
|
4188
|
+
* host (`NodeTopologyService.reachableHostByNode`) so the returned URL is
|
|
4189
|
+
* dialable from there. Same contract as `getStreamWithCodec.hostname` —
|
|
4190
|
+
* `substituteRtspHost` rewrites only the dial address, never the restreamer.
|
|
4191
|
+
*/
|
|
4192
|
+
hostname: z.string().optional(),
|
|
4193
|
+
/** Attribution for the broker panel. Never part of the sharing key. */
|
|
4194
|
+
tag: z.string().optional()
|
|
4195
|
+
});
|
|
4196
|
+
var EgressTranscodeSchema = z.object({
|
|
4197
|
+
/** Dial-able RTSP url (host-substituted when `hostname` was supplied). */
|
|
4198
|
+
url: z.string(),
|
|
4199
|
+
/** Release handle. Refcounted — the child dies when the last holder releases. */
|
|
4200
|
+
pipelineKey: z.string(),
|
|
4201
|
+
videoCodec: z.enum(["H264", "H265"]),
|
|
4202
|
+
resolution: z.object({
|
|
4203
|
+
width: z.number().int().positive(),
|
|
4204
|
+
height: z.number().int().positive()
|
|
4205
|
+
}),
|
|
4206
|
+
transcoded: z.boolean(),
|
|
4207
|
+
encoder: z.string(),
|
|
4208
|
+
/**
|
|
4209
|
+
* The decode backend the child ACTUALLY ran with — `null` for software.
|
|
4210
|
+
* Returned rather than assumed: a consumer that asked for hardware and got
|
|
4211
|
+
* software needs to be able to see that without reading the broker's logs.
|
|
4212
|
+
*/
|
|
4213
|
+
decodeHwAccel: z.string().nullable()
|
|
4214
|
+
});
|
|
3316
4215
|
var streamBrokerCapability = {
|
|
3317
4216
|
name: "stream-broker",
|
|
3318
4217
|
scope: "system",
|
|
@@ -3484,6 +4383,40 @@ var streamBrokerCapability = {
|
|
|
3484
4383
|
auth: "admin"
|
|
3485
4384
|
}),
|
|
3486
4385
|
/**
|
|
4386
|
+
* THE ffmpeg primitive. Acquire an encoded stream matching a structured
|
|
4387
|
+
* encode plan; the broker builds the argv through the ONE builder
|
|
4388
|
+
* (`@camstack/types` `ffmpeg/invocation.ts`), resolves decode hardware from
|
|
4389
|
+
* the DECODER ADDON's per-node ranking, and returns a dialable RTSP url.
|
|
4390
|
+
*
|
|
4391
|
+
* **Refcounted and deduplicated on EXACT match.** Two requesters whose
|
|
4392
|
+
* requests produce the same `egressTranscodeSharingKey` receive the SAME
|
|
4393
|
+
* `pipelineKey` and the same child process. Nearly-identical requests are
|
|
4394
|
+
* NOT merged.
|
|
4395
|
+
*
|
|
4396
|
+
* **The handle is immutable.** There is deliberately no `reconfigure`
|
|
4397
|
+
* method and this one never accepts a `pipelineKey` alongside encode
|
|
4398
|
+
* parameters: a consumer whose requirements change releases and
|
|
4399
|
+
* re-acquires. A mutable shared handle is exactly what made Alexa's old
|
|
4400
|
+
* `derived:alexa-<id>` stream a co-tenant hazard — one consumer's
|
|
4401
|
+
* downgrade dragged every other consumer down with it.
|
|
4402
|
+
*
|
|
4403
|
+
* Placement: unpinned, `classifyCapRoute` serves this hub-in-process
|
|
4404
|
+
* (Priority 1). A caller that wants the transcode elsewhere passes
|
|
4405
|
+
* `nodePin(nodeId)` and a `hostname` it can dial.
|
|
4406
|
+
*/
|
|
4407
|
+
acquireEgressTranscode: method(EgressTranscodeRequestSchema, EgressTranscodeSchema, {
|
|
4408
|
+
kind: "mutation",
|
|
4409
|
+
auth: "admin"
|
|
4410
|
+
}),
|
|
4411
|
+
/** Drop one reference. The child dies when the last holder releases. */
|
|
4412
|
+
releaseEgressTranscode: method(z.object({ pipelineKey: z.string() }), z.object({
|
|
4413
|
+
released: z.boolean(),
|
|
4414
|
+
refcount: z.number().int().nonnegative()
|
|
4415
|
+
}), {
|
|
4416
|
+
kind: "mutation",
|
|
4417
|
+
auth: "admin"
|
|
4418
|
+
}),
|
|
4419
|
+
/**
|
|
3487
4420
|
* ── Decoded audio-chunk plane (Phase 5 / D9) ──────────────────────
|
|
3488
4421
|
*
|
|
3489
4422
|
* The serialisable replacement for the live-object `IStreamBroker.
|
|
@@ -10028,12 +10961,13 @@ var NcConditionsSchema = z.object({
|
|
|
10028
10961
|
* source; otherwise the subject's source must equal it. Legacy records
|
|
10029
10962
|
* with no stamped source are treated as `pipeline`. The union spans both
|
|
10030
10963
|
* record kinds — object events carry `pipeline` | `onboard`, synthetic
|
|
10031
|
-
* tracks carry `sensor
|
|
10964
|
+
* tracks carry `sensor` (a linked device) or `audio` (a D62 audio marker).
|
|
10032
10965
|
*/
|
|
10033
10966
|
source: z.enum([
|
|
10034
10967
|
"pipeline",
|
|
10035
10968
|
"onboard",
|
|
10036
10969
|
"sensor",
|
|
10970
|
+
"audio",
|
|
10037
10971
|
"any"
|
|
10038
10972
|
]).optional(),
|
|
10039
10973
|
/**
|
|
@@ -10587,6 +11521,10 @@ var NC_CONDITION_CATALOG = [
|
|
|
10587
11521
|
{
|
|
10588
11522
|
value: "sensor",
|
|
10589
11523
|
label: "Sensor"
|
|
11524
|
+
},
|
|
11525
|
+
{
|
|
11526
|
+
value: "audio",
|
|
11527
|
+
label: "Audio marker"
|
|
10590
11528
|
}
|
|
10591
11529
|
],
|
|
10592
11530
|
operator: "in",
|
|
@@ -10597,7 +11535,7 @@ var NC_CONDITION_CATALOG = [
|
|
|
10597
11535
|
"package-event"
|
|
10598
11536
|
],
|
|
10599
11537
|
phase: "P1",
|
|
10600
|
-
description: "pipeline / onboard / sensor; a record with no stamped source counts as pipeline."
|
|
11538
|
+
description: "pipeline / onboard / sensor / audio; a record with no stamped source counts as pipeline."
|
|
10601
11539
|
},
|
|
10602
11540
|
{
|
|
10603
11541
|
id: "deviceState",
|
|
@@ -10949,6 +11887,35 @@ var notificationRulesCapability = {
|
|
|
10949
11887
|
auth: "admin"
|
|
10950
11888
|
}),
|
|
10951
11889
|
/**
|
|
11890
|
+
* PERMANENT per-camera mute — the notifications half of the per-camera
|
|
11891
|
+
* function switch group ([D61](../../../../docs/decisions/adr-0067.md)).
|
|
11892
|
+
*
|
|
11893
|
+
* Deliberately NOT a snooze. A snooze is bounded at
|
|
11894
|
+
* {@link NC_SNOOZE_MAX_MINUTES} on purpose — "a snooze that could not
|
|
11895
|
+
* expire would be an outage the operator asked for once and forgot" — and
|
|
11896
|
+
* widening it to express "this camera never notifies" would destroy that
|
|
11897
|
+
* property for every snooze. A mute is the other thing: an explicit,
|
|
11898
|
+
* indefinite, admin-only decision, visible in the switch group next to the
|
|
11899
|
+
* other four, and reported on `CameraStatus.switchedOff` so a silent
|
|
11900
|
+
* camera never reads as a working one.
|
|
11901
|
+
*
|
|
11902
|
+
* Returned as ONE list rather than a per-camera query: the group's reader
|
|
11903
|
+
* needs every camera's state, and a per-camera fan-out over the viewer's
|
|
11904
|
+
* single WebSocket is N frames serialised on one socket.
|
|
11905
|
+
*/
|
|
11906
|
+
listDeviceMutes: method(z.object({}), z.object({ mutedDeviceIds: z.array(z.number().int()).readonly() }), { auth: "admin" }),
|
|
11907
|
+
/**
|
|
11908
|
+
* Mute or unmute one camera. Idempotent; an unmute of a camera that was
|
|
11909
|
+
* never muted succeeds.
|
|
11910
|
+
*/
|
|
11911
|
+
setDeviceMuted: method(z.object({
|
|
11912
|
+
deviceId: z.number().int(),
|
|
11913
|
+
muted: z.boolean()
|
|
11914
|
+
}), z.object({ success: z.literal(true) }), {
|
|
11915
|
+
kind: "mutation",
|
|
11916
|
+
auth: "admin"
|
|
11917
|
+
}),
|
|
11918
|
+
/**
|
|
10952
11919
|
* Dry-run a rule against recently persisted records (object events for
|
|
10953
11920
|
* `immediate`, closed tracks for `track-end`). Mutation kind only to
|
|
10954
11921
|
* carry the full rule object safely; no side effects.
|
|
@@ -11366,12 +12333,60 @@ var TrackAudioLabelSchema = z.object({
|
|
|
11366
12333
|
});
|
|
11367
12334
|
/**
|
|
11368
12335
|
* How a track was produced. `pipeline` (default / absent) = the spatial
|
|
11369
|
-
* detection+tracking pipeline.
|
|
11370
|
-
*
|
|
11371
|
-
*
|
|
11372
|
-
*
|
|
12336
|
+
* detection+tracking pipeline. Every OTHER value is a SYNTHETIC projection —
|
|
12337
|
+
* no positions, a single snapshot, and no bbox trajectory at all:
|
|
12338
|
+
*
|
|
12339
|
+
* - `sensor` — a linked sensor/control device state change.
|
|
12340
|
+
* - `audio` — an audio event on the camera itself that was anomalous for
|
|
12341
|
+
* THAT camera, loud, and heard while nothing visual was happening (D62).
|
|
12342
|
+
*
|
|
12343
|
+
* The spatial subsystems (tracker association, occupancy count, re-id /
|
|
12344
|
+
* embedding, resurrection) MUST skip every synthetic source. Test for that
|
|
12345
|
+
* with `isSpatialTrack`, which allow-lists `pipeline` — a `!== 'sensor'`
|
|
12346
|
+
* check silently readmits every source added after it was written.
|
|
11373
12347
|
*/
|
|
11374
|
-
var TrackSourceSchema = z.enum([
|
|
12348
|
+
var TrackSourceSchema = z.enum([
|
|
12349
|
+
"pipeline",
|
|
12350
|
+
"sensor",
|
|
12351
|
+
"audio"
|
|
12352
|
+
]);
|
|
12353
|
+
/**
|
|
12354
|
+
* Per-track OPERATOR flags — set by hand from the admin UI or the viewer, never
|
|
12355
|
+
* by the pipeline. Spread into `TrackSchema` and `KeyEventSchema` from one place
|
|
12356
|
+
* so the two surfaces cannot drift.
|
|
12357
|
+
*
|
|
12358
|
+
* **Absent ≠ false.** A track that has never been touched omits the field; an
|
|
12359
|
+
* explicitly un-flagged track carries `false`. Legacy rows written before the
|
|
12360
|
+
* columns existed read as absent, and a consumer that needs a boolean should say
|
|
12361
|
+
* `flag === true`, not `flag !== false`.
|
|
12362
|
+
*
|
|
12363
|
+
* What the flags DO is deliberately UNDEFINED at the time of writing: they are
|
|
12364
|
+
* operator curation, and the behaviour they drive will be specified separately.
|
|
12365
|
+
* In particular a `markForTrain` track is NOT pinned against retention — see
|
|
12366
|
+
* `docs/decisions/adr-0059.md` for why that is a store-level change, not a flag.
|
|
12367
|
+
*/
|
|
12368
|
+
var TrackFlagFields = {
|
|
12369
|
+
/** Operator marked this track as training material. */
|
|
12370
|
+
markForTrain: z.boolean().optional(),
|
|
12371
|
+
/** Operator marked this track for diagnostic attention. */
|
|
12372
|
+
debug: z.boolean().optional()
|
|
12373
|
+
};
|
|
12374
|
+
/**
|
|
12375
|
+
* The write half: a PARTIAL patch. An omitted key is left untouched, so setting
|
|
12376
|
+
* one flag can never clear the other — the toggles are independent and are
|
|
12377
|
+
* driven from three surfaces that do not know about each other.
|
|
12378
|
+
*/
|
|
12379
|
+
var TrackFlagsPatchSchema = z.object(TrackFlagFields);
|
|
12380
|
+
/**
|
|
12381
|
+
* The resolved flag state after a write. Both fields are REQUIRED here (absent
|
|
12382
|
+
* collapses to `false`) so a caller can drive a toggle's checked state off the
|
|
12383
|
+
* mutation result without a re-fetch.
|
|
12384
|
+
*/
|
|
12385
|
+
var TrackFlagsSchema = z.object({
|
|
12386
|
+
trackId: z.string(),
|
|
12387
|
+
markForTrain: z.boolean(),
|
|
12388
|
+
debug: z.boolean()
|
|
12389
|
+
});
|
|
11375
12390
|
var TrackSchema = z.object({
|
|
11376
12391
|
trackId: z.string(),
|
|
11377
12392
|
deviceId: z.number(),
|
|
@@ -11414,7 +12429,8 @@ var TrackSchema = z.object({
|
|
|
11414
12429
|
/** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
|
|
11415
12430
|
* Populated from the persisted envelope columns on historical reads;
|
|
11416
12431
|
* absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
|
|
11417
|
-
envelope: TrackEnvelopeSchema.optional()
|
|
12432
|
+
envelope: TrackEnvelopeSchema.optional(),
|
|
12433
|
+
...TrackFlagFields
|
|
11418
12434
|
});
|
|
11419
12435
|
var BaseEventFields = {
|
|
11420
12436
|
id: z.string(),
|
|
@@ -11635,7 +12651,8 @@ var KeyEventSchema = z.object({
|
|
|
11635
12651
|
/** Highest-confidence ObjectEvent id for the track (empty when none). */
|
|
11636
12652
|
bestEventId: z.string(),
|
|
11637
12653
|
/** Track lifetime in ms (lastSeen - firstSeen). */
|
|
11638
|
-
windowMs: z.number().optional()
|
|
12654
|
+
windowMs: z.number().optional(),
|
|
12655
|
+
...TrackFlagFields
|
|
11639
12656
|
});
|
|
11640
12657
|
var TrackedDetectionSchema = z.object({
|
|
11641
12658
|
trackId: z.string(),
|
|
@@ -11720,16 +12737,32 @@ var RebuildObjectEmbeddingsInput = z.object({
|
|
|
11720
12737
|
deviceId: z.number().optional(),
|
|
11721
12738
|
since: z.number().optional(),
|
|
11722
12739
|
until: z.number().optional(),
|
|
12740
|
+
/** Stop after this many tracks; the result reports whether more remain. */
|
|
12741
|
+
maxTracks: z.number().int().positive().optional(),
|
|
12742
|
+
/**
|
|
12743
|
+
* Run every embedding on THIS node instead of round-robining the fleet.
|
|
12744
|
+
*
|
|
12745
|
+
* Named `executeOnNodeId` and not `nodeId` on purpose: an inline `nodeId`
|
|
12746
|
+
* field in cap args is read by `parent-unowned-call.ts` as a ROUTING PIN, so
|
|
12747
|
+
* calling it that would pin the rebuild REQUEST itself to that node — the
|
|
12748
|
+
* rebuild orchestration lives on the hub, and only the per-track step runs
|
|
12749
|
+
* remotely. This field is data; the per-track pin is applied inside.
|
|
12750
|
+
*
|
|
12751
|
+
* Absent ⇒ round-robin over every online node whose runner can serve the
|
|
12752
|
+
* pinned model.
|
|
12753
|
+
*/
|
|
12754
|
+
executeOnNodeId: z.string().optional(),
|
|
11723
12755
|
/**
|
|
11724
|
-
*
|
|
11725
|
-
*
|
|
11726
|
-
*
|
|
12756
|
+
* Milliseconds to wait between tracks; omit for the built-in default, `0` to
|
|
12757
|
+
* run flat out.
|
|
12758
|
+
*
|
|
12759
|
+
* A rebuild is bulk maintenance on hub-main's single thread. Measured
|
|
12760
|
+
* 2026-08-06, an unpaced pass held that thread busy 82.2 s out of 120 and
|
|
12761
|
+
* pushed `nodes.topology` from 0.25 s to 26 s for 43 minutes. The value in
|
|
12762
|
+
* force is logged at start and finish so a deliberately slow pass reads
|
|
12763
|
+
* differently from a stalled one.
|
|
11727
12764
|
*/
|
|
11728
|
-
|
|
11729
|
-
/** Square the window before extracting, so a tall subject is not squashed. */
|
|
11730
|
-
square: z.boolean().optional(),
|
|
11731
|
-
/** Stop after this many tracks; the result reports whether more remain. */
|
|
11732
|
-
maxTracks: z.number().int().positive().optional()
|
|
12765
|
+
pacingMs: z.number().int().nonnegative().optional()
|
|
11733
12766
|
});
|
|
11734
12767
|
/**
|
|
11735
12768
|
* Result of emptying the CLIP index.
|
|
@@ -11762,6 +12795,24 @@ var RebuildStatusSchema = z.object({
|
|
|
11762
12795
|
missingKeyFrame: z.number(),
|
|
11763
12796
|
/** Tracks with no usable detection box. */
|
|
11764
12797
|
missingBbox: z.number(),
|
|
12798
|
+
/**
|
|
12799
|
+
* Tracks an executing node REFUSED rather than broke on — an unreadable key
|
|
12800
|
+
* frame, a step that threw. Separate from `failed` because the remedy is
|
|
12801
|
+
* different, and because a whole camera silently contributing zero vectors
|
|
12802
|
+
* is the shape of failure a rebuild must never hide.
|
|
12803
|
+
*/
|
|
12804
|
+
notRunnable: z.number(),
|
|
12805
|
+
/**
|
|
12806
|
+
* The pass stopped because NO node could serve the pinned model.
|
|
12807
|
+
*
|
|
12808
|
+
* Distinct from `notRunnable` on purpose: that one says "this track was
|
|
12809
|
+
* refused", this one says "the cluster cannot do this work at all" — every
|
|
12810
|
+
* candidate node either lacks the `clip-embedding` step, lacks a build of the
|
|
12811
|
+
* pinned model for its engine format, or dropped out. The remedy is a model /
|
|
12812
|
+
* engine change, not a per-camera one. Non-zero here always comes with
|
|
12813
|
+
* `complete: false`.
|
|
12814
|
+
*/
|
|
12815
|
+
noCapableNode: z.number(),
|
|
11765
12816
|
failed: z.number(),
|
|
11766
12817
|
/** Set once a pass ends: true only when EVERYTHING was covered. */
|
|
11767
12818
|
complete: z.boolean().nullable(),
|
|
@@ -11951,6 +13002,31 @@ var pipelineAnalyticsCapability = {
|
|
|
11951
13002
|
auth: "admin"
|
|
11952
13003
|
}),
|
|
11953
13004
|
/**
|
|
13005
|
+
* Set the per-track operator flags (`markForTrain`, `debug`) on ONE track.
|
|
13006
|
+
* The patch is PARTIAL — an omitted key is left untouched — because the
|
|
13007
|
+
* three surfaces that write it (admin Events grid, viewer track detail,
|
|
13008
|
+
* viewer cluster detail) each own one toggle and must not clobber the other.
|
|
13009
|
+
*
|
|
13010
|
+
* Writes the track ROW: `markForTrain`/`debug` are per-TRACK state, so they
|
|
13011
|
+
* live where `label` and `importance` live, not in any per-device settings
|
|
13012
|
+
* store. Updates the in-RAM active track too, so a flag set on a live track
|
|
13013
|
+
* survives its expiry-time persist.
|
|
13014
|
+
*
|
|
13015
|
+
* `auth: 'protected'` (the default), NOT `admin`: the viewer is an
|
|
13016
|
+
* authenticated non-admin surface and two of the three call sites are
|
|
13017
|
+
* there. Revisit if a flag ever gains an effect that costs storage —
|
|
13018
|
+
* `deleteTracks` next door is admin for exactly that reason.
|
|
13019
|
+
*
|
|
13020
|
+
* Returns the RESOLVED state of both flags (absent → `false`) so a caller
|
|
13021
|
+
* can drive its toggle without a re-fetch. Rejects an unknown track.
|
|
13022
|
+
*/
|
|
13023
|
+
setTrackFlags: method(z.object({
|
|
13024
|
+
/** Log/audit scope only — the trackId is globally unique on its own. */
|
|
13025
|
+
deviceId: z.number(),
|
|
13026
|
+
trackId: z.string(),
|
|
13027
|
+
flags: TrackFlagsPatchSchema
|
|
13028
|
+
}), TrackFlagsSchema, { kind: "mutation" }),
|
|
13029
|
+
/**
|
|
11954
13030
|
* Durable event-store footprint for the management UI: event rows
|
|
11955
13031
|
* (motion + object + audio) counted per camera + total, plus the
|
|
11956
13032
|
* event-owned media bytes on disk per camera + total. Stat/count-based,
|
|
@@ -12839,6 +13915,53 @@ var DetailResultSchema = z.object({
|
|
|
12839
13915
|
nativeFaceShortSidePx: z.number().optional()
|
|
12840
13916
|
});
|
|
12841
13917
|
/**
|
|
13918
|
+
* Why an executing node REFUSED a stateless step run (`runStatelessStep`).
|
|
13919
|
+
*
|
|
13920
|
+
* A refusal is a first-class answer, not an error, because the caller's next
|
|
13921
|
+
* move depends on WHICH one it is — and because "the pass produced nothing"
|
|
13922
|
+
* must never be reachable without a named, counted cause. The two tiers:
|
|
13923
|
+
*
|
|
13924
|
+
* - **node-level** (`unknown-step`, `model-not-servable`) — this node can
|
|
13925
|
+
* never serve this (step, model) pair. The caller drops it from its rotation
|
|
13926
|
+
* and retries the same work elsewhere; nothing about the work changes.
|
|
13927
|
+
* - **work-level** (`unreadable-frame`, `execution-failed`) — this node is
|
|
13928
|
+
* fine, this one request is not. Retrying it on another node would only
|
|
13929
|
+
* spread the same failure.
|
|
13930
|
+
*/
|
|
13931
|
+
var StatelessStepRefusalSchema = z.enum([
|
|
13932
|
+
"unknown-step",
|
|
13933
|
+
"model-not-servable",
|
|
13934
|
+
"unreadable-frame",
|
|
13935
|
+
"execution-failed"
|
|
13936
|
+
]);
|
|
13937
|
+
/**
|
|
13938
|
+
* Answer to `runStatelessStep` — a discriminated union rather than a nullable
|
|
13939
|
+
* result, because `null` is exactly what made the camera-bound detail path
|
|
13940
|
+
* unable to tell "refused" from "never asked".
|
|
13941
|
+
*/
|
|
13942
|
+
var RunStatelessStepResultSchema = z.discriminatedUnion("kind", [z.object({
|
|
13943
|
+
kind: z.literal("ran"),
|
|
13944
|
+
/** The node that actually executed it — the pin, echoed back for the log. */
|
|
13945
|
+
nodeId: z.string(),
|
|
13946
|
+
/**
|
|
13947
|
+
* The model the step ran with.
|
|
13948
|
+
*
|
|
13949
|
+
* The node verified this exact id has a build for the format it dispatched
|
|
13950
|
+
* on BEFORE running, so the executor's format resolution returns it
|
|
13951
|
+
* unchanged. A caller that pinned a model must compare this field and
|
|
13952
|
+
* treat a mismatch as a refusal — the whole point of the pin is that a
|
|
13953
|
+
* pass writes one feature space.
|
|
13954
|
+
*/
|
|
13955
|
+
modelId: z.string(),
|
|
13956
|
+
details: z.array(DetailResultSchema)
|
|
13957
|
+
}), z.object({
|
|
13958
|
+
kind: z.literal("refused"),
|
|
13959
|
+
nodeId: z.string(),
|
|
13960
|
+
reason: StatelessStepRefusalSchema,
|
|
13961
|
+
/** Human-readable specifics — the format tried, the formats shipped, etc. */
|
|
13962
|
+
detail: z.string()
|
|
13963
|
+
})]);
|
|
13964
|
+
/**
|
|
12842
13965
|
* Per-camera tunable ranges + defaults. Single source of truth used
|
|
12843
13966
|
* by both the Zod data schema (validation + default fallback) and
|
|
12844
13967
|
* the device settings UI (slider min/max/step). Touch one place and
|
|
@@ -13381,20 +14504,118 @@ var pipelineRunnerCapability = {
|
|
|
13381
14504
|
* for a single tracked detection. The per-frame plane (`runPipeline`
|
|
13382
14505
|
* with `plane: 'frame'`) skips crop children entirely; a track-level
|
|
13383
14506
|
* caller invokes this per-track, on its own cadence, instead of on
|
|
13384
|
-
* every frame.
|
|
13385
|
-
*
|
|
13386
|
-
*
|
|
13387
|
-
*
|
|
13388
|
-
*
|
|
13389
|
-
*
|
|
14507
|
+
* every frame. `steps` narrows which configured children to run
|
|
14508
|
+
* (default: all configured children for `parent.className`).
|
|
14509
|
+
*
|
|
14510
|
+
* ## Three pixel sources, and WHO decides the rectangle
|
|
14511
|
+
*
|
|
14512
|
+
* Tried in this order; the difference between them is not the pixels but
|
|
14513
|
+
* which side derives the crop, and confusing the two is how the CLIP index
|
|
14514
|
+
* ended up holding two incomparable feature spaces:
|
|
14515
|
+
*
|
|
14516
|
+
* 1. `frameHandle` — shm lease/session, preferred and zero-copy. **The
|
|
14517
|
+
* runner cuts**, applying the cluster crop convention.
|
|
14518
|
+
* 2. `frameJpeg` — a FULL FRAME supplied by the caller (the embedding
|
|
14519
|
+
* rebuild's stored key frame). **The runner cuts**, applying the same
|
|
14520
|
+
* convention to the same function, so a rebuilt vector lands in the same
|
|
14521
|
+
* feature space as a live one.
|
|
14522
|
+
* 3. `cropJpeg` — an ALREADY-CUT tile. **The caller decided the
|
|
14523
|
+
* rectangle**; the runner applies NO padding and no squaring and feeds
|
|
14524
|
+
* it to the model verbatim. Only for the lease-miss retry, where the
|
|
14525
|
+
* caller holds pixels the runner can no longer reach.
|
|
14526
|
+
*
|
|
14527
|
+
* Returns `null` when no source resolves (handle evicted and no fallback
|
|
14528
|
+
* supplied), when the camera is not attached, or when no enabled step
|
|
14529
|
+
* matches — every one of those is logged on the runner with the deviceId.
|
|
13390
14530
|
*/
|
|
13391
14531
|
runDetailSubtree: method(z.object({
|
|
13392
14532
|
deviceId: z.number(),
|
|
13393
14533
|
frameHandle: FrameHandleSchema.optional(),
|
|
14534
|
+
/**
|
|
14535
|
+
* FULL FRAME (base64 JPEG). The runner derives the crop rectangle from
|
|
14536
|
+
* `parent.bbox` with the cluster crop convention and cuts it itself —
|
|
14537
|
+
* do NOT pre-crop for this field, that is what `cropJpeg` is.
|
|
14538
|
+
*/
|
|
14539
|
+
frameJpeg: z.string().optional(),
|
|
14540
|
+
/**
|
|
14541
|
+
* PRE-CUT tile (base64 JPEG), used verbatim — NO padding is applied.
|
|
14542
|
+
* The fallback when the lease/session backing the frame is gone and the
|
|
14543
|
+
* caller already holds a crop.
|
|
14544
|
+
*/
|
|
13394
14545
|
cropJpeg: z.string().optional(),
|
|
13395
14546
|
parent: DetailParentSchema,
|
|
13396
14547
|
steps: z.array(z.string()).optional()
|
|
13397
|
-
}), z.object({ details: z.array(DetailResultSchema) }).nullable(), { kind: "mutation" })
|
|
14548
|
+
}), z.object({ details: z.array(DetailResultSchema) }).nullable(), { kind: "mutation" }),
|
|
14549
|
+
/**
|
|
14550
|
+
* Run ONE enrichment step against caller-supplied pixels, with NO camera
|
|
14551
|
+
* session — no attach, no frame handle, no device affinity.
|
|
14552
|
+
*
|
|
14553
|
+
* ## Why this exists next to `runDetailSubtree` and not inside it
|
|
14554
|
+
*
|
|
14555
|
+
* `runDetailSubtree` resolves its step tree from the LIVE ATTACH STATE. That
|
|
14556
|
+
* is correct for it: its reason to exist is a frame HANDLE, and a handle is
|
|
14557
|
+
* only resolvable while a decode session is open. But it makes the method
|
|
14558
|
+
* useless to anything walking history — cameras run `detectionMode:
|
|
14559
|
+
* 'on-motion'` and detach ~30 s after motion stops, so a fleet-wide
|
|
14560
|
+
* embedding rebuild found most cameras detached and rebuilt only whatever
|
|
14561
|
+
* happened to be attached at that second (measured 2026-08-06: 1125 tracks
|
|
14562
|
+
* scanned, 121 rebuilt, 601 refused as "camera is not attached").
|
|
14563
|
+
*
|
|
14564
|
+
* A caller that ships its own pixels needs none of that machinery. So this
|
|
14565
|
+
* method takes the three things a step actually needs — an image, a box, a
|
|
14566
|
+
* step id — resolves the step from the CATALOG rather than from an
|
|
14567
|
+
* attachment, and runs it on whichever node the caller pinned.
|
|
14568
|
+
*
|
|
14569
|
+
* ## What it deliberately keeps
|
|
14570
|
+
*
|
|
14571
|
+
* The crop rectangle is derived by the SAME `deriveDetailCropRect` call the
|
|
14572
|
+
* live detail plane uses, from the same cluster-wide convention
|
|
14573
|
+
* ([D52](../../../docs/decisions/adr-0052.md)). `frameJpeg` is a FULL frame,
|
|
14574
|
+
* never a pre-cut tile, for exactly the reason `runDetailSubtree` documents:
|
|
14575
|
+
* a caller that cuts is a second feature space.
|
|
14576
|
+
*
|
|
14577
|
+
* ## What it deliberately drops
|
|
14578
|
+
*
|
|
14579
|
+
* No device jump and no `deviceKey`: the jump roster comes from the attach
|
|
14580
|
+
* config, which does not exist here. The step runs on the node's default
|
|
14581
|
+
* engine. This is a maintenance path, not a latency-sensitive one.
|
|
14582
|
+
*
|
|
14583
|
+
* ## Routing
|
|
14584
|
+
*
|
|
14585
|
+
* NOT device-bound. `sourceDeviceId` is DIAGNOSTIC — the camera whose track
|
|
14586
|
+
* these pixels came from, so every log line on the executing node can carry
|
|
14587
|
+
* `tags: { deviceId }`. It is deliberately not named `deviceId`: that field
|
|
14588
|
+
* is a routing hint that would send the call to the camera's owning node,
|
|
14589
|
+
* which is the placement constraint this method exists to remove. Callers
|
|
14590
|
+
* choose the node with `nodePin(nodeId)`; unpinned, an unowned call is
|
|
14591
|
+
* served hub-in-process like any other singleton.
|
|
14592
|
+
*/
|
|
14593
|
+
runStatelessStep: method(z.object({
|
|
14594
|
+
/** Catalog step id, e.g. `clip-embedding`. */
|
|
14595
|
+
stepId: z.string(),
|
|
14596
|
+
/**
|
|
14597
|
+
* REQUIRED model pin. The node runs this exact model or refuses with
|
|
14598
|
+
* `model-not-servable` — it never substitutes a format default, because
|
|
14599
|
+
* a fleet pass that round-robins across nodes would then fill one index
|
|
14600
|
+
* from several encoders.
|
|
14601
|
+
*/
|
|
14602
|
+
modelId: z.string(),
|
|
14603
|
+
/** FULL FRAME, base64 JPEG. The runner cuts — do NOT pre-crop. */
|
|
14604
|
+
frameJpeg: z.string(),
|
|
14605
|
+
/**
|
|
14606
|
+
* The subject box, NORMALISED [0,1] against `frameJpeg`. Normalised on
|
|
14607
|
+
* purpose: the caller stores boxes against a downscaled analysis frame
|
|
14608
|
+
* while the stored key frame is native-resolution, and the only side
|
|
14609
|
+
* that reliably knows the image's pixel dimensions is the side that
|
|
14610
|
+
* decodes it. Denormalising here removes a second reader of the
|
|
14611
|
+
* dimensions and the class of mismatch that comes with it.
|
|
14612
|
+
*/
|
|
14613
|
+
bbox: NativeCropBboxSchema,
|
|
14614
|
+
/** Parent class of the subject (`person`, `vehicle`, …) — carried into the result. */
|
|
14615
|
+
className: z.string(),
|
|
14616
|
+
/** Camera the pixels came from. Diagnostics + log tags ONLY — never routing. */
|
|
14617
|
+
sourceDeviceId: z.number()
|
|
14618
|
+
}), RunStatelessStepResultSchema, { kind: "mutation" })
|
|
13398
14619
|
}
|
|
13399
14620
|
};
|
|
13400
14621
|
//#endregion
|
|
@@ -13704,6 +14925,20 @@ var CameraStatusSchema = z.object({
|
|
|
13704
14925
|
detection: CameraDetectionStatusSchema.nullable(),
|
|
13705
14926
|
audio: CameraAudioStatusSchema.nullable(),
|
|
13706
14927
|
recording: CameraRecordingStatusSchema.nullable(),
|
|
14928
|
+
/**
|
|
14929
|
+
* Per-camera function switches an OPERATOR has turned off
|
|
14930
|
+
* ([D61](../../../../docs/decisions/adr-0067.md)).
|
|
14931
|
+
*
|
|
14932
|
+
* This is the difference between DISABLED and BROKEN. A camera whose
|
|
14933
|
+
* `detection` block reports zero fps and whose `switchedOff` contains
|
|
14934
|
+
* `'object-detection'` was switched off by a person; the same camera with an
|
|
14935
|
+
* empty list is failing. Every status surface must render the two
|
|
14936
|
+
* differently — a quiet camera that looks identical to a dead one is the
|
|
14937
|
+
* silence-reads-as-never-happened trap this repo keeps paying for.
|
|
14938
|
+
*
|
|
14939
|
+
* Empty when nothing is off. Never contains a switch no provider offers.
|
|
14940
|
+
*/
|
|
14941
|
+
switchedOff: z.array(CameraSwitchIdSchema).readonly(),
|
|
13707
14942
|
/** Unix timestamp (ms) when this snapshot was composed server-side. */
|
|
13708
14943
|
fetchedAt: z.number()
|
|
13709
14944
|
});
|
|
@@ -14103,6 +15338,43 @@ var pipelineOrchestratorCapability = {
|
|
|
14103
15338
|
agentNodeId: z.string().optional()
|
|
14104
15339
|
}), CameraPipelineConfigSchema),
|
|
14105
15340
|
/**
|
|
15341
|
+
* The whole per-camera function switch group, DERIVED — never a stored
|
|
15342
|
+
* list ([D61](../../../../docs/decisions/adr-0067.md)).
|
|
15343
|
+
*
|
|
15344
|
+
* The group adds no state. Each switch is a view onto the authority that
|
|
15345
|
+
* already owned it (`deviceManager.setDisabled`,
|
|
15346
|
+
* `deviceManager.setWrapperActive`, `RecordingConfig.enabled`,
|
|
15347
|
+
* `notificationRules.setDeviceMuted`), and `switch.authority` says which.
|
|
15348
|
+
* Availability comes from `deviceManager.listBindableCapsForDeviceType`,
|
|
15349
|
+
* so a deployment with no audio analyzer renders no audio switch.
|
|
15350
|
+
*
|
|
15351
|
+
* `auth: 'view'` deliberately — a NON-admin must be able to see that a
|
|
15352
|
+
* camera is quiet because somebody switched it off. Only the mutation is
|
|
15353
|
+
* admin-gated.
|
|
15354
|
+
*/
|
|
15355
|
+
getCameraSwitches: method(z.object({ deviceId: z.number() }), CameraSwitchGroupSchema),
|
|
15356
|
+
/**
|
|
15357
|
+
* Flip ONE switch, routed to its existing authority.
|
|
15358
|
+
*
|
|
15359
|
+
* Never writes a parallel map: `recording` patches `RecordingConfig.enabled`
|
|
15360
|
+
* and leaves `bands` byte-identical (clearing bands to express "off"
|
|
15361
|
+
* destroys the operator's authored schedule and turning the camera back on
|
|
15362
|
+
* would silently record nothing), and the two pipeline switches write the
|
|
15363
|
+
* SAME wrapper binding the legacy `pipelineEnabled` / `audioEnabled`
|
|
15364
|
+
* booleans were migrated onto.
|
|
15365
|
+
*
|
|
15366
|
+
* Rejects a switch this camera does not offer rather than persisting a
|
|
15367
|
+
* write nothing reads.
|
|
15368
|
+
*/
|
|
15369
|
+
setCameraSwitch: method(z.object({
|
|
15370
|
+
deviceId: z.number(),
|
|
15371
|
+
switchId: CameraSwitchIdSchema,
|
|
15372
|
+
enabled: z.boolean()
|
|
15373
|
+
}), CameraSwitchGroupSchema, {
|
|
15374
|
+
kind: "mutation",
|
|
15375
|
+
auth: "admin"
|
|
15376
|
+
}),
|
|
15377
|
+
/**
|
|
14106
15378
|
* Server-composed aggregated status for a single camera.
|
|
14107
15379
|
*
|
|
14108
15380
|
* Fans out in parallel (bounded, per-stage graceful degradation) to
|
|
@@ -30123,6 +31395,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
30123
31395
|
addonId: null,
|
|
30124
31396
|
access: "view"
|
|
30125
31397
|
},
|
|
31398
|
+
"notificationRules.listDeviceMutes": {
|
|
31399
|
+
capName: "notification-rules",
|
|
31400
|
+
capScope: "system",
|
|
31401
|
+
addonId: null,
|
|
31402
|
+
access: "view"
|
|
31403
|
+
},
|
|
30126
31404
|
"notificationRules.listRules": {
|
|
30127
31405
|
capName: "notification-rules",
|
|
30128
31406
|
capScope: "system",
|
|
@@ -30141,6 +31419,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
30141
31419
|
addonId: null,
|
|
30142
31420
|
access: "create"
|
|
30143
31421
|
},
|
|
31422
|
+
"notificationRules.setDeviceMuted": {
|
|
31423
|
+
capName: "notification-rules",
|
|
31424
|
+
capScope: "system",
|
|
31425
|
+
addonId: null,
|
|
31426
|
+
access: "create"
|
|
31427
|
+
},
|
|
30144
31428
|
"notificationRules.setRuleEnabled": {
|
|
30145
31429
|
capName: "notification-rules",
|
|
30146
31430
|
capScope: "system",
|
|
@@ -30417,6 +31701,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
30417
31701
|
addonId: null,
|
|
30418
31702
|
access: "view"
|
|
30419
31703
|
},
|
|
31704
|
+
"pipelineAnalytics.setTrackFlags": {
|
|
31705
|
+
capName: "pipeline-analytics",
|
|
31706
|
+
capScope: "device",
|
|
31707
|
+
addonId: null,
|
|
31708
|
+
access: "create"
|
|
31709
|
+
},
|
|
30420
31710
|
"pipelineAnalytics.wipeAllAnalytics": {
|
|
30421
31711
|
capName: "pipeline-analytics",
|
|
30422
31712
|
capScope: "device",
|
|
@@ -30723,6 +32013,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
30723
32013
|
addonId: null,
|
|
30724
32014
|
access: "view"
|
|
30725
32015
|
},
|
|
32016
|
+
"pipelineOrchestrator.getCameraSwitches": {
|
|
32017
|
+
capName: "pipeline-orchestrator",
|
|
32018
|
+
capScope: "system",
|
|
32019
|
+
addonId: null,
|
|
32020
|
+
access: "view"
|
|
32021
|
+
},
|
|
30726
32022
|
"pipelineOrchestrator.getCapabilityBindings": {
|
|
30727
32023
|
capName: "pipeline-orchestrator",
|
|
30728
32024
|
capScope: "system",
|
|
@@ -30855,6 +32151,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
30855
32151
|
addonId: null,
|
|
30856
32152
|
access: "create"
|
|
30857
32153
|
},
|
|
32154
|
+
"pipelineOrchestrator.setCameraSwitch": {
|
|
32155
|
+
capName: "pipeline-orchestrator",
|
|
32156
|
+
capScope: "system",
|
|
32157
|
+
addonId: null,
|
|
32158
|
+
access: "create"
|
|
32159
|
+
},
|
|
30858
32160
|
"pipelineOrchestrator.setCapabilityBinding": {
|
|
30859
32161
|
capName: "pipeline-orchestrator",
|
|
30860
32162
|
capScope: "system",
|
|
@@ -30945,6 +32247,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
30945
32247
|
addonId: null,
|
|
30946
32248
|
access: "create"
|
|
30947
32249
|
},
|
|
32250
|
+
"pipelineRunner.runStatelessStep": {
|
|
32251
|
+
capName: "pipeline-runner",
|
|
32252
|
+
capScope: "system",
|
|
32253
|
+
addonId: null,
|
|
32254
|
+
access: "create"
|
|
32255
|
+
},
|
|
30948
32256
|
"plateGallery.assignPlate": {
|
|
30949
32257
|
capName: "plate-gallery",
|
|
30950
32258
|
capScope: "system",
|
|
@@ -31761,6 +33069,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
31761
33069
|
addonId: null,
|
|
31762
33070
|
access: "create"
|
|
31763
33071
|
},
|
|
33072
|
+
"streamBroker.acquireEgressTranscode": {
|
|
33073
|
+
capName: "stream-broker",
|
|
33074
|
+
capScope: "system",
|
|
33075
|
+
addonId: null,
|
|
33076
|
+
access: "create"
|
|
33077
|
+
},
|
|
31764
33078
|
"streamBroker.assignProfile": {
|
|
31765
33079
|
capName: "stream-broker",
|
|
31766
33080
|
capScope: "system",
|
|
@@ -31869,6 +33183,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
31869
33183
|
addonId: null,
|
|
31870
33184
|
access: "create"
|
|
31871
33185
|
},
|
|
33186
|
+
"streamBroker.releaseEgressTranscode": {
|
|
33187
|
+
capName: "stream-broker",
|
|
33188
|
+
capScope: "system",
|
|
33189
|
+
addonId: null,
|
|
33190
|
+
access: "create"
|
|
33191
|
+
},
|
|
31872
33192
|
"streamBroker.releaseStreamWithCodec": {
|
|
31873
33193
|
capName: "stream-broker",
|
|
31874
33194
|
capScope: "system",
|
|
@@ -33281,7 +34601,8 @@ function createSystemProxy(api) {
|
|
|
33281
34601
|
getLocalMetrics: (input) => dispatch("pipelineRunner", "getLocalMetrics", "query", input),
|
|
33282
34602
|
getAllCameraMetrics: (input) => dispatch("pipelineRunner", "getAllCameraMetrics", "query", input),
|
|
33283
34603
|
getLocalCameras: (input) => dispatch("pipelineRunner", "getLocalCameras", "query", input),
|
|
33284
|
-
getNativeCrop: (input) => dispatch("pipelineRunner", "getNativeCrop", "query", input)
|
|
34604
|
+
getNativeCrop: (input) => dispatch("pipelineRunner", "getNativeCrop", "query", input),
|
|
34605
|
+
runStatelessStep: (input) => dispatch("pipelineRunner", "runStatelessStep", "mutation", input)
|
|
33285
34606
|
},
|
|
33286
34607
|
plateGallery: {
|
|
33287
34608
|
getPlateMedia: (input) => dispatch("plateGallery", "getPlateMedia", "query", input),
|
|
@@ -33368,6 +34689,8 @@ function createSystemProxy(api) {
|
|
|
33368
34689
|
getStreamUrl: (input) => dispatch("streamBroker", "getStreamUrl", "query", input),
|
|
33369
34690
|
getStreamWithCodec: (input) => dispatch("streamBroker", "getStreamWithCodec", "mutation", input),
|
|
33370
34691
|
releaseStreamWithCodec: (input) => dispatch("streamBroker", "releaseStreamWithCodec", "mutation", input),
|
|
34692
|
+
acquireEgressTranscode: (input) => dispatch("streamBroker", "acquireEgressTranscode", "mutation", input),
|
|
34693
|
+
releaseEgressTranscode: (input) => dispatch("streamBroker", "releaseEgressTranscode", "mutation", input),
|
|
33371
34694
|
subscribeAudioChunks: (input) => dispatch("streamBroker", "subscribeAudioChunks", "mutation", input),
|
|
33372
34695
|
pullAudioChunks: (input) => dispatch("streamBroker", "pullAudioChunks", "query", input),
|
|
33373
34696
|
unsubscribeAudioChunks: (input) => dispatch("streamBroker", "unsubscribeAudioChunks", "mutation", input),
|
|
@@ -34880,6 +36203,202 @@ function pointInPolygon(point, polygon) {
|
|
|
34880
36203
|
return inside;
|
|
34881
36204
|
}
|
|
34882
36205
|
//#endregion
|
|
36206
|
+
//#region src/pipeline/detail-crop.ts
|
|
36207
|
+
/**
|
|
36208
|
+
* THE detail-crop convention — the single derivation of the rectangle a
|
|
36209
|
+
* detail/enrichment step (clip-embedding, face-detection, plate-detection…)
|
|
36210
|
+
* is fed.
|
|
36211
|
+
*
|
|
36212
|
+
* ## Why this is one module and not two constants
|
|
36213
|
+
*
|
|
36214
|
+
* `object-clip` is ONE vector index, and cosine similarity is only meaningful
|
|
36215
|
+
* between vectors produced from the same crop convention. Two encode paths
|
|
36216
|
+
* write into it — the live detail plane and the embedding rebuild — and they
|
|
36217
|
+
* used to derive their crops independently: `DETAIL_CROP_PADDING_RATIO = 0.15`
|
|
36218
|
+
* with no squaring on one side, `DEFAULT_CROP_MARGIN = 0.2` with squaring on
|
|
36219
|
+
* by default on the other. Every rebuild therefore poured a second, silently
|
|
36220
|
+
* incomparable feature space into the index it exists to keep consistent.
|
|
36221
|
+
*
|
|
36222
|
+
* So the rectangle is derived HERE, once, from ONE convention value. Both
|
|
36223
|
+
* paths now reach this function through `pipelineRunner.runDetailSubtree` —
|
|
36224
|
+
* the runner is the only process that cuts (see `detail-subtree.ts`), and the
|
|
36225
|
+
* convention is a cluster-global `pipeline-orchestrator` setting. There is
|
|
36226
|
+
* deliberately no per-node or per-device scope: a per-accelerator crop margin
|
|
36227
|
+
* would reintroduce the same split, merely relocated.
|
|
36228
|
+
*
|
|
36229
|
+
* ## The default IS the live convention
|
|
36230
|
+
*
|
|
36231
|
+
* {@link DEFAULT_DETAIL_CROP_CONVENTION} reproduces what the live path has
|
|
36232
|
+
* been storing (0.15, no squaring). Anything else would invalidate every
|
|
36233
|
+
* vector already in the index on the day it shipped. Changing the convention
|
|
36234
|
+
* is legitimate — that is what the operator knob is for — but it must be
|
|
36235
|
+
* followed by a rebuild, which is now guaranteed to produce crops from this
|
|
36236
|
+
* same function.
|
|
36237
|
+
*/
|
|
36238
|
+
/**
|
|
36239
|
+
* Store identity of the convention in `pipeline-orchestrator`'s GLOBAL
|
|
36240
|
+
* (cluster-wide) settings.
|
|
36241
|
+
*
|
|
36242
|
+
* These live here rather than in the orchestrator because the reader is a
|
|
36243
|
+
* different addon — the pipeline runner, over the hub-routed `addon-settings`
|
|
36244
|
+
* cap. Addons never import each other, so a key owned by the writer would have
|
|
36245
|
+
* to be hand-copied by the reader, and a hand-copied key is how a setting
|
|
36246
|
+
* silently stops arriving while both sides still look correct.
|
|
36247
|
+
*/
|
|
36248
|
+
var DETAIL_CROP_SECTION_ID = "detail-crop";
|
|
36249
|
+
var DETAIL_CROP_PADDING_KEY = "detailCropPaddingRatio";
|
|
36250
|
+
var DETAIL_CROP_SQUARE_KEY = "detailCropSquare";
|
|
36251
|
+
/**
|
|
36252
|
+
* Operator-tunable crop convention. Single-valued and cluster-wide — see the
|
|
36253
|
+
* module docblock for why it cannot be scoped per node or per device.
|
|
36254
|
+
*/
|
|
36255
|
+
var DetailCropConventionSchema = z.object({
|
|
36256
|
+
/**
|
|
36257
|
+
* Fraction of the box's own size added on EACH side before cutting.
|
|
36258
|
+
*
|
|
36259
|
+
* CLIP is trained on natural images WITH surroundings; a pixel-tight crop
|
|
36260
|
+
* removes exactly the context it is strongest on (a dog cut to its outline
|
|
36261
|
+
* is a dark blob). The right value is an empirical question, which is why it
|
|
36262
|
+
* is a setting: 0 / 0.15 / 0.2 / 0.5 are the interesting points.
|
|
36263
|
+
*/
|
|
36264
|
+
paddingRatio: z.number().min(0).max(4),
|
|
36265
|
+
/**
|
|
36266
|
+
* Square the window (in PIXELS) before cutting.
|
|
36267
|
+
*
|
|
36268
|
+
* CLIP's input is square, so a tall bbox resized straight to NxN is squashed
|
|
36269
|
+
* — a standing person becomes a shape the model never saw. Squaring costs
|
|
36270
|
+
* extra background, which is context the model wants anyway. Off by default
|
|
36271
|
+
* because the live path has never squared and the stored index reflects that.
|
|
36272
|
+
*/
|
|
36273
|
+
square: z.boolean()
|
|
36274
|
+
});
|
|
36275
|
+
/**
|
|
36276
|
+
* The convention in force when nobody has configured one — byte-for-byte the
|
|
36277
|
+
* behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
|
|
36278
|
+
*/
|
|
36279
|
+
var DEFAULT_DETAIL_CROP_CONVENTION = {
|
|
36280
|
+
paddingRatio: .15,
|
|
36281
|
+
square: false
|
|
36282
|
+
};
|
|
36283
|
+
/**
|
|
36284
|
+
* Narrow a FLAT settings record to the convention.
|
|
36285
|
+
*
|
|
36286
|
+
* Per-FIELD fallback, deliberately: a junk padding must not also discard a
|
|
36287
|
+
* valid squaring choice. An absent or invalid value resolves to
|
|
36288
|
+
* {@link DEFAULT_DETAIL_CROP_CONVENTION} — the historical live behaviour —
|
|
36289
|
+
* rather than to a clamped number nobody chose, so a bad read can never
|
|
36290
|
+
* quietly change what the stored vectors mean.
|
|
36291
|
+
*/
|
|
36292
|
+
function readDetailCropConvention(config) {
|
|
36293
|
+
const paddingRatio = DetailCropConventionSchema.shape.paddingRatio.safeParse(config[DETAIL_CROP_PADDING_KEY]);
|
|
36294
|
+
const square = DetailCropConventionSchema.shape.square.safeParse(config[DETAIL_CROP_SQUARE_KEY]);
|
|
36295
|
+
return {
|
|
36296
|
+
paddingRatio: paddingRatio.success ? paddingRatio.data : DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio,
|
|
36297
|
+
square: square.success ? square.data : DEFAULT_DETAIL_CROP_CONVENTION.square
|
|
36298
|
+
};
|
|
36299
|
+
}
|
|
36300
|
+
function isHydratedField(entry) {
|
|
36301
|
+
return typeof entry === "object" && entry !== null && "key" in entry;
|
|
36302
|
+
}
|
|
36303
|
+
/**
|
|
36304
|
+
* Extract the convention from an `addon-settings.getGlobalSettings` payload.
|
|
36305
|
+
*
|
|
36306
|
+
* Walks EVERY section rather than looking inside {@link DETAIL_CROP_SECTION_ID}
|
|
36307
|
+
* alone: the keys are unique across the addon's schema, and a section rename
|
|
36308
|
+
* must not silently revert the whole cluster to the default. A `null` payload
|
|
36309
|
+
* (addon mid-boot) is the default convention.
|
|
36310
|
+
*/
|
|
36311
|
+
function pickDetailCropConvention(view) {
|
|
36312
|
+
if (view === null) return DEFAULT_DETAIL_CROP_CONVENTION;
|
|
36313
|
+
const flat = {};
|
|
36314
|
+
for (const section of view.sections) for (const entry of section.fields) {
|
|
36315
|
+
if (!isHydratedField(entry) || typeof entry.key !== "string") continue;
|
|
36316
|
+
if (entry.key === "detailCropPaddingRatio" || entry.key === "detailCropSquare") flat[entry.key] = entry.value;
|
|
36317
|
+
}
|
|
36318
|
+
return readDetailCropConvention(flat);
|
|
36319
|
+
}
|
|
36320
|
+
/** Slider bounds for the operator-facing padding knob (orchestrator settings UI). */
|
|
36321
|
+
var DETAIL_CROP_PADDING_FIELD = {
|
|
36322
|
+
min: 0,
|
|
36323
|
+
max: 1,
|
|
36324
|
+
step: .05,
|
|
36325
|
+
default: DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio
|
|
36326
|
+
};
|
|
36327
|
+
/**
|
|
36328
|
+
* Derive the crop rectangle for one parent detection.
|
|
36329
|
+
*
|
|
36330
|
+
* Order: pad by `paddingRatio` of the box's own size → optionally square in
|
|
36331
|
+
* pixel space around the padded centre → keep it inside the frame. Pure:
|
|
36332
|
+
* always returns a new rect and never mutates `bbox`.
|
|
36333
|
+
*
|
|
36334
|
+
* Edge handling differs by mode, on purpose:
|
|
36335
|
+
*
|
|
36336
|
+
* - **unsquared** — TRUNCATED at the frame border, byte-for-byte what the live
|
|
36337
|
+
* path has always done (`padAndClampFrameBbox`). A subject against the edge
|
|
36338
|
+
* gets a slightly smaller window. Changing this would silently reinterpret
|
|
36339
|
+
* every edge-touching vector already in the index.
|
|
36340
|
+
* - **squared** — SLID inward instead, because a truncated square is not
|
|
36341
|
+
* square and squaring exists precisely to preserve the aspect the model
|
|
36342
|
+
* sees. It only shrinks when the square is larger than the frame itself.
|
|
36343
|
+
*/
|
|
36344
|
+
function deriveDetailCropRect(bbox, frameWidth, frameHeight, convention) {
|
|
36345
|
+
const padX = convention.paddingRatio * bbox.w;
|
|
36346
|
+
const padY = convention.paddingRatio * bbox.h;
|
|
36347
|
+
const padded = {
|
|
36348
|
+
x: bbox.x - padX,
|
|
36349
|
+
y: bbox.y - padY,
|
|
36350
|
+
w: bbox.w + 2 * padX,
|
|
36351
|
+
h: bbox.h + 2 * padY
|
|
36352
|
+
};
|
|
36353
|
+
return convention.square ? slideInsideFrame(squareInPixels(padded, frameWidth, frameHeight), frameWidth, frameHeight) : truncateToFrame(padded, frameWidth, frameHeight);
|
|
36354
|
+
}
|
|
36355
|
+
/**
|
|
36356
|
+
* Grow the shorter side to the longer one around the window's centre, bounded
|
|
36357
|
+
* by the frame's shorter side — a square larger than the frame cannot exist,
|
|
36358
|
+
* and collapsing to the frame's short side is the most that does.
|
|
36359
|
+
*/
|
|
36360
|
+
function squareInPixels(rect, frameWidth, frameHeight) {
|
|
36361
|
+
const side = Math.min(Math.max(rect.w, rect.h), Math.min(frameWidth, frameHeight));
|
|
36362
|
+
const cx = rect.x + rect.w / 2;
|
|
36363
|
+
const cy = rect.y + rect.h / 2;
|
|
36364
|
+
return {
|
|
36365
|
+
x: cx - side / 2,
|
|
36366
|
+
y: cy - side / 2,
|
|
36367
|
+
w: side,
|
|
36368
|
+
h: side
|
|
36369
|
+
};
|
|
36370
|
+
}
|
|
36371
|
+
/**
|
|
36372
|
+
* Cut the window at the frame border — the pre-unification live behaviour,
|
|
36373
|
+
* preserved exactly so unsquared crops keep matching the stored index.
|
|
36374
|
+
*/
|
|
36375
|
+
function truncateToFrame(rect, frameWidth, frameHeight) {
|
|
36376
|
+
const x1 = Math.max(0, rect.x);
|
|
36377
|
+
const y1 = Math.max(0, rect.y);
|
|
36378
|
+
const x2 = Math.min(frameWidth, rect.x + rect.w);
|
|
36379
|
+
const y2 = Math.min(frameHeight, rect.y + rect.h);
|
|
36380
|
+
return {
|
|
36381
|
+
x: x1,
|
|
36382
|
+
y: y1,
|
|
36383
|
+
w: Math.max(0, x2 - x1),
|
|
36384
|
+
h: Math.max(0, y2 - y1)
|
|
36385
|
+
};
|
|
36386
|
+
}
|
|
36387
|
+
/**
|
|
36388
|
+
* Move the window inside the frame keeping its extent — used only for squared
|
|
36389
|
+
* windows, where truncating would destroy the squareness that is the point.
|
|
36390
|
+
*/
|
|
36391
|
+
function slideInsideFrame(rect, frameWidth, frameHeight) {
|
|
36392
|
+
const w = Math.max(0, Math.min(rect.w, frameWidth));
|
|
36393
|
+
const h = Math.max(0, Math.min(rect.h, frameHeight));
|
|
36394
|
+
return {
|
|
36395
|
+
x: Math.min(Math.max(0, rect.x), Math.max(0, frameWidth - w)),
|
|
36396
|
+
y: Math.min(Math.max(0, rect.y), Math.max(0, frameHeight - h)),
|
|
36397
|
+
w,
|
|
36398
|
+
h
|
|
36399
|
+
};
|
|
36400
|
+
}
|
|
36401
|
+
//#endregion
|
|
34883
36402
|
//#region src/helpers/bind-addon-actions.ts
|
|
34884
36403
|
/**
|
|
34885
36404
|
* Bind an addon's custom-action catalog to its tRPC surface, returning a
|
|
@@ -35131,4 +36650,4 @@ function enumerateInferenceDevices(hw) {
|
|
|
35131
36650
|
return out;
|
|
35132
36651
|
}
|
|
35133
36652
|
//#endregion
|
|
35134
|
-
export { ACCESSORY_LABEL, ALL_CAPABILITY_DEFINITIONS, APPLE_SA_TO_MACRO, AUDIO_BACKEND_CHOICES, AUDIO_MACRO_LABELS, 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, 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, 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, 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_EVENT_COLOR, DEFAULT_FEATURES, DEFAULT_RETENTION, DEFAULT_SCRUB_THUMBNAIL_PRESET, 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, 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, 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, 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, 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, TrackProjectionSchema, TrackSchema, 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, 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, authProviderCapability, autoAssignProfiles, automationControlCapability, backupCapability, batteryCapability, bestLocationMatch, binaryCapability, bindAddonActions, brightnessCapability, brokerCapability, buildAddonRouteProvider, buildEventKindDescriptor, buildModelVariantGroups, buildNcTaxonomy, buildStreamParamsConfigSchema, buttonCapability, cameraCredentialsCapability, cameraPipelineConfigCapability, cameraStreamsCapability, canConvertUnit, carbonMonoxideCapability, cellsToRects, classifyStream, classifyStreams, climateControlCapability, collectHydratedFieldEntries, collectHydratedFieldValues, colorCapability, colorForKind, compileExpression, compileExpressionSafe, connectivityCapability, consumablesCapability, contactCapability, controlCapability, convertUnit, coreBlocksCapability, cosineSimilarity, coverCapability, createDeviceProxy, createDurableState, createEvent, createExpressionScope, createLazyTrpcSource, createMirrorSource, createRuntimeStateBridge, createSliceHandle, createSystemProxy, customAction, customModelRegistryCapability, dataStoreProviderCapability, dayNightCapability, decodeVectorBase64, decoderCapability, defaultDeviceFor, defineCustomActions, deriveRecordingMode, describeModelVariant, detectionPipelineCapability, deviceAdoptionCapability, deviceBackendToFormat, deviceCustomAction, deviceDiscoveryCapability, deviceExportCapability, deviceManagerCapability, deviceMatchesProfile, deviceOpsCapability, deviceProviderCapability, deviceStateCapability, deviceStatusCapability, doorbellCapability, 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, isAgentOnlyPlacement, isArrayOutputSchema, isBaseConditionKey, isCollectionArrayMethod, isDeployableToAgent, isDeviceConfigCap, isDeviceScopedCap, isEvent, isNode, isObjectInput, isVoidInput, jobKindSchema, kebabToCamel, knownValues, lawnMowerControlCapability, lifecycleJobSchema, lifecycleJobScopeSchema, lifecycleJobStateSchema, lifecycleTaskSchema, llmCapability, llmRuntimeCapability, localNetworkCapability, locationSimilarity, lockControlCapability, 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, pickPreferredRtspEntry, pickerForCondition, pipelineAnalyticsCapability, pipelineExecutorCapability, pipelineOrchestratorCapability, pipelineRunnerCapability, plateGalleryCapability, platformProbeCapability, powerMeterCapability, prepareNotification, presenceCapability, pressureSensorCapability, privacyMaskCapability, procedureAuthKey, ptzAutotrackCapability, ptzCapability, pythonScriptForBackend, readDeviceStateFrom, readNodePin, readinessKey, rebootCapability, recordingCapability, recordingExportCapability, rectsToCells, requiresPython, resolveAddonExecution, resolveAddonGroup, resolveAddonPlacement, resolveAddonRuntime, resolveCapMount, resolveDetectionRuntime, resolveDeviceControlKind, resolveDeviceProfile, 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, 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 };
|
|
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 };
|