@camstack/addon-pipeline 1.2.614 → 1.2.616
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/THIRD_PARTY_MODELS.md +2 -2
- package/dist/audio-analyzer/index.js +3 -3
- package/dist/audio-analyzer/index.mjs +3 -3
- package/dist/{custom-model-catalog-D_mgggfr.js → custom-model-catalog-D0EZW4Xb.js} +3 -3
- package/dist/{custom-model-catalog-CLhfiG1p.mjs → custom-model-catalog-D3NopOC9.mjs} +3 -3
- package/dist/detection-pipeline/index.js +114 -6
- package/dist/detection-pipeline/index.mjs +114 -6
- package/dist/{dist-BGq_y1xM.mjs → dist-BWPVIuD_.mjs} +237 -61
- package/dist/{dist-F6F_xjNj.js → dist-D2aJhYm7.js} +237 -61
- package/dist/{model-catalogs-DrUv77wD.js → model-catalogs-BDJEmiKm.js} +14 -4
- package/dist/{model-catalogs-CF3WVSy_.mjs → model-catalogs-CYoIeMo4.mjs} +14 -4
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-D_K-84ig.js → node-BKs5_GlD.js} +1 -1
- package/dist/{node-DwTqHnch.mjs → node-D48F38hW.mjs} +1 -1
- package/dist/pipeline-runner/index.js +3 -3
- package/dist/pipeline-runner/index.mjs +3 -3
- package/dist/{process-memory-k316CseF.mjs → process-memory-58pkBnTk.mjs} +1 -1
- package/dist/{process-memory-BN3N6YZh.js → process-memory-BY-1p6rF.js} +1 -1
- package/dist/recorder/index.js +114 -11
- package/dist/recorder/index.mjs +114 -11
- package/dist/{segment-demux-js-C4-eYvhD.js → segment-demux-js-DbM8w1dc.js} +1 -1
- package/dist/{segment-demux-js-CWJseQHd.mjs → segment-demux-js-VeHvPIJe.mjs} +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DrWysXZj.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B6vm1OlX.mjs} +3 -3
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-qcb2Czgh.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-BvJiBUdN.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-TnEvW5tZ.mjs} +1 -1
- package/dist/stream-broker/demux-worker-child.js +1 -1
- package/dist/stream-broker/demux-worker-child.mjs +1 -1
- package/dist/stream-broker/{hostInit-D5F0gL07.mjs → hostInit-BnK9Yje5.mjs} +3 -3
- package/dist/stream-broker/index.js +38 -5
- package/dist/stream-broker/index.mjs +38 -5
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/python/inference_pool.py +33 -0
- package/python/openvino_compile_probe.py +245 -0
- package/python/test_openvino_compile_probe.py +298 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-QzO03I5h.mjs +0 -26
package/dist/recorder/index.js
CHANGED
|
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
7
|
-
const require_node = require("../node-
|
|
6
|
+
const require_dist = require("../dist-D2aJhYm7.js");
|
|
7
|
+
const require_node = require("../node-BKs5_GlD.js");
|
|
8
8
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
9
9
|
const require_restream_intent = require("../restream-intent-7uDNqMKs.js");
|
|
10
10
|
let node_crypto = require("node:crypto");
|
|
@@ -2991,9 +2991,25 @@ function encodeDirectory(payload) {
|
|
|
2991
2991
|
var MIN_INDEXABLE_SEGMENT_BYTES = 64;
|
|
2992
2992
|
var SegmentStore = class SegmentStore {
|
|
2993
2993
|
deps;
|
|
2994
|
+
stubCount = 0;
|
|
2995
|
+
stubBytes = 0;
|
|
2994
2996
|
constructor(deps) {
|
|
2995
2997
|
this.deps = deps;
|
|
2996
2998
|
}
|
|
2999
|
+
/**
|
|
3000
|
+
* The stubs cleared since the last call, then reset. A recovery pass calls it
|
|
3001
|
+
* once and logs ONE line: ~530 stubs used to re-log at every boot because
|
|
3002
|
+
* each was warned about and left in staging forever.
|
|
3003
|
+
*/
|
|
3004
|
+
takeStubReport() {
|
|
3005
|
+
const report = {
|
|
3006
|
+
count: this.stubCount,
|
|
3007
|
+
bytes: this.stubBytes
|
|
3008
|
+
};
|
|
3009
|
+
this.stubCount = 0;
|
|
3010
|
+
this.stubBytes = 0;
|
|
3011
|
+
return report;
|
|
3012
|
+
}
|
|
2997
3013
|
async hydrate(deviceId, location) {
|
|
2998
3014
|
const paths = await this.deps.list({
|
|
2999
3015
|
location,
|
|
@@ -3013,13 +3029,30 @@ var SegmentStore = class SegmentStore {
|
|
|
3013
3029
|
return null;
|
|
3014
3030
|
}
|
|
3015
3031
|
if (bytes < MIN_INDEXABLE_SEGMENT_BYTES) {
|
|
3016
|
-
this.deps.logger.
|
|
3032
|
+
this.deps.logger.debug?.("segment too small to index — clearing stub from staging", {
|
|
3017
3033
|
tags: { deviceId: input.deviceId },
|
|
3018
3034
|
meta: {
|
|
3019
3035
|
bytes,
|
|
3020
3036
|
path: input.flatAbsPath
|
|
3021
3037
|
}
|
|
3022
3038
|
});
|
|
3039
|
+
if (this.deps.removeStaged !== void 0) {
|
|
3040
|
+
try {
|
|
3041
|
+
await this.deps.removeStaged(input.flatAbsPath);
|
|
3042
|
+
} catch (err) {
|
|
3043
|
+
this.deps.logger.warn("segment stub could not be cleared from staging", {
|
|
3044
|
+
tags: { deviceId: input.deviceId },
|
|
3045
|
+
error: err,
|
|
3046
|
+
meta: {
|
|
3047
|
+
bytes,
|
|
3048
|
+
path: input.flatAbsPath
|
|
3049
|
+
}
|
|
3050
|
+
});
|
|
3051
|
+
return null;
|
|
3052
|
+
}
|
|
3053
|
+
this.stubCount++;
|
|
3054
|
+
this.stubBytes += bytes;
|
|
3055
|
+
}
|
|
3023
3056
|
return null;
|
|
3024
3057
|
}
|
|
3025
3058
|
const relPath = segmentRelPath(input.deviceId, input.profile, input.startMs, input.durMs, bytes);
|
|
@@ -6849,6 +6882,18 @@ Object.freeze({
|
|
|
6849
6882
|
"empty"
|
|
6850
6883
|
]
|
|
6851
6884
|
},
|
|
6885
|
+
{
|
|
6886
|
+
"path": "filterCleaningDue",
|
|
6887
|
+
"valueType": "boolean"
|
|
6888
|
+
},
|
|
6889
|
+
{
|
|
6890
|
+
"path": "machineCareDue",
|
|
6891
|
+
"valueType": "boolean"
|
|
6892
|
+
},
|
|
6893
|
+
{
|
|
6894
|
+
"path": "machineCareRemainingRuns",
|
|
6895
|
+
"valueType": "number"
|
|
6896
|
+
},
|
|
6852
6897
|
{
|
|
6853
6898
|
"path": "halfLoad",
|
|
6854
6899
|
"valueType": "boolean"
|
|
@@ -11780,6 +11825,9 @@ var DurableLegacyKindHandle = class {
|
|
|
11780
11825
|
aggregate = () => notImpl("aggregate");
|
|
11781
11826
|
deleteWhere = () => notImpl("deleteWhere");
|
|
11782
11827
|
allocateId = () => notImpl("allocateId");
|
|
11828
|
+
txPut = () => notImpl("txPut");
|
|
11829
|
+
txPatch = () => notImpl("txPatch");
|
|
11830
|
+
txDelete = () => notImpl("txDelete");
|
|
11783
11831
|
pkColumn() {
|
|
11784
11832
|
return this.spec.columns.find((c) => c.primaryKey === true)?.name ?? "id";
|
|
11785
11833
|
}
|
|
@@ -18052,6 +18100,15 @@ var METHOD_FAILED = /\bmethod ([A-Z_]+) failed: (\d{3})\b/;
|
|
|
18052
18100
|
function isHandshakeMethod(method) {
|
|
18053
18101
|
return method === "OPTIONS" || method === "DESCRIBE" || method === "SETUP" || method === "PLAY";
|
|
18054
18102
|
}
|
|
18103
|
+
/**
|
|
18104
|
+
* ffmpeg's account of a restream that answered DESCRIBE `200` with no SDP at
|
|
18105
|
+
* all (a hub that predates the 503 refusal): it opens the url and finds nothing
|
|
18106
|
+
* to parse — `Error opening input file rtsp://… ` + `Invalid data found when
|
|
18107
|
+
* processing input`, exit 183 (AVERROR_INVALIDDATA & 0xff). Same fact as a
|
|
18108
|
+
* refused DESCRIBE: the source is not serving right now, nothing ran.
|
|
18109
|
+
*/
|
|
18110
|
+
var OPEN_FAILED = /Error opening input file rtsp:\/\//;
|
|
18111
|
+
var INVALID_DATA = /Invalid data found when processing input/;
|
|
18055
18112
|
/** The refusal named in this generation's stderr tail, or `null` when there is none. */
|
|
18056
18113
|
function readDialRefusal(stderrTail) {
|
|
18057
18114
|
for (let i = stderrTail.length - 1; i >= 0; i--) {
|
|
@@ -18064,6 +18121,11 @@ function readDialRefusal(stderrTail) {
|
|
|
18064
18121
|
status: Number(match[2])
|
|
18065
18122
|
};
|
|
18066
18123
|
}
|
|
18124
|
+
const text = stderrTail.join("\n");
|
|
18125
|
+
if (OPEN_FAILED.test(text) && INVALID_DATA.test(text)) return {
|
|
18126
|
+
method: "DESCRIBE",
|
|
18127
|
+
status: 503
|
|
18128
|
+
};
|
|
18067
18129
|
return null;
|
|
18068
18130
|
}
|
|
18069
18131
|
//#endregion
|
|
@@ -18465,10 +18527,11 @@ var RecordingStallMonitor = class {
|
|
|
18465
18527
|
});
|
|
18466
18528
|
return;
|
|
18467
18529
|
}
|
|
18530
|
+
const edge = prev?.expected !== true;
|
|
18468
18531
|
this.state.set(deviceId, {
|
|
18469
18532
|
expected: true,
|
|
18470
|
-
lastSegmentAt: prev?.lastSegmentAt ?? now,
|
|
18471
|
-
stalledReported: prev?.stalledReported ?? false,
|
|
18533
|
+
lastSegmentAt: edge ? now : prev?.lastSegmentAt ?? now,
|
|
18534
|
+
stalledReported: edge ? false : prev?.stalledReported ?? false,
|
|
18472
18535
|
lastDegradedAt: prev?.lastDegradedAt ?? null
|
|
18473
18536
|
});
|
|
18474
18537
|
}
|
|
@@ -18836,6 +18899,15 @@ var RecordingController = class {
|
|
|
18836
18899
|
*/
|
|
18837
18900
|
lastSegmentAt = /* @__PURE__ */ new Map();
|
|
18838
18901
|
/**
|
|
18902
|
+
* Per `deviceId:profile`, when a segment was last FINALIZED — never seeded at
|
|
18903
|
+
* the pin. {@link lastSegmentAt} answers "is this writer still in its grace
|
|
18904
|
+
* window"; this answers "has it actually produced anything recently", which is
|
|
18905
|
+
* what a give-up may claim about the siblings it keeps (2026-10-22, camera
|
|
18906
|
+
* 618: both writers dead, each give-up said the other "keeps recording").
|
|
18907
|
+
* Cleared with {@link lastSegmentAt}.
|
|
18908
|
+
*/
|
|
18909
|
+
lastProducedAt = /* @__PURE__ */ new Map();
|
|
18910
|
+
/**
|
|
18839
18911
|
* Per `deviceId:profile`, the `attachedAtMs` of the attach that has retained
|
|
18840
18912
|
* at least one `events` segment. Read only to LEVEL the discard log: an
|
|
18841
18913
|
* attach that kept nothing is a wasted pull (warn), a later discard from one
|
|
@@ -19376,11 +19448,21 @@ var RecordingController = class {
|
|
|
19376
19448
|
const stalled = profile === void 0 ? current : current.filter((r) => r.profile === profile);
|
|
19377
19449
|
if (stalled.length === 0) return;
|
|
19378
19450
|
const keep = profile === void 0 ? [] : current.filter((r) => r.profile !== profile);
|
|
19379
|
-
|
|
19380
|
-
|
|
19381
|
-
|
|
19382
|
-
|
|
19383
|
-
}
|
|
19451
|
+
const now = this.now();
|
|
19452
|
+
const producing = keep.filter((r) => this.producedRecently(deviceId, r, now));
|
|
19453
|
+
const silentSiblings = keep.filter((r) => !producing.includes(r)).map((r) => r.profile);
|
|
19454
|
+
if (keep.length > 0 && producing.length === 0) this.deps.logger.warn("recorder: writer gave up — no profile produced a segment recently (all stalled) — detaching + re-evaluating device", {
|
|
19455
|
+
tags: { deviceId },
|
|
19456
|
+
meta: {
|
|
19457
|
+
profile,
|
|
19458
|
+
stalledSiblings: silentSiblings
|
|
19459
|
+
}
|
|
19460
|
+
});
|
|
19461
|
+
else if (keep.length === 0) this.deps.logger.warn("recorder: writer gave up — detaching + re-evaluating device", {
|
|
19462
|
+
tags: { deviceId },
|
|
19463
|
+
...profile !== void 0 ? { meta: { profile } } : {}
|
|
19464
|
+
});
|
|
19465
|
+
if (producing.length === 0) {
|
|
19384
19466
|
try {
|
|
19385
19467
|
await this.detachDevice(deviceId);
|
|
19386
19468
|
await this.evaluateDevice(deviceId);
|
|
@@ -19397,7 +19479,8 @@ var RecordingController = class {
|
|
|
19397
19479
|
tags: { deviceId },
|
|
19398
19480
|
meta: {
|
|
19399
19481
|
profile: stalled.map((r) => r.profile),
|
|
19400
|
-
keeping:
|
|
19482
|
+
keeping: producing.map((r) => r.profile),
|
|
19483
|
+
...silentSiblings.length > 0 ? { pinnedWithoutSegment: silentSiblings } : {}
|
|
19401
19484
|
}
|
|
19402
19485
|
});
|
|
19403
19486
|
try {
|
|
@@ -19413,6 +19496,11 @@ var RecordingController = class {
|
|
|
19413
19496
|
});
|
|
19414
19497
|
}
|
|
19415
19498
|
}
|
|
19499
|
+
/** Did this writer finalize a segment within its idle bound? Seeding at the pin does not count. */
|
|
19500
|
+
producedRecently(deviceId, r, now) {
|
|
19501
|
+
const at = this.lastProducedAt.get(idleKey(deviceId, r.profile));
|
|
19502
|
+
return at !== void 0 && now - at <= writerIdleBoundMs(r.segmentSeconds);
|
|
19503
|
+
}
|
|
19416
19504
|
/**
|
|
19417
19505
|
* Tear down only the stalled writers, keep the rest pinned, and retry the
|
|
19418
19506
|
* missing profiles through {@link fillMissingProfiles}.
|
|
@@ -19420,6 +19508,7 @@ var RecordingController = class {
|
|
|
19420
19508
|
async recoverStalledProfiles(deviceId, stalled, keep) {
|
|
19421
19509
|
for (const r of stalled) {
|
|
19422
19510
|
this.lastSegmentAt.delete(idleKey(deviceId, r.profile));
|
|
19511
|
+
this.lastProducedAt.delete(idleKey(deviceId, r.profile));
|
|
19423
19512
|
this.attachRetained.delete(idleKey(deviceId, r.profile));
|
|
19424
19513
|
}
|
|
19425
19514
|
this.active.set(deviceId, [...keep]);
|
|
@@ -20161,6 +20250,7 @@ var RecordingController = class {
|
|
|
20161
20250
|
onFinalized: async (startMs, durMs, flatAbsPath) => {
|
|
20162
20251
|
const segmentAt = this.now();
|
|
20163
20252
|
this.lastSegmentAt.set(idleKey(deviceId, profile), segmentAt);
|
|
20253
|
+
this.lastProducedAt.set(idleKey(deviceId, profile), segmentAt);
|
|
20164
20254
|
const recovered = this.stallMonitor.noteSegment(deviceId, segmentAt);
|
|
20165
20255
|
if (recovered !== null) this.deps.emitRecordingHealth?.(require_dist.EventCategory.RecordingHealthOk, { deviceId: recovered.deviceId });
|
|
20166
20256
|
if (startMs >= writerStartedMs - 1e3 && !firstSegmentSeen) {
|
|
@@ -20340,6 +20430,7 @@ var RecordingController = class {
|
|
|
20340
20430
|
this.skippedProfiles.delete(deviceId);
|
|
20341
20431
|
for (const r of recordings) {
|
|
20342
20432
|
this.lastSegmentAt.delete(idleKey(deviceId, r.profile));
|
|
20433
|
+
this.lastProducedAt.delete(idleKey(deviceId, r.profile));
|
|
20343
20434
|
this.attachRetained.delete(idleKey(deviceId, r.profile));
|
|
20344
20435
|
}
|
|
20345
20436
|
await Promise.all(recordings.map((r) => this.teardownProfile(deviceId, r)));
|
|
@@ -23807,6 +23898,7 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
23807
23898
|
list: (input) => this.ctx.api.storage.list.query(input),
|
|
23808
23899
|
deletePath: (input) => this.ctx.api.storage.delete.mutate(input),
|
|
23809
23900
|
statBytes: async (absPath) => (await node_fs.promises.stat(absPath)).size,
|
|
23901
|
+
removeStaged: (absPath) => node_fs.promises.rm(absPath, { force: true }),
|
|
23810
23902
|
moveFile: async (fromAbs, toAbs) => {
|
|
23811
23903
|
await node_fs.promises.mkdir(node_path.default.dirname(toAbs), { recursive: true });
|
|
23812
23904
|
try {
|
|
@@ -23873,6 +23965,12 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
23873
23965
|
},
|
|
23874
23966
|
info: (message, extras) => {
|
|
23875
23967
|
this.ctx.logger.info(message, { meta: extras.meta });
|
|
23968
|
+
},
|
|
23969
|
+
debug: (message, extras) => {
|
|
23970
|
+
this.ctx.logger.debug(message, {
|
|
23971
|
+
tags: extras.tags,
|
|
23972
|
+
meta: extras.meta
|
|
23973
|
+
});
|
|
23876
23974
|
}
|
|
23877
23975
|
}
|
|
23878
23976
|
};
|
|
@@ -25433,6 +25531,11 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
25433
25531
|
defaultSegmentSeconds: this.config.segmentSeconds,
|
|
25434
25532
|
shouldStop: () => this.segmentStore === null
|
|
25435
25533
|
});
|
|
25534
|
+
const stubs = this.segmentStore?.takeStubReport();
|
|
25535
|
+
if (stubs !== void 0 && stubs.count > 0) this.ctx.logger.info("recorder: staging recovery cleared stub segments", { meta: {
|
|
25536
|
+
count: stubs.count,
|
|
25537
|
+
bytes: stubs.bytes
|
|
25538
|
+
} });
|
|
25436
25539
|
} catch (err) {
|
|
25437
25540
|
this.ctx.logger.warn("recorder: staging boot reconcile failed", { meta: { error: require_dist.errMsg(err) } });
|
|
25438
25541
|
}
|
package/dist/recorder/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { An as DeviceFeature, B as RECORDING_SOURCE_CAMSTACK_ADDON, Bt as mayWriteToLocation, C as EVENT_PAD_MS, Dn as evaluateSensorEdge, Et as exportSubjectOf, G as VIDEOCLIPS_MAX_OFFER_BYTES, H as RecordingConfigSchema, Hn as defineCustomActions, Ht as migrateLegacyDeviceSignalConfig, It as loadContributionCapability, K as VISIT_MERGE_GAP_MS, Kn as hydrateSchema, Mn as errMsg$1, N as OpsLogEntrySchema, Nt as isFirstLevelMacroClass, Pn as BaseAddon, Qn as nodePin, R as RECORDING_EXPORT_MAX_READ_BYTES, S as EVENT_OWNER_TYPES, T as ExportRecordSchema, Tt as evictionPolicyOfLocation, U as RecordingSignalStatusSchema, Un as defineRecordKinds, Ut as modeMayWrite, Vn as customAction, Vt as memoizePinnedFfmpeg, Z as armRemovalReconcile, _n as storageOccupancyCapability, an as resolveCreateExportSubject, ar as boolean, at as clipExportFailure, dr as preprocess, en as recordingArchiveCapability, er as selectAssignedProfileSlots, fr as record, gn as storageEvictableCapability, hr as EventCategory, ht as deriveRecordingMode, ir as array, jn as DeviceType, kt as gbToBytes, lr as number, mn as startMoverUnderClearance, nn as recordingExportCapability, nr as userError, o as BatteryStatusSchema, ot as clipExportFailureOf, pr as string, pt as deriveBatteryPresence, rn as recordingSignalCapability, rr as _enum, s as CLIP_BROKER_PACED_RATES, sn as resolveLocationMode, tn as recordingCapability, tr as sleep$1, tt as batteryCapability, un as resolveRecordingProfiles, ur as object, v as DEFAULT_EVENTS_BAND_BUFFER_SEC, vt as deviceRemovalHookCapability, wt as evictionPolicyForMode, xn as videoclipsCapability, yn as stripRetiredBandPreBufferSec, z as RECORDING_SOURCE_CAMSTACK, zt as mayReadLocation } from "../dist-
|
|
2
|
-
import { i as NO_COST_CLAIM, o as physicalRootOf, t as ChildCostRegistry } from "../node-
|
|
1
|
+
import { An as DeviceFeature, B as RECORDING_SOURCE_CAMSTACK_ADDON, Bt as mayWriteToLocation, C as EVENT_PAD_MS, Dn as evaluateSensorEdge, Et as exportSubjectOf, G as VIDEOCLIPS_MAX_OFFER_BYTES, H as RecordingConfigSchema, Hn as defineCustomActions, Ht as migrateLegacyDeviceSignalConfig, It as loadContributionCapability, K as VISIT_MERGE_GAP_MS, Kn as hydrateSchema, Mn as errMsg$1, N as OpsLogEntrySchema, Nt as isFirstLevelMacroClass, Pn as BaseAddon, Qn as nodePin, R as RECORDING_EXPORT_MAX_READ_BYTES, S as EVENT_OWNER_TYPES, T as ExportRecordSchema, Tt as evictionPolicyOfLocation, U as RecordingSignalStatusSchema, Un as defineRecordKinds, Ut as modeMayWrite, Vn as customAction, Vt as memoizePinnedFfmpeg, Z as armRemovalReconcile, _n as storageOccupancyCapability, an as resolveCreateExportSubject, ar as boolean, at as clipExportFailure, dr as preprocess, en as recordingArchiveCapability, er as selectAssignedProfileSlots, fr as record, gn as storageEvictableCapability, hr as EventCategory, ht as deriveRecordingMode, ir as array, jn as DeviceType, kt as gbToBytes, lr as number, mn as startMoverUnderClearance, nn as recordingExportCapability, nr as userError, o as BatteryStatusSchema, ot as clipExportFailureOf, pr as string, pt as deriveBatteryPresence, rn as recordingSignalCapability, rr as _enum, s as CLIP_BROKER_PACED_RATES, sn as resolveLocationMode, tn as recordingCapability, tr as sleep$1, tt as batteryCapability, un as resolveRecordingProfiles, ur as object, v as DEFAULT_EVENTS_BAND_BUFFER_SEC, vt as deviceRemovalHookCapability, wt as evictionPolicyForMode, xn as videoclipsCapability, yn as stripRetiredBandPreBufferSec, z as RECORDING_SOURCE_CAMSTACK, zt as mayReadLocation } from "../dist-BWPVIuD_.mjs";
|
|
2
|
+
import { i as NO_COST_CLAIM, o as physicalRootOf, t as ChildCostRegistry } from "../node-D48F38hW.mjs";
|
|
3
3
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
4
4
|
import { d as PREBUFFER_MAX_MS, l as withRecordingIntent, r as RECORDING_PRE_ROLL_REQUEST_MS } from "../restream-intent-DyGmLAU9.mjs";
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
@@ -2984,9 +2984,25 @@ function encodeDirectory(payload) {
|
|
|
2984
2984
|
var MIN_INDEXABLE_SEGMENT_BYTES = 64;
|
|
2985
2985
|
var SegmentStore = class SegmentStore {
|
|
2986
2986
|
deps;
|
|
2987
|
+
stubCount = 0;
|
|
2988
|
+
stubBytes = 0;
|
|
2987
2989
|
constructor(deps) {
|
|
2988
2990
|
this.deps = deps;
|
|
2989
2991
|
}
|
|
2992
|
+
/**
|
|
2993
|
+
* The stubs cleared since the last call, then reset. A recovery pass calls it
|
|
2994
|
+
* once and logs ONE line: ~530 stubs used to re-log at every boot because
|
|
2995
|
+
* each was warned about and left in staging forever.
|
|
2996
|
+
*/
|
|
2997
|
+
takeStubReport() {
|
|
2998
|
+
const report = {
|
|
2999
|
+
count: this.stubCount,
|
|
3000
|
+
bytes: this.stubBytes
|
|
3001
|
+
};
|
|
3002
|
+
this.stubCount = 0;
|
|
3003
|
+
this.stubBytes = 0;
|
|
3004
|
+
return report;
|
|
3005
|
+
}
|
|
2990
3006
|
async hydrate(deviceId, location) {
|
|
2991
3007
|
const paths = await this.deps.list({
|
|
2992
3008
|
location,
|
|
@@ -3006,13 +3022,30 @@ var SegmentStore = class SegmentStore {
|
|
|
3006
3022
|
return null;
|
|
3007
3023
|
}
|
|
3008
3024
|
if (bytes < MIN_INDEXABLE_SEGMENT_BYTES) {
|
|
3009
|
-
this.deps.logger.
|
|
3025
|
+
this.deps.logger.debug?.("segment too small to index — clearing stub from staging", {
|
|
3010
3026
|
tags: { deviceId: input.deviceId },
|
|
3011
3027
|
meta: {
|
|
3012
3028
|
bytes,
|
|
3013
3029
|
path: input.flatAbsPath
|
|
3014
3030
|
}
|
|
3015
3031
|
});
|
|
3032
|
+
if (this.deps.removeStaged !== void 0) {
|
|
3033
|
+
try {
|
|
3034
|
+
await this.deps.removeStaged(input.flatAbsPath);
|
|
3035
|
+
} catch (err) {
|
|
3036
|
+
this.deps.logger.warn("segment stub could not be cleared from staging", {
|
|
3037
|
+
tags: { deviceId: input.deviceId },
|
|
3038
|
+
error: err,
|
|
3039
|
+
meta: {
|
|
3040
|
+
bytes,
|
|
3041
|
+
path: input.flatAbsPath
|
|
3042
|
+
}
|
|
3043
|
+
});
|
|
3044
|
+
return null;
|
|
3045
|
+
}
|
|
3046
|
+
this.stubCount++;
|
|
3047
|
+
this.stubBytes += bytes;
|
|
3048
|
+
}
|
|
3016
3049
|
return null;
|
|
3017
3050
|
}
|
|
3018
3051
|
const relPath = segmentRelPath(input.deviceId, input.profile, input.startMs, input.durMs, bytes);
|
|
@@ -6841,6 +6874,18 @@ Object.freeze({
|
|
|
6841
6874
|
"empty"
|
|
6842
6875
|
]
|
|
6843
6876
|
},
|
|
6877
|
+
{
|
|
6878
|
+
"path": "filterCleaningDue",
|
|
6879
|
+
"valueType": "boolean"
|
|
6880
|
+
},
|
|
6881
|
+
{
|
|
6882
|
+
"path": "machineCareDue",
|
|
6883
|
+
"valueType": "boolean"
|
|
6884
|
+
},
|
|
6885
|
+
{
|
|
6886
|
+
"path": "machineCareRemainingRuns",
|
|
6887
|
+
"valueType": "number"
|
|
6888
|
+
},
|
|
6844
6889
|
{
|
|
6845
6890
|
"path": "halfLoad",
|
|
6846
6891
|
"valueType": "boolean"
|
|
@@ -11772,6 +11817,9 @@ var DurableLegacyKindHandle = class {
|
|
|
11772
11817
|
aggregate = () => notImpl("aggregate");
|
|
11773
11818
|
deleteWhere = () => notImpl("deleteWhere");
|
|
11774
11819
|
allocateId = () => notImpl("allocateId");
|
|
11820
|
+
txPut = () => notImpl("txPut");
|
|
11821
|
+
txPatch = () => notImpl("txPatch");
|
|
11822
|
+
txDelete = () => notImpl("txDelete");
|
|
11775
11823
|
pkColumn() {
|
|
11776
11824
|
return this.spec.columns.find((c) => c.primaryKey === true)?.name ?? "id";
|
|
11777
11825
|
}
|
|
@@ -18044,6 +18092,15 @@ var METHOD_FAILED = /\bmethod ([A-Z_]+) failed: (\d{3})\b/;
|
|
|
18044
18092
|
function isHandshakeMethod(method) {
|
|
18045
18093
|
return method === "OPTIONS" || method === "DESCRIBE" || method === "SETUP" || method === "PLAY";
|
|
18046
18094
|
}
|
|
18095
|
+
/**
|
|
18096
|
+
* ffmpeg's account of a restream that answered DESCRIBE `200` with no SDP at
|
|
18097
|
+
* all (a hub that predates the 503 refusal): it opens the url and finds nothing
|
|
18098
|
+
* to parse — `Error opening input file rtsp://… ` + `Invalid data found when
|
|
18099
|
+
* processing input`, exit 183 (AVERROR_INVALIDDATA & 0xff). Same fact as a
|
|
18100
|
+
* refused DESCRIBE: the source is not serving right now, nothing ran.
|
|
18101
|
+
*/
|
|
18102
|
+
var OPEN_FAILED = /Error opening input file rtsp:\/\//;
|
|
18103
|
+
var INVALID_DATA = /Invalid data found when processing input/;
|
|
18047
18104
|
/** The refusal named in this generation's stderr tail, or `null` when there is none. */
|
|
18048
18105
|
function readDialRefusal(stderrTail) {
|
|
18049
18106
|
for (let i = stderrTail.length - 1; i >= 0; i--) {
|
|
@@ -18056,6 +18113,11 @@ function readDialRefusal(stderrTail) {
|
|
|
18056
18113
|
status: Number(match[2])
|
|
18057
18114
|
};
|
|
18058
18115
|
}
|
|
18116
|
+
const text = stderrTail.join("\n");
|
|
18117
|
+
if (OPEN_FAILED.test(text) && INVALID_DATA.test(text)) return {
|
|
18118
|
+
method: "DESCRIBE",
|
|
18119
|
+
status: 503
|
|
18120
|
+
};
|
|
18059
18121
|
return null;
|
|
18060
18122
|
}
|
|
18061
18123
|
//#endregion
|
|
@@ -18457,10 +18519,11 @@ var RecordingStallMonitor = class {
|
|
|
18457
18519
|
});
|
|
18458
18520
|
return;
|
|
18459
18521
|
}
|
|
18522
|
+
const edge = prev?.expected !== true;
|
|
18460
18523
|
this.state.set(deviceId, {
|
|
18461
18524
|
expected: true,
|
|
18462
|
-
lastSegmentAt: prev?.lastSegmentAt ?? now,
|
|
18463
|
-
stalledReported: prev?.stalledReported ?? false,
|
|
18525
|
+
lastSegmentAt: edge ? now : prev?.lastSegmentAt ?? now,
|
|
18526
|
+
stalledReported: edge ? false : prev?.stalledReported ?? false,
|
|
18464
18527
|
lastDegradedAt: prev?.lastDegradedAt ?? null
|
|
18465
18528
|
});
|
|
18466
18529
|
}
|
|
@@ -18828,6 +18891,15 @@ var RecordingController = class {
|
|
|
18828
18891
|
*/
|
|
18829
18892
|
lastSegmentAt = /* @__PURE__ */ new Map();
|
|
18830
18893
|
/**
|
|
18894
|
+
* Per `deviceId:profile`, when a segment was last FINALIZED — never seeded at
|
|
18895
|
+
* the pin. {@link lastSegmentAt} answers "is this writer still in its grace
|
|
18896
|
+
* window"; this answers "has it actually produced anything recently", which is
|
|
18897
|
+
* what a give-up may claim about the siblings it keeps (2026-10-22, camera
|
|
18898
|
+
* 618: both writers dead, each give-up said the other "keeps recording").
|
|
18899
|
+
* Cleared with {@link lastSegmentAt}.
|
|
18900
|
+
*/
|
|
18901
|
+
lastProducedAt = /* @__PURE__ */ new Map();
|
|
18902
|
+
/**
|
|
18831
18903
|
* Per `deviceId:profile`, the `attachedAtMs` of the attach that has retained
|
|
18832
18904
|
* at least one `events` segment. Read only to LEVEL the discard log: an
|
|
18833
18905
|
* attach that kept nothing is a wasted pull (warn), a later discard from one
|
|
@@ -19368,11 +19440,21 @@ var RecordingController = class {
|
|
|
19368
19440
|
const stalled = profile === void 0 ? current : current.filter((r) => r.profile === profile);
|
|
19369
19441
|
if (stalled.length === 0) return;
|
|
19370
19442
|
const keep = profile === void 0 ? [] : current.filter((r) => r.profile !== profile);
|
|
19371
|
-
|
|
19372
|
-
|
|
19373
|
-
|
|
19374
|
-
|
|
19375
|
-
}
|
|
19443
|
+
const now = this.now();
|
|
19444
|
+
const producing = keep.filter((r) => this.producedRecently(deviceId, r, now));
|
|
19445
|
+
const silentSiblings = keep.filter((r) => !producing.includes(r)).map((r) => r.profile);
|
|
19446
|
+
if (keep.length > 0 && producing.length === 0) this.deps.logger.warn("recorder: writer gave up — no profile produced a segment recently (all stalled) — detaching + re-evaluating device", {
|
|
19447
|
+
tags: { deviceId },
|
|
19448
|
+
meta: {
|
|
19449
|
+
profile,
|
|
19450
|
+
stalledSiblings: silentSiblings
|
|
19451
|
+
}
|
|
19452
|
+
});
|
|
19453
|
+
else if (keep.length === 0) this.deps.logger.warn("recorder: writer gave up — detaching + re-evaluating device", {
|
|
19454
|
+
tags: { deviceId },
|
|
19455
|
+
...profile !== void 0 ? { meta: { profile } } : {}
|
|
19456
|
+
});
|
|
19457
|
+
if (producing.length === 0) {
|
|
19376
19458
|
try {
|
|
19377
19459
|
await this.detachDevice(deviceId);
|
|
19378
19460
|
await this.evaluateDevice(deviceId);
|
|
@@ -19389,7 +19471,8 @@ var RecordingController = class {
|
|
|
19389
19471
|
tags: { deviceId },
|
|
19390
19472
|
meta: {
|
|
19391
19473
|
profile: stalled.map((r) => r.profile),
|
|
19392
|
-
keeping:
|
|
19474
|
+
keeping: producing.map((r) => r.profile),
|
|
19475
|
+
...silentSiblings.length > 0 ? { pinnedWithoutSegment: silentSiblings } : {}
|
|
19393
19476
|
}
|
|
19394
19477
|
});
|
|
19395
19478
|
try {
|
|
@@ -19405,6 +19488,11 @@ var RecordingController = class {
|
|
|
19405
19488
|
});
|
|
19406
19489
|
}
|
|
19407
19490
|
}
|
|
19491
|
+
/** Did this writer finalize a segment within its idle bound? Seeding at the pin does not count. */
|
|
19492
|
+
producedRecently(deviceId, r, now) {
|
|
19493
|
+
const at = this.lastProducedAt.get(idleKey(deviceId, r.profile));
|
|
19494
|
+
return at !== void 0 && now - at <= writerIdleBoundMs(r.segmentSeconds);
|
|
19495
|
+
}
|
|
19408
19496
|
/**
|
|
19409
19497
|
* Tear down only the stalled writers, keep the rest pinned, and retry the
|
|
19410
19498
|
* missing profiles through {@link fillMissingProfiles}.
|
|
@@ -19412,6 +19500,7 @@ var RecordingController = class {
|
|
|
19412
19500
|
async recoverStalledProfiles(deviceId, stalled, keep) {
|
|
19413
19501
|
for (const r of stalled) {
|
|
19414
19502
|
this.lastSegmentAt.delete(idleKey(deviceId, r.profile));
|
|
19503
|
+
this.lastProducedAt.delete(idleKey(deviceId, r.profile));
|
|
19415
19504
|
this.attachRetained.delete(idleKey(deviceId, r.profile));
|
|
19416
19505
|
}
|
|
19417
19506
|
this.active.set(deviceId, [...keep]);
|
|
@@ -20153,6 +20242,7 @@ var RecordingController = class {
|
|
|
20153
20242
|
onFinalized: async (startMs, durMs, flatAbsPath) => {
|
|
20154
20243
|
const segmentAt = this.now();
|
|
20155
20244
|
this.lastSegmentAt.set(idleKey(deviceId, profile), segmentAt);
|
|
20245
|
+
this.lastProducedAt.set(idleKey(deviceId, profile), segmentAt);
|
|
20156
20246
|
const recovered = this.stallMonitor.noteSegment(deviceId, segmentAt);
|
|
20157
20247
|
if (recovered !== null) this.deps.emitRecordingHealth?.(EventCategory.RecordingHealthOk, { deviceId: recovered.deviceId });
|
|
20158
20248
|
if (startMs >= writerStartedMs - 1e3 && !firstSegmentSeen) {
|
|
@@ -20332,6 +20422,7 @@ var RecordingController = class {
|
|
|
20332
20422
|
this.skippedProfiles.delete(deviceId);
|
|
20333
20423
|
for (const r of recordings) {
|
|
20334
20424
|
this.lastSegmentAt.delete(idleKey(deviceId, r.profile));
|
|
20425
|
+
this.lastProducedAt.delete(idleKey(deviceId, r.profile));
|
|
20335
20426
|
this.attachRetained.delete(idleKey(deviceId, r.profile));
|
|
20336
20427
|
}
|
|
20337
20428
|
await Promise.all(recordings.map((r) => this.teardownProfile(deviceId, r)));
|
|
@@ -23799,6 +23890,7 @@ var RecorderV2Addon = class extends BaseAddon {
|
|
|
23799
23890
|
list: (input) => this.ctx.api.storage.list.query(input),
|
|
23800
23891
|
deletePath: (input) => this.ctx.api.storage.delete.mutate(input),
|
|
23801
23892
|
statBytes: async (absPath) => (await promises.stat(absPath)).size,
|
|
23893
|
+
removeStaged: (absPath) => promises.rm(absPath, { force: true }),
|
|
23802
23894
|
moveFile: async (fromAbs, toAbs) => {
|
|
23803
23895
|
await promises.mkdir(path.dirname(toAbs), { recursive: true });
|
|
23804
23896
|
try {
|
|
@@ -23865,6 +23957,12 @@ var RecorderV2Addon = class extends BaseAddon {
|
|
|
23865
23957
|
},
|
|
23866
23958
|
info: (message, extras) => {
|
|
23867
23959
|
this.ctx.logger.info(message, { meta: extras.meta });
|
|
23960
|
+
},
|
|
23961
|
+
debug: (message, extras) => {
|
|
23962
|
+
this.ctx.logger.debug(message, {
|
|
23963
|
+
tags: extras.tags,
|
|
23964
|
+
meta: extras.meta
|
|
23965
|
+
});
|
|
23868
23966
|
}
|
|
23869
23967
|
}
|
|
23870
23968
|
};
|
|
@@ -25425,6 +25523,11 @@ var RecorderV2Addon = class extends BaseAddon {
|
|
|
25425
25523
|
defaultSegmentSeconds: this.config.segmentSeconds,
|
|
25426
25524
|
shouldStop: () => this.segmentStore === null
|
|
25427
25525
|
});
|
|
25526
|
+
const stubs = this.segmentStore?.takeStubReport();
|
|
25527
|
+
if (stubs !== void 0 && stubs.count > 0) this.ctx.logger.info("recorder: staging recovery cleared stub segments", { meta: {
|
|
25528
|
+
count: stubs.count,
|
|
25529
|
+
bytes: stubs.bytes
|
|
25530
|
+
} });
|
|
25428
25531
|
} catch (err) {
|
|
25429
25532
|
this.ctx.logger.warn("recorder: staging boot reconcile failed", { meta: { error: errMsg$1(err) } });
|
|
25430
25533
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-emK7D4bc.js");
|
|
2
|
-
const require_dist = require("./dist-
|
|
2
|
+
const require_dist = require("./dist-D2aJhYm7.js");
|
|
3
3
|
let node_child_process = require("node:child_process");
|
|
4
4
|
//#region src/stream-broker/recorded/avcc-annexb.ts
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as __toESM, t as __commonJSMin } from "./chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { Mn as errMsg } from "./dist-
|
|
2
|
+
import { Mn as errMsg } from "./dist-BWPVIuD_.mjs";
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
4
|
//#region src/stream-broker/recorded/avcc-annexb.ts
|
|
5
5
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as e, c as t, d as n, f as r, i, l as a, m as o, n as s, o as c, p as l, r as u, s as d, t as f, u as p } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-
|
|
1
|
+
import { a as e, c as t, d as n, f as r, i, l as a, m as o, n as s, o as c, p as l, r as u, s as d, t as f, u as p } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-TnEvW5tZ.mjs";
|
|
2
2
|
import { a as m, i as h, n as g, o as _, r as v, t as y } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.js-C9j-2lBe.mjs";
|
|
3
3
|
import { n as b, r as x, t as S } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-XO0-Pyu6.mjs";
|
|
4
|
-
import { t as C } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-
|
|
4
|
+
import { t as C } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-qcb2Czgh.mjs";
|
|
5
5
|
import { n as w, t as T } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-BO7TIbJV.mjs";
|
|
6
6
|
//#region ../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
|
|
7
7
|
var E = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), D = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), O = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), k = (e) => {
|
|
@@ -3,7 +3,7 @@ import "./dist-CYZr2fwk.mjs";
|
|
|
3
3
|
var e = {
|
|
4
4
|
"@camstack/sdk": {
|
|
5
5
|
name: "@camstack/sdk",
|
|
6
|
-
version: "1.2.
|
|
6
|
+
version: "1.2.148",
|
|
7
7
|
scope: ["default"],
|
|
8
8
|
loaded: !1,
|
|
9
9
|
from: "addon_stream_broker_widgets",
|
|
@@ -18,7 +18,7 @@ var e = {
|
|
|
18
18
|
},
|
|
19
19
|
"@camstack/types": {
|
|
20
20
|
name: "@camstack/types",
|
|
21
|
-
version: "1.2.
|
|
21
|
+
version: "1.2.398",
|
|
22
22
|
scope: ["default"],
|
|
23
23
|
loaded: !1,
|
|
24
24
|
from: "addon_stream_broker_widgets",
|
|
@@ -33,7 +33,7 @@ var e = {
|
|
|
33
33
|
},
|
|
34
34
|
"@camstack/ui-library": {
|
|
35
35
|
name: "@camstack/ui-library",
|
|
36
|
-
version: "1.2.
|
|
36
|
+
version: "1.2.315",
|
|
37
37
|
scope: ["default"],
|
|
38
38
|
loaded: !1,
|
|
39
39
|
from: "addon_stream_broker_widgets",
|