@camstack/addon-pipeline 0.1.18 → 0.1.20

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 (67) hide show
  1. package/dist/audio-analyzer/index.js +12 -4
  2. package/dist/audio-analyzer/index.js.map +1 -1
  3. package/dist/audio-analyzer/index.mjs +12 -4
  4. package/dist/audio-analyzer/index.mjs.map +1 -1
  5. package/dist/audio-codec-nodeav/index.js +1 -1
  6. package/dist/audio-codec-nodeav/index.mjs +1 -1
  7. package/dist/decoder-nodeav/index.js +2 -2
  8. package/dist/decoder-nodeav/index.mjs +2 -2
  9. package/dist/detection-pipeline/index.js +47 -44
  10. package/dist/detection-pipeline/index.js.map +1 -1
  11. package/dist/detection-pipeline/index.mjs +47 -44
  12. package/dist/detection-pipeline/index.mjs.map +1 -1
  13. package/dist/{index-asZs8U_s.mjs → index-5aYef068.mjs} +4020 -820
  14. package/dist/index-5aYef068.mjs.map +1 -0
  15. package/dist/{index-DLHaHm6u.js → index-B36NMAdu.js} +3996 -796
  16. package/dist/index-B36NMAdu.js.map +1 -0
  17. package/dist/{index-D_cl0Qqb.js → index-CMcx_k6Y.js} +48 -48
  18. package/dist/{index-D_cl0Qqb.js.map → index-CMcx_k6Y.js.map} +1 -1
  19. package/dist/{index-UbcdLS7a.mjs → index-CYb7cFrv.mjs} +46 -46
  20. package/dist/{index-UbcdLS7a.mjs.map → index-CYb7cFrv.mjs.map} +1 -1
  21. package/dist/motion-wasm/index.js +1 -1
  22. package/dist/motion-wasm/index.mjs +1 -1
  23. package/dist/pipeline-runner/index.js +205 -90
  24. package/dist/pipeline-runner/index.js.map +1 -1
  25. package/dist/pipeline-runner/index.mjs +206 -91
  26. package/dist/pipeline-runner/index.mjs.map +1 -1
  27. package/dist/recorder/index.js +2209 -0
  28. package/dist/recorder/index.js.map +1 -0
  29. package/dist/recorder/index.mjs +2209 -0
  30. package/dist/recorder/index.mjs.map +1 -0
  31. package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/FfmpegParamsField.d.ts +41 -0
  32. package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/GeometryBuilder.d.ts +54 -0
  33. package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/format-ua.d.ts +13 -0
  34. package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/index.d.ts +2 -0
  35. package/dist/stream-broker/@mf-types.zip +0 -0
  36. package/dist/stream-broker/{__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_sdk__loadShare__.mjs-h5aXOPSA.mjs → __mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_sdk__loadShare__.mjs-lantnv8e.mjs} +1 -1
  37. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-DJ3UNg7O.mjs +30 -0
  38. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-CYXy_bhS.mjs +21 -0
  39. package/dist/stream-broker/{__mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs-DAssX3h0.mjs → __mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs-CaDEYBIU.mjs} +9 -7
  40. package/dist/stream-broker/{__mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-DFoJJhpt.mjs → __mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-D6EROtlA.mjs} +1 -1
  41. package/dist/stream-broker/{__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.mjs-gBEZsQrp.mjs → __mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.mjs-x6pP3Ghk.mjs} +2 -2
  42. package/dist/stream-broker/{__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-x7XMEeuJ.mjs → __mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-CcnN6sbA.mjs} +1 -1
  43. package/dist/stream-broker/_stub.js +963 -333
  44. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-3TxRVJ5L.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CL9DR49k.mjs} +6 -6
  45. package/dist/stream-broker/{client-CZXrddDR.mjs → client-BvTmMOQu.mjs} +2 -2
  46. package/dist/stream-broker/{hostInit-De6APW25.mjs → hostInit-ChmiMPS0.mjs} +12 -12
  47. package/dist/stream-broker/{index-cYW01SNH.mjs → index-BxsFuFmE.mjs} +24 -24
  48. package/dist/stream-broker/{index-KtR7Pp0O.mjs → index-C-248uOU.mjs} +2 -2
  49. package/dist/stream-broker/{index-C0BzaWmB.mjs → index-C05B6jqp.mjs} +1 -1
  50. package/dist/stream-broker/index-DOJoSShD.mjs +67784 -0
  51. package/dist/stream-broker/index-DtOI1aTU.mjs +18504 -0
  52. package/dist/stream-broker/{index-BvV3RVTZ.mjs → index-oMq6ilgR.mjs} +254 -268
  53. package/dist/stream-broker/{index-CZNxa0ad.mjs → index-vIWZQBIL.mjs} +1 -1
  54. package/dist/stream-broker/index.js +4666 -756
  55. package/dist/stream-broker/index.js.map +1 -1
  56. package/dist/stream-broker/index.mjs +4668 -756
  57. package/dist/stream-broker/index.mjs.map +1 -1
  58. package/dist/stream-broker/{jsx-runtime-B_evVsXl.mjs → jsx-runtime-BRT_HL0A.mjs} +1 -1
  59. package/dist/stream-broker/remoteEntry.js +1 -1
  60. package/dist/stream-broker/{schemas-ChN4Ih0h.mjs → schemas-B7L0qZtq.mjs} +530 -515
  61. package/package.json +51 -3
  62. package/dist/index-DLHaHm6u.js.map +0 -1
  63. package/dist/index-asZs8U_s.mjs.map +0 -1
  64. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-d8PmLbO2.mjs +0 -19
  65. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-B4l8Nb2y.mjs +0 -20
  66. package/dist/stream-broker/index-CUXiTSWS.mjs +0 -13883
  67. package/dist/stream-broker/index-Kb4xa8FX.mjs +0 -36403
@@ -1,4 +1,4 @@
1
- import { h as hfModelUrl, C as COCO_TO_MACRO, g as COCO_80_LABELS, A as AUDIO_MACRO_LABELS, e as errMsg, f as createEvent, E as EventCategory, i as evaluateZoneRules, Y as YAMNET_TO_MACRO, j as APPLE_SA_TO_MACRO, k as parseJsonUnknown, B as BaseAddon, m as hydrateSchema, q as pipelineExecutorCapability, r as detectionPipelineCapability } from "../index-asZs8U_s.mjs";
1
+ import { h as hfModelUrl, C as COCO_TO_MACRO, g as COCO_80_LABELS, A as AUDIO_MACRO_LABELS, e as errMsg, f as createEvent, E as EventCategory, i as sleep, j as evaluateZoneRules, Y as YAMNET_TO_MACRO, k as APPLE_SA_TO_MACRO, q as parseJsonUnknown, B as BaseAddon, r as hydrateSchema, t as pipelineExecutorCapability, u as detectionPipelineCapability } from "../index-5aYef068.mjs";
2
2
  import * as fs from "node:fs";
3
3
  import * as path from "node:path";
4
4
  import * as os from "node:os";
@@ -872,12 +872,12 @@ const OBJECT_DETECTION_MODELS = [
872
872
  openvino: { url: hf("objectDetection/yolo26/openvino/camstack-yolo26x.xml"), sizeMB: 213, runtimes: ["python"] }
873
873
  }
874
874
  },
875
- // ── Scrypted ReLU variants (optimized for int8 quantization) ──
876
- // Note: Scrypted CoreML models are compiled with 320x320 fixed input size
875
+ // ── ReLU variants (optimized for int8 quantization) ──
876
+ // Note: these CoreML models are compiled with 320x320 fixed input size
877
877
  {
878
878
  id: "scrypted-yolov9t-relu",
879
- name: "YOLOv9 Tiny ReLU (Scrypted)",
880
- description: "Scrypted YOLOv9t ReLU — optimized for int8 quantization",
879
+ name: "YOLOv9 Tiny ReLU",
880
+ description: "YOLOv9t ReLU — optimized for int8 quantization",
881
881
  inputSize: { width: 320, height: 320 },
882
882
  labels: [],
883
883
  preprocessMode: "letterbox",
@@ -889,8 +889,8 @@ const OBJECT_DETECTION_MODELS = [
889
889
  },
890
890
  {
891
891
  id: "scrypted-yolov9s-relu",
892
- name: "YOLOv9 Small ReLU (Scrypted)",
893
- description: "Scrypted YOLOv9s ReLU — improved efficiency, int8 ready",
892
+ name: "YOLOv9 Small ReLU",
893
+ description: "YOLOv9s ReLU — improved efficiency, int8 ready",
894
894
  inputSize: { width: 320, height: 320 },
895
895
  labels: [],
896
896
  preprocessMode: "letterbox",
@@ -902,9 +902,9 @@ const OBJECT_DETECTION_MODELS = [
902
902
  },
903
903
  {
904
904
  id: "scrypted-yolov9c-relu",
905
- name: "YOLOv9 C ReLU (Scrypted)",
906
- description: "Scrypted YOLOv9c ReLU — high-accuracy, int8 ready",
907
- // Scrypted ReLU variants are all compiled with fixed 320x320 input
905
+ name: "YOLOv9 C ReLU",
906
+ description: "YOLOv9c ReLU — high-accuracy, int8 ready",
907
+ // ReLU variants are all compiled with fixed 320x320 input
908
908
  // (see the section header above). Validated at engine load via
909
909
  // `validateOnnxInputShape` — mismatches warn, never silently miscompute.
910
910
  inputSize: { width: 320, height: 320 },
@@ -918,9 +918,9 @@ const OBJECT_DETECTION_MODELS = [
918
918
  },
919
919
  {
920
920
  id: "scrypted-yolov9m-relu",
921
- name: "YOLOv9 M ReLU (Scrypted)",
922
- description: "Scrypted YOLOv9m ReLU — medium, int8 ready",
923
- // Scrypted ReLU variants are all compiled with fixed 320x320 input
921
+ name: "YOLOv9 M ReLU",
922
+ description: "YOLOv9m ReLU — medium, int8 ready",
923
+ // ReLU variants are all compiled with fixed 320x320 input
924
924
  // (see the section header above). Validated at engine load via
925
925
  // `validateOnnxInputShape` — mismatches warn, never silently miscompute.
926
926
  inputSize: { width: 320, height: 320 },
@@ -949,9 +949,9 @@ const FACE_DETECTION_MODELS = [
949
949
  },
950
950
  {
951
951
  id: "scrypted-yolov9t-face",
952
- name: "YOLOv9t Face ReLU (Scrypted)",
953
- description: "Scrypted YOLOv9t face detection — YOLO-based, fast",
954
- // Scrypted YOLO face variants follow the 320x320 ReLU convention.
952
+ name: "YOLOv9t Face ReLU",
953
+ description: "YOLOv9t face detection — YOLO-based, fast, 320x320 ReLU",
954
+ // ReLU face variants follow the 320x320 fixed input convention.
955
955
  // Validated at engine load via `validateOnnxInputShape`.
956
956
  inputSize: { width: 320, height: 320 },
957
957
  labels: [{ id: "face", name: "Face" }],
@@ -980,8 +980,8 @@ const FACE_EMBEDDING_MODELS = [
980
980
  },
981
981
  {
982
982
  id: "inception-resnet-v1",
983
- name: "Inception ResNet V1 (Scrypted)",
984
- description: "FaceNet-style face recognition embeddings (512-d) — Scrypted model",
983
+ name: "Inception ResNet V1",
984
+ description: "FaceNet-style face recognition embeddings (512-d) — hosted on plugin-models HF repo",
985
985
  inputSize: { width: 160, height: 160 },
986
986
  labels: [{ id: "embedding", name: "Face Embedding" }],
987
987
  preprocessMode: "resize",
@@ -1794,8 +1794,8 @@ class EngineFactory {
1794
1794
  * single IPC round-trip. Returns the structured Python detection
1795
1795
  * dicts in input order. Throws when this factory has no pool path.
1796
1796
  *
1797
- * Used by `runPipelineBatch` for fair benchmarking against
1798
- * Scrypted's `detectObjects(media, {batch})`.
1797
+ * Used by `runPipelineBatch` for fair batched benchmarking — N frames
1798
+ * in one IPC round-trip, amortising the per-call envelope overhead.
1799
1799
  */
1800
1800
  async batchInferRaw(stepId, items, modelId) {
1801
1801
  if (!this.poolManager) {
@@ -3214,7 +3214,8 @@ function parseWavToAudioChunk(filePath) {
3214
3214
  for (let i = 0; i < pcm.length; i++) {
3215
3215
  float32[i] = pcm[i] / 32768;
3216
3216
  }
3217
- return { data: float32, sampleRate: 16e3, channels: 1, timestamp: Date.now() };
3217
+ const data = new Uint8Array(float32.buffer, float32.byteOffset, float32.byteLength);
3218
+ return { data, sampleRate: 16e3, channels: 1, timestamp: Date.now() };
3218
3219
  }
3219
3220
  function enginesEqual(a, b) {
3220
3221
  return a.runtime === b.runtime && a.backend === b.backend && a.format === b.format && (a.device ?? null) === (b.device ?? null);
@@ -4124,7 +4125,7 @@ class DetectionPipelineProvider {
4124
4125
  if (attempt < maxRetries) {
4125
4126
  const delayMs = 2e3 * Math.pow(2, attempt - 1);
4126
4127
  this.log.warn("Model download failed — retrying", { meta: { modelId: entry.id, attempt, maxRetries, error: msg, retryDelayMs: delayMs } });
4127
- await new Promise((resolve) => setTimeout(resolve, delayMs));
4128
+ await sleep(delayMs);
4128
4129
  } else {
4129
4130
  throw new Error(`Failed to download model "${entry.id}" after ${maxRetries} attempts: ${msg}`, { cause: err });
4130
4131
  }
@@ -4199,10 +4200,10 @@ class DetectionPipelineProvider {
4199
4200
  * factory). Returns one minimally-shaped `FrameResult` per input
4200
4201
  * frame in input order.
4201
4202
  *
4202
- * Used by `scripts/bench-scrypted-style.mts` for the
4203
- * Scrypted-equivalent benchmark Scrypted's `detectObjects(media,
4204
- * {batch})` collapses N requests into one call too, so bypassing
4205
- * the per-call IPC overhead is what makes the comparison fair.
4203
+ * Used by `scripts/bench-batch-style.mts` for the batch benchmark —
4204
+ * collapsing N requests into one call amortises the per-call IPC
4205
+ * envelope overhead, which is what makes the batched path measurably
4206
+ * faster than N sequential `runPipeline` calls.
4206
4207
  */
4207
4208
  async runPipelineBatch(input) {
4208
4209
  this.log.debug("runPipelineBatch entry", {
@@ -4895,7 +4896,7 @@ class DetectionPipelineProvider {
4895
4896
  label: l.className,
4896
4897
  score: l.score
4897
4898
  }));
4898
- const sampleCount = chunk.data.length;
4899
+ const sampleCount = chunk.data.byteLength / 4;
4899
4900
  const startMs = 0;
4900
4901
  const endMs = sampleCount / chunk.sampleRate * 1e3;
4901
4902
  const detections = ranked.filter((l) => l.score >= minConfidence).map((l, i) => ({
@@ -5183,7 +5184,15 @@ const TUNING_DEFAULTS = {
5183
5184
  // (~+30-90% on 4-8 simulated cams in `bench-pool-inprocess.mts`).
5184
5185
  // Higher counts saturate the single ANE channel and degrade — 2 is the
5185
5186
  // sweet spot on M-series.
5186
- coreml: { concurrency: 2, batchMode: "window", windowMs: 30, maxBatchSize: 8, numWorkers: 2 },
5187
+ // Latency-first: one model context, one serialized predict, no cross-camera
5188
+ // window batching. On a single shared ANE, concurrent predicts
5189
+ // (concurrency×numWorkers) oversubscribe the accelerator, so per-frame latency
5190
+ // scales with active-camera count; a `window` adds pure queueing delay and
5191
+ // `model.predict([list])` does NOT fuse image-typed inputs (it loops), so the
5192
+ // batch is no faster while every member waits for the slowest. One predict
5193
+ // owns the ANE → each inference runs at its isolated speed. (Prev throughput-
5194
+ // tuned default was concurrency:2, batchMode:'window', windowMs:30, numWorkers:2.)
5195
+ coreml: { concurrency: 1, batchMode: "none", windowMs: 8, maxBatchSize: 8, numWorkers: 1 },
5187
5196
  openvino: { concurrency: 1, batchMode: "none", numStreams: 0 },
5188
5197
  onnx: { concurrency: 4, batchMode: "list", maxBatchSize: 8, intraOpThreads: 0 },
5189
5198
  cpu: { concurrency: 4, batchMode: "list", maxBatchSize: 8, intraOpThreads: 0 }
@@ -5506,23 +5515,17 @@ class DetectionPipelineAddon extends BaseAddon {
5506
5515
  resolveBackendTuning() {
5507
5516
  const backend = this.config.engineBackend ?? DEFAULT_CONFIG.engineBackend;
5508
5517
  const t = TUNING_DEFAULTS[backend] ?? TUNING_DEFAULTS["onnx"];
5509
- const cfg = this.config;
5510
- const pickNum = (userVal, defaultVal) => {
5511
- if (typeof userVal !== "number" || userVal <= 0) return defaultVal;
5512
- return userVal;
5513
- };
5514
- const pickStr = (userVal, defaultVal) => {
5515
- if (typeof userVal !== "string" || userVal === "") return defaultVal;
5516
- return userVal;
5517
- };
5518
+ const tAny = t;
5519
+ const num = (v, dflt) => typeof v === "number" && v > 0 ? v : dflt;
5520
+ const str = (v, dflt) => typeof v === "string" && v !== "" ? v : dflt;
5518
5521
  return {
5519
- concurrency: pickNum(cfg.concurrency, t.concurrency ?? 1),
5520
- batchMode: pickStr(cfg.batchMode, t.batchMode ?? "window"),
5521
- windowMs: pickNum(cfg.windowMs, t.windowMs ?? 2),
5522
- maxBatchSize: pickNum(cfg.maxBatchSize, t.maxBatchSize ?? 8),
5523
- numStreams: pickNum(cfg.numStreams, t.numStreams ?? 0),
5524
- intraOpThreads: pickNum(cfg.intraOpThreads, t.intraOpThreads ?? 0),
5525
- numWorkers: pickNum(cfg.numWorkers, t["numWorkers"] ?? 1)
5522
+ concurrency: num(t.concurrency, 1),
5523
+ batchMode: str(t.batchMode, "window"),
5524
+ windowMs: num(t.windowMs, 2),
5525
+ maxBatchSize: num(t.maxBatchSize, 8),
5526
+ numStreams: num(t.numStreams, 0),
5527
+ intraOpThreads: num(t.intraOpThreads, 0),
5528
+ numWorkers: num(tAny["numWorkers"], 1)
5526
5529
  };
5527
5530
  }
5528
5531
  async onInitialize() {