@camstack/addon-pipeline 1.2.367 → 1.2.368
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 +3 -3
- package/dist/audio-analyzer/index.mjs +3 -3
- package/dist/{custom-model-catalog-CESZ9DM5.js → custom-model-catalog-BY-aEI2s.js} +2 -2
- package/dist/{custom-model-catalog-BqKEZYFI.mjs → custom-model-catalog-Bnel86hH.mjs} +2 -2
- package/dist/detection-pipeline/index.js +4 -4
- package/dist/detection-pipeline/index.mjs +4 -4
- package/dist/{dist-ClKIJKn0.mjs → dist-5AhGOWWu.mjs} +381 -0
- package/dist/{dist-BmQm6_nm.js → dist-DDXsZaRH.js} +381 -0
- package/dist/{model-catalogs-B3lwxS5R.js → model-catalogs-DJN58c_U.js} +1 -1
- package/dist/{model-catalogs-DKHNVZC0.mjs → model-catalogs-DWR9EsGI.mjs} +1 -1
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-BqTmCMlP.js → node-CiciZWts.js} +1 -1
- package/dist/{node-DlpWXqvO.mjs → node-DqZJFOzR.mjs} +1 -1
- package/dist/pipeline-runner/index.js +3 -3
- package/dist/pipeline-runner/index.mjs +3 -3
- package/dist/{process-memory-DHF3ynR3.js → process-memory-BRu19Dgr.js} +1 -1
- package/dist/{process-memory-BjIiiXGZ.mjs → process-memory-Batknjjt.mjs} +1 -1
- package/dist/recorder/index.js +3 -2
- package/dist/recorder/index.mjs +3 -2
- package/dist/{segment-demux-js-D1Up0mTP.js → segment-demux-js-0CRf7GAb.js} +2 -2
- package/dist/{segment-demux-js-Du_eAog1.mjs → segment-demux-js-dlhO3Q8W.mjs} +2 -2
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CRxJwkgE.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CSajlHKC.mjs} +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BfVREmhg.mjs +26 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-5KL24-a_.mjs +26 -0
- 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-DEnYuDjZ.mjs → hostInit-KJ1eka58.mjs} +2 -2
- package/dist/stream-broker/index.js +123 -57
- package/dist/stream-broker/index.mjs +123 -57
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CIBBQAJc.mjs +0 -26
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DNGQ-Tic.mjs +0 -26
|
@@ -3,12 +3,12 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
7
|
-
const require_node = require("../node-
|
|
6
|
+
const require_dist = require("../dist-DDXsZaRH.js");
|
|
7
|
+
const require_node = require("../node-CiciZWts.js");
|
|
8
8
|
const require_restream_intent = require("../restream-intent-7uDNqMKs.js");
|
|
9
9
|
const require_remote_restream = require("../remote-restream-CO36Sr30.js");
|
|
10
10
|
const require_retire_root_keys = require("../retire-root-keys-Csb8z2f3.js");
|
|
11
|
-
const require_segment_demux_js = require("../segment-demux-js-
|
|
11
|
+
const require_segment_demux_js = require("../segment-demux-js-0CRf7GAb.js");
|
|
12
12
|
let node_os = require("node:os");
|
|
13
13
|
node_os = require_chunk.__toESM(node_os);
|
|
14
14
|
let node_crypto = require("node:crypto");
|
|
@@ -33941,23 +33941,37 @@ function createHttpClipStreamOpener(options = {}) {
|
|
|
33941
33941
|
req.end();
|
|
33942
33942
|
});
|
|
33943
33943
|
}
|
|
33944
|
-
//#endregion
|
|
33945
|
-
//#region src/stream-broker/recorded/demux-off-thread.ts
|
|
33946
33944
|
/**
|
|
33947
|
-
*
|
|
33948
|
-
*
|
|
33949
|
-
*
|
|
33950
|
-
*
|
|
33951
|
-
*
|
|
33952
|
-
*
|
|
33953
|
-
*
|
|
33954
|
-
*
|
|
33955
|
-
*
|
|
33956
|
-
*
|
|
33957
|
-
*
|
|
33958
|
-
*
|
|
33959
|
-
*
|
|
33960
|
-
|
|
33945
|
+
* Heap shaping for the demux isolate. The runner's process-wide V8 flags
|
|
33946
|
+
* (`--initial-old-space-size=512`, `--max-semi-space-size=8`, from the
|
|
33947
|
+
* stream-broker manifest) are sized for the MAIN isolate and leak into every
|
|
33948
|
+
* Worker: with a 512 MB initial old space the worker grew to 144 MB of
|
|
33949
|
+
* garbage without a single major GC. Explicit `resourceLimits` replace the
|
|
33950
|
+
* inherited sizing (measured under those flags with the same allocation
|
|
33951
|
+
* churn: worker heap 474 MB without limits, 88 MB with them; see
|
|
33952
|
+
* docs/history/sessions.md).
|
|
33953
|
+
*
|
|
33954
|
+
* 128 MB old generation: parsing a recorded fragment retains about 1 MB
|
|
33955
|
+
* after GC for an 86 KB input (fixture bench), so even a 10 MB fragment (a
|
|
33956
|
+
* long 4K segment) holds well under 30 MB live; 128 MB is more than 4x that.
|
|
33957
|
+
* A parse that still exceeds it fails the worker cleanly
|
|
33958
|
+
* (`ERR_WORKER_OUT_OF_MEMORY`): in-flight parses resolve null (ffmpeg
|
|
33959
|
+
* fallback) and the next parse spawns a fresh worker.
|
|
33960
|
+
*/
|
|
33961
|
+
var DEMUX_WORKER_RESOURCE_LIMITS = {
|
|
33962
|
+
maxOldGenerationSizeMb: 128,
|
|
33963
|
+
maxYoungGenerationSizeMb: 16
|
|
33964
|
+
};
|
|
33965
|
+
var defaultTimers = {
|
|
33966
|
+
set: (fn, ms) => {
|
|
33967
|
+
const t = setTimeout(fn, ms);
|
|
33968
|
+
t.unref();
|
|
33969
|
+
return t;
|
|
33970
|
+
},
|
|
33971
|
+
clear: (handle) => {
|
|
33972
|
+
if (handle !== void 0) clearTimeout(handle);
|
|
33973
|
+
}
|
|
33974
|
+
};
|
|
33961
33975
|
function isCodec(value) {
|
|
33962
33976
|
return value === "H264" || value === "H265";
|
|
33963
33977
|
}
|
|
@@ -33995,50 +34009,90 @@ function defaultWorkerFilename() {
|
|
|
33995
34009
|
/** {@link createOffThreadJsParse} plus the heap accessor the memory probe reads. */
|
|
33996
34010
|
function createOffThreadDemuxClient(deps) {
|
|
33997
34011
|
const Ctor = deps.WorkerCtor;
|
|
33998
|
-
|
|
33999
|
-
|
|
34012
|
+
const idleMs = deps.idleMs ?? 6e4;
|
|
34013
|
+
const timers = deps.timers ?? defaultTimers;
|
|
34014
|
+
const now = deps.now ?? Date.now;
|
|
34015
|
+
let current = null;
|
|
34000
34016
|
let nextId = 1;
|
|
34001
|
-
const
|
|
34002
|
-
|
|
34003
|
-
|
|
34004
|
-
|
|
34005
|
-
|
|
34017
|
+
const failAll = (slot, why) => {
|
|
34018
|
+
const waiting = [...slot.pending.values()];
|
|
34019
|
+
slot.pending.clear();
|
|
34020
|
+
if (waiting.length > 0 && deps.logger) for (const deviceId of new Set(waiting.map((p) => p.deviceId))) deps.logger.warn(`demux worker lost with parses in flight (${why}) — ffmpeg fallback`, {
|
|
34021
|
+
...deviceId !== void 0 ? { tags: { deviceId } } : {},
|
|
34022
|
+
meta: { inFlight: waiting.length }
|
|
34023
|
+
});
|
|
34024
|
+
for (const p of waiting) p.resolve(null);
|
|
34025
|
+
};
|
|
34026
|
+
const retire = (slot) => {
|
|
34027
|
+
timers.clear(slot.idleTimer);
|
|
34028
|
+
slot.idleTimer = void 0;
|
|
34029
|
+
if (current === slot) current = null;
|
|
34030
|
+
};
|
|
34031
|
+
const onIdle = async (slot) => {
|
|
34032
|
+
slot.idleTimer = void 0;
|
|
34033
|
+
if (current !== slot || slot.pending.size > 0) return;
|
|
34034
|
+
current = null;
|
|
34035
|
+
const heapBytes = (await slot.worker.getHeapStatistics?.().catch(() => null))?.total_heap_size ?? slot.lastHeapBytes;
|
|
34036
|
+
deps.logger?.info("demux worker idle — terminating", { meta: {
|
|
34037
|
+
ageMs: Math.max(0, now() - slot.spawnedAt),
|
|
34038
|
+
idleMs,
|
|
34039
|
+
lastHeapMb: Math.round(heapBytes / 1048576)
|
|
34040
|
+
} });
|
|
34041
|
+
slot.worker.terminate();
|
|
34006
34042
|
};
|
|
34007
|
-
const
|
|
34043
|
+
const armIdle = (slot) => {
|
|
34044
|
+
timers.clear(slot.idleTimer);
|
|
34045
|
+
slot.idleTimer = timers.set(() => void onIdle(slot), idleMs);
|
|
34046
|
+
};
|
|
34047
|
+
const attach = (slot) => {
|
|
34048
|
+
const w = slot.worker;
|
|
34008
34049
|
w.on("message", (message) => {
|
|
34009
34050
|
const parsed = parseWorkerMessage(message);
|
|
34010
34051
|
if (!parsed) return;
|
|
34011
|
-
const
|
|
34012
|
-
if (!
|
|
34013
|
-
pending.delete(parsed.id);
|
|
34014
|
-
resolve(parsed.aus);
|
|
34052
|
+
const pending = slot.pending.get(parsed.id);
|
|
34053
|
+
if (!pending) return;
|
|
34054
|
+
slot.pending.delete(parsed.id);
|
|
34055
|
+
pending.resolve(parsed.aus);
|
|
34056
|
+
if (slot.pending.size === 0 && current === slot) armIdle(slot);
|
|
34015
34057
|
});
|
|
34016
|
-
w.on("error", () => {
|
|
34017
|
-
|
|
34018
|
-
failAll();
|
|
34058
|
+
w.on("error", (err) => {
|
|
34059
|
+
retire(slot);
|
|
34060
|
+
failAll(slot, String(err));
|
|
34019
34061
|
});
|
|
34020
34062
|
w.on("exit", () => {
|
|
34021
|
-
|
|
34022
|
-
failAll();
|
|
34063
|
+
retire(slot);
|
|
34064
|
+
failAll(slot, "exit");
|
|
34023
34065
|
});
|
|
34024
34066
|
};
|
|
34025
34067
|
const ensureWorker = () => {
|
|
34026
|
-
if (
|
|
34068
|
+
if (current) return current;
|
|
34027
34069
|
if (!Ctor) return null;
|
|
34028
34070
|
try {
|
|
34029
|
-
const
|
|
34030
|
-
|
|
34031
|
-
|
|
34032
|
-
|
|
34033
|
-
|
|
34034
|
-
|
|
34071
|
+
const slot = {
|
|
34072
|
+
worker: new Ctor(deps.workerFilename, { resourceLimits: DEMUX_WORKER_RESOURCE_LIMITS }),
|
|
34073
|
+
pending: /* @__PURE__ */ new Map(),
|
|
34074
|
+
spawnedAt: now(),
|
|
34075
|
+
idleTimer: void 0,
|
|
34076
|
+
lastHeapBytes: 0
|
|
34077
|
+
};
|
|
34078
|
+
attach(slot);
|
|
34079
|
+
current = slot;
|
|
34080
|
+
deps.logger?.info("demux worker spawned", { meta: {
|
|
34081
|
+
resourceLimits: DEMUX_WORKER_RESOURCE_LIMITS,
|
|
34082
|
+
idleMs
|
|
34083
|
+
} });
|
|
34084
|
+
return slot;
|
|
34085
|
+
} catch (err) {
|
|
34086
|
+
deps.logger?.warn(`demux worker spawn failed: ${String(err)} — parsing in-process`);
|
|
34035
34087
|
return null;
|
|
34036
34088
|
}
|
|
34037
34089
|
};
|
|
34038
|
-
const parse = async (bytes) => {
|
|
34090
|
+
const parse = async (bytes, ctx) => {
|
|
34039
34091
|
if (!deps.existsSync(deps.workerFilename)) return deps.parseInProcess(bytes);
|
|
34040
|
-
const
|
|
34041
|
-
if (!
|
|
34092
|
+
const slot = ensureWorker();
|
|
34093
|
+
if (!slot) return deps.parseInProcess(bytes);
|
|
34094
|
+
timers.clear(slot.idleTimer);
|
|
34095
|
+
slot.idleTimer = void 0;
|
|
34042
34096
|
const id = nextId;
|
|
34043
34097
|
nextId += 1;
|
|
34044
34098
|
const copy = new Uint8Array(bytes);
|
|
@@ -34047,26 +34101,30 @@ function createOffThreadDemuxClient(deps) {
|
|
|
34047
34101
|
bytes: copy
|
|
34048
34102
|
};
|
|
34049
34103
|
return new Promise((resolve) => {
|
|
34050
|
-
pending.set(id,
|
|
34051
|
-
|
|
34104
|
+
slot.pending.set(id, {
|
|
34105
|
+
resolve,
|
|
34106
|
+
deviceId: ctx?.deviceId
|
|
34107
|
+
});
|
|
34108
|
+
slot.worker.postMessage(request, [copy.buffer]);
|
|
34052
34109
|
});
|
|
34053
34110
|
};
|
|
34054
|
-
const readHeaps = async (
|
|
34055
|
-
const live =
|
|
34111
|
+
const readHeaps = async (at = Date.now()) => {
|
|
34112
|
+
const live = current;
|
|
34056
34113
|
const empty = {
|
|
34057
34114
|
workers: 0,
|
|
34058
34115
|
heapBytes: 0,
|
|
34059
34116
|
physicalBytes: 0,
|
|
34060
34117
|
usedBytes: 0,
|
|
34061
34118
|
maxAgeMs: 0,
|
|
34062
|
-
idleTerminates:
|
|
34119
|
+
idleTerminates: true
|
|
34063
34120
|
};
|
|
34064
34121
|
if (live === null) return empty;
|
|
34065
|
-
const stats = await live.getHeapStatistics?.().catch(() => null);
|
|
34122
|
+
const stats = await live.worker.getHeapStatistics?.().catch(() => null);
|
|
34123
|
+
if (stats) live.lastHeapBytes = stats.total_heap_size;
|
|
34066
34124
|
return {
|
|
34067
34125
|
...empty,
|
|
34068
34126
|
workers: 1,
|
|
34069
|
-
maxAgeMs: Math.max(0,
|
|
34127
|
+
maxAgeMs: Math.max(0, at - live.spawnedAt),
|
|
34070
34128
|
...stats ? {
|
|
34071
34129
|
heapBytes: stats.total_heap_size,
|
|
34072
34130
|
physicalBytes: stats.total_physical_size,
|
|
@@ -34084,15 +34142,21 @@ function defaultOffThreadClient() {
|
|
|
34084
34142
|
workerFilename: defaultWorkerFilename(),
|
|
34085
34143
|
existsSync: node_fs.existsSync,
|
|
34086
34144
|
parseInProcess: require_segment_demux_js.demuxSegmentFullJs,
|
|
34087
|
-
WorkerCtor: node_worker_threads.Worker
|
|
34145
|
+
WorkerCtor: node_worker_threads.Worker,
|
|
34146
|
+
...sharedLogger ? { logger: sharedLogger } : {}
|
|
34088
34147
|
});
|
|
34089
34148
|
}
|
|
34090
34149
|
var shared;
|
|
34091
34150
|
/** Process-wide JS parse: one Worker, shared by every WebRTC session. */
|
|
34092
|
-
var offThreadJsParse = (bytes) => {
|
|
34151
|
+
var offThreadJsParse = (bytes, ctx) => {
|
|
34093
34152
|
shared ??= defaultOffThreadClient();
|
|
34094
|
-
return shared.parse(bytes);
|
|
34153
|
+
return shared.parse(bytes, ctx);
|
|
34095
34154
|
};
|
|
34155
|
+
var sharedLogger;
|
|
34156
|
+
/** Give the process-wide client a logger; call before the first parse. */
|
|
34157
|
+
function setDemuxWorkerLogger(logger) {
|
|
34158
|
+
sharedLogger = logger;
|
|
34159
|
+
}
|
|
34096
34160
|
/** Heap of the shared demux worker, for the `[broker-mem]` probe (tick only). */
|
|
34097
34161
|
async function readDemuxWorkerHeaps(now) {
|
|
34098
34162
|
return shared ? shared.readHeaps(now) : {
|
|
@@ -34101,7 +34165,7 @@ async function readDemuxWorkerHeaps(now) {
|
|
|
34101
34165
|
physicalBytes: 0,
|
|
34102
34166
|
usedBytes: 0,
|
|
34103
34167
|
maxAgeMs: 0,
|
|
34104
|
-
idleTerminates:
|
|
34168
|
+
idleTerminates: true
|
|
34105
34169
|
};
|
|
34106
34170
|
}
|
|
34107
34171
|
/**
|
|
@@ -35004,6 +35068,7 @@ var BrokerWebrtcServer = class {
|
|
|
35004
35068
|
stopped = false;
|
|
35005
35069
|
constructor(options) {
|
|
35006
35070
|
this.logger = options.logger;
|
|
35071
|
+
setDemuxWorkerLogger(options.logger.child("demux-worker"));
|
|
35007
35072
|
this.getIceServersFn = options.getIceServers;
|
|
35008
35073
|
this.staticIceServers = options.iceServers;
|
|
35009
35074
|
this.icePortRange = options.icePortRange;
|
|
@@ -35669,6 +35734,7 @@ var BrokerWebrtcServer = class {
|
|
|
35669
35734
|
if (locateRecorded && readRecorded) {
|
|
35670
35735
|
const demuxVideo = (b) => demuxSegmentPreferJsOffThread(b, {
|
|
35671
35736
|
ffmpegPath: resolveFfmpeg(),
|
|
35737
|
+
deviceId,
|
|
35672
35738
|
onDemuxPath: (outcome) => {
|
|
35673
35739
|
const report = demuxTally.record(outcome, Date.now());
|
|
35674
35740
|
if (!report) return;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { r as __toESM } from "../chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { $n as discriminatedUnion, An as BaseAddon, D as G711_SCALE_CORRECTION_DB, Dn as DeviceType, Dt as gifDeriveSpeed, En as DeviceFeature, Gn as maskUrlCredentials, Hn as isEvent, I as RATE_CONTROL_RELAXED, In as createEvent, J as addonWidgetsSourceCapability, Kn as nodePin, L as RATE_CONTROL_TIGHT, Mn as CamProfileSchema, Nt as loadContributionCapability, On as errMsg, Ot as gifFromMp4Args, Pt as logChannelsCapability, Qn as boolean, Rt as memoizePinnedFfmpeg, Sn as buildFfmpegArgs, Tn as isSoftwareDecode, Tt as ffmpegRate, Un as makeProfileBrokerId, W as RingBuffer, Wn as makeSourceBrokerId, Xn as _enum, Xt as rankStreams, Zn as array, _t as egressTranscodeSharingKey, ar as record, at as clipExportFailureOf, c as CLIP_STILL_REASON_CODE_HEADER, cr as EventCategory, ct as createHwAccelCache, et as batteryCapability, ft as deriveBatteryPresence, jn as CAM_PROFILE_ORDER, kn as BOOT_RECOVERY_BACKOFF_MS, lt as createLogChannelsProvider, mn as streamBrokerCapability, nr as number, o as BatteryStatusSchema, or as string, qn as parseProfileBrokerId, rn as resolveEgressDecodeHwAccel, rr as object, rt as cameraStreamsCapability, s as CLIP_BROKER_PACED_RATES, sr as union, tr as literal, ut as declareLogChannel, vn as webrtcSessionCapability, vt as egressTransportFromRequest, w as EncodeProfileSchema, wn as invocationFromEncodeProfile, yn as AUDIO_PRESETS, zn as expandAudioChunkToF32le } from "../dist-
|
|
3
|
-
import { i as NO_COST_CLAIM, n as Fmp4FragmentChild, o as probeFfmpegBinary, r as Fmp4FragmentPlane, t as ChildCostRegistry } from "../node-
|
|
2
|
+
import { $n as discriminatedUnion, An as BaseAddon, D as G711_SCALE_CORRECTION_DB, Dn as DeviceType, Dt as gifDeriveSpeed, En as DeviceFeature, Gn as maskUrlCredentials, Hn as isEvent, I as RATE_CONTROL_RELAXED, In as createEvent, J as addonWidgetsSourceCapability, Kn as nodePin, L as RATE_CONTROL_TIGHT, Mn as CamProfileSchema, Nt as loadContributionCapability, On as errMsg, Ot as gifFromMp4Args, Pt as logChannelsCapability, Qn as boolean, Rt as memoizePinnedFfmpeg, Sn as buildFfmpegArgs, Tn as isSoftwareDecode, Tt as ffmpegRate, Un as makeProfileBrokerId, W as RingBuffer, Wn as makeSourceBrokerId, Xn as _enum, Xt as rankStreams, Zn as array, _t as egressTranscodeSharingKey, ar as record, at as clipExportFailureOf, c as CLIP_STILL_REASON_CODE_HEADER, cr as EventCategory, ct as createHwAccelCache, et as batteryCapability, ft as deriveBatteryPresence, jn as CAM_PROFILE_ORDER, kn as BOOT_RECOVERY_BACKOFF_MS, lt as createLogChannelsProvider, mn as streamBrokerCapability, nr as number, o as BatteryStatusSchema, or as string, qn as parseProfileBrokerId, rn as resolveEgressDecodeHwAccel, rr as object, rt as cameraStreamsCapability, s as CLIP_BROKER_PACED_RATES, sr as union, tr as literal, ut as declareLogChannel, vn as webrtcSessionCapability, vt as egressTransportFromRequest, w as EncodeProfileSchema, wn as invocationFromEncodeProfile, yn as AUDIO_PRESETS, zn as expandAudioChunkToF32le } from "../dist-5AhGOWWu.mjs";
|
|
3
|
+
import { i as NO_COST_CLAIM, n as Fmp4FragmentChild, o as probeFfmpegBinary, r as Fmp4FragmentPlane, t as ChildCostRegistry } from "../node-DqZJFOzR.mjs";
|
|
4
4
|
import { a as parseRestreamPath, d as PREBUFFER_MAX_MS, f as capPreRollRequestMs, i as isLiveEdgeOnlyDial, m as resolvePrebuffer, n as NO_DECLARATION, p as prebufferRetentionMs, s as sdpVariantFor, u as withSentryIntent } from "../restream-intent-DyGmLAU9.mjs";
|
|
5
5
|
import { n as profileForStreamId } from "../remote-restream-BeHi78PZ.mjs";
|
|
6
6
|
import { n as RowMapStore, t as retireRootKeys } from "../retire-root-keys-DZvlso2l.mjs";
|
|
7
|
-
import { a as require_mp4box_all, c as parseNalLengthSize, i as runFfmpegOnce, n as demuxSegmentPreferJs, o as avccSampleToAnnexB, r as FfmpegFallbackRefusedError, s as buildKeyframeAnnexB, t as demuxSegmentFullJs } from "../segment-demux-js-
|
|
7
|
+
import { a as require_mp4box_all, c as parseNalLengthSize, i as runFfmpegOnce, n as demuxSegmentPreferJs, o as avccSampleToAnnexB, r as FfmpegFallbackRefusedError, s as buildKeyframeAnnexB, t as demuxSegmentFullJs } from "../segment-demux-js-dlhO3Q8W.mjs";
|
|
8
8
|
import { createRequire } from "node:module";
|
|
9
9
|
import * as os$1 from "node:os";
|
|
10
10
|
import { networkInterfaces, tmpdir } from "node:os";
|
|
@@ -33937,23 +33937,37 @@ function createHttpClipStreamOpener(options = {}) {
|
|
|
33937
33937
|
req.end();
|
|
33938
33938
|
});
|
|
33939
33939
|
}
|
|
33940
|
-
//#endregion
|
|
33941
|
-
//#region src/stream-broker/recorded/demux-off-thread.ts
|
|
33942
33940
|
/**
|
|
33943
|
-
*
|
|
33944
|
-
*
|
|
33945
|
-
*
|
|
33946
|
-
*
|
|
33947
|
-
*
|
|
33948
|
-
*
|
|
33949
|
-
*
|
|
33950
|
-
*
|
|
33951
|
-
*
|
|
33952
|
-
*
|
|
33953
|
-
*
|
|
33954
|
-
*
|
|
33955
|
-
*
|
|
33956
|
-
|
|
33941
|
+
* Heap shaping for the demux isolate. The runner's process-wide V8 flags
|
|
33942
|
+
* (`--initial-old-space-size=512`, `--max-semi-space-size=8`, from the
|
|
33943
|
+
* stream-broker manifest) are sized for the MAIN isolate and leak into every
|
|
33944
|
+
* Worker: with a 512 MB initial old space the worker grew to 144 MB of
|
|
33945
|
+
* garbage without a single major GC. Explicit `resourceLimits` replace the
|
|
33946
|
+
* inherited sizing (measured under those flags with the same allocation
|
|
33947
|
+
* churn: worker heap 474 MB without limits, 88 MB with them; see
|
|
33948
|
+
* docs/history/sessions.md).
|
|
33949
|
+
*
|
|
33950
|
+
* 128 MB old generation: parsing a recorded fragment retains about 1 MB
|
|
33951
|
+
* after GC for an 86 KB input (fixture bench), so even a 10 MB fragment (a
|
|
33952
|
+
* long 4K segment) holds well under 30 MB live; 128 MB is more than 4x that.
|
|
33953
|
+
* A parse that still exceeds it fails the worker cleanly
|
|
33954
|
+
* (`ERR_WORKER_OUT_OF_MEMORY`): in-flight parses resolve null (ffmpeg
|
|
33955
|
+
* fallback) and the next parse spawns a fresh worker.
|
|
33956
|
+
*/
|
|
33957
|
+
var DEMUX_WORKER_RESOURCE_LIMITS = {
|
|
33958
|
+
maxOldGenerationSizeMb: 128,
|
|
33959
|
+
maxYoungGenerationSizeMb: 16
|
|
33960
|
+
};
|
|
33961
|
+
var defaultTimers = {
|
|
33962
|
+
set: (fn, ms) => {
|
|
33963
|
+
const t = setTimeout(fn, ms);
|
|
33964
|
+
t.unref();
|
|
33965
|
+
return t;
|
|
33966
|
+
},
|
|
33967
|
+
clear: (handle) => {
|
|
33968
|
+
if (handle !== void 0) clearTimeout(handle);
|
|
33969
|
+
}
|
|
33970
|
+
};
|
|
33957
33971
|
function isCodec(value) {
|
|
33958
33972
|
return value === "H264" || value === "H265";
|
|
33959
33973
|
}
|
|
@@ -33991,50 +34005,90 @@ function defaultWorkerFilename() {
|
|
|
33991
34005
|
/** {@link createOffThreadJsParse} plus the heap accessor the memory probe reads. */
|
|
33992
34006
|
function createOffThreadDemuxClient(deps) {
|
|
33993
34007
|
const Ctor = deps.WorkerCtor;
|
|
33994
|
-
|
|
33995
|
-
|
|
34008
|
+
const idleMs = deps.idleMs ?? 6e4;
|
|
34009
|
+
const timers = deps.timers ?? defaultTimers;
|
|
34010
|
+
const now = deps.now ?? Date.now;
|
|
34011
|
+
let current = null;
|
|
33996
34012
|
let nextId = 1;
|
|
33997
|
-
const
|
|
33998
|
-
|
|
33999
|
-
|
|
34000
|
-
|
|
34001
|
-
|
|
34013
|
+
const failAll = (slot, why) => {
|
|
34014
|
+
const waiting = [...slot.pending.values()];
|
|
34015
|
+
slot.pending.clear();
|
|
34016
|
+
if (waiting.length > 0 && deps.logger) for (const deviceId of new Set(waiting.map((p) => p.deviceId))) deps.logger.warn(`demux worker lost with parses in flight (${why}) — ffmpeg fallback`, {
|
|
34017
|
+
...deviceId !== void 0 ? { tags: { deviceId } } : {},
|
|
34018
|
+
meta: { inFlight: waiting.length }
|
|
34019
|
+
});
|
|
34020
|
+
for (const p of waiting) p.resolve(null);
|
|
34021
|
+
};
|
|
34022
|
+
const retire = (slot) => {
|
|
34023
|
+
timers.clear(slot.idleTimer);
|
|
34024
|
+
slot.idleTimer = void 0;
|
|
34025
|
+
if (current === slot) current = null;
|
|
34026
|
+
};
|
|
34027
|
+
const onIdle = async (slot) => {
|
|
34028
|
+
slot.idleTimer = void 0;
|
|
34029
|
+
if (current !== slot || slot.pending.size > 0) return;
|
|
34030
|
+
current = null;
|
|
34031
|
+
const heapBytes = (await slot.worker.getHeapStatistics?.().catch(() => null))?.total_heap_size ?? slot.lastHeapBytes;
|
|
34032
|
+
deps.logger?.info("demux worker idle — terminating", { meta: {
|
|
34033
|
+
ageMs: Math.max(0, now() - slot.spawnedAt),
|
|
34034
|
+
idleMs,
|
|
34035
|
+
lastHeapMb: Math.round(heapBytes / 1048576)
|
|
34036
|
+
} });
|
|
34037
|
+
slot.worker.terminate();
|
|
34002
34038
|
};
|
|
34003
|
-
const
|
|
34039
|
+
const armIdle = (slot) => {
|
|
34040
|
+
timers.clear(slot.idleTimer);
|
|
34041
|
+
slot.idleTimer = timers.set(() => void onIdle(slot), idleMs);
|
|
34042
|
+
};
|
|
34043
|
+
const attach = (slot) => {
|
|
34044
|
+
const w = slot.worker;
|
|
34004
34045
|
w.on("message", (message) => {
|
|
34005
34046
|
const parsed = parseWorkerMessage(message);
|
|
34006
34047
|
if (!parsed) return;
|
|
34007
|
-
const
|
|
34008
|
-
if (!
|
|
34009
|
-
pending.delete(parsed.id);
|
|
34010
|
-
resolve(parsed.aus);
|
|
34048
|
+
const pending = slot.pending.get(parsed.id);
|
|
34049
|
+
if (!pending) return;
|
|
34050
|
+
slot.pending.delete(parsed.id);
|
|
34051
|
+
pending.resolve(parsed.aus);
|
|
34052
|
+
if (slot.pending.size === 0 && current === slot) armIdle(slot);
|
|
34011
34053
|
});
|
|
34012
|
-
w.on("error", () => {
|
|
34013
|
-
|
|
34014
|
-
failAll();
|
|
34054
|
+
w.on("error", (err) => {
|
|
34055
|
+
retire(slot);
|
|
34056
|
+
failAll(slot, String(err));
|
|
34015
34057
|
});
|
|
34016
34058
|
w.on("exit", () => {
|
|
34017
|
-
|
|
34018
|
-
failAll();
|
|
34059
|
+
retire(slot);
|
|
34060
|
+
failAll(slot, "exit");
|
|
34019
34061
|
});
|
|
34020
34062
|
};
|
|
34021
34063
|
const ensureWorker = () => {
|
|
34022
|
-
if (
|
|
34064
|
+
if (current) return current;
|
|
34023
34065
|
if (!Ctor) return null;
|
|
34024
34066
|
try {
|
|
34025
|
-
const
|
|
34026
|
-
|
|
34027
|
-
|
|
34028
|
-
|
|
34029
|
-
|
|
34030
|
-
|
|
34067
|
+
const slot = {
|
|
34068
|
+
worker: new Ctor(deps.workerFilename, { resourceLimits: DEMUX_WORKER_RESOURCE_LIMITS }),
|
|
34069
|
+
pending: /* @__PURE__ */ new Map(),
|
|
34070
|
+
spawnedAt: now(),
|
|
34071
|
+
idleTimer: void 0,
|
|
34072
|
+
lastHeapBytes: 0
|
|
34073
|
+
};
|
|
34074
|
+
attach(slot);
|
|
34075
|
+
current = slot;
|
|
34076
|
+
deps.logger?.info("demux worker spawned", { meta: {
|
|
34077
|
+
resourceLimits: DEMUX_WORKER_RESOURCE_LIMITS,
|
|
34078
|
+
idleMs
|
|
34079
|
+
} });
|
|
34080
|
+
return slot;
|
|
34081
|
+
} catch (err) {
|
|
34082
|
+
deps.logger?.warn(`demux worker spawn failed: ${String(err)} — parsing in-process`);
|
|
34031
34083
|
return null;
|
|
34032
34084
|
}
|
|
34033
34085
|
};
|
|
34034
|
-
const parse = async (bytes) => {
|
|
34086
|
+
const parse = async (bytes, ctx) => {
|
|
34035
34087
|
if (!deps.existsSync(deps.workerFilename)) return deps.parseInProcess(bytes);
|
|
34036
|
-
const
|
|
34037
|
-
if (!
|
|
34088
|
+
const slot = ensureWorker();
|
|
34089
|
+
if (!slot) return deps.parseInProcess(bytes);
|
|
34090
|
+
timers.clear(slot.idleTimer);
|
|
34091
|
+
slot.idleTimer = void 0;
|
|
34038
34092
|
const id = nextId;
|
|
34039
34093
|
nextId += 1;
|
|
34040
34094
|
const copy = new Uint8Array(bytes);
|
|
@@ -34043,26 +34097,30 @@ function createOffThreadDemuxClient(deps) {
|
|
|
34043
34097
|
bytes: copy
|
|
34044
34098
|
};
|
|
34045
34099
|
return new Promise((resolve) => {
|
|
34046
|
-
pending.set(id,
|
|
34047
|
-
|
|
34100
|
+
slot.pending.set(id, {
|
|
34101
|
+
resolve,
|
|
34102
|
+
deviceId: ctx?.deviceId
|
|
34103
|
+
});
|
|
34104
|
+
slot.worker.postMessage(request, [copy.buffer]);
|
|
34048
34105
|
});
|
|
34049
34106
|
};
|
|
34050
|
-
const readHeaps = async (
|
|
34051
|
-
const live =
|
|
34107
|
+
const readHeaps = async (at = Date.now()) => {
|
|
34108
|
+
const live = current;
|
|
34052
34109
|
const empty = {
|
|
34053
34110
|
workers: 0,
|
|
34054
34111
|
heapBytes: 0,
|
|
34055
34112
|
physicalBytes: 0,
|
|
34056
34113
|
usedBytes: 0,
|
|
34057
34114
|
maxAgeMs: 0,
|
|
34058
|
-
idleTerminates:
|
|
34115
|
+
idleTerminates: true
|
|
34059
34116
|
};
|
|
34060
34117
|
if (live === null) return empty;
|
|
34061
|
-
const stats = await live.getHeapStatistics?.().catch(() => null);
|
|
34118
|
+
const stats = await live.worker.getHeapStatistics?.().catch(() => null);
|
|
34119
|
+
if (stats) live.lastHeapBytes = stats.total_heap_size;
|
|
34062
34120
|
return {
|
|
34063
34121
|
...empty,
|
|
34064
34122
|
workers: 1,
|
|
34065
|
-
maxAgeMs: Math.max(0,
|
|
34123
|
+
maxAgeMs: Math.max(0, at - live.spawnedAt),
|
|
34066
34124
|
...stats ? {
|
|
34067
34125
|
heapBytes: stats.total_heap_size,
|
|
34068
34126
|
physicalBytes: stats.total_physical_size,
|
|
@@ -34080,15 +34138,21 @@ function defaultOffThreadClient() {
|
|
|
34080
34138
|
workerFilename: defaultWorkerFilename(),
|
|
34081
34139
|
existsSync,
|
|
34082
34140
|
parseInProcess: demuxSegmentFullJs,
|
|
34083
|
-
WorkerCtor: Worker
|
|
34141
|
+
WorkerCtor: Worker,
|
|
34142
|
+
...sharedLogger ? { logger: sharedLogger } : {}
|
|
34084
34143
|
});
|
|
34085
34144
|
}
|
|
34086
34145
|
var shared;
|
|
34087
34146
|
/** Process-wide JS parse: one Worker, shared by every WebRTC session. */
|
|
34088
|
-
var offThreadJsParse = (bytes) => {
|
|
34147
|
+
var offThreadJsParse = (bytes, ctx) => {
|
|
34089
34148
|
shared ??= defaultOffThreadClient();
|
|
34090
|
-
return shared.parse(bytes);
|
|
34149
|
+
return shared.parse(bytes, ctx);
|
|
34091
34150
|
};
|
|
34151
|
+
var sharedLogger;
|
|
34152
|
+
/** Give the process-wide client a logger; call before the first parse. */
|
|
34153
|
+
function setDemuxWorkerLogger(logger) {
|
|
34154
|
+
sharedLogger = logger;
|
|
34155
|
+
}
|
|
34092
34156
|
/** Heap of the shared demux worker, for the `[broker-mem]` probe (tick only). */
|
|
34093
34157
|
async function readDemuxWorkerHeaps(now) {
|
|
34094
34158
|
return shared ? shared.readHeaps(now) : {
|
|
@@ -34097,7 +34161,7 @@ async function readDemuxWorkerHeaps(now) {
|
|
|
34097
34161
|
physicalBytes: 0,
|
|
34098
34162
|
usedBytes: 0,
|
|
34099
34163
|
maxAgeMs: 0,
|
|
34100
|
-
idleTerminates:
|
|
34164
|
+
idleTerminates: true
|
|
34101
34165
|
};
|
|
34102
34166
|
}
|
|
34103
34167
|
/**
|
|
@@ -35000,6 +35064,7 @@ var BrokerWebrtcServer = class {
|
|
|
35000
35064
|
stopped = false;
|
|
35001
35065
|
constructor(options) {
|
|
35002
35066
|
this.logger = options.logger;
|
|
35067
|
+
setDemuxWorkerLogger(options.logger.child("demux-worker"));
|
|
35003
35068
|
this.getIceServersFn = options.getIceServers;
|
|
35004
35069
|
this.staticIceServers = options.iceServers;
|
|
35005
35070
|
this.icePortRange = options.icePortRange;
|
|
@@ -35665,6 +35730,7 @@ var BrokerWebrtcServer = class {
|
|
|
35665
35730
|
if (locateRecorded && readRecorded) {
|
|
35666
35731
|
const demuxVideo = (b) => demuxSegmentPreferJsOffThread(b, {
|
|
35667
35732
|
ffmpegPath: resolveFfmpeg(),
|
|
35733
|
+
deviceId,
|
|
35668
35734
|
onDemuxPath: (outcome) => {
|
|
35669
35735
|
const report = demuxTally.record(outcome, Date.now());
|
|
35670
35736
|
if (!report) return;
|
|
@@ -30,7 +30,7 @@ async function d(e) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async function f() {
|
|
33
|
-
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-
|
|
33
|
+
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CSajlHKC.mjs")).catch((e) => {
|
|
34
34
|
throw l = void 0, e;
|
|
35
35
|
}), l;
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-pipeline",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.368",
|
|
4
4
|
"description": "Pipeline bundle — runner, detection, motion, audio + stream broker. Multi-entry npm package shipping pipeline addons under a single bundle.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|