@camstack/addon-pipeline 1.2.218 → 1.2.220
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audio-analyzer/index.js +49 -5
- package/dist/audio-analyzer/index.mjs +46 -3
- package/dist/chunk-emK7D4bc.js +35 -0
- package/dist/{default-detection-model-AJyhoTLF.mjs → default-detection-model-DBNEc3iw.mjs} +1 -1
- package/dist/{default-detection-model-Bf45EQ98.js → default-detection-model-x6oNMBDH.js} +1 -1
- package/dist/detection-pipeline/index.js +10 -9
- package/dist/detection-pipeline/index.mjs +4 -4
- package/dist/{dist-BbvtiBNc.js → dist-ByPsWlTa.js} +57 -38
- package/dist/{dist-Dl6GntEh.mjs → dist-ClihWGOZ.mjs} +57 -3
- package/dist/{lazy-sharp-L9Lcr62v.js → lazy-sharp-BuwKlQLR.js} +2 -2
- package/dist/motion-wasm/index.js +2 -2
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-CbCVHEvJ.js → node-CNPnaux4.js} +4 -3
- package/dist/{node-CEyw52D2.mjs → node-DiaTmz84.mjs} +1 -1
- package/dist/pipeline-runner/index.js +222 -157
- package/dist/pipeline-runner/index.mjs +218 -154
- package/dist/{process-memory-DBxdiCSF.js → process-memory-9KqRtUHt.js} +3 -2
- package/dist/{process-memory-Du00R6-e.mjs → process-memory-D4t8hpJd.mjs} +1 -1
- package/dist/recorder/index.js +334 -123
- package/dist/recorder/index.mjs +332 -122
- package/dist/{segment-demux-js-B278aBtB.mjs → segment-demux-js-CFFXVae4.mjs} +1 -1
- package/dist/{segment-demux-js-D7bjzY8M.js → segment-demux-js-CZefXDLx.js} +4 -3
- package/dist/session-decode/decode-worker-child.js +155 -74
- package/dist/session-decode/decode-worker-child.mjs +154 -73
- package/dist/stream-broker/_stub.js +1 -1
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BnmbfnAd.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CtdpN7Sz.mjs} +3 -3
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-yJ2CyixO.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-7hqrrd88.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-MIKQqs86.mjs → hostInit-McoUiljf.mjs} +3 -3
- package/dist/stream-broker/index.js +24 -25
- package/dist/stream-broker/index.mjs +17 -19
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/worker-protocol-B2MfQLlu.js +184 -0
- package/dist/worker-protocol-C_W-P_g-.mjs +161 -0
- package/package.json +1 -1
- package/dist/worker-protocol-BEbD5adq.mjs +0 -264
- package/dist/worker-protocol-C4rh5uiS.js +0 -299
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
const
|
|
1
|
+
const require_chunk = require("./chunk-emK7D4bc.js");
|
|
2
|
+
const require_dist = require("./dist-ByPsWlTa.js");
|
|
2
3
|
let node_child_process = require("node:child_process");
|
|
3
4
|
//#region ../../node_modules/mp4box/dist/mp4box.all.js
|
|
4
|
-
var require_mp4box_all = /* @__PURE__ */
|
|
5
|
+
var require_mp4box_all = /* @__PURE__ */ require_chunk.__commonJSMin(((exports) => {
|
|
5
6
|
var Log = (function() {
|
|
6
7
|
var start = /* @__PURE__ */ new Date();
|
|
7
8
|
var LOG_LEVEL_ERROR = 4;
|
|
@@ -6569,7 +6570,7 @@ var require_mp4box_all = /* @__PURE__ */ require_dist.__commonJSMin(((exports) =
|
|
|
6569
6570
|
}));
|
|
6570
6571
|
//#endregion
|
|
6571
6572
|
//#region src/recorder/scrub/fmp4-keyframes.ts
|
|
6572
|
-
var import_mp4box_all = /* @__PURE__ */
|
|
6573
|
+
var import_mp4box_all = /* @__PURE__ */ require_chunk.__toESM(require_mp4box_all());
|
|
6573
6574
|
/**
|
|
6574
6575
|
* Normalize an RFC 6381 codec string for WebCodecs HEVC. Apple/WebKit
|
|
6575
6576
|
* WebCodecs only accepts the `hvc1.*` fourcc — a `hev1.*` string (what mp4box
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_worker_protocol = require("../worker-protocol-
|
|
3
|
-
const require_lazy_sharp = require("../lazy-sharp-
|
|
2
|
+
const require_worker_protocol = require("../worker-protocol-B2MfQLlu.js");
|
|
3
|
+
const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
|
|
4
4
|
//#region src/session-decode/color-conversion.ts
|
|
5
5
|
/**
|
|
6
6
|
* Explicit YUV→RGB colorspace/range resolution for the session-decode worker.
|
|
@@ -1602,48 +1602,68 @@ var NATIVE_RING_CAP = (() => {
|
|
|
1602
1602
|
return Math.min(4, Math.max(0, Math.floor(raw)));
|
|
1603
1603
|
})();
|
|
1604
1604
|
/**
|
|
1605
|
-
* The
|
|
1606
|
-
*
|
|
1607
|
-
*
|
|
1608
|
-
*
|
|
1609
|
-
*
|
|
1610
|
-
* `
|
|
1611
|
-
*
|
|
1612
|
-
*
|
|
1613
|
-
*
|
|
1614
|
-
*
|
|
1615
|
-
*
|
|
1616
|
-
*
|
|
1617
|
-
*
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
*
|
|
1622
|
-
*
|
|
1623
|
-
*
|
|
1624
|
-
* `0` DISABLES the hold and falls back to the
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
*
|
|
1629
|
-
*
|
|
1630
|
-
*
|
|
1631
|
-
*
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
*
|
|
1636
|
-
* `
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
*
|
|
1643
|
-
*
|
|
1644
|
-
*
|
|
1645
|
-
|
|
1646
|
-
|
|
1605
|
+
* The native-lease knobs — hold depth, hold RAM ceiling, demand window,
|
|
1606
|
+
* admission mode, subject-tile budget, scene-tile budget — ARRIVE ON `start`
|
|
1607
|
+
* (`WorkerRequest.lease`, D453). They are **operator settings** living on
|
|
1608
|
+
* `pipeline-orchestrator`'s cluster-wide globals; the pipeline-runner reads
|
|
1609
|
+
* them and resolves `setting > env > default` in ITS process
|
|
1610
|
+
* (`native-lease-config.ts`), and this worker builds its stores from the
|
|
1611
|
+
* resolved values in {@link DecodeWorkerChild.handleStart}, before the first
|
|
1612
|
+
* packet. Until then it retains nothing ({@link UNSTARTED_LEASE_KNOBS}).
|
|
1613
|
+
*
|
|
1614
|
+
* Nothing here reads the environment for them any more. The child used to,
|
|
1615
|
+
* from `*_SETTING` vars the parent wrote at fork — which needed the Zod schemas
|
|
1616
|
+
* (the whole `@camstack/types` index) inside this bundle and cost every fork
|
|
1617
|
+
* ~130 ms and ~140 MB, measured; and it bound a worker to the knobs it was
|
|
1618
|
+
* FORKED with, which a pre-forked worker (`decode-worker-pool.ts`) cannot be.
|
|
1619
|
+
* The values AND their sources are logged once per session at `start`.
|
|
1620
|
+
*
|
|
1621
|
+
* What each knob means, in the store it sizes:
|
|
1622
|
+
* - `budgetMb` — hard RAM ceiling (bytes) for the native-frame HOLD store, the
|
|
1623
|
+
* OOM ceiling and since 2026-08-13 nothing else; `holdFrames` is what decides
|
|
1624
|
+
* how much is held. `0` DISABLES the hold and falls back to the
|
|
1625
|
+
* {@link NATIVE_RING_CAP} GPU ring.
|
|
1626
|
+
* - `holdFrames` — how many delivered frames are HELD at once, each waiting for
|
|
1627
|
+
* its own detection result. The ordinary exit is `cutTiles` /
|
|
1628
|
+
* `releaseNativeLease`; this bound only stops a runner that stopped answering
|
|
1629
|
+
* from pinning RAM, and every frame it drops is counted (`holdOverflow`).
|
|
1630
|
+
* - `tileBudgetMb` — the SUBJECT TILE store, what survives a frame. `0` turns
|
|
1631
|
+
* tiles off and restores the pre-2026-08-13 miss profile.
|
|
1632
|
+
* - `sceneBudgetMb` — the SCENE TILE store, one JPEG of the whole native frame
|
|
1633
|
+
* per detection-bearing frame, the only thing that can answer a FULL-FRAME
|
|
1634
|
+
* request after the hold ends. Separate from the subject budget so a key
|
|
1635
|
+
* frame can never evict a face tile. `0` disables the rung.
|
|
1636
|
+
* - `activityMs` — the {@link LeaseActivityGate} demand window: eager per-frame
|
|
1637
|
+
* native downloads run only within it. `0` disables the GATE (always-on eager
|
|
1638
|
+
* capture) — it does not disable retention.
|
|
1639
|
+
*/
|
|
1640
|
+
var MB = 1024 * 1024;
|
|
1641
|
+
/**
|
|
1642
|
+
* What a worker holds BEFORE a session claims it: nothing. Hold off (`budgetMb`
|
|
1643
|
+
* 0 routes to the GPU ring, whose cap is env-only), tiles off, scenes off, the
|
|
1644
|
+
* gate open only because there is nothing behind it to open. Not the shipped
|
|
1645
|
+
* defaults on purpose — those live in `@camstack/types`, which this bundle no
|
|
1646
|
+
* longer carries, and a pre-forked worker that silently held the defaults would
|
|
1647
|
+
* be a worker with a configuration nobody handed it.
|
|
1648
|
+
*/
|
|
1649
|
+
var UNSTARTED_LEASE_KNOBS = {
|
|
1650
|
+
values: {
|
|
1651
|
+
holdFrames: 1,
|
|
1652
|
+
budgetMb: 0,
|
|
1653
|
+
activityMs: 0,
|
|
1654
|
+
admission: "inferred",
|
|
1655
|
+
tileBudgetMb: 0,
|
|
1656
|
+
sceneBudgetMb: 0
|
|
1657
|
+
},
|
|
1658
|
+
sources: {
|
|
1659
|
+
holdFrames: "default",
|
|
1660
|
+
budgetMb: "default",
|
|
1661
|
+
activityMs: "default",
|
|
1662
|
+
admission: "default",
|
|
1663
|
+
tileBudgetMb: "default",
|
|
1664
|
+
sceneBudgetMb: "default"
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1647
1667
|
/**
|
|
1648
1668
|
* How long a subject tile is served. A TTL is honest HERE and dishonest on the
|
|
1649
1669
|
* hold: nothing is waiting on a tile, it is speculative retention against a
|
|
@@ -1690,13 +1710,6 @@ var TILE_CUT_WAIT_MS = (() => {
|
|
|
1690
1710
|
const raw = Number(process.env["CAMSTACK_SESSION_TILE_CUT_WAIT_MS"]);
|
|
1691
1711
|
return Number.isFinite(raw) && raw >= 0 ? Math.floor(raw) : 500;
|
|
1692
1712
|
})();
|
|
1693
|
-
/**
|
|
1694
|
-
* Demand window (ms) for the lease-capture {@link LeaseActivityGate}: eager
|
|
1695
|
-
* per-frame native downloads run only within this window of the last
|
|
1696
|
-
* native-crop request (or dial start). `0` disables the GATE (legacy always-on
|
|
1697
|
-
* eager capture) — it does not disable retention. Default 15000.
|
|
1698
|
-
*/
|
|
1699
|
-
var NATIVE_LEASE_ACTIVITY_WINDOW_MS = NATIVE_LEASE_KNOBS.values.activityMs;
|
|
1700
1713
|
/** How many early-withdrawn frame ids the worker remembers for the miss line. */
|
|
1701
1714
|
var UNMARKED_MEMORY = 256;
|
|
1702
1715
|
/**
|
|
@@ -1818,13 +1831,47 @@ async function importNodeAv(bareSpecifier) {
|
|
|
1818
1831
|
throw bareErr;
|
|
1819
1832
|
}
|
|
1820
1833
|
}
|
|
1834
|
+
var _navLoading = null;
|
|
1835
|
+
var _constsLoading = null;
|
|
1821
1836
|
async function getNodeAv() {
|
|
1822
|
-
if (
|
|
1823
|
-
|
|
1837
|
+
if (_nav) return _nav;
|
|
1838
|
+
_navLoading ??= importNodeAv("node-av").then((mod) => {
|
|
1839
|
+
_nav = mod;
|
|
1840
|
+
return mod;
|
|
1841
|
+
});
|
|
1842
|
+
try {
|
|
1843
|
+
return await _navLoading;
|
|
1844
|
+
} catch (err) {
|
|
1845
|
+
_navLoading = null;
|
|
1846
|
+
throw err;
|
|
1847
|
+
}
|
|
1824
1848
|
}
|
|
1825
1849
|
async function getConstants() {
|
|
1826
|
-
if (
|
|
1827
|
-
|
|
1850
|
+
if (_consts) return _consts;
|
|
1851
|
+
_constsLoading ??= importNodeAv("node-av/constants").then((mod) => {
|
|
1852
|
+
_consts = mod;
|
|
1853
|
+
return mod;
|
|
1854
|
+
});
|
|
1855
|
+
try {
|
|
1856
|
+
return await _constsLoading;
|
|
1857
|
+
} catch (err) {
|
|
1858
|
+
_constsLoading = null;
|
|
1859
|
+
throw err;
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
/** The HOLD store, sized from one session's knobs. */
|
|
1863
|
+
function buildLeaseStore(lease) {
|
|
1864
|
+
return new NativeLeaseStore({
|
|
1865
|
+
budgetBytes: lease.values.budgetMb * MB,
|
|
1866
|
+
maxFrames: lease.values.holdFrames
|
|
1867
|
+
});
|
|
1868
|
+
}
|
|
1869
|
+
/** A TILE store (subject or scene) under `budgetMb`, on the shared tile TTL. */
|
|
1870
|
+
function buildTileStore(budgetMb) {
|
|
1871
|
+
return new NativeTileStore({
|
|
1872
|
+
budgetBytes: budgetMb * MB,
|
|
1873
|
+
ttlMs: NATIVE_TILE_TTL_MS
|
|
1874
|
+
});
|
|
1828
1875
|
}
|
|
1829
1876
|
function errMessage(err) {
|
|
1830
1877
|
if (err instanceof Error) return err.message;
|
|
@@ -2011,20 +2058,14 @@ var DecodeWorkerChild = class {
|
|
|
2011
2058
|
* DOWNLOADED (system-memory) frames, retaining a large window has no VAAPI
|
|
2012
2059
|
* surface-pool starvation risk. Cleared on every re-dial + teardown.
|
|
2013
2060
|
*/
|
|
2014
|
-
leaseStore =
|
|
2015
|
-
budgetBytes: NATIVE_LEASE_BUDGET_BYTES,
|
|
2016
|
-
maxFrames: NATIVE_LEASE_HOLD_FRAMES
|
|
2017
|
-
});
|
|
2061
|
+
leaseStore = buildLeaseStore(UNSTARTED_LEASE_KNOBS);
|
|
2018
2062
|
/**
|
|
2019
2063
|
* What SURVIVES a held frame: one compressed native tile per subject, cut at
|
|
2020
2064
|
* the instant the frame's detection result arrived. Every late native crop
|
|
2021
2065
|
* that the hold can no longer serve is served from here — which measurement
|
|
2022
2066
|
* says is the ordinary case, not the exception. See `native-tile-store.ts`.
|
|
2023
2067
|
*/
|
|
2024
|
-
tileStore =
|
|
2025
|
-
budgetBytes: NATIVE_TILE_BUDGET_BYTES,
|
|
2026
|
-
ttlMs: NATIVE_TILE_TTL_MS
|
|
2027
|
-
});
|
|
2068
|
+
tileStore = buildTileStore(UNSTARTED_LEASE_KNOBS.values.tileBudgetMb);
|
|
2028
2069
|
/**
|
|
2029
2070
|
* What survives a held frame for a FULL-FRAME request: one JPEG of the whole
|
|
2030
2071
|
* native raster, cut in the SAME synchronous read phase as the subject tiles.
|
|
@@ -2034,10 +2075,7 @@ var DecodeWorkerChild = class {
|
|
|
2034
2075
|
* key frames evict the face/plate tiles the recognisers live on. Two stores
|
|
2035
2076
|
* make starving that tier impossible rather than unlikely.
|
|
2036
2077
|
*/
|
|
2037
|
-
sceneStore =
|
|
2038
|
-
budgetBytes: NATIVE_SCENE_BUDGET_BYTES,
|
|
2039
|
-
ttlMs: NATIVE_TILE_TTL_MS
|
|
2040
|
-
});
|
|
2078
|
+
sceneStore = buildTileStore(UNSTARTED_LEASE_KNOBS.values.sceneBudgetMb);
|
|
2041
2079
|
/** Tiles cut / served / refused-for-containment, on the throughput line. */
|
|
2042
2080
|
tilesCut = 0;
|
|
2043
2081
|
tileHits = 0;
|
|
@@ -2081,7 +2119,7 @@ var DecodeWorkerChild = class {
|
|
|
2081
2119
|
* per-frame native-res GPU→RAM download (the N100 saturation source) stops
|
|
2082
2120
|
* on cameras nothing is cropping. See `lease-activity-gate.ts`.
|
|
2083
2121
|
*/
|
|
2084
|
-
leaseGate = new LeaseActivityGate(
|
|
2122
|
+
leaseGate = new LeaseActivityGate(UNSTARTED_LEASE_KNOBS.values.activityMs);
|
|
2085
2123
|
/**
|
|
2086
2124
|
* WHICH delivered frames are worth a native lease — the runner marks the ones
|
|
2087
2125
|
* it admitted to inference (`markInferred`), and in `inferred` mode only
|
|
@@ -2090,7 +2128,14 @@ var DecodeWorkerChild = class {
|
|
|
2090
2128
|
* filter rests on is measured on live traffic rather than argued. See
|
|
2091
2129
|
* `lease-admission-ledger.ts`.
|
|
2092
2130
|
*/
|
|
2093
|
-
admission = new LeaseAdmissionLedger({ mode:
|
|
2131
|
+
admission = new LeaseAdmissionLedger({ mode: UNSTARTED_LEASE_KNOBS.values.admission });
|
|
2132
|
+
/**
|
|
2133
|
+
* The knobs this session runs under — `null` until `start` hands them over.
|
|
2134
|
+
* The stores above are REBUILT from them at that moment (they are empty then:
|
|
2135
|
+
* nothing is captured before a dial), and never again: a knob that changes
|
|
2136
|
+
* after the first frame is a knob with two values during a session.
|
|
2137
|
+
*/
|
|
2138
|
+
lease = null;
|
|
2094
2139
|
/**
|
|
2095
2140
|
* DEDICATED full-frame GPU→system download filtergraph
|
|
2096
2141
|
* (`scale_<be>=iw:ih,hwdownload,format=nv12,format=yuv420p`) used ONLY to
|
|
@@ -2251,7 +2296,7 @@ var DecodeWorkerChild = class {
|
|
|
2251
2296
|
}
|
|
2252
2297
|
switch (message.kind) {
|
|
2253
2298
|
case "start":
|
|
2254
|
-
this.handleStart(message.source, message.opts);
|
|
2299
|
+
this.handleStart(message.source, message.opts, message.lease);
|
|
2255
2300
|
return;
|
|
2256
2301
|
case "pull":
|
|
2257
2302
|
this.handlePull();
|
|
@@ -2331,7 +2376,7 @@ var DecodeWorkerChild = class {
|
|
|
2331
2376
|
const skipped = this.framesSkipped + this.frames.droppedCount;
|
|
2332
2377
|
const rssMb = Math.round(process.memoryUsage().rss / 1048576);
|
|
2333
2378
|
const ageS = Math.round((now - this.startedAt) / 1e3);
|
|
2334
|
-
this.emitStderr(`session-decode metrics {framesDecoded:${this.framesDecoded}, framesSkipped:${skipped}, deliveredFps:${deliveredFps}, nativeCropHits:${this.nativeCropHits}, nativeCropMisses:${this.nativeCropMisses}, leaseOffered:${this.admission.offered}, leaseAdmitted:${this.admission.admitted}, leaseMarks:${this.admission.marks}, leaseUnmarkedCrops:${this.admission.unmarkedCrops}, leaseAdmission:${
|
|
2379
|
+
this.emitStderr(`session-decode metrics {framesDecoded:${this.framesDecoded}, framesSkipped:${skipped}, deliveredFps:${deliveredFps}, nativeCropHits:${this.nativeCropHits}, nativeCropMisses:${this.nativeCropMisses}, leaseOffered:${this.admission.offered}, leaseAdmitted:${this.admission.admitted}, leaseMarks:${this.admission.marks}, leaseUnmarkedCrops:${this.admission.unmarkedCrops}, leaseAdmission:${this.lease?.values.admission ?? "unstarted"}, leaseMb:${Math.round(this.leaseStore.totalBytes / 1048576)}, leaseFrames:${this.leaseStore.size}, holdOverflow:${this.leaseStore.overflowCount}, leaseReleased:${this.leaseReleased}, leaseReleaseMisses:${this.leaseReleaseMisses}, leaseReleasedEarly:${this.leaseReleasedEarly}, tilesCut:${this.tilesCut}, tileHits:${this.tileHits}, tileMisses:${this.tileMisses}, tileCutFailures:${this.tileCutFailures}, tileMissesResolvedByWait:${this.tileMissesResolvedByWait}, tileWaitTimeouts:${this.tileWaitTimeouts}, cutLatencyMsP50:${formatLatency(this.pendingCuts.latencyMs(50))}, cutLatencyMsP95:${formatLatency(this.pendingCuts.latencyMs(95))}, cutsInFlight:${this.pendingCuts.inFlight}, tileMb:${Math.round(this.tileStore.totalBytes / 1048576)}, tileFrames:${this.tileStore.frameCount}, scenesCut:${this.scenesCut}, sceneHits:${this.sceneHits}, sceneRefused:${this.sceneRefused}, sceneUnclassified:${this.sceneUnclassified}, sceneEvicted:${this.sceneStore.evictedCount}, sceneMb:${Math.round(this.sceneStore.totalBytes / 1048576)}, sceneFrames:${this.sceneStore.frameCount}, rssMb:${rssMb}, ageS:${ageS}}${final ? " (final)" : ""}\n`);
|
|
2335
2380
|
this.lastMetricsAt = now;
|
|
2336
2381
|
this.lastDeliveredSnapshot = this.framesDelivered;
|
|
2337
2382
|
if (!this.warnedLarge && rssMb >= WORKER_RSS_WARN_MB) {
|
|
@@ -2339,14 +2384,20 @@ var DecodeWorkerChild = class {
|
|
|
2339
2384
|
this.emitStderr(`decode-worker-child: WORKER IS LARGE — rssMb=${rssMb} ageS=${ageS} framesDecoded=${this.framesDecoded}. Siblings normally recycle in ~30s; a worker this size at this age is how the host ran out of memory on 2026-08-05.\n`);
|
|
2340
2385
|
}
|
|
2341
2386
|
}
|
|
2342
|
-
handleStart(source, opts) {
|
|
2387
|
+
handleStart(source, opts, lease) {
|
|
2343
2388
|
if (this.started) {
|
|
2344
2389
|
this.emitStderr("decode-worker-child: duplicate start ignored\n");
|
|
2345
2390
|
return;
|
|
2346
2391
|
}
|
|
2347
2392
|
this.started = true;
|
|
2348
2393
|
this.deviceId = source.deviceId;
|
|
2349
|
-
this.
|
|
2394
|
+
this.lease = lease;
|
|
2395
|
+
this.leaseStore = buildLeaseStore(lease);
|
|
2396
|
+
this.tileStore = buildTileStore(lease.values.tileBudgetMb);
|
|
2397
|
+
this.sceneStore = buildTileStore(lease.values.sceneBudgetMb);
|
|
2398
|
+
this.leaseGate = new LeaseActivityGate(lease.values.activityMs);
|
|
2399
|
+
this.admission = new LeaseAdmissionLedger({ mode: lease.values.admission });
|
|
2400
|
+
this.emitStderr(`decode-worker-child: ${require_worker_protocol.formatNativeLeaseKnobs(lease)}\n`, "info");
|
|
2350
2401
|
this.sessionFormat = opts.format ?? "rgb";
|
|
2351
2402
|
this.minIntervalMs = opts.fps && opts.fps > 0 ? 1e3 / opts.fps : 0;
|
|
2352
2403
|
this.preRollMs = opts.preRollMs && opts.preRollMs > 0 ? opts.preRollMs : 0;
|
|
@@ -2400,7 +2451,7 @@ var DecodeWorkerChild = class {
|
|
|
2400
2451
|
reservedFrameId: this.frames.reservedFrameId,
|
|
2401
2452
|
marked: this.admission.isMarked(frameId),
|
|
2402
2453
|
leaseFrames: this.leaseStore.size,
|
|
2403
|
-
holdFrames:
|
|
2454
|
+
holdFrames: this.lease?.values.holdFrames ?? UNSTARTED_LEASE_KNOBS.values.holdFrames,
|
|
2404
2455
|
holdOverflow: this.leaseStore.overflowCount,
|
|
2405
2456
|
...this.unmarkedBy.has(frameId) ? { unmarkedBy: this.unmarkedBy.get(frameId) } : {}
|
|
2406
2457
|
}), frameId);
|
|
@@ -3562,6 +3613,35 @@ var DecodeWorkerChild = class {
|
|
|
3562
3613
|
this.demuxer?.[Symbol.dispose]?.();
|
|
3563
3614
|
this.demuxer = null;
|
|
3564
3615
|
}
|
|
3616
|
+
/**
|
|
3617
|
+
* Load the native modules BEFORE any session, then say so. This is what a
|
|
3618
|
+
* pre-forked worker in the zygote pool (`decode-worker-pool.ts`) spends its
|
|
3619
|
+
* idle on — node-av's `dlopen` measured ~50 ms on the hub, and after D453
|
|
3620
|
+
* removed the types chunk it is the largest piece of a cold boot that is left.
|
|
3621
|
+
* It touches no stream, no demuxer, no GPU: a warm worker costs RSS and
|
|
3622
|
+
* nothing else, which is the property the pool exists for and the exact
|
|
3623
|
+
* inverse of the keep-warm D282 measured.
|
|
3624
|
+
*
|
|
3625
|
+
* A failure is reported, not fatal: `start` re-runs the same import and
|
|
3626
|
+
* fails the session the way it always has, so a node where node-av cannot
|
|
3627
|
+
* load is no worse off than before — it just is not warm.
|
|
3628
|
+
*/
|
|
3629
|
+
async warm() {
|
|
3630
|
+
try {
|
|
3631
|
+
await getNodeAv();
|
|
3632
|
+
await getConstants();
|
|
3633
|
+
this.send({
|
|
3634
|
+
kind: "ready",
|
|
3635
|
+
warm: true
|
|
3636
|
+
});
|
|
3637
|
+
} catch (err) {
|
|
3638
|
+
this.emitStderr(`decode-worker-child: native module preload failed — ${errMessage(err)}\n`, "warn");
|
|
3639
|
+
this.send({
|
|
3640
|
+
kind: "ready",
|
|
3641
|
+
warm: false
|
|
3642
|
+
});
|
|
3643
|
+
}
|
|
3644
|
+
}
|
|
3565
3645
|
send(reply) {
|
|
3566
3646
|
process.send?.(reply);
|
|
3567
3647
|
}
|
|
@@ -3619,6 +3699,7 @@ require_lazy_sharp.setSharpWarnSink((message) => {
|
|
|
3619
3699
|
process.on("message", (message) => {
|
|
3620
3700
|
worker.handleMessage(message);
|
|
3621
3701
|
});
|
|
3702
|
+
worker.warm();
|
|
3622
3703
|
process.on("disconnect", () => {
|
|
3623
3704
|
worker.teardown();
|
|
3624
3705
|
process.exit(0);
|