@camstack/addon-pipeline-orchestrator 1.1.27 → 1.1.28
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/_stub.js +2 -2
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-NVcZ0pFA.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-DaBzEEJK.mjs} +3 -3
- package/dist/_virtual_mf___mfe_internal__addon_pipeline_orchestrator_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DF4cZqbE.mjs +26 -0
- package/dist/_virtual_mf___mfe_internal__addon_pipeline_orchestrator_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-ScLTfhI7.mjs +26 -0
- package/dist/{hostInit-oAid8Or_.mjs → hostInit-CSrBjaSu.mjs} +3 -3
- package/dist/index.js +365 -21
- package/dist/index.mjs +365 -21
- package/dist/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/_virtual_mf___mfe_internal__addon_pipeline_orchestrator_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DPNDc6_1.mjs +0 -26
- package/dist/_virtual_mf___mfe_internal__addon_pipeline_orchestrator_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BA0gpKU7.mjs +0 -26
package/dist/index.js
CHANGED
|
@@ -4631,7 +4631,7 @@ function _instanceof(cls, params = {}) {
|
|
|
4631
4631
|
return inst;
|
|
4632
4632
|
}
|
|
4633
4633
|
//#endregion
|
|
4634
|
-
//#region ../types/dist/sleep-
|
|
4634
|
+
//#region ../types/dist/sleep-CZDdRBua.mjs
|
|
4635
4635
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
4636
4636
|
EventCategory["SystemBoot"] = "system.boot";
|
|
4637
4637
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -7638,7 +7638,16 @@ var DecoderStatsSchema = object({
|
|
|
7638
7638
|
inputFps: number(),
|
|
7639
7639
|
outputFps: number(),
|
|
7640
7640
|
avgDecodeTimeMs: number(),
|
|
7641
|
-
droppedFrames: number()
|
|
7641
|
+
droppedFrames: number(),
|
|
7642
|
+
/**
|
|
7643
|
+
* Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
|
|
7644
|
+
* lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
|
|
7645
|
+
* the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
|
|
7646
|
+
* is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
|
|
7647
|
+
*/
|
|
7648
|
+
lagMs: number().optional(),
|
|
7649
|
+
effectiveFps: number().optional(),
|
|
7650
|
+
adaptiveFps: number().optional()
|
|
7642
7651
|
});
|
|
7643
7652
|
var DecoderSessionConfigSchema = object({
|
|
7644
7653
|
codec: string(),
|
|
@@ -7679,7 +7688,15 @@ var DecoderSessionConfigSchema = object({
|
|
|
7679
7688
|
* other — `pullFrames` returns nothing for an `'shm'` session and
|
|
7680
7689
|
* `pullHandles` returns nothing for a `'callback'` session.
|
|
7681
7690
|
*/
|
|
7682
|
-
frameSink: _enum(["callback", "shm"]).default("callback")
|
|
7691
|
+
frameSink: _enum(["callback", "shm"]).default("callback"),
|
|
7692
|
+
/**
|
|
7693
|
+
* Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
|
|
7694
|
+
* a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
|
|
7695
|
+
* real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
|
|
7696
|
+
* stream-broker's `streamingDebug` gate — off by default so production logs
|
|
7697
|
+
* stay quiet and the emit path pays zero per-frame cost when disabled.
|
|
7698
|
+
*/
|
|
7699
|
+
debug: boolean().optional()
|
|
7683
7700
|
});
|
|
7684
7701
|
var EncodeProfileSchema = object({
|
|
7685
7702
|
video: object({
|
|
@@ -9898,6 +9915,75 @@ DeviceType.Cover, method(object({ deviceId: number().int().nonnegative() }), _vo
|
|
|
9898
9915
|
auth: "admin"
|
|
9899
9916
|
});
|
|
9900
9917
|
/**
|
|
9918
|
+
* Vendor-neutral day/night (IR-cut) control — the per-camera config cap
|
|
9919
|
+
* shared by reolink / hikvision / amcrest. Models the common firmware
|
|
9920
|
+
* surface: the IR-cut switching MODE plus the two knobs that gate it
|
|
9921
|
+
* (photocell `sensitivity` + `switchDelaySec`). Each vendor maps these
|
|
9922
|
+
* onto its own ISAPI / Baichuan / Dahua-CGI fields; the cap standardises
|
|
9923
|
+
* the shape so ONE derived-form renders every camera.
|
|
9924
|
+
*
|
|
9925
|
+
* Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
|
|
9926
|
+
* `getOptions` advertises per-camera availability, `getStatus` (auto-
|
|
9927
|
+
* injected from `status`) reports the live values, and a single
|
|
9928
|
+
* `setSettings` mutation applies a partial change. No hand-written
|
|
9929
|
+
* settings-contribution methods — the framework derives the UI + save
|
|
9930
|
+
* routing from this surface.
|
|
9931
|
+
*/
|
|
9932
|
+
/** IR-cut switching mode. `schedule` = time-of-day table configured on the camera. */
|
|
9933
|
+
var DayNightModeSchema = _enum([
|
|
9934
|
+
"auto",
|
|
9935
|
+
"day",
|
|
9936
|
+
"night",
|
|
9937
|
+
"schedule"
|
|
9938
|
+
]);
|
|
9939
|
+
/** Normalized numeric range descriptor — `{ min, max, step }` per the
|
|
9940
|
+
* getOptions availability convention. Normalized values are 0–100. */
|
|
9941
|
+
var NormalizedRangeSchema$1 = object({
|
|
9942
|
+
min: number(),
|
|
9943
|
+
max: number(),
|
|
9944
|
+
step: number()
|
|
9945
|
+
});
|
|
9946
|
+
object({
|
|
9947
|
+
mode: DayNightModeSchema,
|
|
9948
|
+
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
9949
|
+
sensitivity: number().optional(),
|
|
9950
|
+
/** Delay before the IR-cut filter flips, in seconds. */
|
|
9951
|
+
switchDelaySec: number().optional(),
|
|
9952
|
+
lastFetchedAt: number()
|
|
9953
|
+
});
|
|
9954
|
+
/**
|
|
9955
|
+
* Per-camera availability descriptor — drives which controls the admin UI
|
|
9956
|
+
* renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
|
|
9957
|
+
* (normalized 0–100); the mode choice-set as an array. A provider returns
|
|
9958
|
+
* honest, camera-probed values — never hardcoded.
|
|
9959
|
+
*/
|
|
9960
|
+
var DayNightOptionsSchema = object({
|
|
9961
|
+
/** Modes this camera accepts. Empty → the camera has no configurable day/night mode. */
|
|
9962
|
+
modes: array(DayNightModeSchema),
|
|
9963
|
+
supportsSensitivity: boolean(),
|
|
9964
|
+
/** Present when `supportsSensitivity` — the normalized 0–100 range. */
|
|
9965
|
+
sensitivity: NormalizedRangeSchema$1.optional(),
|
|
9966
|
+
supportsSwitchDelay: boolean(),
|
|
9967
|
+
/** Present when `supportsSwitchDelay` — the allowed delay range in seconds. */
|
|
9968
|
+
switchDelaySec: NormalizedRangeSchema$1.optional()
|
|
9969
|
+
});
|
|
9970
|
+
/**
|
|
9971
|
+
* Partial change to the day/night config — every field optional. A
|
|
9972
|
+
* provider ignores fields it does not support.
|
|
9973
|
+
*/
|
|
9974
|
+
var DayNightSettingsPatchSchema = object({
|
|
9975
|
+
mode: DayNightModeSchema.optional(),
|
|
9976
|
+
sensitivity: number().optional(),
|
|
9977
|
+
switchDelaySec: number().optional()
|
|
9978
|
+
});
|
|
9979
|
+
DeviceType.Camera, method(object({ deviceId: number() }), DayNightOptionsSchema), method(object({
|
|
9980
|
+
deviceId: number(),
|
|
9981
|
+
settings: DayNightSettingsPatchSchema
|
|
9982
|
+
}), _void(), {
|
|
9983
|
+
kind: "mutation",
|
|
9984
|
+
auth: "admin"
|
|
9985
|
+
});
|
|
9986
|
+
/**
|
|
9901
9987
|
* Identity envelope for a device's upstream-system metadata.
|
|
9902
9988
|
*
|
|
9903
9989
|
* Two jobs:
|
|
@@ -10253,6 +10339,130 @@ object({
|
|
|
10253
10339
|
});
|
|
10254
10340
|
DeviceType.Image;
|
|
10255
10341
|
/**
|
|
10342
|
+
* Vendor-neutral image / picture-adjustment cap — the per-camera config
|
|
10343
|
+
* cap shared by reolink / hikvision / amcrest. Models the common ISP
|
|
10344
|
+
* surface: the four picture sliders (brightness / contrast / saturation /
|
|
10345
|
+
* sharpness), orientation (mirror / flip / rotate), white-balance,
|
|
10346
|
+
* exposure and backlight-compensation modes.
|
|
10347
|
+
*
|
|
10348
|
+
* NORMALIZATION: every slider is a normalized int 0–100. Vendors expose
|
|
10349
|
+
* these natively as 0–100 or 0–255 (or other ranges); each provider maps
|
|
10350
|
+
* its native range to/from this normalized 0–100 space so the cap surface
|
|
10351
|
+
* (and the derived form) is identical across cameras. `warmth` (manual
|
|
10352
|
+
* white-balance) is likewise normalized 0–100.
|
|
10353
|
+
*
|
|
10354
|
+
* Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
|
|
10355
|
+
* `getOptions` advertises per-camera availability, `getStatus` (auto-
|
|
10356
|
+
* injected from `status`) reports the live values, and a single
|
|
10357
|
+
* `setSettings` mutation applies a partial change. No hand-written
|
|
10358
|
+
* settings-contribution methods — the framework derives the UI + save
|
|
10359
|
+
* routing from this surface.
|
|
10360
|
+
*/
|
|
10361
|
+
/** Sensor/image rotation, degrees clockwise. */
|
|
10362
|
+
var ImageRotateSchema = _enum([
|
|
10363
|
+
"0",
|
|
10364
|
+
"90",
|
|
10365
|
+
"180",
|
|
10366
|
+
"270"
|
|
10367
|
+
]);
|
|
10368
|
+
/** White-balance mode. `manual` unlocks the normalized `warmth` knob. */
|
|
10369
|
+
var WhiteBalanceModeSchema = _enum(["auto", "manual"]);
|
|
10370
|
+
/** Exposure mode. */
|
|
10371
|
+
var ExposureModeSchema = _enum(["auto", "manual"]);
|
|
10372
|
+
/**
|
|
10373
|
+
* Backlight-compensation mode:
|
|
10374
|
+
* - `off` — disabled
|
|
10375
|
+
* - `blc` — backlight compensation
|
|
10376
|
+
* - `wdr` — wide dynamic range
|
|
10377
|
+
* - `hlc` — highlight compensation
|
|
10378
|
+
*/
|
|
10379
|
+
var BacklightModeSchema = _enum([
|
|
10380
|
+
"off",
|
|
10381
|
+
"blc",
|
|
10382
|
+
"wdr",
|
|
10383
|
+
"hlc"
|
|
10384
|
+
]);
|
|
10385
|
+
/** Normalized numeric range descriptor — `{ min, max, step }` per the
|
|
10386
|
+
* getOptions availability convention. Slider values are normalized 0–100. */
|
|
10387
|
+
var NormalizedRangeSchema = object({
|
|
10388
|
+
min: number(),
|
|
10389
|
+
max: number(),
|
|
10390
|
+
step: number()
|
|
10391
|
+
});
|
|
10392
|
+
object({
|
|
10393
|
+
/** Normalized 0–100. */
|
|
10394
|
+
brightness: number().optional(),
|
|
10395
|
+
/** Normalized 0–100. */
|
|
10396
|
+
contrast: number().optional(),
|
|
10397
|
+
/** Normalized 0–100. */
|
|
10398
|
+
saturation: number().optional(),
|
|
10399
|
+
/** Normalized 0–100. */
|
|
10400
|
+
sharpness: number().optional(),
|
|
10401
|
+
mirror: boolean().optional(),
|
|
10402
|
+
flip: boolean().optional(),
|
|
10403
|
+
rotate: ImageRotateSchema.optional(),
|
|
10404
|
+
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
10405
|
+
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
10406
|
+
warmth: number().optional(),
|
|
10407
|
+
exposureMode: ExposureModeSchema.optional(),
|
|
10408
|
+
backlightMode: BacklightModeSchema.optional(),
|
|
10409
|
+
lastFetchedAt: number()
|
|
10410
|
+
});
|
|
10411
|
+
/**
|
|
10412
|
+
* Per-camera availability descriptor — drives which controls the admin UI
|
|
10413
|
+
* renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
|
|
10414
|
+
* (the normalized 0–100 range); enums as arrays of supported values (empty
|
|
10415
|
+
* array → control hidden). A provider returns honest, camera-probed values
|
|
10416
|
+
* — never hardcoded.
|
|
10417
|
+
*/
|
|
10418
|
+
var ImageSettingsOptionsSchema = object({
|
|
10419
|
+
supportsBrightness: boolean(),
|
|
10420
|
+
brightness: NormalizedRangeSchema.optional(),
|
|
10421
|
+
supportsContrast: boolean(),
|
|
10422
|
+
contrast: NormalizedRangeSchema.optional(),
|
|
10423
|
+
supportsSaturation: boolean(),
|
|
10424
|
+
saturation: NormalizedRangeSchema.optional(),
|
|
10425
|
+
supportsSharpness: boolean(),
|
|
10426
|
+
sharpness: NormalizedRangeSchema.optional(),
|
|
10427
|
+
supportsMirror: boolean(),
|
|
10428
|
+
supportsFlip: boolean(),
|
|
10429
|
+
/** Supported rotation values. Empty → rotation not configurable. */
|
|
10430
|
+
rotateOptions: array(ImageRotateSchema),
|
|
10431
|
+
/** Supported white-balance modes. Empty → white-balance not configurable. */
|
|
10432
|
+
whiteBalanceModes: array(WhiteBalanceModeSchema),
|
|
10433
|
+
supportsWarmth: boolean(),
|
|
10434
|
+
/** Present when `supportsWarmth` — the normalized 0–100 range. */
|
|
10435
|
+
warmth: NormalizedRangeSchema.optional(),
|
|
10436
|
+
/** Supported exposure modes. Empty → exposure not configurable. */
|
|
10437
|
+
exposureModes: array(ExposureModeSchema),
|
|
10438
|
+
/** Supported backlight modes. Empty → backlight-compensation not configurable. */
|
|
10439
|
+
backlightModes: array(BacklightModeSchema)
|
|
10440
|
+
});
|
|
10441
|
+
/**
|
|
10442
|
+
* Partial change to the image config — every field optional. Slider values
|
|
10443
|
+
* are normalized 0–100. A provider ignores fields it does not support.
|
|
10444
|
+
*/
|
|
10445
|
+
var ImageSettingsPatchSchema = object({
|
|
10446
|
+
brightness: number().optional(),
|
|
10447
|
+
contrast: number().optional(),
|
|
10448
|
+
saturation: number().optional(),
|
|
10449
|
+
sharpness: number().optional(),
|
|
10450
|
+
mirror: boolean().optional(),
|
|
10451
|
+
flip: boolean().optional(),
|
|
10452
|
+
rotate: ImageRotateSchema.optional(),
|
|
10453
|
+
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
10454
|
+
warmth: number().optional(),
|
|
10455
|
+
exposureMode: ExposureModeSchema.optional(),
|
|
10456
|
+
backlightMode: BacklightModeSchema.optional()
|
|
10457
|
+
});
|
|
10458
|
+
DeviceType.Camera, method(object({ deviceId: number() }), ImageSettingsOptionsSchema), method(object({
|
|
10459
|
+
deviceId: number(),
|
|
10460
|
+
settings: ImageSettingsPatchSchema
|
|
10461
|
+
}), _void(), {
|
|
10462
|
+
kind: "mutation",
|
|
10463
|
+
auth: "admin"
|
|
10464
|
+
});
|
|
10465
|
+
/**
|
|
10256
10466
|
* Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
|
|
10257
10467
|
* with a mowing lifecycle plus a dock action.
|
|
10258
10468
|
*
|
|
@@ -11315,6 +11525,16 @@ var RunnerCameraConfigSchema = object({
|
|
|
11315
11525
|
* this gate is bypassed.
|
|
11316
11526
|
*/
|
|
11317
11527
|
onboardMotionDrivesAnalyzer: boolean().default(true),
|
|
11528
|
+
/**
|
|
11529
|
+
* Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
|
|
11530
|
+
* never arms the periodic recheck timer, regardless of `occupancyRecheckSec` —
|
|
11531
|
+
* this is off by default because the recheck re-subscribes a detection session
|
|
11532
|
+
* every N seconds while `watching`, a major source of pull-decoder re-dial
|
|
11533
|
+
* churn (each cycle creates+tears a session → RTSP re-dial → latency). The
|
|
11534
|
+
* `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
|
|
11535
|
+
* (and only render) when this is enabled.
|
|
11536
|
+
*/
|
|
11537
|
+
occupancyRecheckEnabled: boolean().default(false),
|
|
11318
11538
|
occupancyRecheckSec: number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
|
|
11319
11539
|
occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
|
|
11320
11540
|
/**
|
|
@@ -11365,6 +11585,8 @@ var RunnerCameraDeviceUIFields = [
|
|
|
11365
11585
|
default: motionFpsField.default,
|
|
11366
11586
|
showValue: true,
|
|
11367
11587
|
unit: "fps",
|
|
11588
|
+
nullable: true,
|
|
11589
|
+
nullLabel: "Default",
|
|
11368
11590
|
showWhen: {
|
|
11369
11591
|
field: "motionSources",
|
|
11370
11592
|
includes: "analyzer"
|
|
@@ -11379,7 +11601,9 @@ var RunnerCameraDeviceUIFields = [
|
|
|
11379
11601
|
step: detectionFpsField.step,
|
|
11380
11602
|
default: detectionFpsField.default,
|
|
11381
11603
|
showValue: true,
|
|
11382
|
-
unit: "fps"
|
|
11604
|
+
unit: "fps",
|
|
11605
|
+
nullable: true,
|
|
11606
|
+
nullLabel: "Default"
|
|
11383
11607
|
},
|
|
11384
11608
|
{
|
|
11385
11609
|
key: "motionCooldownMs",
|
|
@@ -11392,7 +11616,9 @@ var RunnerCameraDeviceUIFields = [
|
|
|
11392
11616
|
default: motionCooldownMsField.default,
|
|
11393
11617
|
showValue: true,
|
|
11394
11618
|
unit: "s",
|
|
11395
|
-
displayScale: 1e3
|
|
11619
|
+
displayScale: 1e3,
|
|
11620
|
+
nullable: true,
|
|
11621
|
+
nullLabel: "Default"
|
|
11396
11622
|
},
|
|
11397
11623
|
{
|
|
11398
11624
|
key: "onboardMotionDrivesAnalyzer",
|
|
@@ -11405,17 +11631,29 @@ var RunnerCameraDeviceUIFields = [
|
|
|
11405
11631
|
includes: "onboard"
|
|
11406
11632
|
}
|
|
11407
11633
|
},
|
|
11634
|
+
{
|
|
11635
|
+
key: "occupancyRecheckEnabled",
|
|
11636
|
+
type: "boolean",
|
|
11637
|
+
style: "checkbox",
|
|
11638
|
+
label: "Occupancy re-check",
|
|
11639
|
+
description: "Periodically re-sample a few frames during the watching phase to confirm the scene is truly empty (catches stationary objects motion-gating would miss). Off by default — it adds decoder re-dial churn.",
|
|
11640
|
+
default: false
|
|
11641
|
+
},
|
|
11408
11642
|
{
|
|
11409
11643
|
key: "occupancyRecheckSec",
|
|
11410
11644
|
type: "slider",
|
|
11411
11645
|
label: "Occupancy re-check interval",
|
|
11412
|
-
description: "How often (in seconds) the runner re-samples a few frames to confirm the scene is truly empty during the watching phase.
|
|
11646
|
+
description: "How often (in seconds) the runner re-samples a few frames to confirm the scene is truly empty during the watching phase.",
|
|
11413
11647
|
min: occupancyRecheckSecField.min,
|
|
11414
11648
|
max: occupancyRecheckSecField.max,
|
|
11415
11649
|
step: occupancyRecheckSecField.step,
|
|
11416
11650
|
default: occupancyRecheckSecField.default,
|
|
11417
11651
|
showValue: true,
|
|
11418
|
-
unit: "s"
|
|
11652
|
+
unit: "s",
|
|
11653
|
+
showWhen: {
|
|
11654
|
+
field: "occupancyRecheckEnabled",
|
|
11655
|
+
equals: true
|
|
11656
|
+
}
|
|
11419
11657
|
},
|
|
11420
11658
|
{
|
|
11421
11659
|
key: "occupancyRecheckFrames",
|
|
@@ -11426,7 +11664,11 @@ var RunnerCameraDeviceUIFields = [
|
|
|
11426
11664
|
max: occupancyRecheckFramesField.max,
|
|
11427
11665
|
step: occupancyRecheckFramesField.step,
|
|
11428
11666
|
default: occupancyRecheckFramesField.default,
|
|
11429
|
-
showValue: true
|
|
11667
|
+
showValue: true,
|
|
11668
|
+
showWhen: {
|
|
11669
|
+
field: "occupancyRecheckEnabled",
|
|
11670
|
+
equals: true
|
|
11671
|
+
}
|
|
11430
11672
|
}
|
|
11431
11673
|
];
|
|
11432
11674
|
/**
|
|
@@ -20005,6 +20247,18 @@ Object.freeze({
|
|
|
20005
20247
|
addonId: null,
|
|
20006
20248
|
access: "view"
|
|
20007
20249
|
},
|
|
20250
|
+
"dayNight.getOptions": {
|
|
20251
|
+
capName: "day-night",
|
|
20252
|
+
capScope: "device",
|
|
20253
|
+
addonId: null,
|
|
20254
|
+
access: "view"
|
|
20255
|
+
},
|
|
20256
|
+
"dayNight.setSettings": {
|
|
20257
|
+
capName: "day-night",
|
|
20258
|
+
capScope: "device",
|
|
20259
|
+
addonId: null,
|
|
20260
|
+
access: "create"
|
|
20261
|
+
},
|
|
20008
20262
|
"decoder.createSession": {
|
|
20009
20263
|
capName: "decoder",
|
|
20010
20264
|
capScope: "system",
|
|
@@ -20935,6 +21189,18 @@ Object.freeze({
|
|
|
20935
21189
|
addonId: null,
|
|
20936
21190
|
access: "create"
|
|
20937
21191
|
},
|
|
21192
|
+
"imageSettings.getOptions": {
|
|
21193
|
+
capName: "image-settings",
|
|
21194
|
+
capScope: "device",
|
|
21195
|
+
addonId: null,
|
|
21196
|
+
access: "view"
|
|
21197
|
+
},
|
|
21198
|
+
"imageSettings.setSettings": {
|
|
21199
|
+
capName: "image-settings",
|
|
21200
|
+
capScope: "device",
|
|
21201
|
+
addonId: null,
|
|
21202
|
+
access: "create"
|
|
21203
|
+
},
|
|
20938
21204
|
"integrations.create": {
|
|
20939
21205
|
capName: "integrations",
|
|
20940
21206
|
capScope: "system",
|
|
@@ -24514,7 +24780,8 @@ var DEFAULT_WATCHDOG_THRESHOLDS = {
|
|
|
24514
24780
|
audioMs: 9e4,
|
|
24515
24781
|
motionMs: 3e4,
|
|
24516
24782
|
detectionMs: 6e4,
|
|
24517
|
-
maxRecoveryAttempts: 3
|
|
24783
|
+
maxRecoveryAttempts: 3,
|
|
24784
|
+
exhaustedRetryMs: 6e4
|
|
24518
24785
|
};
|
|
24519
24786
|
var STAGE_THRESHOLD_KEY = {
|
|
24520
24787
|
audio: "audioMs",
|
|
@@ -24535,7 +24802,8 @@ var PipelineWatchdog = class {
|
|
|
24535
24802
|
const stages = /* @__PURE__ */ new Map();
|
|
24536
24803
|
for (const [stage] of cam.continuousStages) stages.set(stage, {
|
|
24537
24804
|
lastSeenMs: now,
|
|
24538
|
-
attempts: 0
|
|
24805
|
+
attempts: 0,
|
|
24806
|
+
lastAttemptMs: 0
|
|
24539
24807
|
});
|
|
24540
24808
|
this.state.set(cam.deviceId, stages);
|
|
24541
24809
|
}
|
|
@@ -24558,7 +24826,10 @@ var PipelineWatchdog = class {
|
|
|
24558
24826
|
else this.deps.logger.info(line);
|
|
24559
24827
|
for (const r of recoveries) {
|
|
24560
24828
|
const rt = this.state.get(cam.deviceId)?.get(r.stage);
|
|
24561
|
-
if (rt)
|
|
24829
|
+
if (rt) {
|
|
24830
|
+
if (rt.attempts < this.deps.thresholds.maxRecoveryAttempts) rt.attempts += 1;
|
|
24831
|
+
rt.lastAttemptMs = now;
|
|
24832
|
+
}
|
|
24562
24833
|
this.deps.recover(cam.deviceId, r.stage, r.streamId);
|
|
24563
24834
|
}
|
|
24564
24835
|
}
|
|
@@ -24602,7 +24873,13 @@ var PipelineWatchdog = class {
|
|
|
24602
24873
|
if (staleness <= thresholdMs) parts.push(`${stage}=${stageMode[stage]}@${streamId}(OK ${sSec}s)`);
|
|
24603
24874
|
else if (rt.attempts >= this.deps.thresholds.maxRecoveryAttempts) {
|
|
24604
24875
|
stalled = true;
|
|
24605
|
-
|
|
24876
|
+
if (now - rt.lastAttemptMs >= this.deps.thresholds.exhaustedRetryMs) {
|
|
24877
|
+
recoveries.push({
|
|
24878
|
+
stage,
|
|
24879
|
+
streamId
|
|
24880
|
+
});
|
|
24881
|
+
parts.push(`${stage}=${stageMode[stage]}@${streamId}(STALLED ${sSec}s · exhausted ${rt.attempts} · retrying)`);
|
|
24882
|
+
} else parts.push(`${stage}=${stageMode[stage]}@${streamId}(STALLED ${sSec}s · exhausted ${rt.attempts})`);
|
|
24606
24883
|
} else {
|
|
24607
24884
|
stalled = true;
|
|
24608
24885
|
recoveries.push({
|
|
@@ -24954,6 +25231,24 @@ function isPipelinePhaseMode(v) {
|
|
|
24954
25231
|
var PREFERRED_AGENT_SETTING = "preferredAgent";
|
|
24955
25232
|
/** Key under which the orchestrator stores the per-device audio node pin. */
|
|
24956
25233
|
var AUDIO_NODE_SETTING = "audioNodeId";
|
|
25234
|
+
/**
|
|
25235
|
+
* Target PCM window duration, in ms, for audio classification.
|
|
25236
|
+
*
|
|
25237
|
+
* Sized for the ~1 s inference window the downstream classifiers expect —
|
|
25238
|
+
* YAMNet consumes a 0.975 s frame and Apple SoundAnalysis a ~1 s frame.
|
|
25239
|
+
* The broker's `AudioCodecSession` no longer batches (its 500 ms
|
|
25240
|
+
* accumulator was removed for WebRTC latency), so decoded codec chunks now
|
|
25241
|
+
* arrive at ~21–64 ms each — ~16–48 chunks per second per camera. Feeding
|
|
25242
|
+
* each tiny chunk to the analyzer meant one cross-process `analyseChunk`
|
|
25243
|
+
* RPC + one `PipelineAudioInferenceResult` event PER chunk for a classifier
|
|
25244
|
+
* that (a) throttles to ~2 Hz internally anyway and (b) needs a ~1 s window
|
|
25245
|
+
* for accurate inference. We instead accumulate raw PCM per device and flush
|
|
25246
|
+
* ONE classify + ONE event per ~1 s window: ~1 RPC/event/s/camera and a
|
|
25247
|
+
* correctly-sized inference frame.
|
|
25248
|
+
*/
|
|
25249
|
+
var AUDIO_WINDOW_TARGET_MS = 1e3;
|
|
25250
|
+
/** f32le PCM = 4 bytes per sample. */
|
|
25251
|
+
var F32_BYTES_PER_SAMPLE = 4;
|
|
24957
25252
|
var DEFAULT_BROKER_CALL_TIMEOUT_MS = 5e3;
|
|
24958
25253
|
/** Debounce window for `scheduleReconcile` — coalesces bursts of topology/slot-change signals. */
|
|
24959
25254
|
var RECONCILE_DEBOUNCE_MS = 200;
|
|
@@ -28862,6 +29157,13 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
28862
29157
|
if (typeof v !== "number") throw new Error(`orchestrator schema missing required number '${key}' for device ${deviceId}`);
|
|
28863
29158
|
return v;
|
|
28864
29159
|
};
|
|
29160
|
+
const numberOrDefault = (key) => {
|
|
29161
|
+
const v = flat[key];
|
|
29162
|
+
if (typeof v === "number") return v;
|
|
29163
|
+
const uiField = RunnerCameraDeviceUIFields.find((f) => f.key === key);
|
|
29164
|
+
const dflt = uiField && "default" in uiField ? uiField.default : void 0;
|
|
29165
|
+
return typeof dflt === "number" ? dflt : 0;
|
|
29166
|
+
};
|
|
28865
29167
|
try {
|
|
28866
29168
|
const features = await this.lookupDeviceFeatures(deviceId);
|
|
28867
29169
|
const profile = resolveDeviceProfile(features);
|
|
@@ -28879,6 +29181,8 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
28879
29181
|
const audioMode = typeof userAudioMode === "string" && isPipelinePhaseMode(userAudioMode) ? userAudioMode : profile?.defaults.audioMode ?? "always-on";
|
|
28880
29182
|
const userOnboardMotionDrivesAnalyzer = raw["onboardMotionDrivesAnalyzer"];
|
|
28881
29183
|
const onboardMotionDrivesAnalyzer = typeof userOnboardMotionDrivesAnalyzer === "boolean" ? userOnboardMotionDrivesAnalyzer : true;
|
|
29184
|
+
const userOccupancyRecheckEnabled = raw["occupancyRecheckEnabled"];
|
|
29185
|
+
const occupancyRecheckEnabled = typeof userOccupancyRecheckEnabled === "boolean" ? userOccupancyRecheckEnabled : false;
|
|
28882
29186
|
const occupancyRecheckSec = mustNumber("occupancyRecheckSec");
|
|
28883
29187
|
const occupancyRecheckFrames = mustNumber("occupancyRecheckFrames");
|
|
28884
29188
|
return {
|
|
@@ -28887,12 +29191,13 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
28887
29191
|
motionSources,
|
|
28888
29192
|
motionStreamProfile: mustString("motionStreamProfile"),
|
|
28889
29193
|
detectionStreamProfile: mustString("detectionStreamProfile"),
|
|
28890
|
-
motionFps:
|
|
28891
|
-
detectionFps:
|
|
28892
|
-
motionCooldownMs:
|
|
29194
|
+
motionFps: numberOrDefault("motionFps"),
|
|
29195
|
+
detectionFps: numberOrDefault("detectionFps"),
|
|
29196
|
+
motionCooldownMs: numberOrDefault("motionCooldownMs"),
|
|
28893
29197
|
detectionMode,
|
|
28894
29198
|
audioMode,
|
|
28895
29199
|
onboardMotionDrivesAnalyzer,
|
|
29200
|
+
occupancyRecheckEnabled,
|
|
28896
29201
|
occupancyRecheckSec,
|
|
28897
29202
|
occupancyRecheckFrames
|
|
28898
29203
|
};
|
|
@@ -29003,6 +29308,7 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
29003
29308
|
detectionMode: resolved.detectionMode,
|
|
29004
29309
|
audioMode: resolved.audioMode,
|
|
29005
29310
|
onboardMotionDrivesAnalyzer: resolved.onboardMotionDrivesAnalyzer,
|
|
29311
|
+
occupancyRecheckEnabled: resolved.occupancyRecheckEnabled,
|
|
29006
29312
|
occupancyRecheckSec: resolved.occupancyRecheckSec,
|
|
29007
29313
|
occupancyRecheckFrames: resolved.occupancyRecheckFrames
|
|
29008
29314
|
};
|
|
@@ -29037,6 +29343,7 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
29037
29343
|
detectionMode: config.detectionMode,
|
|
29038
29344
|
audioMode: config.audioMode,
|
|
29039
29345
|
onboardMotionDrivesAnalyzer: config.onboardMotionDrivesAnalyzer,
|
|
29346
|
+
occupancyRecheckEnabled: config.occupancyRecheckEnabled,
|
|
29040
29347
|
occupancyRecheckSec: config.occupancyRecheckSec,
|
|
29041
29348
|
occupancyRecheckFrames: config.occupancyRecheckFrames
|
|
29042
29349
|
};
|
|
@@ -29202,6 +29509,7 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
29202
29509
|
if (a.motionCooldownMs !== b.motionCooldownMs) return false;
|
|
29203
29510
|
if (a.audioStreamId !== b.audioStreamId) return false;
|
|
29204
29511
|
if (a.onboardMotionDrivesAnalyzer !== b.onboardMotionDrivesAnalyzer) return false;
|
|
29512
|
+
if (a.occupancyRecheckEnabled !== b.occupancyRecheckEnabled) return false;
|
|
29205
29513
|
if (a.occupancyRecheckSec !== b.occupancyRecheckSec) return false;
|
|
29206
29514
|
if (a.occupancyRecheckFrames !== b.occupancyRecheckFrames) return false;
|
|
29207
29515
|
if (a.motionSources.length !== b.motionSources.length) return false;
|
|
@@ -29731,6 +30039,19 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
29731
30039
|
isRemote: isRemoteAudio
|
|
29732
30040
|
}
|
|
29733
30041
|
});
|
|
30042
|
+
let pcmParts = [];
|
|
30043
|
+
let accumulatedBytes = 0;
|
|
30044
|
+
let accumulatedMs = 0;
|
|
30045
|
+
let windowSampleRate = 0;
|
|
30046
|
+
let windowChannels = 0;
|
|
30047
|
+
let windowTimestamp = 0;
|
|
30048
|
+
let windowOpen = false;
|
|
30049
|
+
const resetWindow = () => {
|
|
30050
|
+
pcmParts = [];
|
|
30051
|
+
accumulatedBytes = 0;
|
|
30052
|
+
accumulatedMs = 0;
|
|
30053
|
+
windowOpen = false;
|
|
30054
|
+
};
|
|
29734
30055
|
const teardown = startAudioChunkPoller({
|
|
29735
30056
|
api,
|
|
29736
30057
|
brokerId: audioBrokerId,
|
|
@@ -29740,13 +30061,35 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
29740
30061
|
this.pipelineWatchdog?.noteSignal(deviceId, "audio");
|
|
29741
30062
|
try {
|
|
29742
30063
|
const byteLength = chunk.data.byteLength;
|
|
29743
|
-
const
|
|
29744
|
-
|
|
30064
|
+
const bytes = new Uint8Array(byteLength);
|
|
30065
|
+
bytes.set(new Uint8Array(chunk.data.buffer, chunk.data.byteOffset, byteLength));
|
|
30066
|
+
if (!windowOpen) {
|
|
30067
|
+
windowSampleRate = chunk.sampleRate;
|
|
30068
|
+
windowChannels = chunk.channels;
|
|
30069
|
+
windowTimestamp = chunk.timestamp;
|
|
30070
|
+
windowOpen = true;
|
|
30071
|
+
}
|
|
30072
|
+
pcmParts.push(bytes);
|
|
30073
|
+
accumulatedBytes += byteLength;
|
|
30074
|
+
const channels = chunk.channels > 0 ? chunk.channels : 1;
|
|
30075
|
+
const framesPerChannel = byteLength / F32_BYTES_PER_SAMPLE / channels;
|
|
30076
|
+
accumulatedMs += framesPerChannel / chunk.sampleRate * 1e3;
|
|
30077
|
+
if (accumulatedMs < AUDIO_WINDOW_TARGET_MS) return;
|
|
30078
|
+
const windowData = new Uint8Array(accumulatedBytes);
|
|
30079
|
+
let offset = 0;
|
|
30080
|
+
for (const part of pcmParts) {
|
|
30081
|
+
windowData.set(part, offset);
|
|
30082
|
+
offset += part.byteLength;
|
|
30083
|
+
}
|
|
30084
|
+
const flushSampleRate = windowSampleRate;
|
|
30085
|
+
const flushChannels = windowChannels;
|
|
30086
|
+
const flushTimestamp = windowTimestamp;
|
|
30087
|
+
resetWindow();
|
|
29745
30088
|
const audioChunkInput = {
|
|
29746
|
-
data,
|
|
29747
|
-
sampleRate:
|
|
29748
|
-
channels:
|
|
29749
|
-
timestamp:
|
|
30089
|
+
data: windowData,
|
|
30090
|
+
sampleRate: flushSampleRate,
|
|
30091
|
+
channels: flushChannels,
|
|
30092
|
+
timestamp: flushTimestamp,
|
|
29750
30093
|
deviceId
|
|
29751
30094
|
};
|
|
29752
30095
|
const result = await api.audioAnalyzer.analyseChunk.mutate({
|
|
@@ -29823,6 +30166,7 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
29823
30166
|
this.ctx.logger.info("Audio stream subscribed", { tags: { deviceId } });
|
|
29824
30167
|
return () => {
|
|
29825
30168
|
teardown();
|
|
30169
|
+
resetWindow();
|
|
29826
30170
|
};
|
|
29827
30171
|
}
|
|
29828
30172
|
};
|