@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
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { t as __require } from "../chunk-BdkLduGY.mjs";
|
|
2
|
-
import { D as nodePin, H as createEvent, I as errMsg, L as BaseAddon, O as pipelineExecutorCapability, P as supportedRuntimes$1, U as hydrateSchema, V as EventCategory, X as sleep, b as detectionPipelineCapability, f as YAMNET_TO_MACRO, j as runtimeDevices$1, q as parseJsonUnknown, t as APPLE_SA_TO_MACRO, v as defaultDeviceFor$1, x as evaluateZoneRules } from "../dist-
|
|
3
|
-
import { a as getStepDefinition, i as getStep, n as ALL_STEPS, o as resolveModelForFormat, r as getDefaultModelForFormat, t as ALL_PIPELINE_STEPS } from "../step-definitions-
|
|
2
|
+
import { D as nodePin, H as createEvent, I as errMsg, L as BaseAddon, O as pipelineExecutorCapability, P as supportedRuntimes$1, U as hydrateSchema, V as EventCategory, X as sleep, b as detectionPipelineCapability, f as YAMNET_TO_MACRO, j as runtimeDevices$1, q as parseJsonUnknown, t as APPLE_SA_TO_MACRO, v as defaultDeviceFor$1, x as evaluateZoneRules } from "../dist-CL531uVA.mjs";
|
|
3
|
+
import { a as getStepDefinition, i as getStep, n as ALL_STEPS, o as resolveModelForFormat, r as getDefaultModelForFormat, t as ALL_PIPELINE_STEPS } from "../step-definitions-1d3_vQ6S.mjs";
|
|
4
4
|
import { t as pickNodePlatformArch } from "../node-topology-platform-BkR_k6WT.mjs";
|
|
5
|
-
import { a as isModelDownloaded, i as ensureModel, n as deleteModelFromDisk } from "../model-download-service-C-IHWnXx-
|
|
6
|
-
import { FrameRingReaderCache } from "@camstack/shm-ring";
|
|
5
|
+
import { a as isModelDownloaded, i as ensureModel, n as deleteModelFromDisk } from "../model-download-service-C-IHWnXx-3Mmeob3l.mjs";
|
|
7
6
|
import { spawn } from "node:child_process";
|
|
7
|
+
import sharp from "sharp";
|
|
8
8
|
import * as fs from "node:fs";
|
|
9
9
|
import * as path$1 from "node:path";
|
|
10
10
|
import * as os from "node:os";
|
|
11
|
-
import sharp from "sharp";
|
|
12
11
|
//#region src/detection-pipeline/runtimes.ts
|
|
13
12
|
var KNOWN_PLATFORMS = [
|
|
14
13
|
"darwin",
|
|
@@ -44,6 +43,9 @@ function npuInfoFrom(hw) {
|
|
|
44
43
|
if (!type) return null;
|
|
45
44
|
return { type };
|
|
46
45
|
}
|
|
46
|
+
function coralInfoFrom(hw) {
|
|
47
|
+
return hw.coral?.type === "coral-edgetpu" ? { type: "coral-edgetpu" } : null;
|
|
48
|
+
}
|
|
47
49
|
function envToHardwareInfo(env) {
|
|
48
50
|
return {
|
|
49
51
|
platform: toKnownPlatform(env.platform),
|
|
@@ -53,7 +55,8 @@ function envToHardwareInfo(env) {
|
|
|
53
55
|
totalRAM_MB: 0,
|
|
54
56
|
availableRAM_MB: 0,
|
|
55
57
|
gpu: env.hardware ? gpuInfoFrom(env.hardware) : null,
|
|
56
|
-
npu: env.hardware ? npuInfoFrom(env.hardware) : null
|
|
58
|
+
npu: env.hardware ? npuInfoFrom(env.hardware) : null,
|
|
59
|
+
coral: env.hardware ? coralInfoFrom(env.hardware) : null
|
|
57
60
|
};
|
|
58
61
|
}
|
|
59
62
|
function probedToHardwareInfo(hw) {
|
|
@@ -66,7 +69,8 @@ function probedToHardwareInfo(hw) {
|
|
|
66
69
|
totalRAM_MB: 0,
|
|
67
70
|
availableRAM_MB: 0,
|
|
68
71
|
gpu: gpuInfoFrom(hw),
|
|
69
|
-
npu: npuInfoFrom(hw)
|
|
72
|
+
npu: npuInfoFrom(hw),
|
|
73
|
+
coral: coralInfoFrom(hw)
|
|
70
74
|
};
|
|
71
75
|
}
|
|
72
76
|
var RUNTIME_DETAIL = {
|
|
@@ -99,6 +103,15 @@ var RUNTIME_DETAIL = {
|
|
|
99
103
|
maxBatchSize: 8,
|
|
100
104
|
numWorkers: 1
|
|
101
105
|
}
|
|
106
|
+
},
|
|
107
|
+
edgetpu: {
|
|
108
|
+
label: "Coral Edge TPU",
|
|
109
|
+
pythonRequirements: ["requirements.txt", "requirements-edgetpu.txt"],
|
|
110
|
+
tuning: {
|
|
111
|
+
concurrency: 1,
|
|
112
|
+
batchMode: "none",
|
|
113
|
+
numWorkers: 1
|
|
114
|
+
}
|
|
102
115
|
}
|
|
103
116
|
};
|
|
104
117
|
/**
|
|
@@ -126,11 +139,12 @@ function defaultDeviceFor(id) {
|
|
|
126
139
|
var RUNTIME_FORMAT = {
|
|
127
140
|
onnx: "onnx",
|
|
128
141
|
openvino: "openvino",
|
|
129
|
-
coreml: "coreml"
|
|
142
|
+
coreml: "coreml",
|
|
143
|
+
edgetpu: "tflite"
|
|
130
144
|
};
|
|
131
145
|
/**
|
|
132
146
|
* Returns the model format required for a given runtime.
|
|
133
|
-
* Returns the locally-typed format string ('onnx' | 'openvino' | 'coreml')
|
|
147
|
+
* Returns the locally-typed format string ('onnx' | 'openvino' | 'coreml' | 'tflite')
|
|
134
148
|
* matching the engine-provisioner's own ModelFormat type.
|
|
135
149
|
*/
|
|
136
150
|
function modelFormatFor(id) {
|
|
@@ -159,6 +173,7 @@ function shouldInstallOpenvino(env) {
|
|
|
159
173
|
var PREFERENCE = [
|
|
160
174
|
"coreml",
|
|
161
175
|
"openvino",
|
|
176
|
+
"edgetpu",
|
|
162
177
|
"onnx"
|
|
163
178
|
];
|
|
164
179
|
/**
|
|
@@ -928,6 +943,9 @@ function serializeModelConfig(config) {
|
|
|
928
943
|
postprocessor: config.postprocessor,
|
|
929
944
|
confidence: config.confidence
|
|
930
945
|
};
|
|
946
|
+
if (config.inputWidth !== void 0) result["inputWidth"] = config.inputWidth;
|
|
947
|
+
if (config.inputHeight !== void 0) result["inputHeight"] = config.inputHeight;
|
|
948
|
+
if (config.inputChannels !== void 0) result["inputChannels"] = config.inputChannels;
|
|
931
949
|
if (config.labels) result["labels"] = config.labels;
|
|
932
950
|
if (config.charset) result["charset"] = config.charset;
|
|
933
951
|
if (config.numClasses) result["numClasses"] = config.numClasses;
|
|
@@ -1223,12 +1241,14 @@ var BACKEND_TO_POOL_RUNTIME = {
|
|
|
1223
1241
|
openvino: "openvino",
|
|
1224
1242
|
onnx: "onnxruntime",
|
|
1225
1243
|
cpu: "onnxruntime",
|
|
1226
|
-
cuda: "onnxruntime"
|
|
1244
|
+
cuda: "onnxruntime",
|
|
1245
|
+
edgetpu: "edgetpu"
|
|
1227
1246
|
};
|
|
1228
1247
|
var RUNTIME_TO_FORMAT = {
|
|
1229
1248
|
coreml: "coreml",
|
|
1230
1249
|
openvino: "openvino",
|
|
1231
|
-
onnxruntime: "onnx"
|
|
1250
|
+
onnxruntime: "onnx",
|
|
1251
|
+
edgetpu: "tflite"
|
|
1232
1252
|
};
|
|
1233
1253
|
var EngineFactory = class {
|
|
1234
1254
|
pool = null;
|
|
@@ -1347,13 +1367,15 @@ var EngineFactory = class {
|
|
|
1347
1367
|
const concurrency = this.opts.concurrency ?? {
|
|
1348
1368
|
coreml: 1,
|
|
1349
1369
|
openvino: 1,
|
|
1350
|
-
onnxruntime: 4
|
|
1370
|
+
onnxruntime: 4,
|
|
1371
|
+
edgetpu: 1
|
|
1351
1372
|
}[poolRuntime];
|
|
1352
1373
|
const isAutoDefault = this.opts.concurrency === void 0;
|
|
1353
1374
|
const defaultBatchMode = {
|
|
1354
1375
|
coreml: "window",
|
|
1355
1376
|
openvino: "none",
|
|
1356
|
-
onnxruntime: "list"
|
|
1377
|
+
onnxruntime: "list",
|
|
1378
|
+
edgetpu: "none"
|
|
1357
1379
|
};
|
|
1358
1380
|
const tuning = this.opts.tuning ?? {};
|
|
1359
1381
|
const resolvedTuning = {
|
|
@@ -1391,7 +1413,10 @@ var EngineFactory = class {
|
|
|
1391
1413
|
const urlParts = formatEntry.url.split("/");
|
|
1392
1414
|
const filename = urlParts[urlParts.length - 1] ?? `${modelId}.${format}`;
|
|
1393
1415
|
const modelPath = `${this.opts.modelsDir}/${filename}`;
|
|
1394
|
-
const
|
|
1416
|
+
const inputWidth = modelEntry.inputSize.width;
|
|
1417
|
+
const inputHeight = modelEntry.inputSize.height;
|
|
1418
|
+
const inputSize = Math.max(inputWidth, inputHeight);
|
|
1419
|
+
const inputChannels = modelEntry.inputChannels ?? 3;
|
|
1395
1420
|
let labels = def.labels;
|
|
1396
1421
|
if (!labels && modelEntry.extraFiles) {
|
|
1397
1422
|
const labelsFile = modelEntry.extraFiles.find((f) => f.filename.endsWith("-labels.json"));
|
|
@@ -1403,8 +1428,11 @@ var EngineFactory = class {
|
|
|
1403
1428
|
return {
|
|
1404
1429
|
path: modelPath,
|
|
1405
1430
|
inputSize,
|
|
1431
|
+
inputWidth,
|
|
1432
|
+
inputHeight,
|
|
1433
|
+
inputChannels,
|
|
1406
1434
|
preprocessMode: modelEntry.preprocessMode ?? "letterbox",
|
|
1407
|
-
postprocessor: def.postprocessor,
|
|
1435
|
+
postprocessor: modelEntry.postprocessor ?? def.postprocessor,
|
|
1408
1436
|
confidence: def.defaultConfidence,
|
|
1409
1437
|
labels,
|
|
1410
1438
|
charset: def.charset,
|
|
@@ -1603,6 +1631,11 @@ function postprocessYolo(output, stepDef) {
|
|
|
1603
1631
|
detections: simpleNms(dets, .45)
|
|
1604
1632
|
};
|
|
1605
1633
|
}
|
|
1634
|
+
function postprocessSsd(output, _stepDef) {
|
|
1635
|
+
const structured = tryStructured(output);
|
|
1636
|
+
if (structured) return structured;
|
|
1637
|
+
throw new Error("SSD postprocessing runs in the Python inference pool (ssd.py); no TypeScript raw-tensor path.");
|
|
1638
|
+
}
|
|
1606
1639
|
function postprocessScrfd(output, stepDef) {
|
|
1607
1640
|
const structured = tryStructured(output);
|
|
1608
1641
|
if (structured) return structured;
|
|
@@ -2025,6 +2058,7 @@ function postprocessYamnet(output, _stepDef) {
|
|
|
2025
2058
|
}
|
|
2026
2059
|
var DISPATCH = {
|
|
2027
2060
|
yolo: postprocessYolo,
|
|
2061
|
+
ssd: postprocessSsd,
|
|
2028
2062
|
"yolo-seg": postprocessYoloSeg,
|
|
2029
2063
|
scrfd: postprocessScrfd,
|
|
2030
2064
|
arcface: postprocessArcface,
|
|
@@ -2835,14 +2869,17 @@ var MIN_FACE_DETECTION_FLOOR_PX = 6;
|
|
|
2835
2869
|
var NATIVE_FACE_CROP_MAX_WIDTH = 320;
|
|
2836
2870
|
/**
|
|
2837
2871
|
* StepOutput kinds that synthesize a full-frame detection when they run at
|
|
2838
|
-
* the tree ROOT (see `synthesizeRootDetection`) — classifier/embedding
|
|
2839
|
-
* promoted to root by `pipelineRunner.runDetailSubtree` (task 6b), e.g.
|
|
2840
|
-
* `clip-embedding`, `animal-classifier`. Detector (`'detections'`)
|
|
2841
|
-
* the normal path
|
|
2842
|
-
*
|
|
2872
|
+
* the tree ROOT (see `synthesizeRootDetection`) — classifier/embedding/OCR
|
|
2873
|
+
* steps promoted to root by `pipelineRunner.runDetailSubtree` (task 6b), e.g.
|
|
2874
|
+
* `clip-embedding`, `animal-classifier`, `plate-ocr`. Detector (`'detections'`)
|
|
2875
|
+
* roots take the normal path. `'text'` is included so a `plate-ocr` step run
|
|
2876
|
+
* standalone on an already-cut plate crop (parent class `plate`) synthesizes a
|
|
2877
|
+
* full-frame detection carrying the recognized text as a label, instead of
|
|
2878
|
+
* silently dropping — the OCR chain otherwise only surfaces text when nested
|
|
2879
|
+
* under `plate-detection`. `'mask'` roots remain out of scope.
|
|
2843
2880
|
*/
|
|
2844
2881
|
function isEnrichmentOutput(output) {
|
|
2845
|
-
return output.kind === "classifications" || output.kind === "embedding";
|
|
2882
|
+
return output.kind === "classifications" || output.kind === "embedding" || output.kind === "text";
|
|
2846
2883
|
}
|
|
2847
2884
|
var PipelineExecutor = class {
|
|
2848
2885
|
opts;
|
|
@@ -2852,12 +2889,19 @@ var PipelineExecutor = class {
|
|
|
2852
2889
|
/** Per-key last-warn timestamps, so a persistently-failing/skipping child
|
|
2853
2890
|
* step surfaces a diagnostic without spamming the log every frame. */
|
|
2854
2891
|
warnThrottleAt = /* @__PURE__ */ new Map();
|
|
2855
|
-
throttledWarn(key, everyMs, message, meta) {
|
|
2892
|
+
throttledWarn(key, everyMs, message, meta, deviceId) {
|
|
2856
2893
|
const logger = this.opts.logger;
|
|
2857
2894
|
if (!logger) return;
|
|
2858
2895
|
const now = Date.now();
|
|
2859
2896
|
if (now - (this.warnThrottleAt.get(key) ?? 0) < everyMs) return;
|
|
2860
2897
|
this.warnThrottleAt.set(key, now);
|
|
2898
|
+
if (deviceId !== void 0) {
|
|
2899
|
+
logger.warn(message, {
|
|
2900
|
+
tags: { deviceId },
|
|
2901
|
+
meta
|
|
2902
|
+
});
|
|
2903
|
+
return;
|
|
2904
|
+
}
|
|
2861
2905
|
logger.warn(message, { meta });
|
|
2862
2906
|
}
|
|
2863
2907
|
/**
|
|
@@ -2867,15 +2911,15 @@ var PipelineExecutor = class {
|
|
|
2867
2911
|
* native crop, the NATIVE face size so an operator sees the size that actually
|
|
2868
2912
|
* gated. Throttled so it isn't per-frame spam.
|
|
2869
2913
|
*/
|
|
2870
|
-
warnFaceTooSmall(child, detShortSidePx, minFaceSizePx, nativeFaceShortSidePx) {
|
|
2871
|
-
this.throttledWarn(`face-small:${child.stepId}`, 3e4, "face detected but too small to embed — skipping", {
|
|
2914
|
+
warnFaceTooSmall(child, detShortSidePx, minFaceSizePx, nativeFaceShortSidePx, deviceId) {
|
|
2915
|
+
this.throttledWarn(`face-small:${child.stepId}:${deviceId}`, 3e4, "face detected but too small to embed — skipping", {
|
|
2872
2916
|
step: child.stepId,
|
|
2873
2917
|
model: child.modelId,
|
|
2874
2918
|
faceShortSidePx: Math.round(detShortSidePx),
|
|
2875
2919
|
minFaceSizePx,
|
|
2876
2920
|
gatedOn: nativeFaceShortSidePx === void 0 ? "detection" : "native",
|
|
2877
2921
|
...nativeFaceShortSidePx === void 0 ? {} : { nativeFaceShortSidePx: Math.round(nativeFaceShortSidePx) }
|
|
2878
|
-
});
|
|
2922
|
+
}, deviceId);
|
|
2879
2923
|
}
|
|
2880
2924
|
/**
|
|
2881
2925
|
* Execute the full pipeline tree against a frame.
|
|
@@ -2918,7 +2962,7 @@ var PipelineExecutor = class {
|
|
|
2918
2962
|
const mutable = this.synthesizeRootDetection(rootOutput, rootStep, idGen, rootMs, imageWidth, imageHeight);
|
|
2919
2963
|
applyChildOutput(mutable, rootStep, rootOutput, rootMs, ctx);
|
|
2920
2964
|
try {
|
|
2921
|
-
await this.executeChildren(rootStep.children, mutable, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, nativeFaceCropProvider);
|
|
2965
|
+
await this.executeChildren(rootStep.children, mutable, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, deviceId, nativeFaceCropProvider);
|
|
2922
2966
|
} catch (err) {
|
|
2923
2967
|
this.opts.logger?.warn("Pipeline child execution failed — keeping parent detection", {
|
|
2924
2968
|
tags: { deviceId },
|
|
@@ -2948,7 +2992,7 @@ var PipelineExecutor = class {
|
|
|
2948
2992
|
continue;
|
|
2949
2993
|
}
|
|
2950
2994
|
try {
|
|
2951
|
-
await this.executeChildren(rootStep.children, mutable, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, nativeFaceCropProvider);
|
|
2995
|
+
await this.executeChildren(rootStep.children, mutable, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, deviceId, nativeFaceCropProvider);
|
|
2952
2996
|
} catch (err) {
|
|
2953
2997
|
this.opts.logger?.warn("Pipeline child execution failed — keeping parent detection", {
|
|
2954
2998
|
tags: { deviceId },
|
|
@@ -3073,7 +3117,7 @@ var PipelineExecutor = class {
|
|
|
3073
3117
|
});
|
|
3074
3118
|
return output;
|
|
3075
3119
|
}
|
|
3076
|
-
async executeChildren(children, parentDetection, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, plane, nativeFaceCropProvider) {
|
|
3120
|
+
async executeChildren(children, parentDetection, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, plane, deviceId, nativeFaceCropProvider) {
|
|
3077
3121
|
for (const child of children) {
|
|
3078
3122
|
if (plane === "frame" && child.definition.inputClasses !== null) continue;
|
|
3079
3123
|
if (!this.matchesInputClasses(parentDetection.macroClass, child.inputClasses)) continue;
|
|
@@ -3091,13 +3135,13 @@ var PipelineExecutor = class {
|
|
|
3091
3135
|
const minFaceSize = typeof child.settings?.["minFaceSize"] === "number" ? child.settings["minFaceSize"] : DEFAULT_MIN_FACE_SIZE_PX;
|
|
3092
3136
|
const detShortSide = bboxShortSide(parentDetection.bbox);
|
|
3093
3137
|
if (detShortSide < MIN_FACE_DETECTION_FLOOR_PX) {
|
|
3094
|
-
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0);
|
|
3138
|
+
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0, deviceId);
|
|
3095
3139
|
continue;
|
|
3096
3140
|
}
|
|
3097
3141
|
const lms = parentDetection.landmarks;
|
|
3098
3142
|
if (lms && lms.length >= 5) {
|
|
3099
3143
|
if (!nativeFaceCropProvider && detShortSide < minFaceSize) {
|
|
3100
|
-
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0);
|
|
3144
|
+
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0, deviceId);
|
|
3101
3145
|
continue;
|
|
3102
3146
|
}
|
|
3103
3147
|
const aligned = await buildAlignedFaceCrop({
|
|
@@ -3114,7 +3158,7 @@ var PipelineExecutor = class {
|
|
|
3114
3158
|
});
|
|
3115
3159
|
const gateShortSide = aligned.nativeFaceShortSidePx ?? detShortSide;
|
|
3116
3160
|
if (gateShortSide < minFaceSize) {
|
|
3117
|
-
this.warnFaceTooSmall(child, detShortSide, minFaceSize, aligned.source === "native" ? gateShortSide : void 0);
|
|
3161
|
+
this.warnFaceTooSmall(child, detShortSide, minFaceSize, aligned.source === "native" ? gateShortSide : void 0, deviceId);
|
|
3118
3162
|
continue;
|
|
3119
3163
|
}
|
|
3120
3164
|
cropJpegBuf = aligned.jpeg;
|
|
@@ -3123,7 +3167,7 @@ var PipelineExecutor = class {
|
|
|
3123
3167
|
parentDetection.faceAlignedCrop = cropJpegBuf.toString("base64");
|
|
3124
3168
|
} else {
|
|
3125
3169
|
if (detShortSide < minFaceSize) {
|
|
3126
|
-
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0);
|
|
3170
|
+
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0, deviceId);
|
|
3127
3171
|
continue;
|
|
3128
3172
|
}
|
|
3129
3173
|
const crop = await cropJpeg(fullFrameJpeg, parentDetection.bbox, imageWidth, imageHeight);
|
|
@@ -3155,15 +3199,15 @@ var PipelineExecutor = class {
|
|
|
3155
3199
|
y: l.y + py1
|
|
3156
3200
|
}));
|
|
3157
3201
|
}
|
|
3158
|
-
await this.executeChildren(child.children, detail, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, plane, nativeFaceCropProvider);
|
|
3202
|
+
await this.executeChildren(child.children, detail, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, plane, deviceId, nativeFaceCropProvider);
|
|
3159
3203
|
}
|
|
3160
3204
|
}
|
|
3161
3205
|
} catch (err) {
|
|
3162
|
-
this.throttledWarn(`child-fail:${child.stepId}`, 15e3, "pipeline child step failed", {
|
|
3206
|
+
this.throttledWarn(`child-fail:${child.stepId}:${deviceId}`, 15e3, "pipeline child step failed", {
|
|
3163
3207
|
step: child.stepId,
|
|
3164
3208
|
model: child.modelId,
|
|
3165
3209
|
error: errMsg(err)
|
|
3166
|
-
});
|
|
3210
|
+
}, deviceId);
|
|
3167
3211
|
}
|
|
3168
3212
|
}
|
|
3169
3213
|
}
|
|
@@ -3618,7 +3662,8 @@ function toProbedHardware(hw) {
|
|
|
3618
3662
|
if (!hw) return null;
|
|
3619
3663
|
return {
|
|
3620
3664
|
npu: hw.npu ? { type: hw.npu.type } : null,
|
|
3621
|
-
gpu: hw.gpu ? { type: hw.gpu.type } : null
|
|
3665
|
+
gpu: hw.gpu ? { type: hw.gpu.type } : null,
|
|
3666
|
+
coral: hw.coral ? { type: hw.coral.type } : null
|
|
3622
3667
|
};
|
|
3623
3668
|
}
|
|
3624
3669
|
var ONNX_FLOOR = {
|
|
@@ -3724,16 +3769,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
3724
3769
|
*/
|
|
3725
3770
|
loggedLiveDispatchIssues = /* @__PURE__ */ new Set();
|
|
3726
3771
|
/**
|
|
3727
|
-
* CB5 shm passthrough — the process-local, LONG-LIVED reader cache for
|
|
3728
|
-
* `runPipeline({ frameHandle })`. Opens each named shm segment ONCE and
|
|
3729
|
-
* reuses the mapping for every later handle on the same ring (never
|
|
3730
|
-
* open/close per-call). Lazily created on first handle, unmapped in
|
|
3731
|
-
* {@link shutdown}. The executor and the runner are both hub-local
|
|
3732
|
-
* processes sharing `/dev/shm`, so a LOCAL handle resolves to a zero-copy
|
|
3733
|
-
* read here.
|
|
3734
|
-
*/
|
|
3735
|
-
frameHandleReaders = null;
|
|
3736
|
-
/**
|
|
3737
3772
|
* Lazy detection-engine runtime provisioner (Phase 2). Owns the
|
|
3738
3773
|
* idle → installing → verifying → ready state machine for the
|
|
3739
3774
|
* currently-selected engine and is the SOLE authority the inference
|
|
@@ -3930,14 +3965,15 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
3930
3965
|
*/
|
|
3931
3966
|
resolvedEngineBackend() {
|
|
3932
3967
|
const backend = this.currentEngine.backend;
|
|
3933
|
-
return backend === "openvino" || backend === "coreml" ? backend : "onnx";
|
|
3968
|
+
return backend === "openvino" || backend === "coreml" || backend === "edgetpu" ? backend : "onnx";
|
|
3934
3969
|
}
|
|
3935
3970
|
/** Map a backend string to a known RuntimeId, flooring to onnx. */
|
|
3936
3971
|
toRuntimeId(backend) {
|
|
3937
3972
|
return [
|
|
3938
3973
|
"onnx",
|
|
3939
3974
|
"openvino",
|
|
3940
|
-
"coreml"
|
|
3975
|
+
"coreml",
|
|
3976
|
+
"edgetpu"
|
|
3941
3977
|
].find((id) => id === backend) ?? "onnx";
|
|
3942
3978
|
}
|
|
3943
3979
|
/**
|
|
@@ -4600,35 +4636,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
4600
4636
|
} });
|
|
4601
4637
|
return { success: true };
|
|
4602
4638
|
}
|
|
4603
|
-
/** This executor's cluster node id (suffix-stripped, matching the runner). */
|
|
4604
|
-
ownNodeId() {
|
|
4605
|
-
const raw = this.addonCtx?.kernel?.localNodeId ?? "hub";
|
|
4606
|
-
return raw.includes("/") ? raw.split("/")[0] : raw;
|
|
4607
|
-
}
|
|
4608
|
-
/**
|
|
4609
|
-
* CB5 — resolve a shm `FrameHandle` to pixels zero-copy. Returns `null`
|
|
4610
|
-
* when:
|
|
4611
|
-
* - the handle is FOREIGN (its segment lives on another node — a local
|
|
4612
|
-
* `shm_open` would flood ENOENT; the runner only sends LOCAL handles, so
|
|
4613
|
-
* this is a defensive guard against an unexpected topology);
|
|
4614
|
-
* - the ring slot was recycled before the read (latest-wins drop) or the
|
|
4615
|
-
* segment could not be mapped.
|
|
4616
|
-
* A `null` degrades the caller to an empty `FrameResult` — the runner ships
|
|
4617
|
-
* pixels via `frame` as the fallback.
|
|
4618
|
-
*/
|
|
4619
|
-
resolveFrameHandle(handle) {
|
|
4620
|
-
if (handle.nodeId !== this.ownNodeId()) return null;
|
|
4621
|
-
if (!this.frameHandleReaders) this.frameHandleReaders = new FrameRingReaderCache(this.log);
|
|
4622
|
-
const decoded = this.frameHandleReaders.read(handle);
|
|
4623
|
-
if (!decoded) return null;
|
|
4624
|
-
return {
|
|
4625
|
-
data: decoded.data,
|
|
4626
|
-
width: decoded.width,
|
|
4627
|
-
height: decoded.height,
|
|
4628
|
-
format: decoded.format,
|
|
4629
|
-
timestamp: decoded.timestamp
|
|
4630
|
-
};
|
|
4631
|
-
}
|
|
4632
4639
|
/**
|
|
4633
4640
|
* Minimal detection-free `FrameResult` returned when a `frameHandle` read
|
|
4634
4641
|
* misses (recycled slot / foreign / unmappable). Shape-identical to a
|
|
@@ -4721,12 +4728,8 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
4721
4728
|
].filter((s) => s !== null);
|
|
4722
4729
|
if (sources.length === 0) throw new Error("runPipeline requires exactly one of: frame, frameHandle, image, imageBase64, referenceImage");
|
|
4723
4730
|
if (sources.length > 1) throw new Error(`runPipeline received conflicting image sources: ${sources.join(", ")}`);
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
handleFrame = this.resolveFrameHandle(input.frameHandle);
|
|
4727
|
-
if (!handleFrame) return this.emptyFrameHandleResult(input);
|
|
4728
|
-
}
|
|
4729
|
-
const runtimeFrame = input.frame ?? handleFrame ?? void 0;
|
|
4731
|
+
if (input.frameHandle) return this.emptyFrameHandleResult(input);
|
|
4732
|
+
const runtimeFrame = input.frame ?? void 0;
|
|
4730
4733
|
const decodeT0 = performance.now();
|
|
4731
4734
|
if (runtimeFrame) {
|
|
4732
4735
|
const frame = runtimeFrame;
|
|
@@ -5481,8 +5484,6 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
5481
5484
|
this.executor = null;
|
|
5482
5485
|
}
|
|
5483
5486
|
for (const id of Array.from(this.deviceProxies.keys())) this.releaseDeviceProxy(id);
|
|
5484
|
-
this.frameHandleReaders?.close();
|
|
5485
|
-
this.frameHandleReaders = null;
|
|
5486
5487
|
}
|
|
5487
5488
|
/**
|
|
5488
5489
|
* Resolve and cache a {@link DeviceProxy} for the given camera. Pins
|
|
@@ -6218,7 +6219,8 @@ var BACKEND_TO_FORMAT = {
|
|
|
6218
6219
|
cpu: "onnx",
|
|
6219
6220
|
coreml: "coreml",
|
|
6220
6221
|
openvino: "openvino",
|
|
6221
|
-
onnx: "onnx"
|
|
6222
|
+
onnx: "onnx",
|
|
6223
|
+
edgetpu: "tflite"
|
|
6222
6224
|
};
|
|
6223
6225
|
/**
|
|
6224
6226
|
* Every runtime the registry knows about, in offer order. Used only to build
|
|
@@ -6229,7 +6231,8 @@ var BACKEND_TO_FORMAT = {
|
|
|
6229
6231
|
var ALL_RUNTIME_IDS = [
|
|
6230
6232
|
"onnx",
|
|
6231
6233
|
"openvino",
|
|
6232
|
-
"coreml"
|
|
6234
|
+
"coreml",
|
|
6235
|
+
"edgetpu"
|
|
6233
6236
|
];
|
|
6234
6237
|
/**
|
|
6235
6238
|
* Narrow an arbitrary stored backend string to a known `RuntimeId`. Legacy or
|
|
@@ -6697,6 +6700,7 @@ var DetectionPipelineAddon = class DetectionPipelineAddon extends BaseAddon {
|
|
|
6697
6700
|
return {
|
|
6698
6701
|
npu: hw.npu ? { type: hw.npu.type } : null,
|
|
6699
6702
|
gpu: hw.gpu ? { type: hw.gpu.type } : null,
|
|
6703
|
+
coral: hw.coral ? { type: hw.coral.type } : null,
|
|
6700
6704
|
platform: hw.platform,
|
|
6701
6705
|
arch: hw.arch
|
|
6702
6706
|
};
|