@camstack/addon-pipeline 1.2.217 → 1.2.218

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 (121) hide show
  1. package/dist/audio-analyzer/index.js +2 -2
  2. package/dist/audio-analyzer/index.mjs +2 -2
  3. package/dist/{default-detection-model-BwNEV8Wl.mjs → default-detection-model-AJyhoTLF.mjs} +1 -1
  4. package/dist/{default-detection-model-DzzuINe-.js → default-detection-model-Bf45EQ98.js} +1 -1
  5. package/dist/detection-pipeline/index.js +5 -5
  6. package/dist/detection-pipeline/index.mjs +4 -4
  7. package/dist/{dist-D7hxiBnC.js → dist-BbvtiBNc.js} +41 -4
  8. package/dist/{dist-DgeXZfwn.mjs → dist-Dl6GntEh.mjs} +41 -4
  9. package/dist/{lazy-sharp-BSkbiuz5.js → lazy-sharp-L9Lcr62v.js} +1 -1
  10. package/dist/motion-wasm/index.js +2 -2
  11. package/dist/motion-wasm/index.mjs +1 -1
  12. package/dist/{node-C9GcBrwk.mjs → node-CEyw52D2.mjs} +1 -1
  13. package/dist/{node-DDhmPcOx.js → node-CbCVHEvJ.js} +1 -1
  14. package/dist/pipeline-runner/index.js +13 -6
  15. package/dist/pipeline-runner/index.mjs +12 -5
  16. package/dist/{process-memory-ENqmiiis.js → process-memory-DBxdiCSF.js} +1 -1
  17. package/dist/{process-memory-Dw3CGS3D.mjs → process-memory-Du00R6-e.mjs} +1 -1
  18. package/dist/recorder/index.js +92 -14
  19. package/dist/recorder/index.mjs +92 -14
  20. package/dist/{segment-demux-js-BGbKlotF.mjs → segment-demux-js-B278aBtB.mjs} +1 -1
  21. package/dist/{segment-demux-js-sLs8mbZQ.js → segment-demux-js-D7bjzY8M.js} +1 -1
  22. package/dist/session-decode/decode-worker-child.js +2 -2
  23. package/dist/session-decode/decode-worker-child.mjs +1 -1
  24. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BULotDCb.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BnmbfnAd.mjs} +3 -3
  25. package/dist/stream-broker/demux-worker-child.js +1 -1
  26. package/dist/stream-broker/demux-worker-child.mjs +1 -1
  27. package/dist/stream-broker/{hostInit-_RQxF72h.mjs → hostInit-MIKQqs86.mjs} +3 -3
  28. package/dist/stream-broker/index.js +3 -3
  29. package/dist/stream-broker/index.mjs +3 -3
  30. package/dist/stream-broker/remoteEntry.js +1 -1
  31. package/dist/{worker-protocol-SzmaLNnP.mjs → worker-protocol-BEbD5adq.mjs} +1 -1
  32. package/dist/{worker-protocol-DGql9R4g.js → worker-protocol-C4rh5uiS.js} +1 -1
  33. package/package.json +1 -1
  34. package/python/__pycache__/inference_pool.cpython-312.pyc +0 -0
  35. package/python/__pycache__/inference_pool.cpython-313.pyc +0 -0
  36. package/python/__pycache__/inference_pool.cpython-314.pyc +0 -0
  37. package/python/__pycache__/test_inference_pool_backpressure.cpython-312-pytest-9.1.1.pyc +0 -0
  38. package/python/__pycache__/test_inference_pool_backpressure.cpython-312.pyc +0 -0
  39. package/python/__pycache__/test_inference_pool_backpressure.cpython-314.pyc +0 -0
  40. package/python/__pycache__/test_inference_pool_coreml_cache.cpython-312-pytest-9.1.1.pyc +0 -0
  41. package/python/__pycache__/test_inference_pool_coreml_cache.cpython-312.pyc +0 -0
  42. package/python/__pycache__/test_inference_pool_coreml_cache.cpython-314.pyc +0 -0
  43. package/python/__pycache__/test_inference_pool_deadline.cpython-314.pyc +0 -0
  44. package/python/__pycache__/test_inference_pool_device_selection.cpython-312-pytest-9.1.1.pyc +0 -0
  45. package/python/__pycache__/test_inference_pool_device_selection.cpython-312.pyc +0 -0
  46. package/python/__pycache__/test_inference_pool_device_selection.cpython-314.pyc +0 -0
  47. package/python/__pycache__/test_inference_pool_layout.cpython-312-pytest-9.1.1.pyc +0 -0
  48. package/python/__pycache__/test_inference_pool_layout.cpython-314.pyc +0 -0
  49. package/python/__pycache__/test_inference_pool_memstats.cpython-312-pytest-9.1.1.pyc +0 -0
  50. package/python/__pycache__/test_inference_pool_memstats.cpython-312.pyc +0 -0
  51. package/python/__pycache__/test_inference_pool_memstats.cpython-314.pyc +0 -0
  52. package/python/__pycache__/test_inference_pool_ov_ppp.cpython-312-pytest-9.1.1.pyc +0 -0
  53. package/python/__pycache__/test_inference_pool_ov_ppp.cpython-312.pyc +0 -0
  54. package/python/__pycache__/test_inference_pool_ov_ppp.cpython-314.pyc +0 -0
  55. package/python/__pycache__/test_inference_pool_preprocess.cpython-312-pytest-9.1.1.pyc +0 -0
  56. package/python/__pycache__/test_inference_pool_preprocess.cpython-314.pyc +0 -0
  57. package/python/__pycache__/test_inference_pool_reconfigure.cpython-314.pyc +0 -0
  58. package/python/__pycache__/test_inference_pool_static_batch.cpython-312-pytest-9.1.1.pyc +0 -0
  59. package/python/__pycache__/test_inference_pool_static_batch.cpython-312.pyc +0 -0
  60. package/python/__pycache__/test_inference_pool_static_batch.cpython-314.pyc +0 -0
  61. package/python/__pycache__/yamnet_audio.cpython-314.pyc +0 -0
  62. package/python/postprocessors/__pycache__/__init__.cpython-312.pyc +0 -0
  63. package/python/postprocessors/__pycache__/__init__.cpython-313.pyc +0 -0
  64. package/python/postprocessors/__pycache__/__init__.cpython-314.pyc +0 -0
  65. package/python/postprocessors/__pycache__/_safety.cpython-313.pyc +0 -0
  66. package/python/postprocessors/__pycache__/arcface.cpython-312.pyc +0 -0
  67. package/python/postprocessors/__pycache__/arcface.cpython-313.pyc +0 -0
  68. package/python/postprocessors/__pycache__/arcface.cpython-314.pyc +0 -0
  69. package/python/postprocessors/__pycache__/clip.cpython-312.pyc +0 -0
  70. package/python/postprocessors/__pycache__/clip.cpython-313.pyc +0 -0
  71. package/python/postprocessors/__pycache__/clip.cpython-314.pyc +0 -0
  72. package/python/postprocessors/__pycache__/ctc.cpython-312.pyc +0 -0
  73. package/python/postprocessors/__pycache__/ctc.cpython-313.pyc +0 -0
  74. package/python/postprocessors/__pycache__/ctc.cpython-314.pyc +0 -0
  75. package/python/postprocessors/__pycache__/plate_slots.cpython-312.pyc +0 -0
  76. package/python/postprocessors/__pycache__/plate_slots.cpython-314.pyc +0 -0
  77. package/python/postprocessors/__pycache__/rfdetr.cpython-312.pyc +0 -0
  78. package/python/postprocessors/__pycache__/rfdetr.cpython-314.pyc +0 -0
  79. package/python/postprocessors/__pycache__/saliency.cpython-312.pyc +0 -0
  80. package/python/postprocessors/__pycache__/saliency.cpython-313.pyc +0 -0
  81. package/python/postprocessors/__pycache__/saliency.cpython-314.pyc +0 -0
  82. package/python/postprocessors/__pycache__/scrfd.cpython-312.pyc +0 -0
  83. package/python/postprocessors/__pycache__/scrfd.cpython-313.pyc +0 -0
  84. package/python/postprocessors/__pycache__/scrfd.cpython-314.pyc +0 -0
  85. package/python/postprocessors/__pycache__/softmax.cpython-312.pyc +0 -0
  86. package/python/postprocessors/__pycache__/softmax.cpython-313.pyc +0 -0
  87. package/python/postprocessors/__pycache__/softmax.cpython-314.pyc +0 -0
  88. package/python/postprocessors/__pycache__/ssd.cpython-312.pyc +0 -0
  89. package/python/postprocessors/__pycache__/ssd.cpython-313.pyc +0 -0
  90. package/python/postprocessors/__pycache__/ssd.cpython-314.pyc +0 -0
  91. package/python/postprocessors/__pycache__/test_clip.cpython-312-pytest-9.1.1.pyc +0 -0
  92. package/python/postprocessors/__pycache__/test_clip.cpython-313-pytest-9.1.1.pyc +0 -0
  93. package/python/postprocessors/__pycache__/test_ctc.cpython-312-pytest-9.1.1.pyc +0 -0
  94. package/python/postprocessors/__pycache__/test_ctc.cpython-312.pyc +0 -0
  95. package/python/postprocessors/__pycache__/test_ctc.cpython-313-pytest-9.1.1.pyc +0 -0
  96. package/python/postprocessors/__pycache__/test_ctc.cpython-313.pyc +0 -0
  97. package/python/postprocessors/__pycache__/test_ctc.cpython-314.pyc +0 -0
  98. package/python/postprocessors/__pycache__/test_plate_slots.cpython-312-pytest-9.1.1.pyc +0 -0
  99. package/python/postprocessors/__pycache__/test_rfdetr.cpython-312-pytest-9.1.1.pyc +0 -0
  100. package/python/postprocessors/__pycache__/test_rfdetr.cpython-314.pyc +0 -0
  101. package/python/postprocessors/__pycache__/test_saliency.cpython-312-pytest-9.1.1.pyc +0 -0
  102. package/python/postprocessors/__pycache__/test_saliency.cpython-313-pytest-9.1.1.pyc +0 -0
  103. package/python/postprocessors/__pycache__/test_saliency.cpython-314.pyc +0 -0
  104. package/python/postprocessors/__pycache__/test_softmax.cpython-312-pytest-9.1.1.pyc +0 -0
  105. package/python/postprocessors/__pycache__/test_softmax.cpython-314.pyc +0 -0
  106. package/python/postprocessors/__pycache__/test_yolo_nms.cpython-312-pytest-9.1.1.pyc +0 -0
  107. package/python/postprocessors/__pycache__/test_yolo_nms.cpython-314.pyc +0 -0
  108. package/python/postprocessors/__pycache__/test_yolo_nms.cpython-39.pyc +0 -0
  109. package/python/postprocessors/__pycache__/test_yolonas.cpython-312-pytest-9.1.1.pyc +0 -0
  110. package/python/postprocessors/__pycache__/yamnet.cpython-312.pyc +0 -0
  111. package/python/postprocessors/__pycache__/yamnet.cpython-313.pyc +0 -0
  112. package/python/postprocessors/__pycache__/yamnet.cpython-314.pyc +0 -0
  113. package/python/postprocessors/__pycache__/yolo.cpython-312.pyc +0 -0
  114. package/python/postprocessors/__pycache__/yolo.cpython-313.pyc +0 -0
  115. package/python/postprocessors/__pycache__/yolo.cpython-314.pyc +0 -0
  116. package/python/postprocessors/__pycache__/yolo.cpython-39.pyc +0 -0
  117. package/python/postprocessors/__pycache__/yolo_seg.cpython-312.pyc +0 -0
  118. package/python/postprocessors/__pycache__/yolo_seg.cpython-313.pyc +0 -0
  119. package/python/postprocessors/__pycache__/yolo_seg.cpython-314.pyc +0 -0
  120. package/python/postprocessors/__pycache__/yolonas.cpython-312.pyc +0 -0
  121. package/python/postprocessors/__pycache__/yolonas.cpython-314.pyc +0 -0
@@ -1,5 +1,5 @@
1
- import { At as storageEvictableCapability, Ct as recordingSignalCapability, D as RecordingSignalStatusSchema, E as RecordingConfigSchema, Et as resolveLocationMode, Gt as DeviceFeature, H as deriveBatteryPresence, It as errMsg, Jt as hydrateSchema, Kt as DeviceType, Nt as stripRetiredBandPreBufferSec, Ot as resolveRecordingProfiles, P as batteryCapability, Q as evictionPolicyOfLocation, Qt as nodePin, R as customAction, St as recordingExportCapability, T as RECORDING_EXPORT_MAX_READ_BYTES, Ut as BaseAddon, V as defineCustomActions, W as deriveRecordingMode, Y as evaluateSensorEdge, Z as evictionPolicyForMode, an as boolean, ct as mayReadLocation, d as DEFAULT_EVENTS_BAND_BUFFER_SEC, dn as preprocess, dt as modeMayWrite, et as gbToBytes, fn as record, g as ExportRecordSchema, hn as EventCategory, i as BatteryStatusSchema, in as array, it as loadContributionCapability, jt as storageOccupancyCapability, ln as number, lt as mayWriteToLocation, nn as sleep$1, pn as string, rn as _enum, rt as isFirstLevelMacroClass, tn as selectAssignedProfileSlots, un as object, ut as migrateLegacyDeviceSignalConfig, x as OpsLogEntrySchema, xt as recordingCapability } from "../dist-DgeXZfwn.mjs";
2
- import { a as physicalRootOf, i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-C9GcBrwk.mjs";
1
+ import { At as storageEvictableCapability, Ct as recordingSignalCapability, D as RecordingSignalStatusSchema, E as RecordingConfigSchema, Et as resolveLocationMode, Gt as DeviceFeature, H as deriveBatteryPresence, It as errMsg, Jt as hydrateSchema, Kt as DeviceType, Nt as stripRetiredBandPreBufferSec, Ot as resolveRecordingProfiles, P as batteryCapability, Q as evictionPolicyOfLocation, Qt as nodePin, R as customAction, St as recordingExportCapability, T as RECORDING_EXPORT_MAX_READ_BYTES, Ut as BaseAddon, V as defineCustomActions, W as deriveRecordingMode, Y as evaluateSensorEdge, Z as evictionPolicyForMode, an as boolean, ct as mayReadLocation, d as DEFAULT_EVENTS_BAND_BUFFER_SEC, dn as preprocess, dt as modeMayWrite, et as gbToBytes, fn as record, g as ExportRecordSchema, hn as EventCategory, i as BatteryStatusSchema, in as array, it as loadContributionCapability, jt as storageOccupancyCapability, ln as number, lt as mayWriteToLocation, nn as sleep$1, pn as string, rn as _enum, rt as isFirstLevelMacroClass, tn as selectAssignedProfileSlots, un as object, ut as migrateLegacyDeviceSignalConfig, x as OpsLogEntrySchema, xt as recordingCapability } from "../dist-Dl6GntEh.mjs";
2
+ import { a as physicalRootOf, i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-CEyw52D2.mjs";
3
3
  import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
4
4
  import { c as PREBUFFER_MAX_MS, r as RECORDING_PRE_ROLL_REQUEST_MS, s as withRecordingIntent } from "../restream-intent-DWe2kInY.mjs";
5
5
  import { n as RowMapStore, t as retireRootKeys } from "../retire-root-keys-DZvlso2l.mjs";
@@ -3812,6 +3812,40 @@ async function segmentsOfHour(root, deviceId, profile, hourStartMs) {
3812
3812
  * the directory route serve the profile the client asked for when it exists,
3813
3813
  * and fall back to the availability pick when it does not.
3814
3814
  */
3815
+ /**
3816
+ * EVERY profile this camera holds footage in, across every root.
3817
+ *
3818
+ * {@link availabilityProfile} deliberately returns ONE — the timeline is a
3819
+ * single bar. That is right for the bar and wrong for the ANSWER: on
3820
+ * 2026-09-10 `getAvailability` reported twenty `high` ranges for camera 615
3821
+ * and the conclusion drawn was that this deployment records no `low` at all,
3822
+ * while `/media-fast/recordingsLow/615/low/` held 14 GB on a different
3823
+ * location (D433).
3824
+ *
3825
+ * Unions across roots for exactly that reason: `high` and `low` do not share a
3826
+ * location here, so a per-root answer sees one of them.
3827
+ *
3828
+ * Non-emptiness, not existence — the same rule {@link availabilityProfile}
3829
+ * keeps, so a directory left behind by a config change is not offered. And
3830
+ * only {@link KNOWN_PROFILES}: the camera dir also hosts `events/` and the
3831
+ * retired `strips/` trees, which a walker that trusts readdir would present as
3832
+ * playable.
3833
+ *
3834
+ * `list` is injectable for the test; production passes the module's own
3835
+ * directory read.
3836
+ */
3837
+ async function profilesWithFootage(roots, deviceId, list = listDir) {
3838
+ const found = /* @__PURE__ */ new Set();
3839
+ for (const root of roots) {
3840
+ const entries = await list(path.join(root, String(deviceId)));
3841
+ for (const entry of entries) {
3842
+ if (!KNOWN_PROFILES$1.has(entry)) continue;
3843
+ if (found.has(entry)) continue;
3844
+ if ((await list(path.join(root, String(deviceId), entry))).length > 0) found.add(entry);
3845
+ }
3846
+ }
3847
+ return [...found].sort();
3848
+ }
3815
3849
  async function profileHasFootage(root, deviceId, profile) {
3816
3850
  return (await listDir(path.join(root, String(deviceId), profile))).length > 0;
3817
3851
  }
@@ -3933,6 +3967,8 @@ var CalendarIndex = class {
3933
3967
  segsReadAt = /* @__PURE__ */ new Map();
3934
3968
  /** The profile availability reads from, resolved once per device. */
3935
3969
  profileFor = /* @__PURE__ */ new Map();
3970
+ profilesFor = /* @__PURE__ */ new Map();
3971
+ profilesInFlight = /* @__PURE__ */ new Map();
3936
3972
  /** `deviceId:profile` → whether the device records that profile, resolved
3937
3973
  * once. Same stability trade as {@link profileFor}: a config change that
3938
3974
  * adds a profile mid-session is picked up on restart, not on a timer. */
@@ -4215,6 +4251,31 @@ var CalendarIndex = class {
4215
4251
  * reads at a time and they ALL ask for the profile before the first answer
4216
4252
  * lands, so a cache alone let the pick run eight times. Parallelism found it.
4217
4253
  */
4254
+ /**
4255
+ * Every profile this camera holds footage in, across every root — cached
4256
+ * like the pick, because it is the same shallow read (D433).
4257
+ *
4258
+ * {@link availabilityProfileFor} answers with ONE; this says what the one
4259
+ * was chosen FROM, so a caller cannot mistake the timeline's single bar for
4260
+ * the whole archive.
4261
+ */
4262
+ async profilesWithFootageFor(deviceId) {
4263
+ const cached = this.profilesFor.get(deviceId);
4264
+ if (cached !== void 0) return cached;
4265
+ const running = this.profilesInFlight.get(deviceId);
4266
+ if (running) return running;
4267
+ const resolve = (async () => {
4268
+ const found = await profilesWithFootage(this.deps.roots(), deviceId);
4269
+ this.profilesFor.set(deviceId, found);
4270
+ return found;
4271
+ })();
4272
+ this.profilesInFlight.set(deviceId, resolve);
4273
+ try {
4274
+ return await resolve;
4275
+ } finally {
4276
+ if (this.profilesInFlight.get(deviceId) === resolve) this.profilesInFlight.delete(deviceId);
4277
+ }
4278
+ }
4218
4279
  async availabilityProfileFor(deviceId) {
4219
4280
  const cached = this.profileFor.get(deviceId);
4220
4281
  if (cached !== void 0) return cached;
@@ -5858,6 +5919,8 @@ var TIME_RE = /time=(\d+):(\d+):(\d+(?:\.\d+)?)/;
5858
5919
  * whatever ffmpeg build is installed.
5859
5920
  */
5860
5921
  var EXPORT_MIN_PLAUSIBLE_BYTES = 1024;
5922
+ /** ffmpeg's own announcement of that pass — the only signal it gives. */
5923
+ var FASTSTART_RE = /Starting second pass: moving the moov atom/i;
5861
5924
  /** Expected OUTPUT duration (seconds) for progress scaling. */
5862
5925
  function expectedOutSeconds(rec) {
5863
5926
  const rangeSec = Math.max(.001, (rec.toMs - rec.fromMs) / 1e3);
@@ -6167,6 +6230,7 @@ var ExportEngine = class {
6167
6230
  args
6168
6231
  } });
6169
6232
  const stallMs = this.deps.stallMs ?? 9e4;
6233
+ const faststartStallMs = this.deps.faststartStallMs ?? 9e5;
6170
6234
  return new Promise((resolve) => {
6171
6235
  const proc = this.deps.spawn(this.deps.ffmpegPath ?? "ffmpeg", args);
6172
6236
  this.active.set(id, proc);
@@ -6178,14 +6242,16 @@ var ExportEngine = class {
6178
6242
  stallTimer = null;
6179
6243
  }
6180
6244
  };
6245
+ let budgetMs = stallMs;
6181
6246
  const armStall = () => {
6182
6247
  clearStall();
6248
+ const armedFor = budgetMs;
6183
6249
  stallTimer = setTimeout(() => {
6184
- stderrTail.push(`ffmpeg stalled: no progress for ${stallMs}ms`);
6250
+ stderrTail.push(`ffmpeg stalled: no progress for ${armedFor}ms`);
6185
6251
  try {
6186
6252
  proc.kill("SIGKILL");
6187
6253
  } catch {}
6188
- }, stallMs);
6254
+ }, armedFor);
6189
6255
  };
6190
6256
  armStall();
6191
6257
  proc.stderr?.on("data", (chunk) => {
@@ -6196,6 +6262,10 @@ var ExportEngine = class {
6196
6262
  stderrTail.push(trimmed);
6197
6263
  if (stderrTail.length > STDERR_TAIL_LINES$1) stderrTail.shift();
6198
6264
  }
6265
+ if (FASTSTART_RE.test(line)) {
6266
+ budgetMs = faststartStallMs;
6267
+ armStall();
6268
+ }
6199
6269
  const m = TIME_RE.exec(line);
6200
6270
  if (m) {
6201
6271
  armStall();
@@ -7373,13 +7443,15 @@ function buildRecordingProvider(deps) {
7373
7443
  * and by the batch alike — the batch collapses the TRANSPORT, and sharing the
7374
7444
  * function is what makes that literally true instead of aspirational.
7375
7445
  */
7376
- const availabilityFor = async (deviceId, fromMs, toMs) => {
7446
+ const availabilityFor = async (deviceId, fromMs, toMs, requestedProfile) => {
7377
7447
  const calendar = deps.calendar;
7378
7448
  if (calendar) {
7379
- const profile = await calendar.availabilityProfileFor(deviceId);
7449
+ const profilesWithFootage = await calendar.profilesWithFootageFor(deviceId);
7450
+ const profile = await calendar.servedProfileFor(deviceId, requestedProfile);
7380
7451
  if (profile === null) return {
7381
7452
  deviceId,
7382
- ranges: []
7453
+ ranges: [],
7454
+ profilesWithFootage: [...profilesWithFootage]
7383
7455
  };
7384
7456
  const ranges = [];
7385
7457
  for (const r of await calendar.rangesIn(deviceId, profile, fromMs, toMs)) ranges.push({
@@ -7389,16 +7461,20 @@ function buildRecordingProvider(deps) {
7389
7461
  });
7390
7462
  return {
7391
7463
  deviceId,
7392
- ranges
7464
+ ranges,
7465
+ profilesWithFootage: [...profilesWithFootage]
7393
7466
  };
7394
7467
  }
7468
+ const profiles = new Set(deps.index.segments(deviceId).map((s) => s.profile));
7469
+ const asked = requestedProfile !== void 0 && profiles.has(requestedProfile);
7395
7470
  return {
7396
7471
  deviceId,
7397
- ranges: [...new Set(deps.index.segments(deviceId).map((s) => s.profile))].flatMap((profile) => deps.index.ranges(deviceId, profile, fromMs, toMs, RANGE_MERGE_GAP_MS).map((r) => ({
7472
+ ranges: [...profiles].filter((p) => !asked || p === requestedProfile).flatMap((profile) => deps.index.ranges(deviceId, profile, fromMs, toMs, RANGE_MERGE_GAP_MS).map((r) => ({
7398
7473
  profile,
7399
7474
  startMs: r.startMs,
7400
7475
  endMs: r.endMs
7401
- })))
7476
+ }))),
7477
+ profilesWithFootage: [...profiles].sort()
7402
7478
  };
7403
7479
  };
7404
7480
  /** The per-camera day read. Same rule as {@link availabilityFor}: one body. */
@@ -7428,7 +7504,7 @@ function buildRecordingProvider(deps) {
7428
7504
  getStatus: async ({ deviceId }) => {
7429
7505
  return statusFor(deps, deviceId, await loadDeviceConfig(deps.configStore, deviceId));
7430
7506
  },
7431
- getAvailability: ({ deviceId, fromMs, toMs }) => availabilityFor(deviceId, fromMs, toMs),
7507
+ getAvailability: ({ deviceId, fromMs, toMs, profile }) => availabilityFor(deviceId, fromMs, toMs, profile),
7432
7508
  /**
7433
7509
  * `getAvailability` for a SET of cameras. Same body per camera, run
7434
7510
  * concurrently; only the transport collapses.
@@ -7442,11 +7518,12 @@ function buildRecordingProvider(deps) {
7442
7518
  refuseOverCap("getAvailabilityBatch", deviceIds.length);
7443
7519
  return Promise.all(deviceIds.map(async (deviceId) => {
7444
7520
  try {
7445
- const { ranges } = await availabilityFor(deviceId, fromMs, toMs);
7521
+ const { ranges, profilesWithFootage } = await availabilityFor(deviceId, fromMs, toMs);
7446
7522
  return {
7447
7523
  deviceId,
7448
7524
  read: "read",
7449
- ranges
7525
+ ranges,
7526
+ profilesWithFootage
7450
7527
  };
7451
7528
  } catch (err) {
7452
7529
  deps.logger.warn("recording availability could not be read", {
@@ -7460,7 +7537,8 @@ function buildRecordingProvider(deps) {
7460
7537
  return {
7461
7538
  deviceId,
7462
7539
  read: "unreadable",
7463
- ranges: []
7540
+ ranges: [],
7541
+ profilesWithFootage: []
7464
7542
  };
7465
7543
  }
7466
7544
  }));
@@ -1,5 +1,5 @@
1
1
  import { r as __toESM, t as __commonJSMin } from "./chunk-DnnnRqeS.mjs";
2
- import { It as errMsg } from "./dist-DgeXZfwn.mjs";
2
+ import { It as errMsg } from "./dist-Dl6GntEh.mjs";
3
3
  import { spawn } from "node:child_process";
4
4
  //#region ../../node_modules/mp4box/dist/mp4box.all.js
5
5
  var require_mp4box_all = /* @__PURE__ */ __commonJSMin(((exports) => {
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-D7hxiBnC.js");
1
+ const require_dist = require("./dist-BbvtiBNc.js");
2
2
  let node_child_process = require("node:child_process");
3
3
  //#region ../../node_modules/mp4box/dist/mp4box.all.js
4
4
  var require_mp4box_all = /* @__PURE__ */ require_dist.__commonJSMin(((exports) => {
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_worker_protocol = require("../worker-protocol-DGql9R4g.js");
3
- const require_lazy_sharp = require("../lazy-sharp-BSkbiuz5.js");
2
+ const require_worker_protocol = require("../worker-protocol-C4rh5uiS.js");
3
+ const require_lazy_sharp = require("../lazy-sharp-L9Lcr62v.js");
4
4
  //#region src/session-decode/color-conversion.ts
5
5
  /**
6
6
  * Explicit YUV→RGB colorspace/range resolution for the session-decode worker.
@@ -1,4 +1,4 @@
1
- import { i as formatNativeLeaseKnobs, n as isWorkerRequest, o as resolveNativeLeaseKnobs, r as logLevelForLine } from "../worker-protocol-SzmaLNnP.mjs";
1
+ import { i as formatNativeLeaseKnobs, n as isWorkerRequest, o as resolveNativeLeaseKnobs, r as logLevelForLine } from "../worker-protocol-BEbD5adq.mjs";
2
2
  import { n as setSharpWarnSink, r as hostExternalEntryUrls, t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
3
3
  //#region src/session-decode/color-conversion.ts
4
4
  /**
@@ -3,7 +3,7 @@ import "./dist-CYZr2fwk.mjs";
3
3
  var e = {
4
4
  "@camstack/sdk": {
5
5
  name: "@camstack/sdk",
6
- version: "1.2.95",
6
+ version: "1.2.96",
7
7
  scope: ["default"],
8
8
  loaded: !1,
9
9
  from: "addon_stream_broker_widgets",
@@ -18,7 +18,7 @@ var e = {
18
18
  },
19
19
  "@camstack/types": {
20
20
  name: "@camstack/types",
21
- version: "1.2.175",
21
+ version: "1.2.176",
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.143",
36
+ version: "1.2.144",
37
37
  scope: ["default"],
38
38
  loaded: !1,
39
39
  from: "addon_stream_broker_widgets",
@@ -1,4 +1,4 @@
1
- const require_segment_demux_js = require("../segment-demux-js-sLs8mbZQ.js");
1
+ const require_segment_demux_js = require("../segment-demux-js-D7bjzY8M.js");
2
2
  let node_worker_threads = require("node:worker_threads");
3
3
  //#region src/stream-broker/recorded/demux-worker-child.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as demuxSegmentFullJs } from "../segment-demux-js-BGbKlotF.mjs";
1
+ import { t as demuxSegmentFullJs } from "../segment-demux-js-B278aBtB.mjs";
2
2
  import { parentPort } from "node:worker_threads";
3
3
  //#region src/stream-broker/recorded/demux-worker-child.ts
4
4
  /**
@@ -36,7 +36,7 @@ async function r() {
36
36
  }
37
37
  },
38
38
  "@camstack/types": {
39
- version: "1.2.175",
39
+ version: "1.2.176",
40
40
  scope: "default",
41
41
  shareConfig: {
42
42
  singleton: !0,
@@ -45,7 +45,7 @@ async function r() {
45
45
  }
46
46
  },
47
47
  "@camstack/sdk": {
48
- version: "1.2.95",
48
+ version: "1.2.96",
49
49
  scope: "default",
50
50
  shareConfig: {
51
51
  singleton: !0,
@@ -81,7 +81,7 @@ async function r() {
81
81
  }
82
82
  },
83
83
  "@camstack/ui-library": {
84
- version: "1.2.143",
84
+ version: "1.2.144",
85
85
  scope: "default",
86
86
  shareConfig: {
87
87
  singleton: !0,
@@ -2,12 +2,12 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-D7hxiBnC.js");
6
- const require_node = require("../node-DDhmPcOx.js");
5
+ const require_dist = require("../dist-BbvtiBNc.js");
6
+ const require_node = require("../node-CbCVHEvJ.js");
7
7
  const require_restream_intent = require("../restream-intent-B1Difcnq.js");
8
8
  const require_remote_restream = require("../remote-restream-CO36Sr30.js");
9
9
  const require_retire_root_keys = require("../retire-root-keys-Csb8z2f3.js");
10
- const require_segment_demux_js = require("../segment-demux-js-sLs8mbZQ.js");
10
+ const require_segment_demux_js = require("../segment-demux-js-D7bjzY8M.js");
11
11
  let node_os = require("node:os");
12
12
  node_os = require_dist.__toESM(node_os);
13
13
  let node_crypto = require("node:crypto");
@@ -1,10 +1,10 @@
1
1
  import { r as __toESM } from "../chunk-DnnnRqeS.mjs";
2
- import { A as addonWidgetsSourceCapability, Bt as invocationFromEncodeProfile, C as RATE_CONTROL_RELAXED, F as cameraStreamsCapability, Ft as webrtcSessionCapability, Gt as DeviceFeature, H as deriveBatteryPresence, Ht as BOOT_RECOVERY_BACKOFF_MS, I as createHwAccelCache, It as errMsg, K as egressTranscodeSharingKey, Kt as DeviceType, L as createLogChannelsProvider, Lt as AUDIO_PRESETS, Mt as streamBrokerCapability, O as RingBuffer, P as batteryCapability, Qt as nodePin, Tt as resolveEgressDecodeHwAccel, Ut as BaseAddon, Vt as isSoftwareDecode, Wt as CAM_PROFILE_ORDER, Xt as makeProfileBrokerId, Yt as isEvent, Zt as makeSourceBrokerId, an as boolean, at as logChannelsCapability, cn as literal, en as parseProfileBrokerId, fn as record, h as EncodeProfileSchema, hn as EventCategory, i as BatteryStatusSchema, in as array, it as loadContributionCapability, ln as number, mn as union, on as discriminatedUnion, pn as string, q as egressTransportFromRequest, qt as createEvent, rn as _enum, st as maskUrlCredentials, un as object, w as RATE_CONTROL_TIGHT, z as declareLogChannel, zt as buildFfmpegArgs$1 } from "../dist-DgeXZfwn.mjs";
3
- import { i as NO_COST_CLAIM, n as Fmp4FragmentChild, r as Fmp4FragmentPlane, t as ChildCostRegistry } from "../node-C9GcBrwk.mjs";
2
+ import { A as addonWidgetsSourceCapability, Bt as invocationFromEncodeProfile, C as RATE_CONTROL_RELAXED, F as cameraStreamsCapability, Ft as webrtcSessionCapability, Gt as DeviceFeature, H as deriveBatteryPresence, Ht as BOOT_RECOVERY_BACKOFF_MS, I as createHwAccelCache, It as errMsg, K as egressTranscodeSharingKey, Kt as DeviceType, L as createLogChannelsProvider, Lt as AUDIO_PRESETS, Mt as streamBrokerCapability, O as RingBuffer, P as batteryCapability, Qt as nodePin, Tt as resolveEgressDecodeHwAccel, Ut as BaseAddon, Vt as isSoftwareDecode, Wt as CAM_PROFILE_ORDER, Xt as makeProfileBrokerId, Yt as isEvent, Zt as makeSourceBrokerId, an as boolean, at as logChannelsCapability, cn as literal, en as parseProfileBrokerId, fn as record, h as EncodeProfileSchema, hn as EventCategory, i as BatteryStatusSchema, in as array, it as loadContributionCapability, ln as number, mn as union, on as discriminatedUnion, pn as string, q as egressTransportFromRequest, qt as createEvent, rn as _enum, st as maskUrlCredentials, un as object, w as RATE_CONTROL_TIGHT, z as declareLogChannel, zt as buildFfmpegArgs$1 } from "../dist-Dl6GntEh.mjs";
3
+ import { i as NO_COST_CLAIM, n as Fmp4FragmentChild, r as Fmp4FragmentPlane, t as ChildCostRegistry } from "../node-CEyw52D2.mjs";
4
4
  import { c as PREBUFFER_MAX_MS, d as resolvePrebuffer, i as parseRestreamPath, l as capPreRollRequestMs, n as NO_DECLARATION, u as prebufferRetentionMs } from "../restream-intent-DWe2kInY.mjs";
5
5
  import { n as profileForStreamId } from "../remote-restream-BeHi78PZ.mjs";
6
6
  import { n as RowMapStore, t as retireRootKeys } from "../retire-root-keys-DZvlso2l.mjs";
7
- import { i as require_mp4box_all, n as demuxSegmentPreferJs, r as runFfmpegOnce, t as demuxSegmentFullJs } from "../segment-demux-js-BGbKlotF.mjs";
7
+ import { i as require_mp4box_all, n as demuxSegmentPreferJs, r as runFfmpegOnce, t as demuxSegmentFullJs } from "../segment-demux-js-B278aBtB.mjs";
8
8
  import { createRequire } from "node:module";
9
9
  import * as os from "node:os";
10
10
  import { networkInterfaces, tmpdir } from "node:os";
@@ -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-BULotDCb.mjs")).catch((e) => {
33
+ return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BnmbfnAd.mjs")).catch((e) => {
34
34
  throw l = void 0, e;
35
35
  }), l;
36
36
  }
@@ -1,4 +1,4 @@
1
- import { b as NativeLeaseSettingsSchema, p as DEFAULT_NATIVE_LEASE_SETTINGS, y as NativeLeaseAdmissionSchema } from "./dist-DgeXZfwn.mjs";
1
+ import { b as NativeLeaseSettingsSchema, p as DEFAULT_NATIVE_LEASE_SETTINGS, y as NativeLeaseAdmissionSchema } from "./dist-Dl6GntEh.mjs";
2
2
  //#region src/session-decode/native-lease-config.ts
3
3
  /**
4
4
  * Resolution of the native-frame hold / tile knobs for one decode worker.
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-D7hxiBnC.js");
1
+ const require_dist = require("./dist-BbvtiBNc.js");
2
2
  //#region src/session-decode/native-lease-config.ts
3
3
  /**
4
4
  * Resolution of the native-frame hold / tile knobs for one decode worker.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-pipeline",
3
- "version": "1.2.217",
3
+ "version": "1.2.218",
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",