@camstack/addon-pipeline 1.2.100 → 1.2.102
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/{addon-utils-eUS6n_Zj.js → addon-utils-CLc6yHCN.js} +1 -1
- package/dist/audio-analyzer/index.js +3 -3
- package/dist/audio-analyzer/index.mjs +2 -2
- package/dist/detection-pipeline/index.js +163 -42
- package/dist/detection-pipeline/index.mjs +161 -40
- package/dist/{dist-dm3t4BOt.js → dist-C11WuNUP.js} +87 -51
- package/dist/{dist-gXdWP96z.mjs → dist-Ccmt3fGJ.mjs} +82 -52
- package/dist/{event-loop-stall-monitor-Lki2_mYY.js → event-loop-stall-monitor-Cq_NeC4o.js} +175 -132
- package/dist/{event-loop-stall-monitor-TnQ21mu0.mjs → event-loop-stall-monitor-OJrOMeuu.mjs} +170 -133
- package/dist/{lazy-sharp-oYppDIZR.js → lazy-sharp-RxUs6on_.js} +1 -1
- package/dist/motion-wasm/index.js +2 -2
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +5 -4
- package/dist/pipeline-runner/index.mjs +4 -3
- package/dist/{process-memory-CKWh609B.mjs → process-memory-D0zDmXLI.mjs} +1 -1
- package/dist/{process-memory-vkFVOdkV.js → process-memory-DOjQ3MgC.js} +1 -1
- package/dist/recorder/index.js +333 -125
- package/dist/recorder/index.mjs +332 -124
- package/dist/retire-root-keys-DMolfhsP.mjs +308 -0
- package/dist/retire-root-keys-KE6D6Xh_.js +319 -0
- package/dist/session-decode/decode-worker-child.js +2 -2
- package/dist/session-decode/decode-worker-child.mjs +1 -1
- package/dist/stream-broker/_stub.js +1 -1
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B7ERJocD.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BdgcF1lL.mjs} +2 -2
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-zT-cYUdF.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DY31bUCj.mjs} +1 -1
- package/dist/stream-broker/{hostInit-Cm2rl8-e.mjs → hostInit-Da9wVA2r.mjs} +2 -2
- package/dist/stream-broker/index.js +285 -41
- package/dist/stream-broker/index.mjs +285 -41
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-BrlrMxXu.js → worker-protocol-BePduZVV.js} +1 -1
- package/dist/{worker-protocol-DJWdPLKF.mjs → worker-protocol-DDpliBIW.mjs} +1 -1
- package/package.json +1 -1
- package/python/postprocessors/ctc.py +56 -3
- package/python/postprocessors/test_ctc.py +37 -0
|
@@ -15319,128 +15319,103 @@ var COCO_TO_MACRO = {
|
|
|
15319
15319
|
var AUDIO_MACRO_LABELS = [
|
|
15320
15320
|
{
|
|
15321
15321
|
id: "speech",
|
|
15322
|
-
name: "Speech"
|
|
15323
|
-
icon: "🗣️"
|
|
15322
|
+
name: "Speech"
|
|
15324
15323
|
},
|
|
15325
15324
|
{
|
|
15326
15325
|
id: "scream",
|
|
15327
|
-
name: "Scream / Shout"
|
|
15328
|
-
icon: "😱"
|
|
15326
|
+
name: "Scream / Shout"
|
|
15329
15327
|
},
|
|
15330
15328
|
{
|
|
15331
15329
|
id: "crying",
|
|
15332
|
-
name: "Crying / Baby"
|
|
15333
|
-
icon: "😢"
|
|
15330
|
+
name: "Crying / Baby"
|
|
15334
15331
|
},
|
|
15335
15332
|
{
|
|
15336
15333
|
id: "laughter",
|
|
15337
|
-
name: "Laughter"
|
|
15338
|
-
icon: "😂"
|
|
15334
|
+
name: "Laughter"
|
|
15339
15335
|
},
|
|
15340
15336
|
{
|
|
15341
15337
|
id: "music",
|
|
15342
|
-
name: "Music"
|
|
15343
|
-
icon: "🎵"
|
|
15338
|
+
name: "Music"
|
|
15344
15339
|
},
|
|
15345
15340
|
{
|
|
15346
15341
|
id: "dog",
|
|
15347
|
-
name: "Dog"
|
|
15348
|
-
icon: "🐕"
|
|
15342
|
+
name: "Dog"
|
|
15349
15343
|
},
|
|
15350
15344
|
{
|
|
15351
15345
|
id: "cat",
|
|
15352
|
-
name: "Cat"
|
|
15353
|
-
icon: "🐈"
|
|
15346
|
+
name: "Cat"
|
|
15354
15347
|
},
|
|
15355
15348
|
{
|
|
15356
15349
|
id: "bird",
|
|
15357
|
-
name: "Bird"
|
|
15358
|
-
icon: "🐦"
|
|
15350
|
+
name: "Bird"
|
|
15359
15351
|
},
|
|
15360
15352
|
{
|
|
15361
15353
|
id: "animal",
|
|
15362
|
-
name: "Animal (other)"
|
|
15363
|
-
icon: "🐾"
|
|
15354
|
+
name: "Animal (other)"
|
|
15364
15355
|
},
|
|
15365
15356
|
{
|
|
15366
15357
|
id: "alarm",
|
|
15367
|
-
name: "Alarm / Siren"
|
|
15368
|
-
icon: "🚨"
|
|
15358
|
+
name: "Alarm / Siren"
|
|
15369
15359
|
},
|
|
15370
15360
|
{
|
|
15371
15361
|
id: "doorbell",
|
|
15372
|
-
name: "Doorbell / Knock"
|
|
15373
|
-
icon: "🔔"
|
|
15362
|
+
name: "Doorbell / Knock"
|
|
15374
15363
|
},
|
|
15375
15364
|
{
|
|
15376
15365
|
id: "glass_breaking",
|
|
15377
|
-
name: "Glass Breaking"
|
|
15378
|
-
icon: "💥"
|
|
15366
|
+
name: "Glass Breaking"
|
|
15379
15367
|
},
|
|
15380
15368
|
{
|
|
15381
15369
|
id: "gunshot",
|
|
15382
|
-
name: "Gunshot / Explosion"
|
|
15383
|
-
icon: "💣"
|
|
15370
|
+
name: "Gunshot / Explosion"
|
|
15384
15371
|
},
|
|
15385
15372
|
{
|
|
15386
15373
|
id: "vehicle",
|
|
15387
|
-
name: "Vehicle"
|
|
15388
|
-
icon: "🚗"
|
|
15374
|
+
name: "Vehicle"
|
|
15389
15375
|
},
|
|
15390
15376
|
{
|
|
15391
15377
|
id: "siren",
|
|
15392
|
-
name: "Emergency Siren"
|
|
15393
|
-
icon: "🚑"
|
|
15378
|
+
name: "Emergency Siren"
|
|
15394
15379
|
},
|
|
15395
15380
|
{
|
|
15396
15381
|
id: "fire",
|
|
15397
|
-
name: "Fire / Smoke"
|
|
15398
|
-
icon: "🔥"
|
|
15382
|
+
name: "Fire / Smoke"
|
|
15399
15383
|
},
|
|
15400
15384
|
{
|
|
15401
15385
|
id: "water",
|
|
15402
|
-
name: "Water"
|
|
15403
|
-
icon: "💧"
|
|
15386
|
+
name: "Water"
|
|
15404
15387
|
},
|
|
15405
15388
|
{
|
|
15406
15389
|
id: "wind",
|
|
15407
|
-
name: "Wind / Weather"
|
|
15408
|
-
icon: "🌬️"
|
|
15390
|
+
name: "Wind / Weather"
|
|
15409
15391
|
},
|
|
15410
15392
|
{
|
|
15411
15393
|
id: "door",
|
|
15412
|
-
name: "Door"
|
|
15413
|
-
icon: "🚪"
|
|
15394
|
+
name: "Door"
|
|
15414
15395
|
},
|
|
15415
15396
|
{
|
|
15416
15397
|
id: "footsteps",
|
|
15417
|
-
name: "Footsteps"
|
|
15418
|
-
icon: "👣"
|
|
15398
|
+
name: "Footsteps"
|
|
15419
15399
|
},
|
|
15420
15400
|
{
|
|
15421
15401
|
id: "crowd",
|
|
15422
|
-
name: "Crowd / Chatter"
|
|
15423
|
-
icon: "👥"
|
|
15402
|
+
name: "Crowd / Chatter"
|
|
15424
15403
|
},
|
|
15425
15404
|
{
|
|
15426
15405
|
id: "telephone",
|
|
15427
|
-
name: "Telephone"
|
|
15428
|
-
icon: "📞"
|
|
15406
|
+
name: "Telephone"
|
|
15429
15407
|
},
|
|
15430
15408
|
{
|
|
15431
15409
|
id: "engine",
|
|
15432
|
-
name: "Engine / Motor"
|
|
15433
|
-
icon: "⚙️"
|
|
15410
|
+
name: "Engine / Motor"
|
|
15434
15411
|
},
|
|
15435
15412
|
{
|
|
15436
15413
|
id: "tools",
|
|
15437
|
-
name: "Tools / Construction"
|
|
15438
|
-
icon: "🔨"
|
|
15414
|
+
name: "Tools / Construction"
|
|
15439
15415
|
},
|
|
15440
15416
|
{
|
|
15441
15417
|
id: "silence",
|
|
15442
|
-
name: "Silence"
|
|
15443
|
-
icon: "🤫"
|
|
15418
|
+
name: "Silence"
|
|
15444
15419
|
}
|
|
15445
15420
|
];
|
|
15446
15421
|
var YAMNET_TO_MACRO = {
|
|
@@ -19704,6 +19679,12 @@ var DetailResultSchema = object({
|
|
|
19704
19679
|
/** FRAME-space bbox (already mapped back from crop space). */
|
|
19705
19680
|
bbox: NativeCropBboxSchema.optional(),
|
|
19706
19681
|
embedding: string().optional(),
|
|
19682
|
+
/**
|
|
19683
|
+
* L2 magnitude of the RAW pre-normalization embedding. Additive and optional
|
|
19684
|
+
* so an older runner that does not send it degrades to "unmeasurable", which
|
|
19685
|
+
* the consuming gate treats as accept — never as reject.
|
|
19686
|
+
*/
|
|
19687
|
+
embeddingMagnitude: number().optional(),
|
|
19707
19688
|
label: string().optional(),
|
|
19708
19689
|
/**
|
|
19709
19690
|
* The tier `label` occupies, copied VERBATIM from the producing step's
|
|
@@ -35818,12 +35799,61 @@ Object.freeze({
|
|
|
35818
35799
|
"network-access": "ingress",
|
|
35819
35800
|
"smtp-provider": "email"
|
|
35820
35801
|
});
|
|
35802
|
+
/**
|
|
35803
|
+
* audio-condition — the authoring logic behind the sustained-sound condition
|
|
35804
|
+
* (`NcConditions.audio`), pure and UI-framework-free.
|
|
35805
|
+
*
|
|
35806
|
+
* WHY IT LIVES HERE
|
|
35807
|
+
* ─────────────────
|
|
35808
|
+
* Same reason as `condition-taxonomy.ts` next door: two editors author this
|
|
35809
|
+
* condition (the admin UI and the viewer), the vocabulary it offers is already
|
|
35810
|
+
* in this package (`AUDIO_MACRO_LABELS`), and a second copy of "what a cleared
|
|
35811
|
+
* threshold writes" is a mirror free to drift. The viewer keeps its own copy
|
|
35812
|
+
* because it is a separate app with its own toolchain; every surface that CAN
|
|
35813
|
+
* import `@camstack/types` uses this one.
|
|
35814
|
+
*
|
|
35815
|
+
* Four behaviours here are not cosmetic:
|
|
35816
|
+
*
|
|
35817
|
+
* 1. **dBFS is negative-going.** `0` is full scale; digital silence reads
|
|
35818
|
+
* {@link NC_AUDIO_DBFS_FLOOR}. A control that let an operator author `60`
|
|
35819
|
+
* meaning "loud" would write a threshold no sample can reach, and the rule
|
|
35820
|
+
* would look broken rather than mis-configured. Every write is clamped.
|
|
35821
|
+
* 2. **Neither filter given = the engine REFUSES.** With no level floor and no
|
|
35822
|
+
* labels every sample is trivially a hit, so the window would fire on
|
|
35823
|
+
* silence. {@link audioIsFailClosed} is how an editor says that BEFORE the
|
|
35824
|
+
* save instead of shipping a rule that never notifies and never says why.
|
|
35825
|
+
* 3. **Both label spellings are the same label.** The hub's taxonomy serves
|
|
35826
|
+
* `audio-dog`; the macro catalog and an operator both say `dog`, and the
|
|
35827
|
+
* matcher normalizes the prefix away on both sides. Selection therefore
|
|
35828
|
+
* compares NORMALIZED ids — a rule authored in the admin UI must not read
|
|
35829
|
+
* as "nothing selected" on the phone.
|
|
35830
|
+
* 4. **A stored label the build does not know stays visible.** It is offered
|
|
35831
|
+
* as an explicitly-unknown, removable choice, never silently dropped:
|
|
35832
|
+
* rewriting the rule the operator is looking at is worse than showing a
|
|
35833
|
+
* stale id.
|
|
35834
|
+
*/
|
|
35835
|
+
/** The `audio-` namespace the NC taxonomy uses for these same macro ids. */
|
|
35836
|
+
var AUDIO_KIND_PREFIX = "audio-";
|
|
35837
|
+
/**
|
|
35838
|
+
* The inverse: a macro id in the taxonomy's namespace (`dog` → `audio-dog`),
|
|
35839
|
+
* which is the `iconId` every UI resolves to a glyph (`EVENT_KIND_ICONS` in
|
|
35840
|
+
* `@camstack/ui-library`, `event-kind-icons.ts` in the viewer). Idempotent, so
|
|
35841
|
+
* a value that already carries the namespace is passed through unchanged.
|
|
35842
|
+
*
|
|
35843
|
+
* This lives here — beside `normalizeAudioLabel` and next to the vocabulary
|
|
35844
|
+
* itself — rather than in a UI package, because the *id* is data and the *glyph*
|
|
35845
|
+
* is presentation: the server puts the id on a config option, and whichever
|
|
35846
|
+
* renderer picks it up (lucide-react on the web, lucide-react-native in the
|
|
35847
|
+
* viewer) supplies its own component for it.
|
|
35848
|
+
*/
|
|
35849
|
+
function audioKindId(macroId) {
|
|
35850
|
+
return macroId.startsWith(AUDIO_KIND_PREFIX) ? macroId : `${AUDIO_KIND_PREFIX}${macroId}`;
|
|
35851
|
+
}
|
|
35821
35852
|
/** Schema defaults — an untouched sub-field must author exactly these. */
|
|
35822
35853
|
var NC_AUDIO_DEFAULTS = {
|
|
35823
35854
|
hitPercent: 60,
|
|
35824
35855
|
samplingSeconds: 10
|
|
35825
35856
|
};
|
|
35826
|
-
new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
|
|
35827
35857
|
new Set(["devices", "classes"]);
|
|
35828
35858
|
NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
|
|
35829
35859
|
/**
|
|
@@ -37110,4 +37140,4 @@ function enumerateInferenceDevices(hw) {
|
|
|
37110
37140
|
return out;
|
|
37111
37141
|
}
|
|
37112
37142
|
//#endregion
|
|
37113
|
-
export {
|
|
37143
|
+
export { recordingCapability as $, batteryCapability as A, array as At, egressTranscodeSharingKey as B, EventCategory as Bt, RecordingConfigSchema as C, makeSourceBrokerId as Ct, audioAnalysisCapability as D, selectAssignedProfileSlots as Dt, addonWidgetsSourceCapability as E, parseProfileBrokerId as Et, defineCustomActions as F, number as Ft, mapAudioLabelToMacro as G, enumerateInferenceDevices as H, deriveBatteryPresence as I, object as It, parseProcStatus as J, maskUrlCredentials as K, deriveDetailCropRect as L, record as Lt, createHwAccelCache as M, discriminatedUnion as Mt, customAction as N, lazy as Nt, audioAnalyzerCapability as O, sleep as Ot, defaultDeviceFor as P, literal as Pt, pipelineRunnerCapability as Q, deriveRecordingMode as R, string as Rt, RECORDING_EXPORT_MAX_READ_BYTES as S, makeProfileBrokerId as St, YAMNET_TO_MACRO as T, parseJsonUnknown as Tt, evaluateZoneRules as U, egressTransportFromRequest as V, hfModelUrl as W, pickNativeLeaseOverride as X, pickDetailCropConvention as Y, pipelineExecutorCapability as Z, NativeLeaseSettingsSchema as _, DeviceFeature as _t, COCO_80_LABELS as a, storageEvictableCapability as at, RATE_CONTROL_RELAXED as b, hydrateSchema as bt, DEFAULT_DETAIL_CROP_CONVENTION as c, webrtcSessionCapability as ct, DEVICE_BACKEND_TO_FORMAT as d, Fmp4BoxSplitter as dt, recordingExportCapability as et, EVENT_PAD_MS as f, buildFfmpegArgs as ft, NativeLeaseAdmissionSchema as g, CAM_PROFILE_ORDER as gt, HF_BASE_URL as h, BaseAddon as ht, BatteryStatusSchema as i, runtimeDevices as it, cameraStreamsCapability as j, boolean as jt, audioKindId as k, _enum as kt, DEFAULT_EVENTS_BAND_BUFFER_SEC as l, errMsg as lt, ExportRecordSchema as m, isSoftwareDecode as mt, AUDIO_BACKEND_CHOICES as n, resolvePoolMemoryPolicy as nt, COCO_TO_MACRO as o, streamBrokerCapability as ot, EncodeProfileSchema as p, invocationFromEncodeProfile as pt, motionDetectionCapability as q, AUDIO_MACRO_LABELS as r, resolveRecordingProfiles as rt, DEFAULT_AUDIO_ANALYZER_CONFIG as s, supportedRuntimes as st, APPLE_SA_TO_MACRO as t, resolveEgressDecodeHwAccel as tt, DEFAULT_NATIVE_LEASE_SETTINGS as u, AUDIO_PRESETS as ut, OpsLogEntrySchema as v, DeviceType as vt, RingBuffer as w, nodePin as wt, RATE_CONTROL_TIGHT as x, isEvent as xt, PoolMemoryWatchdog as y, createEvent as yt, detectionPipelineCapability as z, union as zt };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_dist = require("./dist-
|
|
1
|
+
const require_dist = require("./dist-C11WuNUP.js");
|
|
2
2
|
let node_perf_hooks = require("node:perf_hooks");
|
|
3
3
|
//#region src/detection-pipeline/registry/model-catalogs.ts
|
|
4
4
|
var HF_REPO = "camstack/camstack-models";
|
|
@@ -48,7 +48,8 @@ var ovPrecisionVariant = (baseId, ovDir, baseName, precision, sizeMB, legacy = f
|
|
|
48
48
|
...precision === "int8" ? { group: {
|
|
49
49
|
family: baseId.slice(0, -1),
|
|
50
50
|
tier: baseId.slice(-1),
|
|
51
|
-
precision: "int8"
|
|
51
|
+
precision: "int8",
|
|
52
|
+
resolution: 640
|
|
52
53
|
} } : {}
|
|
53
54
|
});
|
|
54
55
|
var MLPACKAGE_FILES = [
|
|
@@ -191,7 +192,8 @@ var OBJECT_DETECTION_MODELS = [
|
|
|
191
192
|
id: "yolo26n",
|
|
192
193
|
group: {
|
|
193
194
|
family: "yolo26",
|
|
194
|
-
tier: "n"
|
|
195
|
+
tier: "n",
|
|
196
|
+
resolution: 640
|
|
195
197
|
},
|
|
196
198
|
name: "YOLO26 Nano",
|
|
197
199
|
description: "YOLO26 Nano — latest generation ultra-lightweight detector with attention mechanism",
|
|
@@ -220,7 +222,8 @@ var OBJECT_DETECTION_MODELS = [
|
|
|
220
222
|
id: "yolo26s",
|
|
221
223
|
group: {
|
|
222
224
|
family: "yolo26",
|
|
223
|
-
tier: "s"
|
|
225
|
+
tier: "s",
|
|
226
|
+
resolution: 640
|
|
224
227
|
},
|
|
225
228
|
name: "YOLO26 Small",
|
|
226
229
|
description: "YOLO26 Small — balanced speed/accuracy with attention-based architecture",
|
|
@@ -249,7 +252,8 @@ var OBJECT_DETECTION_MODELS = [
|
|
|
249
252
|
id: "yolo26m",
|
|
250
253
|
group: {
|
|
251
254
|
family: "yolo26",
|
|
252
|
-
tier: "m"
|
|
255
|
+
tier: "m",
|
|
256
|
+
resolution: 640
|
|
253
257
|
},
|
|
254
258
|
name: "YOLO26 Medium",
|
|
255
259
|
description: "YOLO26 Medium — high accuracy general-purpose detector",
|
|
@@ -278,7 +282,8 @@ var OBJECT_DETECTION_MODELS = [
|
|
|
278
282
|
id: "yolo26l",
|
|
279
283
|
group: {
|
|
280
284
|
family: "yolo26",
|
|
281
|
-
tier: "l"
|
|
285
|
+
tier: "l",
|
|
286
|
+
resolution: 640
|
|
282
287
|
},
|
|
283
288
|
name: "YOLO26 Large",
|
|
284
289
|
description: "YOLO26 Large — maximum accuracy for demanding deployments",
|
|
@@ -474,7 +479,7 @@ var FACE_DETECTION_MODELS = [
|
|
|
474
479
|
{
|
|
475
480
|
id: "scrfd-2.5g",
|
|
476
481
|
name: "SCRFD 2.5G",
|
|
477
|
-
description: "SCRFD 2.5G — balanced face detection
|
|
482
|
+
description: "SCRFD 2.5G bnkps — balanced face detection with 5 keypoints (WIDER FACE 93.80/92.02/77.13). InsightFace pretrained weights.",
|
|
478
483
|
inputSize: {
|
|
479
484
|
width: 640,
|
|
480
485
|
height: 640
|
|
@@ -484,6 +489,7 @@ var FACE_DETECTION_MODELS = [
|
|
|
484
489
|
name: "Face"
|
|
485
490
|
}],
|
|
486
491
|
preprocessMode: "letterbox",
|
|
492
|
+
license: "InsightFace-NonCommercial-Research",
|
|
487
493
|
formats: {
|
|
488
494
|
onnx: {
|
|
489
495
|
url: hf("faceDetection/scrfd/onnx/camstack-scrfd-2.5g.onnx"),
|
|
@@ -512,6 +518,7 @@ var FACE_DETECTION_MODELS = [
|
|
|
512
518
|
name: "Face"
|
|
513
519
|
}],
|
|
514
520
|
preprocessMode: "letterbox",
|
|
521
|
+
license: "UNKNOWN",
|
|
515
522
|
formats: {
|
|
516
523
|
onnx: {
|
|
517
524
|
url: hfScrypted("onnx/scrypted_yolov9t_relu_face/scrypted_yolov9t_relu_face.onnx"),
|
|
@@ -550,63 +557,98 @@ var FACE_DETECTION_MODELS = [
|
|
|
550
557
|
} }
|
|
551
558
|
}
|
|
552
559
|
];
|
|
553
|
-
var FACE_EMBEDDING_MODELS = [
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
inputLayout: "nhwc",
|
|
562
|
-
labels: [{
|
|
563
|
-
id: "embedding",
|
|
564
|
-
name: "Face Embedding"
|
|
565
|
-
}],
|
|
566
|
-
preprocessMode: "resize",
|
|
567
|
-
faceAlignment: true,
|
|
568
|
-
formats: {
|
|
569
|
-
onnx: {
|
|
570
|
-
url: hf("faceRecognition/arcface/onnx/camstack-arcface-arcface.onnx"),
|
|
571
|
-
sizeMB: 130
|
|
572
|
-
},
|
|
573
|
-
coreml: {
|
|
574
|
-
url: hf("faceRecognition/arcface/coreml/camstack-arcface-r100.mlpackage"),
|
|
575
|
-
sizeMB: 65,
|
|
576
|
-
isDirectory: true,
|
|
577
|
-
files: [...MLPACKAGE_FILES],
|
|
578
|
-
runtimes: ["python"]
|
|
560
|
+
var FACE_EMBEDDING_MODELS = [
|
|
561
|
+
{
|
|
562
|
+
id: "arcface-r100",
|
|
563
|
+
name: "ArcFace (ResNet34)",
|
|
564
|
+
description: "ArcFace ResNet34 — face recognition embeddings (512-d). NOTE: despite the `arcface-r100` id this is a ResNet34, not a ResNet-100 (verified 2026-08-19).",
|
|
565
|
+
inputSize: {
|
|
566
|
+
width: 112,
|
|
567
|
+
height: 112
|
|
579
568
|
},
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
569
|
+
inputLayout: "nhwc",
|
|
570
|
+
labels: [{
|
|
571
|
+
id: "embedding",
|
|
572
|
+
name: "Face Embedding"
|
|
573
|
+
}],
|
|
574
|
+
preprocessMode: "resize",
|
|
575
|
+
faceAlignment: true,
|
|
576
|
+
license: "UNKNOWN",
|
|
577
|
+
formats: {
|
|
578
|
+
onnx: {
|
|
579
|
+
url: hf("faceRecognition/arcface/onnx/camstack-arcface-arcface.onnx"),
|
|
580
|
+
sizeMB: 130
|
|
581
|
+
},
|
|
582
|
+
coreml: {
|
|
583
|
+
url: hf("faceRecognition/arcface/coreml/camstack-arcface-r100.mlpackage"),
|
|
584
|
+
sizeMB: 65,
|
|
585
|
+
isDirectory: true,
|
|
586
|
+
files: [...MLPACKAGE_FILES],
|
|
587
|
+
runtimes: ["python"]
|
|
588
|
+
},
|
|
589
|
+
openvino: ovFormat(hf("faceRecognition/arcface/openvino/camstack-arcface-r100.xml"), 65)
|
|
590
|
+
}
|
|
589
591
|
},
|
|
590
|
-
|
|
591
|
-
id: "
|
|
592
|
-
name: "
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
url: hfScrypted("onnx/inception_resnet_v1/inception_resnet_v1.onnx"),
|
|
598
|
-
sizeMB: 89.6
|
|
592
|
+
{
|
|
593
|
+
id: "auraface-r100",
|
|
594
|
+
name: "AuraFace R100",
|
|
595
|
+
description: "AuraFace v1 (fal.ai) — iResNet-100 ArcFace face recognition embeddings (512-d), Apache-2.0. Benchmarks published by fal: LFW 99.65, CFP-FP 95.19, AgeDB 96.10, CALFW 94.70, CPLFW 90.93. Genuinely a ResNet-100 (65 M params) — roughly twice the depth of the `arcface-r100` entry, which is a ResNet34.",
|
|
596
|
+
inputSize: {
|
|
597
|
+
width: 112,
|
|
598
|
+
height: 112
|
|
599
599
|
},
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
600
|
+
labels: [{
|
|
601
|
+
id: "embedding",
|
|
602
|
+
name: "Face Embedding"
|
|
603
|
+
}],
|
|
604
|
+
preprocessMode: "resize",
|
|
605
|
+
faceAlignment: true,
|
|
606
|
+
license: "Apache-2.0",
|
|
607
|
+
formats: {
|
|
608
|
+
onnx: {
|
|
609
|
+
url: hf("faceRecognition/auraface/onnx/camstack-auraface-r100.onnx"),
|
|
610
|
+
sizeMB: 261
|
|
611
|
+
},
|
|
612
|
+
coreml: {
|
|
613
|
+
url: hf("faceRecognition/auraface/coreml/camstack-auraface-r100.mlpackage"),
|
|
614
|
+
sizeMB: 131,
|
|
615
|
+
isDirectory: true,
|
|
616
|
+
files: [...MLPACKAGE_FILES],
|
|
617
|
+
runtimes: ["python"]
|
|
618
|
+
},
|
|
619
|
+
openvino: ovFormat(hf("faceRecognition/auraface/openvino/camstack-auraface-r100.xml"), 131)
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
id: "inception-resnet-v1",
|
|
624
|
+
name: "Inception ResNet V1",
|
|
625
|
+
description: "FaceNet-style face recognition embeddings (512-d) — hosted on plugin-models HF repo",
|
|
626
|
+
inputSize: {
|
|
627
|
+
width: 160,
|
|
628
|
+
height: 160
|
|
606
629
|
},
|
|
607
|
-
|
|
630
|
+
labels: [{
|
|
631
|
+
id: "embedding",
|
|
632
|
+
name: "Face Embedding"
|
|
633
|
+
}],
|
|
634
|
+
preprocessMode: "resize",
|
|
635
|
+
license: "UNKNOWN",
|
|
636
|
+
formats: {
|
|
637
|
+
onnx: {
|
|
638
|
+
url: hfScrypted("onnx/inception_resnet_v1/inception_resnet_v1.onnx"),
|
|
639
|
+
sizeMB: 89.6
|
|
640
|
+
},
|
|
641
|
+
coreml: {
|
|
642
|
+
url: hfScrypted("coreml/inception_resnet_v1/inception_resnet_v1.mlpackage"),
|
|
643
|
+
sizeMB: 45,
|
|
644
|
+
isDirectory: true,
|
|
645
|
+
files: [...MLPACKAGE_FILES],
|
|
646
|
+
runtimes: ["python"]
|
|
647
|
+
},
|
|
648
|
+
openvino: ovFormat(hf("faceRecognition/inception-resnet-v1/openvino/camstack-inception-resnet-v1.xml"), 45)
|
|
649
|
+
}
|
|
608
650
|
}
|
|
609
|
-
|
|
651
|
+
];
|
|
610
652
|
var PLATE_DETECTION_MODELS = [{
|
|
611
653
|
id: "yolov8n-plate",
|
|
612
654
|
name: "YOLOv8 Nano — License Plate",
|
|
@@ -1192,6 +1234,22 @@ var AUDIO_CLASSIFIER_MODELS = [{
|
|
|
1192
1234
|
} }
|
|
1193
1235
|
}];
|
|
1194
1236
|
//#endregion
|
|
1237
|
+
//#region src/detection-pipeline/pipeline/landmark-precision-gate.ts
|
|
1238
|
+
/**
|
|
1239
|
+
* `null` = admit. A verdict = refuse, carrying both numbers so the caller can
|
|
1240
|
+
* name them in a log. Pure.
|
|
1241
|
+
*/
|
|
1242
|
+
function landmarkPrecisionVerdict(input) {
|
|
1243
|
+
const { detectionShortSidePx, floorPx } = input;
|
|
1244
|
+
if (!(floorPx > 0)) return null;
|
|
1245
|
+
if (!Number.isFinite(detectionShortSidePx)) return null;
|
|
1246
|
+
if (detectionShortSidePx >= floorPx) return null;
|
|
1247
|
+
return {
|
|
1248
|
+
detectionShortSidePx,
|
|
1249
|
+
floorPx
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
//#endregion
|
|
1195
1253
|
//#region src/detection-pipeline/registry/step-definitions.ts
|
|
1196
1254
|
var ANIMAL_10_LABELS = [
|
|
1197
1255
|
"cat",
|
|
@@ -1272,7 +1330,7 @@ var ObjectDetectionStep = class {
|
|
|
1272
1330
|
type: "multiselect",
|
|
1273
1331
|
key: "enabledMacroClasses",
|
|
1274
1332
|
label: "Enabled Classes",
|
|
1275
|
-
description: "Which macro classes to detect (empty =
|
|
1333
|
+
description: "Which macro classes to detect (empty = every class listed here).",
|
|
1276
1334
|
options: [
|
|
1277
1335
|
{
|
|
1278
1336
|
value: "person",
|
|
@@ -1285,10 +1343,6 @@ var ObjectDetectionStep = class {
|
|
|
1285
1343
|
{
|
|
1286
1344
|
value: "animal",
|
|
1287
1345
|
label: "Animal"
|
|
1288
|
-
},
|
|
1289
|
-
{
|
|
1290
|
-
value: "package",
|
|
1291
|
-
label: "Package"
|
|
1292
1346
|
}
|
|
1293
1347
|
],
|
|
1294
1348
|
default: [
|
|
@@ -1341,21 +1395,6 @@ var ObjectDetectionStep = class {
|
|
|
1341
1395
|
default: .5,
|
|
1342
1396
|
showValue: true
|
|
1343
1397
|
},
|
|
1344
|
-
{
|
|
1345
|
-
type: "slider",
|
|
1346
|
-
key: "minConfidencePackage",
|
|
1347
|
-
label: "Min Confidence — Package",
|
|
1348
|
-
description: "Drop package predictions below this score.",
|
|
1349
|
-
min: 0,
|
|
1350
|
-
max: 1,
|
|
1351
|
-
step: .05,
|
|
1352
|
-
default: .5,
|
|
1353
|
-
showValue: true,
|
|
1354
|
-
showWhen: {
|
|
1355
|
-
field: "enabledMacroClasses",
|
|
1356
|
-
includes: "package"
|
|
1357
|
-
}
|
|
1358
|
-
},
|
|
1359
1398
|
{
|
|
1360
1399
|
type: "slider",
|
|
1361
1400
|
key: "nmsIouThreshold",
|
|
@@ -1393,7 +1432,8 @@ var AudioClassifierStep = class {
|
|
|
1393
1432
|
description: "Which audio macro classes to surface (empty = all).",
|
|
1394
1433
|
options: require_dist.AUDIO_MACRO_LABELS.map((l) => ({
|
|
1395
1434
|
value: l.id,
|
|
1396
|
-
label:
|
|
1435
|
+
label: l.name,
|
|
1436
|
+
iconId: require_dist.audioKindId(l.id)
|
|
1397
1437
|
})),
|
|
1398
1438
|
default: [
|
|
1399
1439
|
"scream",
|
|
@@ -1520,66 +1560,36 @@ var ClassifierWithMinConfidence = class extends PipelineStepBase {
|
|
|
1520
1560
|
var PLATE_OCR_DEFAULT_REGION = "DE";
|
|
1521
1561
|
var PLATE_OCR_DEFAULT_MIN_TEXT_LENGTH = 3;
|
|
1522
1562
|
var PLATE_OCR_DEFAULT_MIN_TEXT_CONFIDENCE = 0;
|
|
1523
|
-
var PLATE_OCR_REGION_OPTIONS = [{
|
|
1524
|
-
value: "off",
|
|
1525
|
-
label: "Off (no format correction)"
|
|
1526
|
-
}, {
|
|
1527
|
-
value: "DE",
|
|
1528
|
-
label: "Germany"
|
|
1529
|
-
}];
|
|
1530
1563
|
/**
|
|
1531
1564
|
* Plate OCR step — exposes a `rectify` toggle (default ON) that deskews the
|
|
1532
1565
|
* plate crop (rotation rectification) before the CTC recognizer reads it.
|
|
1533
1566
|
* Oblique cameras (steeply angled plates) skew the text baseline and collapse
|
|
1534
1567
|
* CTC beyond ~10-15°; a frontal camera loses nothing at 0° because the executor
|
|
1535
|
-
* skips the warp when the estimated angle is ~0. Per-camera configurable
|
|
1568
|
+
* skips the warp when the estimated angle is ~0. Per-camera configurable, and
|
|
1569
|
+
* the ONLY per-camera knob this step has — see below.
|
|
1536
1570
|
*
|
|
1537
|
-
*
|
|
1538
|
-
*
|
|
1571
|
+
* `plateRegion` / `minTextLength` / `minTextConfidence` are NOT offered here.
|
|
1572
|
+
* They are consumed inside the Python CTC postprocessor, whose config is bound
|
|
1573
|
+
* when the model is loaded into the shared inference pool — node-level by
|
|
1574
|
+
* construction, exactly like `nmsIouThreshold` and the pool confidence floor.
|
|
1575
|
+
* They used to be rendered as per-camera sliders that wrote a settings row
|
|
1576
|
+
* nobody read: `engine-factory.buildPoolModelConfig` takes the STATIC value off
|
|
1577
|
+
* the step definition below, so the operator moved a slider and the runtime
|
|
1578
|
+
* kept the default (D62 — a per-camera switch that stores nothing is worse than
|
|
1579
|
+
* no switch). Making them genuinely per-camera means a per-REQUEST config
|
|
1580
|
+
* override through SharedInferencePool → inference_pool.py → ModelSlot.config,
|
|
1581
|
+
* i.e. a new wire protocol, not a step-schema entry.
|
|
1539
1582
|
*/
|
|
1540
1583
|
var PlateOcrStep = class extends PipelineStepBase {
|
|
1541
1584
|
getConfigSchema() {
|
|
1542
|
-
return [
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
},
|
|
1551
|
-
{
|
|
1552
|
-
type: "select",
|
|
1553
|
-
key: "plateRegion",
|
|
1554
|
-
label: "Plate Format",
|
|
1555
|
-
description: "Validate each read against a country plate grammar and repair OCR confusables (0↔O, 1↔I, 8↔B, …) to the highest-scoring conforming read. Never drops a plausible read — only fixes or annotates it. \"Off\" disables correction.",
|
|
1556
|
-
options: PLATE_OCR_REGION_OPTIONS,
|
|
1557
|
-
default: PLATE_OCR_DEFAULT_REGION,
|
|
1558
|
-
immediate: true
|
|
1559
|
-
},
|
|
1560
|
-
{
|
|
1561
|
-
type: "slider",
|
|
1562
|
-
key: "minTextLength",
|
|
1563
|
-
label: "Min Plate Length",
|
|
1564
|
-
description: "Suppress reads shorter than this many characters as low-resolution noise (never stored as a plate).",
|
|
1565
|
-
min: 1,
|
|
1566
|
-
max: 8,
|
|
1567
|
-
step: 1,
|
|
1568
|
-
default: PLATE_OCR_DEFAULT_MIN_TEXT_LENGTH,
|
|
1569
|
-
showValue: true
|
|
1570
|
-
},
|
|
1571
|
-
{
|
|
1572
|
-
type: "slider",
|
|
1573
|
-
key: "minTextConfidence",
|
|
1574
|
-
label: "Min OCR Confidence",
|
|
1575
|
-
description: "Suppress reads whose mean character confidence is below this floor. 0 disables the confidence gate (length is the primary discriminator).",
|
|
1576
|
-
min: 0,
|
|
1577
|
-
max: 1,
|
|
1578
|
-
step: .05,
|
|
1579
|
-
default: PLATE_OCR_DEFAULT_MIN_TEXT_CONFIDENCE,
|
|
1580
|
-
showValue: true
|
|
1581
|
-
}
|
|
1582
|
-
];
|
|
1585
|
+
return [{
|
|
1586
|
+
type: "boolean",
|
|
1587
|
+
key: "rectify",
|
|
1588
|
+
label: "Deskew Plate Crop",
|
|
1589
|
+
description: "Rotate the plate crop to level the text baseline before OCR. Recommended for oblique/angled cameras; a frontal camera is unaffected (no rotation applied at ~0°).",
|
|
1590
|
+
default: true,
|
|
1591
|
+
style: "switch"
|
|
1592
|
+
}];
|
|
1583
1593
|
}
|
|
1584
1594
|
};
|
|
1585
1595
|
var STEP_FACE_DETECTION = new PipelineStepBase({
|
|
@@ -1599,7 +1609,34 @@ var STEP_FACE_DETECTION = new PipelineStepBase({
|
|
|
1599
1609
|
minIntervalMs: 1e3
|
|
1600
1610
|
}
|
|
1601
1611
|
});
|
|
1602
|
-
|
|
1612
|
+
/**
|
|
1613
|
+
* `face-embedding` — carries the LANDMARK-PRECISION floor as its only operator
|
|
1614
|
+
* knob.
|
|
1615
|
+
*
|
|
1616
|
+
* It has to live here rather than beside the other face thresholds in
|
|
1617
|
+
* post-analysis's `face-settings.ts`: the gate is enforced in the runner's
|
|
1618
|
+
* executor, on the detection-frame measurement, BEFORE the native-size
|
|
1619
|
+
* substitution — and `child.settings` (hydrated from this schema by
|
|
1620
|
+
* `tree-builder`) is the only channel that reaches that code. A copy in
|
|
1621
|
+
* `face-settings.ts` would be a second knob that writes a store the gate never
|
|
1622
|
+
* reads, which this repo has shipped twice already.
|
|
1623
|
+
*/
|
|
1624
|
+
var FaceEmbeddingStep = class extends PipelineStepBase {
|
|
1625
|
+
getConfigSchema() {
|
|
1626
|
+
return [{
|
|
1627
|
+
type: "slider",
|
|
1628
|
+
key: "minLandmarkFaceSize",
|
|
1629
|
+
label: "Min face size for recognition (detection px)",
|
|
1630
|
+
description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME — not at native resolution. The 5 landmarks that align the crop are regressed at detection scale, so below this floor the aligned crop is not reliably a face, and a native-resolution cutout cannot fix it. Measured on 60 live crops: at 24px, 61% come out correctly aligned versus 20% with no floor, at the cost of about 70% of the volume. Lower it if you are losing too many faces; 0 disables the gate. A degenerate crop is worse than no crop — it scores high similarity against everyone and poisons the gallery.",
|
|
1631
|
+
min: 0,
|
|
1632
|
+
max: 64,
|
|
1633
|
+
step: 2,
|
|
1634
|
+
showValue: true,
|
|
1635
|
+
default: 24
|
|
1636
|
+
}];
|
|
1637
|
+
}
|
|
1638
|
+
};
|
|
1639
|
+
var STEP_FACE_EMBEDDING = new FaceEmbeddingStep({
|
|
1603
1640
|
id: "face-embedding",
|
|
1604
1641
|
name: "Face Embedding",
|
|
1605
1642
|
slot: "classifier",
|
|
@@ -2037,6 +2074,12 @@ Object.defineProperty(exports, "getStepDefinition", {
|
|
|
2037
2074
|
return getStepDefinition;
|
|
2038
2075
|
}
|
|
2039
2076
|
});
|
|
2077
|
+
Object.defineProperty(exports, "landmarkPrecisionVerdict", {
|
|
2078
|
+
enumerable: true,
|
|
2079
|
+
get: function() {
|
|
2080
|
+
return landmarkPrecisionVerdict;
|
|
2081
|
+
}
|
|
2082
|
+
});
|
|
2040
2083
|
Object.defineProperty(exports, "resolveModelForFormat", {
|
|
2041
2084
|
enumerable: true,
|
|
2042
2085
|
get: function() {
|