@camstack/addon-static-turn 1.2.22 → 1.2.23
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/static-turn.addon.js +138 -56
- package/dist/static-turn.addon.mjs +138 -56
- package/package.json +1 -1
|
@@ -7550,7 +7550,7 @@ var RecordingBandSchema = object({
|
|
|
7550
7550
|
postBufferSec: number().min(0).optional()
|
|
7551
7551
|
});
|
|
7552
7552
|
({
|
|
7553
|
-
preBufferSec:
|
|
7553
|
+
preBufferSec: 15,
|
|
7554
7554
|
postBufferSec: 30
|
|
7555
7555
|
}).postBufferSec * 1e3;
|
|
7556
7556
|
/**
|
|
@@ -13489,128 +13489,103 @@ var COCO_TO_MACRO = {
|
|
|
13489
13489
|
var AUDIO_MACRO_LABELS = [
|
|
13490
13490
|
{
|
|
13491
13491
|
id: "speech",
|
|
13492
|
-
name: "Speech"
|
|
13493
|
-
icon: "🗣️"
|
|
13492
|
+
name: "Speech"
|
|
13494
13493
|
},
|
|
13495
13494
|
{
|
|
13496
13495
|
id: "scream",
|
|
13497
|
-
name: "Scream / Shout"
|
|
13498
|
-
icon: "😱"
|
|
13496
|
+
name: "Scream / Shout"
|
|
13499
13497
|
},
|
|
13500
13498
|
{
|
|
13501
13499
|
id: "crying",
|
|
13502
|
-
name: "Crying / Baby"
|
|
13503
|
-
icon: "😢"
|
|
13500
|
+
name: "Crying / Baby"
|
|
13504
13501
|
},
|
|
13505
13502
|
{
|
|
13506
13503
|
id: "laughter",
|
|
13507
|
-
name: "Laughter"
|
|
13508
|
-
icon: "😂"
|
|
13504
|
+
name: "Laughter"
|
|
13509
13505
|
},
|
|
13510
13506
|
{
|
|
13511
13507
|
id: "music",
|
|
13512
|
-
name: "Music"
|
|
13513
|
-
icon: "🎵"
|
|
13508
|
+
name: "Music"
|
|
13514
13509
|
},
|
|
13515
13510
|
{
|
|
13516
13511
|
id: "dog",
|
|
13517
|
-
name: "Dog"
|
|
13518
|
-
icon: "🐕"
|
|
13512
|
+
name: "Dog"
|
|
13519
13513
|
},
|
|
13520
13514
|
{
|
|
13521
13515
|
id: "cat",
|
|
13522
|
-
name: "Cat"
|
|
13523
|
-
icon: "🐈"
|
|
13516
|
+
name: "Cat"
|
|
13524
13517
|
},
|
|
13525
13518
|
{
|
|
13526
13519
|
id: "bird",
|
|
13527
|
-
name: "Bird"
|
|
13528
|
-
icon: "🐦"
|
|
13520
|
+
name: "Bird"
|
|
13529
13521
|
},
|
|
13530
13522
|
{
|
|
13531
13523
|
id: "animal",
|
|
13532
|
-
name: "Animal (other)"
|
|
13533
|
-
icon: "🐾"
|
|
13524
|
+
name: "Animal (other)"
|
|
13534
13525
|
},
|
|
13535
13526
|
{
|
|
13536
13527
|
id: "alarm",
|
|
13537
|
-
name: "Alarm / Siren"
|
|
13538
|
-
icon: "🚨"
|
|
13528
|
+
name: "Alarm / Siren"
|
|
13539
13529
|
},
|
|
13540
13530
|
{
|
|
13541
13531
|
id: "doorbell",
|
|
13542
|
-
name: "Doorbell / Knock"
|
|
13543
|
-
icon: "🔔"
|
|
13532
|
+
name: "Doorbell / Knock"
|
|
13544
13533
|
},
|
|
13545
13534
|
{
|
|
13546
13535
|
id: "glass_breaking",
|
|
13547
|
-
name: "Glass Breaking"
|
|
13548
|
-
icon: "💥"
|
|
13536
|
+
name: "Glass Breaking"
|
|
13549
13537
|
},
|
|
13550
13538
|
{
|
|
13551
13539
|
id: "gunshot",
|
|
13552
|
-
name: "Gunshot / Explosion"
|
|
13553
|
-
icon: "💣"
|
|
13540
|
+
name: "Gunshot / Explosion"
|
|
13554
13541
|
},
|
|
13555
13542
|
{
|
|
13556
13543
|
id: "vehicle",
|
|
13557
|
-
name: "Vehicle"
|
|
13558
|
-
icon: "🚗"
|
|
13544
|
+
name: "Vehicle"
|
|
13559
13545
|
},
|
|
13560
13546
|
{
|
|
13561
13547
|
id: "siren",
|
|
13562
|
-
name: "Emergency Siren"
|
|
13563
|
-
icon: "🚑"
|
|
13548
|
+
name: "Emergency Siren"
|
|
13564
13549
|
},
|
|
13565
13550
|
{
|
|
13566
13551
|
id: "fire",
|
|
13567
|
-
name: "Fire / Smoke"
|
|
13568
|
-
icon: "🔥"
|
|
13552
|
+
name: "Fire / Smoke"
|
|
13569
13553
|
},
|
|
13570
13554
|
{
|
|
13571
13555
|
id: "water",
|
|
13572
|
-
name: "Water"
|
|
13573
|
-
icon: "💧"
|
|
13556
|
+
name: "Water"
|
|
13574
13557
|
},
|
|
13575
13558
|
{
|
|
13576
13559
|
id: "wind",
|
|
13577
|
-
name: "Wind / Weather"
|
|
13578
|
-
icon: "🌬️"
|
|
13560
|
+
name: "Wind / Weather"
|
|
13579
13561
|
},
|
|
13580
13562
|
{
|
|
13581
13563
|
id: "door",
|
|
13582
|
-
name: "Door"
|
|
13583
|
-
icon: "🚪"
|
|
13564
|
+
name: "Door"
|
|
13584
13565
|
},
|
|
13585
13566
|
{
|
|
13586
13567
|
id: "footsteps",
|
|
13587
|
-
name: "Footsteps"
|
|
13588
|
-
icon: "👣"
|
|
13568
|
+
name: "Footsteps"
|
|
13589
13569
|
},
|
|
13590
13570
|
{
|
|
13591
13571
|
id: "crowd",
|
|
13592
|
-
name: "Crowd / Chatter"
|
|
13593
|
-
icon: "👥"
|
|
13572
|
+
name: "Crowd / Chatter"
|
|
13594
13573
|
},
|
|
13595
13574
|
{
|
|
13596
13575
|
id: "telephone",
|
|
13597
|
-
name: "Telephone"
|
|
13598
|
-
icon: "📞"
|
|
13576
|
+
name: "Telephone"
|
|
13599
13577
|
},
|
|
13600
13578
|
{
|
|
13601
13579
|
id: "engine",
|
|
13602
|
-
name: "Engine / Motor"
|
|
13603
|
-
icon: "⚙️"
|
|
13580
|
+
name: "Engine / Motor"
|
|
13604
13581
|
},
|
|
13605
13582
|
{
|
|
13606
13583
|
id: "tools",
|
|
13607
|
-
name: "Tools / Construction"
|
|
13608
|
-
icon: "🔨"
|
|
13584
|
+
name: "Tools / Construction"
|
|
13609
13585
|
},
|
|
13610
13586
|
{
|
|
13611
13587
|
id: "silence",
|
|
13612
|
-
name: "Silence"
|
|
13613
|
-
icon: "🤫"
|
|
13588
|
+
name: "Silence"
|
|
13614
13589
|
}
|
|
13615
13590
|
];
|
|
13616
13591
|
var YAMNET_TO_MACRO = {
|
|
@@ -16074,7 +16049,7 @@ var TrackEnvelopeSchema = object({
|
|
|
16074
16049
|
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
16075
16050
|
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
16076
16051
|
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
16077
|
-
* zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
|
|
16052
|
+
* zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
|
|
16078
16053
|
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
16079
16054
|
* `getTrack`. Mirrors the event-store `projection` convention
|
|
16080
16055
|
* (`getObjectEvents` et al.).
|
|
@@ -16369,6 +16344,35 @@ var TrackSchema = object({
|
|
|
16369
16344
|
*/
|
|
16370
16345
|
hasFace: boolean().optional(),
|
|
16371
16346
|
/**
|
|
16347
|
+
* This track has a face row IN THE GALLERY: a crop **and** an embedding — a
|
|
16348
|
+
* face an operator could ASSIGN to an identity.
|
|
16349
|
+
*
|
|
16350
|
+
* The STRICT twin of {@link hasFace}, and the pair only earns its keep
|
|
16351
|
+
* because the two disagree. `hasFace` is stamped at the TOP of the face
|
|
16352
|
+
* branch, before every gate, and means no more than "a face detector produced
|
|
16353
|
+
* a face detail". This one is stamped at the single moment the gallery row
|
|
16354
|
+
* LANDS — after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
|
|
16355
|
+
* past the embedding-magnitude verdict, the `minFacePx` detection gate, the
|
|
16356
|
+
* candidate gate, the imageless-track drop (no crop was ever captured) and
|
|
16357
|
+
* the crop-store drop. Everything between the detector and that insert can
|
|
16358
|
+
* legitimately refuse the face, so a flag written any earlier promises the
|
|
16359
|
+
* operator something to assign and delivers nothing.
|
|
16360
|
+
*
|
|
16361
|
+
* **Independent of recognition.** A face collected but never auto-matched is
|
|
16362
|
+
* still assignable — it is in fact the face an operator most wants to reach —
|
|
16363
|
+
* so this is NOT gated on `recognizedIdentityId`. Recognition lands in
|
|
16364
|
+
* `subLabel`; this says only that the raw material exists.
|
|
16365
|
+
*
|
|
16366
|
+
* **Set once, never cleared.** A track that produced a gallery row produced
|
|
16367
|
+
* one; deleting the row later is the gallery's business, not this flag's.
|
|
16368
|
+
*
|
|
16369
|
+
* **Absent ≠ false**, the same rule as {@link hasFace}: every row written
|
|
16370
|
+
* before the column omits it, and so does every server that predates the
|
|
16371
|
+
* field. A consumer must test `=== true` and render nothing otherwise —
|
|
16372
|
+
* never infer "no assignable face".
|
|
16373
|
+
*/
|
|
16374
|
+
hasEmbeddedFace: boolean().optional(),
|
|
16375
|
+
/**
|
|
16372
16376
|
* This subject CONTAINS a folded rider — a person the rider-pairing step
|
|
16373
16377
|
* ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
|
|
16374
16378
|
* so the passage is tracked once and as a VEHICLE.
|
|
@@ -17718,6 +17722,32 @@ var DetailResultSchema = object({
|
|
|
17718
17722
|
/** FRAME-space bbox (already mapped back from crop space). */
|
|
17719
17723
|
bbox: NativeCropBboxSchema.optional(),
|
|
17720
17724
|
embedding: string().optional(),
|
|
17725
|
+
/**
|
|
17726
|
+
* L2 magnitude of the RAW pre-normalization embedding. Additive and optional
|
|
17727
|
+
* so an older runner that does not send it degrades to "unmeasurable", which
|
|
17728
|
+
* the consuming gate treats as accept — never as reject.
|
|
17729
|
+
*/
|
|
17730
|
+
embeddingMagnitude: number().optional(),
|
|
17731
|
+
/**
|
|
17732
|
+
* Model that produced `embedding` — the SAME contract `labelModelId` has for
|
|
17733
|
+
* `label`, and for the same reason: the producing node is the only side that
|
|
17734
|
+
* knows which model actually ran, and re-deriving it downstream is exactly
|
|
17735
|
+
* the inference this model exists to forbid.
|
|
17736
|
+
*
|
|
17737
|
+
* Additive and optional, so a runner that predates it degrades to
|
|
17738
|
+
* "unmeasurable" rather than to a wrong answer — the consumer falls back to
|
|
17739
|
+
* its previous assumption instead of refusing.
|
|
17740
|
+
*
|
|
17741
|
+
* Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
|
|
17742
|
+
* to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
|
|
17743
|
+
* with nothing on the wire it took the id from the GALLERY, so the gate
|
|
17744
|
+
* compared the gallery against itself and could never fire. That turned the
|
|
17745
|
+
* one guard protecting the face feature space into a tautology, and it is
|
|
17746
|
+
* why swapping `face-embedding`'s model would NOT have stranded the enrolled
|
|
17747
|
+
* gallery as the catalog comment predicts — it would have scored the new
|
|
17748
|
+
* model's vectors against the old model's samples in one cosine space.
|
|
17749
|
+
*/
|
|
17750
|
+
embeddingModelId: string().optional(),
|
|
17721
17751
|
label: string().optional(),
|
|
17722
17752
|
/**
|
|
17723
17753
|
* The tier `label` occupies, copied VERBATIM from the producing step's
|
|
@@ -19128,6 +19158,7 @@ DeviceType.Camera, method(object({
|
|
|
19128
19158
|
isBattery: boolean(),
|
|
19129
19159
|
reason: _enum([
|
|
19130
19160
|
"disabled",
|
|
19161
|
+
"offline",
|
|
19131
19162
|
"sleeping",
|
|
19132
19163
|
"unreachable",
|
|
19133
19164
|
"waking"
|
|
@@ -19173,9 +19204,17 @@ targets: array(object({
|
|
|
19173
19204
|
sleeping: boolean(),
|
|
19174
19205
|
/** Current device state rendered over the cached frame. State images
|
|
19175
19206
|
* remain authoritative even when their photographic background is
|
|
19176
|
-
* old; null means the link must carry a current camera frame.
|
|
19207
|
+
* old; null means the link must carry a current camera frame.
|
|
19208
|
+
*
|
|
19209
|
+
* **This is the ONLY source a surface may derive an inactive tile
|
|
19210
|
+
* from.** A client that reads a device's `online`/`disabled` flags and
|
|
19211
|
+
* draws its own verdict will disagree with the pixels it is painting
|
|
19212
|
+
* — the frame comes from here, and so must the sentence over it
|
|
19213
|
+
* (D190). Pair with `ageMs` for the age of the photograph behind the
|
|
19214
|
+
* state. */
|
|
19177
19215
|
stateReason: _enum([
|
|
19178
19216
|
"disabled",
|
|
19217
|
+
"offline",
|
|
19179
19218
|
"sleeping",
|
|
19180
19219
|
"unreachable",
|
|
19181
19220
|
"waking"
|
|
@@ -33384,7 +33423,6 @@ var NC_AUDIO_DEFAULTS = {
|
|
|
33384
33423
|
hitPercent: 60,
|
|
33385
33424
|
samplingSeconds: 10
|
|
33386
33425
|
};
|
|
33387
|
-
new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
|
|
33388
33426
|
new Set(["devices", "classes"]);
|
|
33389
33427
|
NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
|
|
33390
33428
|
/**
|
|
@@ -33618,6 +33656,39 @@ TimelapseRuleInputSchema.extend({
|
|
|
33618
33656
|
createdAt: number(),
|
|
33619
33657
|
updatedAt: number()
|
|
33620
33658
|
});
|
|
33659
|
+
Object.freeze(Object.fromEntries([{
|
|
33660
|
+
stepId: "face-embedding",
|
|
33661
|
+
label: "Face recognition model",
|
|
33662
|
+
defaultModelId: "arcface-r100",
|
|
33663
|
+
indexName: "the enrolled face gallery",
|
|
33664
|
+
options: [
|
|
33665
|
+
{
|
|
33666
|
+
id: "arcface-r100",
|
|
33667
|
+
label: "ArcFace (ResNet34)"
|
|
33668
|
+
},
|
|
33669
|
+
{
|
|
33670
|
+
id: "auraface-r100",
|
|
33671
|
+
label: "AuraFace R100"
|
|
33672
|
+
},
|
|
33673
|
+
{
|
|
33674
|
+
id: "inception-resnet-v1",
|
|
33675
|
+
label: "Inception ResNet V1"
|
|
33676
|
+
}
|
|
33677
|
+
]
|
|
33678
|
+
}, {
|
|
33679
|
+
stepId: "clip-embedding",
|
|
33680
|
+
label: "Semantic search model",
|
|
33681
|
+
defaultModelId: "mobileclip-s1",
|
|
33682
|
+
indexName: "the object semantic-search index",
|
|
33683
|
+
options: [{
|
|
33684
|
+
id: "mobileclip-s1",
|
|
33685
|
+
label: "MobileCLIP S1"
|
|
33686
|
+
}, {
|
|
33687
|
+
id: "mobileclip-s2",
|
|
33688
|
+
label: "MobileCLIP S2"
|
|
33689
|
+
}]
|
|
33690
|
+
}].map((s) => [s.stepId, s.defaultModelId])));
|
|
33691
|
+
string().min(1);
|
|
33621
33692
|
object({
|
|
33622
33693
|
/**
|
|
33623
33694
|
* Fraction of the box's own size added on EACH side before cutting.
|
|
@@ -33638,10 +33709,21 @@ object({
|
|
|
33638
33709
|
*/
|
|
33639
33710
|
square: boolean()
|
|
33640
33711
|
});
|
|
33641
|
-
|
|
33712
|
+
/**
|
|
33713
|
+
* The convention in force when nobody has configured one — byte-for-byte the
|
|
33714
|
+
* behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
|
|
33715
|
+
*/
|
|
33716
|
+
var DEFAULT_DETAIL_CROP_CONVENTION = {
|
|
33642
33717
|
paddingRatio: .15,
|
|
33643
33718
|
square: false
|
|
33644
|
-
}
|
|
33719
|
+
};
|
|
33720
|
+
Object.freeze({
|
|
33721
|
+
x: 0,
|
|
33722
|
+
y: 0,
|
|
33723
|
+
w: 1,
|
|
33724
|
+
h: 1
|
|
33725
|
+
});
|
|
33726
|
+
DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
|
|
33645
33727
|
/**
|
|
33646
33728
|
* WHICH delivered frames the decode worker retains a native copy of.
|
|
33647
33729
|
*
|
|
@@ -7549,7 +7549,7 @@ var RecordingBandSchema = object({
|
|
|
7549
7549
|
postBufferSec: number().min(0).optional()
|
|
7550
7550
|
});
|
|
7551
7551
|
({
|
|
7552
|
-
preBufferSec:
|
|
7552
|
+
preBufferSec: 15,
|
|
7553
7553
|
postBufferSec: 30
|
|
7554
7554
|
}).postBufferSec * 1e3;
|
|
7555
7555
|
/**
|
|
@@ -13488,128 +13488,103 @@ var COCO_TO_MACRO = {
|
|
|
13488
13488
|
var AUDIO_MACRO_LABELS = [
|
|
13489
13489
|
{
|
|
13490
13490
|
id: "speech",
|
|
13491
|
-
name: "Speech"
|
|
13492
|
-
icon: "🗣️"
|
|
13491
|
+
name: "Speech"
|
|
13493
13492
|
},
|
|
13494
13493
|
{
|
|
13495
13494
|
id: "scream",
|
|
13496
|
-
name: "Scream / Shout"
|
|
13497
|
-
icon: "😱"
|
|
13495
|
+
name: "Scream / Shout"
|
|
13498
13496
|
},
|
|
13499
13497
|
{
|
|
13500
13498
|
id: "crying",
|
|
13501
|
-
name: "Crying / Baby"
|
|
13502
|
-
icon: "😢"
|
|
13499
|
+
name: "Crying / Baby"
|
|
13503
13500
|
},
|
|
13504
13501
|
{
|
|
13505
13502
|
id: "laughter",
|
|
13506
|
-
name: "Laughter"
|
|
13507
|
-
icon: "😂"
|
|
13503
|
+
name: "Laughter"
|
|
13508
13504
|
},
|
|
13509
13505
|
{
|
|
13510
13506
|
id: "music",
|
|
13511
|
-
name: "Music"
|
|
13512
|
-
icon: "🎵"
|
|
13507
|
+
name: "Music"
|
|
13513
13508
|
},
|
|
13514
13509
|
{
|
|
13515
13510
|
id: "dog",
|
|
13516
|
-
name: "Dog"
|
|
13517
|
-
icon: "🐕"
|
|
13511
|
+
name: "Dog"
|
|
13518
13512
|
},
|
|
13519
13513
|
{
|
|
13520
13514
|
id: "cat",
|
|
13521
|
-
name: "Cat"
|
|
13522
|
-
icon: "🐈"
|
|
13515
|
+
name: "Cat"
|
|
13523
13516
|
},
|
|
13524
13517
|
{
|
|
13525
13518
|
id: "bird",
|
|
13526
|
-
name: "Bird"
|
|
13527
|
-
icon: "🐦"
|
|
13519
|
+
name: "Bird"
|
|
13528
13520
|
},
|
|
13529
13521
|
{
|
|
13530
13522
|
id: "animal",
|
|
13531
|
-
name: "Animal (other)"
|
|
13532
|
-
icon: "🐾"
|
|
13523
|
+
name: "Animal (other)"
|
|
13533
13524
|
},
|
|
13534
13525
|
{
|
|
13535
13526
|
id: "alarm",
|
|
13536
|
-
name: "Alarm / Siren"
|
|
13537
|
-
icon: "🚨"
|
|
13527
|
+
name: "Alarm / Siren"
|
|
13538
13528
|
},
|
|
13539
13529
|
{
|
|
13540
13530
|
id: "doorbell",
|
|
13541
|
-
name: "Doorbell / Knock"
|
|
13542
|
-
icon: "🔔"
|
|
13531
|
+
name: "Doorbell / Knock"
|
|
13543
13532
|
},
|
|
13544
13533
|
{
|
|
13545
13534
|
id: "glass_breaking",
|
|
13546
|
-
name: "Glass Breaking"
|
|
13547
|
-
icon: "💥"
|
|
13535
|
+
name: "Glass Breaking"
|
|
13548
13536
|
},
|
|
13549
13537
|
{
|
|
13550
13538
|
id: "gunshot",
|
|
13551
|
-
name: "Gunshot / Explosion"
|
|
13552
|
-
icon: "💣"
|
|
13539
|
+
name: "Gunshot / Explosion"
|
|
13553
13540
|
},
|
|
13554
13541
|
{
|
|
13555
13542
|
id: "vehicle",
|
|
13556
|
-
name: "Vehicle"
|
|
13557
|
-
icon: "🚗"
|
|
13543
|
+
name: "Vehicle"
|
|
13558
13544
|
},
|
|
13559
13545
|
{
|
|
13560
13546
|
id: "siren",
|
|
13561
|
-
name: "Emergency Siren"
|
|
13562
|
-
icon: "🚑"
|
|
13547
|
+
name: "Emergency Siren"
|
|
13563
13548
|
},
|
|
13564
13549
|
{
|
|
13565
13550
|
id: "fire",
|
|
13566
|
-
name: "Fire / Smoke"
|
|
13567
|
-
icon: "🔥"
|
|
13551
|
+
name: "Fire / Smoke"
|
|
13568
13552
|
},
|
|
13569
13553
|
{
|
|
13570
13554
|
id: "water",
|
|
13571
|
-
name: "Water"
|
|
13572
|
-
icon: "💧"
|
|
13555
|
+
name: "Water"
|
|
13573
13556
|
},
|
|
13574
13557
|
{
|
|
13575
13558
|
id: "wind",
|
|
13576
|
-
name: "Wind / Weather"
|
|
13577
|
-
icon: "🌬️"
|
|
13559
|
+
name: "Wind / Weather"
|
|
13578
13560
|
},
|
|
13579
13561
|
{
|
|
13580
13562
|
id: "door",
|
|
13581
|
-
name: "Door"
|
|
13582
|
-
icon: "🚪"
|
|
13563
|
+
name: "Door"
|
|
13583
13564
|
},
|
|
13584
13565
|
{
|
|
13585
13566
|
id: "footsteps",
|
|
13586
|
-
name: "Footsteps"
|
|
13587
|
-
icon: "👣"
|
|
13567
|
+
name: "Footsteps"
|
|
13588
13568
|
},
|
|
13589
13569
|
{
|
|
13590
13570
|
id: "crowd",
|
|
13591
|
-
name: "Crowd / Chatter"
|
|
13592
|
-
icon: "👥"
|
|
13571
|
+
name: "Crowd / Chatter"
|
|
13593
13572
|
},
|
|
13594
13573
|
{
|
|
13595
13574
|
id: "telephone",
|
|
13596
|
-
name: "Telephone"
|
|
13597
|
-
icon: "📞"
|
|
13575
|
+
name: "Telephone"
|
|
13598
13576
|
},
|
|
13599
13577
|
{
|
|
13600
13578
|
id: "engine",
|
|
13601
|
-
name: "Engine / Motor"
|
|
13602
|
-
icon: "⚙️"
|
|
13579
|
+
name: "Engine / Motor"
|
|
13603
13580
|
},
|
|
13604
13581
|
{
|
|
13605
13582
|
id: "tools",
|
|
13606
|
-
name: "Tools / Construction"
|
|
13607
|
-
icon: "🔨"
|
|
13583
|
+
name: "Tools / Construction"
|
|
13608
13584
|
},
|
|
13609
13585
|
{
|
|
13610
13586
|
id: "silence",
|
|
13611
|
-
name: "Silence"
|
|
13612
|
-
icon: "🤫"
|
|
13587
|
+
name: "Silence"
|
|
13613
13588
|
}
|
|
13614
13589
|
];
|
|
13615
13590
|
var YAMNET_TO_MACRO = {
|
|
@@ -16073,7 +16048,7 @@ var TrackEnvelopeSchema = object({
|
|
|
16073
16048
|
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
16074
16049
|
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
16075
16050
|
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
16076
|
-
* zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
|
|
16051
|
+
* zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
|
|
16077
16052
|
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
16078
16053
|
* `getTrack`. Mirrors the event-store `projection` convention
|
|
16079
16054
|
* (`getObjectEvents` et al.).
|
|
@@ -16368,6 +16343,35 @@ var TrackSchema = object({
|
|
|
16368
16343
|
*/
|
|
16369
16344
|
hasFace: boolean().optional(),
|
|
16370
16345
|
/**
|
|
16346
|
+
* This track has a face row IN THE GALLERY: a crop **and** an embedding — a
|
|
16347
|
+
* face an operator could ASSIGN to an identity.
|
|
16348
|
+
*
|
|
16349
|
+
* The STRICT twin of {@link hasFace}, and the pair only earns its keep
|
|
16350
|
+
* because the two disagree. `hasFace` is stamped at the TOP of the face
|
|
16351
|
+
* branch, before every gate, and means no more than "a face detector produced
|
|
16352
|
+
* a face detail". This one is stamped at the single moment the gallery row
|
|
16353
|
+
* LANDS — after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
|
|
16354
|
+
* past the embedding-magnitude verdict, the `minFacePx` detection gate, the
|
|
16355
|
+
* candidate gate, the imageless-track drop (no crop was ever captured) and
|
|
16356
|
+
* the crop-store drop. Everything between the detector and that insert can
|
|
16357
|
+
* legitimately refuse the face, so a flag written any earlier promises the
|
|
16358
|
+
* operator something to assign and delivers nothing.
|
|
16359
|
+
*
|
|
16360
|
+
* **Independent of recognition.** A face collected but never auto-matched is
|
|
16361
|
+
* still assignable — it is in fact the face an operator most wants to reach —
|
|
16362
|
+
* so this is NOT gated on `recognizedIdentityId`. Recognition lands in
|
|
16363
|
+
* `subLabel`; this says only that the raw material exists.
|
|
16364
|
+
*
|
|
16365
|
+
* **Set once, never cleared.** A track that produced a gallery row produced
|
|
16366
|
+
* one; deleting the row later is the gallery's business, not this flag's.
|
|
16367
|
+
*
|
|
16368
|
+
* **Absent ≠ false**, the same rule as {@link hasFace}: every row written
|
|
16369
|
+
* before the column omits it, and so does every server that predates the
|
|
16370
|
+
* field. A consumer must test `=== true` and render nothing otherwise —
|
|
16371
|
+
* never infer "no assignable face".
|
|
16372
|
+
*/
|
|
16373
|
+
hasEmbeddedFace: boolean().optional(),
|
|
16374
|
+
/**
|
|
16371
16375
|
* This subject CONTAINS a folded rider — a person the rider-pairing step
|
|
16372
16376
|
* ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
|
|
16373
16377
|
* so the passage is tracked once and as a VEHICLE.
|
|
@@ -17717,6 +17721,32 @@ var DetailResultSchema = object({
|
|
|
17717
17721
|
/** FRAME-space bbox (already mapped back from crop space). */
|
|
17718
17722
|
bbox: NativeCropBboxSchema.optional(),
|
|
17719
17723
|
embedding: string().optional(),
|
|
17724
|
+
/**
|
|
17725
|
+
* L2 magnitude of the RAW pre-normalization embedding. Additive and optional
|
|
17726
|
+
* so an older runner that does not send it degrades to "unmeasurable", which
|
|
17727
|
+
* the consuming gate treats as accept — never as reject.
|
|
17728
|
+
*/
|
|
17729
|
+
embeddingMagnitude: number().optional(),
|
|
17730
|
+
/**
|
|
17731
|
+
* Model that produced `embedding` — the SAME contract `labelModelId` has for
|
|
17732
|
+
* `label`, and for the same reason: the producing node is the only side that
|
|
17733
|
+
* knows which model actually ran, and re-deriving it downstream is exactly
|
|
17734
|
+
* the inference this model exists to forbid.
|
|
17735
|
+
*
|
|
17736
|
+
* Additive and optional, so a runner that predates it degrades to
|
|
17737
|
+
* "unmeasurable" rather than to a wrong answer — the consumer falls back to
|
|
17738
|
+
* its previous assumption instead of refusing.
|
|
17739
|
+
*
|
|
17740
|
+
* Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
|
|
17741
|
+
* to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
|
|
17742
|
+
* with nothing on the wire it took the id from the GALLERY, so the gate
|
|
17743
|
+
* compared the gallery against itself and could never fire. That turned the
|
|
17744
|
+
* one guard protecting the face feature space into a tautology, and it is
|
|
17745
|
+
* why swapping `face-embedding`'s model would NOT have stranded the enrolled
|
|
17746
|
+
* gallery as the catalog comment predicts — it would have scored the new
|
|
17747
|
+
* model's vectors against the old model's samples in one cosine space.
|
|
17748
|
+
*/
|
|
17749
|
+
embeddingModelId: string().optional(),
|
|
17720
17750
|
label: string().optional(),
|
|
17721
17751
|
/**
|
|
17722
17752
|
* The tier `label` occupies, copied VERBATIM from the producing step's
|
|
@@ -19127,6 +19157,7 @@ DeviceType.Camera, method(object({
|
|
|
19127
19157
|
isBattery: boolean(),
|
|
19128
19158
|
reason: _enum([
|
|
19129
19159
|
"disabled",
|
|
19160
|
+
"offline",
|
|
19130
19161
|
"sleeping",
|
|
19131
19162
|
"unreachable",
|
|
19132
19163
|
"waking"
|
|
@@ -19172,9 +19203,17 @@ targets: array(object({
|
|
|
19172
19203
|
sleeping: boolean(),
|
|
19173
19204
|
/** Current device state rendered over the cached frame. State images
|
|
19174
19205
|
* remain authoritative even when their photographic background is
|
|
19175
|
-
* old; null means the link must carry a current camera frame.
|
|
19206
|
+
* old; null means the link must carry a current camera frame.
|
|
19207
|
+
*
|
|
19208
|
+
* **This is the ONLY source a surface may derive an inactive tile
|
|
19209
|
+
* from.** A client that reads a device's `online`/`disabled` flags and
|
|
19210
|
+
* draws its own verdict will disagree with the pixels it is painting
|
|
19211
|
+
* — the frame comes from here, and so must the sentence over it
|
|
19212
|
+
* (D190). Pair with `ageMs` for the age of the photograph behind the
|
|
19213
|
+
* state. */
|
|
19176
19214
|
stateReason: _enum([
|
|
19177
19215
|
"disabled",
|
|
19216
|
+
"offline",
|
|
19178
19217
|
"sleeping",
|
|
19179
19218
|
"unreachable",
|
|
19180
19219
|
"waking"
|
|
@@ -33383,7 +33422,6 @@ var NC_AUDIO_DEFAULTS = {
|
|
|
33383
33422
|
hitPercent: 60,
|
|
33384
33423
|
samplingSeconds: 10
|
|
33385
33424
|
};
|
|
33386
|
-
new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
|
|
33387
33425
|
new Set(["devices", "classes"]);
|
|
33388
33426
|
NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
|
|
33389
33427
|
/**
|
|
@@ -33617,6 +33655,39 @@ TimelapseRuleInputSchema.extend({
|
|
|
33617
33655
|
createdAt: number(),
|
|
33618
33656
|
updatedAt: number()
|
|
33619
33657
|
});
|
|
33658
|
+
Object.freeze(Object.fromEntries([{
|
|
33659
|
+
stepId: "face-embedding",
|
|
33660
|
+
label: "Face recognition model",
|
|
33661
|
+
defaultModelId: "arcface-r100",
|
|
33662
|
+
indexName: "the enrolled face gallery",
|
|
33663
|
+
options: [
|
|
33664
|
+
{
|
|
33665
|
+
id: "arcface-r100",
|
|
33666
|
+
label: "ArcFace (ResNet34)"
|
|
33667
|
+
},
|
|
33668
|
+
{
|
|
33669
|
+
id: "auraface-r100",
|
|
33670
|
+
label: "AuraFace R100"
|
|
33671
|
+
},
|
|
33672
|
+
{
|
|
33673
|
+
id: "inception-resnet-v1",
|
|
33674
|
+
label: "Inception ResNet V1"
|
|
33675
|
+
}
|
|
33676
|
+
]
|
|
33677
|
+
}, {
|
|
33678
|
+
stepId: "clip-embedding",
|
|
33679
|
+
label: "Semantic search model",
|
|
33680
|
+
defaultModelId: "mobileclip-s1",
|
|
33681
|
+
indexName: "the object semantic-search index",
|
|
33682
|
+
options: [{
|
|
33683
|
+
id: "mobileclip-s1",
|
|
33684
|
+
label: "MobileCLIP S1"
|
|
33685
|
+
}, {
|
|
33686
|
+
id: "mobileclip-s2",
|
|
33687
|
+
label: "MobileCLIP S2"
|
|
33688
|
+
}]
|
|
33689
|
+
}].map((s) => [s.stepId, s.defaultModelId])));
|
|
33690
|
+
string().min(1);
|
|
33620
33691
|
object({
|
|
33621
33692
|
/**
|
|
33622
33693
|
* Fraction of the box's own size added on EACH side before cutting.
|
|
@@ -33637,10 +33708,21 @@ object({
|
|
|
33637
33708
|
*/
|
|
33638
33709
|
square: boolean()
|
|
33639
33710
|
});
|
|
33640
|
-
|
|
33711
|
+
/**
|
|
33712
|
+
* The convention in force when nobody has configured one — byte-for-byte the
|
|
33713
|
+
* behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
|
|
33714
|
+
*/
|
|
33715
|
+
var DEFAULT_DETAIL_CROP_CONVENTION = {
|
|
33641
33716
|
paddingRatio: .15,
|
|
33642
33717
|
square: false
|
|
33643
|
-
}
|
|
33718
|
+
};
|
|
33719
|
+
Object.freeze({
|
|
33720
|
+
x: 0,
|
|
33721
|
+
y: 0,
|
|
33722
|
+
w: 1,
|
|
33723
|
+
h: 1
|
|
33724
|
+
});
|
|
33725
|
+
DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
|
|
33644
33726
|
/**
|
|
33645
33727
|
* WHICH delivered frames the decode worker retains a native copy of.
|
|
33646
33728
|
*
|