@camstack/addon-pipeline 1.2.231 → 1.2.233
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/audio-analyzer/index.js +2 -2
- package/dist/audio-analyzer/index.mjs +2 -2
- package/dist/{default-detection-model-C7fsHtHQ.js → default-detection-model-CDhXxOJQ.js} +1 -1
- package/dist/{default-detection-model-DC4yVaFM.mjs → default-detection-model-I8kuDTEi.mjs} +1 -1
- package/dist/detection-pipeline/index.js +4 -4
- package/dist/detection-pipeline/index.mjs +4 -4
- package/dist/{dist-DTPYOq7J.mjs → dist-But4XMDJ.mjs} +107 -6
- package/dist/{dist-p5lZW8pr.js → dist-NX0e_oWp.js} +107 -6
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-Cz92fVGW.mjs → node-BHxRrsoX.mjs} +1 -1
- package/dist/{node-CGVUk5S9.js → node-BgM4n8D4.js} +1 -1
- package/dist/pipeline-runner/index.js +205 -17
- package/dist/pipeline-runner/index.mjs +205 -17
- package/dist/{process-memory-BwijtYhM.mjs → process-memory-C3-EOjjf.mjs} +1 -1
- package/dist/{process-memory-COypUeEc.js → process-memory-C5_Mo9TI.js} +1 -1
- package/dist/recorder/index.js +3 -2
- package/dist/recorder/index.mjs +3 -2
- package/dist/{segment-demux-js-B-yzHYVc.js → segment-demux-js-BAD7i9RI.js} +1 -1
- package/dist/{segment-demux-js-CyaNDtrw.mjs → segment-demux-js-CVZACSOh.mjs} +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B9KO-igY.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DN-9qAgC.mjs} +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D3XkHB88.mjs +26 -0
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-JoG-yDpV.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DDCieNDB.mjs} +1 -1
- package/dist/stream-broker/demux-worker-child.js +1 -1
- package/dist/stream-broker/demux-worker-child.mjs +1 -1
- package/dist/stream-broker/{hostInit-CDwsQyIR.mjs → hostInit-CT06n_gA.mjs} +2 -2
- package/dist/stream-broker/index.js +3 -3
- package/dist/stream-broker/index.mjs +3 -3
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-mnvO611B.mjs +0 -26
|
@@ -3,9 +3,9 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
7
|
-
const require_node = require("../node-
|
|
8
|
-
const require_default_detection_model = require("../default-detection-model-
|
|
6
|
+
const require_dist = require("../dist-NX0e_oWp.js");
|
|
7
|
+
const require_node = require("../node-BgM4n8D4.js");
|
|
8
|
+
const require_default_detection_model = require("../default-detection-model-CDhXxOJQ.js");
|
|
9
9
|
const require_worker_protocol = require("../worker-protocol-B2MfQLlu.js");
|
|
10
10
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
11
11
|
const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
|
|
@@ -2096,6 +2096,73 @@ function startSessionDecodePump(deps) {
|
|
|
2096
2096
|
iterator.return().catch(() => {});
|
|
2097
2097
|
};
|
|
2098
2098
|
}
|
|
2099
|
+
/**
|
|
2100
|
+
* Read the camera's `detectionSources`.
|
|
2101
|
+
*
|
|
2102
|
+
* ABSENT is the pipeline — a runner or an attach older than the field behaves
|
|
2103
|
+
* exactly as it always did. EMPTY is not the same thing and must never be
|
|
2104
|
+
* widened into "everything": it is a camera an operator left with no root
|
|
2105
|
+
* detector, and inventing one for them is how a default acts without anybody
|
|
2106
|
+
* choosing it.
|
|
2107
|
+
*/
|
|
2108
|
+
function planDetectionSources(sources) {
|
|
2109
|
+
if (sources === void 0) return {
|
|
2110
|
+
runsPipeline: true,
|
|
2111
|
+
runsOnboard: false
|
|
2112
|
+
};
|
|
2113
|
+
return {
|
|
2114
|
+
runsPipeline: sources.includes("pipeline"),
|
|
2115
|
+
runsOnboard: sources.includes("onboard")
|
|
2116
|
+
};
|
|
2117
|
+
}
|
|
2118
|
+
/** Clamp a denormalised box into the frame; a firmware box may exceed it. */
|
|
2119
|
+
function clamp(value, max) {
|
|
2120
|
+
return Math.max(0, Math.min(value, max));
|
|
2121
|
+
}
|
|
2122
|
+
/**
|
|
2123
|
+
* Pair the camera's last detections with a decoded frame, in the FRAME's pixel
|
|
2124
|
+
* space.
|
|
2125
|
+
*
|
|
2126
|
+
* The old converter denormalised against a nominal 1000×1000 when the push
|
|
2127
|
+
* carried no dimensions, and documented that consumers should treat a native
|
|
2128
|
+
* bbox as relative. That was survivable while nothing cut pixels from it. Here
|
|
2129
|
+
* the boxes travel with a real frame and a real handle, so they are scaled to
|
|
2130
|
+
* that frame — the same space every other detection on this plane lives in.
|
|
2131
|
+
*/
|
|
2132
|
+
function onboardRootDetections(slot, frame) {
|
|
2133
|
+
if (slot === null || slot.detections.length === 0) return { kind: "none" };
|
|
2134
|
+
const ageMs = Math.abs(frame.timestamp - slot.at);
|
|
2135
|
+
if (ageMs > 1e3) return {
|
|
2136
|
+
kind: "expired",
|
|
2137
|
+
ageMs
|
|
2138
|
+
};
|
|
2139
|
+
const boxed = slot.detections.filter((d) => d.bbox != null);
|
|
2140
|
+
if (boxed.length === 0) return {
|
|
2141
|
+
kind: "no-geometry",
|
|
2142
|
+
classes: slot.detections.map((d) => d.class)
|
|
2143
|
+
};
|
|
2144
|
+
return {
|
|
2145
|
+
kind: "paired",
|
|
2146
|
+
detections: boxed.map((d, i) => {
|
|
2147
|
+
const [nx, ny, nw, nh] = d.bbox;
|
|
2148
|
+
const x = clamp(nx * frame.width, frame.width);
|
|
2149
|
+
const y = clamp(ny * frame.height, frame.height);
|
|
2150
|
+
return {
|
|
2151
|
+
id: `onboard-${String(slot.at)}-${String(i)}`,
|
|
2152
|
+
kind: "first-level",
|
|
2153
|
+
macroClass: d.class,
|
|
2154
|
+
score: d.confidence ?? 1,
|
|
2155
|
+
labels: [],
|
|
2156
|
+
bbox: {
|
|
2157
|
+
x,
|
|
2158
|
+
y,
|
|
2159
|
+
width: clamp(nw * frame.width, frame.width - x),
|
|
2160
|
+
height: clamp(nh * frame.height, frame.height - y)
|
|
2161
|
+
}
|
|
2162
|
+
};
|
|
2163
|
+
})
|
|
2164
|
+
};
|
|
2165
|
+
}
|
|
2099
2166
|
//#endregion
|
|
2100
2167
|
//#region src/pipeline-runner/bench-step-schema.ts
|
|
2101
2168
|
/**
|
|
@@ -5644,6 +5711,8 @@ var PipelineRunner = class {
|
|
|
5644
5711
|
cameras = /* @__PURE__ */ new Map();
|
|
5645
5712
|
semaphore;
|
|
5646
5713
|
resultCallbacks = [];
|
|
5714
|
+
/** Last report per `deviceId:reason` for {@link noteOnboardRootIdle}. */
|
|
5715
|
+
onboardIdleReportedAt = /* @__PURE__ */ new Map();
|
|
5647
5716
|
defaultRoundRobinKeys = [];
|
|
5648
5717
|
defaultRoundRobinIndex = 0;
|
|
5649
5718
|
intervalHandle = null;
|
|
@@ -5724,6 +5793,7 @@ var PipelineRunner = class {
|
|
|
5724
5793
|
const initialPhase = registration.detectionMode === "disabled" ? "idle" : registration.detectionMode === "always-on" ? "active" : "watching";
|
|
5725
5794
|
const state = {
|
|
5726
5795
|
registration,
|
|
5796
|
+
onboardSlot: null,
|
|
5727
5797
|
motionQueue,
|
|
5728
5798
|
detectionQueue,
|
|
5729
5799
|
preRollQueue: new PreRollLane({
|
|
@@ -6200,6 +6270,15 @@ var PipelineRunner = class {
|
|
|
6200
6270
|
const { frame, handle } = entry;
|
|
6201
6271
|
state.inflight += 1;
|
|
6202
6272
|
const enqueuedAt = frame._enqueuedAt ?? pickedAt;
|
|
6273
|
+
const plan = planDetectionSources(state.registration.detectionSources);
|
|
6274
|
+
if (!plan.runsPipeline) {
|
|
6275
|
+
try {
|
|
6276
|
+
await this.processOnboardRoot(deviceId, entry, state, streamType, plan);
|
|
6277
|
+
} finally {
|
|
6278
|
+
state.inflight -= 1;
|
|
6279
|
+
}
|
|
6280
|
+
return;
|
|
6281
|
+
}
|
|
6203
6282
|
const rawRelease = await this.semaphore.acquire();
|
|
6204
6283
|
let released = false;
|
|
6205
6284
|
const release = () => {
|
|
@@ -6223,7 +6302,7 @@ var PipelineRunner = class {
|
|
|
6223
6302
|
state.processedCount++;
|
|
6224
6303
|
if (result) {
|
|
6225
6304
|
if (result.shed === true) state.shedFrames++;
|
|
6226
|
-
await this.notifyCallbacks(deviceId, frame, result, streamType, handle);
|
|
6305
|
+
await this.notifyCallbacks(deviceId, frame, result, streamType, handle, "pipeline");
|
|
6227
6306
|
frameReleaseReason = "success";
|
|
6228
6307
|
const emittedAt = Date.now();
|
|
6229
6308
|
const capturedAt = frame.capturedAt;
|
|
@@ -6250,6 +6329,96 @@ var PipelineRunner = class {
|
|
|
6250
6329
|
}
|
|
6251
6330
|
}
|
|
6252
6331
|
/**
|
|
6332
|
+
* The CAMERA is this camera's root step.
|
|
6333
|
+
*
|
|
6334
|
+
* Same shape as the pipeline path and deliberately so: one decoded frame, one
|
|
6335
|
+
* `FrameResult`, the same `notifyCallbacks`, the same handle, the same
|
|
6336
|
+
* retention release. Everything downstream — subject tiles, birth evidence,
|
|
6337
|
+
* the `detailSteps` announce, the overlay, the tracker — cannot tell which
|
|
6338
|
+
* detector produced the boxes, which is the entire point. What it does NOT do
|
|
6339
|
+
* is take an inference permit: the accelerator is never asked.
|
|
6340
|
+
*
|
|
6341
|
+
* A frame with no fresh onboard detection produces NO result rather than an
|
|
6342
|
+
* empty one. An empty `FrameResult` is a positive statement ("I looked and
|
|
6343
|
+
* there was nothing"), and this path did not look — it decoded a frame while
|
|
6344
|
+
* the camera happened to be silent. Emitting emptiness would tell the
|
|
6345
|
+
* tracker every silent frame is evidence of absence and coast every subject
|
|
6346
|
+
* to death between two pushes.
|
|
6347
|
+
*/
|
|
6348
|
+
async processOnboardRoot(deviceId, entry, state, streamType, plan) {
|
|
6349
|
+
const { frame, handle } = entry;
|
|
6350
|
+
let frameReleaseReason = "drop";
|
|
6351
|
+
try {
|
|
6352
|
+
if (!plan.runsOnboard) {
|
|
6353
|
+
this.noteOnboardRootIdle(deviceId, "no-source");
|
|
6354
|
+
return;
|
|
6355
|
+
}
|
|
6356
|
+
const pairing = onboardRootDetections(state.onboardSlot, {
|
|
6357
|
+
timestamp: Date.now(),
|
|
6358
|
+
width: frame.width,
|
|
6359
|
+
height: frame.height
|
|
6360
|
+
});
|
|
6361
|
+
if (pairing.kind !== "paired") {
|
|
6362
|
+
this.noteOnboardRootIdle(deviceId, pairing.kind);
|
|
6363
|
+
return;
|
|
6364
|
+
}
|
|
6365
|
+
state.onboardSlot = null;
|
|
6366
|
+
state.processedCount++;
|
|
6367
|
+
const result = {
|
|
6368
|
+
kind: "frame",
|
|
6369
|
+
frameId: `onboard-${String(deviceId)}-${String(frame.timestamp)}`,
|
|
6370
|
+
deviceId,
|
|
6371
|
+
timestamp: Date.now(),
|
|
6372
|
+
width: frame.width,
|
|
6373
|
+
height: frame.height,
|
|
6374
|
+
detections: pairing.detections
|
|
6375
|
+
};
|
|
6376
|
+
state.lastResultDetections = pairing.detections.length;
|
|
6377
|
+
await this.notifyCallbacks(deviceId, frame, result, streamType, handle, "onboard");
|
|
6378
|
+
frameReleaseReason = "success";
|
|
6379
|
+
} catch {
|
|
6380
|
+
frameReleaseReason = "error";
|
|
6381
|
+
} finally {
|
|
6382
|
+
try {
|
|
6383
|
+
if (frameReleaseReason === "success" && handle && isContinuousRetainEnabled()) await this.config.hydrateRetainedFrame?.(handle);
|
|
6384
|
+
} catch {}
|
|
6385
|
+
if (handle) this.config.releaseRetention?.(handle, frameReleaseReason);
|
|
6386
|
+
if (frame.frameRef) this.config.releaseFrameRef?.(frame.frameRef, frameReleaseReason);
|
|
6387
|
+
}
|
|
6388
|
+
}
|
|
6389
|
+
/**
|
|
6390
|
+
* Report — once per camera per interval — that the onboard root step decoded
|
|
6391
|
+
* a frame and produced nothing, with WHICH of the reasons it was. Sampled
|
|
6392
|
+
* because it fires at detection fps on a silent camera, which is most of the
|
|
6393
|
+
* time and is not itself a fault.
|
|
6394
|
+
*/
|
|
6395
|
+
noteOnboardRootIdle(deviceId, reason) {
|
|
6396
|
+
const now = Date.now();
|
|
6397
|
+
const key = `${String(deviceId)}:${reason}`;
|
|
6398
|
+
if (now - (this.onboardIdleReportedAt.get(key) ?? 0) < 6e4) return;
|
|
6399
|
+
this.onboardIdleReportedAt.set(key, now);
|
|
6400
|
+
this.logger?.info("onboard root step produced nothing for a decoded frame", {
|
|
6401
|
+
tags: { deviceId },
|
|
6402
|
+
meta: { reason }
|
|
6403
|
+
});
|
|
6404
|
+
}
|
|
6405
|
+
/**
|
|
6406
|
+
* The camera spoke. Held until a decoded frame can be paired with it.
|
|
6407
|
+
*
|
|
6408
|
+
* Gated by the CALLER on `detectionSources` — this method is the mechanism,
|
|
6409
|
+
* not the policy, and a camera that does not name `onboard` never reaches it.
|
|
6410
|
+
*/
|
|
6411
|
+
reportNativeDetection(deviceId, detections, frameWidth, frameHeight) {
|
|
6412
|
+
const state = this.cameras.get(deviceId);
|
|
6413
|
+
if (!state) return;
|
|
6414
|
+
state.onboardSlot = {
|
|
6415
|
+
at: Date.now(),
|
|
6416
|
+
detections,
|
|
6417
|
+
...frameWidth !== void 0 ? { frameWidth } : {},
|
|
6418
|
+
...frameHeight !== void 0 ? { frameHeight } : {}
|
|
6419
|
+
};
|
|
6420
|
+
}
|
|
6421
|
+
/**
|
|
6253
6422
|
* Await `processFrame` with a hard bound. On expiry the permit is released
|
|
6254
6423
|
* immediately (via the caller's release-once closure) and {@link TIMED_OUT}
|
|
6255
6424
|
* is returned; the underlying call is left to settle into the void, since
|
|
@@ -6334,9 +6503,9 @@ var PipelineRunner = class {
|
|
|
6334
6503
|
});
|
|
6335
6504
|
}
|
|
6336
6505
|
}
|
|
6337
|
-
async notifyCallbacks(deviceId, frame, result, streamType, handle) {
|
|
6506
|
+
async notifyCallbacks(deviceId, frame, result, streamType, handle, source) {
|
|
6338
6507
|
for (const callback of this.resultCallbacks) try {
|
|
6339
|
-
await callback(deviceId, frame, result, streamType, handle);
|
|
6508
|
+
await callback(deviceId, frame, result, streamType, handle, source);
|
|
6340
6509
|
} catch {}
|
|
6341
6510
|
}
|
|
6342
6511
|
pickNextDetectionFrame() {
|
|
@@ -7160,6 +7329,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
|
|
|
7160
7329
|
/** Last runtime-label failure, so only a CHANGE is logged (D463). */
|
|
7161
7330
|
lastRuntimeInfoFailure = null;
|
|
7162
7331
|
unsubMotionEvents = null;
|
|
7332
|
+
unsubNativeDetections = null;
|
|
7163
7333
|
/** Devices we have positively observed reporting `battery.sleeping: true`.
|
|
7164
7334
|
* Absent = unknown or awake; both mean "do not gate" (D49). Fed only by
|
|
7165
7335
|
* `BatteryOnStatusChanged`, so consulting it costs nothing and can never
|
|
@@ -7416,11 +7586,11 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
|
|
|
7416
7586
|
this.runner.onDetectionStreamChange((deviceId, action) => {
|
|
7417
7587
|
this.handleDetectionStreamChange(deviceId, action);
|
|
7418
7588
|
});
|
|
7419
|
-
this.runner.onResult(async (deviceId, frame, result, _streamType, handle) => {
|
|
7589
|
+
this.runner.onResult(async (deviceId, frame, result, _streamType, handle, source) => {
|
|
7420
7590
|
this.retention?.noteInferenceResult(deviceId, handle, result);
|
|
7421
7591
|
this.cutSubjectTiles(deviceId, result, handle);
|
|
7422
7592
|
const carried = await this.attachBirthEvidence(deviceId, frame, result);
|
|
7423
|
-
this.emitInferenceResult(deviceId, frame, carried, handle);
|
|
7593
|
+
this.emitInferenceResult(deviceId, frame, carried, handle, source);
|
|
7424
7594
|
const detectionCount = result.detections?.length ?? 0;
|
|
7425
7595
|
this.runner?.noteDetectionResult(deviceId, detectionCount);
|
|
7426
7596
|
if (detectionCount > 0 && this.occupancyBurstInFlight.has(deviceId)) this.occupancyBurstFound.add(deviceId);
|
|
@@ -7444,13 +7614,26 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
|
|
|
7444
7614
|
if (source === "analyzer" && cameraOwnsMotionViaSensor(attachment.config.motionSources)) return;
|
|
7445
7615
|
this.runner?.reportMotion(deviceId, data.detected, source, data.regions ? [...data.regions] : void 0);
|
|
7446
7616
|
});
|
|
7447
|
-
if (this.ctx.eventBus)
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7617
|
+
if (this.ctx.eventBus) {
|
|
7618
|
+
this.unsubNativeDetections = this.ctx.eventBus.subscribe({ category: require_dist.EventCategory.DetectionCameraNative }, (event) => {
|
|
7619
|
+
const data = event.data;
|
|
7620
|
+
const deviceId = data.cameraId;
|
|
7621
|
+
if (typeof deviceId !== "number") return;
|
|
7622
|
+
const attachment = this.attached.get(deviceId);
|
|
7623
|
+
if (!attachment) return;
|
|
7624
|
+
if (!planDetectionSources(attachment.config.detectionSources).runsOnboard) return;
|
|
7625
|
+
const detections = data.detections;
|
|
7626
|
+
if (!detections || detections.length === 0) return;
|
|
7627
|
+
this.runner?.reportNativeDetection(deviceId, detections, data.frameWidth, data.frameHeight);
|
|
7628
|
+
});
|
|
7629
|
+
this.unsubBatteryEvents = this.ctx.eventBus.subscribe({ category: require_dist.EventCategory.BatteryOnStatusChanged }, (event) => {
|
|
7630
|
+
const data = event.data;
|
|
7631
|
+
const deviceId = data.deviceId;
|
|
7632
|
+
if (typeof deviceId !== "number") return;
|
|
7633
|
+
if (data.status?.sleeping === true) this.sleepingBatteryDevices.add(deviceId);
|
|
7634
|
+
else this.sleepingBatteryDevices.delete(deviceId);
|
|
7635
|
+
});
|
|
7636
|
+
}
|
|
7454
7637
|
this.metricsSnapshotTimer = setInterval(() => this.emitMetricsSnapshot(), METRICS_SNAPSHOT_INTERVAL_MS);
|
|
7455
7638
|
return {
|
|
7456
7639
|
providers: [
|
|
@@ -7499,6 +7682,10 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
|
|
|
7499
7682
|
this.unsubMotionEvents();
|
|
7500
7683
|
this.unsubMotionEvents = null;
|
|
7501
7684
|
}
|
|
7685
|
+
if (this.unsubNativeDetections) {
|
|
7686
|
+
this.unsubNativeDetections();
|
|
7687
|
+
this.unsubNativeDetections = null;
|
|
7688
|
+
}
|
|
7502
7689
|
if (this.unsubBatteryEvents) {
|
|
7503
7690
|
this.unsubBatteryEvents();
|
|
7504
7691
|
this.unsubBatteryEvents = null;
|
|
@@ -10611,7 +10798,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
|
|
|
10611
10798
|
teardown();
|
|
10612
10799
|
}
|
|
10613
10800
|
}
|
|
10614
|
-
emitInferenceResult(deviceId, frame, result, handle) {
|
|
10801
|
+
emitInferenceResult(deviceId, frame, result, handle, source) {
|
|
10615
10802
|
if (!this.ctx?.eventBus) return;
|
|
10616
10803
|
const capturedAt = frame.capturedAt;
|
|
10617
10804
|
const detailSteps = this.attached.get(deviceId)?.detailSteps;
|
|
@@ -10622,7 +10809,8 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
|
|
|
10622
10809
|
frameHandle: handle,
|
|
10623
10810
|
emittedAt: Date.now(),
|
|
10624
10811
|
...typeof capturedAt === "number" && capturedAt > 0 ? { capturedAt } : {},
|
|
10625
|
-
...detailSteps && detailSteps.length > 0 ? { detailSteps } : {}
|
|
10812
|
+
...detailSteps && detailSteps.length > 0 ? { detailSteps } : {},
|
|
10813
|
+
source
|
|
10626
10814
|
};
|
|
10627
10815
|
this.ctx.eventBus.emit(require_dist.createEvent(require_dist.EventCategory.PipelineInferenceResult, {
|
|
10628
10816
|
type: "device",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { B as customAction, G as deriveDetailCropRect, Kt as BaseAddon, S as NativeLeaseSettingsSchema, St as pipelineRunnerCapability, U as defineCustomActions, Zt as createEvent, _ as FailureCounters, b as MOTION_CLOSE_AFTER_MS, bn as EventCategory, bt as pickNativeLeaseOverride, cn as _enum, fn as lazy, hn as object, ln as array, m as DEVICE_BACKEND_TO_FORMAT, mn as number, ot as loadContributionCapability, p as DEFAULT_NATIVE_LEASE_SETTINGS, pn as literal, rn as nodePin, tt as failureContributionCapability, u as DEFAULT_DETAIL_CROP_CONVENTION, un as boolean, vn as string, x as NativeLeaseAdmissionSchema, yt as pickDetailCropConvention, zt as errMsg } from "../dist-
|
|
2
|
-
import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-
|
|
3
|
-
import { i as resolveFrameViewGeometry, l as getStepDefinition, r as localFrameRegistry } from "../default-detection-model-
|
|
1
|
+
import { B as customAction, G as deriveDetailCropRect, Kt as BaseAddon, S as NativeLeaseSettingsSchema, St as pipelineRunnerCapability, U as defineCustomActions, Zt as createEvent, _ as FailureCounters, b as MOTION_CLOSE_AFTER_MS, bn as EventCategory, bt as pickNativeLeaseOverride, cn as _enum, fn as lazy, hn as object, ln as array, m as DEVICE_BACKEND_TO_FORMAT, mn as number, ot as loadContributionCapability, p as DEFAULT_NATIVE_LEASE_SETTINGS, pn as literal, rn as nodePin, tt as failureContributionCapability, u as DEFAULT_DETAIL_CROP_CONVENTION, un as boolean, vn as string, x as NativeLeaseAdmissionSchema, yt as pickDetailCropConvention, zt as errMsg } from "../dist-But4XMDJ.mjs";
|
|
2
|
+
import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-BHxRrsoX.mjs";
|
|
3
|
+
import { i as resolveFrameViewGeometry, l as getStepDefinition, r as localFrameRegistry } from "../default-detection-model-I8kuDTEi.mjs";
|
|
4
4
|
import { t as isWorkerReply } from "../worker-protocol-C_W-P_g-.mjs";
|
|
5
5
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
6
6
|
import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
@@ -2089,6 +2089,73 @@ function startSessionDecodePump(deps) {
|
|
|
2089
2089
|
iterator.return().catch(() => {});
|
|
2090
2090
|
};
|
|
2091
2091
|
}
|
|
2092
|
+
/**
|
|
2093
|
+
* Read the camera's `detectionSources`.
|
|
2094
|
+
*
|
|
2095
|
+
* ABSENT is the pipeline — a runner or an attach older than the field behaves
|
|
2096
|
+
* exactly as it always did. EMPTY is not the same thing and must never be
|
|
2097
|
+
* widened into "everything": it is a camera an operator left with no root
|
|
2098
|
+
* detector, and inventing one for them is how a default acts without anybody
|
|
2099
|
+
* choosing it.
|
|
2100
|
+
*/
|
|
2101
|
+
function planDetectionSources(sources) {
|
|
2102
|
+
if (sources === void 0) return {
|
|
2103
|
+
runsPipeline: true,
|
|
2104
|
+
runsOnboard: false
|
|
2105
|
+
};
|
|
2106
|
+
return {
|
|
2107
|
+
runsPipeline: sources.includes("pipeline"),
|
|
2108
|
+
runsOnboard: sources.includes("onboard")
|
|
2109
|
+
};
|
|
2110
|
+
}
|
|
2111
|
+
/** Clamp a denormalised box into the frame; a firmware box may exceed it. */
|
|
2112
|
+
function clamp(value, max) {
|
|
2113
|
+
return Math.max(0, Math.min(value, max));
|
|
2114
|
+
}
|
|
2115
|
+
/**
|
|
2116
|
+
* Pair the camera's last detections with a decoded frame, in the FRAME's pixel
|
|
2117
|
+
* space.
|
|
2118
|
+
*
|
|
2119
|
+
* The old converter denormalised against a nominal 1000×1000 when the push
|
|
2120
|
+
* carried no dimensions, and documented that consumers should treat a native
|
|
2121
|
+
* bbox as relative. That was survivable while nothing cut pixels from it. Here
|
|
2122
|
+
* the boxes travel with a real frame and a real handle, so they are scaled to
|
|
2123
|
+
* that frame — the same space every other detection on this plane lives in.
|
|
2124
|
+
*/
|
|
2125
|
+
function onboardRootDetections(slot, frame) {
|
|
2126
|
+
if (slot === null || slot.detections.length === 0) return { kind: "none" };
|
|
2127
|
+
const ageMs = Math.abs(frame.timestamp - slot.at);
|
|
2128
|
+
if (ageMs > 1e3) return {
|
|
2129
|
+
kind: "expired",
|
|
2130
|
+
ageMs
|
|
2131
|
+
};
|
|
2132
|
+
const boxed = slot.detections.filter((d) => d.bbox != null);
|
|
2133
|
+
if (boxed.length === 0) return {
|
|
2134
|
+
kind: "no-geometry",
|
|
2135
|
+
classes: slot.detections.map((d) => d.class)
|
|
2136
|
+
};
|
|
2137
|
+
return {
|
|
2138
|
+
kind: "paired",
|
|
2139
|
+
detections: boxed.map((d, i) => {
|
|
2140
|
+
const [nx, ny, nw, nh] = d.bbox;
|
|
2141
|
+
const x = clamp(nx * frame.width, frame.width);
|
|
2142
|
+
const y = clamp(ny * frame.height, frame.height);
|
|
2143
|
+
return {
|
|
2144
|
+
id: `onboard-${String(slot.at)}-${String(i)}`,
|
|
2145
|
+
kind: "first-level",
|
|
2146
|
+
macroClass: d.class,
|
|
2147
|
+
score: d.confidence ?? 1,
|
|
2148
|
+
labels: [],
|
|
2149
|
+
bbox: {
|
|
2150
|
+
x,
|
|
2151
|
+
y,
|
|
2152
|
+
width: clamp(nw * frame.width, frame.width - x),
|
|
2153
|
+
height: clamp(nh * frame.height, frame.height - y)
|
|
2154
|
+
}
|
|
2155
|
+
};
|
|
2156
|
+
})
|
|
2157
|
+
};
|
|
2158
|
+
}
|
|
2092
2159
|
//#endregion
|
|
2093
2160
|
//#region src/pipeline-runner/bench-step-schema.ts
|
|
2094
2161
|
/**
|
|
@@ -5636,6 +5703,8 @@ var PipelineRunner = class {
|
|
|
5636
5703
|
cameras = /* @__PURE__ */ new Map();
|
|
5637
5704
|
semaphore;
|
|
5638
5705
|
resultCallbacks = [];
|
|
5706
|
+
/** Last report per `deviceId:reason` for {@link noteOnboardRootIdle}. */
|
|
5707
|
+
onboardIdleReportedAt = /* @__PURE__ */ new Map();
|
|
5639
5708
|
defaultRoundRobinKeys = [];
|
|
5640
5709
|
defaultRoundRobinIndex = 0;
|
|
5641
5710
|
intervalHandle = null;
|
|
@@ -5716,6 +5785,7 @@ var PipelineRunner = class {
|
|
|
5716
5785
|
const initialPhase = registration.detectionMode === "disabled" ? "idle" : registration.detectionMode === "always-on" ? "active" : "watching";
|
|
5717
5786
|
const state = {
|
|
5718
5787
|
registration,
|
|
5788
|
+
onboardSlot: null,
|
|
5719
5789
|
motionQueue,
|
|
5720
5790
|
detectionQueue,
|
|
5721
5791
|
preRollQueue: new PreRollLane({
|
|
@@ -6192,6 +6262,15 @@ var PipelineRunner = class {
|
|
|
6192
6262
|
const { frame, handle } = entry;
|
|
6193
6263
|
state.inflight += 1;
|
|
6194
6264
|
const enqueuedAt = frame._enqueuedAt ?? pickedAt;
|
|
6265
|
+
const plan = planDetectionSources(state.registration.detectionSources);
|
|
6266
|
+
if (!plan.runsPipeline) {
|
|
6267
|
+
try {
|
|
6268
|
+
await this.processOnboardRoot(deviceId, entry, state, streamType, plan);
|
|
6269
|
+
} finally {
|
|
6270
|
+
state.inflight -= 1;
|
|
6271
|
+
}
|
|
6272
|
+
return;
|
|
6273
|
+
}
|
|
6195
6274
|
const rawRelease = await this.semaphore.acquire();
|
|
6196
6275
|
let released = false;
|
|
6197
6276
|
const release = () => {
|
|
@@ -6215,7 +6294,7 @@ var PipelineRunner = class {
|
|
|
6215
6294
|
state.processedCount++;
|
|
6216
6295
|
if (result) {
|
|
6217
6296
|
if (result.shed === true) state.shedFrames++;
|
|
6218
|
-
await this.notifyCallbacks(deviceId, frame, result, streamType, handle);
|
|
6297
|
+
await this.notifyCallbacks(deviceId, frame, result, streamType, handle, "pipeline");
|
|
6219
6298
|
frameReleaseReason = "success";
|
|
6220
6299
|
const emittedAt = Date.now();
|
|
6221
6300
|
const capturedAt = frame.capturedAt;
|
|
@@ -6242,6 +6321,96 @@ var PipelineRunner = class {
|
|
|
6242
6321
|
}
|
|
6243
6322
|
}
|
|
6244
6323
|
/**
|
|
6324
|
+
* The CAMERA is this camera's root step.
|
|
6325
|
+
*
|
|
6326
|
+
* Same shape as the pipeline path and deliberately so: one decoded frame, one
|
|
6327
|
+
* `FrameResult`, the same `notifyCallbacks`, the same handle, the same
|
|
6328
|
+
* retention release. Everything downstream — subject tiles, birth evidence,
|
|
6329
|
+
* the `detailSteps` announce, the overlay, the tracker — cannot tell which
|
|
6330
|
+
* detector produced the boxes, which is the entire point. What it does NOT do
|
|
6331
|
+
* is take an inference permit: the accelerator is never asked.
|
|
6332
|
+
*
|
|
6333
|
+
* A frame with no fresh onboard detection produces NO result rather than an
|
|
6334
|
+
* empty one. An empty `FrameResult` is a positive statement ("I looked and
|
|
6335
|
+
* there was nothing"), and this path did not look — it decoded a frame while
|
|
6336
|
+
* the camera happened to be silent. Emitting emptiness would tell the
|
|
6337
|
+
* tracker every silent frame is evidence of absence and coast every subject
|
|
6338
|
+
* to death between two pushes.
|
|
6339
|
+
*/
|
|
6340
|
+
async processOnboardRoot(deviceId, entry, state, streamType, plan) {
|
|
6341
|
+
const { frame, handle } = entry;
|
|
6342
|
+
let frameReleaseReason = "drop";
|
|
6343
|
+
try {
|
|
6344
|
+
if (!plan.runsOnboard) {
|
|
6345
|
+
this.noteOnboardRootIdle(deviceId, "no-source");
|
|
6346
|
+
return;
|
|
6347
|
+
}
|
|
6348
|
+
const pairing = onboardRootDetections(state.onboardSlot, {
|
|
6349
|
+
timestamp: Date.now(),
|
|
6350
|
+
width: frame.width,
|
|
6351
|
+
height: frame.height
|
|
6352
|
+
});
|
|
6353
|
+
if (pairing.kind !== "paired") {
|
|
6354
|
+
this.noteOnboardRootIdle(deviceId, pairing.kind);
|
|
6355
|
+
return;
|
|
6356
|
+
}
|
|
6357
|
+
state.onboardSlot = null;
|
|
6358
|
+
state.processedCount++;
|
|
6359
|
+
const result = {
|
|
6360
|
+
kind: "frame",
|
|
6361
|
+
frameId: `onboard-${String(deviceId)}-${String(frame.timestamp)}`,
|
|
6362
|
+
deviceId,
|
|
6363
|
+
timestamp: Date.now(),
|
|
6364
|
+
width: frame.width,
|
|
6365
|
+
height: frame.height,
|
|
6366
|
+
detections: pairing.detections
|
|
6367
|
+
};
|
|
6368
|
+
state.lastResultDetections = pairing.detections.length;
|
|
6369
|
+
await this.notifyCallbacks(deviceId, frame, result, streamType, handle, "onboard");
|
|
6370
|
+
frameReleaseReason = "success";
|
|
6371
|
+
} catch {
|
|
6372
|
+
frameReleaseReason = "error";
|
|
6373
|
+
} finally {
|
|
6374
|
+
try {
|
|
6375
|
+
if (frameReleaseReason === "success" && handle && isContinuousRetainEnabled()) await this.config.hydrateRetainedFrame?.(handle);
|
|
6376
|
+
} catch {}
|
|
6377
|
+
if (handle) this.config.releaseRetention?.(handle, frameReleaseReason);
|
|
6378
|
+
if (frame.frameRef) this.config.releaseFrameRef?.(frame.frameRef, frameReleaseReason);
|
|
6379
|
+
}
|
|
6380
|
+
}
|
|
6381
|
+
/**
|
|
6382
|
+
* Report — once per camera per interval — that the onboard root step decoded
|
|
6383
|
+
* a frame and produced nothing, with WHICH of the reasons it was. Sampled
|
|
6384
|
+
* because it fires at detection fps on a silent camera, which is most of the
|
|
6385
|
+
* time and is not itself a fault.
|
|
6386
|
+
*/
|
|
6387
|
+
noteOnboardRootIdle(deviceId, reason) {
|
|
6388
|
+
const now = Date.now();
|
|
6389
|
+
const key = `${String(deviceId)}:${reason}`;
|
|
6390
|
+
if (now - (this.onboardIdleReportedAt.get(key) ?? 0) < 6e4) return;
|
|
6391
|
+
this.onboardIdleReportedAt.set(key, now);
|
|
6392
|
+
this.logger?.info("onboard root step produced nothing for a decoded frame", {
|
|
6393
|
+
tags: { deviceId },
|
|
6394
|
+
meta: { reason }
|
|
6395
|
+
});
|
|
6396
|
+
}
|
|
6397
|
+
/**
|
|
6398
|
+
* The camera spoke. Held until a decoded frame can be paired with it.
|
|
6399
|
+
*
|
|
6400
|
+
* Gated by the CALLER on `detectionSources` — this method is the mechanism,
|
|
6401
|
+
* not the policy, and a camera that does not name `onboard` never reaches it.
|
|
6402
|
+
*/
|
|
6403
|
+
reportNativeDetection(deviceId, detections, frameWidth, frameHeight) {
|
|
6404
|
+
const state = this.cameras.get(deviceId);
|
|
6405
|
+
if (!state) return;
|
|
6406
|
+
state.onboardSlot = {
|
|
6407
|
+
at: Date.now(),
|
|
6408
|
+
detections,
|
|
6409
|
+
...frameWidth !== void 0 ? { frameWidth } : {},
|
|
6410
|
+
...frameHeight !== void 0 ? { frameHeight } : {}
|
|
6411
|
+
};
|
|
6412
|
+
}
|
|
6413
|
+
/**
|
|
6245
6414
|
* Await `processFrame` with a hard bound. On expiry the permit is released
|
|
6246
6415
|
* immediately (via the caller's release-once closure) and {@link TIMED_OUT}
|
|
6247
6416
|
* is returned; the underlying call is left to settle into the void, since
|
|
@@ -6326,9 +6495,9 @@ var PipelineRunner = class {
|
|
|
6326
6495
|
});
|
|
6327
6496
|
}
|
|
6328
6497
|
}
|
|
6329
|
-
async notifyCallbacks(deviceId, frame, result, streamType, handle) {
|
|
6498
|
+
async notifyCallbacks(deviceId, frame, result, streamType, handle, source) {
|
|
6330
6499
|
for (const callback of this.resultCallbacks) try {
|
|
6331
|
-
await callback(deviceId, frame, result, streamType, handle);
|
|
6500
|
+
await callback(deviceId, frame, result, streamType, handle, source);
|
|
6332
6501
|
} catch {}
|
|
6333
6502
|
}
|
|
6334
6503
|
pickNextDetectionFrame() {
|
|
@@ -7152,6 +7321,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
7152
7321
|
/** Last runtime-label failure, so only a CHANGE is logged (D463). */
|
|
7153
7322
|
lastRuntimeInfoFailure = null;
|
|
7154
7323
|
unsubMotionEvents = null;
|
|
7324
|
+
unsubNativeDetections = null;
|
|
7155
7325
|
/** Devices we have positively observed reporting `battery.sleeping: true`.
|
|
7156
7326
|
* Absent = unknown or awake; both mean "do not gate" (D49). Fed only by
|
|
7157
7327
|
* `BatteryOnStatusChanged`, so consulting it costs nothing and can never
|
|
@@ -7408,11 +7578,11 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
7408
7578
|
this.runner.onDetectionStreamChange((deviceId, action) => {
|
|
7409
7579
|
this.handleDetectionStreamChange(deviceId, action);
|
|
7410
7580
|
});
|
|
7411
|
-
this.runner.onResult(async (deviceId, frame, result, _streamType, handle) => {
|
|
7581
|
+
this.runner.onResult(async (deviceId, frame, result, _streamType, handle, source) => {
|
|
7412
7582
|
this.retention?.noteInferenceResult(deviceId, handle, result);
|
|
7413
7583
|
this.cutSubjectTiles(deviceId, result, handle);
|
|
7414
7584
|
const carried = await this.attachBirthEvidence(deviceId, frame, result);
|
|
7415
|
-
this.emitInferenceResult(deviceId, frame, carried, handle);
|
|
7585
|
+
this.emitInferenceResult(deviceId, frame, carried, handle, source);
|
|
7416
7586
|
const detectionCount = result.detections?.length ?? 0;
|
|
7417
7587
|
this.runner?.noteDetectionResult(deviceId, detectionCount);
|
|
7418
7588
|
if (detectionCount > 0 && this.occupancyBurstInFlight.has(deviceId)) this.occupancyBurstFound.add(deviceId);
|
|
@@ -7436,13 +7606,26 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
7436
7606
|
if (source === "analyzer" && cameraOwnsMotionViaSensor(attachment.config.motionSources)) return;
|
|
7437
7607
|
this.runner?.reportMotion(deviceId, data.detected, source, data.regions ? [...data.regions] : void 0);
|
|
7438
7608
|
});
|
|
7439
|
-
if (this.ctx.eventBus)
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7609
|
+
if (this.ctx.eventBus) {
|
|
7610
|
+
this.unsubNativeDetections = this.ctx.eventBus.subscribe({ category: EventCategory.DetectionCameraNative }, (event) => {
|
|
7611
|
+
const data = event.data;
|
|
7612
|
+
const deviceId = data.cameraId;
|
|
7613
|
+
if (typeof deviceId !== "number") return;
|
|
7614
|
+
const attachment = this.attached.get(deviceId);
|
|
7615
|
+
if (!attachment) return;
|
|
7616
|
+
if (!planDetectionSources(attachment.config.detectionSources).runsOnboard) return;
|
|
7617
|
+
const detections = data.detections;
|
|
7618
|
+
if (!detections || detections.length === 0) return;
|
|
7619
|
+
this.runner?.reportNativeDetection(deviceId, detections, data.frameWidth, data.frameHeight);
|
|
7620
|
+
});
|
|
7621
|
+
this.unsubBatteryEvents = this.ctx.eventBus.subscribe({ category: EventCategory.BatteryOnStatusChanged }, (event) => {
|
|
7622
|
+
const data = event.data;
|
|
7623
|
+
const deviceId = data.deviceId;
|
|
7624
|
+
if (typeof deviceId !== "number") return;
|
|
7625
|
+
if (data.status?.sleeping === true) this.sleepingBatteryDevices.add(deviceId);
|
|
7626
|
+
else this.sleepingBatteryDevices.delete(deviceId);
|
|
7627
|
+
});
|
|
7628
|
+
}
|
|
7446
7629
|
this.metricsSnapshotTimer = setInterval(() => this.emitMetricsSnapshot(), METRICS_SNAPSHOT_INTERVAL_MS);
|
|
7447
7630
|
return {
|
|
7448
7631
|
providers: [
|
|
@@ -7491,6 +7674,10 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
7491
7674
|
this.unsubMotionEvents();
|
|
7492
7675
|
this.unsubMotionEvents = null;
|
|
7493
7676
|
}
|
|
7677
|
+
if (this.unsubNativeDetections) {
|
|
7678
|
+
this.unsubNativeDetections();
|
|
7679
|
+
this.unsubNativeDetections = null;
|
|
7680
|
+
}
|
|
7494
7681
|
if (this.unsubBatteryEvents) {
|
|
7495
7682
|
this.unsubBatteryEvents();
|
|
7496
7683
|
this.unsubBatteryEvents = null;
|
|
@@ -10603,7 +10790,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
10603
10790
|
teardown();
|
|
10604
10791
|
}
|
|
10605
10792
|
}
|
|
10606
|
-
emitInferenceResult(deviceId, frame, result, handle) {
|
|
10793
|
+
emitInferenceResult(deviceId, frame, result, handle, source) {
|
|
10607
10794
|
if (!this.ctx?.eventBus) return;
|
|
10608
10795
|
const capturedAt = frame.capturedAt;
|
|
10609
10796
|
const detailSteps = this.attached.get(deviceId)?.detailSteps;
|
|
@@ -10614,7 +10801,8 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
10614
10801
|
frameHandle: handle,
|
|
10615
10802
|
emittedAt: Date.now(),
|
|
10616
10803
|
...typeof capturedAt === "number" && capturedAt > 0 ? { capturedAt } : {},
|
|
10617
|
-
...detailSteps && detailSteps.length > 0 ? { detailSteps } : {}
|
|
10804
|
+
...detailSteps && detailSteps.length > 0 ? { detailSteps } : {},
|
|
10805
|
+
source
|
|
10618
10806
|
};
|
|
10619
10807
|
this.ctx.eventBus.emit(createEvent(EventCategory.PipelineInferenceResult, {
|
|
10620
10808
|
type: "device",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-emK7D4bc.js");
|
|
2
|
-
const require_dist = require("./dist-
|
|
2
|
+
const require_dist = require("./dist-NX0e_oWp.js");
|
|
3
3
|
let node_fs = require("node:fs");
|
|
4
4
|
node_fs = require_chunk.__toESM(node_fs);
|
|
5
5
|
let node_child_process = require("node:child_process");
|
package/dist/recorder/index.js
CHANGED
|
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
7
|
-
const require_node = require("../node-
|
|
6
|
+
const require_dist = require("../dist-NX0e_oWp.js");
|
|
7
|
+
const require_node = require("../node-BgM4n8D4.js");
|
|
8
8
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
9
9
|
const require_restream_intent = require("../restream-intent-C4adO0P8.js");
|
|
10
10
|
const require_retire_root_keys = require("../retire-root-keys-Csb8z2f3.js");
|
|
@@ -10905,6 +10905,7 @@ Object.freeze({
|
|
|
10905
10905
|
"motionFps": 4,
|
|
10906
10906
|
"detectionFps": 10,
|
|
10907
10907
|
"motionSources": ["analyzer"],
|
|
10908
|
+
"detectionSources": ["pipeline"],
|
|
10908
10909
|
"pipelineEnabled": true,
|
|
10909
10910
|
"zones": [],
|
|
10910
10911
|
"onboardMotionDrivesAnalyzer": true,
|