@camstack/addon-pipeline 1.1.39 → 1.1.41

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.
Files changed (38) hide show
  1. package/dist/audio-analyzer/index.js +168 -61
  2. package/dist/audio-analyzer/index.mjs +168 -61
  3. package/dist/detection-pipeline/index.js +2 -2
  4. package/dist/detection-pipeline/index.mjs +2 -2
  5. package/dist/{dist-DbGdZ8Nr.js → dist-BJTPkJFw.js} +247 -3
  6. package/dist/{dist-DvvYzO58.mjs → dist-v6cKLmU3.mjs} +247 -3
  7. package/dist/{frame-handle-plane-B7jMIZc2.js → frame-handle-plane-BP8YV4sF.js} +54 -5
  8. package/dist/{frame-handle-plane-BFzoIfkd.mjs → frame-handle-plane-DKAXTtfn.mjs} +54 -5
  9. package/dist/motion-wasm/index.js +1 -1
  10. package/dist/motion-wasm/index.mjs +1 -1
  11. package/dist/pipeline-runner/index.js +893 -12
  12. package/dist/pipeline-runner/index.mjs +892 -13
  13. package/dist/recorder/index.js +2 -2
  14. package/dist/recorder/index.mjs +2 -2
  15. package/dist/session-decode/decode-worker-child.js +544 -0
  16. package/dist/session-decode/decode-worker-child.mjs +543 -0
  17. package/dist/stream-broker/_stub.js +44 -44
  18. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DezFy4Fu.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-C2l0kmD4.mjs} +3 -3
  19. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DqJvWBKS.mjs +26 -0
  20. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-dGka8yZY.mjs +26 -0
  21. package/dist/stream-broker/{hostInit-BOf0hg9q.mjs → hostInit-DHaCRMjM.mjs} +3 -3
  22. package/dist/stream-broker/index.js +268 -38
  23. package/dist/stream-broker/index.mjs +268 -38
  24. package/dist/stream-broker/remoteEntry.js +1 -1
  25. package/dist/worker-protocol-BCfO8gUF.js +67 -0
  26. package/dist/worker-protocol-pk7qdYXt.mjs +56 -0
  27. package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-Br2fqwe7.js → MaskShapeCanvas-DI4BY7W2-B6fza7ic.js} +1 -1
  28. package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-DYXRf30g.js → MotionZonesSettings-NcxxQN8r-Cy-4iTog.js} +1 -1
  29. package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-DLpqLgPo.js → PrivacyMaskSettings-APgPLF7p-CYX33lJb.js} +1 -1
  30. package/embed-dist/assets/index-BPkayx9u.js +81 -0
  31. package/embed-dist/assets/index-CSFtK41z.css +2 -0
  32. package/embed-dist/index.html +2 -2
  33. package/package.json +6 -3
  34. package/python/inference_pool.py +3 -1
  35. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DhY3MZ2C.mjs +0 -26
  36. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BsrrdOBU.mjs +0 -26
  37. package/embed-dist/assets/index-C5UpuPr8.css +0 -2
  38. package/embed-dist/assets/index-CR367rYR.js +0 -81
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-DbGdZ8Nr.js");
1
+ const require_dist = require("./dist-BJTPkJFw.js");
2
2
  let node_crypto = require("node:crypto");
3
3
  //#region src/stream-broker/stream-broker/decoder-session-proxy.ts
4
4
  /**
@@ -173,6 +173,27 @@ var DECODE_FPS_WINDOW_MS = 2e3;
173
173
  */
174
174
  var SESSION_LINGER_MS = 45e3;
175
175
  /**
176
+ * Short keep-warm grace for a PURE-OCCUPANCY session (every remaining
177
+ * subscriber is a periodic on-motion occupancy recheck, tag `'occupancy'`).
178
+ *
179
+ * Occupancy rechecks subscribe to decoded frames for ~1s every ~30s. The
180
+ * normal `SESSION_LINGER_MS` (45s) EXCEEDS that ~30s interval, so the linger
181
+ * timer is perpetually cancelled by the next recheck before it can fire — the
182
+ * decoder never tears down and decodes continuously at source-rate to serve a
183
+ * 1s/30s consumer (~30x wasted decode; multiplied across cameras this is the
184
+ * iGPU baseline that saturated the decoder). A pure-occupancy session instead
185
+ * tears down between polls: short enough to fire well before the next ~30s
186
+ * recheck, long enough to absorb the ~1s poll plus minor jitter. Re-dial is
187
+ * cheap on GPU-scale decode and the restream burst re-primes the live edge
188
+ * fast, so on-demand re-arm on the next recheck is fine.
189
+ */
190
+ var OCCUPANCY_LINGER_MS = 5e3;
191
+ /** Subscription tag emitted by the periodic on-motion occupancy recheck. A
192
+ * session whose subscribers have only ever carried this tag gets the short
193
+ * `OCCUPANCY_LINGER_MS` teardown; any other subscriber biases to the long
194
+ * `SESSION_LINGER_MS` warm linger (interactive viewers, detection, motion). */
195
+ var OCCUPANCY_TAG = "occupancy";
196
+ /**
176
197
  * Default retry cooldown after a decoder session lands on a NON-LOCAL node
177
198
  * (see `FrameHandlePlaneOptions.sessionRetryCooldownMs`). Long enough to
178
199
  * turn a per-packet storm into a slow probe; short enough that the plane
@@ -190,6 +211,7 @@ var FrameHandlePlane = class {
190
211
  localNodeId;
191
212
  sessionRetryCooldownMs;
192
213
  getSeedPackets;
214
+ isDebugEnabled;
193
215
  subscriptions = /* @__PURE__ */ new Map();
194
216
  sessions = /* @__PURE__ */ new Map();
195
217
  /** Per-format retry gate set when a session lands on a non-local node:
@@ -219,6 +241,7 @@ var FrameHandlePlane = class {
219
241
  this.localNodeId = options.localNodeId;
220
242
  this.sessionRetryCooldownMs = options.sessionRetryCooldownMs ?? SESSION_RETRY_COOLDOWN_MS;
221
243
  this.getSeedPackets = options.getSeedPackets;
244
+ this.isDebugEnabled = options.isDebugEnabled;
222
245
  }
223
246
  /** Number of active handle subscriptions — surfaced for diagnostics. */
224
247
  get subscriberCount() {
@@ -375,15 +398,33 @@ var FrameHandlePlane = class {
375
398
  */
376
399
  scheduleLinger(session) {
377
400
  this.clearLinger(session);
401
+ const occupancyOnly = !session.hasNonOccupancySubscriberEver;
402
+ const lingerMs = occupancyOnly ? OCCUPANCY_LINGER_MS : SESSION_LINGER_MS;
403
+ this.logger?.debug(occupancyOnly ? "frame-handle plane: short occupancy linger scheduled" : "frame-handle plane: keep-warm linger scheduled", { meta: {
404
+ format: session.format,
405
+ lingerMs,
406
+ occupancyOnly
407
+ } });
378
408
  const timer = setTimeout(() => {
379
409
  session.lingerTimer = null;
380
410
  if (session.subscriberIds.size > 0) return;
381
411
  this.sessions.delete(session.format);
382
412
  this.destroySession(session).catch(() => {});
383
- }, SESSION_LINGER_MS);
413
+ }, lingerMs);
384
414
  timer.unref?.();
385
415
  session.lingerTimer = timer;
386
416
  }
417
+ /**
418
+ * Latch `session.hasNonOccupancySubscriberEver` when the subscription
419
+ * `subscriptionId` carries any tag other than `OCCUPANCY_TAG`. Called at
420
+ * every point a subscription is attached to a session so the keep-warm
421
+ * decision only fast-tears-down sessions that have been PURELY on-demand
422
+ * occupancy rechecks. Unknown ids (mid-teardown) are ignored.
423
+ */
424
+ noteSessionSubscriberTag(session, subscriptionId) {
425
+ const subscription = this.subscriptions.get(subscriptionId);
426
+ if (subscription && subscription.tag !== OCCUPANCY_TAG) session.hasNonOccupancySubscriberEver = true;
427
+ }
387
428
  /** Cancel a session's pending keep-warm teardown timer, if any. */
388
429
  clearLinger(session) {
389
430
  if (session.lingerTimer) {
@@ -563,12 +604,17 @@ var FrameHandlePlane = class {
563
604
  if (existing) {
564
605
  this.clearLinger(existing);
565
606
  existing.subscriberIds.add(subscriptionId);
607
+ this.noteSessionSubscriberTag(existing, subscriptionId);
566
608
  return;
567
609
  }
568
610
  const inflight = this.sessionCreating.get(format);
569
611
  if (inflight) {
570
612
  await inflight;
571
- this.sessions.get(format)?.subscriberIds.add(subscriptionId);
613
+ const session = this.sessions.get(format);
614
+ if (session) {
615
+ session.subscriberIds.add(subscriptionId);
616
+ this.noteSessionSubscriberTag(session, subscriptionId);
617
+ }
572
618
  return;
573
619
  }
574
620
  if (Date.now() < (this.sessionRetryCooldownUntil.get(format) ?? 0)) return;
@@ -583,8 +629,10 @@ var FrameHandlePlane = class {
583
629
  bootstrapped: false,
584
630
  pullMode: false,
585
631
  targetFps: this.computeFormatFps(format),
586
- lingerTimer: null
632
+ lingerTimer: null,
633
+ hasNonOccupancySubscriberEver: false
587
634
  };
635
+ for (const id of subscriberIds) this.noteSessionSubscriberTag(session, id);
588
636
  let started = false;
589
637
  try {
590
638
  started = await this.startSessionDecoder(session);
@@ -631,7 +679,8 @@ var FrameHandlePlane = class {
631
679
  scale: 1,
632
680
  frameSink: "shm",
633
681
  ...info.numericDeviceId !== void 0 ? { deviceId: info.numericDeviceId } : {},
634
- tag: `${info.tag}:shm:${format}`
682
+ tag: `${info.tag}:shm:${format}`,
683
+ ...this.isDebugEnabled?.() ? { debug: true } : {}
635
684
  });
636
685
  if (!isDecoderNodeColocated(this.localNodeId, nodeId)) {
637
686
  this.sessionRetryCooldownUntil.set(format, Date.now() + this.sessionRetryCooldownMs);
@@ -1,4 +1,4 @@
1
- import { I as errMsg, d as RingBuffer } from "./dist-DvvYzO58.mjs";
1
+ import { I as errMsg, d as RingBuffer } from "./dist-v6cKLmU3.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  //#region src/stream-broker/stream-broker/decoder-session-proxy.ts
4
4
  /**
@@ -173,6 +173,27 @@ var DECODE_FPS_WINDOW_MS = 2e3;
173
173
  */
174
174
  var SESSION_LINGER_MS = 45e3;
175
175
  /**
176
+ * Short keep-warm grace for a PURE-OCCUPANCY session (every remaining
177
+ * subscriber is a periodic on-motion occupancy recheck, tag `'occupancy'`).
178
+ *
179
+ * Occupancy rechecks subscribe to decoded frames for ~1s every ~30s. The
180
+ * normal `SESSION_LINGER_MS` (45s) EXCEEDS that ~30s interval, so the linger
181
+ * timer is perpetually cancelled by the next recheck before it can fire — the
182
+ * decoder never tears down and decodes continuously at source-rate to serve a
183
+ * 1s/30s consumer (~30x wasted decode; multiplied across cameras this is the
184
+ * iGPU baseline that saturated the decoder). A pure-occupancy session instead
185
+ * tears down between polls: short enough to fire well before the next ~30s
186
+ * recheck, long enough to absorb the ~1s poll plus minor jitter. Re-dial is
187
+ * cheap on GPU-scale decode and the restream burst re-primes the live edge
188
+ * fast, so on-demand re-arm on the next recheck is fine.
189
+ */
190
+ var OCCUPANCY_LINGER_MS = 5e3;
191
+ /** Subscription tag emitted by the periodic on-motion occupancy recheck. A
192
+ * session whose subscribers have only ever carried this tag gets the short
193
+ * `OCCUPANCY_LINGER_MS` teardown; any other subscriber biases to the long
194
+ * `SESSION_LINGER_MS` warm linger (interactive viewers, detection, motion). */
195
+ var OCCUPANCY_TAG = "occupancy";
196
+ /**
176
197
  * Default retry cooldown after a decoder session lands on a NON-LOCAL node
177
198
  * (see `FrameHandlePlaneOptions.sessionRetryCooldownMs`). Long enough to
178
199
  * turn a per-packet storm into a slow probe; short enough that the plane
@@ -190,6 +211,7 @@ var FrameHandlePlane = class {
190
211
  localNodeId;
191
212
  sessionRetryCooldownMs;
192
213
  getSeedPackets;
214
+ isDebugEnabled;
193
215
  subscriptions = /* @__PURE__ */ new Map();
194
216
  sessions = /* @__PURE__ */ new Map();
195
217
  /** Per-format retry gate set when a session lands on a non-local node:
@@ -219,6 +241,7 @@ var FrameHandlePlane = class {
219
241
  this.localNodeId = options.localNodeId;
220
242
  this.sessionRetryCooldownMs = options.sessionRetryCooldownMs ?? SESSION_RETRY_COOLDOWN_MS;
221
243
  this.getSeedPackets = options.getSeedPackets;
244
+ this.isDebugEnabled = options.isDebugEnabled;
222
245
  }
223
246
  /** Number of active handle subscriptions — surfaced for diagnostics. */
224
247
  get subscriberCount() {
@@ -375,15 +398,33 @@ var FrameHandlePlane = class {
375
398
  */
376
399
  scheduleLinger(session) {
377
400
  this.clearLinger(session);
401
+ const occupancyOnly = !session.hasNonOccupancySubscriberEver;
402
+ const lingerMs = occupancyOnly ? OCCUPANCY_LINGER_MS : SESSION_LINGER_MS;
403
+ this.logger?.debug(occupancyOnly ? "frame-handle plane: short occupancy linger scheduled" : "frame-handle plane: keep-warm linger scheduled", { meta: {
404
+ format: session.format,
405
+ lingerMs,
406
+ occupancyOnly
407
+ } });
378
408
  const timer = setTimeout(() => {
379
409
  session.lingerTimer = null;
380
410
  if (session.subscriberIds.size > 0) return;
381
411
  this.sessions.delete(session.format);
382
412
  this.destroySession(session).catch(() => {});
383
- }, SESSION_LINGER_MS);
413
+ }, lingerMs);
384
414
  timer.unref?.();
385
415
  session.lingerTimer = timer;
386
416
  }
417
+ /**
418
+ * Latch `session.hasNonOccupancySubscriberEver` when the subscription
419
+ * `subscriptionId` carries any tag other than `OCCUPANCY_TAG`. Called at
420
+ * every point a subscription is attached to a session so the keep-warm
421
+ * decision only fast-tears-down sessions that have been PURELY on-demand
422
+ * occupancy rechecks. Unknown ids (mid-teardown) are ignored.
423
+ */
424
+ noteSessionSubscriberTag(session, subscriptionId) {
425
+ const subscription = this.subscriptions.get(subscriptionId);
426
+ if (subscription && subscription.tag !== OCCUPANCY_TAG) session.hasNonOccupancySubscriberEver = true;
427
+ }
387
428
  /** Cancel a session's pending keep-warm teardown timer, if any. */
388
429
  clearLinger(session) {
389
430
  if (session.lingerTimer) {
@@ -563,12 +604,17 @@ var FrameHandlePlane = class {
563
604
  if (existing) {
564
605
  this.clearLinger(existing);
565
606
  existing.subscriberIds.add(subscriptionId);
607
+ this.noteSessionSubscriberTag(existing, subscriptionId);
566
608
  return;
567
609
  }
568
610
  const inflight = this.sessionCreating.get(format);
569
611
  if (inflight) {
570
612
  await inflight;
571
- this.sessions.get(format)?.subscriberIds.add(subscriptionId);
613
+ const session = this.sessions.get(format);
614
+ if (session) {
615
+ session.subscriberIds.add(subscriptionId);
616
+ this.noteSessionSubscriberTag(session, subscriptionId);
617
+ }
572
618
  return;
573
619
  }
574
620
  if (Date.now() < (this.sessionRetryCooldownUntil.get(format) ?? 0)) return;
@@ -583,8 +629,10 @@ var FrameHandlePlane = class {
583
629
  bootstrapped: false,
584
630
  pullMode: false,
585
631
  targetFps: this.computeFormatFps(format),
586
- lingerTimer: null
632
+ lingerTimer: null,
633
+ hasNonOccupancySubscriberEver: false
587
634
  };
635
+ for (const id of subscriberIds) this.noteSessionSubscriberTag(session, id);
588
636
  let started = false;
589
637
  try {
590
638
  started = await this.startSessionDecoder(session);
@@ -631,7 +679,8 @@ var FrameHandlePlane = class {
631
679
  scale: 1,
632
680
  frameSink: "shm",
633
681
  ...info.numericDeviceId !== void 0 ? { deviceId: info.numericDeviceId } : {},
634
- tag: `${info.tag}:shm:${format}`
682
+ tag: `${info.tag}:shm:${format}`,
683
+ ...this.isDebugEnabled?.() ? { debug: true } : {}
635
684
  });
636
685
  if (!isDecoderNodeColocated(this.localNodeId, nodeId)) {
637
686
  this.sessionRetryCooldownUntil.set(format, Date.now() + this.sessionRetryCooldownMs);
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-DbGdZ8Nr.js");
5
+ const require_dist = require("../dist-BJTPkJFw.js");
6
6
  let _camstack_shm_ring = require("@camstack/shm-ring");
7
7
  let node_fs = require("node:fs");
8
8
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { B as DeviceType, E as motionDetectionCapability, L as BaseAddon, U as hydrateSchema, x as evaluateZoneRules } from "../dist-DvvYzO58.mjs";
1
+ import { B as DeviceType, E as motionDetectionCapability, L as BaseAddon, U as hydrateSchema, x as evaluateZoneRules } from "../dist-v6cKLmU3.mjs";
2
2
  import { FrameRingReaderCache } from "@camstack/shm-ring";
3
3
  import { readFileSync } from "node:fs";
4
4
  import { join } from "node:path";