@camstack/addon-pipeline-orchestrator 1.1.26 → 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-0vYngRZJ.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-CrNnXa-5.mjs → hostInit-CSrBjaSu.mjs} +3 -3
- package/dist/index.js +386 -52
- package/dist/index.mjs +386 -52
- 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.mjs
CHANGED
|
@@ -4627,7 +4627,7 @@ function _instanceof(cls, params = {}) {
|
|
|
4627
4627
|
return inst;
|
|
4628
4628
|
}
|
|
4629
4629
|
//#endregion
|
|
4630
|
-
//#region ../types/dist/sleep-
|
|
4630
|
+
//#region ../types/dist/sleep-CZDdRBua.mjs
|
|
4631
4631
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
4632
4632
|
EventCategory["SystemBoot"] = "system.boot";
|
|
4633
4633
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -7634,7 +7634,16 @@ var DecoderStatsSchema = object({
|
|
|
7634
7634
|
inputFps: number(),
|
|
7635
7635
|
outputFps: number(),
|
|
7636
7636
|
avgDecodeTimeMs: number(),
|
|
7637
|
-
droppedFrames: number()
|
|
7637
|
+
droppedFrames: number(),
|
|
7638
|
+
/**
|
|
7639
|
+
* Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
|
|
7640
|
+
* lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
|
|
7641
|
+
* the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
|
|
7642
|
+
* is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
|
|
7643
|
+
*/
|
|
7644
|
+
lagMs: number().optional(),
|
|
7645
|
+
effectiveFps: number().optional(),
|
|
7646
|
+
adaptiveFps: number().optional()
|
|
7638
7647
|
});
|
|
7639
7648
|
var DecoderSessionConfigSchema = object({
|
|
7640
7649
|
codec: string(),
|
|
@@ -7675,7 +7684,15 @@ var DecoderSessionConfigSchema = object({
|
|
|
7675
7684
|
* other — `pullFrames` returns nothing for an `'shm'` session and
|
|
7676
7685
|
* `pullHandles` returns nothing for a `'callback'` session.
|
|
7677
7686
|
*/
|
|
7678
|
-
frameSink: _enum(["callback", "shm"]).default("callback")
|
|
7687
|
+
frameSink: _enum(["callback", "shm"]).default("callback"),
|
|
7688
|
+
/**
|
|
7689
|
+
* Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
|
|
7690
|
+
* a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
|
|
7691
|
+
* real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
|
|
7692
|
+
* stream-broker's `streamingDebug` gate — off by default so production logs
|
|
7693
|
+
* stay quiet and the emit path pays zero per-frame cost when disabled.
|
|
7694
|
+
*/
|
|
7695
|
+
debug: boolean().optional()
|
|
7679
7696
|
});
|
|
7680
7697
|
var EncodeProfileSchema = object({
|
|
7681
7698
|
video: object({
|
|
@@ -9894,6 +9911,75 @@ DeviceType.Cover, method(object({ deviceId: number().int().nonnegative() }), _vo
|
|
|
9894
9911
|
auth: "admin"
|
|
9895
9912
|
});
|
|
9896
9913
|
/**
|
|
9914
|
+
* Vendor-neutral day/night (IR-cut) control — the per-camera config cap
|
|
9915
|
+
* shared by reolink / hikvision / amcrest. Models the common firmware
|
|
9916
|
+
* surface: the IR-cut switching MODE plus the two knobs that gate it
|
|
9917
|
+
* (photocell `sensitivity` + `switchDelaySec`). Each vendor maps these
|
|
9918
|
+
* onto its own ISAPI / Baichuan / Dahua-CGI fields; the cap standardises
|
|
9919
|
+
* the shape so ONE derived-form renders every camera.
|
|
9920
|
+
*
|
|
9921
|
+
* Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
|
|
9922
|
+
* `getOptions` advertises per-camera availability, `getStatus` (auto-
|
|
9923
|
+
* injected from `status`) reports the live values, and a single
|
|
9924
|
+
* `setSettings` mutation applies a partial change. No hand-written
|
|
9925
|
+
* settings-contribution methods — the framework derives the UI + save
|
|
9926
|
+
* routing from this surface.
|
|
9927
|
+
*/
|
|
9928
|
+
/** IR-cut switching mode. `schedule` = time-of-day table configured on the camera. */
|
|
9929
|
+
var DayNightModeSchema = _enum([
|
|
9930
|
+
"auto",
|
|
9931
|
+
"day",
|
|
9932
|
+
"night",
|
|
9933
|
+
"schedule"
|
|
9934
|
+
]);
|
|
9935
|
+
/** Normalized numeric range descriptor — `{ min, max, step }` per the
|
|
9936
|
+
* getOptions availability convention. Normalized values are 0–100. */
|
|
9937
|
+
var NormalizedRangeSchema$1 = object({
|
|
9938
|
+
min: number(),
|
|
9939
|
+
max: number(),
|
|
9940
|
+
step: number()
|
|
9941
|
+
});
|
|
9942
|
+
object({
|
|
9943
|
+
mode: DayNightModeSchema,
|
|
9944
|
+
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
9945
|
+
sensitivity: number().optional(),
|
|
9946
|
+
/** Delay before the IR-cut filter flips, in seconds. */
|
|
9947
|
+
switchDelaySec: number().optional(),
|
|
9948
|
+
lastFetchedAt: number()
|
|
9949
|
+
});
|
|
9950
|
+
/**
|
|
9951
|
+
* Per-camera availability descriptor — drives which controls the admin UI
|
|
9952
|
+
* renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
|
|
9953
|
+
* (normalized 0–100); the mode choice-set as an array. A provider returns
|
|
9954
|
+
* honest, camera-probed values — never hardcoded.
|
|
9955
|
+
*/
|
|
9956
|
+
var DayNightOptionsSchema = object({
|
|
9957
|
+
/** Modes this camera accepts. Empty → the camera has no configurable day/night mode. */
|
|
9958
|
+
modes: array(DayNightModeSchema),
|
|
9959
|
+
supportsSensitivity: boolean(),
|
|
9960
|
+
/** Present when `supportsSensitivity` — the normalized 0–100 range. */
|
|
9961
|
+
sensitivity: NormalizedRangeSchema$1.optional(),
|
|
9962
|
+
supportsSwitchDelay: boolean(),
|
|
9963
|
+
/** Present when `supportsSwitchDelay` — the allowed delay range in seconds. */
|
|
9964
|
+
switchDelaySec: NormalizedRangeSchema$1.optional()
|
|
9965
|
+
});
|
|
9966
|
+
/**
|
|
9967
|
+
* Partial change to the day/night config — every field optional. A
|
|
9968
|
+
* provider ignores fields it does not support.
|
|
9969
|
+
*/
|
|
9970
|
+
var DayNightSettingsPatchSchema = object({
|
|
9971
|
+
mode: DayNightModeSchema.optional(),
|
|
9972
|
+
sensitivity: number().optional(),
|
|
9973
|
+
switchDelaySec: number().optional()
|
|
9974
|
+
});
|
|
9975
|
+
DeviceType.Camera, method(object({ deviceId: number() }), DayNightOptionsSchema), method(object({
|
|
9976
|
+
deviceId: number(),
|
|
9977
|
+
settings: DayNightSettingsPatchSchema
|
|
9978
|
+
}), _void(), {
|
|
9979
|
+
kind: "mutation",
|
|
9980
|
+
auth: "admin"
|
|
9981
|
+
});
|
|
9982
|
+
/**
|
|
9897
9983
|
* Identity envelope for a device's upstream-system metadata.
|
|
9898
9984
|
*
|
|
9899
9985
|
* Two jobs:
|
|
@@ -10249,6 +10335,130 @@ object({
|
|
|
10249
10335
|
});
|
|
10250
10336
|
DeviceType.Image;
|
|
10251
10337
|
/**
|
|
10338
|
+
* Vendor-neutral image / picture-adjustment cap — the per-camera config
|
|
10339
|
+
* cap shared by reolink / hikvision / amcrest. Models the common ISP
|
|
10340
|
+
* surface: the four picture sliders (brightness / contrast / saturation /
|
|
10341
|
+
* sharpness), orientation (mirror / flip / rotate), white-balance,
|
|
10342
|
+
* exposure and backlight-compensation modes.
|
|
10343
|
+
*
|
|
10344
|
+
* NORMALIZATION: every slider is a normalized int 0–100. Vendors expose
|
|
10345
|
+
* these natively as 0–100 or 0–255 (or other ranges); each provider maps
|
|
10346
|
+
* its native range to/from this normalized 0–100 space so the cap surface
|
|
10347
|
+
* (and the derived form) is identical across cameras. `warmth` (manual
|
|
10348
|
+
* white-balance) is likewise normalized 0–100.
|
|
10349
|
+
*
|
|
10350
|
+
* Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
|
|
10351
|
+
* `getOptions` advertises per-camera availability, `getStatus` (auto-
|
|
10352
|
+
* injected from `status`) reports the live values, and a single
|
|
10353
|
+
* `setSettings` mutation applies a partial change. No hand-written
|
|
10354
|
+
* settings-contribution methods — the framework derives the UI + save
|
|
10355
|
+
* routing from this surface.
|
|
10356
|
+
*/
|
|
10357
|
+
/** Sensor/image rotation, degrees clockwise. */
|
|
10358
|
+
var ImageRotateSchema = _enum([
|
|
10359
|
+
"0",
|
|
10360
|
+
"90",
|
|
10361
|
+
"180",
|
|
10362
|
+
"270"
|
|
10363
|
+
]);
|
|
10364
|
+
/** White-balance mode. `manual` unlocks the normalized `warmth` knob. */
|
|
10365
|
+
var WhiteBalanceModeSchema = _enum(["auto", "manual"]);
|
|
10366
|
+
/** Exposure mode. */
|
|
10367
|
+
var ExposureModeSchema = _enum(["auto", "manual"]);
|
|
10368
|
+
/**
|
|
10369
|
+
* Backlight-compensation mode:
|
|
10370
|
+
* - `off` — disabled
|
|
10371
|
+
* - `blc` — backlight compensation
|
|
10372
|
+
* - `wdr` — wide dynamic range
|
|
10373
|
+
* - `hlc` — highlight compensation
|
|
10374
|
+
*/
|
|
10375
|
+
var BacklightModeSchema = _enum([
|
|
10376
|
+
"off",
|
|
10377
|
+
"blc",
|
|
10378
|
+
"wdr",
|
|
10379
|
+
"hlc"
|
|
10380
|
+
]);
|
|
10381
|
+
/** Normalized numeric range descriptor — `{ min, max, step }` per the
|
|
10382
|
+
* getOptions availability convention. Slider values are normalized 0–100. */
|
|
10383
|
+
var NormalizedRangeSchema = object({
|
|
10384
|
+
min: number(),
|
|
10385
|
+
max: number(),
|
|
10386
|
+
step: number()
|
|
10387
|
+
});
|
|
10388
|
+
object({
|
|
10389
|
+
/** Normalized 0–100. */
|
|
10390
|
+
brightness: number().optional(),
|
|
10391
|
+
/** Normalized 0–100. */
|
|
10392
|
+
contrast: number().optional(),
|
|
10393
|
+
/** Normalized 0–100. */
|
|
10394
|
+
saturation: number().optional(),
|
|
10395
|
+
/** Normalized 0–100. */
|
|
10396
|
+
sharpness: number().optional(),
|
|
10397
|
+
mirror: boolean().optional(),
|
|
10398
|
+
flip: boolean().optional(),
|
|
10399
|
+
rotate: ImageRotateSchema.optional(),
|
|
10400
|
+
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
10401
|
+
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
10402
|
+
warmth: number().optional(),
|
|
10403
|
+
exposureMode: ExposureModeSchema.optional(),
|
|
10404
|
+
backlightMode: BacklightModeSchema.optional(),
|
|
10405
|
+
lastFetchedAt: number()
|
|
10406
|
+
});
|
|
10407
|
+
/**
|
|
10408
|
+
* Per-camera availability descriptor — drives which controls the admin UI
|
|
10409
|
+
* renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
|
|
10410
|
+
* (the normalized 0–100 range); enums as arrays of supported values (empty
|
|
10411
|
+
* array → control hidden). A provider returns honest, camera-probed values
|
|
10412
|
+
* — never hardcoded.
|
|
10413
|
+
*/
|
|
10414
|
+
var ImageSettingsOptionsSchema = object({
|
|
10415
|
+
supportsBrightness: boolean(),
|
|
10416
|
+
brightness: NormalizedRangeSchema.optional(),
|
|
10417
|
+
supportsContrast: boolean(),
|
|
10418
|
+
contrast: NormalizedRangeSchema.optional(),
|
|
10419
|
+
supportsSaturation: boolean(),
|
|
10420
|
+
saturation: NormalizedRangeSchema.optional(),
|
|
10421
|
+
supportsSharpness: boolean(),
|
|
10422
|
+
sharpness: NormalizedRangeSchema.optional(),
|
|
10423
|
+
supportsMirror: boolean(),
|
|
10424
|
+
supportsFlip: boolean(),
|
|
10425
|
+
/** Supported rotation values. Empty → rotation not configurable. */
|
|
10426
|
+
rotateOptions: array(ImageRotateSchema),
|
|
10427
|
+
/** Supported white-balance modes. Empty → white-balance not configurable. */
|
|
10428
|
+
whiteBalanceModes: array(WhiteBalanceModeSchema),
|
|
10429
|
+
supportsWarmth: boolean(),
|
|
10430
|
+
/** Present when `supportsWarmth` — the normalized 0–100 range. */
|
|
10431
|
+
warmth: NormalizedRangeSchema.optional(),
|
|
10432
|
+
/** Supported exposure modes. Empty → exposure not configurable. */
|
|
10433
|
+
exposureModes: array(ExposureModeSchema),
|
|
10434
|
+
/** Supported backlight modes. Empty → backlight-compensation not configurable. */
|
|
10435
|
+
backlightModes: array(BacklightModeSchema)
|
|
10436
|
+
});
|
|
10437
|
+
/**
|
|
10438
|
+
* Partial change to the image config — every field optional. Slider values
|
|
10439
|
+
* are normalized 0–100. A provider ignores fields it does not support.
|
|
10440
|
+
*/
|
|
10441
|
+
var ImageSettingsPatchSchema = object({
|
|
10442
|
+
brightness: number().optional(),
|
|
10443
|
+
contrast: number().optional(),
|
|
10444
|
+
saturation: number().optional(),
|
|
10445
|
+
sharpness: number().optional(),
|
|
10446
|
+
mirror: boolean().optional(),
|
|
10447
|
+
flip: boolean().optional(),
|
|
10448
|
+
rotate: ImageRotateSchema.optional(),
|
|
10449
|
+
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
10450
|
+
warmth: number().optional(),
|
|
10451
|
+
exposureMode: ExposureModeSchema.optional(),
|
|
10452
|
+
backlightMode: BacklightModeSchema.optional()
|
|
10453
|
+
});
|
|
10454
|
+
DeviceType.Camera, method(object({ deviceId: number() }), ImageSettingsOptionsSchema), method(object({
|
|
10455
|
+
deviceId: number(),
|
|
10456
|
+
settings: ImageSettingsPatchSchema
|
|
10457
|
+
}), _void(), {
|
|
10458
|
+
kind: "mutation",
|
|
10459
|
+
auth: "admin"
|
|
10460
|
+
});
|
|
10461
|
+
/**
|
|
10252
10462
|
* Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
|
|
10253
10463
|
* with a mowing lifecycle plus a dock action.
|
|
10254
10464
|
*
|
|
@@ -11311,6 +11521,16 @@ var RunnerCameraConfigSchema = object({
|
|
|
11311
11521
|
* this gate is bypassed.
|
|
11312
11522
|
*/
|
|
11313
11523
|
onboardMotionDrivesAnalyzer: boolean().default(true),
|
|
11524
|
+
/**
|
|
11525
|
+
* Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
|
|
11526
|
+
* never arms the periodic recheck timer, regardless of `occupancyRecheckSec` —
|
|
11527
|
+
* this is off by default because the recheck re-subscribes a detection session
|
|
11528
|
+
* every N seconds while `watching`, a major source of pull-decoder re-dial
|
|
11529
|
+
* churn (each cycle creates+tears a session → RTSP re-dial → latency). The
|
|
11530
|
+
* `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
|
|
11531
|
+
* (and only render) when this is enabled.
|
|
11532
|
+
*/
|
|
11533
|
+
occupancyRecheckEnabled: boolean().default(false),
|
|
11314
11534
|
occupancyRecheckSec: number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
|
|
11315
11535
|
occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
|
|
11316
11536
|
/**
|
|
@@ -11361,6 +11581,8 @@ var RunnerCameraDeviceUIFields = [
|
|
|
11361
11581
|
default: motionFpsField.default,
|
|
11362
11582
|
showValue: true,
|
|
11363
11583
|
unit: "fps",
|
|
11584
|
+
nullable: true,
|
|
11585
|
+
nullLabel: "Default",
|
|
11364
11586
|
showWhen: {
|
|
11365
11587
|
field: "motionSources",
|
|
11366
11588
|
includes: "analyzer"
|
|
@@ -11375,7 +11597,9 @@ var RunnerCameraDeviceUIFields = [
|
|
|
11375
11597
|
step: detectionFpsField.step,
|
|
11376
11598
|
default: detectionFpsField.default,
|
|
11377
11599
|
showValue: true,
|
|
11378
|
-
unit: "fps"
|
|
11600
|
+
unit: "fps",
|
|
11601
|
+
nullable: true,
|
|
11602
|
+
nullLabel: "Default"
|
|
11379
11603
|
},
|
|
11380
11604
|
{
|
|
11381
11605
|
key: "motionCooldownMs",
|
|
@@ -11388,7 +11612,9 @@ var RunnerCameraDeviceUIFields = [
|
|
|
11388
11612
|
default: motionCooldownMsField.default,
|
|
11389
11613
|
showValue: true,
|
|
11390
11614
|
unit: "s",
|
|
11391
|
-
displayScale: 1e3
|
|
11615
|
+
displayScale: 1e3,
|
|
11616
|
+
nullable: true,
|
|
11617
|
+
nullLabel: "Default"
|
|
11392
11618
|
},
|
|
11393
11619
|
{
|
|
11394
11620
|
key: "onboardMotionDrivesAnalyzer",
|
|
@@ -11401,17 +11627,29 @@ var RunnerCameraDeviceUIFields = [
|
|
|
11401
11627
|
includes: "onboard"
|
|
11402
11628
|
}
|
|
11403
11629
|
},
|
|
11630
|
+
{
|
|
11631
|
+
key: "occupancyRecheckEnabled",
|
|
11632
|
+
type: "boolean",
|
|
11633
|
+
style: "checkbox",
|
|
11634
|
+
label: "Occupancy re-check",
|
|
11635
|
+
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.",
|
|
11636
|
+
default: false
|
|
11637
|
+
},
|
|
11404
11638
|
{
|
|
11405
11639
|
key: "occupancyRecheckSec",
|
|
11406
11640
|
type: "slider",
|
|
11407
11641
|
label: "Occupancy re-check interval",
|
|
11408
|
-
description: "How often (in seconds) the runner re-samples a few frames to confirm the scene is truly empty during the watching phase.
|
|
11642
|
+
description: "How often (in seconds) the runner re-samples a few frames to confirm the scene is truly empty during the watching phase.",
|
|
11409
11643
|
min: occupancyRecheckSecField.min,
|
|
11410
11644
|
max: occupancyRecheckSecField.max,
|
|
11411
11645
|
step: occupancyRecheckSecField.step,
|
|
11412
11646
|
default: occupancyRecheckSecField.default,
|
|
11413
11647
|
showValue: true,
|
|
11414
|
-
unit: "s"
|
|
11648
|
+
unit: "s",
|
|
11649
|
+
showWhen: {
|
|
11650
|
+
field: "occupancyRecheckEnabled",
|
|
11651
|
+
equals: true
|
|
11652
|
+
}
|
|
11415
11653
|
},
|
|
11416
11654
|
{
|
|
11417
11655
|
key: "occupancyRecheckFrames",
|
|
@@ -11422,7 +11660,11 @@ var RunnerCameraDeviceUIFields = [
|
|
|
11422
11660
|
max: occupancyRecheckFramesField.max,
|
|
11423
11661
|
step: occupancyRecheckFramesField.step,
|
|
11424
11662
|
default: occupancyRecheckFramesField.default,
|
|
11425
|
-
showValue: true
|
|
11663
|
+
showValue: true,
|
|
11664
|
+
showWhen: {
|
|
11665
|
+
field: "occupancyRecheckEnabled",
|
|
11666
|
+
equals: true
|
|
11667
|
+
}
|
|
11426
11668
|
}
|
|
11427
11669
|
];
|
|
11428
11670
|
/**
|
|
@@ -20001,6 +20243,18 @@ Object.freeze({
|
|
|
20001
20243
|
addonId: null,
|
|
20002
20244
|
access: "view"
|
|
20003
20245
|
},
|
|
20246
|
+
"dayNight.getOptions": {
|
|
20247
|
+
capName: "day-night",
|
|
20248
|
+
capScope: "device",
|
|
20249
|
+
addonId: null,
|
|
20250
|
+
access: "view"
|
|
20251
|
+
},
|
|
20252
|
+
"dayNight.setSettings": {
|
|
20253
|
+
capName: "day-night",
|
|
20254
|
+
capScope: "device",
|
|
20255
|
+
addonId: null,
|
|
20256
|
+
access: "create"
|
|
20257
|
+
},
|
|
20004
20258
|
"decoder.createSession": {
|
|
20005
20259
|
capName: "decoder",
|
|
20006
20260
|
capScope: "system",
|
|
@@ -20931,6 +21185,18 @@ Object.freeze({
|
|
|
20931
21185
|
addonId: null,
|
|
20932
21186
|
access: "create"
|
|
20933
21187
|
},
|
|
21188
|
+
"imageSettings.getOptions": {
|
|
21189
|
+
capName: "image-settings",
|
|
21190
|
+
capScope: "device",
|
|
21191
|
+
addonId: null,
|
|
21192
|
+
access: "view"
|
|
21193
|
+
},
|
|
21194
|
+
"imageSettings.setSettings": {
|
|
21195
|
+
capName: "image-settings",
|
|
21196
|
+
capScope: "device",
|
|
21197
|
+
addonId: null,
|
|
21198
|
+
access: "create"
|
|
21199
|
+
},
|
|
20934
21200
|
"integrations.create": {
|
|
20935
21201
|
capName: "integrations",
|
|
20936
21202
|
capScope: "system",
|
|
@@ -24510,7 +24776,8 @@ var DEFAULT_WATCHDOG_THRESHOLDS = {
|
|
|
24510
24776
|
audioMs: 9e4,
|
|
24511
24777
|
motionMs: 3e4,
|
|
24512
24778
|
detectionMs: 6e4,
|
|
24513
|
-
maxRecoveryAttempts: 3
|
|
24779
|
+
maxRecoveryAttempts: 3,
|
|
24780
|
+
exhaustedRetryMs: 6e4
|
|
24514
24781
|
};
|
|
24515
24782
|
var STAGE_THRESHOLD_KEY = {
|
|
24516
24783
|
audio: "audioMs",
|
|
@@ -24531,7 +24798,8 @@ var PipelineWatchdog = class {
|
|
|
24531
24798
|
const stages = /* @__PURE__ */ new Map();
|
|
24532
24799
|
for (const [stage] of cam.continuousStages) stages.set(stage, {
|
|
24533
24800
|
lastSeenMs: now,
|
|
24534
|
-
attempts: 0
|
|
24801
|
+
attempts: 0,
|
|
24802
|
+
lastAttemptMs: 0
|
|
24535
24803
|
});
|
|
24536
24804
|
this.state.set(cam.deviceId, stages);
|
|
24537
24805
|
}
|
|
@@ -24554,7 +24822,10 @@ var PipelineWatchdog = class {
|
|
|
24554
24822
|
else this.deps.logger.info(line);
|
|
24555
24823
|
for (const r of recoveries) {
|
|
24556
24824
|
const rt = this.state.get(cam.deviceId)?.get(r.stage);
|
|
24557
|
-
if (rt)
|
|
24825
|
+
if (rt) {
|
|
24826
|
+
if (rt.attempts < this.deps.thresholds.maxRecoveryAttempts) rt.attempts += 1;
|
|
24827
|
+
rt.lastAttemptMs = now;
|
|
24828
|
+
}
|
|
24558
24829
|
this.deps.recover(cam.deviceId, r.stage, r.streamId);
|
|
24559
24830
|
}
|
|
24560
24831
|
}
|
|
@@ -24598,7 +24869,13 @@ var PipelineWatchdog = class {
|
|
|
24598
24869
|
if (staleness <= thresholdMs) parts.push(`${stage}=${stageMode[stage]}@${streamId}(OK ${sSec}s)`);
|
|
24599
24870
|
else if (rt.attempts >= this.deps.thresholds.maxRecoveryAttempts) {
|
|
24600
24871
|
stalled = true;
|
|
24601
|
-
|
|
24872
|
+
if (now - rt.lastAttemptMs >= this.deps.thresholds.exhaustedRetryMs) {
|
|
24873
|
+
recoveries.push({
|
|
24874
|
+
stage,
|
|
24875
|
+
streamId
|
|
24876
|
+
});
|
|
24877
|
+
parts.push(`${stage}=${stageMode[stage]}@${streamId}(STALLED ${sSec}s · exhausted ${rt.attempts} · retrying)`);
|
|
24878
|
+
} else parts.push(`${stage}=${stageMode[stage]}@${streamId}(STALLED ${sSec}s · exhausted ${rt.attempts})`);
|
|
24602
24879
|
} else {
|
|
24603
24880
|
stalled = true;
|
|
24604
24881
|
recoveries.push({
|
|
@@ -24950,6 +25227,24 @@ function isPipelinePhaseMode(v) {
|
|
|
24950
25227
|
var PREFERRED_AGENT_SETTING = "preferredAgent";
|
|
24951
25228
|
/** Key under which the orchestrator stores the per-device audio node pin. */
|
|
24952
25229
|
var AUDIO_NODE_SETTING = "audioNodeId";
|
|
25230
|
+
/**
|
|
25231
|
+
* Target PCM window duration, in ms, for audio classification.
|
|
25232
|
+
*
|
|
25233
|
+
* Sized for the ~1 s inference window the downstream classifiers expect —
|
|
25234
|
+
* YAMNet consumes a 0.975 s frame and Apple SoundAnalysis a ~1 s frame.
|
|
25235
|
+
* The broker's `AudioCodecSession` no longer batches (its 500 ms
|
|
25236
|
+
* accumulator was removed for WebRTC latency), so decoded codec chunks now
|
|
25237
|
+
* arrive at ~21–64 ms each — ~16–48 chunks per second per camera. Feeding
|
|
25238
|
+
* each tiny chunk to the analyzer meant one cross-process `analyseChunk`
|
|
25239
|
+
* RPC + one `PipelineAudioInferenceResult` event PER chunk for a classifier
|
|
25240
|
+
* that (a) throttles to ~2 Hz internally anyway and (b) needs a ~1 s window
|
|
25241
|
+
* for accurate inference. We instead accumulate raw PCM per device and flush
|
|
25242
|
+
* ONE classify + ONE event per ~1 s window: ~1 RPC/event/s/camera and a
|
|
25243
|
+
* correctly-sized inference frame.
|
|
25244
|
+
*/
|
|
25245
|
+
var AUDIO_WINDOW_TARGET_MS = 1e3;
|
|
25246
|
+
/** f32le PCM = 4 bytes per sample. */
|
|
25247
|
+
var F32_BYTES_PER_SAMPLE = 4;
|
|
24953
25248
|
var DEFAULT_BROKER_CALL_TIMEOUT_MS = 5e3;
|
|
24954
25249
|
/** Debounce window for `scheduleReconcile` — coalesces bursts of topology/slot-change signals. */
|
|
24955
25250
|
var RECONCILE_DEBOUNCE_MS = 200;
|
|
@@ -25002,7 +25297,6 @@ var OrchestratorDiagnosticsSchema = object({
|
|
|
25002
25297
|
enabledAudioNodes: array(string()),
|
|
25003
25298
|
clusterRoles: object({
|
|
25004
25299
|
ingestNode: string(),
|
|
25005
|
-
recordingNode: string(),
|
|
25006
25300
|
audioNode: string()
|
|
25007
25301
|
}),
|
|
25008
25302
|
assignedDeviceCount: number().int().min(0),
|
|
@@ -25163,12 +25457,15 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
25163
25457
|
/**
|
|
25164
25458
|
* Cluster-wide singleton role assignments (placement-model §6). Each role
|
|
25165
25459
|
* is the ONE node that serves it for every camera. Driven by the
|
|
25166
|
-
* `ingestNode` / `
|
|
25167
|
-
*
|
|
25460
|
+
* `ingestNode` / `audioNode` node-selects in the addon global schema;
|
|
25461
|
+
* defaults to the hub for both. NOTE: the recording node is NOT a role here
|
|
25462
|
+
* — the `recorder` addon owns it as the single source of truth (its
|
|
25463
|
+
* `recordingNodeId` global setting, obeyed by the recorder's gate). The
|
|
25464
|
+
* Pipeline placement board's "Recording" picker reads/writes that canonical
|
|
25465
|
+
* setting directly via `addonSettings`, not an orchestrator-owned duplicate.
|
|
25168
25466
|
*/
|
|
25169
25467
|
clusterRoles = {
|
|
25170
25468
|
ingestNode: "hub",
|
|
25171
|
-
recordingNode: "hub",
|
|
25172
25469
|
audioNode: "hub"
|
|
25173
25470
|
};
|
|
25174
25471
|
/**
|
|
@@ -28142,32 +28439,21 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
28142
28439
|
title: "Cluster Roles",
|
|
28143
28440
|
tab: "pipeline",
|
|
28144
28441
|
description: "Cluster-wide singleton roles: the single node that serves each role for every camera. Per-node detection/decode/audio CAPABILITIES + weights + camera caps are edited in the per-node capability table (agent settings), not here.",
|
|
28145
|
-
fields: [
|
|
28146
|
-
|
|
28147
|
-
|
|
28148
|
-
|
|
28149
|
-
|
|
28150
|
-
|
|
28151
|
-
|
|
28152
|
-
|
|
28153
|
-
|
|
28154
|
-
|
|
28155
|
-
|
|
28156
|
-
|
|
28157
|
-
|
|
28158
|
-
|
|
28159
|
-
|
|
28160
|
-
showOffline: true
|
|
28161
|
-
},
|
|
28162
|
-
{
|
|
28163
|
-
key: "audioNode",
|
|
28164
|
-
type: "node-select",
|
|
28165
|
-
label: "Audio Node",
|
|
28166
|
-
description: "The node that runs all audio analysis. Defaults to the hub. Must be an audio-capable node.",
|
|
28167
|
-
default: "hub",
|
|
28168
|
-
showOffline: true
|
|
28169
|
-
}
|
|
28170
|
-
]
|
|
28442
|
+
fields: [{
|
|
28443
|
+
key: "ingestNode",
|
|
28444
|
+
type: "node-select",
|
|
28445
|
+
label: "Ingest Node",
|
|
28446
|
+
description: "The node that connects every camera and serves the compressed restream. Defaults to the hub. (Arbitrary ingest ≠ hub is a later phase; kept here so the role is modeled.)",
|
|
28447
|
+
default: "hub",
|
|
28448
|
+
showOffline: true
|
|
28449
|
+
}, {
|
|
28450
|
+
key: "audioNode",
|
|
28451
|
+
type: "node-select",
|
|
28452
|
+
label: "Audio Node",
|
|
28453
|
+
description: "The node that runs all audio analysis. Defaults to the hub. Must be an audio-capable node.",
|
|
28454
|
+
default: "hub",
|
|
28455
|
+
showOffline: true
|
|
28456
|
+
}]
|
|
28171
28457
|
},
|
|
28172
28458
|
{
|
|
28173
28459
|
id: "decoder",
|
|
@@ -28693,7 +28979,6 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
28693
28979
|
};
|
|
28694
28980
|
this.clusterRoles = {
|
|
28695
28981
|
ingestNode: readRole("ingestNode"),
|
|
28696
|
-
recordingNode: readRole("recordingNode"),
|
|
28697
28982
|
audioNode: readRole("audioNode")
|
|
28698
28983
|
};
|
|
28699
28984
|
this.schedulePendingRetry();
|
|
@@ -28868,6 +29153,13 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
28868
29153
|
if (typeof v !== "number") throw new Error(`orchestrator schema missing required number '${key}' for device ${deviceId}`);
|
|
28869
29154
|
return v;
|
|
28870
29155
|
};
|
|
29156
|
+
const numberOrDefault = (key) => {
|
|
29157
|
+
const v = flat[key];
|
|
29158
|
+
if (typeof v === "number") return v;
|
|
29159
|
+
const uiField = RunnerCameraDeviceUIFields.find((f) => f.key === key);
|
|
29160
|
+
const dflt = uiField && "default" in uiField ? uiField.default : void 0;
|
|
29161
|
+
return typeof dflt === "number" ? dflt : 0;
|
|
29162
|
+
};
|
|
28871
29163
|
try {
|
|
28872
29164
|
const features = await this.lookupDeviceFeatures(deviceId);
|
|
28873
29165
|
const profile = resolveDeviceProfile(features);
|
|
@@ -28885,6 +29177,8 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
28885
29177
|
const audioMode = typeof userAudioMode === "string" && isPipelinePhaseMode(userAudioMode) ? userAudioMode : profile?.defaults.audioMode ?? "always-on";
|
|
28886
29178
|
const userOnboardMotionDrivesAnalyzer = raw["onboardMotionDrivesAnalyzer"];
|
|
28887
29179
|
const onboardMotionDrivesAnalyzer = typeof userOnboardMotionDrivesAnalyzer === "boolean" ? userOnboardMotionDrivesAnalyzer : true;
|
|
29180
|
+
const userOccupancyRecheckEnabled = raw["occupancyRecheckEnabled"];
|
|
29181
|
+
const occupancyRecheckEnabled = typeof userOccupancyRecheckEnabled === "boolean" ? userOccupancyRecheckEnabled : false;
|
|
28888
29182
|
const occupancyRecheckSec = mustNumber("occupancyRecheckSec");
|
|
28889
29183
|
const occupancyRecheckFrames = mustNumber("occupancyRecheckFrames");
|
|
28890
29184
|
return {
|
|
@@ -28893,12 +29187,13 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
28893
29187
|
motionSources,
|
|
28894
29188
|
motionStreamProfile: mustString("motionStreamProfile"),
|
|
28895
29189
|
detectionStreamProfile: mustString("detectionStreamProfile"),
|
|
28896
|
-
motionFps:
|
|
28897
|
-
detectionFps:
|
|
28898
|
-
motionCooldownMs:
|
|
29190
|
+
motionFps: numberOrDefault("motionFps"),
|
|
29191
|
+
detectionFps: numberOrDefault("detectionFps"),
|
|
29192
|
+
motionCooldownMs: numberOrDefault("motionCooldownMs"),
|
|
28899
29193
|
detectionMode,
|
|
28900
29194
|
audioMode,
|
|
28901
29195
|
onboardMotionDrivesAnalyzer,
|
|
29196
|
+
occupancyRecheckEnabled,
|
|
28902
29197
|
occupancyRecheckSec,
|
|
28903
29198
|
occupancyRecheckFrames
|
|
28904
29199
|
};
|
|
@@ -29009,6 +29304,7 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
29009
29304
|
detectionMode: resolved.detectionMode,
|
|
29010
29305
|
audioMode: resolved.audioMode,
|
|
29011
29306
|
onboardMotionDrivesAnalyzer: resolved.onboardMotionDrivesAnalyzer,
|
|
29307
|
+
occupancyRecheckEnabled: resolved.occupancyRecheckEnabled,
|
|
29012
29308
|
occupancyRecheckSec: resolved.occupancyRecheckSec,
|
|
29013
29309
|
occupancyRecheckFrames: resolved.occupancyRecheckFrames
|
|
29014
29310
|
};
|
|
@@ -29043,6 +29339,7 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
29043
29339
|
detectionMode: config.detectionMode,
|
|
29044
29340
|
audioMode: config.audioMode,
|
|
29045
29341
|
onboardMotionDrivesAnalyzer: config.onboardMotionDrivesAnalyzer,
|
|
29342
|
+
occupancyRecheckEnabled: config.occupancyRecheckEnabled,
|
|
29046
29343
|
occupancyRecheckSec: config.occupancyRecheckSec,
|
|
29047
29344
|
occupancyRecheckFrames: config.occupancyRecheckFrames
|
|
29048
29345
|
};
|
|
@@ -29208,6 +29505,7 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
29208
29505
|
if (a.motionCooldownMs !== b.motionCooldownMs) return false;
|
|
29209
29506
|
if (a.audioStreamId !== b.audioStreamId) return false;
|
|
29210
29507
|
if (a.onboardMotionDrivesAnalyzer !== b.onboardMotionDrivesAnalyzer) return false;
|
|
29508
|
+
if (a.occupancyRecheckEnabled !== b.occupancyRecheckEnabled) return false;
|
|
29211
29509
|
if (a.occupancyRecheckSec !== b.occupancyRecheckSec) return false;
|
|
29212
29510
|
if (a.occupancyRecheckFrames !== b.occupancyRecheckFrames) return false;
|
|
29213
29511
|
if (a.motionSources.length !== b.motionSources.length) return false;
|
|
@@ -29737,6 +30035,19 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
29737
30035
|
isRemote: isRemoteAudio
|
|
29738
30036
|
}
|
|
29739
30037
|
});
|
|
30038
|
+
let pcmParts = [];
|
|
30039
|
+
let accumulatedBytes = 0;
|
|
30040
|
+
let accumulatedMs = 0;
|
|
30041
|
+
let windowSampleRate = 0;
|
|
30042
|
+
let windowChannels = 0;
|
|
30043
|
+
let windowTimestamp = 0;
|
|
30044
|
+
let windowOpen = false;
|
|
30045
|
+
const resetWindow = () => {
|
|
30046
|
+
pcmParts = [];
|
|
30047
|
+
accumulatedBytes = 0;
|
|
30048
|
+
accumulatedMs = 0;
|
|
30049
|
+
windowOpen = false;
|
|
30050
|
+
};
|
|
29740
30051
|
const teardown = startAudioChunkPoller({
|
|
29741
30052
|
api,
|
|
29742
30053
|
brokerId: audioBrokerId,
|
|
@@ -29746,13 +30057,35 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
29746
30057
|
this.pipelineWatchdog?.noteSignal(deviceId, "audio");
|
|
29747
30058
|
try {
|
|
29748
30059
|
const byteLength = chunk.data.byteLength;
|
|
29749
|
-
const
|
|
29750
|
-
|
|
30060
|
+
const bytes = new Uint8Array(byteLength);
|
|
30061
|
+
bytes.set(new Uint8Array(chunk.data.buffer, chunk.data.byteOffset, byteLength));
|
|
30062
|
+
if (!windowOpen) {
|
|
30063
|
+
windowSampleRate = chunk.sampleRate;
|
|
30064
|
+
windowChannels = chunk.channels;
|
|
30065
|
+
windowTimestamp = chunk.timestamp;
|
|
30066
|
+
windowOpen = true;
|
|
30067
|
+
}
|
|
30068
|
+
pcmParts.push(bytes);
|
|
30069
|
+
accumulatedBytes += byteLength;
|
|
30070
|
+
const channels = chunk.channels > 0 ? chunk.channels : 1;
|
|
30071
|
+
const framesPerChannel = byteLength / F32_BYTES_PER_SAMPLE / channels;
|
|
30072
|
+
accumulatedMs += framesPerChannel / chunk.sampleRate * 1e3;
|
|
30073
|
+
if (accumulatedMs < AUDIO_WINDOW_TARGET_MS) return;
|
|
30074
|
+
const windowData = new Uint8Array(accumulatedBytes);
|
|
30075
|
+
let offset = 0;
|
|
30076
|
+
for (const part of pcmParts) {
|
|
30077
|
+
windowData.set(part, offset);
|
|
30078
|
+
offset += part.byteLength;
|
|
30079
|
+
}
|
|
30080
|
+
const flushSampleRate = windowSampleRate;
|
|
30081
|
+
const flushChannels = windowChannels;
|
|
30082
|
+
const flushTimestamp = windowTimestamp;
|
|
30083
|
+
resetWindow();
|
|
29751
30084
|
const audioChunkInput = {
|
|
29752
|
-
data,
|
|
29753
|
-
sampleRate:
|
|
29754
|
-
channels:
|
|
29755
|
-
timestamp:
|
|
30085
|
+
data: windowData,
|
|
30086
|
+
sampleRate: flushSampleRate,
|
|
30087
|
+
channels: flushChannels,
|
|
30088
|
+
timestamp: flushTimestamp,
|
|
29756
30089
|
deviceId
|
|
29757
30090
|
};
|
|
29758
30091
|
const result = await api.audioAnalyzer.analyseChunk.mutate({
|
|
@@ -29829,6 +30162,7 @@ var PipelineOrchestratorAddon = class PipelineOrchestratorAddon extends BaseAddo
|
|
|
29829
30162
|
this.ctx.logger.info("Audio stream subscribed", { tags: { deviceId } });
|
|
29830
30163
|
return () => {
|
|
29831
30164
|
teardown();
|
|
30165
|
+
resetWindow();
|
|
29832
30166
|
};
|
|
29833
30167
|
}
|
|
29834
30168
|
};
|
package/dist/remoteEntry.js
CHANGED
|
@@ -30,7 +30,7 @@ async function d(e) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async function f() {
|
|
33
|
-
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-
|
|
33
|
+
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-DaBzEEJK.mjs")).catch((e) => {
|
|
34
34
|
throw l = void 0, e;
|
|
35
35
|
}), l;
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-pipeline-orchestrator",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.28",
|
|
4
4
|
"description": "Hub-side camera-to-agent load balancer — tracks runner capacity and dispatches attachCamera calls to the optimal pipeline-runner instance",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|