@camstack/addon-decoder-ffmpeg 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.
Files changed (3) hide show
  1. package/dist/index.js +138 -56
  2. package/dist/index.mjs +138 -56
  3. 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: 10,
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"
@@ -33508,7 +33547,6 @@ var NC_AUDIO_DEFAULTS = {
33508
33547
  hitPercent: 60,
33509
33548
  samplingSeconds: 10
33510
33549
  };
33511
- new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
33512
33550
  new Set(["devices", "classes"]);
33513
33551
  NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
33514
33552
  /**
@@ -33742,6 +33780,39 @@ TimelapseRuleInputSchema.extend({
33742
33780
  createdAt: number(),
33743
33781
  updatedAt: number()
33744
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);
33745
33816
  object({
33746
33817
  /**
33747
33818
  * Fraction of the box's own size added on EACH side before cutting.
@@ -33762,10 +33833,21 @@ object({
33762
33833
  */
33763
33834
  square: boolean()
33764
33835
  });
33765
- ({
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 = {
33766
33841
  paddingRatio: .15,
33767
33842
  square: false
33768
- }).paddingRatio;
33843
+ };
33844
+ Object.freeze({
33845
+ x: 0,
33846
+ y: 0,
33847
+ w: 1,
33848
+ h: 1
33849
+ });
33850
+ DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
33769
33851
  /**
33770
33852
  * WHICH delivered frames the decode worker retains a native copy of.
33771
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: 10,
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"
@@ -33504,7 +33543,6 @@ var NC_AUDIO_DEFAULTS = {
33504
33543
  hitPercent: 60,
33505
33544
  samplingSeconds: 10
33506
33545
  };
33507
- new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
33508
33546
  new Set(["devices", "classes"]);
33509
33547
  NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
33510
33548
  /**
@@ -33738,6 +33776,39 @@ TimelapseRuleInputSchema.extend({
33738
33776
  createdAt: number(),
33739
33777
  updatedAt: number()
33740
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);
33741
33812
  object({
33742
33813
  /**
33743
33814
  * Fraction of the box's own size added on EACH side before cutting.
@@ -33758,10 +33829,21 @@ object({
33758
33829
  */
33759
33830
  square: boolean()
33760
33831
  });
33761
- ({
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 = {
33762
33837
  paddingRatio: .15,
33763
33838
  square: false
33764
- }).paddingRatio;
33839
+ };
33840
+ Object.freeze({
33841
+ x: 0,
33842
+ y: 0,
33843
+ w: 1,
33844
+ h: 1
33845
+ });
33846
+ DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
33765
33847
  /**
33766
33848
  * WHICH delivered frames the decode worker retains a native copy of.
33767
33849
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-decoder-ffmpeg",
3
- "version": "1.2.22",
3
+ "version": "1.2.23",
4
4
  "description": "Standalone ffmpeg-subprocess decoder fallback addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",