@camstack/addon-post-analysis 1.2.298 → 1.2.300
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/{clip-model-registry-D9WaswEs.mjs → clip-model-registry-B44A1-Xh.mjs} +267 -2
- package/dist/{clip-model-registry-olxNKN7T.js → clip-model-registry-BeJUe0vk.js} +380 -1
- package/dist/embedding-encoder/index.js +26 -7
- package/dist/embedding-encoder/index.mjs +26 -7
- package/dist/pipeline-analytics/_stub.js +1 -1
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-Bk7ACano.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-D_krhxwa.mjs} +1 -1
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BdQKTjgL.mjs +26 -0
- package/dist/pipeline-analytics/{hostInit-DtPqVNsM.mjs → hostInit-DbRGSQxy.mjs} +1 -1
- package/dist/pipeline-analytics/index.js +3291 -552
- package/dist/pipeline-analytics/index.mjs +3306 -568
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D1CfMkm2.mjs +0 -26
|
@@ -7660,7 +7660,7 @@ function errMsg(err) {
|
|
|
7660
7660
|
return String(err);
|
|
7661
7661
|
}
|
|
7662
7662
|
//#endregion
|
|
7663
|
-
//#region ../types/dist/composition-
|
|
7663
|
+
//#region ../types/dist/composition-Dq42XWp0.mjs
|
|
7664
7664
|
/**
|
|
7665
7665
|
* Deterministic SHA-256 hash of an arbitrary serialisable value. The
|
|
7666
7666
|
* canonical form sorts object keys alphabetically at every depth so two
|
|
@@ -7693,6 +7693,58 @@ function replaceWithSortedKeys(_key, value) {
|
|
|
7693
7693
|
return value;
|
|
7694
7694
|
}
|
|
7695
7695
|
/**
|
|
7696
|
+
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
7697
|
+
*
|
|
7698
|
+
* ## Why a download, on every node, including the container
|
|
7699
|
+
*
|
|
7700
|
+
* The version of ffmpeg used to be CODE: baked into the image, changeable only
|
|
7701
|
+
* by rebuilding and rolling it. Now it is DATA — this file states the release,
|
|
7702
|
+
* and a node that boots with a different one downloads it. Changing ffmpeg is a
|
|
7703
|
+
* framework bump, not an image rebuild.
|
|
7704
|
+
*
|
|
7705
|
+
* It also settles the licence question by removing it. FFmpeg's licence is
|
|
7706
|
+
* chosen at compile time: the core is LGPL 2.1+, `--enable-gpl` makes it GPL
|
|
7707
|
+
* (for x264/x265), `--enable-version3` makes that v3, and `--enable-nonfree`
|
|
7708
|
+
* makes the result undistributable. These are GPL v3 builds, and we do not
|
|
7709
|
+
* distribute them: the user's own node fetches the archive from the project
|
|
7710
|
+
* that publishes it, so we convey no GPL work and inherit none of the
|
|
7711
|
+
* obligations that come with conveying one. That is the whole reason the image
|
|
7712
|
+
* no longer installs ffmpeg at all — not a technical preference.
|
|
7713
|
+
*
|
|
7714
|
+
* ## Why jellyfin-ffmpeg
|
|
7715
|
+
*
|
|
7716
|
+
* One vendor covering linux-amd64, linux-arm64, darwin-arm64 and darwin-x64
|
|
7717
|
+
* from one release, with the widest hardware surface of anything maintained:
|
|
7718
|
+
* VAAPI, QSV, NVENC/NVDEC, AMF, Vulkan, OpenCL and DRM on amd64, plus Rockchip
|
|
7719
|
+
* MPP on arm64. It reaches the vendor libraries through dlopen trampolines,
|
|
7720
|
+
* so the binary is not linked against a driver stack it may not find.
|
|
7721
|
+
*
|
|
7722
|
+
* **What it still needs from the host, measured 2026-09-19.** On the Unraid
|
|
7723
|
+
* HOST, which has no libva, `-vaapi_device` aborts the process outright —
|
|
7724
|
+
* `implib-gen: libva-drm.so.2: failed to load library ... Assertion '0 &&
|
|
7725
|
+
* "Assertion in generated code"' failed`. Inside our container, which installs
|
|
7726
|
+
* libva plus the iHD driver, the same command encodes: verified end to end with
|
|
7727
|
+
* `testsrc → format=nv12,hwupload → h264_vaapi`. So the image drops ffmpeg and
|
|
7728
|
+
* KEEPS the Intel media stack; the drivers are the part a binary cannot bring.
|
|
7729
|
+
*
|
|
7730
|
+
* ## Why each artifact carries a checksum and a claim
|
|
7731
|
+
*
|
|
7732
|
+
* The download is now the only source, so `sha256` is verified before anything
|
|
7733
|
+
* is extracted — jellyfin publishes no checksums on its release assets, so
|
|
7734
|
+
* these are ours, taken at the version bump. And `expectedHwaccels` is what the
|
|
7735
|
+
* build is supposed to be able to do: a binary that probes short of its own
|
|
7736
|
+
* claim is a source that changed under us, which is precisely what went
|
|
7737
|
+
* unnoticed for months when a static build turned out to carry no VAAPI at all
|
|
7738
|
+
* (D536).
|
|
7739
|
+
*/
|
|
7740
|
+
/** The pinned jellyfin-ffmpeg release. Changing this is the version change. */
|
|
7741
|
+
var FFMPEG_RELEASE = "8.1.2-5";
|
|
7742
|
+
var BASE = `https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v${FFMPEG_RELEASE}`;
|
|
7743
|
+
function portable(target) {
|
|
7744
|
+
return `${BASE}/jellyfin-ffmpeg_${FFMPEG_RELEASE}_portable_${target}-gpl.tar.xz`;
|
|
7745
|
+
}
|
|
7746
|
+
portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
|
|
7747
|
+
/**
|
|
7696
7748
|
* LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
|
|
7697
7749
|
* valutatore puro del suo FRONTE.
|
|
7698
7750
|
*
|
|
@@ -8781,6 +8833,110 @@ var BASE_LIVE_EGRESS_PROFILE = {
|
|
|
8781
8833
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
8782
8834
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
8783
8835
|
/**
|
|
8836
|
+
* The notification GIF's filter chain and argv — ONE definition for every
|
|
8837
|
+
* process that derives a gif from a notification video.
|
|
8838
|
+
*
|
|
8839
|
+
* ## Why this lives in `@camstack/types`
|
|
8840
|
+
*
|
|
8841
|
+
* Two addons derive a notification gif from an mp4, and they may never import
|
|
8842
|
+
* each other:
|
|
8843
|
+
*
|
|
8844
|
+
* - the stream broker (`addon-pipeline`), from the clip it just cut out of its
|
|
8845
|
+
* own ring (`gif-from-mp4.ts`);
|
|
8846
|
+
* - the notification centre (`addon-post-analysis`), from a clip cut out of
|
|
8847
|
+
* the RECORDINGS when the moment is older than any ring holds
|
|
8848
|
+
* ([D682](../../../../docs/decisions/adr-0682-a-pick-ups-footage-is-cut-around-the-pick-up.md)).
|
|
8849
|
+
*
|
|
8850
|
+
* Two copies of this chain would be two gifs of the same kind of moment that
|
|
8851
|
+
* look different depending on how old the moment was — the class of defect
|
|
8852
|
+
* D85/D91 already paid for once. So the chain is here, pure and dependency
|
|
8853
|
+
* free, and each caller owns only its own process lifecycle.
|
|
8854
|
+
*
|
|
8855
|
+
* ## The palette was never the problem
|
|
8856
|
+
*
|
|
8857
|
+
* The `split` + `palettegen(stats_mode=diff)` + `paletteuse(bayer)` pair is
|
|
8858
|
+
* right and stays. The measured cause of "the gif looks de-pixellated" was a
|
|
8859
|
+
* 640×360 substream scaled DOWN to 480 px, upstream of the palette. The `split`
|
|
8860
|
+
* form is a single READ of the input, not a lesser two-pass.
|
|
8861
|
+
*/
|
|
8862
|
+
/**
|
|
8863
|
+
* Format a frame rate for an ffmpeg filter argument.
|
|
8864
|
+
*
|
|
8865
|
+
* `12 / 4` must reach the filter as `3` and `15 / 4` as `3.75`, not as a float
|
|
8866
|
+
* tail that `av_parse_video_rate` then has to guess at.
|
|
8867
|
+
*/
|
|
8868
|
+
function ffmpegRate(rate) {
|
|
8869
|
+
return String(Math.round(rate * 1e3) / 1e3);
|
|
8870
|
+
}
|
|
8871
|
+
/**
|
|
8872
|
+
* The factor the derive must apply ON TOP of the speed the mp4 already carries.
|
|
8873
|
+
*
|
|
8874
|
+
* The gif is derived from a muxed mp4, so if that mux already ran `setpts` at
|
|
8875
|
+
* the caller's `speed`, applying the absolute gif rate again would compound
|
|
8876
|
+
* them — a 4× gif beside a 2× video would come out at 8×. Discounting here is
|
|
8877
|
+
* what keeps the gif rate ABSOLUTE against real time whatever the video does.
|
|
8878
|
+
*/
|
|
8879
|
+
function gifDeriveSpeed(gifSpeed, videoSpeed) {
|
|
8880
|
+
if (!Number.isFinite(videoSpeed) || videoSpeed <= 0) return gifSpeed;
|
|
8881
|
+
return gifSpeed / videoSpeed;
|
|
8882
|
+
}
|
|
8883
|
+
/**
|
|
8884
|
+
* The filter chain. Extracted so a test can assert the palette pair without
|
|
8885
|
+
* spawning ffmpeg — an argv test cannot see quality, but it can see a filter
|
|
8886
|
+
* that somebody deleted.
|
|
8887
|
+
*
|
|
8888
|
+
* `fps` BEFORE `setpts`: decimating an already sped-up timeline yields `speed`
|
|
8889
|
+
* times the frames asked for, and a gif pays for every one. So the decimation
|
|
8890
|
+
* runs at `fps / speed` in SOURCE time and `setpts` multiplies what survived.
|
|
8891
|
+
* The trailing `fps` re-declares the rate, which is NOT redundant: `setpts`
|
|
8892
|
+
* leaves the filter link advertising the sampled rate and the gif muxer
|
|
8893
|
+
* believes the link — measured on 615 as a 3.01 s gif of ten frames.
|
|
8894
|
+
*/
|
|
8895
|
+
function gifFilterComplex(input) {
|
|
8896
|
+
const speed = input.speed > 0 ? input.speed : 1;
|
|
8897
|
+
if (speed === 1) return `[0:v]fps=${ffmpegRate(input.fps)},scale=${input.maxWidth}:-2:flags=lanczos,split[a][b];[a]palettegen=stats_mode=diff[p];[b][p]paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle`;
|
|
8898
|
+
return `[0:v]fps=${ffmpegRate(input.fps / speed)},setpts=PTS/${speed},fps=${ffmpegRate(input.fps)},scale=${input.maxWidth}:-2:flags=lanczos,split[a][b];[a]palettegen=stats_mode=diff[p];[b][p]paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle`;
|
|
8899
|
+
}
|
|
8900
|
+
/** The full argv: mp4 in, gif on stdout. */
|
|
8901
|
+
function gifFromMp4Args(input) {
|
|
8902
|
+
return [
|
|
8903
|
+
"-y",
|
|
8904
|
+
"-v",
|
|
8905
|
+
"error",
|
|
8906
|
+
"-f",
|
|
8907
|
+
"mp4",
|
|
8908
|
+
"-i",
|
|
8909
|
+
input.input ?? "pipe:0",
|
|
8910
|
+
"-filter_complex",
|
|
8911
|
+
gifFilterComplex(input),
|
|
8912
|
+
"-loop",
|
|
8913
|
+
"0",
|
|
8914
|
+
"-f",
|
|
8915
|
+
"gif",
|
|
8916
|
+
"pipe:1"
|
|
8917
|
+
];
|
|
8918
|
+
}
|
|
8919
|
+
/**
|
|
8920
|
+
* Memoize `ensure` on SUCCESS only.
|
|
8921
|
+
*
|
|
8922
|
+
* A failure is not remembered: the next caller asks again, so a node whose
|
|
8923
|
+
* first download failed (no network at boot) recovers on the next spawn that
|
|
8924
|
+
* needs it — with no timer and no retry loop, because the ask is driven by
|
|
8925
|
+
* work that actually wants the binary.
|
|
8926
|
+
*/
|
|
8927
|
+
function memoizePinnedFfmpeg(ensure) {
|
|
8928
|
+
let pending = null;
|
|
8929
|
+
return () => {
|
|
8930
|
+
if (pending !== null) return pending;
|
|
8931
|
+
const attempt = ensure();
|
|
8932
|
+
pending = attempt;
|
|
8933
|
+
attempt.catch(() => {
|
|
8934
|
+
if (pending === attempt) pending = null;
|
|
8935
|
+
});
|
|
8936
|
+
return attempt;
|
|
8937
|
+
};
|
|
8938
|
+
}
|
|
8939
|
+
/**
|
|
8784
8940
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
8785
8941
|
* every declared capability + widget of every installed plugin, on every
|
|
8786
8942
|
* node. Produced by the backend `WiringHealthService` and surfaced via
|
|
@@ -9195,6 +9351,8 @@ var DETECTION_PIPELINE_CAP_NAME = "detection-pipeline";
|
|
|
9195
9351
|
* oldest-first on append.
|
|
9196
9352
|
*/
|
|
9197
9353
|
var MAX_BIRTH_DECISION_RECORDS = 3e4;
|
|
9354
|
+
/** Default page size for `listBirthDecisions` when the caller omits one. */
|
|
9355
|
+
var BIRTH_DECISION_DEFAULT_LIMIT = 500;
|
|
9198
9356
|
/**
|
|
9199
9357
|
* How stale a motion onset may be and still be offered as the birth-latency
|
|
9200
9358
|
* proxy. Beyond this the row records `null`, never a large number.
|
|
@@ -9407,6 +9565,8 @@ var BirthDecisionQueryInputSchema = object({
|
|
|
9407
9565
|
* `tracks` table measured at 4.6 MB for a single 501-row page.
|
|
9408
9566
|
*/
|
|
9409
9567
|
var MAX_ARCHIVED_DEBUG_NOTES = 5e3;
|
|
9568
|
+
/** Default page size for `listArchivedDebugNotes` when the caller omits one. */
|
|
9569
|
+
var ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT = 200;
|
|
9410
9570
|
/** One archived note — the operator's words plus enough context to find what
|
|
9411
9571
|
* they were looking at, after the track itself is gone. */
|
|
9412
9572
|
var ArchivedDebugNoteSchema = object({
|
|
@@ -9496,6 +9656,8 @@ var OpsLogQueryInputSchema = object({
|
|
|
9496
9656
|
/** Max rows returned, newest-first. */
|
|
9497
9657
|
limit: number().int().min(1).max(1e3).optional()
|
|
9498
9658
|
});
|
|
9659
|
+
/** Default page size for a `listOpsLog` query when the caller omits `limit`. */
|
|
9660
|
+
var OPS_LOG_DEFAULT_LIMIT = 200;
|
|
9499
9661
|
var LabelDefinitionSchema = object({
|
|
9500
9662
|
id: string(),
|
|
9501
9663
|
name: string(),
|
|
@@ -19111,6 +19273,12 @@ var NC_TANK_SYSTEM_EVENT_KINDS = [
|
|
|
19111
19273
|
"device-tank-normal"
|
|
19112
19274
|
];
|
|
19113
19275
|
/**
|
|
19276
|
+
* The consumable threshold a rule that does not state one judges at (D642).
|
|
19277
|
+
* The operator's number ("default 15 %, configurable on the rule"), and the
|
|
19278
|
+
* value the cluster-wide setting it replaces shipped with.
|
|
19279
|
+
*/
|
|
19280
|
+
var NC_CONSUMABLE_LOW_PERCENT_DEFAULT = 15;
|
|
19281
|
+
/**
|
|
19114
19282
|
* One coherent system-event condition. `kinds` is the required opt-in safety
|
|
19115
19283
|
* gate; the remaining lists are optional narrowing filters relevant to the
|
|
19116
19284
|
* selected kinds.
|
|
@@ -19803,6 +19971,24 @@ var NcMediaFrameSchema = _enum([
|
|
|
19803
19971
|
* sensor linked to one camera ships that camera's plain snapshot either way.
|
|
19804
19972
|
*/
|
|
19805
19973
|
var NcLinkedCameraModeSchema = _enum(["mosaic", "each"]);
|
|
19974
|
+
/**
|
|
19975
|
+
* The clip window a rule gets when it stores no `clipPreRollSec` /
|
|
19976
|
+
* `clipPostRollSec` (D654): 4 s before the moment, 6 s after.
|
|
19977
|
+
*
|
|
19978
|
+
* THE one owner. The Notification Center resolves an absent roll to these at
|
|
19979
|
+
* dispatch and sizes the broker's clip ring from them (`clip-retention-ask`).
|
|
19980
|
+
* The admin editor does not author the roll; the viewer editor still keeps its
|
|
19981
|
+
* own 3 / 7 until it imports these (viewer follow-up). A second copy is how the
|
|
19982
|
+
* viewer came to display 3 / 7 — copied from a stale comment on the schema
|
|
19983
|
+
* below — while the hub cut 4 / 6, and to prune a typed 3 back to "absent",
|
|
19984
|
+
* which the hub then read as 4.
|
|
19985
|
+
*
|
|
19986
|
+
* A product decision of the notification, not the broker's history window
|
|
19987
|
+
* (D381/D382): the clip is cut from the broker's per-camera clip ring, which
|
|
19988
|
+
* the rules size, not from a pre-roll dial.
|
|
19989
|
+
*/
|
|
19990
|
+
var NC_CLIP_PRE_ROLL_DEFAULT_SEC = 4;
|
|
19991
|
+
var NC_CLIP_POST_ROLL_DEFAULT_SEC = 6;
|
|
19806
19992
|
var NcMediaPolicySchema = object({
|
|
19807
19993
|
attach: _enum([
|
|
19808
19994
|
"best",
|
|
@@ -21335,6 +21521,24 @@ var NcAlarmConfigSchema = object({
|
|
|
21335
21521
|
live: NcAlarmLiveSchema.optional()
|
|
21336
21522
|
});
|
|
21337
21523
|
/**
|
|
21524
|
+
* The most seconds of footage any notification rule may ask a camera to retain.
|
|
21525
|
+
*
|
|
21526
|
+
* Sixty, and it is the OCCUPANCY number. An occupancy edge is confirmed by an
|
|
21527
|
+
* independent read that lands long after the fact (D279) plus the condition's
|
|
21528
|
+
* own `sustainSeconds` (29 s on this hub), so its clip is anchored well in the
|
|
21529
|
+
* past — and the other source, the recordings, cannot cover a recent moment:
|
|
21530
|
+
* measured against `recording.getAvailability` for a 10 s window at several
|
|
21531
|
+
* anchors, full coverage arrived at −18 s on device 590 and −26 s on 615 and
|
|
21532
|
+
* 617. That edge is a PHASE of the 10-second segment cycle, not a number. The
|
|
21533
|
+
* ring therefore has to hold the moment until the recordings can take it over:
|
|
21534
|
+
* the worst measured phase (26 s) plus the confirmation lag (29 s) is 55 s, and
|
|
21535
|
+
* 60 is the round number above it.
|
|
21536
|
+
*
|
|
21537
|
+
* It is a ceiling, not a default. Every other rule kind asks for its own window
|
|
21538
|
+
* plus the dispatch margin, which is roughly a third of this.
|
|
21539
|
+
*/
|
|
21540
|
+
var NC_CLIP_RETENTION_MAX_SEC = 60;
|
|
21541
|
+
/**
|
|
21338
21542
|
* ONE rule's demand on ONE camera's clip ring.
|
|
21339
21543
|
*
|
|
21340
21544
|
* A rule, not a camera: the broker takes the MAX over the asks that reach a
|
|
@@ -23012,6 +23216,21 @@ var ObjectEventSchema = object({
|
|
|
23012
23216
|
keyFrameMediaId: number().int().optional(),
|
|
23013
23217
|
/** Populated by B5 (recording playback URL for this event). */
|
|
23014
23218
|
mediaUrl: string().optional(),
|
|
23219
|
+
/**
|
|
23220
|
+
* When the change this row records HAPPENED, epoch ms, when that is earlier
|
|
23221
|
+
* than {@link timestamp} and the producer could date it (D684).
|
|
23222
|
+
*
|
|
23223
|
+
* Set on a package PICK-UP row only: its `timestamp` is when the departure
|
|
23224
|
+
* was CONCLUDED — five minutes of unseen observed time after the parcel went
|
|
23225
|
+
* — and a notification's footage has to be cut around the pick-up, not the
|
|
23226
|
+
* empty doormat after it (D682). Stored so every path that rebuilds a
|
|
23227
|
+
* notification subject from the row (the boot reconcile, a dry-run) anchors
|
|
23228
|
+
* on the same instant the live hook did.
|
|
23229
|
+
*
|
|
23230
|
+
* `timestamp` keeps its meaning. Absent on every other row and on every
|
|
23231
|
+
* pick-up written before D684 — UNKNOWN, never 0 and never `timestamp`.
|
|
23232
|
+
*/
|
|
23233
|
+
observedAt: number().optional(),
|
|
23015
23234
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
23016
23235
|
* event of the track (so an event row can be sorted by importance without a
|
|
23017
23236
|
* track join). Absent on legacy rows / before the track was scored. */
|
|
@@ -23427,6 +23646,21 @@ var EventDensityBucketSchema = object({
|
|
|
23427
23646
|
audioDbfs: number().optional()
|
|
23428
23647
|
});
|
|
23429
23648
|
/**
|
|
23649
|
+
* Most cameras one `getEventDensityBatch` may name.
|
|
23650
|
+
*
|
|
23651
|
+
* The same ceiling the sibling batches on this cap already carry
|
|
23652
|
+
* (`listEventKindsBatch`, `getKeyEventsBatch`): a tablet grid is tens of
|
|
23653
|
+
* cameras, never hundreds, and one call's answer is N × (window / bucketMs)
|
|
23654
|
+
* buckets crossing a process boundary.
|
|
23655
|
+
*
|
|
23656
|
+
* The ceiling is on the SCHEMA, not only on the caller. An over-eager ask is
|
|
23657
|
+
* REFUSED — never truncated to the first {@link EVENT_DENSITY_BATCH_MAX} ids,
|
|
23658
|
+
* because that answer is indistinguishable from a complete one and the caller
|
|
23659
|
+
* would never learn it asked too much. A caller with more cameras sends
|
|
23660
|
+
* ⌈n/max⌉ calls.
|
|
23661
|
+
*/
|
|
23662
|
+
var EVENT_DENSITY_BATCH_MAX = 200;
|
|
23663
|
+
/**
|
|
23430
23664
|
* One camera's row in a `getEventDensityBatch` answer.
|
|
23431
23665
|
*
|
|
23432
23666
|
* TWO facts, and the timeline draws them differently:
|
|
@@ -37575,6 +37809,16 @@ var ExportDenseRangeSchema = object({
|
|
|
37575
37809
|
toSec: number().nonnegative()
|
|
37576
37810
|
}).refine((r) => r.toSec > r.fromSec, { message: "dense range must have toSec > fromSec" });
|
|
37577
37811
|
/**
|
|
37812
|
+
* Hard ceiling on dense ranges in ONE render.
|
|
37813
|
+
*
|
|
37814
|
+
* The ranges become terms of a single ffmpeg `select` expression, so the count
|
|
37815
|
+
* is the length of a command-line argument. The producer (the timelapse
|
|
37816
|
+
* scheduler) coalesces and then falls back to the base cadence alone rather
|
|
37817
|
+
* than trimming — a truncated range list is a video that quietly omits the
|
|
37818
|
+
* evening.
|
|
37819
|
+
*/
|
|
37820
|
+
var EXPORT_DENSE_MAX_RANGES = 200;
|
|
37821
|
+
/**
|
|
37578
37822
|
* Dense-interval overlay for a timelapse: sample at `dense.everyMs` INSIDE the
|
|
37579
37823
|
* listed ranges and at the base `everyMs` everywhere else.
|
|
37580
37824
|
*
|
|
@@ -38396,11 +38640,23 @@ var SceneCheckSchema = discriminatedUnion("mode", [object({
|
|
|
38396
38640
|
profileId: string().optional(),
|
|
38397
38641
|
hysteresisCount: number().int().positive()
|
|
38398
38642
|
})]);
|
|
38643
|
+
/** Defaults, as CONSTANTS rather than only as Zod `.default()`. A Zod default
|
|
38644
|
+
* does NOT run on the addon→addon cap path, so every runtime seam reads these
|
|
38645
|
+
* as absent-with-a-constant (the `NcConfirmSchema` lesson, three production
|
|
38646
|
+
* failures in one day). The schema defaults and these values are the same
|
|
38647
|
+
* numbers on purpose. */
|
|
38648
|
+
var SCENE_DEFAULT_QUIET_SECONDS = 60;
|
|
38649
|
+
var SCENE_DEFAULT_OBSERVATION_SPACING_SEC = 120;
|
|
38650
|
+
var SCENE_DEFAULT_CHECK_INTERVAL_SEC = 60;
|
|
38399
38651
|
var SCENE_DEFAULT_ANCHOR_THRESHOLD = .85;
|
|
38400
38652
|
/** Night is OPTIONAL. A scene with only a daylight reference sits the IR hours
|
|
38401
38653
|
* out in silence rather than reporting a fault every night. */
|
|
38402
38654
|
var SCENE_DEFAULT_UNCOVERED_POLICY = "skip";
|
|
38403
38655
|
var SCENE_CONFIRM_DEFAULT_TIMEOUT_MS = 8e3;
|
|
38656
|
+
var SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX = 448;
|
|
38657
|
+
/** `resetScene({ recapture })` absent means TRUE — the operator decision. Read
|
|
38658
|
+
* at the seam, because a Zod `.optional()` carries no default at all. */
|
|
38659
|
+
var SCENE_RESET_RECAPTURES = true;
|
|
38404
38660
|
/**
|
|
38405
38661
|
* Vision-model adjudication of a candidate flip. Field names deliberately
|
|
38406
38662
|
* mirror `NcConfirmSchema` so an operator meets one vocabulary, not two.
|
|
@@ -52476,6 +52732,15 @@ function ituDbfsFromPreEpoch(law, authoredDbfs) {
|
|
|
52476
52732
|
return authoredDbfs + G711_SCALE_CORRECTION_DB[law];
|
|
52477
52733
|
}
|
|
52478
52734
|
Math.round(ituDbfsFromPreEpoch("PCMU", -55));
|
|
52735
|
+
/**
|
|
52736
|
+
* LABEL-mode confirm-count defaults. Chosen against the live "Pianti" rule
|
|
52737
|
+
* (2026-08-23): 15 notifies in 12 h, each a single YAMNet `crying` frame,
|
|
52738
|
+
* nobody actually crying. Two labelled frames in 5 s drops the single-frame
|
|
52739
|
+
* false positives and still catches a real episode (YAMNet labels 2–3
|
|
52740
|
+
* frames of a genuine cry).
|
|
52741
|
+
*/
|
|
52742
|
+
var NC_AUDIO_CONFIRM_HITS_DEFAULT = 2;
|
|
52743
|
+
var NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT = 5;
|
|
52479
52744
|
/** Schema defaults — an untouched sub-field must author exactly these. */
|
|
52480
52745
|
var NC_AUDIO_DEFAULTS = {
|
|
52481
52746
|
hitPercent: 60,
|
|
@@ -55283,6 +55548,12 @@ function buildClipModelRegistry(entries) {
|
|
|
55283
55548
|
/** The built-in catalog's registry. */
|
|
55284
55549
|
var BUILTIN_CLIP_MODELS = buildClipModelRegistry(CLIP_IMAGE_MODELS);
|
|
55285
55550
|
//#endregion
|
|
55551
|
+
Object.defineProperty(exports, "ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT", {
|
|
55552
|
+
enumerable: true,
|
|
55553
|
+
get: function() {
|
|
55554
|
+
return ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT;
|
|
55555
|
+
}
|
|
55556
|
+
});
|
|
55286
55557
|
Object.defineProperty(exports, "AUDIO_MACRO_LABELS", {
|
|
55287
55558
|
enumerable: true,
|
|
55288
55559
|
get: function() {
|
|
@@ -55301,6 +55572,12 @@ Object.defineProperty(exports, "ArchivedDebugNoteSchema", {
|
|
|
55301
55572
|
return ArchivedDebugNoteSchema;
|
|
55302
55573
|
}
|
|
55303
55574
|
});
|
|
55575
|
+
Object.defineProperty(exports, "BIRTH_DECISION_DEFAULT_LIMIT", {
|
|
55576
|
+
enumerable: true,
|
|
55577
|
+
get: function() {
|
|
55578
|
+
return BIRTH_DECISION_DEFAULT_LIMIT;
|
|
55579
|
+
}
|
|
55580
|
+
});
|
|
55304
55581
|
Object.defineProperty(exports, "BUILTIN_CLIP_MODELS", {
|
|
55305
55582
|
enumerable: true,
|
|
55306
55583
|
get: function() {
|
|
@@ -55427,6 +55704,12 @@ Object.defineProperty(exports, "EMBEDDING_REQUIREMENTS_UNAVAILABLE", {
|
|
|
55427
55704
|
return EMBEDDING_REQUIREMENTS_UNAVAILABLE;
|
|
55428
55705
|
}
|
|
55429
55706
|
});
|
|
55707
|
+
Object.defineProperty(exports, "EVENT_DENSITY_BATCH_MAX", {
|
|
55708
|
+
enumerable: true,
|
|
55709
|
+
get: function() {
|
|
55710
|
+
return EVENT_DENSITY_BATCH_MAX;
|
|
55711
|
+
}
|
|
55712
|
+
});
|
|
55430
55713
|
Object.defineProperty(exports, "EVENT_KIND_BY_CAP", {
|
|
55431
55714
|
enumerable: true,
|
|
55432
55715
|
get: function() {
|
|
@@ -55439,6 +55722,12 @@ Object.defineProperty(exports, "EVENT_OWNER_TYPES", {
|
|
|
55439
55722
|
return EVENT_OWNER_TYPES;
|
|
55440
55723
|
}
|
|
55441
55724
|
});
|
|
55725
|
+
Object.defineProperty(exports, "EXPORT_DENSE_MAX_RANGES", {
|
|
55726
|
+
enumerable: true,
|
|
55727
|
+
get: function() {
|
|
55728
|
+
return EXPORT_DENSE_MAX_RANGES;
|
|
55729
|
+
}
|
|
55730
|
+
});
|
|
55442
55731
|
Object.defineProperty(exports, "EventCategory", {
|
|
55443
55732
|
enumerable: true,
|
|
55444
55733
|
get: function() {
|
|
@@ -55523,12 +55812,48 @@ Object.defineProperty(exports, "NC_ALARM_SYSTEM_EVENT_KINDS", {
|
|
|
55523
55812
|
return NC_ALARM_SYSTEM_EVENT_KINDS;
|
|
55524
55813
|
}
|
|
55525
55814
|
});
|
|
55815
|
+
Object.defineProperty(exports, "NC_AUDIO_CONFIRM_HITS_DEFAULT", {
|
|
55816
|
+
enumerable: true,
|
|
55817
|
+
get: function() {
|
|
55818
|
+
return NC_AUDIO_CONFIRM_HITS_DEFAULT;
|
|
55819
|
+
}
|
|
55820
|
+
});
|
|
55821
|
+
Object.defineProperty(exports, "NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT", {
|
|
55822
|
+
enumerable: true,
|
|
55823
|
+
get: function() {
|
|
55824
|
+
return NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT;
|
|
55825
|
+
}
|
|
55826
|
+
});
|
|
55827
|
+
Object.defineProperty(exports, "NC_CLIP_POST_ROLL_DEFAULT_SEC", {
|
|
55828
|
+
enumerable: true,
|
|
55829
|
+
get: function() {
|
|
55830
|
+
return NC_CLIP_POST_ROLL_DEFAULT_SEC;
|
|
55831
|
+
}
|
|
55832
|
+
});
|
|
55833
|
+
Object.defineProperty(exports, "NC_CLIP_PRE_ROLL_DEFAULT_SEC", {
|
|
55834
|
+
enumerable: true,
|
|
55835
|
+
get: function() {
|
|
55836
|
+
return NC_CLIP_PRE_ROLL_DEFAULT_SEC;
|
|
55837
|
+
}
|
|
55838
|
+
});
|
|
55839
|
+
Object.defineProperty(exports, "NC_CLIP_RETENTION_MAX_SEC", {
|
|
55840
|
+
enumerable: true,
|
|
55841
|
+
get: function() {
|
|
55842
|
+
return NC_CLIP_RETENTION_MAX_SEC;
|
|
55843
|
+
}
|
|
55844
|
+
});
|
|
55526
55845
|
Object.defineProperty(exports, "NC_CONDITION_CATALOG", {
|
|
55527
55846
|
enumerable: true,
|
|
55528
55847
|
get: function() {
|
|
55529
55848
|
return NC_CONDITION_CATALOG;
|
|
55530
55849
|
}
|
|
55531
55850
|
});
|
|
55851
|
+
Object.defineProperty(exports, "NC_CONSUMABLE_LOW_PERCENT_DEFAULT", {
|
|
55852
|
+
enumerable: true,
|
|
55853
|
+
get: function() {
|
|
55854
|
+
return NC_CONSUMABLE_LOW_PERCENT_DEFAULT;
|
|
55855
|
+
}
|
|
55856
|
+
});
|
|
55532
55857
|
Object.defineProperty(exports, "NC_CONSUMABLE_SYSTEM_EVENT_KINDS", {
|
|
55533
55858
|
enumerable: true,
|
|
55534
55859
|
get: function() {
|
|
@@ -55685,6 +56010,12 @@ Object.defineProperty(exports, "NcTemplateVarDescriptorSchema", {
|
|
|
55685
56010
|
return NcTemplateVarDescriptorSchema;
|
|
55686
56011
|
}
|
|
55687
56012
|
});
|
|
56013
|
+
Object.defineProperty(exports, "OPS_LOG_DEFAULT_LIMIT", {
|
|
56014
|
+
enumerable: true,
|
|
56015
|
+
get: function() {
|
|
56016
|
+
return OPS_LOG_DEFAULT_LIMIT;
|
|
56017
|
+
}
|
|
56018
|
+
});
|
|
55688
56019
|
Object.defineProperty(exports, "OpsLogEntrySchema", {
|
|
55689
56020
|
enumerable: true,
|
|
55690
56021
|
get: function() {
|
|
@@ -55721,6 +56052,12 @@ Object.defineProperty(exports, "RetrainStatusSchema", {
|
|
|
55721
56052
|
return RetrainStatusSchema;
|
|
55722
56053
|
}
|
|
55723
56054
|
});
|
|
56055
|
+
Object.defineProperty(exports, "SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX", {
|
|
56056
|
+
enumerable: true,
|
|
56057
|
+
get: function() {
|
|
56058
|
+
return SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX;
|
|
56059
|
+
}
|
|
56060
|
+
});
|
|
55724
56061
|
Object.defineProperty(exports, "SCENE_CONFIRM_DEFAULT_TIMEOUT_MS", {
|
|
55725
56062
|
enumerable: true,
|
|
55726
56063
|
get: function() {
|
|
@@ -55733,6 +56070,24 @@ Object.defineProperty(exports, "SCENE_DEFAULT_ANCHOR_THRESHOLD", {
|
|
|
55733
56070
|
return SCENE_DEFAULT_ANCHOR_THRESHOLD;
|
|
55734
56071
|
}
|
|
55735
56072
|
});
|
|
56073
|
+
Object.defineProperty(exports, "SCENE_DEFAULT_CHECK_INTERVAL_SEC", {
|
|
56074
|
+
enumerable: true,
|
|
56075
|
+
get: function() {
|
|
56076
|
+
return SCENE_DEFAULT_CHECK_INTERVAL_SEC;
|
|
56077
|
+
}
|
|
56078
|
+
});
|
|
56079
|
+
Object.defineProperty(exports, "SCENE_DEFAULT_OBSERVATION_SPACING_SEC", {
|
|
56080
|
+
enumerable: true,
|
|
56081
|
+
get: function() {
|
|
56082
|
+
return SCENE_DEFAULT_OBSERVATION_SPACING_SEC;
|
|
56083
|
+
}
|
|
56084
|
+
});
|
|
56085
|
+
Object.defineProperty(exports, "SCENE_DEFAULT_QUIET_SECONDS", {
|
|
56086
|
+
enumerable: true,
|
|
56087
|
+
get: function() {
|
|
56088
|
+
return SCENE_DEFAULT_QUIET_SECONDS;
|
|
56089
|
+
}
|
|
56090
|
+
});
|
|
55736
56091
|
Object.defineProperty(exports, "SCENE_DEFAULT_UNCOVERED_POLICY", {
|
|
55737
56092
|
enumerable: true,
|
|
55738
56093
|
get: function() {
|
|
@@ -55745,6 +56100,12 @@ Object.defineProperty(exports, "SCENE_DIVERGED", {
|
|
|
55745
56100
|
return SCENE_DIVERGED;
|
|
55746
56101
|
}
|
|
55747
56102
|
});
|
|
56103
|
+
Object.defineProperty(exports, "SCENE_RESET_RECAPTURES", {
|
|
56104
|
+
enumerable: true,
|
|
56105
|
+
get: function() {
|
|
56106
|
+
return SCENE_RESET_RECAPTURES;
|
|
56107
|
+
}
|
|
56108
|
+
});
|
|
55748
56109
|
Object.defineProperty(exports, "SceneMonitorSchema", {
|
|
55749
56110
|
enumerable: true,
|
|
55750
56111
|
get: function() {
|
|
@@ -55973,6 +56334,18 @@ Object.defineProperty(exports, "failureContributionCapability", {
|
|
|
55973
56334
|
return failureContributionCapability;
|
|
55974
56335
|
}
|
|
55975
56336
|
});
|
|
56337
|
+
Object.defineProperty(exports, "gifDeriveSpeed", {
|
|
56338
|
+
enumerable: true,
|
|
56339
|
+
get: function() {
|
|
56340
|
+
return gifDeriveSpeed;
|
|
56341
|
+
}
|
|
56342
|
+
});
|
|
56343
|
+
Object.defineProperty(exports, "gifFromMp4Args", {
|
|
56344
|
+
enumerable: true,
|
|
56345
|
+
get: function() {
|
|
56346
|
+
return gifFromMp4Args;
|
|
56347
|
+
}
|
|
56348
|
+
});
|
|
55976
56349
|
Object.defineProperty(exports, "hydrateSchema", {
|
|
55977
56350
|
enumerable: true,
|
|
55978
56351
|
get: function() {
|
|
@@ -56057,6 +56430,12 @@ Object.defineProperty(exports, "mayWriteToLocation", {
|
|
|
56057
56430
|
return mayWriteToLocation;
|
|
56058
56431
|
}
|
|
56059
56432
|
});
|
|
56433
|
+
Object.defineProperty(exports, "memoizePinnedFfmpeg", {
|
|
56434
|
+
enumerable: true,
|
|
56435
|
+
get: function() {
|
|
56436
|
+
return memoizePinnedFfmpeg;
|
|
56437
|
+
}
|
|
56438
|
+
});
|
|
56060
56439
|
Object.defineProperty(exports, "nodePin", {
|
|
56061
56440
|
enumerable: true,
|
|
56062
56441
|
get: function() {
|
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_clip_model_registry = require("../clip-model-registry-
|
|
5
|
+
const require_clip_model_registry = require("../clip-model-registry-BeJUe0vk.js");
|
|
6
6
|
let node_fs = require("node:fs");
|
|
7
7
|
node_fs = require_clip_model_registry.__toESM(node_fs);
|
|
8
8
|
let node_path = require("node:path");
|
|
@@ -328,6 +328,10 @@ var PythonRawTensorEngine = class {
|
|
|
328
328
|
await this.proc.dispose();
|
|
329
329
|
}
|
|
330
330
|
};
|
|
331
|
+
//#endregion
|
|
332
|
+
//#region src/embedding-encoder/addon/active-clip-model.ts
|
|
333
|
+
/** How long a cluster-row read is trusted. The operator's flip lands within this. */
|
|
334
|
+
var ENCODER_ROW_TTL_MS = 3e4;
|
|
331
335
|
var ActiveClipModel = class {
|
|
332
336
|
deps;
|
|
333
337
|
cached = null;
|
|
@@ -345,7 +349,7 @@ var ActiveClipModel = class {
|
|
|
345
349
|
}
|
|
346
350
|
async get() {
|
|
347
351
|
const now = this.deps.now();
|
|
348
|
-
if (this.cached !== null && now - this.cached.at <
|
|
352
|
+
if (this.cached !== null && now - this.cached.at < ENCODER_ROW_TTL_MS) return this.cached.modelId;
|
|
349
353
|
const row = await this.deps.readRow();
|
|
350
354
|
if (row === null) {
|
|
351
355
|
const kept = this.lastRead ?? this.deps.fallbackModelId();
|
|
@@ -369,6 +373,10 @@ var ActiveClipModel = class {
|
|
|
369
373
|
return row;
|
|
370
374
|
}
|
|
371
375
|
};
|
|
376
|
+
//#endregion
|
|
377
|
+
//#region src/embedding-encoder/addon/crash-budget.ts
|
|
378
|
+
var MAX_CRASHES = 3;
|
|
379
|
+
var CRASH_WINDOW_MS = 10 * 6e4;
|
|
372
380
|
var CrashBudget = class {
|
|
373
381
|
deps;
|
|
374
382
|
recent = /* @__PURE__ */ new Map();
|
|
@@ -386,11 +394,11 @@ var CrashBudget = class {
|
|
|
386
394
|
record(modelId, reason) {
|
|
387
395
|
if (this.failedModels.has(modelId)) return false;
|
|
388
396
|
const now = this.now();
|
|
389
|
-
const windowMs = this.deps.windowMs ??
|
|
397
|
+
const windowMs = this.deps.windowMs ?? CRASH_WINDOW_MS;
|
|
390
398
|
const times = (this.recent.get(modelId) ?? []).filter((t) => now - t < windowMs);
|
|
391
399
|
times.push(now);
|
|
392
400
|
this.recent.set(modelId, times);
|
|
393
|
-
if (times.length < (this.deps.maxCrashes ??
|
|
401
|
+
if (times.length < (this.deps.maxCrashes ?? MAX_CRASHES)) return false;
|
|
394
402
|
const failed = {
|
|
395
403
|
modelId,
|
|
396
404
|
tower: this.deps.tower,
|
|
@@ -566,6 +574,13 @@ var ModelEngineSlot = class {
|
|
|
566
574
|
held.engine.dispose().catch(() => {});
|
|
567
575
|
}
|
|
568
576
|
};
|
|
577
|
+
//#endregion
|
|
578
|
+
//#region src/embedding-encoder/addon/model-requirements.ts
|
|
579
|
+
/** First cooldown after a failed attempt; doubles per failure up to the cap. */
|
|
580
|
+
var REQUIREMENTS_COOLDOWN_BASE_MS = 5e3;
|
|
581
|
+
var REQUIREMENTS_COOLDOWN_MAX_MS = 5 * 6e4;
|
|
582
|
+
/** Failed attempts at a PERMANENTLY unmeetable requirement before it is terminal. */
|
|
583
|
+
var MAX_REQUIREMENTS_ATTEMPTS = 3;
|
|
569
584
|
/**
|
|
570
585
|
* Thrown by the requirements stage when a retry can never help: the catalog
|
|
571
586
|
* does not know the id, the server said the file does not exist (404/410), a
|
|
@@ -621,7 +636,7 @@ var RequirementsGate = class {
|
|
|
621
636
|
const attempts = (prior?.attempts ?? 0) + 1;
|
|
622
637
|
const permanent = isPermanentRequirementsFailure(err);
|
|
623
638
|
const permanentAttempts = (prior?.permanentAttempts ?? 0) + (permanent ? 1 : 0);
|
|
624
|
-
const cooldownMs = Math.min(this.deps.cooldownMaxMs ??
|
|
639
|
+
const cooldownMs = Math.min(this.deps.cooldownMaxMs ?? REQUIREMENTS_COOLDOWN_MAX_MS, (this.deps.cooldownBaseMs ?? REQUIREMENTS_COOLDOWN_BASE_MS) * 2 ** (attempts - 1));
|
|
625
640
|
const base = {
|
|
626
641
|
sinceMs: prior?.sinceMs ?? now,
|
|
627
642
|
reason,
|
|
@@ -638,7 +653,7 @@ var RequirementsGate = class {
|
|
|
638
653
|
reason,
|
|
639
654
|
cooldownMs
|
|
640
655
|
} });
|
|
641
|
-
if (permanent && permanentAttempts >= (this.deps.maxAttempts ??
|
|
656
|
+
if (permanent && permanentAttempts >= (this.deps.maxAttempts ?? MAX_REQUIREMENTS_ATTEMPTS)) {
|
|
642
657
|
const terminal = {
|
|
643
658
|
...this.on(modelId),
|
|
644
659
|
attempts: permanentAttempts,
|
|
@@ -750,6 +765,10 @@ function l2Normalize(vec) {
|
|
|
750
765
|
if (norm > 0) for (let i = 0; i < vec.length; i++) vec[i] /= norm;
|
|
751
766
|
return vec;
|
|
752
767
|
}
|
|
768
|
+
//#endregion
|
|
769
|
+
//#region src/embedding-encoder/addon/clip-text-engines.ts
|
|
770
|
+
/** At most this many text towers stay loaded (SigLIP2's is ~565 MB). */
|
|
771
|
+
var MAX_TEXT_ENGINES = 2;
|
|
753
772
|
/**
|
|
754
773
|
* A tower unused this long is disposed ({@link ClipTextEngines.evictIdle}) —
|
|
755
774
|
* EXCEPT the tower of the model the cluster row names, which stays loaded for
|
|
@@ -927,7 +946,7 @@ var ClipTextEngines = class {
|
|
|
927
946
|
}
|
|
928
947
|
/** Fire-and-log: eviction errors never reach an encode. */
|
|
929
948
|
scheduleEviction() {
|
|
930
|
-
this.evictBeyond(this.deps.maxEngines ??
|
|
949
|
+
this.evictBeyond(this.deps.maxEngines ?? MAX_TEXT_ENGINES).catch((err) => {
|
|
931
950
|
this.deps.logger.warn("CLIP text tower eviction failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
932
951
|
});
|
|
933
952
|
}
|