@camstack/addon-post-analysis 1.2.44 → 1.2.46
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.
|
@@ -12169,8 +12169,15 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
12169
12169
|
failed += 1;
|
|
12170
12170
|
continue;
|
|
12171
12171
|
}
|
|
12172
|
-
await deps.store(source, embedding);
|
|
12173
|
-
rebuilt += 1;
|
|
12172
|
+
const outcome = await deps.store(source, embedding);
|
|
12173
|
+
if (outcome === "persisted") rebuilt += 1;
|
|
12174
|
+
else {
|
|
12175
|
+
failed += 1;
|
|
12176
|
+
deps.logger.warn("embedding rebuild wrote nothing for a track", { meta: {
|
|
12177
|
+
trackId,
|
|
12178
|
+
outcome
|
|
12179
|
+
} });
|
|
12180
|
+
}
|
|
12174
12181
|
} catch (err) {
|
|
12175
12182
|
failed += 1;
|
|
12176
12183
|
deps.logger.warn("embedding rebuild failed for a track", { meta: {
|
|
@@ -20597,6 +20604,14 @@ var ObjectEmbeddingStore = class {
|
|
|
20597
20604
|
* write: the provider rejects an upsert into an index it has never seen. A
|
|
20598
20605
|
* dim change against a populated index is REFUSED rather than wiping it, so
|
|
20599
20606
|
* this failing is the signal that the encoder model changed.
|
|
20607
|
+
*
|
|
20608
|
+
* `declaredDim` caches the declaration, and that cache is per-PROCESS while
|
|
20609
|
+
* the index lives in whichever addon currently provides `vector-store`. When
|
|
20610
|
+
* the active provider changed under a running hub the cache stayed warm
|
|
20611
|
+
* against an index that no longer existed, and every write from then on threw
|
|
20612
|
+
* `index "object-clip" was never declared` — for hours, until the addon was
|
|
20613
|
+
* restarted by hand. So a failed write clears the cache (see
|
|
20614
|
+
* {@link upsertIfBetter}) and the next one re-declares.
|
|
20600
20615
|
*/
|
|
20601
20616
|
async ensureIndex(dim) {
|
|
20602
20617
|
if (this.declaredDim === dim) return true;
|
|
@@ -20621,31 +20636,56 @@ var ObjectEmbeddingStore = class {
|
|
|
20621
20636
|
* Upsert the best-confidence embedding for a track. At most ONE row per
|
|
20622
20637
|
* track: a write only replaces the stored row when its confidence is
|
|
20623
20638
|
* strictly higher, keeping the track's best crop over its lifetime.
|
|
20639
|
+
*
|
|
20640
|
+
* `force` BYPASSES that gate — it does not try to out-score it. A rebuild
|
|
20641
|
+
* first attempted to win by writing `confidence: Infinity`, which worked
|
|
20642
|
+
* exactly once: the stored row then held Infinity, `Infinity <= Infinity`
|
|
20643
|
+
* short-circuited, and every later pass silently wrote nothing while
|
|
20644
|
+
* reporting hundreds rebuilt. Observed live — 214 "rebuilt" moved the index
|
|
20645
|
+
* by 4 rows.
|
|
20646
|
+
*
|
|
20647
|
+
* ## Why this returns an outcome instead of `void`
|
|
20648
|
+
*
|
|
20649
|
+
* It used to return `void` and turn every failure into a warn. The rebuild
|
|
20650
|
+
* therefore counted a write the instant the call returned, and the second time
|
|
20651
|
+
* this class of bug appeared it produced `rebuilt: 704` against `indexed: 0` —
|
|
20652
|
+
* a progress number that was pure fiction while the real cause sat in a warn
|
|
20653
|
+
* nobody was reading. The caller now has to distinguish "written" from "logged
|
|
20654
|
+
* and dropped", because a counter that cannot reads as verification.
|
|
20624
20655
|
*/
|
|
20625
20656
|
async upsertIfBetter(input) {
|
|
20626
|
-
if (input.embedding.length === 0) return;
|
|
20627
|
-
if (!await this.ensureIndex(input.embedding.length)) return;
|
|
20657
|
+
if (input.embedding.length === 0) return "failed";
|
|
20658
|
+
if (!await this.ensureIndex(input.embedding.length)) return "failed";
|
|
20628
20659
|
try {
|
|
20629
|
-
|
|
20660
|
+
if (input.force !== true) {
|
|
20661
|
+
const stored = (await this.vectorStore.getByIds.query({
|
|
20662
|
+
index: OBJECT_CLIP_INDEX,
|
|
20663
|
+
ids: [input.trackId]
|
|
20664
|
+
})).items[0]?.metadata["confidence"];
|
|
20665
|
+
if (typeof stored === "number" && input.confidence <= stored) return "skipped";
|
|
20666
|
+
}
|
|
20667
|
+
const result = await this.vectorStore.upsert.mutate({
|
|
20630
20668
|
index: OBJECT_CLIP_INDEX,
|
|
20631
|
-
ids: [input.trackId]
|
|
20632
|
-
})).items[0]?.metadata["confidence"];
|
|
20633
|
-
if (typeof stored === "number" && input.confidence <= stored) return;
|
|
20634
|
-
if ((await this.vectorStore.upsert.mutate({
|
|
20635
|
-
index: "object-clip",
|
|
20636
20669
|
items: [{
|
|
20637
20670
|
id: input.trackId,
|
|
20638
20671
|
vector: require_dist.encodeVectorBase64(input.embedding),
|
|
20639
20672
|
metadata: metadataFor(input)
|
|
20640
20673
|
}]
|
|
20641
|
-
})).rejected > 0) this.logger.warn("object-embedding upsert rejected", {
|
|
20642
|
-
tags: { deviceId: input.deviceId },
|
|
20643
|
-
meta: {
|
|
20644
|
-
trackId: input.trackId,
|
|
20645
|
-
dim: input.embedding.length
|
|
20646
|
-
}
|
|
20647
20674
|
});
|
|
20675
|
+
if (result.upserted === 0) {
|
|
20676
|
+
this.logger.warn("object-embedding upsert rejected", {
|
|
20677
|
+
tags: { deviceId: input.deviceId },
|
|
20678
|
+
meta: {
|
|
20679
|
+
trackId: input.trackId,
|
|
20680
|
+
dim: input.embedding.length,
|
|
20681
|
+
rejected: result.rejected
|
|
20682
|
+
}
|
|
20683
|
+
});
|
|
20684
|
+
return "failed";
|
|
20685
|
+
}
|
|
20686
|
+
return "persisted";
|
|
20648
20687
|
} catch (err) {
|
|
20688
|
+
this.declaredDim = null;
|
|
20649
20689
|
this.logger.warn("ObjectEmbeddingStore.upsertIfBetter failed", {
|
|
20650
20690
|
tags: { deviceId: input.deviceId },
|
|
20651
20691
|
meta: {
|
|
@@ -20653,6 +20693,7 @@ var ObjectEmbeddingStore = class {
|
|
|
20653
20693
|
error: String(err)
|
|
20654
20694
|
}
|
|
20655
20695
|
});
|
|
20696
|
+
return "failed";
|
|
20656
20697
|
}
|
|
20657
20698
|
}
|
|
20658
20699
|
/**
|
|
@@ -27104,19 +27145,18 @@ var PipelineAnalyticsAddon = class extends require_dist.BaseAddon {
|
|
|
27104
27145
|
height
|
|
27105
27146
|
})).embedding;
|
|
27106
27147
|
},
|
|
27107
|
-
store: async (source, embedding) => {
|
|
27108
|
-
|
|
27109
|
-
|
|
27110
|
-
|
|
27111
|
-
|
|
27112
|
-
|
|
27113
|
-
|
|
27114
|
-
|
|
27115
|
-
|
|
27116
|
-
|
|
27117
|
-
|
|
27118
|
-
|
|
27119
|
-
},
|
|
27148
|
+
store: async (source, embedding) => store.upsertIfBetter({
|
|
27149
|
+
trackId: source.trackId,
|
|
27150
|
+
deviceId: source.deviceId,
|
|
27151
|
+
timestamp: source.timestamp,
|
|
27152
|
+
className: source.className,
|
|
27153
|
+
embedding,
|
|
27154
|
+
modelId,
|
|
27155
|
+
confidence: source.confidence,
|
|
27156
|
+
force: true,
|
|
27157
|
+
...source.mediaKey !== void 0 ? { mediaKey: source.mediaKey } : {},
|
|
27158
|
+
...source.keyFrameMediaKey !== void 0 ? { keyFrameMediaKey: source.keyFrameMediaKey } : {}
|
|
27159
|
+
}),
|
|
27120
27160
|
logger: {
|
|
27121
27161
|
info: (message, extras) => this.ctx.logger.info(message, extras),
|
|
27122
27162
|
warn: (message, extras) => this.ctx.logger.warn(message, extras)
|
|
@@ -12163,8 +12163,15 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
12163
12163
|
failed += 1;
|
|
12164
12164
|
continue;
|
|
12165
12165
|
}
|
|
12166
|
-
await deps.store(source, embedding);
|
|
12167
|
-
rebuilt += 1;
|
|
12166
|
+
const outcome = await deps.store(source, embedding);
|
|
12167
|
+
if (outcome === "persisted") rebuilt += 1;
|
|
12168
|
+
else {
|
|
12169
|
+
failed += 1;
|
|
12170
|
+
deps.logger.warn("embedding rebuild wrote nothing for a track", { meta: {
|
|
12171
|
+
trackId,
|
|
12172
|
+
outcome
|
|
12173
|
+
} });
|
|
12174
|
+
}
|
|
12168
12175
|
} catch (err) {
|
|
12169
12176
|
failed += 1;
|
|
12170
12177
|
deps.logger.warn("embedding rebuild failed for a track", { meta: {
|
|
@@ -20591,6 +20598,14 @@ var ObjectEmbeddingStore = class {
|
|
|
20591
20598
|
* write: the provider rejects an upsert into an index it has never seen. A
|
|
20592
20599
|
* dim change against a populated index is REFUSED rather than wiping it, so
|
|
20593
20600
|
* this failing is the signal that the encoder model changed.
|
|
20601
|
+
*
|
|
20602
|
+
* `declaredDim` caches the declaration, and that cache is per-PROCESS while
|
|
20603
|
+
* the index lives in whichever addon currently provides `vector-store`. When
|
|
20604
|
+
* the active provider changed under a running hub the cache stayed warm
|
|
20605
|
+
* against an index that no longer existed, and every write from then on threw
|
|
20606
|
+
* `index "object-clip" was never declared` — for hours, until the addon was
|
|
20607
|
+
* restarted by hand. So a failed write clears the cache (see
|
|
20608
|
+
* {@link upsertIfBetter}) and the next one re-declares.
|
|
20594
20609
|
*/
|
|
20595
20610
|
async ensureIndex(dim) {
|
|
20596
20611
|
if (this.declaredDim === dim) return true;
|
|
@@ -20615,31 +20630,56 @@ var ObjectEmbeddingStore = class {
|
|
|
20615
20630
|
* Upsert the best-confidence embedding for a track. At most ONE row per
|
|
20616
20631
|
* track: a write only replaces the stored row when its confidence is
|
|
20617
20632
|
* strictly higher, keeping the track's best crop over its lifetime.
|
|
20633
|
+
*
|
|
20634
|
+
* `force` BYPASSES that gate — it does not try to out-score it. A rebuild
|
|
20635
|
+
* first attempted to win by writing `confidence: Infinity`, which worked
|
|
20636
|
+
* exactly once: the stored row then held Infinity, `Infinity <= Infinity`
|
|
20637
|
+
* short-circuited, and every later pass silently wrote nothing while
|
|
20638
|
+
* reporting hundreds rebuilt. Observed live — 214 "rebuilt" moved the index
|
|
20639
|
+
* by 4 rows.
|
|
20640
|
+
*
|
|
20641
|
+
* ## Why this returns an outcome instead of `void`
|
|
20642
|
+
*
|
|
20643
|
+
* It used to return `void` and turn every failure into a warn. The rebuild
|
|
20644
|
+
* therefore counted a write the instant the call returned, and the second time
|
|
20645
|
+
* this class of bug appeared it produced `rebuilt: 704` against `indexed: 0` —
|
|
20646
|
+
* a progress number that was pure fiction while the real cause sat in a warn
|
|
20647
|
+
* nobody was reading. The caller now has to distinguish "written" from "logged
|
|
20648
|
+
* and dropped", because a counter that cannot reads as verification.
|
|
20618
20649
|
*/
|
|
20619
20650
|
async upsertIfBetter(input) {
|
|
20620
|
-
if (input.embedding.length === 0) return;
|
|
20621
|
-
if (!await this.ensureIndex(input.embedding.length)) return;
|
|
20651
|
+
if (input.embedding.length === 0) return "failed";
|
|
20652
|
+
if (!await this.ensureIndex(input.embedding.length)) return "failed";
|
|
20622
20653
|
try {
|
|
20623
|
-
|
|
20654
|
+
if (input.force !== true) {
|
|
20655
|
+
const stored = (await this.vectorStore.getByIds.query({
|
|
20656
|
+
index: OBJECT_CLIP_INDEX,
|
|
20657
|
+
ids: [input.trackId]
|
|
20658
|
+
})).items[0]?.metadata["confidence"];
|
|
20659
|
+
if (typeof stored === "number" && input.confidence <= stored) return "skipped";
|
|
20660
|
+
}
|
|
20661
|
+
const result = await this.vectorStore.upsert.mutate({
|
|
20624
20662
|
index: OBJECT_CLIP_INDEX,
|
|
20625
|
-
ids: [input.trackId]
|
|
20626
|
-
})).items[0]?.metadata["confidence"];
|
|
20627
|
-
if (typeof stored === "number" && input.confidence <= stored) return;
|
|
20628
|
-
if ((await this.vectorStore.upsert.mutate({
|
|
20629
|
-
index: "object-clip",
|
|
20630
20663
|
items: [{
|
|
20631
20664
|
id: input.trackId,
|
|
20632
20665
|
vector: encodeVectorBase64(input.embedding),
|
|
20633
20666
|
metadata: metadataFor(input)
|
|
20634
20667
|
}]
|
|
20635
|
-
})).rejected > 0) this.logger.warn("object-embedding upsert rejected", {
|
|
20636
|
-
tags: { deviceId: input.deviceId },
|
|
20637
|
-
meta: {
|
|
20638
|
-
trackId: input.trackId,
|
|
20639
|
-
dim: input.embedding.length
|
|
20640
|
-
}
|
|
20641
20668
|
});
|
|
20669
|
+
if (result.upserted === 0) {
|
|
20670
|
+
this.logger.warn("object-embedding upsert rejected", {
|
|
20671
|
+
tags: { deviceId: input.deviceId },
|
|
20672
|
+
meta: {
|
|
20673
|
+
trackId: input.trackId,
|
|
20674
|
+
dim: input.embedding.length,
|
|
20675
|
+
rejected: result.rejected
|
|
20676
|
+
}
|
|
20677
|
+
});
|
|
20678
|
+
return "failed";
|
|
20679
|
+
}
|
|
20680
|
+
return "persisted";
|
|
20642
20681
|
} catch (err) {
|
|
20682
|
+
this.declaredDim = null;
|
|
20643
20683
|
this.logger.warn("ObjectEmbeddingStore.upsertIfBetter failed", {
|
|
20644
20684
|
tags: { deviceId: input.deviceId },
|
|
20645
20685
|
meta: {
|
|
@@ -20647,6 +20687,7 @@ var ObjectEmbeddingStore = class {
|
|
|
20647
20687
|
error: String(err)
|
|
20648
20688
|
}
|
|
20649
20689
|
});
|
|
20690
|
+
return "failed";
|
|
20650
20691
|
}
|
|
20651
20692
|
}
|
|
20652
20693
|
/**
|
|
@@ -27098,19 +27139,18 @@ var PipelineAnalyticsAddon = class extends BaseAddon {
|
|
|
27098
27139
|
height
|
|
27099
27140
|
})).embedding;
|
|
27100
27141
|
},
|
|
27101
|
-
store: async (source, embedding) => {
|
|
27102
|
-
|
|
27103
|
-
|
|
27104
|
-
|
|
27105
|
-
|
|
27106
|
-
|
|
27107
|
-
|
|
27108
|
-
|
|
27109
|
-
|
|
27110
|
-
|
|
27111
|
-
|
|
27112
|
-
|
|
27113
|
-
},
|
|
27142
|
+
store: async (source, embedding) => store.upsertIfBetter({
|
|
27143
|
+
trackId: source.trackId,
|
|
27144
|
+
deviceId: source.deviceId,
|
|
27145
|
+
timestamp: source.timestamp,
|
|
27146
|
+
className: source.className,
|
|
27147
|
+
embedding,
|
|
27148
|
+
modelId,
|
|
27149
|
+
confidence: source.confidence,
|
|
27150
|
+
force: true,
|
|
27151
|
+
...source.mediaKey !== void 0 ? { mediaKey: source.mediaKey } : {},
|
|
27152
|
+
...source.keyFrameMediaKey !== void 0 ? { keyFrameMediaKey: source.keyFrameMediaKey } : {}
|
|
27153
|
+
}),
|
|
27114
27154
|
logger: {
|
|
27115
27155
|
info: (message, extras) => this.ctx.logger.info(message, extras),
|
|
27116
27156
|
warn: (message, extras) => this.ctx.logger.warn(message, extras)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-post-analysis",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.46",
|
|
4
4
|
"description": "Post-Analysis bundle — enrichment, embedding-encoder, pipeline-analytics. Multi-entry npm package shipping addons that consume pipeline output.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|
|
@@ -87,6 +87,12 @@
|
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
89
|
"name": "videoclips"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"name": "face-gallery"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"name": "plate-gallery"
|
|
90
96
|
}
|
|
91
97
|
],
|
|
92
98
|
"storageLocations": [
|