@camstack/addon-pipeline 1.2.328 → 1.2.329
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/THIRD_PARTY_MODELS.md +2 -2
- package/dist/audio-analyzer/index.js +2 -2
- package/dist/audio-analyzer/index.mjs +2 -2
- package/dist/{default-detection-model-1SadEKsW.js → default-detection-model-ChH7Y219.js} +15 -5
- package/dist/{default-detection-model-CMeVTcPZ.mjs → default-detection-model-j0nBpRoB.mjs} +15 -5
- package/dist/detection-pipeline/index.js +414 -12
- package/dist/detection-pipeline/index.mjs +414 -12
- package/dist/{dist-Bpub2VcJ.mjs → dist-0HoA3wAi.mjs} +10 -1
- package/dist/{dist-wJO7mXeO.js → dist-BlIWhjnu.js} +10 -1
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-BCrqaejt.js → node-BPpVMnZy.js} +1 -1
- package/dist/{node-BjCSgD4M.mjs → node-HOMWRPzW.mjs} +1 -1
- package/dist/pipeline-runner/index.js +3 -3
- package/dist/pipeline-runner/index.mjs +3 -3
- package/dist/{process-memory-iUJuTpXs.js → process-memory-BW06vOIQ.js} +1 -1
- package/dist/{process-memory-BaKQ8u2G.mjs → process-memory-DuF8pa2w.mjs} +1 -1
- package/dist/recorder/index.js +2 -2
- package/dist/recorder/index.mjs +2 -2
- package/dist/{segment-demux-js-C5ez9LYG.mjs → segment-demux-js-BU2MXpln.mjs} +1 -1
- package/dist/{segment-demux-js-Opx6Hv9G.js → segment-demux-js-Dl52Zz8w.js} +1 -1
- package/dist/stream-broker/_stub.js +1 -1
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B94LgsV0.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-vNfS65In.mjs} +3 -3
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BPWYf4_O.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DfeHvW4k.mjs} +1 -1
- package/dist/stream-broker/demux-worker-child.js +1 -1
- package/dist/stream-broker/demux-worker-child.mjs +1 -1
- package/dist/stream-broker/{hostInit-xOx7AvgW.mjs → hostInit-Ciacp783.mjs} +3 -3
- package/dist/stream-broker/index.js +3 -3
- package/dist/stream-broker/index.mjs +3 -3
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/python/edgetpu_dequant.py +38 -1
- package/python/inference_pool.py +31 -17
- package/python/postprocessors/test_yolox_plate_edgetpu.py +126 -0
- package/python/postprocessors/test_yunet_edgetpu.py +149 -0
- package/python/postprocessors/testdata/yolox_plate_int8_outputs.json +1 -0
- package/python/postprocessors/testdata/yunet_int8_outputs.json +1 -0
- package/python/postprocessors/yolo.py +44 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { n as __require } from "../chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { An as hydrateSchema, Bn as array, Dt as loadContributionCapability, En as createEvent, F as PoolMemoryWatchdog, Fn as parseJsonUnknown, Ht as pipelineExecutorCapability, K as YAMNET_TO_MACRO, Kn as object, Lt as overlayClusterStepSettings, Pn as nodePin, Rn as sleep, Sn as BaseAddon, T as FILLABLE_STEP_MACRO, Tt as linkedLabelStepId, Xn as union, Yn as string, Yt as resolveClusterStepModelId, Zn as EventCategory, at as defaultDeviceFor$1, b as DEVICE_BACKEND_TO_FORMAT, bn as errMsg, cn as supportedRuntimes$1, d as CLUSTER_MODEL_SCOPED_STEPS, en as resolvePoolMemoryPolicy, ft as enumerateInferenceDevices, h as DEFAULT_CLUSTER_STEP_SETTINGS, lt as detectionPipelineCapability, n as APPLE_SA_TO_MACRO, nn as runtimeDevices$1, pt as evaluateZoneRules, rn as stepModelRunsOnFormat, zt as pickClusterStepSettings } from "../dist-
|
|
3
|
-
import { s as readProcessCost } from "../node-
|
|
4
|
-
import { _ as getStep, a as buildSubtreeCanRun, b as landmarkPrecisionVerdict, c as macroGateVerdict, g as getDefaultModelForFormat, h as ALL_STEPS, i as mergeCustomModels, m as ALL_PIPELINE_STEPS, n as resolveDefaultDetectionModel, r as CustomModelCatalog, u as localFrameRegistry, v as getStepDefinition, x as resolveModelDefaultConfidence, y as resolveModelForFormat } from "../default-detection-model-
|
|
2
|
+
import { An as hydrateSchema, Bn as array, Dt as loadContributionCapability, En as createEvent, F as PoolMemoryWatchdog, Fn as parseJsonUnknown, Ht as pipelineExecutorCapability, K as YAMNET_TO_MACRO, Kn as object, Lt as overlayClusterStepSettings, Pn as nodePin, Rn as sleep, Sn as BaseAddon, St as hfModelUrl, T as FILLABLE_STEP_MACRO, Tt as linkedLabelStepId, Xn as union, Yn as string, Yt as resolveClusterStepModelId, Zn as EventCategory, at as defaultDeviceFor$1, b as DEVICE_BACKEND_TO_FORMAT, bn as errMsg, cn as supportedRuntimes$1, d as CLUSTER_MODEL_SCOPED_STEPS, en as resolvePoolMemoryPolicy, ft as enumerateInferenceDevices, h as DEFAULT_CLUSTER_STEP_SETTINGS, lt as detectionPipelineCapability, n as APPLE_SA_TO_MACRO, nn as runtimeDevices$1, pt as evaluateZoneRules, rn as stepModelRunsOnFormat, zt as pickClusterStepSettings } from "../dist-0HoA3wAi.mjs";
|
|
3
|
+
import { s as readProcessCost } from "../node-HOMWRPzW.mjs";
|
|
4
|
+
import { _ as getStep, a as buildSubtreeCanRun, b as landmarkPrecisionVerdict, c as macroGateVerdict, g as getDefaultModelForFormat, h as ALL_STEPS, i as mergeCustomModels, m as ALL_PIPELINE_STEPS, n as resolveDefaultDetectionModel, r as CustomModelCatalog, u as localFrameRegistry, v as getStepDefinition, x as resolveModelDefaultConfidence, y as resolveModelForFormat } from "../default-detection-model-j0nBpRoB.mjs";
|
|
5
5
|
import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
6
|
-
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-
|
|
6
|
+
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DuF8pa2w.mjs";
|
|
7
7
|
import * as os from "node:os";
|
|
8
8
|
import * as fs from "node:fs";
|
|
9
9
|
import * as path$1 from "node:path";
|
|
@@ -2809,6 +2809,8 @@ var PipelineModelManager = class {
|
|
|
2809
2809
|
stepId,
|
|
2810
2810
|
modelId,
|
|
2811
2811
|
poolIndex: index,
|
|
2812
|
+
path: config.path,
|
|
2813
|
+
...settings !== void 0 ? { settings } : {},
|
|
2812
2814
|
lruTick: ++this.lruClock,
|
|
2813
2815
|
decode
|
|
2814
2816
|
};
|
|
@@ -2816,6 +2818,56 @@ var PipelineModelManager = class {
|
|
|
2816
2818
|
return entry;
|
|
2817
2819
|
}
|
|
2818
2820
|
/**
|
|
2821
|
+
* Reload every resident slot whose model FILE is no longer the one
|
|
2822
|
+
* `buildConfig` names — a Coral pool that switched co-compiled set (D724).
|
|
2823
|
+
* The new slot is loaded BEFORE the old one is unloaded and the entry is
|
|
2824
|
+
* replaced in between, so a lookup always finds a loaded index. Returns the
|
|
2825
|
+
* `(step, model)` pairs reloaded. A failed reload keeps the old slot (it
|
|
2826
|
+
* still serves, from the file it was loaded from) and is logged.
|
|
2827
|
+
*/
|
|
2828
|
+
async reloadChangedPaths() {
|
|
2829
|
+
const reloaded = [];
|
|
2830
|
+
for (const [stepId, perStep] of this.loaded) for (const entry of perStep.values()) {
|
|
2831
|
+
const config = this.source.buildConfig(stepId, entry.modelId, entry.settings);
|
|
2832
|
+
if (config.path === entry.path) continue;
|
|
2833
|
+
const index = this.pool.allocateIndex();
|
|
2834
|
+
try {
|
|
2835
|
+
await this.pool.loadModel(index, config);
|
|
2836
|
+
} catch (err) {
|
|
2837
|
+
this.pool.releaseIndex(index);
|
|
2838
|
+
this.log.error("Step variant reload from another model file failed — the old file keeps serving", { meta: {
|
|
2839
|
+
step: stepId,
|
|
2840
|
+
modelId: entry.modelId,
|
|
2841
|
+
deviceKey: this.deviceKey,
|
|
2842
|
+
from: entry.path,
|
|
2843
|
+
to: config.path,
|
|
2844
|
+
error: err instanceof Error ? err.message : String(err)
|
|
2845
|
+
} });
|
|
2846
|
+
continue;
|
|
2847
|
+
}
|
|
2848
|
+
perStep.set(entry.modelId, {
|
|
2849
|
+
...entry,
|
|
2850
|
+
poolIndex: index,
|
|
2851
|
+
path: config.path,
|
|
2852
|
+
decode: poolDecodeSettingsOf(config)
|
|
2853
|
+
});
|
|
2854
|
+
await this.pool.unloadModel(entry.poolIndex);
|
|
2855
|
+
this.log.info("Step variant reloaded from another model file", { meta: {
|
|
2856
|
+
step: stepId,
|
|
2857
|
+
modelId: entry.modelId,
|
|
2858
|
+
deviceKey: this.deviceKey,
|
|
2859
|
+
from: entry.path,
|
|
2860
|
+
to: config.path,
|
|
2861
|
+
poolIndex: index
|
|
2862
|
+
} });
|
|
2863
|
+
reloaded.push({
|
|
2864
|
+
stepId,
|
|
2865
|
+
modelId: entry.modelId
|
|
2866
|
+
});
|
|
2867
|
+
}
|
|
2868
|
+
return reloaded;
|
|
2869
|
+
}
|
|
2870
|
+
/**
|
|
2819
2871
|
* Push a retuned decode setting into ONE already-loaded slot.
|
|
2820
2872
|
*
|
|
2821
2873
|
* Scope is the point: `reconfigure` names a single pool index, so a slider
|
|
@@ -2974,6 +3026,251 @@ function deviceKeyOf(engine) {
|
|
|
2974
3026
|
return engine.device ? `${engine.backend}:${engine.device}` : engine.backend;
|
|
2975
3027
|
}
|
|
2976
3028
|
//#endregion
|
|
3029
|
+
//#region src/detection-pipeline/engine/coral-cocompiled-set.ts
|
|
3030
|
+
var ROOT_DETECTOR_STEP_ID = "object-detection";
|
|
3031
|
+
/** The models a dispatch places on the pool that runs it: every enabled video step. */
|
|
3032
|
+
function placedModelsOf(steps) {
|
|
3033
|
+
return flattenEnabledVideoSteps(steps).map((s) => ({
|
|
3034
|
+
stepId: s.addonId,
|
|
3035
|
+
modelId: s.modelId
|
|
3036
|
+
}));
|
|
3037
|
+
}
|
|
3038
|
+
var sameModel = (a, b) => a.stepId === b.stepId && a.modelId === b.modelId;
|
|
3039
|
+
/**
|
|
3040
|
+
* The set for `placed`, or why there is none.
|
|
3041
|
+
*
|
|
3042
|
+
* 1. A set that reserves the cache for the root detector is eligible only when
|
|
3043
|
+
* the root is placed here, and a rootless set only when it is not: a root
|
|
3044
|
+
* set on a pool without the root wastes the cache the root would have had,
|
|
3045
|
+
* and a rootless set beside a root makes the root swap.
|
|
3046
|
+
* 2. A set must stand for at least two placed models — one model alone is
|
|
3047
|
+
* better off with the whole cache (its separately compiled file).
|
|
3048
|
+
* 3. Most placed models covered wins; then the set with fewest members nobody
|
|
3049
|
+
* placed (they hold cache for nothing); then declaration order.
|
|
3050
|
+
*/
|
|
3051
|
+
function selectCoCompiledSet(placed, sets) {
|
|
3052
|
+
if (placed.length === 0) return {
|
|
3053
|
+
kind: "separate",
|
|
3054
|
+
reason: "nothing-placed"
|
|
3055
|
+
};
|
|
3056
|
+
if (placed.length === 1) return {
|
|
3057
|
+
kind: "separate",
|
|
3058
|
+
reason: "single-model"
|
|
3059
|
+
};
|
|
3060
|
+
const hostsRoot = placed.some((p) => p.stepId === ROOT_DETECTOR_STEP_ID);
|
|
3061
|
+
let best = null;
|
|
3062
|
+
for (const set of sets) {
|
|
3063
|
+
if (set.hostsRoot !== hostsRoot) continue;
|
|
3064
|
+
const covered = placed.filter((p) => set.members.some((m) => sameModel(m, p)));
|
|
3065
|
+
if (covered.length < 2) continue;
|
|
3066
|
+
const idle = set.members.length - covered.length;
|
|
3067
|
+
if (best === null || covered.length > best.covered.length || covered.length === best.covered.length && idle < best.idle) best = {
|
|
3068
|
+
set,
|
|
3069
|
+
covered,
|
|
3070
|
+
idle
|
|
3071
|
+
};
|
|
3072
|
+
}
|
|
3073
|
+
if (best === null) return {
|
|
3074
|
+
kind: "separate",
|
|
3075
|
+
reason: "no-set-covers-two"
|
|
3076
|
+
};
|
|
3077
|
+
const { set, covered } = best;
|
|
3078
|
+
return {
|
|
3079
|
+
kind: "set",
|
|
3080
|
+
set,
|
|
3081
|
+
covered,
|
|
3082
|
+
uncovered: placed.filter((p) => !covered.some((c) => sameModel(c, p)))
|
|
3083
|
+
};
|
|
3084
|
+
}
|
|
3085
|
+
/** The member a selection loads `(stepId, modelId)` from, or `null` (its own `formats.tflite`). */
|
|
3086
|
+
function setMemberFor(selection, stepId, modelId) {
|
|
3087
|
+
if (selection.kind !== "set") return null;
|
|
3088
|
+
return selection.set.members.find((m) => m.stepId === stepId && m.modelId === modelId) ?? null;
|
|
3089
|
+
}
|
|
3090
|
+
/**
|
|
3091
|
+
* `entry` with its `tflite` build pointed at the set's file. Everything else —
|
|
3092
|
+
* labels, postprocessor, input contract, licence — is the entry's own: a
|
|
3093
|
+
* member is the same model, compiled together with others.
|
|
3094
|
+
*/
|
|
3095
|
+
function withSetBuild(entry, member) {
|
|
3096
|
+
return {
|
|
3097
|
+
...entry,
|
|
3098
|
+
formats: {
|
|
3099
|
+
...entry.formats,
|
|
3100
|
+
tflite: {
|
|
3101
|
+
url: member.url,
|
|
3102
|
+
sizeMB: member.sizeMB,
|
|
3103
|
+
runtimes: ["python"]
|
|
3104
|
+
}
|
|
3105
|
+
}
|
|
3106
|
+
};
|
|
3107
|
+
}
|
|
3108
|
+
/** Identity of a selection for change detection: the set AND what it leaves out. */
|
|
3109
|
+
var selectionKey = (s) => s.kind === "set" ? `${s.set.id}|${s.uncovered.map((u) => `${u.stepId}/${u.modelId}`).toSorted().join(",")}` : `separate:${s.reason}`;
|
|
3110
|
+
/**
|
|
3111
|
+
* The placement of ONE Coral pool and the set it loads. Lives exactly as long
|
|
3112
|
+
* as the pool (the factory owns it).
|
|
3113
|
+
*/
|
|
3114
|
+
var CoralSetPlanner = class {
|
|
3115
|
+
sets;
|
|
3116
|
+
placed = [];
|
|
3117
|
+
current = {
|
|
3118
|
+
kind: "separate",
|
|
3119
|
+
reason: "nothing-placed"
|
|
3120
|
+
};
|
|
3121
|
+
constructor(sets) {
|
|
3122
|
+
this.sets = sets;
|
|
3123
|
+
}
|
|
3124
|
+
/** Add the models a dispatch places on this pool; say whether the set changed. */
|
|
3125
|
+
note(models) {
|
|
3126
|
+
let grew = false;
|
|
3127
|
+
for (const m of models) {
|
|
3128
|
+
if (this.placed.some((p) => sameModel(p, m))) continue;
|
|
3129
|
+
this.placed.push({
|
|
3130
|
+
stepId: m.stepId,
|
|
3131
|
+
modelId: m.modelId
|
|
3132
|
+
});
|
|
3133
|
+
grew = true;
|
|
3134
|
+
}
|
|
3135
|
+
if (!grew) return { kind: "unchanged" };
|
|
3136
|
+
const next = selectCoCompiledSet(this.placed, this.sets);
|
|
3137
|
+
if (selectionKey(next) === selectionKey(this.current)) {
|
|
3138
|
+
this.current = next;
|
|
3139
|
+
return { kind: "unchanged" };
|
|
3140
|
+
}
|
|
3141
|
+
const from = this.current;
|
|
3142
|
+
this.current = next;
|
|
3143
|
+
return {
|
|
3144
|
+
kind: "changed",
|
|
3145
|
+
from,
|
|
3146
|
+
to: next,
|
|
3147
|
+
placed: [...this.placed]
|
|
3148
|
+
};
|
|
3149
|
+
}
|
|
3150
|
+
selection() {
|
|
3151
|
+
return this.current;
|
|
3152
|
+
}
|
|
3153
|
+
/** `entry` as this pool must load it: from the set when the set stands for it. */
|
|
3154
|
+
entryFor(stepId, entry) {
|
|
3155
|
+
const member = setMemberFor(this.current, stepId, entry.id);
|
|
3156
|
+
return member === null ? entry : withSetBuild(entry, member);
|
|
3157
|
+
}
|
|
3158
|
+
};
|
|
3159
|
+
//#endregion
|
|
3160
|
+
//#region src/detection-pipeline/registry/edgetpu-cocompiled-sets.ts
|
|
3161
|
+
/**
|
|
3162
|
+
* Co-compiled Edge TPU sets — pool-level artifacts, not models (D724).
|
|
3163
|
+
*
|
|
3164
|
+
* A Coral holds ~6.9 MiB of parameter cache. Two separately compiled models
|
|
3165
|
+
* carry two different cache tokens, so every alternation between them on one
|
|
3166
|
+
* Coral flushes the cache and re-streams the incoming model's parameters over
|
|
3167
|
+
* USB (D710). `edgetpu_compiler` given several models at once allocates the
|
|
3168
|
+
* cache between them, in command-line order, under ONE token: loaded from the
|
|
3169
|
+
* same set, they never evict each other — whatever does not fit is streamed on
|
|
3170
|
+
* every invoke of THAT model instead.
|
|
3171
|
+
*
|
|
3172
|
+
* Each member is the SAME model as its catalog entry's `formats.tflite` (same
|
|
3173
|
+
* `modelId`, same int8 graph, same labels and licence record), compiled
|
|
3174
|
+
* together with the other members (D710: a Coral build is a format of the
|
|
3175
|
+
* survivor; the set is where it is placed, not a new model). A Coral pool picks
|
|
3176
|
+
* at most one set from the models placed on it (`coral-cocompiled-set.ts`) and
|
|
3177
|
+
* falls back to the separately compiled `formats.tflite` for everything else.
|
|
3178
|
+
*
|
|
3179
|
+
* Built by `scripts/build-edgetpu-sets.py` (compile order = `members` order =
|
|
3180
|
+
* cache priority) and hosted under `edgetpuSets/<id>/`. Only sets whose
|
|
3181
|
+
* measured cost is acceptable are listed here: a set that would make the root
|
|
3182
|
+
* detector stream parameters on every frame (root + YuNet at 640: the root
|
|
3183
|
+
* keeps 3.34 of its 6.39 MiB, YuNet's activations take the rest) is
|
|
3184
|
+
* deliberately absent.
|
|
3185
|
+
*/
|
|
3186
|
+
var HF_REPO = "camstack/camstack-models";
|
|
3187
|
+
var setFile = (setId, file) => hfModelUrl(HF_REPO, `edgetpuSets/${setId}/${setId}__${file}`);
|
|
3188
|
+
var SSD = "ssd-mobilenet-v2-coco-edgetpu";
|
|
3189
|
+
var YUNET = "yunet-2023mar";
|
|
3190
|
+
var YOLOX = "yolox-tiny-plate";
|
|
3191
|
+
var BIRD = "bird-classifier";
|
|
3192
|
+
var EDGETPU_COCOMPILED_SETS = [
|
|
3193
|
+
{
|
|
3194
|
+
id: "root-plate-bird",
|
|
3195
|
+
hostsRoot: true,
|
|
3196
|
+
members: [
|
|
3197
|
+
{
|
|
3198
|
+
stepId: "object-detection",
|
|
3199
|
+
modelId: SSD,
|
|
3200
|
+
url: setFile("root-plate-bird", "ssd_mobilenet_v2_coco_quant_postprocess_edgetpu.tflite"),
|
|
3201
|
+
sizeMB: 6.9,
|
|
3202
|
+
onChipMiB: 6.39,
|
|
3203
|
+
streamedMiB: 0
|
|
3204
|
+
},
|
|
3205
|
+
{
|
|
3206
|
+
stepId: "plate-detection",
|
|
3207
|
+
modelId: YOLOX,
|
|
3208
|
+
url: setFile("root-plate-bird", "camstack-yolox-tiny-plate_int8_edgetpu.tflite"),
|
|
3209
|
+
sizeMB: 6.9,
|
|
3210
|
+
onChipMiB: .08,
|
|
3211
|
+
streamedMiB: 5.41
|
|
3212
|
+
},
|
|
3213
|
+
{
|
|
3214
|
+
stepId: "bird-classifier",
|
|
3215
|
+
modelId: BIRD,
|
|
3216
|
+
url: setFile("root-plate-bird", "mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite"),
|
|
3217
|
+
sizeMB: 4.9,
|
|
3218
|
+
onChipMiB: 0,
|
|
3219
|
+
streamedMiB: 4.54
|
|
3220
|
+
}
|
|
3221
|
+
]
|
|
3222
|
+
},
|
|
3223
|
+
{
|
|
3224
|
+
id: "face-plate-bird",
|
|
3225
|
+
hostsRoot: false,
|
|
3226
|
+
members: [
|
|
3227
|
+
{
|
|
3228
|
+
stepId: "face-detection",
|
|
3229
|
+
modelId: YUNET,
|
|
3230
|
+
url: setFile("face-plate-bird", "camstack-yunet-2023mar_int8_edgetpu.tflite"),
|
|
3231
|
+
sizeMB: .7,
|
|
3232
|
+
onChipMiB: .11,
|
|
3233
|
+
streamedMiB: 0
|
|
3234
|
+
},
|
|
3235
|
+
{
|
|
3236
|
+
stepId: "plate-detection",
|
|
3237
|
+
modelId: YOLOX,
|
|
3238
|
+
url: setFile("face-plate-bird", "camstack-yolox-tiny-plate_int8_edgetpu.tflite"),
|
|
3239
|
+
sizeMB: 6.9,
|
|
3240
|
+
onChipMiB: 3.23,
|
|
3241
|
+
streamedMiB: 2.27
|
|
3242
|
+
},
|
|
3243
|
+
{
|
|
3244
|
+
stepId: "bird-classifier",
|
|
3245
|
+
modelId: BIRD,
|
|
3246
|
+
url: setFile("face-plate-bird", "mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite"),
|
|
3247
|
+
sizeMB: 4.9,
|
|
3248
|
+
onChipMiB: 0,
|
|
3249
|
+
streamedMiB: 4.54
|
|
3250
|
+
}
|
|
3251
|
+
]
|
|
3252
|
+
},
|
|
3253
|
+
{
|
|
3254
|
+
id: "plate-bird",
|
|
3255
|
+
hostsRoot: false,
|
|
3256
|
+
members: [{
|
|
3257
|
+
stepId: "plate-detection",
|
|
3258
|
+
modelId: YOLOX,
|
|
3259
|
+
url: setFile("plate-bird", "camstack-yolox-tiny-plate_int8_edgetpu.tflite"),
|
|
3260
|
+
sizeMB: 6.9,
|
|
3261
|
+
onChipMiB: 5.55,
|
|
3262
|
+
streamedMiB: 0
|
|
3263
|
+
}, {
|
|
3264
|
+
stepId: "bird-classifier",
|
|
3265
|
+
modelId: BIRD,
|
|
3266
|
+
url: setFile("plate-bird", "mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite"),
|
|
3267
|
+
sizeMB: 4.1,
|
|
3268
|
+
onChipMiB: .92,
|
|
3269
|
+
streamedMiB: 2.8
|
|
3270
|
+
}]
|
|
3271
|
+
}
|
|
3272
|
+
];
|
|
3273
|
+
//#endregion
|
|
2977
3274
|
//#region src/detection-pipeline/engine/engine-factory.ts
|
|
2978
3275
|
var BACKEND_TO_POOL_RUNTIME = {
|
|
2979
3276
|
coreml: "coreml",
|
|
@@ -3067,11 +3364,45 @@ var EngineFactory = class {
|
|
|
3067
3364
|
* trying to be.
|
|
3068
3365
|
*/
|
|
3069
3366
|
resolvedProvisioning;
|
|
3367
|
+
/**
|
|
3368
|
+
* A Coral pool's placement and the co-compiled set it loads (D724); `null`
|
|
3369
|
+
* on every other runtime. Lives exactly as long as this factory — a new
|
|
3370
|
+
* pool starts from nothing placed.
|
|
3371
|
+
*/
|
|
3372
|
+
coralSets;
|
|
3070
3373
|
constructor(opts) {
|
|
3071
3374
|
this.opts = opts;
|
|
3072
3375
|
this.log = opts.logger;
|
|
3073
3376
|
this.deviceKey = deviceKeyOf(opts.engine);
|
|
3074
3377
|
this.resolvedProvisioning = resolvePoolProvisioning(opts.engine, opts.provisioning);
|
|
3378
|
+
this.coralSets = BACKEND_TO_POOL_RUNTIME[opts.engine.backend] === "edgetpu" ? new CoralSetPlanner(opts.coCompiledSets ?? EDGETPU_COCOMPILED_SETS) : null;
|
|
3379
|
+
}
|
|
3380
|
+
/**
|
|
3381
|
+
* Record the models a dispatch places on this pool. On a Coral pool the
|
|
3382
|
+
* answer says whether the co-compiled set it loads from changed; on any
|
|
3383
|
+
* other pool nothing is placed and nothing changes.
|
|
3384
|
+
*/
|
|
3385
|
+
notePlacement(models) {
|
|
3386
|
+
return this.coralSets?.note(models) ?? { kind: "unchanged" };
|
|
3387
|
+
}
|
|
3388
|
+
/** The co-compiled set this pool loads from, or why none (`null`: not a Coral pool). */
|
|
3389
|
+
coralSetSelection() {
|
|
3390
|
+
return this.coralSets?.selection() ?? null;
|
|
3391
|
+
}
|
|
3392
|
+
/**
|
|
3393
|
+
* The catalog entry as THIS pool must download and load it: on a Coral pool
|
|
3394
|
+
* whose set stands for the model, the `tflite` build is the set's file.
|
|
3395
|
+
* Every other entry is returned unchanged.
|
|
3396
|
+
*/
|
|
3397
|
+
entryForPool(stepId, entry) {
|
|
3398
|
+
return this.coralSets?.entryFor(stepId, entry) ?? entry;
|
|
3399
|
+
}
|
|
3400
|
+
/**
|
|
3401
|
+
* Reload every resident model whose file this pool no longer names — after
|
|
3402
|
+
* the Coral set changed. The caller has already downloaded the new files.
|
|
3403
|
+
*/
|
|
3404
|
+
async reloadChangedModelFiles() {
|
|
3405
|
+
return this.poolManager?.reloadChangedPaths() ?? [];
|
|
3075
3406
|
}
|
|
3076
3407
|
/**
|
|
3077
3408
|
* The provisioning this factory's pool runs with — resolved from the pool's
|
|
@@ -3333,6 +3664,7 @@ var EngineFactory = class {
|
|
|
3333
3664
|
stepSettings,
|
|
3334
3665
|
device: this.opts.engine.device,
|
|
3335
3666
|
resolveCustomModel: this.opts.resolveCustomModel,
|
|
3667
|
+
entryForPool: (sid, entry) => this.entryForPool(sid, entry),
|
|
3336
3668
|
onClassMapDrop: ({ stepId: sid, modelId: mid, unmappedLabels }) => {
|
|
3337
3669
|
const key = `${sid}::${mid}`;
|
|
3338
3670
|
if (this.classMapDropLogged.has(key)) return;
|
|
@@ -3358,8 +3690,9 @@ var EngineFactory = class {
|
|
|
3358
3690
|
function buildPoolModelConfigForStep(inputs) {
|
|
3359
3691
|
const { stepId, modelId, poolRuntime, modelsDir } = inputs;
|
|
3360
3692
|
const def = getStepDefinition(stepId);
|
|
3361
|
-
const
|
|
3362
|
-
if (!
|
|
3693
|
+
const resolvedEntry = def.models.find((m) => m.id === modelId) ?? inputs.resolveCustomModel?.(stepId, modelId);
|
|
3694
|
+
if (!resolvedEntry) throw new Error(`Model "${modelId}" not found in step "${stepId}" catalog (static or custom registry)`);
|
|
3695
|
+
const modelEntry = inputs.entryForPool?.(stepId, resolvedEntry) ?? resolvedEntry;
|
|
3363
3696
|
const format = RUNTIME_TO_FORMAT[poolRuntime];
|
|
3364
3697
|
if (!format) throw new Error(`No format mapping for pool runtime "${poolRuntime}"`);
|
|
3365
3698
|
const dropWarning = collectClassMapDropWarning(def, modelEntry);
|
|
@@ -9425,6 +9758,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9425
9758
|
*/
|
|
9426
9759
|
async loadDispatchModels(steps, factory, format, context, policy) {
|
|
9427
9760
|
const failures = [];
|
|
9761
|
+
if (factory !== null) await this.noteCoralPlacement(steps, factory, format, context);
|
|
9428
9762
|
const walk = async (nodes, root) => {
|
|
9429
9763
|
for (const step of nodes) {
|
|
9430
9764
|
if (!step.enabled || step.slot === "audio-classifier") continue;
|
|
@@ -9449,6 +9783,69 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9449
9783
|
await walk(steps, true);
|
|
9450
9784
|
return failures;
|
|
9451
9785
|
}
|
|
9786
|
+
/**
|
|
9787
|
+
* Tell a Coral pool which models this dispatch places on it, and act on a
|
|
9788
|
+
* change of the co-compiled set it loads from (D724): download the set's
|
|
9789
|
+
* files for the models already resident and reload them — queued behind the
|
|
9790
|
+
* pool's other loads, so nothing loads from the old file meanwhile. Logged
|
|
9791
|
+
* once per change, tagged with the camera whose dispatch moved it.
|
|
9792
|
+
*/
|
|
9793
|
+
async noteCoralPlacement(steps, factory, format, context) {
|
|
9794
|
+
const change = factory.notePlacement(placedModelsOf(steps));
|
|
9795
|
+
if (change.kind === "unchanged") return;
|
|
9796
|
+
const deviceKey = context.deviceKey ?? deviceKeyOf(this.currentEngine);
|
|
9797
|
+
const tags = context.deviceId !== void 0 ? { tags: { deviceId: context.deviceId } } : {};
|
|
9798
|
+
const placed = change.placed.map((p) => `${p.stepId}/${p.modelId}`);
|
|
9799
|
+
if (change.to.kind === "set") this.log.info("Coral pool loads a co-compiled set — the models placed on it share the parameter cache", {
|
|
9800
|
+
...tags,
|
|
9801
|
+
meta: {
|
|
9802
|
+
deviceKey,
|
|
9803
|
+
set: change.to.set.id,
|
|
9804
|
+
placed,
|
|
9805
|
+
fromSet: change.to.covered.map((p) => `${p.stepId}/${p.modelId}`),
|
|
9806
|
+
separatelyCompiled: change.to.uncovered.map((p) => `${p.stepId}/${p.modelId}`),
|
|
9807
|
+
previous: change.from.kind === "set" ? change.from.set.id : null
|
|
9808
|
+
}
|
|
9809
|
+
});
|
|
9810
|
+
else if (change.to.reason === "no-set-covers-two") this.log.warn("Coral pool has no co-compiled set for the models placed on it — each is compiled alone, so they evict each other from the parameter cache on every alternation", {
|
|
9811
|
+
...tags,
|
|
9812
|
+
meta: {
|
|
9813
|
+
deviceKey,
|
|
9814
|
+
placed,
|
|
9815
|
+
previous: change.from.kind === "set" ? change.from.set.id : null,
|
|
9816
|
+
hint: "keep the extra step off this Coral with its jumpDeviceKey, or place a combination a published set covers"
|
|
9817
|
+
}
|
|
9818
|
+
});
|
|
9819
|
+
const pool = factory;
|
|
9820
|
+
const previous = this.modelLoadTail.get(pool) ?? Promise.resolve();
|
|
9821
|
+
const tail = (async () => {
|
|
9822
|
+
await previous;
|
|
9823
|
+
for (const loaded of factory.listLoaded()) {
|
|
9824
|
+
const resolved = await this.resolveModelEntry(loaded.stepId, loaded.modelId);
|
|
9825
|
+
if (resolved === void 0) continue;
|
|
9826
|
+
const entry = factory.entryForPool(loaded.stepId, resolved);
|
|
9827
|
+
if (!isModelDownloaded(this.modelsDir, entry, format)) await this.downloadWithRetry(entry, format, 3);
|
|
9828
|
+
}
|
|
9829
|
+
const reloaded = await factory.reloadChangedModelFiles();
|
|
9830
|
+
if (reloaded.length > 0) this.log.info("Coral pool reloaded its resident models from the new set", {
|
|
9831
|
+
...tags,
|
|
9832
|
+
meta: {
|
|
9833
|
+
deviceKey,
|
|
9834
|
+
reloaded: reloaded.map((r) => `${r.stepId}/${r.modelId}`)
|
|
9835
|
+
}
|
|
9836
|
+
});
|
|
9837
|
+
})().catch((err) => {
|
|
9838
|
+
this.log.error("Coral pool could not move its resident models to the new set — they keep serving from the old files", {
|
|
9839
|
+
...tags,
|
|
9840
|
+
meta: {
|
|
9841
|
+
deviceKey,
|
|
9842
|
+
error: errMsg(err)
|
|
9843
|
+
}
|
|
9844
|
+
});
|
|
9845
|
+
});
|
|
9846
|
+
this.modelLoadTail.set(pool, tail);
|
|
9847
|
+
await tail;
|
|
9848
|
+
}
|
|
9452
9849
|
/** Ensure all models needed by steps are downloaded and loaded in the engine pool.
|
|
9453
9850
|
* `factory`/`format` default to the node's engine; a per-device dispatch passes
|
|
9454
9851
|
* that device's factory + format (Phase 2 multi-device). `context` names the
|
|
@@ -9546,7 +9943,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9546
9943
|
const refusal = this.loadRefusal(pool, deviceKey, models);
|
|
9547
9944
|
if (refusal !== null) throw refusal;
|
|
9548
9945
|
try {
|
|
9549
|
-
await this.downloadNeededModels(needed, format);
|
|
9946
|
+
await this.downloadNeededModels(needed, format, factory);
|
|
9550
9947
|
this.log.info("Loading additional models for benchmark", { meta: {
|
|
9551
9948
|
count: needed.length,
|
|
9552
9949
|
models,
|
|
@@ -9610,16 +10007,21 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
9610
10007
|
});
|
|
9611
10008
|
}
|
|
9612
10009
|
/** Download any model of `needed` missing in `format` (the device's). */
|
|
9613
|
-
async downloadNeededModels(needed, format) {
|
|
10010
|
+
async downloadNeededModels(needed, format, factory = null) {
|
|
9614
10011
|
for (const step of needed) try {
|
|
9615
|
-
await this.ensureStepModelArtifact(step, format);
|
|
10012
|
+
await this.ensureStepModelArtifact(step, format, factory);
|
|
9616
10013
|
} catch (err) {
|
|
9617
10014
|
throw new StepModelArtifactError(step.addonId, step.modelId, err);
|
|
9618
10015
|
}
|
|
9619
10016
|
}
|
|
9620
|
-
/**
|
|
9621
|
-
|
|
9622
|
-
|
|
10017
|
+
/**
|
|
10018
|
+
* Make one step's model artifact present on disk for `format`, or say why it
|
|
10019
|
+
* cannot be. The entry is the one `factory`'s pool will LOAD — on a Coral
|
|
10020
|
+
* pool, a co-compiled set's file when the set stands for the model (D724).
|
|
10021
|
+
*/
|
|
10022
|
+
async ensureStepModelArtifact(step, format, factory = null) {
|
|
10023
|
+
const resolved = await this.resolveModelEntry(step.addonId, step.modelId);
|
|
10024
|
+
const modelEntry = resolved && factory !== null ? factory.entryForPool(step.addonId, resolved) : resolved;
|
|
9623
10025
|
if (modelEntry && !isModelDownloaded(this.modelsDir, modelEntry, format)) {
|
|
9624
10026
|
if (modelEntry.formats[format] === void 0) throw new Error(`Model "${modelEntry.id}" has no ${format} format build (available: ${Object.keys(modelEntry.formats).join(", ") || "none"}) — not retrying a permanent format mismatch`);
|
|
9625
10027
|
if (modelEntry.formats[format]?.url.startsWith("camstack-local://") === true) throw new Error(`Custom model "${modelEntry.id}" (${format}) is not present in this node's models directory — distribute it to this node from Model Studio before selecting it here`);
|
|
@@ -21616,6 +21616,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
21616
21616
|
"stream-offline",
|
|
21617
21617
|
"node-online",
|
|
21618
21618
|
"node-offline",
|
|
21619
|
+
"node-restarting",
|
|
21620
|
+
"node-updating",
|
|
21619
21621
|
"node-inference-unavailable",
|
|
21620
21622
|
"detection-blind",
|
|
21621
21623
|
"addon-crash-loop",
|
|
@@ -35057,7 +35059,8 @@ object({
|
|
|
35057
35059
|
* writes this slice (not even a boot seed), and neither does the runner's
|
|
35058
35060
|
* phase machine: its phase is "a session is attached" for every on-motion
|
|
35059
35061
|
* session, not motion, and it now has its own `DetectionPhaseTransition`.
|
|
35060
|
-
* A provider's `isDetected`
|
|
35062
|
+
* A provider's `isDetected` and `getStatus` answer from the hub's slice
|
|
35063
|
+
* (`hubMotionNativeProvider`).
|
|
35061
35064
|
* - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
|
|
35062
35065
|
* imports) — the provider pushes both edges itself, from the upstream
|
|
35063
35066
|
* system's own state change. That is the sensor's own fact.
|
|
@@ -52176,6 +52179,8 @@ new Map(Object.entries({
|
|
|
52176
52179
|
"detection-blind": "device-events",
|
|
52177
52180
|
"node-online": "system",
|
|
52178
52181
|
"node-offline": "system",
|
|
52182
|
+
"node-restarting": "system",
|
|
52183
|
+
"node-updating": "system",
|
|
52179
52184
|
"node-inference-unavailable": "system",
|
|
52180
52185
|
"addon-crash-loop": "system",
|
|
52181
52186
|
"addon-update-available": "system",
|
|
@@ -52253,6 +52258,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
52253
52258
|
kinds: [
|
|
52254
52259
|
"node-offline",
|
|
52255
52260
|
"node-online",
|
|
52261
|
+
"node-restarting",
|
|
52256
52262
|
"node-inference-unavailable"
|
|
52257
52263
|
]
|
|
52258
52264
|
},
|
|
@@ -52274,6 +52280,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
52274
52280
|
label: "Server & container updates",
|
|
52275
52281
|
kinds: [
|
|
52276
52282
|
"server-update-available",
|
|
52283
|
+
"node-updating",
|
|
52277
52284
|
"server-updated",
|
|
52278
52285
|
"wrapper-update-available"
|
|
52279
52286
|
]
|
|
@@ -52421,6 +52428,7 @@ var STATE_SUMMARY_SECTION_VARS = [
|
|
|
52421
52428
|
kinds: [
|
|
52422
52429
|
"node-offline",
|
|
52423
52430
|
"node-online",
|
|
52431
|
+
"node-restarting",
|
|
52424
52432
|
"node-inference-unavailable"
|
|
52425
52433
|
]
|
|
52426
52434
|
},
|
|
@@ -52442,6 +52450,7 @@ var STATE_SUMMARY_SECTION_VARS = [
|
|
|
52442
52450
|
example: "server 1.2.377 → 1.2.378",
|
|
52443
52451
|
kinds: [
|
|
52444
52452
|
"server-update-available",
|
|
52453
|
+
"node-updating",
|
|
52445
52454
|
"server-updated",
|
|
52446
52455
|
"wrapper-update-available"
|
|
52447
52456
|
]
|
|
@@ -21616,6 +21616,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
21616
21616
|
"stream-offline",
|
|
21617
21617
|
"node-online",
|
|
21618
21618
|
"node-offline",
|
|
21619
|
+
"node-restarting",
|
|
21620
|
+
"node-updating",
|
|
21619
21621
|
"node-inference-unavailable",
|
|
21620
21622
|
"detection-blind",
|
|
21621
21623
|
"addon-crash-loop",
|
|
@@ -35057,7 +35059,8 @@ object({
|
|
|
35057
35059
|
* writes this slice (not even a boot seed), and neither does the runner's
|
|
35058
35060
|
* phase machine: its phase is "a session is attached" for every on-motion
|
|
35059
35061
|
* session, not motion, and it now has its own `DetectionPhaseTransition`.
|
|
35060
|
-
* A provider's `isDetected`
|
|
35062
|
+
* A provider's `isDetected` and `getStatus` answer from the hub's slice
|
|
35063
|
+
* (`hubMotionNativeProvider`).
|
|
35061
35064
|
* - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
|
|
35062
35065
|
* imports) — the provider pushes both edges itself, from the upstream
|
|
35063
35066
|
* system's own state change. That is the sensor's own fact.
|
|
@@ -52176,6 +52179,8 @@ new Map(Object.entries({
|
|
|
52176
52179
|
"detection-blind": "device-events",
|
|
52177
52180
|
"node-online": "system",
|
|
52178
52181
|
"node-offline": "system",
|
|
52182
|
+
"node-restarting": "system",
|
|
52183
|
+
"node-updating": "system",
|
|
52179
52184
|
"node-inference-unavailable": "system",
|
|
52180
52185
|
"addon-crash-loop": "system",
|
|
52181
52186
|
"addon-update-available": "system",
|
|
@@ -52253,6 +52258,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
52253
52258
|
kinds: [
|
|
52254
52259
|
"node-offline",
|
|
52255
52260
|
"node-online",
|
|
52261
|
+
"node-restarting",
|
|
52256
52262
|
"node-inference-unavailable"
|
|
52257
52263
|
]
|
|
52258
52264
|
},
|
|
@@ -52274,6 +52280,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
52274
52280
|
label: "Server & container updates",
|
|
52275
52281
|
kinds: [
|
|
52276
52282
|
"server-update-available",
|
|
52283
|
+
"node-updating",
|
|
52277
52284
|
"server-updated",
|
|
52278
52285
|
"wrapper-update-available"
|
|
52279
52286
|
]
|
|
@@ -52421,6 +52428,7 @@ var STATE_SUMMARY_SECTION_VARS = [
|
|
|
52421
52428
|
kinds: [
|
|
52422
52429
|
"node-offline",
|
|
52423
52430
|
"node-online",
|
|
52431
|
+
"node-restarting",
|
|
52424
52432
|
"node-inference-unavailable"
|
|
52425
52433
|
]
|
|
52426
52434
|
},
|
|
@@ -52442,6 +52450,7 @@ var STATE_SUMMARY_SECTION_VARS = [
|
|
|
52442
52450
|
example: "server 1.2.377 → 1.2.378",
|
|
52443
52451
|
kinds: [
|
|
52444
52452
|
"server-update-available",
|
|
52453
|
+
"node-updating",
|
|
52445
52454
|
"server-updated",
|
|
52446
52455
|
"wrapper-update-available"
|
|
52447
52456
|
]
|
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
5
|
+
const require_dist = require("../dist-BlIWhjnu.js");
|
|
6
6
|
const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { An as hydrateSchema, It as motionDetectionCapability, Sn as BaseAddon, pt as evaluateZoneRules, yn as DeviceType } from "../dist-
|
|
1
|
+
import { An as hydrateSchema, It as motionDetectionCapability, Sn as BaseAddon, pt as evaluateZoneRules, yn as DeviceType } from "../dist-0HoA3wAi.mjs";
|
|
2
2
|
import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-emK7D4bc.js");
|
|
2
|
-
const require_dist = require("./dist-
|
|
2
|
+
const require_dist = require("./dist-BlIWhjnu.js");
|
|
3
3
|
let node_crypto = require("node:crypto");
|
|
4
4
|
let node_fs = require("node:fs");
|
|
5
5
|
node_fs = require_chunk.__toESM(node_fs, 1);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _n as isSoftwareDecode, bn as errMsg, mn as buildFfmpegArgs, pn as Fmp4BoxSplitter } from "./dist-
|
|
1
|
+
import { _n as isSoftwareDecode, bn as errMsg, mn as buildFfmpegArgs, pn as Fmp4BoxSplitter } from "./dist-0HoA3wAi.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
@@ -3,9 +3,9 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
7
|
-
const require_node = require("../node-
|
|
8
|
-
const require_default_detection_model = require("../default-detection-model-
|
|
6
|
+
const require_dist = require("../dist-BlIWhjnu.js");
|
|
7
|
+
const require_node = require("../node-BPpVMnZy.js");
|
|
8
|
+
const require_default_detection_model = require("../default-detection-model-ChH7Y219.js");
|
|
9
9
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
10
10
|
const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
|
|
11
11
|
const require_restream_intent = require("../restream-intent-7uDNqMKs.js");
|