@camstack/addon-decoder-ffmpeg 1.2.21 → 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/index.js +167 -59
- package/dist/index.mjs +167 -59
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7567,7 +7567,7 @@ var RecordingBandSchema = object({
|
|
|
7567
7567
|
postBufferSec: number().min(0).optional()
|
|
7568
7568
|
});
|
|
7569
7569
|
({
|
|
7570
|
-
preBufferSec:
|
|
7570
|
+
preBufferSec: 15,
|
|
7571
7571
|
postBufferSec: 30
|
|
7572
7572
|
}).postBufferSec * 1e3;
|
|
7573
7573
|
/**
|
|
@@ -13636,128 +13636,103 @@ var COCO_TO_MACRO = {
|
|
|
13636
13636
|
var AUDIO_MACRO_LABELS = [
|
|
13637
13637
|
{
|
|
13638
13638
|
id: "speech",
|
|
13639
|
-
name: "Speech"
|
|
13640
|
-
icon: "🗣️"
|
|
13639
|
+
name: "Speech"
|
|
13641
13640
|
},
|
|
13642
13641
|
{
|
|
13643
13642
|
id: "scream",
|
|
13644
|
-
name: "Scream / Shout"
|
|
13645
|
-
icon: "😱"
|
|
13643
|
+
name: "Scream / Shout"
|
|
13646
13644
|
},
|
|
13647
13645
|
{
|
|
13648
13646
|
id: "crying",
|
|
13649
|
-
name: "Crying / Baby"
|
|
13650
|
-
icon: "😢"
|
|
13647
|
+
name: "Crying / Baby"
|
|
13651
13648
|
},
|
|
13652
13649
|
{
|
|
13653
13650
|
id: "laughter",
|
|
13654
|
-
name: "Laughter"
|
|
13655
|
-
icon: "😂"
|
|
13651
|
+
name: "Laughter"
|
|
13656
13652
|
},
|
|
13657
13653
|
{
|
|
13658
13654
|
id: "music",
|
|
13659
|
-
name: "Music"
|
|
13660
|
-
icon: "🎵"
|
|
13655
|
+
name: "Music"
|
|
13661
13656
|
},
|
|
13662
13657
|
{
|
|
13663
13658
|
id: "dog",
|
|
13664
|
-
name: "Dog"
|
|
13665
|
-
icon: "🐕"
|
|
13659
|
+
name: "Dog"
|
|
13666
13660
|
},
|
|
13667
13661
|
{
|
|
13668
13662
|
id: "cat",
|
|
13669
|
-
name: "Cat"
|
|
13670
|
-
icon: "🐈"
|
|
13663
|
+
name: "Cat"
|
|
13671
13664
|
},
|
|
13672
13665
|
{
|
|
13673
13666
|
id: "bird",
|
|
13674
|
-
name: "Bird"
|
|
13675
|
-
icon: "🐦"
|
|
13667
|
+
name: "Bird"
|
|
13676
13668
|
},
|
|
13677
13669
|
{
|
|
13678
13670
|
id: "animal",
|
|
13679
|
-
name: "Animal (other)"
|
|
13680
|
-
icon: "🐾"
|
|
13671
|
+
name: "Animal (other)"
|
|
13681
13672
|
},
|
|
13682
13673
|
{
|
|
13683
13674
|
id: "alarm",
|
|
13684
|
-
name: "Alarm / Siren"
|
|
13685
|
-
icon: "🚨"
|
|
13675
|
+
name: "Alarm / Siren"
|
|
13686
13676
|
},
|
|
13687
13677
|
{
|
|
13688
13678
|
id: "doorbell",
|
|
13689
|
-
name: "Doorbell / Knock"
|
|
13690
|
-
icon: "🔔"
|
|
13679
|
+
name: "Doorbell / Knock"
|
|
13691
13680
|
},
|
|
13692
13681
|
{
|
|
13693
13682
|
id: "glass_breaking",
|
|
13694
|
-
name: "Glass Breaking"
|
|
13695
|
-
icon: "💥"
|
|
13683
|
+
name: "Glass Breaking"
|
|
13696
13684
|
},
|
|
13697
13685
|
{
|
|
13698
13686
|
id: "gunshot",
|
|
13699
|
-
name: "Gunshot / Explosion"
|
|
13700
|
-
icon: "💣"
|
|
13687
|
+
name: "Gunshot / Explosion"
|
|
13701
13688
|
},
|
|
13702
13689
|
{
|
|
13703
13690
|
id: "vehicle",
|
|
13704
|
-
name: "Vehicle"
|
|
13705
|
-
icon: "🚗"
|
|
13691
|
+
name: "Vehicle"
|
|
13706
13692
|
},
|
|
13707
13693
|
{
|
|
13708
13694
|
id: "siren",
|
|
13709
|
-
name: "Emergency Siren"
|
|
13710
|
-
icon: "🚑"
|
|
13695
|
+
name: "Emergency Siren"
|
|
13711
13696
|
},
|
|
13712
13697
|
{
|
|
13713
13698
|
id: "fire",
|
|
13714
|
-
name: "Fire / Smoke"
|
|
13715
|
-
icon: "🔥"
|
|
13699
|
+
name: "Fire / Smoke"
|
|
13716
13700
|
},
|
|
13717
13701
|
{
|
|
13718
13702
|
id: "water",
|
|
13719
|
-
name: "Water"
|
|
13720
|
-
icon: "💧"
|
|
13703
|
+
name: "Water"
|
|
13721
13704
|
},
|
|
13722
13705
|
{
|
|
13723
13706
|
id: "wind",
|
|
13724
|
-
name: "Wind / Weather"
|
|
13725
|
-
icon: "🌬️"
|
|
13707
|
+
name: "Wind / Weather"
|
|
13726
13708
|
},
|
|
13727
13709
|
{
|
|
13728
13710
|
id: "door",
|
|
13729
|
-
name: "Door"
|
|
13730
|
-
icon: "🚪"
|
|
13711
|
+
name: "Door"
|
|
13731
13712
|
},
|
|
13732
13713
|
{
|
|
13733
13714
|
id: "footsteps",
|
|
13734
|
-
name: "Footsteps"
|
|
13735
|
-
icon: "👣"
|
|
13715
|
+
name: "Footsteps"
|
|
13736
13716
|
},
|
|
13737
13717
|
{
|
|
13738
13718
|
id: "crowd",
|
|
13739
|
-
name: "Crowd / Chatter"
|
|
13740
|
-
icon: "👥"
|
|
13719
|
+
name: "Crowd / Chatter"
|
|
13741
13720
|
},
|
|
13742
13721
|
{
|
|
13743
13722
|
id: "telephone",
|
|
13744
|
-
name: "Telephone"
|
|
13745
|
-
icon: "📞"
|
|
13723
|
+
name: "Telephone"
|
|
13746
13724
|
},
|
|
13747
13725
|
{
|
|
13748
13726
|
id: "engine",
|
|
13749
|
-
name: "Engine / Motor"
|
|
13750
|
-
icon: "⚙️"
|
|
13727
|
+
name: "Engine / Motor"
|
|
13751
13728
|
},
|
|
13752
13729
|
{
|
|
13753
13730
|
id: "tools",
|
|
13754
|
-
name: "Tools / Construction"
|
|
13755
|
-
icon: "🔨"
|
|
13731
|
+
name: "Tools / Construction"
|
|
13756
13732
|
},
|
|
13757
13733
|
{
|
|
13758
13734
|
id: "silence",
|
|
13759
|
-
name: "Silence"
|
|
13760
|
-
icon: "🤫"
|
|
13735
|
+
name: "Silence"
|
|
13761
13736
|
}
|
|
13762
13737
|
];
|
|
13763
13738
|
var YAMNET_TO_MACRO = {
|
|
@@ -16221,7 +16196,7 @@ var TrackEnvelopeSchema = object({
|
|
|
16221
16196
|
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
16222
16197
|
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
16223
16198
|
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
16224
|
-
* zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
|
|
16199
|
+
* zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
|
|
16225
16200
|
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
16226
16201
|
* `getTrack`. Mirrors the event-store `projection` convention
|
|
16227
16202
|
* (`getObjectEvents` et al.).
|
|
@@ -16516,6 +16491,35 @@ var TrackSchema = object({
|
|
|
16516
16491
|
*/
|
|
16517
16492
|
hasFace: boolean().optional(),
|
|
16518
16493
|
/**
|
|
16494
|
+
* This track has a face row IN THE GALLERY: a crop **and** an embedding — a
|
|
16495
|
+
* face an operator could ASSIGN to an identity.
|
|
16496
|
+
*
|
|
16497
|
+
* The STRICT twin of {@link hasFace}, and the pair only earns its keep
|
|
16498
|
+
* because the two disagree. `hasFace` is stamped at the TOP of the face
|
|
16499
|
+
* branch, before every gate, and means no more than "a face detector produced
|
|
16500
|
+
* a face detail". This one is stamped at the single moment the gallery row
|
|
16501
|
+
* LANDS — after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
|
|
16502
|
+
* past the embedding-magnitude verdict, the `minFacePx` detection gate, the
|
|
16503
|
+
* candidate gate, the imageless-track drop (no crop was ever captured) and
|
|
16504
|
+
* the crop-store drop. Everything between the detector and that insert can
|
|
16505
|
+
* legitimately refuse the face, so a flag written any earlier promises the
|
|
16506
|
+
* operator something to assign and delivers nothing.
|
|
16507
|
+
*
|
|
16508
|
+
* **Independent of recognition.** A face collected but never auto-matched is
|
|
16509
|
+
* still assignable — it is in fact the face an operator most wants to reach —
|
|
16510
|
+
* so this is NOT gated on `recognizedIdentityId`. Recognition lands in
|
|
16511
|
+
* `subLabel`; this says only that the raw material exists.
|
|
16512
|
+
*
|
|
16513
|
+
* **Set once, never cleared.** A track that produced a gallery row produced
|
|
16514
|
+
* one; deleting the row later is the gallery's business, not this flag's.
|
|
16515
|
+
*
|
|
16516
|
+
* **Absent ≠ false**, the same rule as {@link hasFace}: every row written
|
|
16517
|
+
* before the column omits it, and so does every server that predates the
|
|
16518
|
+
* field. A consumer must test `=== true` and render nothing otherwise —
|
|
16519
|
+
* never infer "no assignable face".
|
|
16520
|
+
*/
|
|
16521
|
+
hasEmbeddedFace: boolean().optional(),
|
|
16522
|
+
/**
|
|
16519
16523
|
* This subject CONTAINS a folded rider — a person the rider-pairing step
|
|
16520
16524
|
* ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
|
|
16521
16525
|
* so the passage is tracked once and as a VEHICLE.
|
|
@@ -17865,6 +17869,32 @@ var DetailResultSchema = object({
|
|
|
17865
17869
|
/** FRAME-space bbox (already mapped back from crop space). */
|
|
17866
17870
|
bbox: NativeCropBboxSchema.optional(),
|
|
17867
17871
|
embedding: string().optional(),
|
|
17872
|
+
/**
|
|
17873
|
+
* L2 magnitude of the RAW pre-normalization embedding. Additive and optional
|
|
17874
|
+
* so an older runner that does not send it degrades to "unmeasurable", which
|
|
17875
|
+
* the consuming gate treats as accept — never as reject.
|
|
17876
|
+
*/
|
|
17877
|
+
embeddingMagnitude: number().optional(),
|
|
17878
|
+
/**
|
|
17879
|
+
* Model that produced `embedding` — the SAME contract `labelModelId` has for
|
|
17880
|
+
* `label`, and for the same reason: the producing node is the only side that
|
|
17881
|
+
* knows which model actually ran, and re-deriving it downstream is exactly
|
|
17882
|
+
* the inference this model exists to forbid.
|
|
17883
|
+
*
|
|
17884
|
+
* Additive and optional, so a runner that predates it degrades to
|
|
17885
|
+
* "unmeasurable" rather than to a wrong answer — the consumer falls back to
|
|
17886
|
+
* its previous assumption instead of refusing.
|
|
17887
|
+
*
|
|
17888
|
+
* Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
|
|
17889
|
+
* to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
|
|
17890
|
+
* with nothing on the wire it took the id from the GALLERY, so the gate
|
|
17891
|
+
* compared the gallery against itself and could never fire. That turned the
|
|
17892
|
+
* one guard protecting the face feature space into a tautology, and it is
|
|
17893
|
+
* why swapping `face-embedding`'s model would NOT have stranded the enrolled
|
|
17894
|
+
* gallery as the catalog comment predicts — it would have scored the new
|
|
17895
|
+
* model's vectors against the old model's samples in one cosine space.
|
|
17896
|
+
*/
|
|
17897
|
+
embeddingModelId: string().optional(),
|
|
17868
17898
|
label: string().optional(),
|
|
17869
17899
|
/**
|
|
17870
17900
|
* The tier `label` occupies, copied VERBATIM from the producing step's
|
|
@@ -19275,6 +19305,7 @@ DeviceType.Camera, method(object({
|
|
|
19275
19305
|
isBattery: boolean(),
|
|
19276
19306
|
reason: _enum([
|
|
19277
19307
|
"disabled",
|
|
19308
|
+
"offline",
|
|
19278
19309
|
"sleeping",
|
|
19279
19310
|
"unreachable",
|
|
19280
19311
|
"waking"
|
|
@@ -19320,9 +19351,17 @@ targets: array(object({
|
|
|
19320
19351
|
sleeping: boolean(),
|
|
19321
19352
|
/** Current device state rendered over the cached frame. State images
|
|
19322
19353
|
* remain authoritative even when their photographic background is
|
|
19323
|
-
* old; null means the link must carry a current camera frame.
|
|
19354
|
+
* old; null means the link must carry a current camera frame.
|
|
19355
|
+
*
|
|
19356
|
+
* **This is the ONLY source a surface may derive an inactive tile
|
|
19357
|
+
* from.** A client that reads a device's `online`/`disabled` flags and
|
|
19358
|
+
* draws its own verdict will disagree with the pixels it is painting
|
|
19359
|
+
* — the frame comes from here, and so must the sentence over it
|
|
19360
|
+
* (D190). Pair with `ageMs` for the age of the photograph behind the
|
|
19361
|
+
* state. */
|
|
19324
19362
|
stateReason: _enum([
|
|
19325
19363
|
"disabled",
|
|
19364
|
+
"offline",
|
|
19326
19365
|
"sleeping",
|
|
19327
19366
|
"unreachable",
|
|
19328
19367
|
"waking"
|
|
@@ -24353,9 +24392,21 @@ var RecordingLocationUsageSchema = object({
|
|
|
24353
24392
|
* previously rendered as two identical "disks" with a nonsensical used
|
|
24354
24393
|
* split — hydrate attribution across aliases is arbitrary by nature. */
|
|
24355
24394
|
locationIds: array(string()).optional(),
|
|
24356
|
-
/**
|
|
24395
|
+
/**
|
|
24396
|
+
* Filesystem root of the physical volume this row accounts — the only
|
|
24397
|
+
* operator-legible identity when a location has no `displayName` yet, and
|
|
24398
|
+
* what a "which disk is full" alert has to name. OPTIONAL for the same
|
|
24399
|
+
* train-skew reason as `oldestMs`: a recorder that predates the field omits
|
|
24400
|
+
* it, and this schema must keep validating that older provider's payload.
|
|
24401
|
+
*/
|
|
24402
|
+
root: string().optional(),
|
|
24403
|
+
/** Bytes of recordings stored on this PHYSICAL volume (all aliases). This is
|
|
24404
|
+
* the footage's SHARE of the volume, not how full the volume is — the disk
|
|
24405
|
+
* also holds everything that is not recordings. Volume fill is
|
|
24406
|
+
* `(totalBytes - availableBytes) / totalBytes`. */
|
|
24357
24407
|
usedBytes: number(),
|
|
24358
|
-
/** Free bytes on the location's volume; null when capacity is unknown
|
|
24408
|
+
/** Free bytes on the location's volume; null when capacity is unknown
|
|
24409
|
+
* (remote/unstattable — the recorder logs the statfs failure with the root). */
|
|
24359
24410
|
availableBytes: number().nullable(),
|
|
24360
24411
|
/** Total bytes of the location's volume; null when unknown. */
|
|
24361
24412
|
totalBytes: number().nullable()
|
|
@@ -24367,7 +24418,15 @@ var RecordingStorageUsageSchema = object({
|
|
|
24367
24418
|
nodeId: string(),
|
|
24368
24419
|
totalUsedBytes: number(),
|
|
24369
24420
|
devices: array(RecordingDeviceUsageSchema),
|
|
24370
|
-
|
|
24421
|
+
/**
|
|
24422
|
+
* Per-physical-volume capacity. OPTIONAL, and consumers must render the rest
|
|
24423
|
+
* of the payload without it: the hub serves this method through a BAKED
|
|
24424
|
+
* router, so a hub whose framework train predates a change to this array
|
|
24425
|
+
* strips it out of an answer a newer recorder happily produced. A UI that
|
|
24426
|
+
* dereferences it unconditionally crashes the whole Storage page over a
|
|
24427
|
+
* missing disk bar.
|
|
24428
|
+
*/
|
|
24429
|
+
locations: array(RecordingLocationUsageSchema).optional()
|
|
24371
24430
|
});
|
|
24372
24431
|
/**
|
|
24373
24432
|
* The OPERATOR-ARMED half of multi-location recordings (D116).
|
|
@@ -33483,8 +33542,13 @@ Object.freeze({
|
|
|
33483
33542
|
"network-access": "ingress",
|
|
33484
33543
|
"smtp-provider": "email"
|
|
33485
33544
|
});
|
|
33486
|
-
|
|
33545
|
+
/** Schema defaults — an untouched sub-field must author exactly these. */
|
|
33546
|
+
var NC_AUDIO_DEFAULTS = {
|
|
33547
|
+
hitPercent: 60,
|
|
33548
|
+
samplingSeconds: 10
|
|
33549
|
+
};
|
|
33487
33550
|
new Set(["devices", "classes"]);
|
|
33551
|
+
NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
|
|
33488
33552
|
/**
|
|
33489
33553
|
* TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
|
|
33490
33554
|
*
|
|
@@ -33716,6 +33780,39 @@ TimelapseRuleInputSchema.extend({
|
|
|
33716
33780
|
createdAt: number(),
|
|
33717
33781
|
updatedAt: number()
|
|
33718
33782
|
});
|
|
33783
|
+
Object.freeze(Object.fromEntries([{
|
|
33784
|
+
stepId: "face-embedding",
|
|
33785
|
+
label: "Face recognition model",
|
|
33786
|
+
defaultModelId: "arcface-r100",
|
|
33787
|
+
indexName: "the enrolled face gallery",
|
|
33788
|
+
options: [
|
|
33789
|
+
{
|
|
33790
|
+
id: "arcface-r100",
|
|
33791
|
+
label: "ArcFace (ResNet34)"
|
|
33792
|
+
},
|
|
33793
|
+
{
|
|
33794
|
+
id: "auraface-r100",
|
|
33795
|
+
label: "AuraFace R100"
|
|
33796
|
+
},
|
|
33797
|
+
{
|
|
33798
|
+
id: "inception-resnet-v1",
|
|
33799
|
+
label: "Inception ResNet V1"
|
|
33800
|
+
}
|
|
33801
|
+
]
|
|
33802
|
+
}, {
|
|
33803
|
+
stepId: "clip-embedding",
|
|
33804
|
+
label: "Semantic search model",
|
|
33805
|
+
defaultModelId: "mobileclip-s1",
|
|
33806
|
+
indexName: "the object semantic-search index",
|
|
33807
|
+
options: [{
|
|
33808
|
+
id: "mobileclip-s1",
|
|
33809
|
+
label: "MobileCLIP S1"
|
|
33810
|
+
}, {
|
|
33811
|
+
id: "mobileclip-s2",
|
|
33812
|
+
label: "MobileCLIP S2"
|
|
33813
|
+
}]
|
|
33814
|
+
}].map((s) => [s.stepId, s.defaultModelId])));
|
|
33815
|
+
string().min(1);
|
|
33719
33816
|
object({
|
|
33720
33817
|
/**
|
|
33721
33818
|
* Fraction of the box's own size added on EACH side before cutting.
|
|
@@ -33736,10 +33833,21 @@ object({
|
|
|
33736
33833
|
*/
|
|
33737
33834
|
square: boolean()
|
|
33738
33835
|
});
|
|
33739
|
-
|
|
33836
|
+
/**
|
|
33837
|
+
* The convention in force when nobody has configured one — byte-for-byte the
|
|
33838
|
+
* behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
|
|
33839
|
+
*/
|
|
33840
|
+
var DEFAULT_DETAIL_CROP_CONVENTION = {
|
|
33740
33841
|
paddingRatio: .15,
|
|
33741
33842
|
square: false
|
|
33742
|
-
}
|
|
33843
|
+
};
|
|
33844
|
+
Object.freeze({
|
|
33845
|
+
x: 0,
|
|
33846
|
+
y: 0,
|
|
33847
|
+
w: 1,
|
|
33848
|
+
h: 1
|
|
33849
|
+
});
|
|
33850
|
+
DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
|
|
33743
33851
|
/**
|
|
33744
33852
|
* WHICH delivered frames the decode worker retains a native copy of.
|
|
33745
33853
|
*
|
package/dist/index.mjs
CHANGED
|
@@ -7563,7 +7563,7 @@ var RecordingBandSchema = object({
|
|
|
7563
7563
|
postBufferSec: number().min(0).optional()
|
|
7564
7564
|
});
|
|
7565
7565
|
({
|
|
7566
|
-
preBufferSec:
|
|
7566
|
+
preBufferSec: 15,
|
|
7567
7567
|
postBufferSec: 30
|
|
7568
7568
|
}).postBufferSec * 1e3;
|
|
7569
7569
|
/**
|
|
@@ -13632,128 +13632,103 @@ var COCO_TO_MACRO = {
|
|
|
13632
13632
|
var AUDIO_MACRO_LABELS = [
|
|
13633
13633
|
{
|
|
13634
13634
|
id: "speech",
|
|
13635
|
-
name: "Speech"
|
|
13636
|
-
icon: "🗣️"
|
|
13635
|
+
name: "Speech"
|
|
13637
13636
|
},
|
|
13638
13637
|
{
|
|
13639
13638
|
id: "scream",
|
|
13640
|
-
name: "Scream / Shout"
|
|
13641
|
-
icon: "😱"
|
|
13639
|
+
name: "Scream / Shout"
|
|
13642
13640
|
},
|
|
13643
13641
|
{
|
|
13644
13642
|
id: "crying",
|
|
13645
|
-
name: "Crying / Baby"
|
|
13646
|
-
icon: "😢"
|
|
13643
|
+
name: "Crying / Baby"
|
|
13647
13644
|
},
|
|
13648
13645
|
{
|
|
13649
13646
|
id: "laughter",
|
|
13650
|
-
name: "Laughter"
|
|
13651
|
-
icon: "😂"
|
|
13647
|
+
name: "Laughter"
|
|
13652
13648
|
},
|
|
13653
13649
|
{
|
|
13654
13650
|
id: "music",
|
|
13655
|
-
name: "Music"
|
|
13656
|
-
icon: "🎵"
|
|
13651
|
+
name: "Music"
|
|
13657
13652
|
},
|
|
13658
13653
|
{
|
|
13659
13654
|
id: "dog",
|
|
13660
|
-
name: "Dog"
|
|
13661
|
-
icon: "🐕"
|
|
13655
|
+
name: "Dog"
|
|
13662
13656
|
},
|
|
13663
13657
|
{
|
|
13664
13658
|
id: "cat",
|
|
13665
|
-
name: "Cat"
|
|
13666
|
-
icon: "🐈"
|
|
13659
|
+
name: "Cat"
|
|
13667
13660
|
},
|
|
13668
13661
|
{
|
|
13669
13662
|
id: "bird",
|
|
13670
|
-
name: "Bird"
|
|
13671
|
-
icon: "🐦"
|
|
13663
|
+
name: "Bird"
|
|
13672
13664
|
},
|
|
13673
13665
|
{
|
|
13674
13666
|
id: "animal",
|
|
13675
|
-
name: "Animal (other)"
|
|
13676
|
-
icon: "🐾"
|
|
13667
|
+
name: "Animal (other)"
|
|
13677
13668
|
},
|
|
13678
13669
|
{
|
|
13679
13670
|
id: "alarm",
|
|
13680
|
-
name: "Alarm / Siren"
|
|
13681
|
-
icon: "🚨"
|
|
13671
|
+
name: "Alarm / Siren"
|
|
13682
13672
|
},
|
|
13683
13673
|
{
|
|
13684
13674
|
id: "doorbell",
|
|
13685
|
-
name: "Doorbell / Knock"
|
|
13686
|
-
icon: "🔔"
|
|
13675
|
+
name: "Doorbell / Knock"
|
|
13687
13676
|
},
|
|
13688
13677
|
{
|
|
13689
13678
|
id: "glass_breaking",
|
|
13690
|
-
name: "Glass Breaking"
|
|
13691
|
-
icon: "💥"
|
|
13679
|
+
name: "Glass Breaking"
|
|
13692
13680
|
},
|
|
13693
13681
|
{
|
|
13694
13682
|
id: "gunshot",
|
|
13695
|
-
name: "Gunshot / Explosion"
|
|
13696
|
-
icon: "💣"
|
|
13683
|
+
name: "Gunshot / Explosion"
|
|
13697
13684
|
},
|
|
13698
13685
|
{
|
|
13699
13686
|
id: "vehicle",
|
|
13700
|
-
name: "Vehicle"
|
|
13701
|
-
icon: "🚗"
|
|
13687
|
+
name: "Vehicle"
|
|
13702
13688
|
},
|
|
13703
13689
|
{
|
|
13704
13690
|
id: "siren",
|
|
13705
|
-
name: "Emergency Siren"
|
|
13706
|
-
icon: "🚑"
|
|
13691
|
+
name: "Emergency Siren"
|
|
13707
13692
|
},
|
|
13708
13693
|
{
|
|
13709
13694
|
id: "fire",
|
|
13710
|
-
name: "Fire / Smoke"
|
|
13711
|
-
icon: "🔥"
|
|
13695
|
+
name: "Fire / Smoke"
|
|
13712
13696
|
},
|
|
13713
13697
|
{
|
|
13714
13698
|
id: "water",
|
|
13715
|
-
name: "Water"
|
|
13716
|
-
icon: "💧"
|
|
13699
|
+
name: "Water"
|
|
13717
13700
|
},
|
|
13718
13701
|
{
|
|
13719
13702
|
id: "wind",
|
|
13720
|
-
name: "Wind / Weather"
|
|
13721
|
-
icon: "🌬️"
|
|
13703
|
+
name: "Wind / Weather"
|
|
13722
13704
|
},
|
|
13723
13705
|
{
|
|
13724
13706
|
id: "door",
|
|
13725
|
-
name: "Door"
|
|
13726
|
-
icon: "🚪"
|
|
13707
|
+
name: "Door"
|
|
13727
13708
|
},
|
|
13728
13709
|
{
|
|
13729
13710
|
id: "footsteps",
|
|
13730
|
-
name: "Footsteps"
|
|
13731
|
-
icon: "👣"
|
|
13711
|
+
name: "Footsteps"
|
|
13732
13712
|
},
|
|
13733
13713
|
{
|
|
13734
13714
|
id: "crowd",
|
|
13735
|
-
name: "Crowd / Chatter"
|
|
13736
|
-
icon: "👥"
|
|
13715
|
+
name: "Crowd / Chatter"
|
|
13737
13716
|
},
|
|
13738
13717
|
{
|
|
13739
13718
|
id: "telephone",
|
|
13740
|
-
name: "Telephone"
|
|
13741
|
-
icon: "📞"
|
|
13719
|
+
name: "Telephone"
|
|
13742
13720
|
},
|
|
13743
13721
|
{
|
|
13744
13722
|
id: "engine",
|
|
13745
|
-
name: "Engine / Motor"
|
|
13746
|
-
icon: "⚙️"
|
|
13723
|
+
name: "Engine / Motor"
|
|
13747
13724
|
},
|
|
13748
13725
|
{
|
|
13749
13726
|
id: "tools",
|
|
13750
|
-
name: "Tools / Construction"
|
|
13751
|
-
icon: "🔨"
|
|
13727
|
+
name: "Tools / Construction"
|
|
13752
13728
|
},
|
|
13753
13729
|
{
|
|
13754
13730
|
id: "silence",
|
|
13755
|
-
name: "Silence"
|
|
13756
|
-
icon: "🤫"
|
|
13731
|
+
name: "Silence"
|
|
13757
13732
|
}
|
|
13758
13733
|
];
|
|
13759
13734
|
var YAMNET_TO_MACRO = {
|
|
@@ -16217,7 +16192,7 @@ var TrackEnvelopeSchema = object({
|
|
|
16217
16192
|
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
16218
16193
|
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
16219
16194
|
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
16220
|
-
* zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
|
|
16195
|
+
* zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
|
|
16221
16196
|
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
16222
16197
|
* `getTrack`. Mirrors the event-store `projection` convention
|
|
16223
16198
|
* (`getObjectEvents` et al.).
|
|
@@ -16512,6 +16487,35 @@ var TrackSchema = object({
|
|
|
16512
16487
|
*/
|
|
16513
16488
|
hasFace: boolean().optional(),
|
|
16514
16489
|
/**
|
|
16490
|
+
* This track has a face row IN THE GALLERY: a crop **and** an embedding — a
|
|
16491
|
+
* face an operator could ASSIGN to an identity.
|
|
16492
|
+
*
|
|
16493
|
+
* The STRICT twin of {@link hasFace}, and the pair only earns its keep
|
|
16494
|
+
* because the two disagree. `hasFace` is stamped at the TOP of the face
|
|
16495
|
+
* branch, before every gate, and means no more than "a face detector produced
|
|
16496
|
+
* a face detail". This one is stamped at the single moment the gallery row
|
|
16497
|
+
* LANDS — after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
|
|
16498
|
+
* past the embedding-magnitude verdict, the `minFacePx` detection gate, the
|
|
16499
|
+
* candidate gate, the imageless-track drop (no crop was ever captured) and
|
|
16500
|
+
* the crop-store drop. Everything between the detector and that insert can
|
|
16501
|
+
* legitimately refuse the face, so a flag written any earlier promises the
|
|
16502
|
+
* operator something to assign and delivers nothing.
|
|
16503
|
+
*
|
|
16504
|
+
* **Independent of recognition.** A face collected but never auto-matched is
|
|
16505
|
+
* still assignable — it is in fact the face an operator most wants to reach —
|
|
16506
|
+
* so this is NOT gated on `recognizedIdentityId`. Recognition lands in
|
|
16507
|
+
* `subLabel`; this says only that the raw material exists.
|
|
16508
|
+
*
|
|
16509
|
+
* **Set once, never cleared.** A track that produced a gallery row produced
|
|
16510
|
+
* one; deleting the row later is the gallery's business, not this flag's.
|
|
16511
|
+
*
|
|
16512
|
+
* **Absent ≠ false**, the same rule as {@link hasFace}: every row written
|
|
16513
|
+
* before the column omits it, and so does every server that predates the
|
|
16514
|
+
* field. A consumer must test `=== true` and render nothing otherwise —
|
|
16515
|
+
* never infer "no assignable face".
|
|
16516
|
+
*/
|
|
16517
|
+
hasEmbeddedFace: boolean().optional(),
|
|
16518
|
+
/**
|
|
16515
16519
|
* This subject CONTAINS a folded rider — a person the rider-pairing step
|
|
16516
16520
|
* ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
|
|
16517
16521
|
* so the passage is tracked once and as a VEHICLE.
|
|
@@ -17861,6 +17865,32 @@ var DetailResultSchema = object({
|
|
|
17861
17865
|
/** FRAME-space bbox (already mapped back from crop space). */
|
|
17862
17866
|
bbox: NativeCropBboxSchema.optional(),
|
|
17863
17867
|
embedding: string().optional(),
|
|
17868
|
+
/**
|
|
17869
|
+
* L2 magnitude of the RAW pre-normalization embedding. Additive and optional
|
|
17870
|
+
* so an older runner that does not send it degrades to "unmeasurable", which
|
|
17871
|
+
* the consuming gate treats as accept — never as reject.
|
|
17872
|
+
*/
|
|
17873
|
+
embeddingMagnitude: number().optional(),
|
|
17874
|
+
/**
|
|
17875
|
+
* Model that produced `embedding` — the SAME contract `labelModelId` has for
|
|
17876
|
+
* `label`, and for the same reason: the producing node is the only side that
|
|
17877
|
+
* knows which model actually ran, and re-deriving it downstream is exactly
|
|
17878
|
+
* the inference this model exists to forbid.
|
|
17879
|
+
*
|
|
17880
|
+
* Additive and optional, so a runner that predates it degrades to
|
|
17881
|
+
* "unmeasurable" rather than to a wrong answer — the consumer falls back to
|
|
17882
|
+
* its previous assumption instead of refusing.
|
|
17883
|
+
*
|
|
17884
|
+
* Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
|
|
17885
|
+
* to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
|
|
17886
|
+
* with nothing on the wire it took the id from the GALLERY, so the gate
|
|
17887
|
+
* compared the gallery against itself and could never fire. That turned the
|
|
17888
|
+
* one guard protecting the face feature space into a tautology, and it is
|
|
17889
|
+
* why swapping `face-embedding`'s model would NOT have stranded the enrolled
|
|
17890
|
+
* gallery as the catalog comment predicts — it would have scored the new
|
|
17891
|
+
* model's vectors against the old model's samples in one cosine space.
|
|
17892
|
+
*/
|
|
17893
|
+
embeddingModelId: string().optional(),
|
|
17864
17894
|
label: string().optional(),
|
|
17865
17895
|
/**
|
|
17866
17896
|
* The tier `label` occupies, copied VERBATIM from the producing step's
|
|
@@ -19271,6 +19301,7 @@ DeviceType.Camera, method(object({
|
|
|
19271
19301
|
isBattery: boolean(),
|
|
19272
19302
|
reason: _enum([
|
|
19273
19303
|
"disabled",
|
|
19304
|
+
"offline",
|
|
19274
19305
|
"sleeping",
|
|
19275
19306
|
"unreachable",
|
|
19276
19307
|
"waking"
|
|
@@ -19316,9 +19347,17 @@ targets: array(object({
|
|
|
19316
19347
|
sleeping: boolean(),
|
|
19317
19348
|
/** Current device state rendered over the cached frame. State images
|
|
19318
19349
|
* remain authoritative even when their photographic background is
|
|
19319
|
-
* old; null means the link must carry a current camera frame.
|
|
19350
|
+
* old; null means the link must carry a current camera frame.
|
|
19351
|
+
*
|
|
19352
|
+
* **This is the ONLY source a surface may derive an inactive tile
|
|
19353
|
+
* from.** A client that reads a device's `online`/`disabled` flags and
|
|
19354
|
+
* draws its own verdict will disagree with the pixels it is painting
|
|
19355
|
+
* — the frame comes from here, and so must the sentence over it
|
|
19356
|
+
* (D190). Pair with `ageMs` for the age of the photograph behind the
|
|
19357
|
+
* state. */
|
|
19320
19358
|
stateReason: _enum([
|
|
19321
19359
|
"disabled",
|
|
19360
|
+
"offline",
|
|
19322
19361
|
"sleeping",
|
|
19323
19362
|
"unreachable",
|
|
19324
19363
|
"waking"
|
|
@@ -24349,9 +24388,21 @@ var RecordingLocationUsageSchema = object({
|
|
|
24349
24388
|
* previously rendered as two identical "disks" with a nonsensical used
|
|
24350
24389
|
* split — hydrate attribution across aliases is arbitrary by nature. */
|
|
24351
24390
|
locationIds: array(string()).optional(),
|
|
24352
|
-
/**
|
|
24391
|
+
/**
|
|
24392
|
+
* Filesystem root of the physical volume this row accounts — the only
|
|
24393
|
+
* operator-legible identity when a location has no `displayName` yet, and
|
|
24394
|
+
* what a "which disk is full" alert has to name. OPTIONAL for the same
|
|
24395
|
+
* train-skew reason as `oldestMs`: a recorder that predates the field omits
|
|
24396
|
+
* it, and this schema must keep validating that older provider's payload.
|
|
24397
|
+
*/
|
|
24398
|
+
root: string().optional(),
|
|
24399
|
+
/** Bytes of recordings stored on this PHYSICAL volume (all aliases). This is
|
|
24400
|
+
* the footage's SHARE of the volume, not how full the volume is — the disk
|
|
24401
|
+
* also holds everything that is not recordings. Volume fill is
|
|
24402
|
+
* `(totalBytes - availableBytes) / totalBytes`. */
|
|
24353
24403
|
usedBytes: number(),
|
|
24354
|
-
/** Free bytes on the location's volume; null when capacity is unknown
|
|
24404
|
+
/** Free bytes on the location's volume; null when capacity is unknown
|
|
24405
|
+
* (remote/unstattable — the recorder logs the statfs failure with the root). */
|
|
24355
24406
|
availableBytes: number().nullable(),
|
|
24356
24407
|
/** Total bytes of the location's volume; null when unknown. */
|
|
24357
24408
|
totalBytes: number().nullable()
|
|
@@ -24363,7 +24414,15 @@ var RecordingStorageUsageSchema = object({
|
|
|
24363
24414
|
nodeId: string(),
|
|
24364
24415
|
totalUsedBytes: number(),
|
|
24365
24416
|
devices: array(RecordingDeviceUsageSchema),
|
|
24366
|
-
|
|
24417
|
+
/**
|
|
24418
|
+
* Per-physical-volume capacity. OPTIONAL, and consumers must render the rest
|
|
24419
|
+
* of the payload without it: the hub serves this method through a BAKED
|
|
24420
|
+
* router, so a hub whose framework train predates a change to this array
|
|
24421
|
+
* strips it out of an answer a newer recorder happily produced. A UI that
|
|
24422
|
+
* dereferences it unconditionally crashes the whole Storage page over a
|
|
24423
|
+
* missing disk bar.
|
|
24424
|
+
*/
|
|
24425
|
+
locations: array(RecordingLocationUsageSchema).optional()
|
|
24367
24426
|
});
|
|
24368
24427
|
/**
|
|
24369
24428
|
* The OPERATOR-ARMED half of multi-location recordings (D116).
|
|
@@ -33479,8 +33538,13 @@ Object.freeze({
|
|
|
33479
33538
|
"network-access": "ingress",
|
|
33480
33539
|
"smtp-provider": "email"
|
|
33481
33540
|
});
|
|
33482
|
-
|
|
33541
|
+
/** Schema defaults — an untouched sub-field must author exactly these. */
|
|
33542
|
+
var NC_AUDIO_DEFAULTS = {
|
|
33543
|
+
hitPercent: 60,
|
|
33544
|
+
samplingSeconds: 10
|
|
33545
|
+
};
|
|
33483
33546
|
new Set(["devices", "classes"]);
|
|
33547
|
+
NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
|
|
33484
33548
|
/**
|
|
33485
33549
|
* TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
|
|
33486
33550
|
*
|
|
@@ -33712,6 +33776,39 @@ TimelapseRuleInputSchema.extend({
|
|
|
33712
33776
|
createdAt: number(),
|
|
33713
33777
|
updatedAt: number()
|
|
33714
33778
|
});
|
|
33779
|
+
Object.freeze(Object.fromEntries([{
|
|
33780
|
+
stepId: "face-embedding",
|
|
33781
|
+
label: "Face recognition model",
|
|
33782
|
+
defaultModelId: "arcface-r100",
|
|
33783
|
+
indexName: "the enrolled face gallery",
|
|
33784
|
+
options: [
|
|
33785
|
+
{
|
|
33786
|
+
id: "arcface-r100",
|
|
33787
|
+
label: "ArcFace (ResNet34)"
|
|
33788
|
+
},
|
|
33789
|
+
{
|
|
33790
|
+
id: "auraface-r100",
|
|
33791
|
+
label: "AuraFace R100"
|
|
33792
|
+
},
|
|
33793
|
+
{
|
|
33794
|
+
id: "inception-resnet-v1",
|
|
33795
|
+
label: "Inception ResNet V1"
|
|
33796
|
+
}
|
|
33797
|
+
]
|
|
33798
|
+
}, {
|
|
33799
|
+
stepId: "clip-embedding",
|
|
33800
|
+
label: "Semantic search model",
|
|
33801
|
+
defaultModelId: "mobileclip-s1",
|
|
33802
|
+
indexName: "the object semantic-search index",
|
|
33803
|
+
options: [{
|
|
33804
|
+
id: "mobileclip-s1",
|
|
33805
|
+
label: "MobileCLIP S1"
|
|
33806
|
+
}, {
|
|
33807
|
+
id: "mobileclip-s2",
|
|
33808
|
+
label: "MobileCLIP S2"
|
|
33809
|
+
}]
|
|
33810
|
+
}].map((s) => [s.stepId, s.defaultModelId])));
|
|
33811
|
+
string().min(1);
|
|
33715
33812
|
object({
|
|
33716
33813
|
/**
|
|
33717
33814
|
* Fraction of the box's own size added on EACH side before cutting.
|
|
@@ -33732,10 +33829,21 @@ object({
|
|
|
33732
33829
|
*/
|
|
33733
33830
|
square: boolean()
|
|
33734
33831
|
});
|
|
33735
|
-
|
|
33832
|
+
/**
|
|
33833
|
+
* The convention in force when nobody has configured one — byte-for-byte the
|
|
33834
|
+
* behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
|
|
33835
|
+
*/
|
|
33836
|
+
var DEFAULT_DETAIL_CROP_CONVENTION = {
|
|
33736
33837
|
paddingRatio: .15,
|
|
33737
33838
|
square: false
|
|
33738
|
-
}
|
|
33839
|
+
};
|
|
33840
|
+
Object.freeze({
|
|
33841
|
+
x: 0,
|
|
33842
|
+
y: 0,
|
|
33843
|
+
w: 1,
|
|
33844
|
+
h: 1
|
|
33845
|
+
});
|
|
33846
|
+
DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
|
|
33739
33847
|
/**
|
|
33740
33848
|
* WHICH delivered frames the decode worker retains a native copy of.
|
|
33741
33849
|
*
|