@camstack/addon-post-analysis 1.2.289 → 1.2.291
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/{clip-model-registry-JFtcAZEB.js → clip-model-registry-CTY5co6P.js} +472 -27
- package/dist/{clip-model-registry-g3-Yz08Y.mjs → clip-model-registry-Cudz--Ql.mjs} +472 -27
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/pipeline-analytics/_stub.js +2 -2
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-D5OpYfsh.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-CBHxwCSj.mjs} +2 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-2OwTV_D2.mjs +26 -0
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DAAKQ3sC.mjs +26 -0
- package/dist/pipeline-analytics/{hostInit-BsQiXbDx.mjs → hostInit-DSKT2dE4.mjs} +2 -2
- package/dist/pipeline-analytics/index.js +322 -59
- package/dist/pipeline-analytics/index.mjs +322 -59
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CfU5NAwo.mjs +0 -26
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-r4OU_ahc.mjs +0 -26
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_clip_model_registry = require("../clip-model-registry-
|
|
5
|
+
const require_clip_model_registry = require("../clip-model-registry-CTY5co6P.js");
|
|
6
6
|
let node_fs = require("node:fs");
|
|
7
7
|
node_fs = require_clip_model_registry.__toESM(node_fs, 1);
|
|
8
8
|
let node_path = require("node:path");
|
|
@@ -39677,7 +39677,12 @@ var RebuildInputSchema = require_clip_model_registry.object({
|
|
|
39677
39677
|
* Milliseconds between tracks; omit for the default, `0` to run flat out.
|
|
39678
39678
|
* A rebuild shares hub-main's only thread with every live request.
|
|
39679
39679
|
*/
|
|
39680
|
-
pacingMs: require_clip_model_registry.number().int().nonnegative().optional()
|
|
39680
|
+
pacingMs: require_clip_model_registry.number().int().nonnegative().optional(),
|
|
39681
|
+
/**
|
|
39682
|
+
* Re-embed ONLY tracks already in the pinned space — to redo vectors cut
|
|
39683
|
+
* from the wrong box (D664). Requires `maxTracks`.
|
|
39684
|
+
*/
|
|
39685
|
+
force: require_clip_model_registry.boolean().optional()
|
|
39681
39686
|
});
|
|
39682
39687
|
var RebuildStartedSchema = require_clip_model_registry.object({
|
|
39683
39688
|
started: require_clip_model_registry.boolean(),
|
|
@@ -39697,7 +39702,20 @@ var RebuildStatusSchema = require_clip_model_registry.object({
|
|
|
39697
39702
|
scanned: require_clip_model_registry.number(),
|
|
39698
39703
|
rebuilt: require_clip_model_registry.number(),
|
|
39699
39704
|
missingKeyFrame: require_clip_model_registry.number(),
|
|
39705
|
+
/** No object event at all — its own number since D664. */
|
|
39706
|
+
missingEvent: require_clip_model_registry.number(),
|
|
39700
39707
|
missingBbox: require_clip_model_registry.number(),
|
|
39708
|
+
/** Which rule placed each judged track's box (D664). */
|
|
39709
|
+
boxSource: require_clip_model_registry.object({
|
|
39710
|
+
subjectBox: require_clip_model_registry.number(),
|
|
39711
|
+
positions: require_clip_model_registry.number(),
|
|
39712
|
+
event: require_clip_model_registry.number(),
|
|
39713
|
+
refused: require_clip_model_registry.number()
|
|
39714
|
+
}),
|
|
39715
|
+
alreadyInSpace: require_clip_model_registry.number(),
|
|
39716
|
+
/** Whether the current / last pass was a `force` pass (D664). */
|
|
39717
|
+
force: require_clip_model_registry.boolean().nullable(),
|
|
39718
|
+
forcedInSpace: require_clip_model_registry.number(),
|
|
39701
39719
|
/** Refused by the executing node (unreadable key frame / bad box), not broken. */
|
|
39702
39720
|
notRunnable: require_clip_model_registry.number(),
|
|
39703
39721
|
/** The pass STOPPED: no node in the cluster could serve the pinned model. */
|
|
@@ -40972,7 +40990,7 @@ function toPixelBox(b) {
|
|
|
40972
40990
|
h: b.height
|
|
40973
40991
|
};
|
|
40974
40992
|
}
|
|
40975
|
-
function refused(reason, detail) {
|
|
40993
|
+
function refused$1(reason, detail) {
|
|
40976
40994
|
return {
|
|
40977
40995
|
kind: "refused",
|
|
40978
40996
|
reason,
|
|
@@ -41000,8 +41018,8 @@ function comparableFaces(input) {
|
|
|
41000
41018
|
/** Refuse before choosing when nothing in the photo can become the sample. */
|
|
41001
41019
|
function precondition(input) {
|
|
41002
41020
|
const enrollable = input.faces.filter((f) => f.enrollable && f.embedding !== void 0);
|
|
41003
|
-
if (enrollable.length === 0) return refused("no-enrollable-face", `${input.faces.length} face(s) found, none enrollable (${input.faces.map((f) => f.refusedReason ?? "unknown").join(", ")})`);
|
|
41004
|
-
if (!enrollable.some((f) => isEnrollableIn(f, input.modelId))) return refused("model-mismatch", `faces were embedded by ${[...new Set(enrollable.map((f) => f.modelId))].join(", ")}, the old sample by ${input.modelId} — re-embed the gallery first`);
|
|
41021
|
+
if (enrollable.length === 0) return refused$1("no-enrollable-face", `${input.faces.length} face(s) found, none enrollable (${input.faces.map((f) => f.refusedReason ?? "unknown").join(", ")})`);
|
|
41022
|
+
if (!enrollable.some((f) => isEnrollableIn(f, input.modelId))) return refused$1("model-mismatch", `faces were embedded by ${[...new Set(enrollable.map((f) => f.modelId))].join(", ")}, the old sample by ${input.modelId} — re-embed the gallery first`);
|
|
41005
41023
|
return null;
|
|
41006
41024
|
}
|
|
41007
41025
|
function chooseByIou(input, oldBox, scored) {
|
|
@@ -41010,13 +41028,13 @@ function chooseByIou(input, oldBox, scored) {
|
|
|
41010
41028
|
face,
|
|
41011
41029
|
iou: iou$3(box, toPixelBox(face.bbox))
|
|
41012
41030
|
})).filter((c) => c.iou >= PHOTO_REENROL_MIN_IOU);
|
|
41013
|
-
if (overlapping.length === 0) return refused("no-iou-match", `no face overlaps the old box at IoU ≥ ${PHOTO_REENROL_MIN_IOU}`);
|
|
41014
|
-
if (overlapping.length > 1) return refused("ambiguous", `${overlapping.length} faces overlap the old box (IoU ${overlapping.map((c) => c.iou.toFixed(2)).join(", ")})`);
|
|
41031
|
+
if (overlapping.length === 0) return refused$1("no-iou-match", `no face overlaps the old box at IoU ≥ ${PHOTO_REENROL_MIN_IOU}`);
|
|
41032
|
+
if (overlapping.length > 1) return refused$1("ambiguous", `${overlapping.length} faces overlap the old box (IoU ${overlapping.map((c) => c.iou.toFixed(2)).join(", ")})`);
|
|
41015
41033
|
const [only] = overlapping;
|
|
41016
|
-
if (only === void 0) return refused("no-iou-match", "no overlapping face");
|
|
41017
|
-
if (!isEnrollableIn(only.face, input.modelId)) return refused("no-enrollable-face", `the face on the old box is not enrollable (${only.face.refusedReason ?? `model ${only.face.modelId ?? "none"}`})`);
|
|
41034
|
+
if (only === void 0) return refused$1("no-iou-match", "no overlapping face");
|
|
41035
|
+
if (!isEnrollableIn(only.face, input.modelId)) return refused$1("no-enrollable-face", `the face on the old box is not enrollable (${only.face.refusedReason ?? `model ${only.face.modelId ?? "none"}`})`);
|
|
41018
41036
|
const cosine = scored.find((s) => s.face === only.face)?.cosine;
|
|
41019
|
-
if (cosine === void 0 || cosine < .5) return refused("below-floor", `the overlapping face scores cosine ${cosine?.toFixed(3) ?? "n/a"} < ${PHOTO_REENROL_COSINE_FLOOR}`);
|
|
41037
|
+
if (cosine === void 0 || cosine < .5) return refused$1("below-floor", `the overlapping face scores cosine ${cosine?.toFixed(3) ?? "n/a"} < ${PHOTO_REENROL_COSINE_FLOOR}`);
|
|
41020
41038
|
return {
|
|
41021
41039
|
kind: "chosen",
|
|
41022
41040
|
face: only.face,
|
|
@@ -41027,10 +41045,10 @@ function chooseByIou(input, oldBox, scored) {
|
|
|
41027
41045
|
}
|
|
41028
41046
|
function chooseByCosine(input, scored) {
|
|
41029
41047
|
const [best, runnerUp] = [...scored].toSorted((a, b) => b.cosine - a.cosine);
|
|
41030
|
-
if (best === void 0) return refused("model-mismatch", "no face has a comparable vector");
|
|
41031
|
-
if (best.cosine < .5) return refused("below-floor", `best cosine ${best.cosine.toFixed(3)} < ${PHOTO_REENROL_COSINE_FLOOR}`);
|
|
41032
|
-
if (runnerUp !== void 0 && runnerUp.cosine >= .5 && best.cosine - runnerUp.cosine < .1) return refused("ambiguous", `two faces clear the floor within ${PHOTO_REENROL_AMBIGUITY_MARGIN}: ${best.cosine.toFixed(3)} vs ${runnerUp.cosine.toFixed(3)}`);
|
|
41033
|
-
if (!isEnrollableIn(best.face, input.modelId)) return refused("ambiguous", `the closest face (cosine ${best.cosine.toFixed(3)}) is not enrollable (${best.face.refusedReason ?? "unknown"}) — the enrollable ones may be someone else`);
|
|
41048
|
+
if (best === void 0) return refused$1("model-mismatch", "no face has a comparable vector");
|
|
41049
|
+
if (best.cosine < .5) return refused$1("below-floor", `best cosine ${best.cosine.toFixed(3)} < ${PHOTO_REENROL_COSINE_FLOOR}`);
|
|
41050
|
+
if (runnerUp !== void 0 && runnerUp.cosine >= .5 && best.cosine - runnerUp.cosine < .1) return refused$1("ambiguous", `two faces clear the floor within ${PHOTO_REENROL_AMBIGUITY_MARGIN}: ${best.cosine.toFixed(3)} vs ${runnerUp.cosine.toFixed(3)}`);
|
|
41051
|
+
if (!isEnrollableIn(best.face, input.modelId)) return refused$1("ambiguous", `the closest face (cosine ${best.cosine.toFixed(3)}) is not enrollable (${best.face.refusedReason ?? "unknown"}) — the enrollable ones may be someone else`);
|
|
41034
41052
|
return {
|
|
41035
41053
|
kind: "chosen",
|
|
41036
41054
|
face: best.face,
|
|
@@ -53746,11 +53764,10 @@ var EventStore = class {
|
|
|
53746
53764
|
let entryId;
|
|
53747
53765
|
for (const row of rows) {
|
|
53748
53766
|
const bbox = row.data["bbox"];
|
|
53749
|
-
if (bbox
|
|
53750
|
-
|
|
53751
|
-
|
|
53752
|
-
|
|
53753
|
-
}
|
|
53767
|
+
if (bbox === null || typeof bbox !== "object") continue;
|
|
53768
|
+
const bw = "w" in bbox && typeof bbox.w === "number" ? bbox.w : 0;
|
|
53769
|
+
const bh = "h" in bbox && typeof bbox.h === "number" ? bbox.h : 0;
|
|
53770
|
+
if (bw <= 0 || bh <= 0) continue;
|
|
53754
53771
|
const conf = typeof row.data["confidence"] === "number" ? row.data["confidence"] : 0;
|
|
53755
53772
|
if (conf > bestConf) {
|
|
53756
53773
|
bestConf = conf;
|
|
@@ -62453,6 +62470,26 @@ var EmbeddingDispatcher = class {
|
|
|
62453
62470
|
return this.pendingCrops.size;
|
|
62454
62471
|
}
|
|
62455
62472
|
};
|
|
62473
|
+
//#endregion
|
|
62474
|
+
//#region src/pipeline-analytics/embedding-rebuild.ts
|
|
62475
|
+
/**
|
|
62476
|
+
* Track sources a rebuild never lists (D664). An audio track and a synthetic
|
|
62477
|
+
* sensor track have no object event and no subject to embed — on the live hub
|
|
62478
|
+
* 6,726 + 180 of 42,254 tracks — and walking them only inflated the skip
|
|
62479
|
+
* counters an operator reads to judge media coverage.
|
|
62480
|
+
*/
|
|
62481
|
+
var REBUILD_EXCLUDED_SOURCES = ["audio", "sensor"];
|
|
62482
|
+
/**
|
|
62483
|
+
* One page of the rebuild listing as a `queryRecentIds` query. Pure, so the
|
|
62484
|
+
* exclusion is assertable: dropping it would look identical in every result
|
|
62485
|
+
* except the skip counters.
|
|
62486
|
+
*/
|
|
62487
|
+
function rebuildTrackPageQuery(window) {
|
|
62488
|
+
return {
|
|
62489
|
+
...window,
|
|
62490
|
+
excludeSources: REBUILD_EXCLUDED_SOURCES
|
|
62491
|
+
};
|
|
62492
|
+
}
|
|
62456
62493
|
/**
|
|
62457
62494
|
* Re-embed every listed track from its key frame.
|
|
62458
62495
|
*
|
|
@@ -62468,6 +62505,14 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62468
62505
|
let recoveredKeyFrame = 0;
|
|
62469
62506
|
let missingEvent = 0;
|
|
62470
62507
|
let missingBbox = 0;
|
|
62508
|
+
let boxSubject = 0;
|
|
62509
|
+
let boxPositions = 0;
|
|
62510
|
+
let boxEvent = 0;
|
|
62511
|
+
let boxRefused = 0;
|
|
62512
|
+
let forcedInSpace = 0;
|
|
62513
|
+
let skippedOutOfSpace = 0;
|
|
62514
|
+
const refusalsByDevice = /* @__PURE__ */ new Map();
|
|
62515
|
+
const force = options.force === true;
|
|
62471
62516
|
let alreadyInSpace = 0;
|
|
62472
62517
|
let notRunnable = 0;
|
|
62473
62518
|
let noCapableNode = 0;
|
|
@@ -62478,6 +62523,12 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62478
62523
|
let budgetExhausted = false;
|
|
62479
62524
|
/** Set when the cluster ran out of nodes — the pass stops, `complete` is false. */
|
|
62480
62525
|
let abandoned = null;
|
|
62526
|
+
const boxSourceCounts = () => ({
|
|
62527
|
+
subjectBox: boxSubject,
|
|
62528
|
+
positions: boxPositions,
|
|
62529
|
+
event: boxEvent,
|
|
62530
|
+
refused: boxRefused
|
|
62531
|
+
});
|
|
62481
62532
|
while (scanned < maxTracks && abandoned === null) {
|
|
62482
62533
|
const page = await deps.listTrackIdPage(cursor);
|
|
62483
62534
|
if (page.trackIds.length === 0) {
|
|
@@ -62485,9 +62536,14 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62485
62536
|
break;
|
|
62486
62537
|
}
|
|
62487
62538
|
let pageIds = page.trackIds;
|
|
62539
|
+
let forcedPage = false;
|
|
62488
62540
|
if (deps.filterOutOfSpace) {
|
|
62489
62541
|
const split = await deps.filterOutOfSpace(page.trackIds);
|
|
62490
|
-
if (split !== null) {
|
|
62542
|
+
if (split !== null && force) {
|
|
62543
|
+
skippedOutOfSpace += split.outOfSpace.length;
|
|
62544
|
+
pageIds = split.inSpace;
|
|
62545
|
+
forcedPage = true;
|
|
62546
|
+
} else if (split !== null) {
|
|
62491
62547
|
alreadyInSpace += split.alreadyInSpace;
|
|
62492
62548
|
pageIds = split.outOfSpace;
|
|
62493
62549
|
}
|
|
@@ -62503,6 +62559,7 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62503
62559
|
const room = maxTracks - scanned;
|
|
62504
62560
|
const batch = pageIds.slice(0, Number.isFinite(room) ? room : void 0);
|
|
62505
62561
|
if (batch.length < pageIds.length) budgetExhausted = true;
|
|
62562
|
+
if (forcedPage) forcedInSpace += batch.length;
|
|
62506
62563
|
for (const trackId of batch) {
|
|
62507
62564
|
if (!deps.canDispatch()) {
|
|
62508
62565
|
abandoned = "no node left in the rotation can serve the pinned model — stopped before loading any further media";
|
|
@@ -62521,6 +62578,25 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62521
62578
|
missingEvent += 1;
|
|
62522
62579
|
return;
|
|
62523
62580
|
}
|
|
62581
|
+
if (source.bbox === null || source.bbox.w <= 0 || source.bbox.h <= 0) {
|
|
62582
|
+
missingBbox += 1;
|
|
62583
|
+
boxRefused += 1;
|
|
62584
|
+
const reason = source.boxSource.kind === "refused" ? source.boxSource.reason : "degenerate-box";
|
|
62585
|
+
const n = (refusalsByDevice.get(source.deviceId) ?? 0) + 1;
|
|
62586
|
+
refusalsByDevice.set(source.deviceId, n);
|
|
62587
|
+
if (n === 1 || n % 100 === 0) deps.logger.warn("embedding rebuild: no box measured on the key frame — track refused (D303)", {
|
|
62588
|
+
tags: { deviceId: source.deviceId },
|
|
62589
|
+
meta: {
|
|
62590
|
+
trackId,
|
|
62591
|
+
reason,
|
|
62592
|
+
refusedOnThisCamera: n
|
|
62593
|
+
}
|
|
62594
|
+
});
|
|
62595
|
+
return;
|
|
62596
|
+
}
|
|
62597
|
+
if (source.boxSource.kind === "subjectBox") boxSubject += 1;
|
|
62598
|
+
else if (source.boxSource.kind === "positions") boxPositions += 1;
|
|
62599
|
+
else boxEvent += 1;
|
|
62524
62600
|
let keyFrame = source.keyFrame;
|
|
62525
62601
|
let recovered = false;
|
|
62526
62602
|
if (keyFrame === null && deps.recoverKeyFrame) {
|
|
@@ -62532,10 +62608,6 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62532
62608
|
return;
|
|
62533
62609
|
}
|
|
62534
62610
|
if (recovered) recoveredKeyFrame += 1;
|
|
62535
|
-
if (source.bbox === null || source.bbox.w <= 0 || source.bbox.h <= 0) {
|
|
62536
|
-
missingBbox += 1;
|
|
62537
|
-
return;
|
|
62538
|
-
}
|
|
62539
62611
|
const outcome = await deps.embed(recovered ? {
|
|
62540
62612
|
...source,
|
|
62541
62613
|
keyFrame
|
|
@@ -62603,6 +62675,9 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62603
62675
|
recoveredKeyFrame,
|
|
62604
62676
|
missingEvent,
|
|
62605
62677
|
missingBbox,
|
|
62678
|
+
boxSource: boxSourceCounts(),
|
|
62679
|
+
forcedInSpace,
|
|
62680
|
+
skippedOutOfSpace,
|
|
62606
62681
|
alreadyInSpace,
|
|
62607
62682
|
notRunnable,
|
|
62608
62683
|
noCapableNode,
|
|
@@ -62626,6 +62701,10 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62626
62701
|
recoveredKeyFrame,
|
|
62627
62702
|
missingEvent,
|
|
62628
62703
|
missingBbox,
|
|
62704
|
+
boxSource: boxSourceCounts(),
|
|
62705
|
+
force,
|
|
62706
|
+
forcedInSpace,
|
|
62707
|
+
skippedOutOfSpace,
|
|
62629
62708
|
alreadyInSpace,
|
|
62630
62709
|
notRunnable,
|
|
62631
62710
|
noCapableNode,
|
|
@@ -62640,6 +62719,9 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62640
62719
|
recoveredKeyFrame,
|
|
62641
62720
|
missingEvent,
|
|
62642
62721
|
missingBbox,
|
|
62722
|
+
boxSource: boxSourceCounts(),
|
|
62723
|
+
forcedInSpace,
|
|
62724
|
+
skippedOutOfSpace,
|
|
62643
62725
|
alreadyInSpace,
|
|
62644
62726
|
notRunnable,
|
|
62645
62727
|
noCapableNode,
|
|
@@ -62996,8 +63078,6 @@ var FaceSettingsSchema = require_clip_model_registry.object({
|
|
|
62996
63078
|
* (2026-07-23), then →0.12 (2026-08-18) alongside the threshold retune —
|
|
62997
63079
|
* same story and the same recalibration plan as {@link similarityThreshold}. */
|
|
62998
63080
|
margin: require_clip_model_registry.number().min(0).max(1).default(.12),
|
|
62999
|
-
/** Minimum face-detection confidence for a face to be considered. */
|
|
63000
|
-
minFaceConfidence: require_clip_model_registry.number().min(0).max(1).default(.5),
|
|
63001
63081
|
/**
|
|
63002
63082
|
* Minimum face bbox size (px, shorter side, NATIVE scale when the runner
|
|
63003
63083
|
* measured it, else detection-frame space) for a face to be DETECTED and
|
|
@@ -63079,7 +63159,6 @@ function resolveFaceSettings(raw) {
|
|
|
63079
63159
|
enabled: pick("enabled"),
|
|
63080
63160
|
similarityThreshold: pick("similarityThreshold"),
|
|
63081
63161
|
margin: pick("margin"),
|
|
63082
|
-
minFaceConfidence: pick("minFaceConfidence"),
|
|
63083
63162
|
minFacePx: pick("minFacePx"),
|
|
63084
63163
|
recognitionMinFacePx: pick("recognitionMinFacePx"),
|
|
63085
63164
|
minIdentitySamples: pick("minIdentitySamples"),
|
|
@@ -63152,6 +63231,17 @@ function deriveSuggestedBufferCap(bufferMaxPerDevice) {
|
|
|
63152
63231
|
* it from a store.
|
|
63153
63232
|
*/
|
|
63154
63233
|
var STORED_SUGGESTION_MIN_COSINE_KEY = "suggestionMinCosine";
|
|
63234
|
+
/** The settings key that held the retired recognizer face-confidence bar (D662). */
|
|
63235
|
+
var STORED_MIN_FACE_CONFIDENCE_KEY = "minFaceConfidence";
|
|
63236
|
+
/** Plan the removal of ONE retired key from a settings blob; `null` = absent. */
|
|
63237
|
+
function planRetiredKeyPurge(raw, key) {
|
|
63238
|
+
const was = raw[key];
|
|
63239
|
+
if (was === void 0) return null;
|
|
63240
|
+
return {
|
|
63241
|
+
was,
|
|
63242
|
+
patch: { [key]: void 0 }
|
|
63243
|
+
};
|
|
63244
|
+
}
|
|
63155
63245
|
/**
|
|
63156
63246
|
* Plan the removal of a persisted suggestion floor from one settings blob.
|
|
63157
63247
|
*
|
|
@@ -63166,12 +63256,15 @@ var STORED_SUGGESTION_MIN_COSINE_KEY = "suggestionMinCosine";
|
|
|
63166
63256
|
* serialisation the blob round-trips through.
|
|
63167
63257
|
*/
|
|
63168
63258
|
function planStoredSuggestionPurge(raw) {
|
|
63169
|
-
|
|
63170
|
-
|
|
63171
|
-
|
|
63172
|
-
|
|
63173
|
-
|
|
63174
|
-
|
|
63259
|
+
return planRetiredKeyPurge(raw, STORED_SUGGESTION_MIN_COSINE_KEY);
|
|
63260
|
+
}
|
|
63261
|
+
/**
|
|
63262
|
+
* Plan the removal of a persisted `minFaceConfidence` (D662). Same contract as
|
|
63263
|
+
* {@link planStoredSuggestionPurge}: absence of the key is the marker, and the
|
|
63264
|
+
* patch unsets with `undefined`.
|
|
63265
|
+
*/
|
|
63266
|
+
function planStoredMinFaceConfidencePurge(raw) {
|
|
63267
|
+
return planRetiredKeyPurge(raw, STORED_MIN_FACE_CONFIDENCE_KEY);
|
|
63175
63268
|
}
|
|
63176
63269
|
/**
|
|
63177
63270
|
* Map a detection-frame face short side to the 0..1 `sizeScore` the
|
|
@@ -63460,7 +63553,7 @@ var FaceRecognizer = class {
|
|
|
63460
63553
|
async processFrame(input) {
|
|
63461
63554
|
const { settings } = input;
|
|
63462
63555
|
for (const t of input.tracked) if (t.resurrectionScene === "multi-subject") this.quarantineHeldFace(input.deviceId, t.trackId);
|
|
63463
|
-
const candidates = input.tracked.filter((t) => Array.isArray(t.embedding) && t.embedding.length > 0 && typeof t.embeddingModelId === "string" &&
|
|
63556
|
+
const candidates = input.tracked.filter((t) => Array.isArray(t.embedding) && t.embedding.length > 0 && typeof t.embeddingModelId === "string" && (t.nativeFaceShortSidePx ?? (t.faceBbox ? Math.min(t.faceBbox.w, t.faceBbox.h) : void 0) ?? Number.POSITIVE_INFINITY) >= settings.minFacePx);
|
|
63464
63557
|
if (candidates.length === 0) return;
|
|
63465
63558
|
this.deps.logger.debug("face: frame candidates", {
|
|
63466
63559
|
tags: { deviceId: input.deviceId },
|
|
@@ -73027,6 +73120,58 @@ function hasKeyFrame(source) {
|
|
|
73027
73120
|
}
|
|
73028
73121
|
//#endregion
|
|
73029
73122
|
//#region src/pipeline-analytics/rebuild-source-loader.ts
|
|
73123
|
+
function refused(reason) {
|
|
73124
|
+
return {
|
|
73125
|
+
bbox: null,
|
|
73126
|
+
boxSource: {
|
|
73127
|
+
kind: "refused",
|
|
73128
|
+
reason
|
|
73129
|
+
}
|
|
73130
|
+
};
|
|
73131
|
+
}
|
|
73132
|
+
function normaliseMeasured(box) {
|
|
73133
|
+
if (box.frameWidth <= 0 || box.frameHeight <= 0 || box.w <= 0 || box.h <= 0) return null;
|
|
73134
|
+
return {
|
|
73135
|
+
x: box.x / box.frameWidth,
|
|
73136
|
+
y: box.y / box.frameHeight,
|
|
73137
|
+
w: box.w / box.frameWidth,
|
|
73138
|
+
h: box.h / box.frameHeight
|
|
73139
|
+
};
|
|
73140
|
+
}
|
|
73141
|
+
/**
|
|
73142
|
+
* The box measured on THIS key frame: its own `subjectBox`, else the track
|
|
73143
|
+
* position at exactly its instant, else a named refusal. Never another
|
|
73144
|
+
* frame's box (D303).
|
|
73145
|
+
*/
|
|
73146
|
+
async function keyFrameBox(deps, trackId, keyFrame) {
|
|
73147
|
+
const own = (await deps.media.listSubjectBoxesByOwner("track", trackId)).find((row) => row.mediaId === keyFrame.mediaId);
|
|
73148
|
+
if (own !== void 0) {
|
|
73149
|
+
const bbox = normaliseMeasured(own.subjectBox);
|
|
73150
|
+
if (bbox !== null) return {
|
|
73151
|
+
bbox,
|
|
73152
|
+
boxSource: { kind: "subjectBox" }
|
|
73153
|
+
};
|
|
73154
|
+
}
|
|
73155
|
+
const track = await deps.tracks.getPersistedByTrackId(trackId);
|
|
73156
|
+
if (track === null) return refused("track-row-missing");
|
|
73157
|
+
const { frameWidth, frameHeight } = track;
|
|
73158
|
+
if (frameWidth === void 0 || frameHeight === void 0) return refused("track-frame-size-unknown");
|
|
73159
|
+
const at = track.positions.find((p) => p.timestamp === keyFrame.timestamp);
|
|
73160
|
+
if (at === void 0) return refused("no-position-at-key-frame");
|
|
73161
|
+
const bbox = normaliseMeasured({
|
|
73162
|
+
...at.bbox,
|
|
73163
|
+
frameWidth,
|
|
73164
|
+
frameHeight
|
|
73165
|
+
});
|
|
73166
|
+
if (bbox === null) return refused("no-position-at-key-frame");
|
|
73167
|
+
return {
|
|
73168
|
+
bbox,
|
|
73169
|
+
boxSource: { kind: "positions" }
|
|
73170
|
+
};
|
|
73171
|
+
}
|
|
73172
|
+
function hasBox(event) {
|
|
73173
|
+
return event.bbox !== void 0 && event.bbox.w > 0 && event.bbox.h > 0;
|
|
73174
|
+
}
|
|
73030
73175
|
/**
|
|
73031
73176
|
* Assemble one track's rebuild inputs, reading at most ONE blob.
|
|
73032
73177
|
*
|
|
@@ -73034,7 +73179,8 @@ function hasKeyFrame(source) {
|
|
|
73034
73179
|
* to describe, and the caller counts it. A track WITH an event but WITHOUT a
|
|
73035
73180
|
* key frame still returns a source (with `keyFrame: null`) so the caller's
|
|
73036
73181
|
* `missingKeyFrame` counter stays the one place that decision is made; no blob
|
|
73037
|
-
* is read in that case either.
|
|
73182
|
+
* is read in that case either. A key frame with no box measured on it returns
|
|
73183
|
+
* `bbox: null` and a named refusal, also without reading the blob.
|
|
73038
73184
|
*/
|
|
73039
73185
|
async function loadRebuildSource(deps, trackId) {
|
|
73040
73186
|
const media = await deps.media.listInfoByOwner("track", trackId);
|
|
@@ -73042,26 +73188,44 @@ async function loadRebuildSource(deps, trackId) {
|
|
|
73042
73188
|
const cropInfo = media.find((m) => m.kind === "thumbnail");
|
|
73043
73189
|
const peak = await deps.events.peakForTrack(trackId);
|
|
73044
73190
|
const events = await deps.events.queryObjectByTrackIds([trackId]);
|
|
73045
|
-
const best = events.find((e) => String(e.id) === peak.bestEventId) ?? events[0];
|
|
73191
|
+
const best = events.find((e) => String(e.id) === peak.bestEventId) ?? events.find(hasBox) ?? events[0];
|
|
73046
73192
|
if (best === void 0) return null;
|
|
73047
73193
|
const common = {
|
|
73048
73194
|
trackId,
|
|
73049
73195
|
deviceId: best.deviceId,
|
|
73050
|
-
timestamp: best.timestamp,
|
|
73051
73196
|
className: best.className,
|
|
73052
73197
|
confidence: best.confidence ?? 0,
|
|
73053
|
-
bbox: normaliseEventBbox(best),
|
|
73054
73198
|
...cropInfo !== void 0 ? { mediaId: cropInfo.mediaId } : {}
|
|
73055
73199
|
};
|
|
73056
|
-
if (keyFrameInfo === void 0)
|
|
73200
|
+
if (keyFrameInfo === void 0) {
|
|
73201
|
+
const bbox = normaliseEventBbox(best);
|
|
73202
|
+
return {
|
|
73203
|
+
...common,
|
|
73204
|
+
timestamp: best.timestamp,
|
|
73205
|
+
bbox,
|
|
73206
|
+
boxSource: bbox !== null ? { kind: "event" } : {
|
|
73207
|
+
kind: "refused",
|
|
73208
|
+
reason: "event-without-box"
|
|
73209
|
+
},
|
|
73210
|
+
keyFrame: null
|
|
73211
|
+
};
|
|
73212
|
+
}
|
|
73213
|
+
const box = await keyFrameBox(deps, trackId, keyFrameInfo);
|
|
73214
|
+
const keyed = {
|
|
73057
73215
|
...common,
|
|
73216
|
+
timestamp: keyFrameInfo.timestamp,
|
|
73217
|
+
bbox: box.bbox,
|
|
73218
|
+
boxSource: box.boxSource,
|
|
73219
|
+
keyFrameMediaId: keyFrameInfo.mediaId
|
|
73220
|
+
};
|
|
73221
|
+
if (box.bbox === null) return {
|
|
73222
|
+
...keyed,
|
|
73058
73223
|
keyFrame: null
|
|
73059
73224
|
};
|
|
73060
73225
|
const keyFrameFile = await deps.media.getById(keyFrameInfo.mediaId);
|
|
73061
73226
|
return {
|
|
73062
|
-
...
|
|
73063
|
-
keyFrame: keyFrameFile ? Buffer.from(keyFrameFile.base64, "base64") : null
|
|
73064
|
-
keyFrameMediaId: keyFrameInfo.mediaId
|
|
73227
|
+
...keyed,
|
|
73228
|
+
keyFrame: keyFrameFile ? Buffer.from(keyFrameFile.base64, "base64") : null
|
|
73065
73229
|
};
|
|
73066
73230
|
}
|
|
73067
73231
|
//#endregion
|
|
@@ -83610,7 +83774,7 @@ function buildGlobalSettingsSchema(cap) {
|
|
|
83610
83774
|
addonId: "pipeline-analytics",
|
|
83611
83775
|
action: "embedding.rebuildStatus",
|
|
83612
83776
|
buttonLabel: "Check progress",
|
|
83613
|
-
successMessage: "{modelId} → {index}: indexed {indexed} · scanned {scanned} · rebuilt {rebuilt} · no key frame {missingKeyFrame} · not runnable {notRunnable} · failed {failed}"
|
|
83777
|
+
successMessage: "{modelId} → {index}: indexed {indexed} · scanned {scanned} · rebuilt {rebuilt} · no key frame {missingKeyFrame} · no box {missingBbox} · no event {missingEvent} · not runnable {notRunnable} · failed {failed}"
|
|
83614
83778
|
},
|
|
83615
83779
|
{
|
|
83616
83780
|
type: "addon-action-button",
|
|
@@ -84162,16 +84326,6 @@ function buildGlobalSettingsSchema(cap) {
|
|
|
84162
84326
|
step: .01,
|
|
84163
84327
|
default: FACE_DEFAULTS.margin
|
|
84164
84328
|
},
|
|
84165
|
-
{
|
|
84166
|
-
type: "number",
|
|
84167
|
-
key: "minFaceConfidence",
|
|
84168
|
-
label: "Min face confidence",
|
|
84169
|
-
description: "Minimum face-detection confidence (0–1) for a face to be considered.",
|
|
84170
|
-
min: 0,
|
|
84171
|
-
max: 1,
|
|
84172
|
-
step: .05,
|
|
84173
|
-
default: FACE_DEFAULTS.minFaceConfidence
|
|
84174
|
-
},
|
|
84175
84329
|
{
|
|
84176
84330
|
type: "number",
|
|
84177
84331
|
key: "minFacePx",
|
|
@@ -94951,6 +95105,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
94951
95105
|
const deviceIds = await this.retentionDeviceIds();
|
|
94952
95106
|
await this.migrateRetiredRetentionSettings(deviceIds);
|
|
94953
95107
|
await this.purgeStoredSuggestionThreshold(deviceIds);
|
|
95108
|
+
await this.purgeStoredMinFaceConfidence(deviceIds);
|
|
94954
95109
|
await this.runTrackRetentionSweep(deviceIds, now);
|
|
94955
95110
|
const eventStore = this.eventStore;
|
|
94956
95111
|
const sensorEventStore = this.sensorEventStore;
|
|
@@ -95078,6 +95233,80 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
95078
95233
|
* this process, and which devices have. One announcement, not a heartbeat. */
|
|
95079
95234
|
storedSuggestionCheckedGlobal = false;
|
|
95080
95235
|
storedSuggestionCheckedDevices = /* @__PURE__ */ new Set();
|
|
95236
|
+
storedMinFaceConfidenceCheckedGlobal = false;
|
|
95237
|
+
storedMinFaceConfidenceCheckedDevices = /* @__PURE__ */ new Set();
|
|
95238
|
+
/**
|
|
95239
|
+
* One-time: announce the recognizer face-confidence bar D662 retired, then
|
|
95240
|
+
* unset it — globally and per device. Same shape as
|
|
95241
|
+
* {@link purgeStoredSuggestionThreshold}: absence of the key is the marker,
|
|
95242
|
+
* the write goes through `updateGlobalSettings` / `writeDeviceStore`, and the
|
|
95243
|
+
* patch unsets with `undefined`.
|
|
95244
|
+
*
|
|
95245
|
+
* Why it must leave the store and not merely go unread: the bar compared the
|
|
95246
|
+
* DETECTOR's score without knowing which detector produced it, so its units
|
|
95247
|
+
* changed under it when YuNet became the default (D645). A number left in the
|
|
95248
|
+
* blob is an authority the next reader who greps for it would re-adopt — at a
|
|
95249
|
+
* scale nobody can name. The hub carried an interim 0.85 set by hand on
|
|
95250
|
+
* 2026-09-27; the one bar in force is now the detector model's own floor.
|
|
95251
|
+
*/
|
|
95252
|
+
async purgeStoredMinFaceConfidence(deviceIds) {
|
|
95253
|
+
const settings = this.ctxIfReady?.settings;
|
|
95254
|
+
if (!settings) return;
|
|
95255
|
+
if (!this.storedMinFaceConfidenceCheckedGlobal) {
|
|
95256
|
+
this.storedMinFaceConfidenceCheckedGlobal = true;
|
|
95257
|
+
try {
|
|
95258
|
+
const plan = planStoredMinFaceConfidencePurge(await this.resolveGlobalStore());
|
|
95259
|
+
if (plan !== null) {
|
|
95260
|
+
this.announceRetiredFaceConfidenceBar({
|
|
95261
|
+
scope: "global",
|
|
95262
|
+
was: plan.was
|
|
95263
|
+
});
|
|
95264
|
+
await this.updateGlobalSettings(plan.patch);
|
|
95265
|
+
}
|
|
95266
|
+
} catch (err) {
|
|
95267
|
+
this.storedMinFaceConfidenceCheckedGlobal = false;
|
|
95268
|
+
this.ctx.logger.warn("face confidence bar purge failed — will retry", { meta: {
|
|
95269
|
+
scope: "global",
|
|
95270
|
+
error: String(err)
|
|
95271
|
+
} });
|
|
95272
|
+
}
|
|
95273
|
+
}
|
|
95274
|
+
for (const deviceId of deviceIds) {
|
|
95275
|
+
if (this.storedMinFaceConfidenceCheckedDevices.has(deviceId)) continue;
|
|
95276
|
+
this.storedMinFaceConfidenceCheckedDevices.add(deviceId);
|
|
95277
|
+
try {
|
|
95278
|
+
const plan = planStoredMinFaceConfidencePurge(await this.readDeviceBlob(deviceId));
|
|
95279
|
+
if (plan === null) continue;
|
|
95280
|
+
this.announceRetiredFaceConfidenceBar({
|
|
95281
|
+
scope: "device",
|
|
95282
|
+
was: plan.was,
|
|
95283
|
+
deviceId
|
|
95284
|
+
});
|
|
95285
|
+
await settings.writeDeviceStore(deviceId, plan.patch);
|
|
95286
|
+
this.rawDeviceBlobMirror.invalidate(deviceId);
|
|
95287
|
+
} catch (err) {
|
|
95288
|
+
this.storedMinFaceConfidenceCheckedDevices.delete(deviceId);
|
|
95289
|
+
this.ctx.logger.warn("face confidence bar purge failed — will retry", {
|
|
95290
|
+
tags: { deviceId },
|
|
95291
|
+
meta: {
|
|
95292
|
+
scope: "device",
|
|
95293
|
+
error: String(err)
|
|
95294
|
+
}
|
|
95295
|
+
});
|
|
95296
|
+
}
|
|
95297
|
+
}
|
|
95298
|
+
}
|
|
95299
|
+
announceRetiredFaceConfidenceBar(found) {
|
|
95300
|
+
this.ctx.logger.warn("face confidence bar RETIRED — the detector model floor on the runner is the one bar now", {
|
|
95301
|
+
...found.deviceId !== void 0 ? { tags: { deviceId: found.deviceId } } : {},
|
|
95302
|
+
meta: {
|
|
95303
|
+
scope: found.scope,
|
|
95304
|
+
setting: STORED_MIN_FACE_CONFIDENCE_KEY,
|
|
95305
|
+
wasSetTo: found.was,
|
|
95306
|
+
why: "the recognizer compared the detector score without knowing which detector ran; after YuNet became the default its 0.5 was SCRFD’s bar on YuNet’s scale (D662)."
|
|
95307
|
+
}
|
|
95308
|
+
});
|
|
95309
|
+
}
|
|
95081
95310
|
/**
|
|
95082
95311
|
* One-time: announce the suggestion floor D222 retired, then unset it —
|
|
95083
95312
|
* globally and per device.
|
|
@@ -97132,6 +97361,15 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
97132
97361
|
refusal: "stores-unavailable"
|
|
97133
97362
|
};
|
|
97134
97363
|
}
|
|
97364
|
+
const force = input.force === true;
|
|
97365
|
+
if (force && input.maxTracks === void 0) {
|
|
97366
|
+
this.ctx.logger.warn("rebuildObjectEmbeddings: refusing a force pass with no maxTracks", { meta: { refusal: "force-requires-max-tracks" } });
|
|
97367
|
+
return {
|
|
97368
|
+
started: false,
|
|
97369
|
+
alreadyRunning: false,
|
|
97370
|
+
refusal: "force-requires-max-tracks"
|
|
97371
|
+
};
|
|
97372
|
+
}
|
|
97135
97373
|
const confirmation = await this.getClusterPinConfirmer(api, "clip-rebuild").confirm();
|
|
97136
97374
|
if (confirmation.kind === "refused") {
|
|
97137
97375
|
this.ctx.logger.warn("rebuildObjectEmbeddings: the cluster CLIP model is not confirmed — refusing to start a pass that cannot pin one", { meta: { refusal: confirmation.reason } });
|
|
@@ -97175,16 +97413,17 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
97175
97413
|
logger: this.ctx.logger
|
|
97176
97414
|
}));
|
|
97177
97415
|
const deps = {
|
|
97178
|
-
listTrackIdPage: async (cursor) => trackStore.queryRecentIds({
|
|
97416
|
+
listTrackIdPage: async (cursor) => trackStore.queryRecentIds(rebuildTrackPageQuery({
|
|
97179
97417
|
deviceIds,
|
|
97180
97418
|
...input.since !== void 0 ? { since: input.since } : {},
|
|
97181
97419
|
...input.until !== void 0 ? { until: input.until } : {},
|
|
97182
97420
|
...cursor !== null ? { cursor } : {},
|
|
97183
97421
|
limit: REBUILD_PAGE_SIZE
|
|
97184
|
-
}),
|
|
97422
|
+
})),
|
|
97185
97423
|
loadSource: (trackId) => loadRebuildSource({
|
|
97186
97424
|
media: mediaStore,
|
|
97187
|
-
events: eventStore
|
|
97425
|
+
events: eventStore,
|
|
97426
|
+
tracks: trackStore
|
|
97188
97427
|
}, trackId),
|
|
97189
97428
|
recoverKeyFrame: async (source) => {
|
|
97190
97429
|
const recovered = await recordedStills.recover(source.deviceId, source.timestamp, RECOVERED_KEY_FRAME_MAX_WIDTH);
|
|
@@ -97210,7 +97449,8 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
97210
97449
|
if (split === null) return null;
|
|
97211
97450
|
return {
|
|
97212
97451
|
outOfSpace: split.outOfSpaceIds,
|
|
97213
|
-
alreadyInSpace: split.inSpace
|
|
97452
|
+
alreadyInSpace: split.inSpace,
|
|
97453
|
+
inSpace: split.inSpaceIds
|
|
97214
97454
|
};
|
|
97215
97455
|
},
|
|
97216
97456
|
logger: {
|
|
@@ -97222,6 +97462,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
97222
97462
|
running: true,
|
|
97223
97463
|
modelId,
|
|
97224
97464
|
index,
|
|
97465
|
+
force,
|
|
97225
97466
|
startedAtMs: Date.now(),
|
|
97226
97467
|
progress: {
|
|
97227
97468
|
scanned: 0,
|
|
@@ -97230,6 +97471,14 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
97230
97471
|
recoveredKeyFrame: 0,
|
|
97231
97472
|
missingEvent: 0,
|
|
97232
97473
|
missingBbox: 0,
|
|
97474
|
+
boxSource: {
|
|
97475
|
+
subjectBox: 0,
|
|
97476
|
+
positions: 0,
|
|
97477
|
+
event: 0,
|
|
97478
|
+
refused: 0
|
|
97479
|
+
},
|
|
97480
|
+
forcedInSpace: 0,
|
|
97481
|
+
skippedOutOfSpace: 0,
|
|
97233
97482
|
alreadyInSpace: 0,
|
|
97234
97483
|
notRunnable: 0,
|
|
97235
97484
|
noCapableNode: 0,
|
|
@@ -97237,6 +97486,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
97237
97486
|
}
|
|
97238
97487
|
};
|
|
97239
97488
|
rebuildObjectEmbeddings(deps, {
|
|
97489
|
+
force,
|
|
97240
97490
|
...input.maxTracks !== void 0 ? { maxTracks: input.maxTracks } : {},
|
|
97241
97491
|
...input.pacingMs !== void 0 ? { pacingMs: input.pacingMs } : {},
|
|
97242
97492
|
onProgress: (progress) => {
|
|
@@ -97248,6 +97498,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
97248
97498
|
running: false,
|
|
97249
97499
|
modelId,
|
|
97250
97500
|
index,
|
|
97501
|
+
force,
|
|
97251
97502
|
startedAtMs: this.rebuildState.startedAtMs ?? Date.now(),
|
|
97252
97503
|
finishedAtMs: Date.now(),
|
|
97253
97504
|
progress: outcome,
|
|
@@ -97263,6 +97514,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
97263
97514
|
running: false,
|
|
97264
97515
|
modelId,
|
|
97265
97516
|
index,
|
|
97517
|
+
force,
|
|
97266
97518
|
startedAtMs: this.rebuildState.startedAtMs ?? Date.now(),
|
|
97267
97519
|
finishedAtMs: Date.now(),
|
|
97268
97520
|
error: String(err)
|
|
@@ -97277,7 +97529,8 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
97277
97529
|
modelId,
|
|
97278
97530
|
index,
|
|
97279
97531
|
deviceId: input.deviceId ?? "all",
|
|
97280
|
-
maxTracks: input.maxTracks ?? "unbounded"
|
|
97532
|
+
maxTracks: input.maxTracks ?? "unbounded",
|
|
97533
|
+
force
|
|
97281
97534
|
} });
|
|
97282
97535
|
return {
|
|
97283
97536
|
started: true,
|
|
@@ -98279,8 +98532,18 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
98279
98532
|
running: state.running,
|
|
98280
98533
|
scanned: p?.scanned ?? 0,
|
|
98281
98534
|
rebuilt: p?.rebuilt ?? 0,
|
|
98282
|
-
missingKeyFrame:
|
|
98535
|
+
missingKeyFrame: p?.missingKeyFrame ?? 0,
|
|
98536
|
+
missingEvent: p?.missingEvent ?? 0,
|
|
98283
98537
|
missingBbox: p?.missingBbox ?? 0,
|
|
98538
|
+
boxSource: p?.boxSource ?? {
|
|
98539
|
+
subjectBox: 0,
|
|
98540
|
+
positions: 0,
|
|
98541
|
+
event: 0,
|
|
98542
|
+
refused: 0
|
|
98543
|
+
},
|
|
98544
|
+
alreadyInSpace: p?.alreadyInSpace ?? 0,
|
|
98545
|
+
force: state.force ?? null,
|
|
98546
|
+
forcedInSpace: p?.forcedInSpace ?? 0,
|
|
98284
98547
|
notRunnable: p?.notRunnable ?? 0,
|
|
98285
98548
|
noCapableNode: p?.noCapableNode ?? 0,
|
|
98286
98549
|
failed: p?.failed ?? 0,
|