@trillboards/edge-sdk 0.2.42 → 0.2.52
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/README.md +76 -0
- package/deploy/docker/connector-entrypoint.sh +1 -1
- package/dist/AudioOnsetDetector.d.ts +211 -0
- package/dist/AudioOnsetDetector.d.ts.map +1 -0
- package/dist/AudioOnsetDetector.js +286 -0
- package/dist/AudioOnsetDetector.js.map +1 -0
- package/dist/CloudSensingManager.d.ts +67 -0
- package/dist/CloudSensingManager.d.ts.map +1 -1
- package/dist/CloudSensingManager.js +185 -17
- package/dist/CloudSensingManager.js.map +1 -1
- package/dist/DurableVlmCandidateSpool.d.ts +99 -0
- package/dist/DurableVlmCandidateSpool.d.ts.map +1 -0
- package/dist/DurableVlmCandidateSpool.js +522 -0
- package/dist/DurableVlmCandidateSpool.js.map +1 -0
- package/dist/EdgeAgent.d.ts.map +1 -1
- package/dist/EdgeAgent.js +20 -2
- package/dist/EdgeAgent.js.map +1 -1
- package/dist/LiteRtVlmProvider.d.ts +66 -1
- package/dist/LiteRtVlmProvider.d.ts.map +1 -1
- package/dist/LiteRtVlmProvider.js +132 -0
- package/dist/LiteRtVlmProvider.js.map +1 -1
- package/dist/SceneChangeDetector.d.ts +62 -6
- package/dist/SceneChangeDetector.d.ts.map +1 -1
- package/dist/SceneChangeDetector.js +61 -5
- package/dist/SceneChangeDetector.js.map +1 -1
- package/dist/VlmAdmissionGate.d.ts +63 -0
- package/dist/VlmAdmissionGate.d.ts.map +1 -1
- package/dist/VlmAdmissionGate.js +64 -0
- package/dist/VlmAdmissionGate.js.map +1 -1
- package/dist/VlmCandidateBuffer.d.ts +17 -0
- package/dist/VlmCandidateBuffer.d.ts.map +1 -1
- package/dist/VlmCandidateBuffer.js +6 -0
- package/dist/VlmCandidateBuffer.js.map +1 -1
- package/dist/attachAudioOnset.d.ts +87 -0
- package/dist/attachAudioOnset.d.ts.map +1 -0
- package/dist/attachAudioOnset.js +87 -0
- package/dist/attachAudioOnset.js.map +1 -0
- package/dist/config.d.ts +83 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/connectorCadence.d.ts +193 -8
- package/dist/connectorCadence.d.ts.map +1 -1
- package/dist/connectorCadence.js +225 -10
- package/dist/connectorCadence.js.map +1 -1
- package/dist/deployedCadence.d.ts +18 -5
- package/dist/deployedCadence.d.ts.map +1 -1
- package/dist/deployedCadence.js +50 -13
- package/dist/deployedCadence.js.map +1 -1
- package/dist/diagnose.d.ts +1 -1
- package/dist/diagnose.js +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -1
- package/dist/index.js.map +1 -1
- package/dist/sensingCatchRate.d.ts +105 -3
- package/dist/sensingCatchRate.d.ts.map +1 -1
- package/dist/sensingCatchRate.js +98 -10
- package/dist/sensingCatchRate.js.map +1 -1
- package/dist/sensingRunMode.d.ts.map +1 -1
- package/dist/sensingRunMode.js +100 -4
- package/dist/sensingRunMode.js.map +1 -1
- package/dist/wavEncode.d.ts +29 -0
- package/dist/wavEncode.d.ts.map +1 -0
- package/dist/wavEncode.js +63 -0
- package/dist/wavEncode.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { AudioOnsetDetector, type AudioOnsetDetectorOptions, type AudioOnsetEvent } from './AudioOnsetDetector';
|
|
2
|
+
import type { MotionGate } from './SceneChangeDetector';
|
|
3
|
+
/**
|
|
4
|
+
* attachAudioOnset — joins the acoustic transport to the visual cascade.
|
|
5
|
+
*
|
|
6
|
+
* This is the ONLY place `RTSPAudioProvider` (transport, in
|
|
7
|
+
* `@trillboards/edge-platform-rtsp`) and `AudioOnsetDetector` (analysis, here)
|
|
8
|
+
* meet, and it is a separate module rather than inline in `CloudSensingManager`
|
|
9
|
+
* for two reasons: that file is the connector's busiest, and the join has
|
|
10
|
+
* enough behaviour of its own — failure classification, lifecycle, per-feed
|
|
11
|
+
* accounting — to deserve its own tests.
|
|
12
|
+
*
|
|
13
|
+
* ── OFF BY DEFAULT, AND THAT IS A LEGAL POSITION, NOT A ROLLOUT SETTING.
|
|
14
|
+
* `audioSensing.enabled` defaults to FALSE and must be turned on deliberately
|
|
15
|
+
* per deployment. Recording audio in a venue is not the same act as recording
|
|
16
|
+
* video: a large number of US states are all-party-consent for audio, and the
|
|
17
|
+
* cameras this connector attaches to belong to the CUSTOMER, who bought them
|
|
18
|
+
* for video and may have signage and a DPA that say exactly that. Shipping a
|
|
19
|
+
* default that starts pulling microphone audio off a retail chain's existing
|
|
20
|
+
* NVR would be a change in what the product DOES to the people in that store,
|
|
21
|
+
* made silently by an upgrade. It must be an explicit choice by someone who
|
|
22
|
+
* can make it.
|
|
23
|
+
*
|
|
24
|
+
* ── EVERY FAILURE HERE IS NON-FATAL, BY CONSTRUCTION. `attach` returns `null`
|
|
25
|
+
* rather than throwing, for all of: the recorder's audio lane already full, the
|
|
26
|
+
* stream carrying no audio track (most CCTV channels do not), a missing
|
|
27
|
+
* platform package, a missing ffmpeg. Audio is a SUPPLEMENTARY sense. Nothing
|
|
28
|
+
* in this path may ever be able to stop a camera from producing frames, and a
|
|
29
|
+
* connector that refused to start because a microphone was absent would be a
|
|
30
|
+
* strictly worse product than one that quietly sees.
|
|
31
|
+
*/
|
|
32
|
+
/** The transport surface this module needs — `RTSPAudioProvider` satisfies it. */
|
|
33
|
+
export interface AudioOnsetTransport {
|
|
34
|
+
open(deviceId?: string): Promise<void>;
|
|
35
|
+
onPcm(listener: (pcm: Float32Array, atMs: number) => void): () => void;
|
|
36
|
+
getSampleRate(): number;
|
|
37
|
+
close(): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
export interface AudioSensingOptions {
|
|
40
|
+
/**
|
|
41
|
+
* Master switch. DEFAULT FALSE — see the header; this is a consent decision,
|
|
42
|
+
* not a rollout percentage.
|
|
43
|
+
*/
|
|
44
|
+
enabled?: boolean;
|
|
45
|
+
/** Capture sample rate (Hz). Default 16000. */
|
|
46
|
+
sampleRate?: number;
|
|
47
|
+
/** Long-lived audio sessions allowed per recorder host:port. Default 1. */
|
|
48
|
+
maxAudioSessionsPerSource?: number;
|
|
49
|
+
/** RTSP transport for the audio pull. */
|
|
50
|
+
transport?: 'tcp' | 'udp';
|
|
51
|
+
/** ffmpeg binary for the audio pull. */
|
|
52
|
+
ffmpegPath?: string;
|
|
53
|
+
/** Onset tuning. `sampleRate` is taken from the transport, never from here. */
|
|
54
|
+
onset?: Omit<AudioOnsetDetectorOptions, 'sampleRate'>;
|
|
55
|
+
/** DI seam for tests and for hosts that supply their own transport. */
|
|
56
|
+
transportFactory?: (config: {
|
|
57
|
+
rtspUrl: string;
|
|
58
|
+
sampleRate: number;
|
|
59
|
+
maxAudioSessionsPerSource: number;
|
|
60
|
+
transport: 'tcp' | 'udp';
|
|
61
|
+
ffmpegPath?: string;
|
|
62
|
+
}) => AudioOnsetTransport;
|
|
63
|
+
/** Observability hook — fires for every onset, per feed. */
|
|
64
|
+
onOnset?: (feedName: string, event: AudioOnsetEvent) => void;
|
|
65
|
+
onLog?: (level: 'debug' | 'info' | 'warn' | 'error', message: string) => void;
|
|
66
|
+
}
|
|
67
|
+
export interface AudioOnsetAttachment {
|
|
68
|
+
readonly feedName: string;
|
|
69
|
+
/** Onsets reported since attach. */
|
|
70
|
+
onsetCount(): number;
|
|
71
|
+
/** Current detector state (calibration, background level). */
|
|
72
|
+
detectorStats(): ReturnType<AudioOnsetDetector['getStats']>;
|
|
73
|
+
close(): Promise<void>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Open one feed's audio session and route its onsets into that feed's
|
|
77
|
+
* `MotionGate`. Returns `null` when this feed simply has no audio — which is
|
|
78
|
+
* the common case and not an error.
|
|
79
|
+
*/
|
|
80
|
+
export declare function attachAudioOnset(params: {
|
|
81
|
+
feedName: string;
|
|
82
|
+
rtspUrl: string;
|
|
83
|
+
gate: MotionGate;
|
|
84
|
+
options?: AudioSensingOptions;
|
|
85
|
+
now?: () => number;
|
|
86
|
+
}): Promise<AudioOnsetAttachment | null>;
|
|
87
|
+
//# sourceMappingURL=attachAudioOnset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachAudioOnset.d.ts","sourceRoot":"","sources":["../src/attachAudioOnset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAChH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,kFAAkF;AAClF,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,KAAK,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACvE,aAAa,IAAI,MAAM,CAAC;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,yCAAyC;IACzC,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAC1B,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,IAAI,CAAC,yBAAyB,EAAE,YAAY,CAAC,CAAC;IACtD,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE;QAC1B,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,yBAAyB,EAAE,MAAM,CAAC;QAClC,SAAS,EAAE,KAAK,GAAG,KAAK,CAAC;QACzB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,KAAK,mBAAmB,CAAC;IAC1B,4DAA4D;IAC5D,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7D,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/E;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oCAAoC;IACpC,UAAU,IAAI,MAAM,CAAC;IACrB,8DAA8D;IAC9D,aAAa,IAAI,UAAU,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC;IAC5D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAsBD;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CA8DvC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.attachAudioOnset = attachAudioOnset;
|
|
4
|
+
const AudioOnsetDetector_1 = require("./AudioOnsetDetector");
|
|
5
|
+
function defaultTransportFactory(config) {
|
|
6
|
+
// require() so the platform package stays an OPTIONAL dependency, exactly as
|
|
7
|
+
// the camera factory does. A host without it loses audio, never frames.
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
9
|
+
const { RTSPAudioProvider } = require('@trillboards/edge-platform-rtsp');
|
|
10
|
+
return new RTSPAudioProvider({
|
|
11
|
+
rtspUrl: config.rtspUrl,
|
|
12
|
+
sampleRate: config.sampleRate,
|
|
13
|
+
maxAudioSessionsPerSource: config.maxAudioSessionsPerSource,
|
|
14
|
+
transport: config.transport,
|
|
15
|
+
ffmpegPath: config.ffmpegPath,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Open one feed's audio session and route its onsets into that feed's
|
|
20
|
+
* `MotionGate`. Returns `null` when this feed simply has no audio — which is
|
|
21
|
+
* the common case and not an error.
|
|
22
|
+
*/
|
|
23
|
+
async function attachAudioOnset(params) {
|
|
24
|
+
const { feedName, rtspUrl, gate } = params;
|
|
25
|
+
const options = params.options ?? {};
|
|
26
|
+
if (options.enabled !== true)
|
|
27
|
+
return null;
|
|
28
|
+
if (!rtspUrl)
|
|
29
|
+
return null;
|
|
30
|
+
const sampleRate = options.sampleRate ?? 16000;
|
|
31
|
+
const factory = options.transportFactory ?? defaultTransportFactory;
|
|
32
|
+
let transport;
|
|
33
|
+
try {
|
|
34
|
+
transport = factory({
|
|
35
|
+
rtspUrl,
|
|
36
|
+
sampleRate,
|
|
37
|
+
maxAudioSessionsPerSource: options.maxAudioSessionsPerSource ?? 1,
|
|
38
|
+
transport: options.transport ?? 'tcp',
|
|
39
|
+
ffmpegPath: options.ffmpegPath,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
options.onLog?.('warn', `audio transport unavailable for ${feedName}: ${describe(err)}`);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const detector = new AudioOnsetDetector_1.AudioOnsetDetector({
|
|
47
|
+
...(options.onset ?? {}),
|
|
48
|
+
sampleRate: transport.getSampleRate(),
|
|
49
|
+
now: params.now,
|
|
50
|
+
});
|
|
51
|
+
let onsets = 0;
|
|
52
|
+
const unsubscribe = transport.onPcm((pcm, atMs) => {
|
|
53
|
+
for (const event of detector.push(pcm, atMs)) {
|
|
54
|
+
onsets += 1;
|
|
55
|
+
// THE SEAM. The gate is sampled on the scan cadence; the onset is
|
|
56
|
+
// recorded when it HAPPENS and carries the next look. Nothing here
|
|
57
|
+
// touches the cadence.
|
|
58
|
+
gate.noteAudioOnset(atMs);
|
|
59
|
+
options.onOnset?.(feedName, event);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
try {
|
|
63
|
+
await transport.open();
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
// Admission refused, no audio track, no ffmpeg — all the same answer to the
|
|
67
|
+
// caller: this feed has no audio, and the camera is unaffected.
|
|
68
|
+
unsubscribe();
|
|
69
|
+
await transport.close().catch(() => undefined);
|
|
70
|
+
options.onLog?.('info', `no audio on ${feedName}: ${describe(err)}`);
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
options.onLog?.('info', `audio sensing attached to ${feedName}`);
|
|
74
|
+
return {
|
|
75
|
+
feedName,
|
|
76
|
+
onsetCount: () => onsets,
|
|
77
|
+
detectorStats: () => detector.getStats(),
|
|
78
|
+
close: async () => {
|
|
79
|
+
unsubscribe();
|
|
80
|
+
await transport.close().catch(() => undefined);
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function describe(err) {
|
|
85
|
+
return err instanceof Error ? err.message : String(err);
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=attachAudioOnset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachAudioOnset.js","sourceRoot":"","sources":["../src/attachAudioOnset.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -224,10 +224,26 @@ export interface EdgeAgentConfig {
|
|
|
224
224
|
/** Moving fraction treated as a lighting event, not motion. Default 0.8. */
|
|
225
225
|
lightningThreshold?: number;
|
|
226
226
|
/**
|
|
227
|
-
*
|
|
228
|
-
* through — a parked car
|
|
229
|
-
*
|
|
230
|
-
*
|
|
227
|
+
* How long same-place motion is suppressed before one verdict is let
|
|
228
|
+
* through, in MILLISECONDS — a parked car, a swinging sign or a display
|
|
229
|
+
* screen costs one analysis per window instead of one per look. Default
|
|
230
|
+
* 300000 (5 min). 0 disables suppression.
|
|
231
|
+
*
|
|
232
|
+
* This replaced the frame COUNT `stationaryReanalyzeEvery` on 2026-08-18,
|
|
233
|
+
* because a frame count silently couples suppression strength to the look
|
|
234
|
+
* cadence: ten suppressions span 300 s at a 30 s scan and 20 s at a 2 s
|
|
235
|
+
* scan, so looking more often multiplied the analyses a motionless-but-
|
|
236
|
+
* moving scene costs. Measured on real CCTV frames through the real gate,
|
|
237
|
+
* a fixed region of repeating motion cost 13 analyses/hour at 30 s and 120
|
|
238
|
+
* at 1 s under the frame count, and 13 at every cadence under this one.
|
|
239
|
+
*/
|
|
240
|
+
stationaryReanalyzeAfterMs?: number;
|
|
241
|
+
/**
|
|
242
|
+
* @deprecated Superseded by `stationaryReanalyzeAfterMs`. Still honoured:
|
|
243
|
+
* `CloudSensingManager` multiplies it by the resolved scan interval, which
|
|
244
|
+
* is the only place that knows both, so an existing connector config keeps
|
|
245
|
+
* meaning what it meant. Prefer the duration — a count re-interprets itself
|
|
246
|
+
* every time the look cadence moves.
|
|
231
247
|
*/
|
|
232
248
|
stationaryReanalyzeEvery?: number;
|
|
233
249
|
};
|
|
@@ -248,6 +264,52 @@ export interface EdgeAgentConfig {
|
|
|
248
264
|
* Every bound is enforced on the way in and every drop is counted
|
|
249
265
|
* (`getSensingHealth().candidateBuffer`, and the operator capacity line).
|
|
250
266
|
*/
|
|
267
|
+
/**
|
|
268
|
+
* ACOUSTIC SENSING — a microphone catches what a camera has nothing to show
|
|
269
|
+
* for (a freezer door left open behind a shelf, glass breaking off frame,
|
|
270
|
+
* an alarm next door), so an onset carries a frame the motion cascade would
|
|
271
|
+
* have dropped as `no_motion`.
|
|
272
|
+
*
|
|
273
|
+
* OFF UNLESS SET, and that default is a CONSENT position rather than a
|
|
274
|
+
* rollout setting: many US states are all-party-consent for AUDIO, and
|
|
275
|
+
* these are the customer's cameras, installed and papered for video.
|
|
276
|
+
* Turning this on changes what the product does to the people in that
|
|
277
|
+
* venue, so it has to be somebody's explicit decision — never a default
|
|
278
|
+
* that arrives with an upgrade.
|
|
279
|
+
*
|
|
280
|
+
* Requires `motionGate` to be on: the onset's only effect is on a gate
|
|
281
|
+
* verdict, so with no cascade there is nothing to notify.
|
|
282
|
+
*/
|
|
283
|
+
audioSensing?: {
|
|
284
|
+
/** Default: FALSE. See above — this is a consent decision. */
|
|
285
|
+
enabled?: boolean;
|
|
286
|
+
/** Capture sample rate (Hz). Default 16000, mono. */
|
|
287
|
+
sampleRate?: number;
|
|
288
|
+
/**
|
|
289
|
+
* Long-lived audio sessions per PHYSICAL RECORDER (`host:port`). Default
|
|
290
|
+
* 1. This is a pool SEPARATE from video pulls, so audio can never consume
|
|
291
|
+
* a frame-capture slot; the cap is what stops a 32-channel NVR opening 32
|
|
292
|
+
* never-exiting ffmpeg sessions. Raise only against a measured recorder.
|
|
293
|
+
*/
|
|
294
|
+
maxAudioSessionsPerSource?: number;
|
|
295
|
+
/** RTSP transport for the audio pull. Default 'tcp'. */
|
|
296
|
+
transport?: 'tcp' | 'udp';
|
|
297
|
+
/** Onset detector tuning. Sample rate comes from the transport. */
|
|
298
|
+
onset?: {
|
|
299
|
+
/** dB above the rolling background that counts as an onset. Default 12. */
|
|
300
|
+
thresholdDb?: number;
|
|
301
|
+
/** Loudness must persist this long to fire (ms). Default 40. */
|
|
302
|
+
minDurationMs?: number;
|
|
303
|
+
/** Minimum gap between reported onsets (ms). Default 3000. */
|
|
304
|
+
refractoryMs?: number;
|
|
305
|
+
/** Hops before the background is trusted. Default 50 (=1 s). */
|
|
306
|
+
calibrationFrames?: number;
|
|
307
|
+
/** Sustained loudness is absorbed after this long (ms). Default 4000. */
|
|
308
|
+
backgroundAbsorbAfterMs?: number;
|
|
309
|
+
/** Absolute floor (dBFS) below which nothing fires. Default -55. */
|
|
310
|
+
minLevelDbfs?: number;
|
|
311
|
+
};
|
|
312
|
+
};
|
|
251
313
|
candidateBuffer?: {
|
|
252
314
|
/** Default: true wherever the motion cascade is on. */
|
|
253
315
|
enabled?: boolean;
|
|
@@ -276,6 +338,23 @@ export interface EdgeAgentConfig {
|
|
|
276
338
|
* derived value as `admissionRetryDelayMs` (250…5000).
|
|
277
339
|
*/
|
|
278
340
|
pumpIntervalMs?: number;
|
|
341
|
+
/** Durable local evidence spool (enabled automatically by local sensing). */
|
|
342
|
+
diskSpool?: {
|
|
343
|
+
enabled?: boolean;
|
|
344
|
+
directory?: string;
|
|
345
|
+
/** Default 4096 persisted candidates. */
|
|
346
|
+
maxFrames?: number;
|
|
347
|
+
/** Default 128 persisted candidates per feed. */
|
|
348
|
+
maxPerFeed?: number;
|
|
349
|
+
/** Default 536870912 (512 MiB). */
|
|
350
|
+
maxBytes?: number;
|
|
351
|
+
/** Default 86400000 (24 hours). */
|
|
352
|
+
retentionMs?: number;
|
|
353
|
+
/** Default 5000. */
|
|
354
|
+
retryInitialMs?: number;
|
|
355
|
+
/** Default 300000. */
|
|
356
|
+
retryMaxMs?: number;
|
|
357
|
+
};
|
|
279
358
|
};
|
|
280
359
|
};
|
|
281
360
|
localSensing?: {
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -48,9 +48,18 @@
|
|
|
48
48
|
* is both cheaper and far tighter — 6.0-7.5 s — which is a second,
|
|
49
49
|
* independent reason the two products should not share a cadence.)
|
|
50
50
|
*
|
|
51
|
-
* LOOKING
|
|
52
|
-
*
|
|
53
|
-
*
|
|
51
|
+
* LOOKING costs almost no CPU — 3.6 ms median / 7.1 ms p95 to pull a frame
|
|
52
|
+
* down to ~178x100 grey and run the motion detector, so sixteen
|
|
53
|
+
* feeds looking every 30 s is 0.19% of one core.
|
|
54
|
+
*
|
|
55
|
+
* CORRECTED 2026-08-18: that is the cost AFTER the frame is in
|
|
56
|
+
* hand, and it is NOT the cost of a look. `buildCaptureArgs` spawns
|
|
57
|
+
* one ffmpeg per grab with `-frames:v 1`, so every look also pays a
|
|
58
|
+
* process start, an RTSP handshake and a wait for the next
|
|
59
|
+
* keyframe. Measured through the shipped provider: p50 1 999 ms at
|
|
60
|
+
* a 2 s keyframe interval, 4 005 ms at 4 s. Looking is CHEAP IN CPU
|
|
61
|
+
* and EXPENSIVE IN WALL CLOCK, and it is the wall clock that bounds
|
|
62
|
+
* the cadence — see MEASURED_LOOK_MS and lookIntervalMsForFeedCount.
|
|
54
63
|
*
|
|
55
64
|
* FLOOR on a still scene the motion gate contributes exactly ZERO
|
|
56
65
|
* analyses — verified across byte-identical frames and gaussian
|
|
@@ -73,8 +82,11 @@
|
|
|
73
82
|
* would degrade into reporting empty aisles on time while missing the incident.
|
|
74
83
|
*
|
|
75
84
|
* Two clamps, both from values the system already declares:
|
|
76
|
-
* - never faster than
|
|
77
|
-
*
|
|
85
|
+
* - never faster than MIN_ANALYZE_INTERVAL_MS (30 s). This clamp used to read
|
|
86
|
+
* "never faster than the LOOK interval", which was the same 30 s constant;
|
|
87
|
+
* the two split on 2026-08-18 and this one is the ANALYZE floor. You still
|
|
88
|
+
* cannot analyze more often than you look, but the look cadence is now the
|
|
89
|
+
* faster of the two, so it is no longer what binds here.
|
|
78
90
|
* - never slower than the DOOH default (300 s): this can only make a
|
|
79
91
|
* connector sample MORE often than it does today, never less.
|
|
80
92
|
*
|
|
@@ -105,10 +117,161 @@ export declare const MEASURED_LOCAL_ANALYZE_MS = 7300;
|
|
|
105
117
|
*/
|
|
106
118
|
export declare const STILL_FLOOR_SLOT_SHARE = 0.5;
|
|
107
119
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
120
|
+
* ── Two cadences, two different machines ───────────────────────────────────
|
|
121
|
+
*
|
|
122
|
+
* After the 2026-08-18 split, the connector's two cadences are bounded by two
|
|
123
|
+
* DIFFERENT pieces of hardware, and that is why they cannot share a constant:
|
|
124
|
+
*
|
|
125
|
+
* ANALYZE is bounded by the BOX. `MEASURED_LOCAL_ANALYZE_MS` is one machine's
|
|
126
|
+
* per-frame inference cost, and it varies by ~7x across the machines
|
|
127
|
+
* this ships on. `periodicIntervalMsForFeedCount` derives the
|
|
128
|
+
* still-scene heartbeat from it, so a slower box automatically gets a
|
|
129
|
+
* slower heartbeat with no other change.
|
|
130
|
+
*
|
|
131
|
+
* LOOK is bounded by the RECORDER. `MEASURED_LOOK_MS` is an ffmpeg spawn
|
|
132
|
+
* plus an RTSP handshake plus a wait for the camera's next keyframe;
|
|
133
|
+
* none of that is inference and none of it moves when the box gets
|
|
134
|
+
* faster. `lookIntervalMsForFeedCount` derives it from the recorder's
|
|
135
|
+
* capture concurrency.
|
|
136
|
+
*
|
|
137
|
+
* So the look cadence below is NOT a function of the box, and does not need a
|
|
138
|
+
* hardware caveat. Re-measure it when the CAPTURE PATH changes — a persistent
|
|
139
|
+
* RTSP session instead of one process per grab would move it by an order of
|
|
140
|
+
* magnitude, and is the only thing that would.
|
|
141
|
+
*/
|
|
142
|
+
/**
|
|
143
|
+
* The fastest a connector may ANALYZE one feed, in ms.
|
|
144
|
+
*
|
|
145
|
+
* SEPARATE FROM `LOOK_INTERVAL_MS` since 2026-08-18, and the separation is the
|
|
146
|
+
* whole point. Both were 30 000 and one constant did both jobs, so nothing
|
|
147
|
+
* anywhere distinguished "how often do we look at the scene" from "how often
|
|
148
|
+
* may we spend an inference on it" — and the look cadence could not be lowered
|
|
149
|
+
* without dragging the analyze floor down with it and multiplying VLM volume on
|
|
150
|
+
* a 493/hour ceiling.
|
|
151
|
+
*
|
|
152
|
+
* 30 s is not a fresh judgement; it is the value the system already declares in
|
|
153
|
+
* two independent places, now named once:
|
|
154
|
+
* - `faceTriggeredIntervalMs` (`DEFAULT_FACE_MS`, 30 s) is the default for
|
|
155
|
+
* `MotionGate.minAnalyzeIntervalMs` — the floor between two motion-driven
|
|
156
|
+
* analyses of one feed.
|
|
157
|
+
* - `vision_pacing_config.daily_limit_per_screen` is 2 880 for the connector
|
|
158
|
+
* fleet, i.e. 86 400 / 2 880 = one analysis per 30 s, enforced server-side.
|
|
159
|
+
*
|
|
160
|
+
* So a connector that analyzed faster than this would be throttled by the
|
|
161
|
+
* server anyway. Lowering the LOOK cadence must not move this number, and the
|
|
162
|
+
* `analyzeFloorUnmovedByLookCadence` test asserts exactly that.
|
|
163
|
+
*/
|
|
164
|
+
export declare const MIN_ANALYZE_INTERVAL_MS = 30000;
|
|
165
|
+
/**
|
|
166
|
+
* Measured wall-clock cost of ONE LOOK, in ms — a real RTSP grab, not the
|
|
167
|
+
* decode-and-detect that follows it.
|
|
168
|
+
*
|
|
169
|
+
* The cascade budget above quotes 3.6 ms for a look. That is the cost AFTER the
|
|
170
|
+
* frame is in hand: pull it down to ~178x100 grey and run the detector. Getting
|
|
171
|
+
* it in hand is a different order of magnitude, because `buildCaptureArgs`
|
|
172
|
+
* spawns ONE ffmpeg per grab with `-frames:v 1` and no `-ss`, so every look pays
|
|
173
|
+
* a process start, a full RTSP DESCRIBE/SETUP/PLAY handshake, and a wait for the
|
|
174
|
+
* next keyframe before anything can be decoded.
|
|
175
|
+
*
|
|
176
|
+
* MEASURED 2026-08-18 through the shipped `RTSPCameraProvider` against mediamtx
|
|
177
|
+
* re-streaming a real CCTV clip at the documented degraded profile
|
|
178
|
+
* (640x360 / 399 kbps), one feed, no contention, p50 of 8 grabs:
|
|
179
|
+
*
|
|
180
|
+
* keyframe interval p50 grab
|
|
181
|
+
* 1 s 1 986 ms
|
|
182
|
+
* 2 s 1 999 - 2 025 ms
|
|
183
|
+
* 4 s 4 005 ms
|
|
184
|
+
*
|
|
185
|
+
* So the cost is `max(~2 s, keyframe interval)`. The floor is the RTSP SESSION,
|
|
186
|
+
* not the process: the same ffmpeg args against a local file complete in
|
|
187
|
+
* 20-30 ms, so ~99% of a look is DESCRIBE/SETUP/PLAY plus the wait for an IDR.
|
|
188
|
+
* That is a property of pulling one frame per session, not of the machine — a
|
|
189
|
+
* faster box does not move it, and a persistent session would remove almost all
|
|
190
|
+
* of it. 2 s is taken as the floor
|
|
191
|
+
* because it is the fastest observed and because a 1-2 s keyframe interval is
|
|
192
|
+
* the common CCTV default.
|
|
193
|
+
*
|
|
194
|
+
* This is why `lookIntervalMsForFeedCount` exists. Asking for a look cadence
|
|
195
|
+
* finer than the capture path can deliver does not produce more looks — the
|
|
196
|
+
* grabs queue on `CaptureAdmission` and `getSensingHealth()` reports a cadence
|
|
197
|
+
* the connector is not running.
|
|
110
198
|
*/
|
|
111
|
-
export declare const
|
|
199
|
+
export declare const MEASURED_LOOK_MS = 2000;
|
|
200
|
+
/**
|
|
201
|
+
* Concurrent RTSP grabs one physical recorder will take —
|
|
202
|
+
* `DEFAULT_MAX_CONCURRENT_CAPTURES_PER_SOURCE` in `RTSPCameraProvider`, which
|
|
203
|
+
* keys its admission gate on `host:port` because 32 NVR channels are usually
|
|
204
|
+
* one recorder with one session budget.
|
|
205
|
+
*
|
|
206
|
+
* Restated here rather than imported because `edge-sdk` must not depend on a
|
|
207
|
+
* platform package, and asserted against the real constant by
|
|
208
|
+
* `connectorCadence.test.ts` so the two cannot drift.
|
|
209
|
+
*
|
|
210
|
+
* Raising it does NOT buy look throughput: measured at 16 feeds on one recorder,
|
|
211
|
+
* 2 concurrent and 8 concurrent both sustained 1.00 looks/s (the per-grab p50
|
|
212
|
+
* simply rose from 9 962 ms to 9 996 ms). The recorder, not the gate, is the
|
|
213
|
+
* bound.
|
|
214
|
+
*/
|
|
215
|
+
export declare const LOOK_CAPTURE_CONCURRENCY = 2;
|
|
216
|
+
/**
|
|
217
|
+
* The look cadence this connector ran until 2026-08-18, kept ONLY as the slow
|
|
218
|
+
* clamp on `lookIntervalMsForFeedCount`.
|
|
219
|
+
*
|
|
220
|
+
* It is numerically equal to `MIN_ANALYZE_INTERVAL_MS` and that is a
|
|
221
|
+
* coincidence of history, not a relationship: they were one constant, and the
|
|
222
|
+
* whole point of the split is that they are free to move independently. Using
|
|
223
|
+
* the analyze floor here would re-create exactly the conflation this change
|
|
224
|
+
* removes — a future PR that lowers the analyze floor would silently speed up
|
|
225
|
+
* the slowest look cadence with it.
|
|
226
|
+
*
|
|
227
|
+
* Its only job is a guarantee: deriving a look cadence can make a connector look
|
|
228
|
+
* MORE often than it used to, never less. A 32-feed host cannot sustain even
|
|
229
|
+
* this (32 feeds want 1.07 looks/s against a measured 1.00), so past ~30 feeds
|
|
230
|
+
* the derivation is pinned here and the grabs queue on `CaptureAdmission` — a
|
|
231
|
+
* pre-existing capacity fact about one recorder, not something a faster look
|
|
232
|
+
* cadence introduces.
|
|
233
|
+
*/
|
|
234
|
+
export declare const LEGACY_LOOK_INTERVAL_MS = 30000;
|
|
235
|
+
/**
|
|
236
|
+
* The connector's TARGET look cadence, in ms — how often the motion gate gets a
|
|
237
|
+
* chance to see anything at all.
|
|
238
|
+
*
|
|
239
|
+
* DERIVED FROM THE CATCH-RATE EVAL, not chosen. An event is catchable only if a
|
|
240
|
+
* LOOK lands inside it, so for an event of duration `d` against an
|
|
241
|
+
* event-uncorrelated look cadence `T` the ceiling on catch rate is
|
|
242
|
+
* `E[min(d/T,1)]`. Evaluated over the whole 75,657-event corpus
|
|
243
|
+
* (`eval/sensing-event-corpus.json`), event-weighted per reporting group and
|
|
244
|
+
* UNCAPPED:
|
|
245
|
+
*
|
|
246
|
+
* T Instant Brief Sustained State
|
|
247
|
+
* 30 s 8.4% 18.6% 100% 100%
|
|
248
|
+
* 5 s 50.2% 55.1% 100% 100%
|
|
249
|
+
* 2.44 s 89.1% 71.2% 100% 100%
|
|
250
|
+
* 2 s 95.5% 75.2% 100% 100%
|
|
251
|
+
* 1 s 100.0% 86.6% 100% 100%
|
|
252
|
+
* 0.75 s 100.0% 90.1% 100% 100%
|
|
253
|
+
*
|
|
254
|
+
* Two things fall out of that table and both are load bearing:
|
|
255
|
+
*
|
|
256
|
+
* - The Instant group — "alert me if the door opens after hours", a 2.2 s
|
|
257
|
+
* median event — clears the 90% target at 2.4 s and is at 8.4% today. This
|
|
258
|
+
* is the promise the 30 s cadence was silently failing.
|
|
259
|
+
*
|
|
260
|
+
* - The Brief group does NOT reach 90% until 0.75 s, and 0.75 s is well below
|
|
261
|
+
* the measured cost of a single grab (`MEASURED_LOOK_MS`). So 90% on every
|
|
262
|
+
* shape is NOT reachable by look cadence on the current capture
|
|
263
|
+
* architecture, and this constant does not pretend otherwise. Closing that
|
|
264
|
+
* gap needs a persistent RTSP session — one long-lived ffmpeg per feed
|
|
265
|
+
* instead of one per grab — which is an architecture change, not a number.
|
|
266
|
+
*
|
|
267
|
+
* 2 000 ms is therefore the fastest cadence that is BOTH an eval output and
|
|
268
|
+
* physically deliverable: it is the measured single-grab floor, and at it the
|
|
269
|
+
* Instant group clears the target. Do not lower it without first lowering
|
|
270
|
+
* `MEASURED_LOOK_MS`, and do not raise it without re-running the replay — the
|
|
271
|
+
* `sensing-catch-rate` guard re-reads this constant and fails if it drifts from
|
|
272
|
+
* the cadence the corpus was measured at.
|
|
273
|
+
*/
|
|
274
|
+
export declare const LOOK_INTERVAL_MS = 2000;
|
|
112
275
|
/** The DOOH audience default (`DEFAULT_PERIODIC_MS`). The slow end of the clamp. */
|
|
113
276
|
export declare const DOOH_PERIODIC_MS = 300000;
|
|
114
277
|
/**
|
|
@@ -122,6 +285,28 @@ export declare const DOOH_PERIODIC_MS = 300000;
|
|
|
122
285
|
* the key entirely rather than write a cadence derived from a bad count.
|
|
123
286
|
*/
|
|
124
287
|
export declare function periodicIntervalMsForFeedCount(feedCount: unknown): number | null;
|
|
288
|
+
/**
|
|
289
|
+
* The fastest look cadence a connector running `feedCount` feeds against ONE
|
|
290
|
+
* recorder can actually SUSTAIN, in ms.
|
|
291
|
+
*
|
|
292
|
+
* Same shape as `periodicIntervalMsForFeedCount` and for the same reason: a
|
|
293
|
+
* cadence is only real if the machine can deliver it. That function divides one
|
|
294
|
+
* inference slot among N feeds; this one divides one recorder's capture
|
|
295
|
+
* capacity among N feeds.
|
|
296
|
+
*
|
|
297
|
+
* N feeds x (1 look / T) <= LOOK_CAPTURE_CONCURRENCY / MEASURED_LOOK_MS
|
|
298
|
+
* T >= N x MEASURED_LOOK_MS / LOOK_CAPTURE_CONCURRENCY
|
|
299
|
+
*
|
|
300
|
+
* Measured against that formula at 16 feeds on one recorder, GOP 2 s: predicted
|
|
301
|
+
* 16.0 s/feed, observed 16.0 s/feed.
|
|
302
|
+
*
|
|
303
|
+
* Never faster than `LOOK_INTERVAL_MS` (the eval target — looking finer than
|
|
304
|
+
* that buys nothing the corpus can see) and never slower than
|
|
305
|
+
* `LEGACY_LOOK_INTERVAL_MS`, so this can only make a connector look MORE often
|
|
306
|
+
* than it did, never less. Returns `null` on an uncountable feed count so a caller can
|
|
307
|
+
* omit the key rather than derive a cadence from nothing.
|
|
308
|
+
*/
|
|
309
|
+
export declare function lookIntervalMsForFeedCount(feedCount: unknown): number | null;
|
|
125
310
|
/**
|
|
126
311
|
* The still-scene analyses/hour a whole connector demands at a heartbeat, and
|
|
127
312
|
* what fraction of the single slot that is. Exposed so the derivation is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectorCadence.d.ts","sourceRoot":"","sources":["../src/connectorCadence.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"connectorCadence.d.ts","sourceRoot":"","sources":["../src/connectorCadence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0GG;AAEH;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,OAAQ,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,gBAAgB,OAAQ,CAAC;AAEtC;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,gBAAgB,OAAQ,CAAC;AAEtC,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,SAAU,CAAC;AAExC;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CA4BhF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAK5E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,OAAO,EAClB,kBAAkB,EAAE,OAAO,GAC1B;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAOhD"}
|