@camstack/addon-decoder-ffmpeg 1.1.14 → 1.1.15

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 +176 -12
  2. package/dist/index.mjs +176 -12
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ Object.defineProperties(exports, {
4
4
  });
5
5
  let node_crypto = require("node:crypto");
6
6
  let node_child_process = require("node:child_process");
7
- //#region ../types/dist/event-category-CFZs3jI4.mjs
7
+ //#region ../types/dist/event-category-H4AVePnn.mjs
8
8
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
9
9
  EventCategory["SystemBoot"] = "system.boot";
10
10
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -154,6 +154,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
154
154
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
155
155
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
156
156
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
157
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
158
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
159
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
157
160
  EventCategory["DetectionEvent"] = "detection.event";
158
161
  EventCategory["SessionTrackNew"] = "session.track.new";
159
162
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -9830,7 +9833,7 @@ object({
9830
9833
  deviceId: number(),
9831
9834
  timestamp: number()
9832
9835
  });
9833
- DeviceType.Button;
9836
+ DeviceType.Button, DeviceType.Camera;
9834
9837
  /**
9835
9838
  * Enum-state sensor — a string value picked from a finite option set.
9836
9839
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -14330,6 +14333,14 @@ var ConfigEntrySchema = object({
14330
14333
  value: unknown(),
14331
14334
  description: string().optional()
14332
14335
  });
14336
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
14337
+ /** One resolved linked device — the compact projection consumers need. */
14338
+ var LinkedDeviceSchema = object({
14339
+ deviceId: number(),
14340
+ name: string(),
14341
+ location: string().nullable(),
14342
+ features: array(string())
14343
+ });
14333
14344
  var SavedDeviceRowSchema = object({
14334
14345
  /** Numeric id reserved at allocateDeviceId time. */
14335
14346
  id: number(),
@@ -14551,7 +14562,10 @@ method(object({
14551
14562
  }), _void(), {
14552
14563
  kind: "mutation",
14553
14564
  auth: "admin"
14554
- }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14565
+ }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
14566
+ mode: DeviceLinkModeSchema,
14567
+ devices: array(LinkedDeviceSchema)
14568
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14555
14569
  deviceId: number(),
14556
14570
  values: record(string(), unknown())
14557
14571
  }), object({ success: literal(true) }), {
@@ -15820,6 +15834,61 @@ var EventKindSchema = _enum([
15820
15834
  "object",
15821
15835
  "audio"
15822
15836
  ]);
15837
+ /**
15838
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
15839
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
15840
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
15841
+ */
15842
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
15843
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
15844
+ var EventKindIconSchema = _enum([
15845
+ "motion",
15846
+ "audio",
15847
+ "person",
15848
+ "vehicle",
15849
+ "animal",
15850
+ "door",
15851
+ "pir",
15852
+ "smoke",
15853
+ "water",
15854
+ "button",
15855
+ "generic"
15856
+ ]);
15857
+ var EventKindCategorySchema = _enum([
15858
+ "motion",
15859
+ "audio",
15860
+ "detection",
15861
+ "sensor",
15862
+ "custom"
15863
+ ]);
15864
+ var EventKindDescriptorSchema = object({
15865
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
15866
+ kind: string(),
15867
+ label: string(),
15868
+ /** Hex color for timeline/legend rendering. */
15869
+ color: string(),
15870
+ icon: EventKindIconSchema,
15871
+ category: EventKindCategorySchema,
15872
+ /** Which cap + device contributes this kind. For built-ins the camera
15873
+ * itself; for sensor kinds the LINKED source device. */
15874
+ source: object({
15875
+ capName: string(),
15876
+ deviceId: number()
15877
+ })
15878
+ });
15879
+ var SensorEventSchema = object({
15880
+ id: string(),
15881
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
15882
+ * yields N rows, one per camera). */
15883
+ deviceId: number(),
15884
+ /** The linked sensor device whose state changed. */
15885
+ sourceDeviceId: number(),
15886
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
15887
+ kind: string(),
15888
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
15889
+ value: record(string(), unknown()).nullable(),
15890
+ timestamp: number()
15891
+ });
15823
15892
  var TrackPositionSchema = object({
15824
15893
  x: number(),
15825
15894
  y: number(),
@@ -15833,6 +15902,30 @@ var TrackSnapshotSchema = object({
15833
15902
  mediaKey: string()
15834
15903
  });
15835
15904
  /**
15905
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
15906
+ * divided by the track's detection-frame dims), computed at persist time.
15907
+ * Absent when the frame dims were unknown when the track was persisted
15908
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
15909
+ */
15910
+ var TrackEnvelopeSchema = object({
15911
+ minX: number(),
15912
+ minY: number(),
15913
+ maxX: number(),
15914
+ maxY: number()
15915
+ });
15916
+ /**
15917
+ * Row projection for track list queries. `full` (default) returns the
15918
+ * complete Track including the frame-rate `positions[]` history and the
15919
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
15920
+ * keeps every scalar the list surfaces actually render (ids, class(es),
15921
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
15922
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
15923
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
15924
+ * `getTrack`. Mirrors the event-store `projection` convention
15925
+ * (`getObjectEvents` et al.).
15926
+ */
15927
+ var TrackProjectionSchema = _enum(["full", "slim"]);
15928
+ /**
15836
15929
  * One audio-classification label heard on the track's camera while the
15837
15930
  * track was alive, aggregated per label. An "episode" is one persisted
15838
15931
  * audio event (the confident-classification path: score ≥ the device's
@@ -15883,7 +15976,11 @@ var TrackSchema = object({
15883
15976
  /** Audio-classification labels heard on the camera during the track's
15884
15977
  * life (score ≥ device `classificationMinScore`), aggregated per label.
15885
15978
  * Absent on legacy rows / tracks with no confident audio. */
15886
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
15979
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
15980
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
15981
+ * Populated from the persisted envelope columns on historical reads;
15982
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
15983
+ envelope: TrackEnvelopeSchema.optional()
15887
15984
  });
15888
15985
  var BaseEventFields = {
15889
15986
  id: string(),
@@ -15993,11 +16090,13 @@ var MediaFileSchema = object({
15993
16090
  sizeBytes: number(),
15994
16091
  timestamp: number()
15995
16092
  });
16093
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
16094
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
15996
16095
  var DeviceEventQueryInput = object({
15997
16096
  deviceId: number(),
15998
16097
  since: number().optional(),
15999
16098
  until: number().optional(),
16000
- limit: number().int().min(1).max(5e3).default(1e3),
16099
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
16001
16100
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
16002
16101
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
16003
16102
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -16005,6 +16104,27 @@ var DeviceEventQueryInput = object({
16005
16104
  projection: _enum(["full", "slim"]).optional()
16006
16105
  });
16007
16106
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16107
+ var RecentTracksQueryInput = object({
16108
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16109
+ deviceIds: array(number()),
16110
+ /** Window lower bound on `lastSeen` (inclusive). */
16111
+ since: number().optional(),
16112
+ /** Window upper bound on `lastSeen` (inclusive). */
16113
+ until: number().optional(),
16114
+ /** Page size. Default 200, max 1000. */
16115
+ limit: number().int().min(1).max(1e3).default(200),
16116
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16117
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16118
+ cursor: string().optional(),
16119
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16120
+ projection: TrackProjectionSchema.optional()
16121
+ });
16122
+ var RecentTracksPageSchema = object({
16123
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16124
+ tracks: array(TrackSchema).readonly(),
16125
+ /** Cursor for the next page, or null when this page is the last. */
16126
+ nextCursor: string().nullable()
16127
+ });
16008
16128
  var KeyEventQueryInput = object({
16009
16129
  deviceId: number(),
16010
16130
  /** Window lower bound (track firstSeen ≥ since). */
@@ -16087,11 +16207,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
16087
16207
  deviceId: number(),
16088
16208
  since: number().optional(),
16089
16209
  until: number().optional(),
16090
- limit: number().optional()
16091
- }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
16092
- kind: "mutation",
16093
- auth: "admin"
16094
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16210
+ limit: number().optional(),
16211
+ /** Spatial filter only tracks whose trajectory intersects the zone
16212
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16213
+ * envelope columns, then precisely tested per position. Tracks with
16214
+ * an unknown envelope (no frame dims at persist time) always match. */
16215
+ zone: TrackZoneFilterSchema.optional(),
16216
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16217
+ * compatible — omitting the field keeps today's exact behaviour). */
16218
+ projection: TrackProjectionSchema.optional()
16219
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
16220
+ kind: "mutation",
16221
+ auth: "admin"
16222
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
16223
+ deviceId: number(),
16224
+ since: number().optional(),
16225
+ until: number().optional(),
16226
+ kinds: array(string()).optional(),
16227
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16228
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16095
16229
  deviceId: number(),
16096
16230
  since: number(),
16097
16231
  until: number(),
@@ -19292,7 +19426,12 @@ var RecordingStorageUsageSchema = object({
19292
19426
  /**
19293
19427
  * Result of locating footage at a wall-clock instant for one device/profile.
19294
19428
  * `segment` carries the covering segment's window; `gap` reports the forward
19295
- * nearest covered edge (`null` past the end of footage / when none exists).
19429
+ * nearest covered edge (`null` past the end of footage / when none exists)
19430
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
19431
+ * footage behind the epoch; `null` when none — optional so older providers
19432
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
19433
+ * small inter-segment cracks (durMs under-covers the span to the next
19434
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
19296
19435
  */
19297
19436
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19298
19437
  kind: literal("segment"),
@@ -19301,7 +19440,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19301
19440
  bytes: number()
19302
19441
  }), object({
19303
19442
  kind: literal("gap"),
19304
- nearestEdgeMs: number().nullable()
19443
+ nearestEdgeMs: number().nullable(),
19444
+ prevEndMs: number().nullable().optional()
19305
19445
  })]);
19306
19446
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
19307
19447
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -20870,6 +21010,12 @@ Object.freeze({
20870
21010
  addonId: null,
20871
21011
  access: "view"
20872
21012
  },
21013
+ "deviceManager.getLinkedDevices": {
21014
+ capName: "device-manager",
21015
+ capScope: "system",
21016
+ addonId: null,
21017
+ access: "view"
21018
+ },
20873
21019
  "deviceManager.getRoleDisplayDefaults": {
20874
21020
  capName: "device-manager",
20875
21021
  capScope: "system",
@@ -22424,6 +22570,12 @@ Object.freeze({
22424
22570
  addonId: null,
22425
22571
  access: "view"
22426
22572
  },
22573
+ "pipelineAnalytics.getSensorEvents": {
22574
+ capName: "pipeline-analytics",
22575
+ capScope: "device",
22576
+ addonId: null,
22577
+ access: "view"
22578
+ },
22427
22579
  "pipelineAnalytics.getTrack": {
22428
22580
  capName: "pipeline-analytics",
22429
22581
  capScope: "device",
@@ -22436,6 +22588,18 @@ Object.freeze({
22436
22588
  addonId: null,
22437
22589
  access: "view"
22438
22590
  },
22591
+ "pipelineAnalytics.listEventKinds": {
22592
+ capName: "pipeline-analytics",
22593
+ capScope: "device",
22594
+ addonId: null,
22595
+ access: "view"
22596
+ },
22597
+ "pipelineAnalytics.listRecentTracks": {
22598
+ capName: "pipeline-analytics",
22599
+ capScope: "device",
22600
+ addonId: null,
22601
+ access: "view"
22602
+ },
22439
22603
  "pipelineAnalytics.listTracks": {
22440
22604
  capName: "pipeline-analytics",
22441
22605
  capScope: "device",
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { spawn } from "node:child_process";
3
- //#region ../types/dist/event-category-CFZs3jI4.mjs
3
+ //#region ../types/dist/event-category-H4AVePnn.mjs
4
4
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
5
5
  EventCategory["SystemBoot"] = "system.boot";
6
6
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -150,6 +150,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
150
150
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
151
151
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
152
152
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
153
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
154
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
155
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
153
156
  EventCategory["DetectionEvent"] = "detection.event";
154
157
  EventCategory["SessionTrackNew"] = "session.track.new";
155
158
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -9826,7 +9829,7 @@ object({
9826
9829
  deviceId: number(),
9827
9830
  timestamp: number()
9828
9831
  });
9829
- DeviceType.Button;
9832
+ DeviceType.Button, DeviceType.Camera;
9830
9833
  /**
9831
9834
  * Enum-state sensor — a string value picked from a finite option set.
9832
9835
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -14326,6 +14329,14 @@ var ConfigEntrySchema = object({
14326
14329
  value: unknown(),
14327
14330
  description: string().optional()
14328
14331
  });
14332
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
14333
+ /** One resolved linked device — the compact projection consumers need. */
14334
+ var LinkedDeviceSchema = object({
14335
+ deviceId: number(),
14336
+ name: string(),
14337
+ location: string().nullable(),
14338
+ features: array(string())
14339
+ });
14329
14340
  var SavedDeviceRowSchema = object({
14330
14341
  /** Numeric id reserved at allocateDeviceId time. */
14331
14342
  id: number(),
@@ -14547,7 +14558,10 @@ method(object({
14547
14558
  }), _void(), {
14548
14559
  kind: "mutation",
14549
14560
  auth: "admin"
14550
- }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14561
+ }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
14562
+ mode: DeviceLinkModeSchema,
14563
+ devices: array(LinkedDeviceSchema)
14564
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14551
14565
  deviceId: number(),
14552
14566
  values: record(string(), unknown())
14553
14567
  }), object({ success: literal(true) }), {
@@ -15816,6 +15830,61 @@ var EventKindSchema = _enum([
15816
15830
  "object",
15817
15831
  "audio"
15818
15832
  ]);
15833
+ /**
15834
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
15835
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
15836
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
15837
+ */
15838
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
15839
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
15840
+ var EventKindIconSchema = _enum([
15841
+ "motion",
15842
+ "audio",
15843
+ "person",
15844
+ "vehicle",
15845
+ "animal",
15846
+ "door",
15847
+ "pir",
15848
+ "smoke",
15849
+ "water",
15850
+ "button",
15851
+ "generic"
15852
+ ]);
15853
+ var EventKindCategorySchema = _enum([
15854
+ "motion",
15855
+ "audio",
15856
+ "detection",
15857
+ "sensor",
15858
+ "custom"
15859
+ ]);
15860
+ var EventKindDescriptorSchema = object({
15861
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
15862
+ kind: string(),
15863
+ label: string(),
15864
+ /** Hex color for timeline/legend rendering. */
15865
+ color: string(),
15866
+ icon: EventKindIconSchema,
15867
+ category: EventKindCategorySchema,
15868
+ /** Which cap + device contributes this kind. For built-ins the camera
15869
+ * itself; for sensor kinds the LINKED source device. */
15870
+ source: object({
15871
+ capName: string(),
15872
+ deviceId: number()
15873
+ })
15874
+ });
15875
+ var SensorEventSchema = object({
15876
+ id: string(),
15877
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
15878
+ * yields N rows, one per camera). */
15879
+ deviceId: number(),
15880
+ /** The linked sensor device whose state changed. */
15881
+ sourceDeviceId: number(),
15882
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
15883
+ kind: string(),
15884
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
15885
+ value: record(string(), unknown()).nullable(),
15886
+ timestamp: number()
15887
+ });
15819
15888
  var TrackPositionSchema = object({
15820
15889
  x: number(),
15821
15890
  y: number(),
@@ -15829,6 +15898,30 @@ var TrackSnapshotSchema = object({
15829
15898
  mediaKey: string()
15830
15899
  });
15831
15900
  /**
15901
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
15902
+ * divided by the track's detection-frame dims), computed at persist time.
15903
+ * Absent when the frame dims were unknown when the track was persisted
15904
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
15905
+ */
15906
+ var TrackEnvelopeSchema = object({
15907
+ minX: number(),
15908
+ minY: number(),
15909
+ maxX: number(),
15910
+ maxY: number()
15911
+ });
15912
+ /**
15913
+ * Row projection for track list queries. `full` (default) returns the
15914
+ * complete Track including the frame-rate `positions[]` history and the
15915
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
15916
+ * keeps every scalar the list surfaces actually render (ids, class(es),
15917
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
15918
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
15919
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
15920
+ * `getTrack`. Mirrors the event-store `projection` convention
15921
+ * (`getObjectEvents` et al.).
15922
+ */
15923
+ var TrackProjectionSchema = _enum(["full", "slim"]);
15924
+ /**
15832
15925
  * One audio-classification label heard on the track's camera while the
15833
15926
  * track was alive, aggregated per label. An "episode" is one persisted
15834
15927
  * audio event (the confident-classification path: score ≥ the device's
@@ -15879,7 +15972,11 @@ var TrackSchema = object({
15879
15972
  /** Audio-classification labels heard on the camera during the track's
15880
15973
  * life (score ≥ device `classificationMinScore`), aggregated per label.
15881
15974
  * Absent on legacy rows / tracks with no confident audio. */
15882
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
15975
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
15976
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
15977
+ * Populated from the persisted envelope columns on historical reads;
15978
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
15979
+ envelope: TrackEnvelopeSchema.optional()
15883
15980
  });
15884
15981
  var BaseEventFields = {
15885
15982
  id: string(),
@@ -15989,11 +16086,13 @@ var MediaFileSchema = object({
15989
16086
  sizeBytes: number(),
15990
16087
  timestamp: number()
15991
16088
  });
16089
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
16090
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
15992
16091
  var DeviceEventQueryInput = object({
15993
16092
  deviceId: number(),
15994
16093
  since: number().optional(),
15995
16094
  until: number().optional(),
15996
- limit: number().int().min(1).max(5e3).default(1e3),
16095
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
15997
16096
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
15998
16097
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
15999
16098
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -16001,6 +16100,27 @@ var DeviceEventQueryInput = object({
16001
16100
  projection: _enum(["full", "slim"]).optional()
16002
16101
  });
16003
16102
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16103
+ var RecentTracksQueryInput = object({
16104
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16105
+ deviceIds: array(number()),
16106
+ /** Window lower bound on `lastSeen` (inclusive). */
16107
+ since: number().optional(),
16108
+ /** Window upper bound on `lastSeen` (inclusive). */
16109
+ until: number().optional(),
16110
+ /** Page size. Default 200, max 1000. */
16111
+ limit: number().int().min(1).max(1e3).default(200),
16112
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16113
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16114
+ cursor: string().optional(),
16115
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16116
+ projection: TrackProjectionSchema.optional()
16117
+ });
16118
+ var RecentTracksPageSchema = object({
16119
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16120
+ tracks: array(TrackSchema).readonly(),
16121
+ /** Cursor for the next page, or null when this page is the last. */
16122
+ nextCursor: string().nullable()
16123
+ });
16004
16124
  var KeyEventQueryInput = object({
16005
16125
  deviceId: number(),
16006
16126
  /** Window lower bound (track firstSeen ≥ since). */
@@ -16083,11 +16203,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
16083
16203
  deviceId: number(),
16084
16204
  since: number().optional(),
16085
16205
  until: number().optional(),
16086
- limit: number().optional()
16087
- }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
16088
- kind: "mutation",
16089
- auth: "admin"
16090
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16206
+ limit: number().optional(),
16207
+ /** Spatial filter only tracks whose trajectory intersects the zone
16208
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16209
+ * envelope columns, then precisely tested per position. Tracks with
16210
+ * an unknown envelope (no frame dims at persist time) always match. */
16211
+ zone: TrackZoneFilterSchema.optional(),
16212
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16213
+ * compatible — omitting the field keeps today's exact behaviour). */
16214
+ projection: TrackProjectionSchema.optional()
16215
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
16216
+ kind: "mutation",
16217
+ auth: "admin"
16218
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
16219
+ deviceId: number(),
16220
+ since: number().optional(),
16221
+ until: number().optional(),
16222
+ kinds: array(string()).optional(),
16223
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16224
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16091
16225
  deviceId: number(),
16092
16226
  since: number(),
16093
16227
  until: number(),
@@ -19288,7 +19422,12 @@ var RecordingStorageUsageSchema = object({
19288
19422
  /**
19289
19423
  * Result of locating footage at a wall-clock instant for one device/profile.
19290
19424
  * `segment` carries the covering segment's window; `gap` reports the forward
19291
- * nearest covered edge (`null` past the end of footage / when none exists).
19425
+ * nearest covered edge (`null` past the end of footage / when none exists)
19426
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
19427
+ * footage behind the epoch; `null` when none — optional so older providers
19428
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
19429
+ * small inter-segment cracks (durMs under-covers the span to the next
19430
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
19292
19431
  */
19293
19432
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19294
19433
  kind: literal("segment"),
@@ -19297,7 +19436,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19297
19436
  bytes: number()
19298
19437
  }), object({
19299
19438
  kind: literal("gap"),
19300
- nearestEdgeMs: number().nullable()
19439
+ nearestEdgeMs: number().nullable(),
19440
+ prevEndMs: number().nullable().optional()
19301
19441
  })]);
19302
19442
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
19303
19443
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -20866,6 +21006,12 @@ Object.freeze({
20866
21006
  addonId: null,
20867
21007
  access: "view"
20868
21008
  },
21009
+ "deviceManager.getLinkedDevices": {
21010
+ capName: "device-manager",
21011
+ capScope: "system",
21012
+ addonId: null,
21013
+ access: "view"
21014
+ },
20869
21015
  "deviceManager.getRoleDisplayDefaults": {
20870
21016
  capName: "device-manager",
20871
21017
  capScope: "system",
@@ -22420,6 +22566,12 @@ Object.freeze({
22420
22566
  addonId: null,
22421
22567
  access: "view"
22422
22568
  },
22569
+ "pipelineAnalytics.getSensorEvents": {
22570
+ capName: "pipeline-analytics",
22571
+ capScope: "device",
22572
+ addonId: null,
22573
+ access: "view"
22574
+ },
22423
22575
  "pipelineAnalytics.getTrack": {
22424
22576
  capName: "pipeline-analytics",
22425
22577
  capScope: "device",
@@ -22432,6 +22584,18 @@ Object.freeze({
22432
22584
  addonId: null,
22433
22585
  access: "view"
22434
22586
  },
22587
+ "pipelineAnalytics.listEventKinds": {
22588
+ capName: "pipeline-analytics",
22589
+ capScope: "device",
22590
+ addonId: null,
22591
+ access: "view"
22592
+ },
22593
+ "pipelineAnalytics.listRecentTracks": {
22594
+ capName: "pipeline-analytics",
22595
+ capScope: "device",
22596
+ addonId: null,
22597
+ access: "view"
22598
+ },
22435
22599
  "pipelineAnalytics.listTracks": {
22436
22600
  capName: "pipeline-analytics",
22437
22601
  capScope: "device",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-decoder-ffmpeg",
3
- "version": "1.1.14",
3
+ "version": "1.1.15",
4
4
  "description": "Standalone ffmpeg-subprocess decoder fallback addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",