@camstack/addon-pipeline 1.1.53 → 1.1.54
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/audio-analyzer/index.js +1 -1
- package/dist/audio-analyzer/index.mjs +1 -1
- package/dist/detection-pipeline/index.js +146 -7
- package/dist/detection-pipeline/index.mjs +146 -7
- package/dist/{dist-DWb62H5U.js → dist-BbaoC680.js} +110 -7
- package/dist/{dist-BalxNwOt.mjs → dist-CEcTeu1h.mjs} +110 -7
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +114 -5
- package/dist/pipeline-runner/index.mjs +114 -5
- package/dist/recorder/index.js +1 -1
- package/dist/recorder/index.mjs +1 -1
- package/dist/{remote-source-plane-BCJW5CvF.mjs → remote-source-plane-CNCqC_XG.mjs} +1 -1
- package/dist/{remote-source-plane-CZpzIVro.js → remote-source-plane-vN45KFSm.js} +1 -1
- package/dist/session-decode/decode-worker-child.js +319 -35
- package/dist/session-decode/decode-worker-child.mjs +319 -35
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DIN3CcRP.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-HS0tc6Sa.mjs} +3 -3
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-B3gTdHEh.mjs +26 -0
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-C9fwKMfg.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-B_v5r5ya.mjs} +1 -1
- package/dist/stream-broker/{hostInit-CGUEq--X.mjs → hostInit-DgohfEDA.mjs} +3 -3
- package/dist/stream-broker/index.js +2 -2
- package/dist/stream-broker/index.mjs +2 -2
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-pk7qdYXt.mjs → worker-protocol-DGIt_waM.mjs} +6 -0
- package/dist/{worker-protocol-BCfO8gUF.js → worker-protocol-DkL6GDxe.js} +6 -0
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-CqOe8eYa.js → MaskShapeCanvas-DI4BY7W2-CA2Hd6xx.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-CZyLeUnd.js → MotionZonesSettings-NcxxQN8r-DUN1VeC7.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-Cn0hGZnu.js → PrivacyMaskSettings-APgPLF7p-BqZIAU5s.js} +1 -1
- package/embed-dist/assets/{index-DRl4XYjA.js → index-CMkYypxB.js} +10 -10
- package/embed-dist/index.html +1 -1
- package/package.json +1 -1
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-o4tu_xuc.mjs +0 -26
|
@@ -4627,7 +4627,7 @@ function _instanceof(cls, params = {}) {
|
|
|
4627
4627
|
return inst;
|
|
4628
4628
|
}
|
|
4629
4629
|
//#endregion
|
|
4630
|
-
//#region ../types/dist/sleep-
|
|
4630
|
+
//#region ../types/dist/sleep-BC9Yqte7.mjs
|
|
4631
4631
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
4632
4632
|
EventCategory["SystemBoot"] = "system.boot";
|
|
4633
4633
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -11890,6 +11890,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(ZoneSchema).read
|
|
|
11890
11890
|
auth: "admin"
|
|
11891
11891
|
}), object({ zones: array(ZoneSchema).readonly() });
|
|
11892
11892
|
/**
|
|
11893
|
+
* A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
|
|
11894
|
+
* decode worker resolves it against the RETAINED native frame's real pixel dims,
|
|
11895
|
+
* so the caller supplies only the detection-res bbox divided by the detection
|
|
11896
|
+
* dims — no native resolution to plumb.
|
|
11897
|
+
*/
|
|
11898
|
+
var NativeCropBboxSchema = object({
|
|
11899
|
+
x: number(),
|
|
11900
|
+
y: number(),
|
|
11901
|
+
w: number(),
|
|
11902
|
+
h: number()
|
|
11903
|
+
});
|
|
11904
|
+
/** Result of a best-effort native-resolution crop (`getNativeCrop`). */
|
|
11905
|
+
var NativeCropResultSchema = object({
|
|
11906
|
+
/** Packed rgb (24-bit) pixels of the crop. */
|
|
11907
|
+
bytes: _instanceof(Uint8Array),
|
|
11908
|
+
width: number().int().positive(),
|
|
11909
|
+
height: number().int().positive()
|
|
11910
|
+
});
|
|
11911
|
+
/**
|
|
11893
11912
|
* Per-camera tunable ranges + defaults. Single source of truth used
|
|
11894
11913
|
* by both the Zod data schema (validation + default fallback) and
|
|
11895
11914
|
* the device settings UI (slider min/max/step). Touch one place and
|
|
@@ -12193,7 +12212,22 @@ var pipelineRunnerCapability = {
|
|
|
12193
12212
|
/** All per-camera metrics in one round-trip. */
|
|
12194
12213
|
getAllCameraMetrics: method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()),
|
|
12195
12214
|
/** List the deviceIds currently attached to this runner. */
|
|
12196
|
-
getLocalCameras: method(_void(), array(number()).readonly())
|
|
12215
|
+
getLocalCameras: method(_void(), array(number()).readonly()),
|
|
12216
|
+
/**
|
|
12217
|
+
* Best-effort NATIVE-resolution crop of a retention-ring frame. Given the
|
|
12218
|
+
* `FrameHandle` that rode an inference-result event and a normalized `bbox`,
|
|
12219
|
+
* the runner asks the decode worker still holding that frame's NATIVE
|
|
12220
|
+
* surface to GPU/CPU-crop ONLY the ROI at native res and download just the
|
|
12221
|
+
* crop. Returns `null` on a miss (handle not registered, or the worker's
|
|
12222
|
+
* tiny native-retention ring already evicted the frame) — the caller falls
|
|
12223
|
+
* back to a detection-frame crop. Routed to the frame's owning node by
|
|
12224
|
+
* `handle.nodeId`; NEVER ships a full native frame.
|
|
12225
|
+
*/
|
|
12226
|
+
getNativeCrop: method(object({
|
|
12227
|
+
handle: FrameHandleSchema,
|
|
12228
|
+
bbox: NativeCropBboxSchema,
|
|
12229
|
+
maxWidth: number().int().positive().optional()
|
|
12230
|
+
}), NativeCropResultSchema.nullable())
|
|
12197
12231
|
}
|
|
12198
12232
|
};
|
|
12199
12233
|
object({
|
|
@@ -16443,7 +16477,17 @@ var TrackSchema = object({
|
|
|
16443
16477
|
/** Cumulative normalized distance travelled (0..1 units = full frame width). */
|
|
16444
16478
|
totalDistance: number(),
|
|
16445
16479
|
state: TrackStateSchema,
|
|
16446
|
-
active: boolean()
|
|
16480
|
+
active: boolean(),
|
|
16481
|
+
/** Deterministic key-event importance score in [0,1] (server-computed at
|
|
16482
|
+
* track expiry, recomputed on late label). Absent on legacy rows written
|
|
16483
|
+
* before scoring shipped — consumers degrade to absence / compute-on-read. */
|
|
16484
|
+
importance: number().optional(),
|
|
16485
|
+
/** Id of the track's highest-confidence ObjectEvent (its representative
|
|
16486
|
+
* "best" frame). Absent when the track produced no object events. */
|
|
16487
|
+
bestEventId: string().optional(),
|
|
16488
|
+
/** Tag of the importance sub-signal that dominated the score
|
|
16489
|
+
* (identity|dwell|proximity|class|confidence|travel|zone). */
|
|
16490
|
+
importanceReason: string().optional()
|
|
16447
16491
|
});
|
|
16448
16492
|
var BaseEventFields = {
|
|
16449
16493
|
id: string(),
|
|
@@ -16508,8 +16552,18 @@ var ObjectEventSchema = object({
|
|
|
16508
16552
|
frameHeight: number().optional(),
|
|
16509
16553
|
/** MediaStore key for the crop attached to this event (if any). */
|
|
16510
16554
|
mediaKey: string().optional(),
|
|
16555
|
+
/** Design B: MediaStore key of the track's native-resolution key frame (the
|
|
16556
|
+
* best-detection full frame). Resolve via the event-media data-plane
|
|
16557
|
+
* (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
|
|
16558
|
+
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
16559
|
+
* sources — consumers fall back to `mediaKey` (the tight crop). */
|
|
16560
|
+
keyFrameMediaKey: string().optional(),
|
|
16511
16561
|
/** Populated by B5 (recording playback URL for this event). */
|
|
16512
|
-
mediaUrl: string().optional()
|
|
16562
|
+
mediaUrl: string().optional(),
|
|
16563
|
+
/** The parent track's key-event importance [0,1], propagated to every object
|
|
16564
|
+
* event of the track (so an event row can be sorted by importance without a
|
|
16565
|
+
* track join). Absent on legacy rows / before the track was scored. */
|
|
16566
|
+
importance: number().optional()
|
|
16513
16567
|
});
|
|
16514
16568
|
var AudioEventSchema = object({
|
|
16515
16569
|
...BaseEventFields,
|
|
@@ -16533,7 +16587,8 @@ var MediaFileKindEnum = _enum([
|
|
|
16533
16587
|
"fullFrame",
|
|
16534
16588
|
"fullFrameBoxed",
|
|
16535
16589
|
"faceCrop",
|
|
16536
|
-
"plateCrop"
|
|
16590
|
+
"plateCrop",
|
|
16591
|
+
"keyFrame"
|
|
16537
16592
|
]);
|
|
16538
16593
|
var MediaFileSchema = object({
|
|
16539
16594
|
key: string(),
|
|
@@ -16554,6 +16609,32 @@ var DeviceEventQueryInput = object({
|
|
|
16554
16609
|
projection: _enum(["full", "slim"]).optional()
|
|
16555
16610
|
});
|
|
16556
16611
|
var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
|
|
16612
|
+
var KeyEventQueryInput = object({
|
|
16613
|
+
deviceId: number(),
|
|
16614
|
+
/** Window lower bound (track firstSeen ≥ since). */
|
|
16615
|
+
since: number(),
|
|
16616
|
+
/** Window upper bound (track firstSeen ≤ until). */
|
|
16617
|
+
until: number(),
|
|
16618
|
+
limit: number().int().min(1).max(200).default(50),
|
|
16619
|
+
/** Drop tracks scoring below this importance. */
|
|
16620
|
+
minImportance: number().min(0).max(1).optional(),
|
|
16621
|
+
/** Restrict to a single class (e.g. 'person'). */
|
|
16622
|
+
classFilter: string().optional()
|
|
16623
|
+
});
|
|
16624
|
+
var KeyEventSchema = object({
|
|
16625
|
+
/** The representative event id (the track's best ObjectEvent, else its trackId). */
|
|
16626
|
+
id: string(),
|
|
16627
|
+
trackId: string(),
|
|
16628
|
+
/** Track start time (firstSeen). */
|
|
16629
|
+
timestamp: number(),
|
|
16630
|
+
className: string(),
|
|
16631
|
+
label: string().optional(),
|
|
16632
|
+
importance: number(),
|
|
16633
|
+
/** Highest-confidence ObjectEvent id for the track (empty when none). */
|
|
16634
|
+
bestEventId: string(),
|
|
16635
|
+
/** Track lifetime in ms (lastSeen - firstSeen). */
|
|
16636
|
+
windowMs: number().optional()
|
|
16637
|
+
});
|
|
16557
16638
|
var TrackedDetectionSchema = object({
|
|
16558
16639
|
trackId: string(),
|
|
16559
16640
|
className: string(),
|
|
@@ -16583,7 +16664,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16583
16664
|
}), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
|
|
16584
16665
|
kind: "mutation",
|
|
16585
16666
|
auth: "admin"
|
|
16586
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({
|
|
16667
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
16587
16668
|
deviceId: number(),
|
|
16588
16669
|
since: number(),
|
|
16589
16670
|
until: number(),
|
|
@@ -18595,7 +18676,17 @@ var FaceInfoSchema = object({
|
|
|
18595
18676
|
recognizedIdentityId: string().optional(),
|
|
18596
18677
|
identityName: string().optional(),
|
|
18597
18678
|
assigned: boolean(),
|
|
18598
|
-
base64: string().optional()
|
|
18679
|
+
base64: string().optional(),
|
|
18680
|
+
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
18681
|
+
* view draw the box over the native `keyFrameMediaKey` frame. Absent on
|
|
18682
|
+
* legacy rows written before design B. */
|
|
18683
|
+
faceBbox: BoundingBoxSchema.optional(),
|
|
18684
|
+
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
18685
|
+
* Fetch the native JPEG via the event-media data-plane
|
|
18686
|
+
* (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
|
|
18687
|
+
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
18688
|
+
* back to the inline `base64` face crop. */
|
|
18689
|
+
keyFrameMediaKey: string().optional()
|
|
18599
18690
|
});
|
|
18600
18691
|
var FaceFilterEnum = _enum([
|
|
18601
18692
|
"unassigned",
|
|
@@ -22747,6 +22838,12 @@ Object.freeze({
|
|
|
22747
22838
|
addonId: null,
|
|
22748
22839
|
access: "view"
|
|
22749
22840
|
},
|
|
22841
|
+
"pipelineAnalytics.getKeyEvents": {
|
|
22842
|
+
capName: "pipeline-analytics",
|
|
22843
|
+
capScope: "device",
|
|
22844
|
+
addonId: null,
|
|
22845
|
+
access: "view"
|
|
22846
|
+
},
|
|
22750
22847
|
"pipelineAnalytics.getMotionEvents": {
|
|
22751
22848
|
capName: "pipeline-analytics",
|
|
22752
22849
|
capScope: "device",
|
|
@@ -23275,6 +23372,12 @@ Object.freeze({
|
|
|
23275
23372
|
addonId: null,
|
|
23276
23373
|
access: "view"
|
|
23277
23374
|
},
|
|
23375
|
+
"pipelineRunner.getNativeCrop": {
|
|
23376
|
+
capName: "pipeline-runner",
|
|
23377
|
+
capScope: "system",
|
|
23378
|
+
addonId: null,
|
|
23379
|
+
access: "view"
|
|
23380
|
+
},
|
|
23278
23381
|
"pipelineRunner.reportMotion": {
|
|
23279
23382
|
capName: "pipeline-runner",
|
|
23280
23383
|
capScope: "system",
|
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
5
|
+
const require_dist = require("../dist-BbaoC680.js");
|
|
6
6
|
let _camstack_shm_ring = require("@camstack/shm-ring");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as DeviceType, E as motionDetectionCapability, L as BaseAddon, U as hydrateSchema, x as evaluateZoneRules } from "../dist-
|
|
1
|
+
import { B as DeviceType, E as motionDetectionCapability, L as BaseAddon, U as hydrateSchema, x as evaluateZoneRules } from "../dist-CEcTeu1h.mjs";
|
|
2
2
|
import { FrameRingReaderCache } from "@camstack/shm-ring";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
@@ -2,10 +2,10 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
6
|
-
const require_remote_source_plane = require("../remote-source-plane-
|
|
5
|
+
const require_dist = require("../dist-BbaoC680.js");
|
|
6
|
+
const require_remote_source_plane = require("../remote-source-plane-vN45KFSm.js");
|
|
7
7
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
8
|
-
const require_worker_protocol = require("../worker-protocol-
|
|
8
|
+
const require_worker_protocol = require("../worker-protocol-DkL6GDxe.js");
|
|
9
9
|
let _camstack_shm_ring = require("@camstack/shm-ring");
|
|
10
10
|
let node_child_process = require("node:child_process");
|
|
11
11
|
let node_url = require("node:url");
|
|
@@ -1455,6 +1455,9 @@ var SessionDecodeSession = class {
|
|
|
1455
1455
|
frameTimeoutMs;
|
|
1456
1456
|
pendingPull = null;
|
|
1457
1457
|
pendingToBuffers = /* @__PURE__ */ new Map();
|
|
1458
|
+
/** Outstanding `nativeCrop` requests, keyed by the monotonic `requestId`. */
|
|
1459
|
+
pendingNativeCrops = /* @__PURE__ */ new Map();
|
|
1460
|
+
nextNativeCropId = 1;
|
|
1458
1461
|
exited = false;
|
|
1459
1462
|
sigkillTimer = null;
|
|
1460
1463
|
pullTimeoutTimer = null;
|
|
@@ -1519,6 +1522,30 @@ var SessionDecodeSession = class {
|
|
|
1519
1522
|
}
|
|
1520
1523
|
});
|
|
1521
1524
|
}
|
|
1525
|
+
/**
|
|
1526
|
+
* Send `nativeCrop` for `frameId` and resolve with the crop result, or `null`
|
|
1527
|
+
* on any miss (frame aged out, worker error, or worker already exited). Never
|
|
1528
|
+
* rejects — native crops are strictly best-effort with a free fallback.
|
|
1529
|
+
*/
|
|
1530
|
+
requestNativeCrop(frameId, bbox, maxWidth) {
|
|
1531
|
+
if (this.exited) return Promise.resolve(null);
|
|
1532
|
+
const requestId = this.nextNativeCropId++;
|
|
1533
|
+
return new Promise((resolve) => {
|
|
1534
|
+
this.pendingNativeCrops.set(requestId, { resolve });
|
|
1535
|
+
try {
|
|
1536
|
+
this.child.send({
|
|
1537
|
+
kind: "nativeCrop",
|
|
1538
|
+
requestId,
|
|
1539
|
+
frameId,
|
|
1540
|
+
bbox,
|
|
1541
|
+
...maxWidth !== void 0 ? { maxWidth } : {}
|
|
1542
|
+
});
|
|
1543
|
+
} catch {
|
|
1544
|
+
this.pendingNativeCrops.delete(requestId);
|
|
1545
|
+
resolve(null);
|
|
1546
|
+
}
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1522
1549
|
/** Teardown: `stop`, `kill()`, arm the SIGKILL fallback unless already exited. */
|
|
1523
1550
|
teardown() {
|
|
1524
1551
|
this.clearPullTimeout();
|
|
@@ -1551,6 +1578,16 @@ var SessionDecodeSession = class {
|
|
|
1551
1578
|
case "buffer":
|
|
1552
1579
|
this.settleToBuffer(raw.frameId, raw.bytes);
|
|
1553
1580
|
return;
|
|
1581
|
+
case "nativeCropResult":
|
|
1582
|
+
this.settleNativeCrop(raw.requestId, {
|
|
1583
|
+
bytes: raw.bytes,
|
|
1584
|
+
width: raw.width,
|
|
1585
|
+
height: raw.height
|
|
1586
|
+
});
|
|
1587
|
+
return;
|
|
1588
|
+
case "nativeCropMiss":
|
|
1589
|
+
this.settleNativeCrop(raw.requestId, null);
|
|
1590
|
+
return;
|
|
1554
1591
|
case "error":
|
|
1555
1592
|
this.settleError(raw.message, raw.frameId);
|
|
1556
1593
|
return;
|
|
@@ -1570,6 +1607,15 @@ var SessionDecodeSession = class {
|
|
|
1570
1607
|
}
|
|
1571
1608
|
for (const waiters of this.pendingToBuffers.values()) for (const waiter of waiters) waiter.reject(/* @__PURE__ */ new Error("session-decode-coordinator: worker exited before toBuffer reply"));
|
|
1572
1609
|
this.pendingToBuffers.clear();
|
|
1610
|
+
for (const waiter of this.pendingNativeCrops.values()) waiter.resolve(null);
|
|
1611
|
+
this.pendingNativeCrops.clear();
|
|
1612
|
+
}
|
|
1613
|
+
/** Settle the `nativeCrop` waiter for `requestId` (dropping unknown/stale ids). */
|
|
1614
|
+
settleNativeCrop(requestId, result) {
|
|
1615
|
+
const waiter = this.pendingNativeCrops.get(requestId);
|
|
1616
|
+
if (!waiter) return;
|
|
1617
|
+
this.pendingNativeCrops.delete(requestId);
|
|
1618
|
+
waiter.resolve(result);
|
|
1573
1619
|
}
|
|
1574
1620
|
settlePendingPull(outcome) {
|
|
1575
1621
|
const waiter = this.pendingPull;
|
|
@@ -1701,10 +1747,12 @@ function buildFrameImage(session, reply) {
|
|
|
1701
1747
|
width: reply.width,
|
|
1702
1748
|
height: reply.height,
|
|
1703
1749
|
format: reply.format,
|
|
1750
|
+
frameId: reply.frameId,
|
|
1704
1751
|
toBuffer: async (opts) => {
|
|
1705
1752
|
if (closed) throw new Error(`session-decode-coordinator: toBuffer() called on a closed frame (frameId=${reply.frameId})`);
|
|
1706
1753
|
return session.requestBuffer(reply.frameId, opts);
|
|
1707
1754
|
},
|
|
1755
|
+
nativeCrop: (bbox, maxWidth) => session.requestNativeCrop(reply.frameId, bbox, maxWidth),
|
|
1708
1756
|
close: () => {
|
|
1709
1757
|
closed = true;
|
|
1710
1758
|
}
|
|
@@ -1845,7 +1893,9 @@ function startSessionDecodePump(deps) {
|
|
|
1845
1893
|
}
|
|
1846
1894
|
try {
|
|
1847
1895
|
const decoded = await toDecodedFrame(frame, format);
|
|
1848
|
-
|
|
1896
|
+
const image = frame.image;
|
|
1897
|
+
const nativeCrop = image.nativeCrop ? (bbox, maxWidth) => image.nativeCrop(bbox, maxWidth) : void 0;
|
|
1898
|
+
deps.onDecodedFrame(decoded, nativeCrop);
|
|
1849
1899
|
} catch (err) {
|
|
1850
1900
|
deps.logger.debug("session-decode pump: skipped a frame (decode/consume error)", {
|
|
1851
1901
|
tags: { deviceId: deps.source.deviceId },
|
|
@@ -1878,6 +1928,40 @@ function startSessionDecodePump(deps) {
|
|
|
1878
1928
|
iterator.return().catch(() => {});
|
|
1879
1929
|
};
|
|
1880
1930
|
}
|
|
1931
|
+
var NativeCropRegistry = class {
|
|
1932
|
+
capacity;
|
|
1933
|
+
entries = /* @__PURE__ */ new Map();
|
|
1934
|
+
constructor(capacity = 64) {
|
|
1935
|
+
this.capacity = capacity;
|
|
1936
|
+
}
|
|
1937
|
+
/** Number of registered handles (tests / metrics). */
|
|
1938
|
+
get size() {
|
|
1939
|
+
return this.entries.size;
|
|
1940
|
+
}
|
|
1941
|
+
/** A retention frame is uniquely identified by its segment + slot + committed seq. */
|
|
1942
|
+
key(handle) {
|
|
1943
|
+
return `${handle.shmId}#${handle.slot}#${handle.seq}`;
|
|
1944
|
+
}
|
|
1945
|
+
/** Bind `request` to `handle`; evicts the oldest entry past the cap. */
|
|
1946
|
+
register(handle, request) {
|
|
1947
|
+
const k = this.key(handle);
|
|
1948
|
+
this.entries.delete(k);
|
|
1949
|
+
this.entries.set(k, request);
|
|
1950
|
+
while (this.entries.size > this.capacity) {
|
|
1951
|
+
const oldest = this.entries.keys().next().value;
|
|
1952
|
+
if (oldest === void 0) break;
|
|
1953
|
+
this.entries.delete(oldest);
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
/** The requester for `handle`, or `null` if never registered / already evicted. */
|
|
1957
|
+
get(handle) {
|
|
1958
|
+
return this.entries.get(this.key(handle)) ?? null;
|
|
1959
|
+
}
|
|
1960
|
+
/** Drop every entry (node/addon shutdown). */
|
|
1961
|
+
clear() {
|
|
1962
|
+
this.entries.clear();
|
|
1963
|
+
}
|
|
1964
|
+
};
|
|
1881
1965
|
//#endregion
|
|
1882
1966
|
//#region src/pipeline-runner/index.ts
|
|
1883
1967
|
var DEFAULT_CONFIG = {
|
|
@@ -2102,6 +2186,13 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
|
|
|
2102
2186
|
* `resize()`d live in `onConfigChanged`. Null until `onInitialize`.
|
|
2103
2187
|
*/
|
|
2104
2188
|
spawnGate = null;
|
|
2189
|
+
/**
|
|
2190
|
+
* Node-level map from a retention-ring `FrameHandle` to the decode worker
|
|
2191
|
+
* still holding that frame's NATIVE surface — backs the `getNativeCrop` cap
|
|
2192
|
+
* so post-analysis can cut native-res crops (best-effort; a miss falls back
|
|
2193
|
+
* to the detection-frame crop). See {@link NativeCropRegistry}.
|
|
2194
|
+
*/
|
|
2195
|
+
nativeCropRegistry = new NativeCropRegistry();
|
|
2105
2196
|
attached = /* @__PURE__ */ new Map();
|
|
2106
2197
|
nodeId = "unknown";
|
|
2107
2198
|
metricsSnapshotTimer = null;
|
|
@@ -2671,6 +2762,23 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
|
|
|
2671
2762
|
this.runner?.reportMotion(input.deviceId, input.detected, input.source, input.regions);
|
|
2672
2763
|
return { success: true };
|
|
2673
2764
|
}
|
|
2765
|
+
/**
|
|
2766
|
+
* Best-effort native-resolution crop for a retention-ring frame (native-crop
|
|
2767
|
+
* feature). Looks the handle up in {@link nativeCropRegistry}; a miss (never
|
|
2768
|
+
* registered, or the worker's tiny native ring already evicted the frame)
|
|
2769
|
+
* returns `null` so the caller falls back to a detection-frame crop. The
|
|
2770
|
+
* worker downloads ONLY the ROI — a full native frame never travels the wire.
|
|
2771
|
+
*/
|
|
2772
|
+
async getNativeCrop(input) {
|
|
2773
|
+
const requester = this.nativeCropRegistry.get(input.handle);
|
|
2774
|
+
if (!requester) return null;
|
|
2775
|
+
const result = await requester(input.bbox, input.maxWidth);
|
|
2776
|
+
return result ? {
|
|
2777
|
+
bytes: result.bytes,
|
|
2778
|
+
width: result.width,
|
|
2779
|
+
height: result.height
|
|
2780
|
+
} : null;
|
|
2781
|
+
}
|
|
2674
2782
|
detachInternal(deviceId) {
|
|
2675
2783
|
const attachment = this.attached.get(deviceId);
|
|
2676
2784
|
if (!attachment) return;
|
|
@@ -2990,8 +3098,9 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
|
|
|
2990
3098
|
format: "rgb"
|
|
2991
3099
|
},
|
|
2992
3100
|
acquireSpawnSlot: this.buildDecodeSpawnAcquire(log, "detect"),
|
|
2993
|
-
onDecodedFrame: (frame) => {
|
|
3101
|
+
onDecodedFrame: (frame, nativeCrop) => {
|
|
2994
3102
|
const handle = retentionSink.write(frame) ?? void 0;
|
|
3103
|
+
if (handle && nativeCrop) this.nativeCropRegistry.register(handle, nativeCrop);
|
|
2995
3104
|
this.enqueueSharedDetectionFrame(config.deviceId, frame, handle);
|
|
2996
3105
|
}
|
|
2997
3106
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { $ as boolean, D as nodePin, H as createEvent, I as errMsg, K as makeSourceBrokerId, L as BaseAddon, Q as array, V as EventCategory, Z as _enum, _ as customAction, it as object, k as pipelineRunnerCapability, ot as string, rt as number, tt as lazy, y as defineCustomActions } from "../dist-
|
|
2
|
-
import { n as isRemoteRestream, r as profileForStreamId, t as RemoteSourcePlane } from "../remote-source-plane-
|
|
1
|
+
import { $ as boolean, D as nodePin, H as createEvent, I as errMsg, K as makeSourceBrokerId, L as BaseAddon, Q as array, V as EventCategory, Z as _enum, _ as customAction, it as object, k as pipelineRunnerCapability, ot as string, rt as number, tt as lazy, y as defineCustomActions } from "../dist-CEcTeu1h.mjs";
|
|
2
|
+
import { n as isRemoteRestream, r as profileForStreamId, t as RemoteSourcePlane } from "../remote-source-plane-CNCqC_XG.mjs";
|
|
3
3
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
4
|
-
import { t as isWorkerReply } from "../worker-protocol-
|
|
4
|
+
import { t as isWorkerReply } from "../worker-protocol-DGIt_waM.mjs";
|
|
5
5
|
import { DecoderFrameRingSink, FrameRingReaderCache, unlinkSegment } from "@camstack/shm-ring";
|
|
6
6
|
import { fork } from "node:child_process";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
@@ -1451,6 +1451,9 @@ var SessionDecodeSession = class {
|
|
|
1451
1451
|
frameTimeoutMs;
|
|
1452
1452
|
pendingPull = null;
|
|
1453
1453
|
pendingToBuffers = /* @__PURE__ */ new Map();
|
|
1454
|
+
/** Outstanding `nativeCrop` requests, keyed by the monotonic `requestId`. */
|
|
1455
|
+
pendingNativeCrops = /* @__PURE__ */ new Map();
|
|
1456
|
+
nextNativeCropId = 1;
|
|
1454
1457
|
exited = false;
|
|
1455
1458
|
sigkillTimer = null;
|
|
1456
1459
|
pullTimeoutTimer = null;
|
|
@@ -1515,6 +1518,30 @@ var SessionDecodeSession = class {
|
|
|
1515
1518
|
}
|
|
1516
1519
|
});
|
|
1517
1520
|
}
|
|
1521
|
+
/**
|
|
1522
|
+
* Send `nativeCrop` for `frameId` and resolve with the crop result, or `null`
|
|
1523
|
+
* on any miss (frame aged out, worker error, or worker already exited). Never
|
|
1524
|
+
* rejects — native crops are strictly best-effort with a free fallback.
|
|
1525
|
+
*/
|
|
1526
|
+
requestNativeCrop(frameId, bbox, maxWidth) {
|
|
1527
|
+
if (this.exited) return Promise.resolve(null);
|
|
1528
|
+
const requestId = this.nextNativeCropId++;
|
|
1529
|
+
return new Promise((resolve) => {
|
|
1530
|
+
this.pendingNativeCrops.set(requestId, { resolve });
|
|
1531
|
+
try {
|
|
1532
|
+
this.child.send({
|
|
1533
|
+
kind: "nativeCrop",
|
|
1534
|
+
requestId,
|
|
1535
|
+
frameId,
|
|
1536
|
+
bbox,
|
|
1537
|
+
...maxWidth !== void 0 ? { maxWidth } : {}
|
|
1538
|
+
});
|
|
1539
|
+
} catch {
|
|
1540
|
+
this.pendingNativeCrops.delete(requestId);
|
|
1541
|
+
resolve(null);
|
|
1542
|
+
}
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1518
1545
|
/** Teardown: `stop`, `kill()`, arm the SIGKILL fallback unless already exited. */
|
|
1519
1546
|
teardown() {
|
|
1520
1547
|
this.clearPullTimeout();
|
|
@@ -1547,6 +1574,16 @@ var SessionDecodeSession = class {
|
|
|
1547
1574
|
case "buffer":
|
|
1548
1575
|
this.settleToBuffer(raw.frameId, raw.bytes);
|
|
1549
1576
|
return;
|
|
1577
|
+
case "nativeCropResult":
|
|
1578
|
+
this.settleNativeCrop(raw.requestId, {
|
|
1579
|
+
bytes: raw.bytes,
|
|
1580
|
+
width: raw.width,
|
|
1581
|
+
height: raw.height
|
|
1582
|
+
});
|
|
1583
|
+
return;
|
|
1584
|
+
case "nativeCropMiss":
|
|
1585
|
+
this.settleNativeCrop(raw.requestId, null);
|
|
1586
|
+
return;
|
|
1550
1587
|
case "error":
|
|
1551
1588
|
this.settleError(raw.message, raw.frameId);
|
|
1552
1589
|
return;
|
|
@@ -1566,6 +1603,15 @@ var SessionDecodeSession = class {
|
|
|
1566
1603
|
}
|
|
1567
1604
|
for (const waiters of this.pendingToBuffers.values()) for (const waiter of waiters) waiter.reject(/* @__PURE__ */ new Error("session-decode-coordinator: worker exited before toBuffer reply"));
|
|
1568
1605
|
this.pendingToBuffers.clear();
|
|
1606
|
+
for (const waiter of this.pendingNativeCrops.values()) waiter.resolve(null);
|
|
1607
|
+
this.pendingNativeCrops.clear();
|
|
1608
|
+
}
|
|
1609
|
+
/** Settle the `nativeCrop` waiter for `requestId` (dropping unknown/stale ids). */
|
|
1610
|
+
settleNativeCrop(requestId, result) {
|
|
1611
|
+
const waiter = this.pendingNativeCrops.get(requestId);
|
|
1612
|
+
if (!waiter) return;
|
|
1613
|
+
this.pendingNativeCrops.delete(requestId);
|
|
1614
|
+
waiter.resolve(result);
|
|
1569
1615
|
}
|
|
1570
1616
|
settlePendingPull(outcome) {
|
|
1571
1617
|
const waiter = this.pendingPull;
|
|
@@ -1697,10 +1743,12 @@ function buildFrameImage(session, reply) {
|
|
|
1697
1743
|
width: reply.width,
|
|
1698
1744
|
height: reply.height,
|
|
1699
1745
|
format: reply.format,
|
|
1746
|
+
frameId: reply.frameId,
|
|
1700
1747
|
toBuffer: async (opts) => {
|
|
1701
1748
|
if (closed) throw new Error(`session-decode-coordinator: toBuffer() called on a closed frame (frameId=${reply.frameId})`);
|
|
1702
1749
|
return session.requestBuffer(reply.frameId, opts);
|
|
1703
1750
|
},
|
|
1751
|
+
nativeCrop: (bbox, maxWidth) => session.requestNativeCrop(reply.frameId, bbox, maxWidth),
|
|
1704
1752
|
close: () => {
|
|
1705
1753
|
closed = true;
|
|
1706
1754
|
}
|
|
@@ -1841,7 +1889,9 @@ function startSessionDecodePump(deps) {
|
|
|
1841
1889
|
}
|
|
1842
1890
|
try {
|
|
1843
1891
|
const decoded = await toDecodedFrame(frame, format);
|
|
1844
|
-
|
|
1892
|
+
const image = frame.image;
|
|
1893
|
+
const nativeCrop = image.nativeCrop ? (bbox, maxWidth) => image.nativeCrop(bbox, maxWidth) : void 0;
|
|
1894
|
+
deps.onDecodedFrame(decoded, nativeCrop);
|
|
1845
1895
|
} catch (err) {
|
|
1846
1896
|
deps.logger.debug("session-decode pump: skipped a frame (decode/consume error)", {
|
|
1847
1897
|
tags: { deviceId: deps.source.deviceId },
|
|
@@ -1874,6 +1924,40 @@ function startSessionDecodePump(deps) {
|
|
|
1874
1924
|
iterator.return().catch(() => {});
|
|
1875
1925
|
};
|
|
1876
1926
|
}
|
|
1927
|
+
var NativeCropRegistry = class {
|
|
1928
|
+
capacity;
|
|
1929
|
+
entries = /* @__PURE__ */ new Map();
|
|
1930
|
+
constructor(capacity = 64) {
|
|
1931
|
+
this.capacity = capacity;
|
|
1932
|
+
}
|
|
1933
|
+
/** Number of registered handles (tests / metrics). */
|
|
1934
|
+
get size() {
|
|
1935
|
+
return this.entries.size;
|
|
1936
|
+
}
|
|
1937
|
+
/** A retention frame is uniquely identified by its segment + slot + committed seq. */
|
|
1938
|
+
key(handle) {
|
|
1939
|
+
return `${handle.shmId}#${handle.slot}#${handle.seq}`;
|
|
1940
|
+
}
|
|
1941
|
+
/** Bind `request` to `handle`; evicts the oldest entry past the cap. */
|
|
1942
|
+
register(handle, request) {
|
|
1943
|
+
const k = this.key(handle);
|
|
1944
|
+
this.entries.delete(k);
|
|
1945
|
+
this.entries.set(k, request);
|
|
1946
|
+
while (this.entries.size > this.capacity) {
|
|
1947
|
+
const oldest = this.entries.keys().next().value;
|
|
1948
|
+
if (oldest === void 0) break;
|
|
1949
|
+
this.entries.delete(oldest);
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
/** The requester for `handle`, or `null` if never registered / already evicted. */
|
|
1953
|
+
get(handle) {
|
|
1954
|
+
return this.entries.get(this.key(handle)) ?? null;
|
|
1955
|
+
}
|
|
1956
|
+
/** Drop every entry (node/addon shutdown). */
|
|
1957
|
+
clear() {
|
|
1958
|
+
this.entries.clear();
|
|
1959
|
+
}
|
|
1960
|
+
};
|
|
1877
1961
|
//#endregion
|
|
1878
1962
|
//#region src/pipeline-runner/index.ts
|
|
1879
1963
|
var DEFAULT_CONFIG = {
|
|
@@ -2098,6 +2182,13 @@ var PipelineRunnerAddon = class extends BaseAddon {
|
|
|
2098
2182
|
* `resize()`d live in `onConfigChanged`. Null until `onInitialize`.
|
|
2099
2183
|
*/
|
|
2100
2184
|
spawnGate = null;
|
|
2185
|
+
/**
|
|
2186
|
+
* Node-level map from a retention-ring `FrameHandle` to the decode worker
|
|
2187
|
+
* still holding that frame's NATIVE surface — backs the `getNativeCrop` cap
|
|
2188
|
+
* so post-analysis can cut native-res crops (best-effort; a miss falls back
|
|
2189
|
+
* to the detection-frame crop). See {@link NativeCropRegistry}.
|
|
2190
|
+
*/
|
|
2191
|
+
nativeCropRegistry = new NativeCropRegistry();
|
|
2101
2192
|
attached = /* @__PURE__ */ new Map();
|
|
2102
2193
|
nodeId = "unknown";
|
|
2103
2194
|
metricsSnapshotTimer = null;
|
|
@@ -2667,6 +2758,23 @@ var PipelineRunnerAddon = class extends BaseAddon {
|
|
|
2667
2758
|
this.runner?.reportMotion(input.deviceId, input.detected, input.source, input.regions);
|
|
2668
2759
|
return { success: true };
|
|
2669
2760
|
}
|
|
2761
|
+
/**
|
|
2762
|
+
* Best-effort native-resolution crop for a retention-ring frame (native-crop
|
|
2763
|
+
* feature). Looks the handle up in {@link nativeCropRegistry}; a miss (never
|
|
2764
|
+
* registered, or the worker's tiny native ring already evicted the frame)
|
|
2765
|
+
* returns `null` so the caller falls back to a detection-frame crop. The
|
|
2766
|
+
* worker downloads ONLY the ROI — a full native frame never travels the wire.
|
|
2767
|
+
*/
|
|
2768
|
+
async getNativeCrop(input) {
|
|
2769
|
+
const requester = this.nativeCropRegistry.get(input.handle);
|
|
2770
|
+
if (!requester) return null;
|
|
2771
|
+
const result = await requester(input.bbox, input.maxWidth);
|
|
2772
|
+
return result ? {
|
|
2773
|
+
bytes: result.bytes,
|
|
2774
|
+
width: result.width,
|
|
2775
|
+
height: result.height
|
|
2776
|
+
} : null;
|
|
2777
|
+
}
|
|
2670
2778
|
detachInternal(deviceId) {
|
|
2671
2779
|
const attachment = this.attached.get(deviceId);
|
|
2672
2780
|
if (!attachment) return;
|
|
@@ -2986,8 +3094,9 @@ var PipelineRunnerAddon = class extends BaseAddon {
|
|
|
2986
3094
|
format: "rgb"
|
|
2987
3095
|
},
|
|
2988
3096
|
acquireSpawnSlot: this.buildDecodeSpawnAcquire(log, "detect"),
|
|
2989
|
-
onDecodedFrame: (frame) => {
|
|
3097
|
+
onDecodedFrame: (frame, nativeCrop) => {
|
|
2990
3098
|
const handle = retentionSink.write(frame) ?? void 0;
|
|
3099
|
+
if (handle && nativeCrop) this.nativeCropRegistry.register(handle, nativeCrop);
|
|
2991
3100
|
this.enqueueSharedDetectionFrame(config.deviceId, frame, handle);
|
|
2992
3101
|
}
|
|
2993
3102
|
});
|
package/dist/recorder/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("../chunk-D6vf50IK.js");
|
|
2
|
-
const require_dist = require("../dist-
|
|
2
|
+
const require_dist = require("../dist-BbaoC680.js");
|
|
3
3
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
4
4
|
const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-BLXzxpRB.js");
|
|
5
5
|
let node_child_process = require("node:child_process");
|
package/dist/recorder/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as recordingCapability, B as DeviceType, D as nodePin, I as errMsg, L as BaseAddon, M as storageEvictableCapability, T as migrateConfigToBands, U as hydrateSchema, V as EventCategory, Y as selectAssignedProfileSlots, at as record, ot as string, s as EVENT_PAD_MS, u as RecordingConfigSchema } from "../dist-
|
|
1
|
+
import { A as recordingCapability, B as DeviceType, D as nodePin, I as errMsg, L as BaseAddon, M as storageEvictableCapability, T as migrateConfigToBands, U as hydrateSchema, V as EventCategory, Y as selectAssignedProfileSlots, at as record, ot as string, s as EVENT_PAD_MS, u as RecordingConfigSchema } from "../dist-CEcTeu1h.mjs";
|
|
2
2
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
3
3
|
import { t as createFileDataPlaneHandler } from "../model-download-service-C-IHWnXx-BPy6aoAx.mjs";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as nodePin, I as errMsg, d as RingBuffer } from "./dist-
|
|
1
|
+
import { D as nodePin, I as errMsg, d as RingBuffer } from "./dist-CEcTeu1h.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
//#region src/stream-broker/stream-broker/decoder-session-proxy.ts
|
|
4
4
|
/**
|