@camstack/addon-pipeline 1.1.55 → 1.1.57
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.
- package/dist/audio-analyzer/index.js +2 -2
- package/dist/audio-analyzer/index.mjs +2 -2
- package/dist/detection-pipeline/index.js +92 -88
- package/dist/detection-pipeline/index.mjs +91 -87
- package/dist/{dist-DI57FC8K.js → dist-CK8Ur-OS.js} +1045 -43
- package/dist/{dist-RWGGPwVx.mjs → dist-CL531uVA.mjs} +1045 -43
- package/dist/motion-wasm/index.js +9 -41
- package/dist/motion-wasm/index.mjs +9 -41
- package/dist/pipeline-runner/index.js +338 -664
- package/dist/pipeline-runner/index.mjs +327 -655
- package/dist/recorder/index.js +2 -2
- package/dist/recorder/index.mjs +2 -2
- package/dist/remote-restream-BeHi78PZ.mjs +25 -0
- package/dist/remote-restream-CO36Sr30.js +36 -0
- package/dist/session-decode/decode-worker-child.js +5 -3
- package/dist/session-decode/decode-worker-child.mjs +5 -3
- package/dist/{step-definitions-CP9kVSml.mjs → step-definitions-1d3_vQ6S.mjs} +45 -3
- package/dist/{step-definitions-CNBFKjZe.js → step-definitions-DHAxruAQ.js} +45 -3
- package/dist/stream-broker/_stub.js +351 -291
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-mDCPzmT3.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-Cm_B-hQT.mjs} +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Ba7Eyd47.mjs +26 -0
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Dn_pxzP-.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-TWCUWhCm.mjs} +2 -2
- package/dist/stream-broker/{hostInit-GM_CI22k.mjs → hostInit-DEaqJpGA.mjs} +2 -2
- package/dist/stream-broker/index.js +935 -38
- package/dist/stream-broker/index.mjs +932 -35
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-BChW0ntM.js → MaskShapeCanvas-DI4BY7W2-CZUzu3MF.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-DDzqEbSe.js → MotionZonesSettings-NcxxQN8r-CmZbzLQi.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-B879GXaf.js → PrivacyMaskSettings-APgPLF7p-BOKDrH0N.js} +1 -1
- package/embed-dist/assets/index-Bmpl9O1K.css +2 -0
- package/embed-dist/assets/index-DOsK8CZb.js +81 -0
- package/embed-dist/index.html +2 -2
- package/package.json +7 -5
- package/python/inference_pool.py +183 -29
- package/python/postprocessors/__init__.py +2 -0
- package/python/postprocessors/ssd.py +128 -0
- package/python/requirements-edgetpu.txt +23 -0
- package/python/test_inference_pool_layout.py +16 -1
- package/python/test_inference_pool_preprocess.py +65 -0
- package/dist/remote-source-plane-CHgvzzA6.js +0 -1030
- package/dist/remote-source-plane-DU0aRSPv.mjs +0 -1001
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-B3gTdHEh.mjs +0 -26
- package/embed-dist/assets/index-CC06JBcl.css +0 -2
- package/embed-dist/assets/index-CNjQ5rAE.js +0 -81
- package/dist/{model-download-service-C-IHWnXx-BPy6aoAx.mjs → model-download-service-C-IHWnXx-3Mmeob3l.mjs} +1 -1
- package/dist/{model-download-service-C-IHWnXx-BLXzxpRB.js → model-download-service-C-IHWnXx-D326YNnt.js} +1 -1
|
@@ -3,9 +3,9 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-D6vf50IK.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
6
|
+
const require_dist = require("../dist-CK8Ur-OS.js");
|
|
7
7
|
const require_node_topology_platform = require("../node-topology-platform-CFZ7F4xW.js");
|
|
8
|
-
const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-
|
|
8
|
+
const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-D326YNnt.js");
|
|
9
9
|
let node_fs = require("node:fs");
|
|
10
10
|
node_fs = require_chunk.__toESM(node_fs);
|
|
11
11
|
let node_path = require("node:path");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __require } from "../chunk-BdkLduGY.mjs";
|
|
2
|
-
import { C as mapAudioLabelToMacro, I as errMsg, L as BaseAddon, U as hydrateSchema, h as audioAnalyzerCapability, l as HF_BASE_URL, m as audioAnalysisCapability, n as AUDIO_BACKEND_CHOICES, o as DEFAULT_AUDIO_ANALYZER_CONFIG } from "../dist-
|
|
2
|
+
import { C as mapAudioLabelToMacro, I as errMsg, L as BaseAddon, U as hydrateSchema, h as audioAnalyzerCapability, l as HF_BASE_URL, m as audioAnalysisCapability, n as AUDIO_BACKEND_CHOICES, o as DEFAULT_AUDIO_ANALYZER_CONFIG } from "../dist-CL531uVA.mjs";
|
|
3
3
|
import { t as pickNodePlatformArch } from "../node-topology-platform-BkR_k6WT.mjs";
|
|
4
|
-
import { r as downloadFile } from "../model-download-service-C-IHWnXx-
|
|
4
|
+
import { r as downloadFile } from "../model-download-service-C-IHWnXx-3Mmeob3l.mjs";
|
|
5
5
|
import * as fs from "node:fs";
|
|
6
6
|
import * as path$1 from "node:path";
|
|
7
7
|
//#region src/audio-analyzer/audio-pipeline.ts
|
|
@@ -3,20 +3,19 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-D6vf50IK.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
7
|
-
const require_step_definitions = require("../step-definitions-
|
|
6
|
+
const require_dist = require("../dist-CK8Ur-OS.js");
|
|
7
|
+
const require_step_definitions = require("../step-definitions-DHAxruAQ.js");
|
|
8
8
|
const require_node_topology_platform = require("../node-topology-platform-CFZ7F4xW.js");
|
|
9
|
-
const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-
|
|
10
|
-
let _camstack_shm_ring = require("@camstack/shm-ring");
|
|
9
|
+
const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-D326YNnt.js");
|
|
11
10
|
let node_child_process = require("node:child_process");
|
|
11
|
+
let sharp = require("sharp");
|
|
12
|
+
sharp = require_chunk.__toESM(sharp);
|
|
12
13
|
let node_fs = require("node:fs");
|
|
13
14
|
node_fs = require_chunk.__toESM(node_fs);
|
|
14
15
|
let node_path = require("node:path");
|
|
15
16
|
node_path = require_chunk.__toESM(node_path);
|
|
16
17
|
let node_os = require("node:os");
|
|
17
18
|
node_os = require_chunk.__toESM(node_os);
|
|
18
|
-
let sharp = require("sharp");
|
|
19
|
-
sharp = require_chunk.__toESM(sharp);
|
|
20
19
|
//#region src/detection-pipeline/runtimes.ts
|
|
21
20
|
var KNOWN_PLATFORMS = [
|
|
22
21
|
"darwin",
|
|
@@ -52,6 +51,9 @@ function npuInfoFrom(hw) {
|
|
|
52
51
|
if (!type) return null;
|
|
53
52
|
return { type };
|
|
54
53
|
}
|
|
54
|
+
function coralInfoFrom(hw) {
|
|
55
|
+
return hw.coral?.type === "coral-edgetpu" ? { type: "coral-edgetpu" } : null;
|
|
56
|
+
}
|
|
55
57
|
function envToHardwareInfo(env) {
|
|
56
58
|
return {
|
|
57
59
|
platform: toKnownPlatform(env.platform),
|
|
@@ -61,7 +63,8 @@ function envToHardwareInfo(env) {
|
|
|
61
63
|
totalRAM_MB: 0,
|
|
62
64
|
availableRAM_MB: 0,
|
|
63
65
|
gpu: env.hardware ? gpuInfoFrom(env.hardware) : null,
|
|
64
|
-
npu: env.hardware ? npuInfoFrom(env.hardware) : null
|
|
66
|
+
npu: env.hardware ? npuInfoFrom(env.hardware) : null,
|
|
67
|
+
coral: env.hardware ? coralInfoFrom(env.hardware) : null
|
|
65
68
|
};
|
|
66
69
|
}
|
|
67
70
|
function probedToHardwareInfo(hw) {
|
|
@@ -74,7 +77,8 @@ function probedToHardwareInfo(hw) {
|
|
|
74
77
|
totalRAM_MB: 0,
|
|
75
78
|
availableRAM_MB: 0,
|
|
76
79
|
gpu: gpuInfoFrom(hw),
|
|
77
|
-
npu: npuInfoFrom(hw)
|
|
80
|
+
npu: npuInfoFrom(hw),
|
|
81
|
+
coral: coralInfoFrom(hw)
|
|
78
82
|
};
|
|
79
83
|
}
|
|
80
84
|
var RUNTIME_DETAIL = {
|
|
@@ -107,6 +111,15 @@ var RUNTIME_DETAIL = {
|
|
|
107
111
|
maxBatchSize: 8,
|
|
108
112
|
numWorkers: 1
|
|
109
113
|
}
|
|
114
|
+
},
|
|
115
|
+
edgetpu: {
|
|
116
|
+
label: "Coral Edge TPU",
|
|
117
|
+
pythonRequirements: ["requirements.txt", "requirements-edgetpu.txt"],
|
|
118
|
+
tuning: {
|
|
119
|
+
concurrency: 1,
|
|
120
|
+
batchMode: "none",
|
|
121
|
+
numWorkers: 1
|
|
122
|
+
}
|
|
110
123
|
}
|
|
111
124
|
};
|
|
112
125
|
/**
|
|
@@ -134,11 +147,12 @@ function defaultDeviceFor(id) {
|
|
|
134
147
|
var RUNTIME_FORMAT = {
|
|
135
148
|
onnx: "onnx",
|
|
136
149
|
openvino: "openvino",
|
|
137
|
-
coreml: "coreml"
|
|
150
|
+
coreml: "coreml",
|
|
151
|
+
edgetpu: "tflite"
|
|
138
152
|
};
|
|
139
153
|
/**
|
|
140
154
|
* Returns the model format required for a given runtime.
|
|
141
|
-
* Returns the locally-typed format string ('onnx' | 'openvino' | 'coreml')
|
|
155
|
+
* Returns the locally-typed format string ('onnx' | 'openvino' | 'coreml' | 'tflite')
|
|
142
156
|
* matching the engine-provisioner's own ModelFormat type.
|
|
143
157
|
*/
|
|
144
158
|
function modelFormatFor(id) {
|
|
@@ -167,6 +181,7 @@ function shouldInstallOpenvino(env) {
|
|
|
167
181
|
var PREFERENCE = [
|
|
168
182
|
"coreml",
|
|
169
183
|
"openvino",
|
|
184
|
+
"edgetpu",
|
|
170
185
|
"onnx"
|
|
171
186
|
];
|
|
172
187
|
/**
|
|
@@ -936,6 +951,9 @@ function serializeModelConfig(config) {
|
|
|
936
951
|
postprocessor: config.postprocessor,
|
|
937
952
|
confidence: config.confidence
|
|
938
953
|
};
|
|
954
|
+
if (config.inputWidth !== void 0) result["inputWidth"] = config.inputWidth;
|
|
955
|
+
if (config.inputHeight !== void 0) result["inputHeight"] = config.inputHeight;
|
|
956
|
+
if (config.inputChannels !== void 0) result["inputChannels"] = config.inputChannels;
|
|
939
957
|
if (config.labels) result["labels"] = config.labels;
|
|
940
958
|
if (config.charset) result["charset"] = config.charset;
|
|
941
959
|
if (config.numClasses) result["numClasses"] = config.numClasses;
|
|
@@ -1231,12 +1249,14 @@ var BACKEND_TO_POOL_RUNTIME = {
|
|
|
1231
1249
|
openvino: "openvino",
|
|
1232
1250
|
onnx: "onnxruntime",
|
|
1233
1251
|
cpu: "onnxruntime",
|
|
1234
|
-
cuda: "onnxruntime"
|
|
1252
|
+
cuda: "onnxruntime",
|
|
1253
|
+
edgetpu: "edgetpu"
|
|
1235
1254
|
};
|
|
1236
1255
|
var RUNTIME_TO_FORMAT = {
|
|
1237
1256
|
coreml: "coreml",
|
|
1238
1257
|
openvino: "openvino",
|
|
1239
|
-
onnxruntime: "onnx"
|
|
1258
|
+
onnxruntime: "onnx",
|
|
1259
|
+
edgetpu: "tflite"
|
|
1240
1260
|
};
|
|
1241
1261
|
var EngineFactory = class {
|
|
1242
1262
|
pool = null;
|
|
@@ -1355,13 +1375,15 @@ var EngineFactory = class {
|
|
|
1355
1375
|
const concurrency = this.opts.concurrency ?? {
|
|
1356
1376
|
coreml: 1,
|
|
1357
1377
|
openvino: 1,
|
|
1358
|
-
onnxruntime: 4
|
|
1378
|
+
onnxruntime: 4,
|
|
1379
|
+
edgetpu: 1
|
|
1359
1380
|
}[poolRuntime];
|
|
1360
1381
|
const isAutoDefault = this.opts.concurrency === void 0;
|
|
1361
1382
|
const defaultBatchMode = {
|
|
1362
1383
|
coreml: "window",
|
|
1363
1384
|
openvino: "none",
|
|
1364
|
-
onnxruntime: "list"
|
|
1385
|
+
onnxruntime: "list",
|
|
1386
|
+
edgetpu: "none"
|
|
1365
1387
|
};
|
|
1366
1388
|
const tuning = this.opts.tuning ?? {};
|
|
1367
1389
|
const resolvedTuning = {
|
|
@@ -1399,7 +1421,10 @@ var EngineFactory = class {
|
|
|
1399
1421
|
const urlParts = formatEntry.url.split("/");
|
|
1400
1422
|
const filename = urlParts[urlParts.length - 1] ?? `${modelId}.${format}`;
|
|
1401
1423
|
const modelPath = `${this.opts.modelsDir}/${filename}`;
|
|
1402
|
-
const
|
|
1424
|
+
const inputWidth = modelEntry.inputSize.width;
|
|
1425
|
+
const inputHeight = modelEntry.inputSize.height;
|
|
1426
|
+
const inputSize = Math.max(inputWidth, inputHeight);
|
|
1427
|
+
const inputChannels = modelEntry.inputChannels ?? 3;
|
|
1403
1428
|
let labels = def.labels;
|
|
1404
1429
|
if (!labels && modelEntry.extraFiles) {
|
|
1405
1430
|
const labelsFile = modelEntry.extraFiles.find((f) => f.filename.endsWith("-labels.json"));
|
|
@@ -1411,8 +1436,11 @@ var EngineFactory = class {
|
|
|
1411
1436
|
return {
|
|
1412
1437
|
path: modelPath,
|
|
1413
1438
|
inputSize,
|
|
1439
|
+
inputWidth,
|
|
1440
|
+
inputHeight,
|
|
1441
|
+
inputChannels,
|
|
1414
1442
|
preprocessMode: modelEntry.preprocessMode ?? "letterbox",
|
|
1415
|
-
postprocessor: def.postprocessor,
|
|
1443
|
+
postprocessor: modelEntry.postprocessor ?? def.postprocessor,
|
|
1416
1444
|
confidence: def.defaultConfidence,
|
|
1417
1445
|
labels,
|
|
1418
1446
|
charset: def.charset,
|
|
@@ -1611,6 +1639,11 @@ function postprocessYolo(output, stepDef) {
|
|
|
1611
1639
|
detections: simpleNms(dets, .45)
|
|
1612
1640
|
};
|
|
1613
1641
|
}
|
|
1642
|
+
function postprocessSsd(output, _stepDef) {
|
|
1643
|
+
const structured = tryStructured(output);
|
|
1644
|
+
if (structured) return structured;
|
|
1645
|
+
throw new Error("SSD postprocessing runs in the Python inference pool (ssd.py); no TypeScript raw-tensor path.");
|
|
1646
|
+
}
|
|
1614
1647
|
function postprocessScrfd(output, stepDef) {
|
|
1615
1648
|
const structured = tryStructured(output);
|
|
1616
1649
|
if (structured) return structured;
|
|
@@ -2033,6 +2066,7 @@ function postprocessYamnet(output, _stepDef) {
|
|
|
2033
2066
|
}
|
|
2034
2067
|
var DISPATCH = {
|
|
2035
2068
|
yolo: postprocessYolo,
|
|
2069
|
+
ssd: postprocessSsd,
|
|
2036
2070
|
"yolo-seg": postprocessYoloSeg,
|
|
2037
2071
|
scrfd: postprocessScrfd,
|
|
2038
2072
|
arcface: postprocessArcface,
|
|
@@ -2843,14 +2877,17 @@ var MIN_FACE_DETECTION_FLOOR_PX = 6;
|
|
|
2843
2877
|
var NATIVE_FACE_CROP_MAX_WIDTH = 320;
|
|
2844
2878
|
/**
|
|
2845
2879
|
* StepOutput kinds that synthesize a full-frame detection when they run at
|
|
2846
|
-
* the tree ROOT (see `synthesizeRootDetection`) — classifier/embedding
|
|
2847
|
-
* promoted to root by `pipelineRunner.runDetailSubtree` (task 6b), e.g.
|
|
2848
|
-
* `clip-embedding`, `animal-classifier`. Detector (`'detections'`)
|
|
2849
|
-
* the normal path
|
|
2850
|
-
*
|
|
2880
|
+
* the tree ROOT (see `synthesizeRootDetection`) — classifier/embedding/OCR
|
|
2881
|
+
* steps promoted to root by `pipelineRunner.runDetailSubtree` (task 6b), e.g.
|
|
2882
|
+
* `clip-embedding`, `animal-classifier`, `plate-ocr`. Detector (`'detections'`)
|
|
2883
|
+
* roots take the normal path. `'text'` is included so a `plate-ocr` step run
|
|
2884
|
+
* standalone on an already-cut plate crop (parent class `plate`) synthesizes a
|
|
2885
|
+
* full-frame detection carrying the recognized text as a label, instead of
|
|
2886
|
+
* silently dropping — the OCR chain otherwise only surfaces text when nested
|
|
2887
|
+
* under `plate-detection`. `'mask'` roots remain out of scope.
|
|
2851
2888
|
*/
|
|
2852
2889
|
function isEnrichmentOutput(output) {
|
|
2853
|
-
return output.kind === "classifications" || output.kind === "embedding";
|
|
2890
|
+
return output.kind === "classifications" || output.kind === "embedding" || output.kind === "text";
|
|
2854
2891
|
}
|
|
2855
2892
|
var PipelineExecutor = class {
|
|
2856
2893
|
opts;
|
|
@@ -2860,12 +2897,19 @@ var PipelineExecutor = class {
|
|
|
2860
2897
|
/** Per-key last-warn timestamps, so a persistently-failing/skipping child
|
|
2861
2898
|
* step surfaces a diagnostic without spamming the log every frame. */
|
|
2862
2899
|
warnThrottleAt = /* @__PURE__ */ new Map();
|
|
2863
|
-
throttledWarn(key, everyMs, message, meta) {
|
|
2900
|
+
throttledWarn(key, everyMs, message, meta, deviceId) {
|
|
2864
2901
|
const logger = this.opts.logger;
|
|
2865
2902
|
if (!logger) return;
|
|
2866
2903
|
const now = Date.now();
|
|
2867
2904
|
if (now - (this.warnThrottleAt.get(key) ?? 0) < everyMs) return;
|
|
2868
2905
|
this.warnThrottleAt.set(key, now);
|
|
2906
|
+
if (deviceId !== void 0) {
|
|
2907
|
+
logger.warn(message, {
|
|
2908
|
+
tags: { deviceId },
|
|
2909
|
+
meta
|
|
2910
|
+
});
|
|
2911
|
+
return;
|
|
2912
|
+
}
|
|
2869
2913
|
logger.warn(message, { meta });
|
|
2870
2914
|
}
|
|
2871
2915
|
/**
|
|
@@ -2875,15 +2919,15 @@ var PipelineExecutor = class {
|
|
|
2875
2919
|
* native crop, the NATIVE face size so an operator sees the size that actually
|
|
2876
2920
|
* gated. Throttled so it isn't per-frame spam.
|
|
2877
2921
|
*/
|
|
2878
|
-
warnFaceTooSmall(child, detShortSidePx, minFaceSizePx, nativeFaceShortSidePx) {
|
|
2879
|
-
this.throttledWarn(`face-small:${child.stepId}`, 3e4, "face detected but too small to embed — skipping", {
|
|
2922
|
+
warnFaceTooSmall(child, detShortSidePx, minFaceSizePx, nativeFaceShortSidePx, deviceId) {
|
|
2923
|
+
this.throttledWarn(`face-small:${child.stepId}:${deviceId}`, 3e4, "face detected but too small to embed — skipping", {
|
|
2880
2924
|
step: child.stepId,
|
|
2881
2925
|
model: child.modelId,
|
|
2882
2926
|
faceShortSidePx: Math.round(detShortSidePx),
|
|
2883
2927
|
minFaceSizePx,
|
|
2884
2928
|
gatedOn: nativeFaceShortSidePx === void 0 ? "detection" : "native",
|
|
2885
2929
|
...nativeFaceShortSidePx === void 0 ? {} : { nativeFaceShortSidePx: Math.round(nativeFaceShortSidePx) }
|
|
2886
|
-
});
|
|
2930
|
+
}, deviceId);
|
|
2887
2931
|
}
|
|
2888
2932
|
/**
|
|
2889
2933
|
* Execute the full pipeline tree against a frame.
|
|
@@ -2926,7 +2970,7 @@ var PipelineExecutor = class {
|
|
|
2926
2970
|
const mutable = this.synthesizeRootDetection(rootOutput, rootStep, idGen, rootMs, imageWidth, imageHeight);
|
|
2927
2971
|
applyChildOutput(mutable, rootStep, rootOutput, rootMs, ctx);
|
|
2928
2972
|
try {
|
|
2929
|
-
await this.executeChildren(rootStep.children, mutable, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, nativeFaceCropProvider);
|
|
2973
|
+
await this.executeChildren(rootStep.children, mutable, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, deviceId, nativeFaceCropProvider);
|
|
2930
2974
|
} catch (err) {
|
|
2931
2975
|
this.opts.logger?.warn("Pipeline child execution failed — keeping parent detection", {
|
|
2932
2976
|
tags: { deviceId },
|
|
@@ -2956,7 +3000,7 @@ var PipelineExecutor = class {
|
|
|
2956
3000
|
continue;
|
|
2957
3001
|
}
|
|
2958
3002
|
try {
|
|
2959
|
-
await this.executeChildren(rootStep.children, mutable, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, nativeFaceCropProvider);
|
|
3003
|
+
await this.executeChildren(rootStep.children, mutable, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, deviceId, nativeFaceCropProvider);
|
|
2960
3004
|
} catch (err) {
|
|
2961
3005
|
this.opts.logger?.warn("Pipeline child execution failed — keeping parent detection", {
|
|
2962
3006
|
tags: { deviceId },
|
|
@@ -3081,7 +3125,7 @@ var PipelineExecutor = class {
|
|
|
3081
3125
|
});
|
|
3082
3126
|
return output;
|
|
3083
3127
|
}
|
|
3084
|
-
async executeChildren(children, parentDetection, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, plane, nativeFaceCropProvider) {
|
|
3128
|
+
async executeChildren(children, parentDetection, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, plane, deviceId, nativeFaceCropProvider) {
|
|
3085
3129
|
for (const child of children) {
|
|
3086
3130
|
if (plane === "frame" && child.definition.inputClasses !== null) continue;
|
|
3087
3131
|
if (!this.matchesInputClasses(parentDetection.macroClass, child.inputClasses)) continue;
|
|
@@ -3099,13 +3143,13 @@ var PipelineExecutor = class {
|
|
|
3099
3143
|
const minFaceSize = typeof child.settings?.["minFaceSize"] === "number" ? child.settings["minFaceSize"] : DEFAULT_MIN_FACE_SIZE_PX;
|
|
3100
3144
|
const detShortSide = bboxShortSide(parentDetection.bbox);
|
|
3101
3145
|
if (detShortSide < MIN_FACE_DETECTION_FLOOR_PX) {
|
|
3102
|
-
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0);
|
|
3146
|
+
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0, deviceId);
|
|
3103
3147
|
continue;
|
|
3104
3148
|
}
|
|
3105
3149
|
const lms = parentDetection.landmarks;
|
|
3106
3150
|
if (lms && lms.length >= 5) {
|
|
3107
3151
|
if (!nativeFaceCropProvider && detShortSide < minFaceSize) {
|
|
3108
|
-
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0);
|
|
3152
|
+
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0, deviceId);
|
|
3109
3153
|
continue;
|
|
3110
3154
|
}
|
|
3111
3155
|
const aligned = await buildAlignedFaceCrop({
|
|
@@ -3122,7 +3166,7 @@ var PipelineExecutor = class {
|
|
|
3122
3166
|
});
|
|
3123
3167
|
const gateShortSide = aligned.nativeFaceShortSidePx ?? detShortSide;
|
|
3124
3168
|
if (gateShortSide < minFaceSize) {
|
|
3125
|
-
this.warnFaceTooSmall(child, detShortSide, minFaceSize, aligned.source === "native" ? gateShortSide : void 0);
|
|
3169
|
+
this.warnFaceTooSmall(child, detShortSide, minFaceSize, aligned.source === "native" ? gateShortSide : void 0, deviceId);
|
|
3126
3170
|
continue;
|
|
3127
3171
|
}
|
|
3128
3172
|
cropJpegBuf = aligned.jpeg;
|
|
@@ -3131,7 +3175,7 @@ var PipelineExecutor = class {
|
|
|
3131
3175
|
parentDetection.faceAlignedCrop = cropJpegBuf.toString("base64");
|
|
3132
3176
|
} else {
|
|
3133
3177
|
if (detShortSide < minFaceSize) {
|
|
3134
|
-
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0);
|
|
3178
|
+
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0, deviceId);
|
|
3135
3179
|
continue;
|
|
3136
3180
|
}
|
|
3137
3181
|
const crop = await cropJpeg(fullFrameJpeg, parentDetection.bbox, imageWidth, imageHeight);
|
|
@@ -3163,15 +3207,15 @@ var PipelineExecutor = class {
|
|
|
3163
3207
|
y: l.y + py1
|
|
3164
3208
|
}));
|
|
3165
3209
|
}
|
|
3166
|
-
await this.executeChildren(child.children, detail, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, plane, nativeFaceCropProvider);
|
|
3210
|
+
await this.executeChildren(child.children, detail, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, plane, deviceId, nativeFaceCropProvider);
|
|
3167
3211
|
}
|
|
3168
3212
|
}
|
|
3169
3213
|
} catch (err) {
|
|
3170
|
-
this.throttledWarn(`child-fail:${child.stepId}`, 15e3, "pipeline child step failed", {
|
|
3214
|
+
this.throttledWarn(`child-fail:${child.stepId}:${deviceId}`, 15e3, "pipeline child step failed", {
|
|
3171
3215
|
step: child.stepId,
|
|
3172
3216
|
model: child.modelId,
|
|
3173
3217
|
error: require_dist.errMsg(err)
|
|
3174
|
-
});
|
|
3218
|
+
}, deviceId);
|
|
3175
3219
|
}
|
|
3176
3220
|
}
|
|
3177
3221
|
}
|
|
@@ -3626,7 +3670,8 @@ function toProbedHardware(hw) {
|
|
|
3626
3670
|
if (!hw) return null;
|
|
3627
3671
|
return {
|
|
3628
3672
|
npu: hw.npu ? { type: hw.npu.type } : null,
|
|
3629
|
-
gpu: hw.gpu ? { type: hw.gpu.type } : null
|
|
3673
|
+
gpu: hw.gpu ? { type: hw.gpu.type } : null,
|
|
3674
|
+
coral: hw.coral ? { type: hw.coral.type } : null
|
|
3630
3675
|
};
|
|
3631
3676
|
}
|
|
3632
3677
|
var ONNX_FLOOR = {
|
|
@@ -3732,16 +3777,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
3732
3777
|
*/
|
|
3733
3778
|
loggedLiveDispatchIssues = /* @__PURE__ */ new Set();
|
|
3734
3779
|
/**
|
|
3735
|
-
* CB5 shm passthrough — the process-local, LONG-LIVED reader cache for
|
|
3736
|
-
* `runPipeline({ frameHandle })`. Opens each named shm segment ONCE and
|
|
3737
|
-
* reuses the mapping for every later handle on the same ring (never
|
|
3738
|
-
* open/close per-call). Lazily created on first handle, unmapped in
|
|
3739
|
-
* {@link shutdown}. The executor and the runner are both hub-local
|
|
3740
|
-
* processes sharing `/dev/shm`, so a LOCAL handle resolves to a zero-copy
|
|
3741
|
-
* read here.
|
|
3742
|
-
*/
|
|
3743
|
-
frameHandleReaders = null;
|
|
3744
|
-
/**
|
|
3745
3780
|
* Lazy detection-engine runtime provisioner (Phase 2). Owns the
|
|
3746
3781
|
* idle → installing → verifying → ready state machine for the
|
|
3747
3782
|
* currently-selected engine and is the SOLE authority the inference
|
|
@@ -3938,14 +3973,15 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
3938
3973
|
*/
|
|
3939
3974
|
resolvedEngineBackend() {
|
|
3940
3975
|
const backend = this.currentEngine.backend;
|
|
3941
|
-
return backend === "openvino" || backend === "coreml" ? backend : "onnx";
|
|
3976
|
+
return backend === "openvino" || backend === "coreml" || backend === "edgetpu" ? backend : "onnx";
|
|
3942
3977
|
}
|
|
3943
3978
|
/** Map a backend string to a known RuntimeId, flooring to onnx. */
|
|
3944
3979
|
toRuntimeId(backend) {
|
|
3945
3980
|
return [
|
|
3946
3981
|
"onnx",
|
|
3947
3982
|
"openvino",
|
|
3948
|
-
"coreml"
|
|
3983
|
+
"coreml",
|
|
3984
|
+
"edgetpu"
|
|
3949
3985
|
].find((id) => id === backend) ?? "onnx";
|
|
3950
3986
|
}
|
|
3951
3987
|
/**
|
|
@@ -4608,35 +4644,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
4608
4644
|
} });
|
|
4609
4645
|
return { success: true };
|
|
4610
4646
|
}
|
|
4611
|
-
/** This executor's cluster node id (suffix-stripped, matching the runner). */
|
|
4612
|
-
ownNodeId() {
|
|
4613
|
-
const raw = this.addonCtx?.kernel?.localNodeId ?? "hub";
|
|
4614
|
-
return raw.includes("/") ? raw.split("/")[0] : raw;
|
|
4615
|
-
}
|
|
4616
|
-
/**
|
|
4617
|
-
* CB5 — resolve a shm `FrameHandle` to pixels zero-copy. Returns `null`
|
|
4618
|
-
* when:
|
|
4619
|
-
* - the handle is FOREIGN (its segment lives on another node — a local
|
|
4620
|
-
* `shm_open` would flood ENOENT; the runner only sends LOCAL handles, so
|
|
4621
|
-
* this is a defensive guard against an unexpected topology);
|
|
4622
|
-
* - the ring slot was recycled before the read (latest-wins drop) or the
|
|
4623
|
-
* segment could not be mapped.
|
|
4624
|
-
* A `null` degrades the caller to an empty `FrameResult` — the runner ships
|
|
4625
|
-
* pixels via `frame` as the fallback.
|
|
4626
|
-
*/
|
|
4627
|
-
resolveFrameHandle(handle) {
|
|
4628
|
-
if (handle.nodeId !== this.ownNodeId()) return null;
|
|
4629
|
-
if (!this.frameHandleReaders) this.frameHandleReaders = new _camstack_shm_ring.FrameRingReaderCache(this.log);
|
|
4630
|
-
const decoded = this.frameHandleReaders.read(handle);
|
|
4631
|
-
if (!decoded) return null;
|
|
4632
|
-
return {
|
|
4633
|
-
data: decoded.data,
|
|
4634
|
-
width: decoded.width,
|
|
4635
|
-
height: decoded.height,
|
|
4636
|
-
format: decoded.format,
|
|
4637
|
-
timestamp: decoded.timestamp
|
|
4638
|
-
};
|
|
4639
|
-
}
|
|
4640
4647
|
/**
|
|
4641
4648
|
* Minimal detection-free `FrameResult` returned when a `frameHandle` read
|
|
4642
4649
|
* misses (recycled slot / foreign / unmappable). Shape-identical to a
|
|
@@ -4729,12 +4736,8 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
4729
4736
|
].filter((s) => s !== null);
|
|
4730
4737
|
if (sources.length === 0) throw new Error("runPipeline requires exactly one of: frame, frameHandle, image, imageBase64, referenceImage");
|
|
4731
4738
|
if (sources.length > 1) throw new Error(`runPipeline received conflicting image sources: ${sources.join(", ")}`);
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
handleFrame = this.resolveFrameHandle(input.frameHandle);
|
|
4735
|
-
if (!handleFrame) return this.emptyFrameHandleResult(input);
|
|
4736
|
-
}
|
|
4737
|
-
const runtimeFrame = input.frame ?? handleFrame ?? void 0;
|
|
4739
|
+
if (input.frameHandle) return this.emptyFrameHandleResult(input);
|
|
4740
|
+
const runtimeFrame = input.frame ?? void 0;
|
|
4738
4741
|
const decodeT0 = performance.now();
|
|
4739
4742
|
if (runtimeFrame) {
|
|
4740
4743
|
const frame = runtimeFrame;
|
|
@@ -5489,8 +5492,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
5489
5492
|
this.executor = null;
|
|
5490
5493
|
}
|
|
5491
5494
|
for (const id of Array.from(this.deviceProxies.keys())) this.releaseDeviceProxy(id);
|
|
5492
|
-
this.frameHandleReaders?.close();
|
|
5493
|
-
this.frameHandleReaders = null;
|
|
5494
5495
|
}
|
|
5495
5496
|
/**
|
|
5496
5497
|
* Resolve and cache a {@link DeviceProxy} for the given camera. Pins
|
|
@@ -6226,7 +6227,8 @@ var BACKEND_TO_FORMAT = {
|
|
|
6226
6227
|
cpu: "onnx",
|
|
6227
6228
|
coreml: "coreml",
|
|
6228
6229
|
openvino: "openvino",
|
|
6229
|
-
onnx: "onnx"
|
|
6230
|
+
onnx: "onnx",
|
|
6231
|
+
edgetpu: "tflite"
|
|
6230
6232
|
};
|
|
6231
6233
|
/**
|
|
6232
6234
|
* Every runtime the registry knows about, in offer order. Used only to build
|
|
@@ -6237,7 +6239,8 @@ var BACKEND_TO_FORMAT = {
|
|
|
6237
6239
|
var ALL_RUNTIME_IDS = [
|
|
6238
6240
|
"onnx",
|
|
6239
6241
|
"openvino",
|
|
6240
|
-
"coreml"
|
|
6242
|
+
"coreml",
|
|
6243
|
+
"edgetpu"
|
|
6241
6244
|
];
|
|
6242
6245
|
/**
|
|
6243
6246
|
* Narrow an arbitrary stored backend string to a known `RuntimeId`. Legacy or
|
|
@@ -6705,6 +6708,7 @@ var DetectionPipelineAddon = class DetectionPipelineAddon extends require_dist.B
|
|
|
6705
6708
|
return {
|
|
6706
6709
|
npu: hw.npu ? { type: hw.npu.type } : null,
|
|
6707
6710
|
gpu: hw.gpu ? { type: hw.gpu.type } : null,
|
|
6711
|
+
coral: hw.coral ? { type: hw.coral.type } : null,
|
|
6708
6712
|
platform: hw.platform,
|
|
6709
6713
|
arch: hw.arch
|
|
6710
6714
|
};
|