@camstack/addon-pipeline 1.2.233 → 1.2.235

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.
@@ -6302,7 +6302,7 @@ var PipelineRunner = class {
6302
6302
  state.processedCount++;
6303
6303
  if (result) {
6304
6304
  if (result.shed === true) state.shedFrames++;
6305
- await this.notifyCallbacks(deviceId, frame, result, streamType, handle, "pipeline");
6305
+ await this.notifyCallbacks(deviceId, frame, plan.runsOnboard ? this.mergeOnboardDetections(state, result, frame) : result, streamType, handle, "pipeline");
6306
6306
  frameReleaseReason = "success";
6307
6307
  const emittedAt = Date.now();
6308
6308
  const capturedAt = frame.capturedAt;
@@ -6329,6 +6329,27 @@ var PipelineRunner = class {
6329
6329
  }
6330
6330
  }
6331
6331
  /**
6332
+ * Fold the camera's pending boxes into a result the ML pass just produced.
6333
+ *
6334
+ * Consumes the slot exactly as {@link processOnboardRoot} does — the same
6335
+ * push must never be pinned onto a second frame — and returns `result`
6336
+ * untouched when there is nothing fresh to add, so the common quiet frame
6337
+ * allocates nothing.
6338
+ */
6339
+ mergeOnboardDetections(state, result, frame) {
6340
+ const pairing = onboardRootDetections(state.onboardSlot, {
6341
+ timestamp: Date.now(),
6342
+ width: frame.width,
6343
+ height: frame.height
6344
+ });
6345
+ if (pairing.kind !== "paired") return result;
6346
+ state.onboardSlot = null;
6347
+ return {
6348
+ ...result,
6349
+ detections: [...result.detections ?? [], ...pairing.detections]
6350
+ };
6351
+ }
6352
+ /**
6332
6353
  * The CAMERA is this camera's root step.
6333
6354
  *
6334
6355
  * Same shape as the pipeline path and deliberately so: one decoded frame, one
@@ -8422,6 +8443,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
8422
8443
  this.dropParkedDetail(config.deviceId);
8423
8444
  runner.registerCamera(config.deviceId, {
8424
8445
  detectionMode: config.detectionMode,
8446
+ ...config.detectionSources !== void 0 ? { detectionSources: config.detectionSources } : {},
8425
8447
  fps: config.detectionFps,
8426
8448
  motionCooldownMs: config.motionCooldownMs,
8427
8449
  occupancyRecheckEnabled: config.occupancyRecheckEnabled,
@@ -6294,7 +6294,7 @@ var PipelineRunner = class {
6294
6294
  state.processedCount++;
6295
6295
  if (result) {
6296
6296
  if (result.shed === true) state.shedFrames++;
6297
- await this.notifyCallbacks(deviceId, frame, result, streamType, handle, "pipeline");
6297
+ await this.notifyCallbacks(deviceId, frame, plan.runsOnboard ? this.mergeOnboardDetections(state, result, frame) : result, streamType, handle, "pipeline");
6298
6298
  frameReleaseReason = "success";
6299
6299
  const emittedAt = Date.now();
6300
6300
  const capturedAt = frame.capturedAt;
@@ -6321,6 +6321,27 @@ var PipelineRunner = class {
6321
6321
  }
6322
6322
  }
6323
6323
  /**
6324
+ * Fold the camera's pending boxes into a result the ML pass just produced.
6325
+ *
6326
+ * Consumes the slot exactly as {@link processOnboardRoot} does — the same
6327
+ * push must never be pinned onto a second frame — and returns `result`
6328
+ * untouched when there is nothing fresh to add, so the common quiet frame
6329
+ * allocates nothing.
6330
+ */
6331
+ mergeOnboardDetections(state, result, frame) {
6332
+ const pairing = onboardRootDetections(state.onboardSlot, {
6333
+ timestamp: Date.now(),
6334
+ width: frame.width,
6335
+ height: frame.height
6336
+ });
6337
+ if (pairing.kind !== "paired") return result;
6338
+ state.onboardSlot = null;
6339
+ return {
6340
+ ...result,
6341
+ detections: [...result.detections ?? [], ...pairing.detections]
6342
+ };
6343
+ }
6344
+ /**
6324
6345
  * The CAMERA is this camera's root step.
6325
6346
  *
6326
6347
  * Same shape as the pipeline path and deliberately so: one decoded frame, one
@@ -8414,6 +8435,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
8414
8435
  this.dropParkedDetail(config.deviceId);
8415
8436
  runner.registerCamera(config.deviceId, {
8416
8437
  detectionMode: config.detectionMode,
8438
+ ...config.detectionSources !== void 0 ? { detectionSources: config.detectionSources } : {},
8417
8439
  fps: config.detectionFps,
8418
8440
  motionCooldownMs: config.motionCooldownMs,
8419
8441
  occupancyRecheckEnabled: config.occupancyRecheckEnabled,
@@ -18,7 +18,7 @@ var e = {
18
18
  },
19
19
  "@camstack/types": {
20
20
  name: "@camstack/types",
21
- version: "1.2.191",
21
+ version: "1.2.193",
22
22
  scope: ["default"],
23
23
  loaded: !1,
24
24
  from: "addon_stream_broker_widgets",
@@ -33,7 +33,7 @@ var e = {
33
33
  },
34
34
  "@camstack/ui-library": {
35
35
  name: "@camstack/ui-library",
36
- version: "1.2.156",
36
+ version: "1.2.158",
37
37
  scope: ["default"],
38
38
  loaded: !1,
39
39
  from: "addon_stream_broker_widgets",
@@ -36,7 +36,7 @@ async function r() {
36
36
  }
37
37
  },
38
38
  "@camstack/types": {
39
- version: "1.2.191",
39
+ version: "1.2.193",
40
40
  scope: "default",
41
41
  shareConfig: {
42
42
  singleton: !0,
@@ -81,7 +81,7 @@ async function r() {
81
81
  }
82
82
  },
83
83
  "@camstack/ui-library": {
84
- version: "1.2.156",
84
+ version: "1.2.158",
85
85
  scope: "default",
86
86
  shareConfig: {
87
87
  singleton: !0,
@@ -12107,6 +12107,33 @@ var PrestreamPump = class {
12107
12107
  });
12108
12108
  }
12109
12109
  /**
12110
+ * Prepare the picture NOW, so the next wake does not have to.
12111
+ *
12112
+ * The window is ~6 s wide and the preparation was measured at 2.5-5.5 s of
12113
+ * it (Baby monitor, 2026-09-14) — the placeholder was ready with under a
12114
+ * second left and emitted ONE frame, which is indistinguishable from the
12115
+ * prestream not working, and is how the operator reported it. The encode
12116
+ * cache upstream was built for exactly this and missed every time: it is
12117
+ * keyed on the snapshot's digest, and a fresh snapshot is captured during
12118
+ * every stream window, so the key changed on every wake.
12119
+ *
12120
+ * Called when the camera is ALREADY awake and nobody is waiting (the broker
12121
+ * suspends), which is also the moment its snapshot is the freshest it will
12122
+ * be until the next wake — so the digest that gets cached is the digest the
12123
+ * next wake will compute. It opens NO window, emits nothing and arms no
12124
+ * timer: the only effect it wants is the one it has upstream, a warm cache.
12125
+ *
12126
+ * A failure is swallowed on purpose. This is an optimisation running on
12127
+ * nobody's behalf; reporting it as a fault would put a warn line on every
12128
+ * camera that sleeps with a busy encoder.
12129
+ */
12130
+ warm(sourceUrl) {
12131
+ if (this.active) return;
12132
+ this.options.prepare({ sourceUrl }).then(() => {
12133
+ this.options.logger?.debug("prestream: picture warmed for the next wake", { ...this.tags });
12134
+ }).catch(() => {});
12135
+ }
12136
+ /**
12110
12137
  * Close the window. Called on the first NON-placeholder packet — the one edge
12111
12138
  * the prestream is defined by — and on the broker's own teardown paths so a
12112
12139
  * stopped broker leaves no timer behind.
@@ -13576,6 +13603,8 @@ var StreamBroker = class StreamBroker {
13576
13603
  this.placeholderTimer = void 0;
13577
13604
  }
13578
13605
  this.prestreamPump?.stop("broker suspended");
13606
+ const warmUrl = this.source?.url;
13607
+ if (warmUrl !== void 0 && warmUrl.length > 0) this.prestreamPump?.warm(warmUrl);
13579
13608
  this.prestreamWindowClosed = false;
13580
13609
  this.preBuffer.clear();
13581
13610
  this.decoderSeedBuffer.clear();
@@ -12103,6 +12103,33 @@ var PrestreamPump = class {
12103
12103
  });
12104
12104
  }
12105
12105
  /**
12106
+ * Prepare the picture NOW, so the next wake does not have to.
12107
+ *
12108
+ * The window is ~6 s wide and the preparation was measured at 2.5-5.5 s of
12109
+ * it (Baby monitor, 2026-09-14) — the placeholder was ready with under a
12110
+ * second left and emitted ONE frame, which is indistinguishable from the
12111
+ * prestream not working, and is how the operator reported it. The encode
12112
+ * cache upstream was built for exactly this and missed every time: it is
12113
+ * keyed on the snapshot's digest, and a fresh snapshot is captured during
12114
+ * every stream window, so the key changed on every wake.
12115
+ *
12116
+ * Called when the camera is ALREADY awake and nobody is waiting (the broker
12117
+ * suspends), which is also the moment its snapshot is the freshest it will
12118
+ * be until the next wake — so the digest that gets cached is the digest the
12119
+ * next wake will compute. It opens NO window, emits nothing and arms no
12120
+ * timer: the only effect it wants is the one it has upstream, a warm cache.
12121
+ *
12122
+ * A failure is swallowed on purpose. This is an optimisation running on
12123
+ * nobody's behalf; reporting it as a fault would put a warn line on every
12124
+ * camera that sleeps with a busy encoder.
12125
+ */
12126
+ warm(sourceUrl) {
12127
+ if (this.active) return;
12128
+ this.options.prepare({ sourceUrl }).then(() => {
12129
+ this.options.logger?.debug("prestream: picture warmed for the next wake", { ...this.tags });
12130
+ }).catch(() => {});
12131
+ }
12132
+ /**
12106
12133
  * Close the window. Called on the first NON-placeholder packet — the one edge
12107
12134
  * the prestream is defined by — and on the broker's own teardown paths so a
12108
12135
  * stopped broker leaves no timer behind.
@@ -13572,6 +13599,8 @@ var StreamBroker = class StreamBroker {
13572
13599
  this.placeholderTimer = void 0;
13573
13600
  }
13574
13601
  this.prestreamPump?.stop("broker suspended");
13602
+ const warmUrl = this.source?.url;
13603
+ if (warmUrl !== void 0 && warmUrl.length > 0) this.prestreamPump?.warm(warmUrl);
13575
13604
  this.prestreamWindowClosed = false;
13576
13605
  this.preBuffer.clear();
13577
13606
  this.decoderSeedBuffer.clear();
@@ -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_stream_broker_widgets-DN-9qAgC.mjs")).catch((e) => {
33
+ return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DmrtFHgm.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",
3
- "version": "1.2.233",
3
+ "version": "1.2.235",
4
4
  "description": "Pipeline bundle — runner, detection, motion, audio + stream broker. Multi-entry npm package shipping pipeline addons under a single bundle.",
5
5
  "keywords": [
6
6
  "camstack",