@camstack/addon-pipeline 1.2.125 → 1.2.126

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.
@@ -3151,65 +3151,6 @@ function buildExportArgs(input) {
3151
3151
  ];
3152
3152
  }
3153
3153
  //#endregion
3154
- //#region src/recorder/addon/export-timelapse-chunks.ts
3155
- /** One hour of concatenated footage — not one hour of wall clock. */
3156
- var TIMELAPSE_CHUNK_MS = 36e5;
3157
- /**
3158
- * Split a concat list into hour-sized chunks. A single file longer than the
3159
- * chunk stays whole — it is already one open, and cutting it would need a
3160
- * second demux we do not have.
3161
- */
3162
- function splitTimelapseChunks(entries, chunkMs = TIMELAPSE_CHUNK_MS) {
3163
- if (entries.length === 0) return [];
3164
- const chunks = [];
3165
- let current = [];
3166
- let currentDur = 0;
3167
- let streamStartMs = 0;
3168
- for (const entry of entries) {
3169
- if (current.length > 0 && currentDur + entry.durMs > chunkMs) {
3170
- chunks.push({
3171
- entries: current,
3172
- streamStartMs
3173
- });
3174
- streamStartMs += currentDur;
3175
- current = [];
3176
- currentDur = 0;
3177
- }
3178
- current.push(entry);
3179
- currentDur += entry.durMs;
3180
- }
3181
- if (current.length > 0) chunks.push({
3182
- entries: current,
3183
- streamStartMs
3184
- });
3185
- return chunks;
3186
- }
3187
- /**
3188
- * Move stream-time dense ranges onto a chunk's own `t=0`. Ranges that miss
3189
- * the chunk disappear; a range that straddles the edge is clipped. Empty →
3190
- * `undefined` so the select stays the single-rate form.
3191
- */
3192
- function denseRangesForChunk(dense, chunkStreamStartMs, chunkDurMs) {
3193
- if (dense === void 0 || dense.ranges.length === 0) return void 0;
3194
- const startSec = chunkStreamStartMs / 1e3;
3195
- const endSec = (chunkStreamStartMs + chunkDurMs) / 1e3;
3196
- const ranges = [];
3197
- for (const r of dense.ranges) {
3198
- const from = Math.max(r.fromSec, startSec);
3199
- const to = Math.min(r.toSec, endSec);
3200
- if (to <= from) continue;
3201
- ranges.push({
3202
- fromSec: from - startSec,
3203
- toSec: to - startSec
3204
- });
3205
- }
3206
- if (ranges.length === 0) return void 0;
3207
- return {
3208
- everyMs: dense.everyMs,
3209
- ranges
3210
- };
3211
- }
3212
- //#endregion
3213
3154
  //#region src/recorder/addon/export-store.ts
3214
3155
  /**
3215
3156
  * Recording-export persistence for the recorder addon.
@@ -3371,6 +3312,65 @@ async function listExportsFor(state, deviceId) {
3371
3312
  })).map((entry) => entry.value);
3372
3313
  }
3373
3314
  //#endregion
3315
+ //#region src/recorder/addon/export-timelapse-chunks.ts
3316
+ /** One hour of concatenated footage — not one hour of wall clock. */
3317
+ var TIMELAPSE_CHUNK_MS = 36e5;
3318
+ /**
3319
+ * Split a concat list into hour-sized chunks. A single file longer than the
3320
+ * chunk stays whole — it is already one open, and cutting it would need a
3321
+ * second demux we do not have.
3322
+ */
3323
+ function splitTimelapseChunks(entries, chunkMs = TIMELAPSE_CHUNK_MS) {
3324
+ if (entries.length === 0) return [];
3325
+ const chunks = [];
3326
+ let current = [];
3327
+ let currentDur = 0;
3328
+ let streamStartMs = 0;
3329
+ for (const entry of entries) {
3330
+ if (current.length > 0 && currentDur + entry.durMs > chunkMs) {
3331
+ chunks.push({
3332
+ entries: current,
3333
+ streamStartMs
3334
+ });
3335
+ streamStartMs += currentDur;
3336
+ current = [];
3337
+ currentDur = 0;
3338
+ }
3339
+ current.push(entry);
3340
+ currentDur += entry.durMs;
3341
+ }
3342
+ if (current.length > 0) chunks.push({
3343
+ entries: current,
3344
+ streamStartMs
3345
+ });
3346
+ return chunks;
3347
+ }
3348
+ /**
3349
+ * Move stream-time dense ranges onto a chunk's own `t=0`. Ranges that miss
3350
+ * the chunk disappear; a range that straddles the edge is clipped. Empty →
3351
+ * `undefined` so the select stays the single-rate form.
3352
+ */
3353
+ function denseRangesForChunk(dense, chunkStreamStartMs, chunkDurMs) {
3354
+ if (dense === void 0 || dense.ranges.length === 0) return void 0;
3355
+ const startSec = chunkStreamStartMs / 1e3;
3356
+ const endSec = (chunkStreamStartMs + chunkDurMs) / 1e3;
3357
+ const ranges = [];
3358
+ for (const r of dense.ranges) {
3359
+ const from = Math.max(r.fromSec, startSec);
3360
+ const to = Math.min(r.toSec, endSec);
3361
+ if (to <= from) continue;
3362
+ ranges.push({
3363
+ fromSec: from - startSec,
3364
+ toSec: to - startSec
3365
+ });
3366
+ }
3367
+ if (ranges.length === 0) return void 0;
3368
+ return {
3369
+ everyMs: dense.everyMs,
3370
+ ranges
3371
+ };
3372
+ }
3373
+ //#endregion
3374
3374
  //#region src/recorder/addon/spawn-failure.ts
3375
3375
  /**
3376
3376
  * How the recorder reads a `child_process` `'error'` — ONE owner of the
@@ -3649,12 +3649,11 @@ var ExportEngine = class {
3649
3649
  const survivors = [];
3650
3650
  const sidecars = [];
3651
3651
  try {
3652
- for (let i = 0; i < chunks.length; i++) {
3652
+ for (const [i, chunk] of chunks.entries()) {
3653
3653
  if (this.cancelled.has(id)) {
3654
3654
  await this.fail(id, "cancelled");
3655
3655
  return;
3656
3656
  }
3657
- const chunk = chunks[i];
3658
3657
  const chunkDur = chunk.entries.reduce((s, e) => s + e.durMs, 0);
3659
3658
  const listPath = `${outPath}.chunk${i}.ffconcat`;
3660
3659
  const concatPath = `${outPath}.chunk${i}.concat.ts`;
@@ -3687,8 +3686,8 @@ var ExportEngine = class {
3687
3686
  await this.fail(id, "every timelapse hour failed");
3688
3687
  return;
3689
3688
  }
3690
- if (survivors.length === 1) {
3691
- const only = survivors[0];
3689
+ const only = survivors[0];
3690
+ if (survivors.length === 1 && only !== void 0) {
3692
3691
  const copyArgs = buildExportArgs({
3693
3692
  inputPlaylist: only,
3694
3693
  outPath,
@@ -12044,6 +12043,13 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
12044
12043
  /**
12045
12044
  * Opt-in fleet walk — NOT armed at boot (2026-08-22: starved scrub/play).
12046
12045
  * Kept so an operator path can still request a full reconcile later.
12046
+ *
12047
+ * ⚠ That operator path DOES NOT EXIST YET. This is the only caller of
12048
+ * `runFullArchiveWalk`, so today the whole walk is unreachable — `tsc` was
12049
+ * flagging it as unused and it was one of the errors keeping this package
12050
+ * red. Made public rather than deleted, because deleting it would have taken
12051
+ * the 100-line walk with it; but a comment promising a path nobody built is
12052
+ * exactly the leftover that reads as verification. Wire it or drop it.
12047
12053
  */
12048
12054
  scheduleDeferredFullWalk(deviceIds) {
12049
12055
  if (this.fullWalkTimer !== null || this.fullWalkInFlight) return;
@@ -3150,65 +3150,6 @@ function buildExportArgs(input) {
3150
3150
  ];
3151
3151
  }
3152
3152
  //#endregion
3153
- //#region src/recorder/addon/export-timelapse-chunks.ts
3154
- /** One hour of concatenated footage — not one hour of wall clock. */
3155
- var TIMELAPSE_CHUNK_MS = 36e5;
3156
- /**
3157
- * Split a concat list into hour-sized chunks. A single file longer than the
3158
- * chunk stays whole — it is already one open, and cutting it would need a
3159
- * second demux we do not have.
3160
- */
3161
- function splitTimelapseChunks(entries, chunkMs = TIMELAPSE_CHUNK_MS) {
3162
- if (entries.length === 0) return [];
3163
- const chunks = [];
3164
- let current = [];
3165
- let currentDur = 0;
3166
- let streamStartMs = 0;
3167
- for (const entry of entries) {
3168
- if (current.length > 0 && currentDur + entry.durMs > chunkMs) {
3169
- chunks.push({
3170
- entries: current,
3171
- streamStartMs
3172
- });
3173
- streamStartMs += currentDur;
3174
- current = [];
3175
- currentDur = 0;
3176
- }
3177
- current.push(entry);
3178
- currentDur += entry.durMs;
3179
- }
3180
- if (current.length > 0) chunks.push({
3181
- entries: current,
3182
- streamStartMs
3183
- });
3184
- return chunks;
3185
- }
3186
- /**
3187
- * Move stream-time dense ranges onto a chunk's own `t=0`. Ranges that miss
3188
- * the chunk disappear; a range that straddles the edge is clipped. Empty →
3189
- * `undefined` so the select stays the single-rate form.
3190
- */
3191
- function denseRangesForChunk(dense, chunkStreamStartMs, chunkDurMs) {
3192
- if (dense === void 0 || dense.ranges.length === 0) return void 0;
3193
- const startSec = chunkStreamStartMs / 1e3;
3194
- const endSec = (chunkStreamStartMs + chunkDurMs) / 1e3;
3195
- const ranges = [];
3196
- for (const r of dense.ranges) {
3197
- const from = Math.max(r.fromSec, startSec);
3198
- const to = Math.min(r.toSec, endSec);
3199
- if (to <= from) continue;
3200
- ranges.push({
3201
- fromSec: from - startSec,
3202
- toSec: to - startSec
3203
- });
3204
- }
3205
- if (ranges.length === 0) return void 0;
3206
- return {
3207
- everyMs: dense.everyMs,
3208
- ranges
3209
- };
3210
- }
3211
- //#endregion
3212
3153
  //#region src/recorder/addon/export-store.ts
3213
3154
  /**
3214
3155
  * Recording-export persistence for the recorder addon.
@@ -3370,6 +3311,65 @@ async function listExportsFor(state, deviceId) {
3370
3311
  })).map((entry) => entry.value);
3371
3312
  }
3372
3313
  //#endregion
3314
+ //#region src/recorder/addon/export-timelapse-chunks.ts
3315
+ /** One hour of concatenated footage — not one hour of wall clock. */
3316
+ var TIMELAPSE_CHUNK_MS = 36e5;
3317
+ /**
3318
+ * Split a concat list into hour-sized chunks. A single file longer than the
3319
+ * chunk stays whole — it is already one open, and cutting it would need a
3320
+ * second demux we do not have.
3321
+ */
3322
+ function splitTimelapseChunks(entries, chunkMs = TIMELAPSE_CHUNK_MS) {
3323
+ if (entries.length === 0) return [];
3324
+ const chunks = [];
3325
+ let current = [];
3326
+ let currentDur = 0;
3327
+ let streamStartMs = 0;
3328
+ for (const entry of entries) {
3329
+ if (current.length > 0 && currentDur + entry.durMs > chunkMs) {
3330
+ chunks.push({
3331
+ entries: current,
3332
+ streamStartMs
3333
+ });
3334
+ streamStartMs += currentDur;
3335
+ current = [];
3336
+ currentDur = 0;
3337
+ }
3338
+ current.push(entry);
3339
+ currentDur += entry.durMs;
3340
+ }
3341
+ if (current.length > 0) chunks.push({
3342
+ entries: current,
3343
+ streamStartMs
3344
+ });
3345
+ return chunks;
3346
+ }
3347
+ /**
3348
+ * Move stream-time dense ranges onto a chunk's own `t=0`. Ranges that miss
3349
+ * the chunk disappear; a range that straddles the edge is clipped. Empty →
3350
+ * `undefined` so the select stays the single-rate form.
3351
+ */
3352
+ function denseRangesForChunk(dense, chunkStreamStartMs, chunkDurMs) {
3353
+ if (dense === void 0 || dense.ranges.length === 0) return void 0;
3354
+ const startSec = chunkStreamStartMs / 1e3;
3355
+ const endSec = (chunkStreamStartMs + chunkDurMs) / 1e3;
3356
+ const ranges = [];
3357
+ for (const r of dense.ranges) {
3358
+ const from = Math.max(r.fromSec, startSec);
3359
+ const to = Math.min(r.toSec, endSec);
3360
+ if (to <= from) continue;
3361
+ ranges.push({
3362
+ fromSec: from - startSec,
3363
+ toSec: to - startSec
3364
+ });
3365
+ }
3366
+ if (ranges.length === 0) return void 0;
3367
+ return {
3368
+ everyMs: dense.everyMs,
3369
+ ranges
3370
+ };
3371
+ }
3372
+ //#endregion
3373
3373
  //#region src/recorder/addon/spawn-failure.ts
3374
3374
  /**
3375
3375
  * How the recorder reads a `child_process` `'error'` — ONE owner of the
@@ -3648,12 +3648,11 @@ var ExportEngine = class {
3648
3648
  const survivors = [];
3649
3649
  const sidecars = [];
3650
3650
  try {
3651
- for (let i = 0; i < chunks.length; i++) {
3651
+ for (const [i, chunk] of chunks.entries()) {
3652
3652
  if (this.cancelled.has(id)) {
3653
3653
  await this.fail(id, "cancelled");
3654
3654
  return;
3655
3655
  }
3656
- const chunk = chunks[i];
3657
3656
  const chunkDur = chunk.entries.reduce((s, e) => s + e.durMs, 0);
3658
3657
  const listPath = `${outPath}.chunk${i}.ffconcat`;
3659
3658
  const concatPath = `${outPath}.chunk${i}.concat.ts`;
@@ -3686,8 +3685,8 @@ var ExportEngine = class {
3686
3685
  await this.fail(id, "every timelapse hour failed");
3687
3686
  return;
3688
3687
  }
3689
- if (survivors.length === 1) {
3690
- const only = survivors[0];
3688
+ const only = survivors[0];
3689
+ if (survivors.length === 1 && only !== void 0) {
3691
3690
  const copyArgs = buildExportArgs({
3692
3691
  inputPlaylist: only,
3693
3692
  outPath,
@@ -12043,6 +12042,13 @@ var RecorderV2Addon = class extends BaseAddon {
12043
12042
  /**
12044
12043
  * Opt-in fleet walk — NOT armed at boot (2026-08-22: starved scrub/play).
12045
12044
  * Kept so an operator path can still request a full reconcile later.
12045
+ *
12046
+ * ⚠ That operator path DOES NOT EXIST YET. This is the only caller of
12047
+ * `runFullArchiveWalk`, so today the whole walk is unreachable — `tsc` was
12048
+ * flagging it as unused and it was one of the errors keeping this package
12049
+ * red. Made public rather than deleted, because deleting it would have taken
12050
+ * the 100-line walk with it; but a comment promising a path nobody built is
12051
+ * exactly the leftover that reads as verification. Wire it or drop it.
12046
12052
  */
12047
12053
  scheduleDeferredFullWalk(deviceIds) {
12048
12054
  if (this.fullWalkTimer !== null || this.fullWalkInFlight) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-pipeline",
3
- "version": "1.2.125",
3
+ "version": "1.2.126",
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",