@camstack/addon-export-hap 1.1.24 → 1.1.26
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/export-hap.addon.js +218 -5
- package/dist/export-hap.addon.mjs +218 -5
- package/package.json +1 -1
package/dist/export-hap.addon.js
CHANGED
|
@@ -35,7 +35,7 @@ let node_fs_promises = require("node:fs/promises");
|
|
|
35
35
|
node_fs_promises = __toESM(node_fs_promises);
|
|
36
36
|
let node_dgram = require("node:dgram");
|
|
37
37
|
let node_os = require("node:os");
|
|
38
|
-
//#region ../types/dist/event-category-
|
|
38
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
39
39
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
40
40
|
EventCategory["SystemBoot"] = "system.boot";
|
|
41
41
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -188,6 +188,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
188
188
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
189
189
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
190
190
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
191
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
192
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
193
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
194
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
195
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
191
196
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
192
197
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
193
198
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -477,6 +482,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
477
482
|
*/
|
|
478
483
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
479
484
|
/**
|
|
485
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
486
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
487
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
488
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
489
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
490
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
491
|
+
* this bus topic drives notifier rules + live UI. See
|
|
492
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
493
|
+
*/
|
|
494
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
495
|
+
/**
|
|
496
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
497
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
498
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
499
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
500
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
501
|
+
*/
|
|
502
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
503
|
+
/**
|
|
480
504
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
481
505
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
482
506
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -5215,6 +5239,25 @@ function _instanceof(cls, params = {}) {
|
|
|
5215
5239
|
};
|
|
5216
5240
|
return inst;
|
|
5217
5241
|
}
|
|
5242
|
+
//#endregion
|
|
5243
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
5244
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
5245
|
+
var ZodIssueCode = {
|
|
5246
|
+
invalid_type: "invalid_type",
|
|
5247
|
+
too_big: "too_big",
|
|
5248
|
+
too_small: "too_small",
|
|
5249
|
+
invalid_format: "invalid_format",
|
|
5250
|
+
not_multiple_of: "not_multiple_of",
|
|
5251
|
+
unrecognized_keys: "unrecognized_keys",
|
|
5252
|
+
invalid_union: "invalid_union",
|
|
5253
|
+
invalid_key: "invalid_key",
|
|
5254
|
+
invalid_element: "invalid_element",
|
|
5255
|
+
invalid_value: "invalid_value",
|
|
5256
|
+
custom: "custom"
|
|
5257
|
+
};
|
|
5258
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
5259
|
+
var ZodFirstPartyTypeKind;
|
|
5260
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5218
5261
|
Object.fromEntries([
|
|
5219
5262
|
{
|
|
5220
5263
|
id: "overview",
|
|
@@ -7257,6 +7300,24 @@ var RecordingRetentionSchema = object({
|
|
|
7257
7300
|
maxSizeGb: number().min(0).optional()
|
|
7258
7301
|
});
|
|
7259
7302
|
/**
|
|
7303
|
+
* Scrub-thumbnail fidelity preset — the single per-camera selector bundling the
|
|
7304
|
+
* sprite tile RESOLUTION + JPEG QUALITY the recorder packs timeline-scrub
|
|
7305
|
+
* previews at. Five graduated steps; absent on a config = `standard` (the
|
|
7306
|
+
* shipped default, matching `sheet-geometry`/`sheet-composer`).
|
|
7307
|
+
*
|
|
7308
|
+
* Existing sheets are IMMUTABLE — a changed preset applies to NEW windows only.
|
|
7309
|
+
* Each window's index sidecar carries its own tile dims, so a camera whose
|
|
7310
|
+
* preset changed over time renders every historical window at the dims it was
|
|
7311
|
+
* written with.
|
|
7312
|
+
*/
|
|
7313
|
+
var ScrubThumbnailPresetSchema = _enum([
|
|
7314
|
+
"minimal",
|
|
7315
|
+
"low",
|
|
7316
|
+
"standard",
|
|
7317
|
+
"high",
|
|
7318
|
+
"max"
|
|
7319
|
+
]);
|
|
7320
|
+
/**
|
|
7260
7321
|
* The full per-camera recording intent — the wire shape of a RecordingTarget.
|
|
7261
7322
|
*
|
|
7262
7323
|
* `mode` is the authoritative storage choice; `schedule`/`triggers`/`pre`/`post`
|
|
@@ -7293,7 +7354,14 @@ var RecordingConfigSchema = object({
|
|
|
7293
7354
|
* derived into bands once via `migrateConfigToBands`.
|
|
7294
7355
|
*/
|
|
7295
7356
|
bands: array(RecordingBandSchema).optional(),
|
|
7296
|
-
retention: RecordingRetentionSchema.optional()
|
|
7357
|
+
retention: RecordingRetentionSchema.optional(),
|
|
7358
|
+
/**
|
|
7359
|
+
* Per-camera scrub-thumbnail fidelity preset (resolution + JPEG quality for
|
|
7360
|
+
* timeline-scrub sprite previews). Absent = `standard`. Applies to NEW
|
|
7361
|
+
* windows only — existing sheets are immutable, and each window's index
|
|
7362
|
+
* carries its own tile dims so mixed-preset history renders correctly.
|
|
7363
|
+
*/
|
|
7364
|
+
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7297
7365
|
});
|
|
7298
7366
|
/**
|
|
7299
7367
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
@@ -12599,7 +12667,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
12599
12667
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
12600
12668
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
12601
12669
|
*/
|
|
12602
|
-
var ZoneRuleStageEnum = _enum([
|
|
12670
|
+
var ZoneRuleStageEnum = _enum([
|
|
12671
|
+
"motion",
|
|
12672
|
+
"detection",
|
|
12673
|
+
"package"
|
|
12674
|
+
]);
|
|
12603
12675
|
DeviceType.Camera, method(object({
|
|
12604
12676
|
deviceId: number(),
|
|
12605
12677
|
stage: ZoneRuleStageEnum
|
|
@@ -12612,7 +12684,8 @@ DeviceType.Camera, method(object({
|
|
|
12612
12684
|
auth: "admin"
|
|
12613
12685
|
}), object({
|
|
12614
12686
|
motion: array(ZoneRuleSchema).readonly(),
|
|
12615
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
12687
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
12688
|
+
package: array(ZoneRuleSchema).readonly()
|
|
12616
12689
|
});
|
|
12617
12690
|
var ProviderStatusSchema = object({
|
|
12618
12691
|
connected: boolean(),
|
|
@@ -15820,6 +15893,7 @@ var EventKindIconSchema = _enum([
|
|
|
15820
15893
|
"smoke",
|
|
15821
15894
|
"water",
|
|
15822
15895
|
"button",
|
|
15896
|
+
"package",
|
|
15823
15897
|
"generic"
|
|
15824
15898
|
]);
|
|
15825
15899
|
var EventKindCategorySchema = _enum([
|
|
@@ -15827,7 +15901,8 @@ var EventKindCategorySchema = _enum([
|
|
|
15827
15901
|
"audio",
|
|
15828
15902
|
"detection",
|
|
15829
15903
|
"sensor",
|
|
15830
|
-
"custom"
|
|
15904
|
+
"custom",
|
|
15905
|
+
"package"
|
|
15831
15906
|
]);
|
|
15832
15907
|
var EventKindDescriptorSchema = object({
|
|
15833
15908
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19473,6 +19548,108 @@ method(object({
|
|
|
19473
19548
|
auth: "admin"
|
|
19474
19549
|
});
|
|
19475
19550
|
/**
|
|
19551
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
19552
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
19553
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
19554
|
+
* delete-after-download.
|
|
19555
|
+
*
|
|
19556
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
19557
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
19558
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
19559
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
19560
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
19561
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
19562
|
+
* SQLite); history rows survive file deletion for audit.
|
|
19563
|
+
*/
|
|
19564
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
19565
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
19566
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
19567
|
+
var ExportTimelapseSchema = object({
|
|
19568
|
+
everyMs: number().int().positive(),
|
|
19569
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
19570
|
+
});
|
|
19571
|
+
/**
|
|
19572
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
19573
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
19574
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
19575
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
19576
|
+
*/
|
|
19577
|
+
var ExportOptionsSchema = object({
|
|
19578
|
+
speed: ExportSpeedSchema.optional(),
|
|
19579
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
19580
|
+
includeAudio: boolean(),
|
|
19581
|
+
maxLifeMs: number().int().positive(),
|
|
19582
|
+
deleteAfterDownload: boolean(),
|
|
19583
|
+
title: string().max(200).optional()
|
|
19584
|
+
}).superRefine((v, ctx) => {
|
|
19585
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
19586
|
+
code: ZodIssueCode.custom,
|
|
19587
|
+
message: "speed and timelapse are mutually exclusive",
|
|
19588
|
+
path: ["timelapse"]
|
|
19589
|
+
});
|
|
19590
|
+
});
|
|
19591
|
+
var ExportStateSchema = _enum([
|
|
19592
|
+
"queued",
|
|
19593
|
+
"rendering",
|
|
19594
|
+
"ready",
|
|
19595
|
+
"failed",
|
|
19596
|
+
"expired",
|
|
19597
|
+
"deleted"
|
|
19598
|
+
]);
|
|
19599
|
+
/** One export job / history row. */
|
|
19600
|
+
var ExportRecordSchema = object({
|
|
19601
|
+
id: string(),
|
|
19602
|
+
deviceId: number(),
|
|
19603
|
+
profile: string(),
|
|
19604
|
+
fromMs: number(),
|
|
19605
|
+
toMs: number(),
|
|
19606
|
+
options: ExportOptionsSchema,
|
|
19607
|
+
state: ExportStateSchema,
|
|
19608
|
+
/** 0–100 while rendering; null otherwise. */
|
|
19609
|
+
progressPct: number().nullable(),
|
|
19610
|
+
/** File size once ready; null before. */
|
|
19611
|
+
fileBytes: number().nullable(),
|
|
19612
|
+
expiresAt: number(),
|
|
19613
|
+
deleteAfterDownload: boolean(),
|
|
19614
|
+
/** Epoch of the first complete download; null until then. */
|
|
19615
|
+
downloadedAt: number().nullable(),
|
|
19616
|
+
createdAt: number(),
|
|
19617
|
+
/** User id/name that requested the export. */
|
|
19618
|
+
createdBy: string(),
|
|
19619
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
19620
|
+
error: string().nullable()
|
|
19621
|
+
});
|
|
19622
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
19623
|
+
var ExportDownloadSchema = object({
|
|
19624
|
+
url: string(),
|
|
19625
|
+
endpoints: array(string())
|
|
19626
|
+
});
|
|
19627
|
+
method(object({
|
|
19628
|
+
deviceId: number(),
|
|
19629
|
+
profile: string(),
|
|
19630
|
+
fromMs: number(),
|
|
19631
|
+
toMs: number(),
|
|
19632
|
+
options: ExportOptionsSchema
|
|
19633
|
+
}), ExportRecordSchema, {
|
|
19634
|
+
kind: "mutation",
|
|
19635
|
+
auth: "protected"
|
|
19636
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
19637
|
+
kind: "query",
|
|
19638
|
+
auth: "protected"
|
|
19639
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
19640
|
+
kind: "query",
|
|
19641
|
+
auth: "protected"
|
|
19642
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
19643
|
+
kind: "mutation",
|
|
19644
|
+
auth: "protected"
|
|
19645
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
19646
|
+
kind: "mutation",
|
|
19647
|
+
auth: "protected"
|
|
19648
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
19649
|
+
kind: "query",
|
|
19650
|
+
auth: "protected"
|
|
19651
|
+
});
|
|
19652
|
+
/**
|
|
19476
19653
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
19477
19654
|
* payload the (legacy) push `streamBroker.publishCameraStream` carried, minus
|
|
19478
19655
|
* `deviceId`.
|
|
@@ -23396,6 +23573,42 @@ Object.freeze({
|
|
|
23396
23573
|
addonId: null,
|
|
23397
23574
|
access: "create"
|
|
23398
23575
|
},
|
|
23576
|
+
"recordingExport.cancelExport": {
|
|
23577
|
+
capName: "recordingExport",
|
|
23578
|
+
capScope: "system",
|
|
23579
|
+
addonId: null,
|
|
23580
|
+
access: "create"
|
|
23581
|
+
},
|
|
23582
|
+
"recordingExport.createExport": {
|
|
23583
|
+
capName: "recordingExport",
|
|
23584
|
+
capScope: "system",
|
|
23585
|
+
addonId: null,
|
|
23586
|
+
access: "create"
|
|
23587
|
+
},
|
|
23588
|
+
"recordingExport.deleteExport": {
|
|
23589
|
+
capName: "recordingExport",
|
|
23590
|
+
capScope: "system",
|
|
23591
|
+
addonId: null,
|
|
23592
|
+
access: "delete"
|
|
23593
|
+
},
|
|
23594
|
+
"recordingExport.getDownloadUrl": {
|
|
23595
|
+
capName: "recordingExport",
|
|
23596
|
+
capScope: "system",
|
|
23597
|
+
addonId: null,
|
|
23598
|
+
access: "view"
|
|
23599
|
+
},
|
|
23600
|
+
"recordingExport.getExport": {
|
|
23601
|
+
capName: "recordingExport",
|
|
23602
|
+
capScope: "system",
|
|
23603
|
+
addonId: null,
|
|
23604
|
+
access: "view"
|
|
23605
|
+
},
|
|
23606
|
+
"recordingExport.listExports": {
|
|
23607
|
+
capName: "recordingExport",
|
|
23608
|
+
capScope: "system",
|
|
23609
|
+
addonId: null,
|
|
23610
|
+
access: "view"
|
|
23611
|
+
},
|
|
23399
23612
|
"sceneMonitor.captureReference": {
|
|
23400
23613
|
capName: "scene-monitor",
|
|
23401
23614
|
capScope: "device",
|
|
@@ -10,7 +10,7 @@ import { networkInterfaces } from "node:os";
|
|
|
10
10
|
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
11
11
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
12
12
|
//#endregion
|
|
13
|
-
//#region ../types/dist/event-category-
|
|
13
|
+
//#region ../types/dist/event-category-D4HJq7Mw.mjs
|
|
14
14
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
15
15
|
EventCategory["SystemBoot"] = "system.boot";
|
|
16
16
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -163,6 +163,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
163
163
|
/** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
|
|
164
164
|
* thumb is a scrub gap the recorder's keyframe backfill covers. */
|
|
165
165
|
EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
|
|
166
|
+
/** Export render progress (0–100). Telemetry (D8): a lost tick is a stale
|
|
167
|
+
* progress bar the client reconciles via `recordingExport.getExport`. */
|
|
168
|
+
EventCategory["RecordingExportProgress"] = "recording.export.progress";
|
|
169
|
+
EventCategory["RecordingExportCompleted"] = "recording.export.completed";
|
|
170
|
+
EventCategory["RecordingExportFailed"] = "recording.export.failed";
|
|
166
171
|
EventCategory["DetectionEvent"] = "detection.event";
|
|
167
172
|
EventCategory["SessionTrackNew"] = "session.track.new";
|
|
168
173
|
EventCategory["SessionTrackExpired"] = "session.track.expired";
|
|
@@ -452,6 +457,25 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
452
457
|
*/
|
|
453
458
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
454
459
|
/**
|
|
460
|
+
* Fired by `addon-post-analysis` when a package-drop is confirmed inside
|
|
461
|
+
* a package zone — a newly-appeared stationary object of a package class
|
|
462
|
+
* that cleared the class / zone / dwell / size gates. Payload:
|
|
463
|
+
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
464
|
+
* entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
|
|
465
|
+
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
466
|
+
* this bus topic drives notifier rules + live UI. See
|
|
467
|
+
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
468
|
+
*/
|
|
469
|
+
EventCategory["PipelineAnalyticsPackageDelivered"] = "pipeline-analytics.package-delivered";
|
|
470
|
+
/**
|
|
471
|
+
* Fired by `addon-post-analysis` when a previously-delivered package
|
|
472
|
+
* leaves its zone (the stationary entry departed — moved or swept).
|
|
473
|
+
* Payload: `PipelineAnalyticsPackagePickedUpPayload` carrying
|
|
474
|
+
* `{ deviceId, entryId, deliveredEventId, className, timestamp }`.
|
|
475
|
+
* Telemetry (D8). See package-zones-design §5.2.
|
|
476
|
+
*/
|
|
477
|
+
EventCategory["PipelineAnalyticsPackagePickedUp"] = "pipeline-analytics.package-picked-up";
|
|
478
|
+
/**
|
|
455
479
|
* Fired by `addon-post-analysis` whenever a gallery face row changes:
|
|
456
480
|
* `kind:'buffered'` a new detected face was persisted, `'assigned'` /
|
|
457
481
|
* `'unassigned'` its identity link changed, `'deleted'` the row was
|
|
@@ -5190,6 +5214,25 @@ function _instanceof(cls, params = {}) {
|
|
|
5190
5214
|
};
|
|
5191
5215
|
return inst;
|
|
5192
5216
|
}
|
|
5217
|
+
//#endregion
|
|
5218
|
+
//#region ../../node_modules/zod/v4/classic/compat.js
|
|
5219
|
+
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
5220
|
+
var ZodIssueCode = {
|
|
5221
|
+
invalid_type: "invalid_type",
|
|
5222
|
+
too_big: "too_big",
|
|
5223
|
+
too_small: "too_small",
|
|
5224
|
+
invalid_format: "invalid_format",
|
|
5225
|
+
not_multiple_of: "not_multiple_of",
|
|
5226
|
+
unrecognized_keys: "unrecognized_keys",
|
|
5227
|
+
invalid_union: "invalid_union",
|
|
5228
|
+
invalid_key: "invalid_key",
|
|
5229
|
+
invalid_element: "invalid_element",
|
|
5230
|
+
invalid_value: "invalid_value",
|
|
5231
|
+
custom: "custom"
|
|
5232
|
+
};
|
|
5233
|
+
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
5234
|
+
var ZodFirstPartyTypeKind;
|
|
5235
|
+
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5193
5236
|
Object.fromEntries([
|
|
5194
5237
|
{
|
|
5195
5238
|
id: "overview",
|
|
@@ -7232,6 +7275,24 @@ var RecordingRetentionSchema = object({
|
|
|
7232
7275
|
maxSizeGb: number().min(0).optional()
|
|
7233
7276
|
});
|
|
7234
7277
|
/**
|
|
7278
|
+
* Scrub-thumbnail fidelity preset — the single per-camera selector bundling the
|
|
7279
|
+
* sprite tile RESOLUTION + JPEG QUALITY the recorder packs timeline-scrub
|
|
7280
|
+
* previews at. Five graduated steps; absent on a config = `standard` (the
|
|
7281
|
+
* shipped default, matching `sheet-geometry`/`sheet-composer`).
|
|
7282
|
+
*
|
|
7283
|
+
* Existing sheets are IMMUTABLE — a changed preset applies to NEW windows only.
|
|
7284
|
+
* Each window's index sidecar carries its own tile dims, so a camera whose
|
|
7285
|
+
* preset changed over time renders every historical window at the dims it was
|
|
7286
|
+
* written with.
|
|
7287
|
+
*/
|
|
7288
|
+
var ScrubThumbnailPresetSchema = _enum([
|
|
7289
|
+
"minimal",
|
|
7290
|
+
"low",
|
|
7291
|
+
"standard",
|
|
7292
|
+
"high",
|
|
7293
|
+
"max"
|
|
7294
|
+
]);
|
|
7295
|
+
/**
|
|
7235
7296
|
* The full per-camera recording intent — the wire shape of a RecordingTarget.
|
|
7236
7297
|
*
|
|
7237
7298
|
* `mode` is the authoritative storage choice; `schedule`/`triggers`/`pre`/`post`
|
|
@@ -7268,7 +7329,14 @@ var RecordingConfigSchema = object({
|
|
|
7268
7329
|
* derived into bands once via `migrateConfigToBands`.
|
|
7269
7330
|
*/
|
|
7270
7331
|
bands: array(RecordingBandSchema).optional(),
|
|
7271
|
-
retention: RecordingRetentionSchema.optional()
|
|
7332
|
+
retention: RecordingRetentionSchema.optional(),
|
|
7333
|
+
/**
|
|
7334
|
+
* Per-camera scrub-thumbnail fidelity preset (resolution + JPEG quality for
|
|
7335
|
+
* timeline-scrub sprite previews). Absent = `standard`. Applies to NEW
|
|
7336
|
+
* windows only — existing sheets are immutable, and each window's index
|
|
7337
|
+
* carries its own tile dims so mixed-preset history renders correctly.
|
|
7338
|
+
*/
|
|
7339
|
+
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7272
7340
|
});
|
|
7273
7341
|
/**
|
|
7274
7342
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
@@ -12574,7 +12642,11 @@ array(ZoneRuleSchema).readonly();
|
|
|
12574
12642
|
* Extend the enum here when a new gating consumer comes online (audio
|
|
12575
12643
|
* gating, alert filtering, …) — no other surface needs to change.
|
|
12576
12644
|
*/
|
|
12577
|
-
var ZoneRuleStageEnum = _enum([
|
|
12645
|
+
var ZoneRuleStageEnum = _enum([
|
|
12646
|
+
"motion",
|
|
12647
|
+
"detection",
|
|
12648
|
+
"package"
|
|
12649
|
+
]);
|
|
12578
12650
|
DeviceType.Camera, method(object({
|
|
12579
12651
|
deviceId: number(),
|
|
12580
12652
|
stage: ZoneRuleStageEnum
|
|
@@ -12587,7 +12659,8 @@ DeviceType.Camera, method(object({
|
|
|
12587
12659
|
auth: "admin"
|
|
12588
12660
|
}), object({
|
|
12589
12661
|
motion: array(ZoneRuleSchema).readonly(),
|
|
12590
|
-
detection: array(ZoneRuleSchema).readonly()
|
|
12662
|
+
detection: array(ZoneRuleSchema).readonly(),
|
|
12663
|
+
package: array(ZoneRuleSchema).readonly()
|
|
12591
12664
|
});
|
|
12592
12665
|
var ProviderStatusSchema = object({
|
|
12593
12666
|
connected: boolean(),
|
|
@@ -15795,6 +15868,7 @@ var EventKindIconSchema = _enum([
|
|
|
15795
15868
|
"smoke",
|
|
15796
15869
|
"water",
|
|
15797
15870
|
"button",
|
|
15871
|
+
"package",
|
|
15798
15872
|
"generic"
|
|
15799
15873
|
]);
|
|
15800
15874
|
var EventKindCategorySchema = _enum([
|
|
@@ -15802,7 +15876,8 @@ var EventKindCategorySchema = _enum([
|
|
|
15802
15876
|
"audio",
|
|
15803
15877
|
"detection",
|
|
15804
15878
|
"sensor",
|
|
15805
|
-
"custom"
|
|
15879
|
+
"custom",
|
|
15880
|
+
"package"
|
|
15806
15881
|
]);
|
|
15807
15882
|
var EventKindDescriptorSchema = object({
|
|
15808
15883
|
/** Stable kind id (e.g. 'motion', 'person', 'contact'). */
|
|
@@ -19448,6 +19523,108 @@ method(object({
|
|
|
19448
19523
|
auth: "admin"
|
|
19449
19524
|
});
|
|
19450
19525
|
/**
|
|
19526
|
+
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
19527
|
+
* MP4 (regular / accelerated / decelerated / timelapse, ± audio), kept for a
|
|
19528
|
+
* bounded lifetime with a durable history, auto-expiry, and optional
|
|
19529
|
+
* delete-after-download.
|
|
19530
|
+
*
|
|
19531
|
+
* Like `recording` this is a `scope:'system', mode:'singleton'` cap: the
|
|
19532
|
+
* recorder self-gates so exactly ONE node (the designated `recordingNodeId`,
|
|
19533
|
+
* default `hub`) registers it. Device-scoped methods carry `deviceId` in their
|
|
19534
|
+
* input and dispatch to that single provider; the render runs on the node that
|
|
19535
|
+
* owns the footage (no cross-node segment transfer). Download rides the
|
|
19536
|
+
* framework addon data-plane. State persists in a DurableState blob (NOT
|
|
19537
|
+
* SQLite); history rows survive file deletion for audit.
|
|
19538
|
+
*/
|
|
19539
|
+
/** Playback-speed multiplier for the render (1 = realtime). */
|
|
19540
|
+
var ExportSpeedSchema = number().min(.25).max(32);
|
|
19541
|
+
/** Timelapse cadence — sample one source frame per `everyMs`, output at `outputFps`. */
|
|
19542
|
+
var ExportTimelapseSchema = object({
|
|
19543
|
+
everyMs: number().int().positive(),
|
|
19544
|
+
outputFps: number().int().min(1).max(60).optional()
|
|
19545
|
+
});
|
|
19546
|
+
/**
|
|
19547
|
+
* Render options. `speed` and `timelapse` are mutually exclusive. `includeAudio`
|
|
19548
|
+
* is honoured only for a realtime-ish speed (0.5–2×); timelapse is always
|
|
19549
|
+
* silent. `maxLifeMs` bounds how long the finished file is kept;
|
|
19550
|
+
* `deleteAfterDownload` removes it shortly after the first complete download.
|
|
19551
|
+
*/
|
|
19552
|
+
var ExportOptionsSchema = object({
|
|
19553
|
+
speed: ExportSpeedSchema.optional(),
|
|
19554
|
+
timelapse: ExportTimelapseSchema.optional(),
|
|
19555
|
+
includeAudio: boolean(),
|
|
19556
|
+
maxLifeMs: number().int().positive(),
|
|
19557
|
+
deleteAfterDownload: boolean(),
|
|
19558
|
+
title: string().max(200).optional()
|
|
19559
|
+
}).superRefine((v, ctx) => {
|
|
19560
|
+
if (v.speed !== void 0 && v.timelapse !== void 0) ctx.addIssue({
|
|
19561
|
+
code: ZodIssueCode.custom,
|
|
19562
|
+
message: "speed and timelapse are mutually exclusive",
|
|
19563
|
+
path: ["timelapse"]
|
|
19564
|
+
});
|
|
19565
|
+
});
|
|
19566
|
+
var ExportStateSchema = _enum([
|
|
19567
|
+
"queued",
|
|
19568
|
+
"rendering",
|
|
19569
|
+
"ready",
|
|
19570
|
+
"failed",
|
|
19571
|
+
"expired",
|
|
19572
|
+
"deleted"
|
|
19573
|
+
]);
|
|
19574
|
+
/** One export job / history row. */
|
|
19575
|
+
var ExportRecordSchema = object({
|
|
19576
|
+
id: string(),
|
|
19577
|
+
deviceId: number(),
|
|
19578
|
+
profile: string(),
|
|
19579
|
+
fromMs: number(),
|
|
19580
|
+
toMs: number(),
|
|
19581
|
+
options: ExportOptionsSchema,
|
|
19582
|
+
state: ExportStateSchema,
|
|
19583
|
+
/** 0–100 while rendering; null otherwise. */
|
|
19584
|
+
progressPct: number().nullable(),
|
|
19585
|
+
/** File size once ready; null before. */
|
|
19586
|
+
fileBytes: number().nullable(),
|
|
19587
|
+
expiresAt: number(),
|
|
19588
|
+
deleteAfterDownload: boolean(),
|
|
19589
|
+
/** Epoch of the first complete download; null until then. */
|
|
19590
|
+
downloadedAt: number().nullable(),
|
|
19591
|
+
createdAt: number(),
|
|
19592
|
+
/** User id/name that requested the export. */
|
|
19593
|
+
createdBy: string(),
|
|
19594
|
+
/** Failure reason when state is 'failed'; null otherwise. */
|
|
19595
|
+
error: string().nullable()
|
|
19596
|
+
});
|
|
19597
|
+
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
19598
|
+
var ExportDownloadSchema = object({
|
|
19599
|
+
url: string(),
|
|
19600
|
+
endpoints: array(string())
|
|
19601
|
+
});
|
|
19602
|
+
method(object({
|
|
19603
|
+
deviceId: number(),
|
|
19604
|
+
profile: string(),
|
|
19605
|
+
fromMs: number(),
|
|
19606
|
+
toMs: number(),
|
|
19607
|
+
options: ExportOptionsSchema
|
|
19608
|
+
}), ExportRecordSchema, {
|
|
19609
|
+
kind: "mutation",
|
|
19610
|
+
auth: "protected"
|
|
19611
|
+
}), method(object({ deviceId: number().optional() }), array(ExportRecordSchema), {
|
|
19612
|
+
kind: "query",
|
|
19613
|
+
auth: "protected"
|
|
19614
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
19615
|
+
kind: "query",
|
|
19616
|
+
auth: "protected"
|
|
19617
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
19618
|
+
kind: "mutation",
|
|
19619
|
+
auth: "protected"
|
|
19620
|
+
}), method(object({ exportId: string() }), ExportRecordSchema, {
|
|
19621
|
+
kind: "mutation",
|
|
19622
|
+
auth: "protected"
|
|
19623
|
+
}), method(object({ exportId: string() }), ExportDownloadSchema, {
|
|
19624
|
+
kind: "query",
|
|
19625
|
+
auth: "protected"
|
|
19626
|
+
});
|
|
19627
|
+
/**
|
|
19451
19628
|
* One publishable camera stream as its OWNING PROVIDER describes it — the same
|
|
19452
19629
|
* payload the (legacy) push `streamBroker.publishCameraStream` carried, minus
|
|
19453
19630
|
* `deviceId`.
|
|
@@ -23371,6 +23548,42 @@ Object.freeze({
|
|
|
23371
23548
|
addonId: null,
|
|
23372
23549
|
access: "create"
|
|
23373
23550
|
},
|
|
23551
|
+
"recordingExport.cancelExport": {
|
|
23552
|
+
capName: "recordingExport",
|
|
23553
|
+
capScope: "system",
|
|
23554
|
+
addonId: null,
|
|
23555
|
+
access: "create"
|
|
23556
|
+
},
|
|
23557
|
+
"recordingExport.createExport": {
|
|
23558
|
+
capName: "recordingExport",
|
|
23559
|
+
capScope: "system",
|
|
23560
|
+
addonId: null,
|
|
23561
|
+
access: "create"
|
|
23562
|
+
},
|
|
23563
|
+
"recordingExport.deleteExport": {
|
|
23564
|
+
capName: "recordingExport",
|
|
23565
|
+
capScope: "system",
|
|
23566
|
+
addonId: null,
|
|
23567
|
+
access: "delete"
|
|
23568
|
+
},
|
|
23569
|
+
"recordingExport.getDownloadUrl": {
|
|
23570
|
+
capName: "recordingExport",
|
|
23571
|
+
capScope: "system",
|
|
23572
|
+
addonId: null,
|
|
23573
|
+
access: "view"
|
|
23574
|
+
},
|
|
23575
|
+
"recordingExport.getExport": {
|
|
23576
|
+
capName: "recordingExport",
|
|
23577
|
+
capScope: "system",
|
|
23578
|
+
addonId: null,
|
|
23579
|
+
access: "view"
|
|
23580
|
+
},
|
|
23581
|
+
"recordingExport.listExports": {
|
|
23582
|
+
capName: "recordingExport",
|
|
23583
|
+
capScope: "system",
|
|
23584
|
+
addonId: null,
|
|
23585
|
+
access: "view"
|
|
23586
|
+
},
|
|
23374
23587
|
"sceneMonitor.captureReference": {
|
|
23375
23588
|
capName: "scene-monitor",
|
|
23376
23589
|
capScope: "device",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-export-hap",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.26",
|
|
4
4
|
"description": "HomeKit (HAP) bridge exporter for CamStack devices. Publishes a bridged accessory per exposed device — MotionSensor in this MVP; Camera/Doorbell/Switch/Light follow.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|