@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
|
@@ -2,26 +2,27 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
+
const require_dist = require("../dist-ByPsWlTa.js");
|
|
7
|
+
const require_node = require("../node-CNPnaux4.js");
|
|
7
8
|
const require_restream_intent = require("../restream-intent-B1Difcnq.js");
|
|
8
9
|
const require_remote_restream = require("../remote-restream-CO36Sr30.js");
|
|
9
10
|
const require_retire_root_keys = require("../retire-root-keys-Csb8z2f3.js");
|
|
10
|
-
const require_segment_demux_js = require("../segment-demux-js-
|
|
11
|
+
const require_segment_demux_js = require("../segment-demux-js-CZefXDLx.js");
|
|
11
12
|
let node_os = require("node:os");
|
|
12
|
-
node_os =
|
|
13
|
+
node_os = require_chunk.__toESM(node_os);
|
|
13
14
|
let node_crypto = require("node:crypto");
|
|
14
|
-
node_crypto =
|
|
15
|
+
node_crypto = require_chunk.__toESM(node_crypto);
|
|
15
16
|
let node_fs = require("node:fs");
|
|
16
|
-
node_fs =
|
|
17
|
+
node_fs = require_chunk.__toESM(node_fs);
|
|
17
18
|
let node_path = require("node:path");
|
|
18
|
-
node_path =
|
|
19
|
+
node_path = require_chunk.__toESM(node_path);
|
|
19
20
|
let node_child_process = require("node:child_process");
|
|
20
21
|
let node_fs_promises = require("node:fs/promises");
|
|
21
22
|
let node_url = require("node:url");
|
|
22
23
|
let node_module = require("node:module");
|
|
23
24
|
let node_net = require("node:net");
|
|
24
|
-
node_net =
|
|
25
|
+
node_net = require_chunk.__toESM(node_net);
|
|
25
26
|
let node_dgram = require("node:dgram");
|
|
26
27
|
let events = require("events");
|
|
27
28
|
let net = require("net");
|
|
@@ -8380,14 +8381,14 @@ function depacketizeRfc3640(payload, opts = {
|
|
|
8380
8381
|
}
|
|
8381
8382
|
//#endregion
|
|
8382
8383
|
//#region src/stream-broker/rtsp/audio-rtp-decoder.ts
|
|
8383
|
-
/**
|
|
8384
|
-
var
|
|
8385
|
-
var CHUNK_SAMPLES =
|
|
8384
|
+
/** G.711 is 8 kHz by definition (RFC 3551): the plane carries that rate. */
|
|
8385
|
+
var G711_SAMPLE_RATE = 8e3;
|
|
8386
|
+
var CHUNK_SAMPLES = G711_SAMPLE_RATE * 500 / 1e3;
|
|
8386
8387
|
/**
|
|
8387
|
-
* Decodes G.711 audio RTP packets into PCM f32le chunks.
|
|
8388
|
+
* Decodes G.711 audio RTP packets into PCM f32le chunks at 8 kHz.
|
|
8388
8389
|
*
|
|
8389
|
-
* Buffers decoded samples and emits DecodedAudioChunk when
|
|
8390
|
-
*
|
|
8390
|
+
* Buffers decoded samples and emits a DecodedAudioChunk when ~0.5 s has
|
|
8391
|
+
* accumulated (4000 samples, 16 000 bytes).
|
|
8391
8392
|
*/
|
|
8392
8393
|
var AudioRtpDecoder = class {
|
|
8393
8394
|
codec;
|
|
@@ -8401,18 +8402,14 @@ var AudioRtpDecoder = class {
|
|
|
8401
8402
|
}
|
|
8402
8403
|
/**
|
|
8403
8404
|
* Process a raw RTP packet (header + payload).
|
|
8404
|
-
* Strips the 12-byte RTP header
|
|
8405
|
+
* Strips the 12-byte RTP header and decodes the G.711 payload: one byte,
|
|
8406
|
+
* one 8 kHz sample. Nothing is interpolated here.
|
|
8405
8407
|
*/
|
|
8406
8408
|
processPacket(rtpData) {
|
|
8407
8409
|
if (rtpData.length <= 12) return;
|
|
8408
8410
|
const payload = rtpData.subarray(12);
|
|
8409
8411
|
const decode = this.codec === "PCMU" ? decodeUlaw : decodeAlaw;
|
|
8410
|
-
for (let i = 0; i < payload.length; i++)
|
|
8411
|
-
const current = decode(payload[i]);
|
|
8412
|
-
const next = i + 1 < payload.length ? decode(payload[i + 1]) : current;
|
|
8413
|
-
this.pushSample(current);
|
|
8414
|
-
this.pushSample((current + next) * .5);
|
|
8415
|
-
}
|
|
8412
|
+
for (let i = 0; i < payload.length; i++) this.pushSample(decode(payload[i]));
|
|
8416
8413
|
}
|
|
8417
8414
|
/** Flush any remaining buffered samples as a partial chunk. */
|
|
8418
8415
|
flush() {
|
|
@@ -8420,7 +8417,7 @@ var AudioRtpDecoder = class {
|
|
|
8420
8417
|
const data = Buffer.from(this.buffer.buffer, this.buffer.byteOffset, this.bufferOffset * 4);
|
|
8421
8418
|
this.onChunk({
|
|
8422
8419
|
data: Buffer.from(data),
|
|
8423
|
-
sampleRate:
|
|
8420
|
+
sampleRate: G711_SAMPLE_RATE,
|
|
8424
8421
|
channels: 1,
|
|
8425
8422
|
timestamp: Date.now()
|
|
8426
8423
|
});
|
|
@@ -8436,7 +8433,7 @@ var AudioRtpDecoder = class {
|
|
|
8436
8433
|
const data = Buffer.from(this.buffer.buffer, this.buffer.byteOffset, CHUNK_SAMPLES * 4);
|
|
8437
8434
|
this.onChunk({
|
|
8438
8435
|
data: Buffer.from(data),
|
|
8439
|
-
sampleRate:
|
|
8436
|
+
sampleRate: G711_SAMPLE_RATE,
|
|
8440
8437
|
channels: 1,
|
|
8441
8438
|
timestamp: Date.now()
|
|
8442
8439
|
});
|
|
@@ -13694,7 +13691,9 @@ var StreamBroker = class StreamBroker {
|
|
|
13694
13691
|
this.logger?.info("native: audio decoder initialized", { meta: {
|
|
13695
13692
|
codec: codecUpper,
|
|
13696
13693
|
sampleRate: audioTrack.clockRate,
|
|
13697
|
-
channels: audioTrack.channels
|
|
13694
|
+
channels: audioTrack.channels,
|
|
13695
|
+
planeSampleRate: G711_SAMPLE_RATE,
|
|
13696
|
+
planeFormat: "f32le"
|
|
13698
13697
|
} });
|
|
13699
13698
|
} else if (this.audioCodecApi) {
|
|
13700
13699
|
const capCfg = this.buildAudioCodecSessionConfig(audioTrack);
|
|
@@ -27485,7 +27484,7 @@ async function demuxSegmentToPcmu(bytes, ffmpegPath = "ffmpeg") {
|
|
|
27485
27484
|
}
|
|
27486
27485
|
//#endregion
|
|
27487
27486
|
//#region src/stream-broker/recorded/segment-audio-js.ts
|
|
27488
|
-
var import_mp4box_all = /* @__PURE__ */
|
|
27487
|
+
var import_mp4box_all = /* @__PURE__ */ require_chunk.__toESM(require_segment_demux_js.require_mp4box_all());
|
|
27489
27488
|
/** True for an mp4box audio codec string that is Opus (`Opus`/`opus`). */
|
|
27490
27489
|
function isOpusCodec(codec) {
|
|
27491
27490
|
return /^opus$/i.test(codec);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { r as __toESM } from "../chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { A as addonWidgetsSourceCapability, Bt as invocationFromEncodeProfile, C as RATE_CONTROL_RELAXED, F as cameraStreamsCapability, Ft as webrtcSessionCapability, Gt as DeviceFeature, H as deriveBatteryPresence, Ht as BOOT_RECOVERY_BACKOFF_MS, I as createHwAccelCache, It as errMsg, K as egressTranscodeSharingKey, Kt as DeviceType, L as createLogChannelsProvider, Lt as AUDIO_PRESETS, Mt as streamBrokerCapability, O as RingBuffer, P as batteryCapability, Qt as nodePin, Tt as resolveEgressDecodeHwAccel, Ut as BaseAddon, Vt as isSoftwareDecode, Wt as CAM_PROFILE_ORDER, Xt as makeProfileBrokerId, Yt as isEvent, Zt as makeSourceBrokerId, an as boolean, at as logChannelsCapability, cn as literal, en as parseProfileBrokerId, fn as record, h as EncodeProfileSchema, hn as EventCategory, i as BatteryStatusSchema, in as array, it as loadContributionCapability, ln as number, mn as union, on as discriminatedUnion, pn as string, q as egressTransportFromRequest, qt as createEvent, rn as _enum, st as maskUrlCredentials, un as object, w as RATE_CONTROL_TIGHT, z as declareLogChannel, zt as buildFfmpegArgs$1 } from "../dist-
|
|
3
|
-
import { i as NO_COST_CLAIM, n as Fmp4FragmentChild, r as Fmp4FragmentPlane, t as ChildCostRegistry } from "../node-
|
|
2
|
+
import { A as addonWidgetsSourceCapability, Bt as invocationFromEncodeProfile, C as RATE_CONTROL_RELAXED, F as cameraStreamsCapability, Ft as webrtcSessionCapability, Gt as DeviceFeature, H as deriveBatteryPresence, Ht as BOOT_RECOVERY_BACKOFF_MS, I as createHwAccelCache, It as errMsg, K as egressTranscodeSharingKey, Kt as DeviceType, L as createLogChannelsProvider, Lt as AUDIO_PRESETS, Mt as streamBrokerCapability, O as RingBuffer, P as batteryCapability, Qt as nodePin, Tt as resolveEgressDecodeHwAccel, Ut as BaseAddon, Vt as isSoftwareDecode, Wt as CAM_PROFILE_ORDER, Xt as makeProfileBrokerId, Yt as isEvent, Zt as makeSourceBrokerId, an as boolean, at as logChannelsCapability, cn as literal, en as parseProfileBrokerId, fn as record, h as EncodeProfileSchema, hn as EventCategory, i as BatteryStatusSchema, in as array, it as loadContributionCapability, ln as number, mn as union, on as discriminatedUnion, pn as string, q as egressTransportFromRequest, qt as createEvent, rn as _enum, st as maskUrlCredentials, un as object, w as RATE_CONTROL_TIGHT, z as declareLogChannel, zt as buildFfmpegArgs$1 } from "../dist-ClihWGOZ.mjs";
|
|
3
|
+
import { i as NO_COST_CLAIM, n as Fmp4FragmentChild, r as Fmp4FragmentPlane, t as ChildCostRegistry } from "../node-DiaTmz84.mjs";
|
|
4
4
|
import { c as PREBUFFER_MAX_MS, d as resolvePrebuffer, i as parseRestreamPath, l as capPreRollRequestMs, n as NO_DECLARATION, u as prebufferRetentionMs } from "../restream-intent-DWe2kInY.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 { i as require_mp4box_all, n as demuxSegmentPreferJs, r as runFfmpegOnce, t as demuxSegmentFullJs } from "../segment-demux-js-
|
|
7
|
+
import { i as require_mp4box_all, n as demuxSegmentPreferJs, r as runFfmpegOnce, t as demuxSegmentFullJs } from "../segment-demux-js-CFFXVae4.mjs";
|
|
8
8
|
import { createRequire } from "node:module";
|
|
9
9
|
import * as os from "node:os";
|
|
10
10
|
import { networkInterfaces, tmpdir } from "node:os";
|
|
@@ -8377,14 +8377,14 @@ function depacketizeRfc3640(payload, opts = {
|
|
|
8377
8377
|
}
|
|
8378
8378
|
//#endregion
|
|
8379
8379
|
//#region src/stream-broker/rtsp/audio-rtp-decoder.ts
|
|
8380
|
-
/**
|
|
8381
|
-
var
|
|
8382
|
-
var CHUNK_SAMPLES =
|
|
8380
|
+
/** G.711 is 8 kHz by definition (RFC 3551): the plane carries that rate. */
|
|
8381
|
+
var G711_SAMPLE_RATE = 8e3;
|
|
8382
|
+
var CHUNK_SAMPLES = G711_SAMPLE_RATE * 500 / 1e3;
|
|
8383
8383
|
/**
|
|
8384
|
-
* Decodes G.711 audio RTP packets into PCM f32le chunks.
|
|
8384
|
+
* Decodes G.711 audio RTP packets into PCM f32le chunks at 8 kHz.
|
|
8385
8385
|
*
|
|
8386
|
-
* Buffers decoded samples and emits DecodedAudioChunk when
|
|
8387
|
-
*
|
|
8386
|
+
* Buffers decoded samples and emits a DecodedAudioChunk when ~0.5 s has
|
|
8387
|
+
* accumulated (4000 samples, 16 000 bytes).
|
|
8388
8388
|
*/
|
|
8389
8389
|
var AudioRtpDecoder = class {
|
|
8390
8390
|
codec;
|
|
@@ -8398,18 +8398,14 @@ var AudioRtpDecoder = class {
|
|
|
8398
8398
|
}
|
|
8399
8399
|
/**
|
|
8400
8400
|
* Process a raw RTP packet (header + payload).
|
|
8401
|
-
* Strips the 12-byte RTP header
|
|
8401
|
+
* Strips the 12-byte RTP header and decodes the G.711 payload: one byte,
|
|
8402
|
+
* one 8 kHz sample. Nothing is interpolated here.
|
|
8402
8403
|
*/
|
|
8403
8404
|
processPacket(rtpData) {
|
|
8404
8405
|
if (rtpData.length <= 12) return;
|
|
8405
8406
|
const payload = rtpData.subarray(12);
|
|
8406
8407
|
const decode = this.codec === "PCMU" ? decodeUlaw : decodeAlaw;
|
|
8407
|
-
for (let i = 0; i < payload.length; i++)
|
|
8408
|
-
const current = decode(payload[i]);
|
|
8409
|
-
const next = i + 1 < payload.length ? decode(payload[i + 1]) : current;
|
|
8410
|
-
this.pushSample(current);
|
|
8411
|
-
this.pushSample((current + next) * .5);
|
|
8412
|
-
}
|
|
8408
|
+
for (let i = 0; i < payload.length; i++) this.pushSample(decode(payload[i]));
|
|
8413
8409
|
}
|
|
8414
8410
|
/** Flush any remaining buffered samples as a partial chunk. */
|
|
8415
8411
|
flush() {
|
|
@@ -8417,7 +8413,7 @@ var AudioRtpDecoder = class {
|
|
|
8417
8413
|
const data = Buffer.from(this.buffer.buffer, this.buffer.byteOffset, this.bufferOffset * 4);
|
|
8418
8414
|
this.onChunk({
|
|
8419
8415
|
data: Buffer.from(data),
|
|
8420
|
-
sampleRate:
|
|
8416
|
+
sampleRate: G711_SAMPLE_RATE,
|
|
8421
8417
|
channels: 1,
|
|
8422
8418
|
timestamp: Date.now()
|
|
8423
8419
|
});
|
|
@@ -8433,7 +8429,7 @@ var AudioRtpDecoder = class {
|
|
|
8433
8429
|
const data = Buffer.from(this.buffer.buffer, this.buffer.byteOffset, CHUNK_SAMPLES * 4);
|
|
8434
8430
|
this.onChunk({
|
|
8435
8431
|
data: Buffer.from(data),
|
|
8436
|
-
sampleRate:
|
|
8432
|
+
sampleRate: G711_SAMPLE_RATE,
|
|
8437
8433
|
channels: 1,
|
|
8438
8434
|
timestamp: Date.now()
|
|
8439
8435
|
});
|
|
@@ -13691,7 +13687,9 @@ var StreamBroker = class StreamBroker {
|
|
|
13691
13687
|
this.logger?.info("native: audio decoder initialized", { meta: {
|
|
13692
13688
|
codec: codecUpper,
|
|
13693
13689
|
sampleRate: audioTrack.clockRate,
|
|
13694
|
-
channels: audioTrack.channels
|
|
13690
|
+
channels: audioTrack.channels,
|
|
13691
|
+
planeSampleRate: G711_SAMPLE_RATE,
|
|
13692
|
+
planeFormat: "f32le"
|
|
13695
13693
|
} });
|
|
13696
13694
|
} else if (this.audioCodecApi) {
|
|
13697
13695
|
const capCfg = this.buildAudioCodecSessionConfig(audioTrack);
|
|
@@ -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-CtdpN7Sz.mjs")).catch((e) => {
|
|
34
34
|
throw l = void 0, e;
|
|
35
35
|
}), l;
|
|
36
36
|
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
//#region src/session-decode/native-lease-knobs.ts
|
|
2
|
+
/** Every knob, in the order the spawn line names them. */
|
|
3
|
+
var NATIVE_LEASE_KNOB_NAMES = [
|
|
4
|
+
"holdFrames",
|
|
5
|
+
"budgetMb",
|
|
6
|
+
"activityMs",
|
|
7
|
+
"admission",
|
|
8
|
+
"tileBudgetMb",
|
|
9
|
+
"sceneBudgetMb"
|
|
10
|
+
];
|
|
11
|
+
/** The numeric knobs — every knob but `admission`. */
|
|
12
|
+
var NATIVE_LEASE_NUMBER_KNOBS = [
|
|
13
|
+
"holdFrames",
|
|
14
|
+
"budgetMb",
|
|
15
|
+
"activityMs",
|
|
16
|
+
"tileBudgetMb",
|
|
17
|
+
"sceneBudgetMb"
|
|
18
|
+
];
|
|
19
|
+
var KNOB_SOURCES = [
|
|
20
|
+
"setting",
|
|
21
|
+
"env",
|
|
22
|
+
"default"
|
|
23
|
+
];
|
|
24
|
+
function isRecord$1(value) {
|
|
25
|
+
return typeof value === "object" && value !== null;
|
|
26
|
+
}
|
|
27
|
+
function isNonNegativeInteger(value) {
|
|
28
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
29
|
+
}
|
|
30
|
+
function isAdmission(value) {
|
|
31
|
+
return value === "all" || value === "inferred";
|
|
32
|
+
}
|
|
33
|
+
function isKnobSource(value) {
|
|
34
|
+
return typeof value === "string" && KNOB_SOURCES.some((s) => s === value);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Shape guard for the wire. The parent already bounded every value through the
|
|
38
|
+
* knob's own Zod schema; what is checked here is what a store constructor would
|
|
39
|
+
* otherwise turn into a silent misconfiguration — a non-integer, a negative
|
|
40
|
+
* budget, a hold of zero (a worker that holds nothing can crop nothing), an
|
|
41
|
+
* admission word that is neither mode, a source that names no level.
|
|
42
|
+
*/
|
|
43
|
+
function isWorkerLeaseKnobs(value) {
|
|
44
|
+
if (!isRecord$1(value) || !isRecord$1(value.values) || !isRecord$1(value.sources)) return false;
|
|
45
|
+
const { values, sources } = value;
|
|
46
|
+
for (const knob of NATIVE_LEASE_NUMBER_KNOBS) if (!isNonNegativeInteger(values[knob])) return false;
|
|
47
|
+
if (!isNonNegativeInteger(values.holdFrames) || values.holdFrames < 1) return false;
|
|
48
|
+
if (!isAdmission(values.admission)) return false;
|
|
49
|
+
return NATIVE_LEASE_KNOB_NAMES.every((knob) => isKnobSource(sources[knob]));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The one-line spawn diagnostic. Names the effective value AND its source for
|
|
53
|
+
* every knob: without the source, a log saying `holdFrames=8` cannot distinguish
|
|
54
|
+
* "the operator's setting arrived" from "someone left a shell variable set", and
|
|
55
|
+
* a setting that silently fails to arrive is exactly the failure the source
|
|
56
|
+
* field exists to make visible.
|
|
57
|
+
*/
|
|
58
|
+
function formatNativeLeaseKnobs(resolved) {
|
|
59
|
+
const part = (knob) => `${knob}=${resolved.values[knob]} source=${resolved.sources[knob]}`;
|
|
60
|
+
return `native lease knobs — ${NATIVE_LEASE_KNOB_NAMES.map(part).join("; ")}`;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/session-decode/worker-protocol.ts
|
|
64
|
+
/**
|
|
65
|
+
* Typed IPC protocol between the per-session decode coordinator (Task 3 —
|
|
66
|
+
* `child_process.fork`s the worker) and the decode-worker child
|
|
67
|
+
* (`decode-worker-child.ts`, Task 2). Pure module: no node-av, no
|
|
68
|
+
* `process.on`/`process.send` here — those live in `decode-worker-child.ts`,
|
|
69
|
+
* which documents why raw IPC is sanctioned for that file.
|
|
70
|
+
*
|
|
71
|
+
* The protocol is a request/response pull: the parent asks for the next
|
|
72
|
+
* frame (`pull`), gets back metadata + an opaque `frameId`, then asks for
|
|
73
|
+
* pixel bytes for that id with an optional ROI (`toBuffer`). No shared
|
|
74
|
+
* memory, no `/dev/shm` — frames travel as IPC messages only.
|
|
75
|
+
*/
|
|
76
|
+
/**
|
|
77
|
+
* Classify a worker diagnostic line into a {@link WorkerLogLevel}. Failure /
|
|
78
|
+
* fault lines surface at `warn` (visible at the default log level so a
|
|
79
|
+
* native-crop failure is finally seen in `addons.getLogs`); routine
|
|
80
|
+
* provenance / transition / lifecycle lines stay `debug`. Pure + exported so
|
|
81
|
+
* the mapping is unit-testable without spawning a worker.
|
|
82
|
+
*/
|
|
83
|
+
function logLevelForLine(line) {
|
|
84
|
+
return /\b(fail(?:ed|ure)?|error|exception|unhandled rejection|corrupt|EIO|EINVAL)\b/i.test(line) ? "warn" : "debug";
|
|
85
|
+
}
|
|
86
|
+
function isRecord(value) {
|
|
87
|
+
return typeof value === "object" && value !== null;
|
|
88
|
+
}
|
|
89
|
+
function isFiniteNumber(value) {
|
|
90
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
91
|
+
}
|
|
92
|
+
function isWorkerFrameFormat(value) {
|
|
93
|
+
return value === "rgb" || value === "gray";
|
|
94
|
+
}
|
|
95
|
+
function isWorkerBufferFormat(value) {
|
|
96
|
+
return isWorkerFrameFormat(value) || value === "jpeg";
|
|
97
|
+
}
|
|
98
|
+
function isWorkerLogLevel(value) {
|
|
99
|
+
return value === "debug" || value === "info" || value === "warn" || value === "error";
|
|
100
|
+
}
|
|
101
|
+
function isWorkerCropRegion(value) {
|
|
102
|
+
return isRecord(value) && isFiniteNumber(value.left) && isFiniteNumber(value.top) && isFiniteNumber(value.width) && isFiniteNumber(value.height);
|
|
103
|
+
}
|
|
104
|
+
function isWorkerResizeTarget(value) {
|
|
105
|
+
return isRecord(value) && isFiniteNumber(value.width) && isFiniteNumber(value.height);
|
|
106
|
+
}
|
|
107
|
+
function isFrameImageOptions(value) {
|
|
108
|
+
if (!isRecord(value)) return false;
|
|
109
|
+
if (value.crop !== void 0 && !isWorkerCropRegion(value.crop)) return false;
|
|
110
|
+
if (value.resize !== void 0 && !isWorkerResizeTarget(value.resize)) return false;
|
|
111
|
+
if (value.format !== void 0 && !isWorkerBufferFormat(value.format)) return false;
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
function isNormalizedBbox(value) {
|
|
115
|
+
return isRecord(value) && isFiniteNumber(value.x) && isFiniteNumber(value.y) && isFiniteNumber(value.w) && isFiniteNumber(value.h);
|
|
116
|
+
}
|
|
117
|
+
function isVideoFrameSource(value) {
|
|
118
|
+
return isRecord(value) && typeof value.restreamUrl === "string" && isFiniteNumber(value.deviceId) && typeof value.codec === "string";
|
|
119
|
+
}
|
|
120
|
+
function isVideoFrameGenOptions(value) {
|
|
121
|
+
if (!isRecord(value)) return false;
|
|
122
|
+
if (value.fps !== void 0 && !isFiniteNumber(value.fps)) return false;
|
|
123
|
+
if (value.format !== void 0 && !isWorkerFrameFormat(value.format)) return false;
|
|
124
|
+
if (value.preRollMs !== void 0 && !isFiniteNumber(value.preRollMs)) return false;
|
|
125
|
+
if (value.preRollMaxFrames !== void 0 && !isFiniteNumber(value.preRollMaxFrames)) return false;
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
/** Discriminated-union guard for {@link WorkerRequest} — no `as` casts. */
|
|
129
|
+
function isWorkerRequest(value) {
|
|
130
|
+
if (!isRecord(value)) return false;
|
|
131
|
+
switch (value.kind) {
|
|
132
|
+
case "start": return isVideoFrameSource(value.source) && isVideoFrameGenOptions(value.opts) && isWorkerLeaseKnobs(value.lease);
|
|
133
|
+
case "pull": return true;
|
|
134
|
+
case "toBuffer": return isFiniteNumber(value.frameId) && (value.opts === void 0 || isFrameImageOptions(value.opts));
|
|
135
|
+
case "nativeCrop": return isFiniteNumber(value.requestId) && isFiniteNumber(value.frameId) && isNormalizedBbox(value.bbox) && (value.maxWidth === void 0 || isFiniteNumber(value.maxWidth));
|
|
136
|
+
case "cutTiles": return isFiniteNumber(value.frameId) && Array.isArray(value.bboxes) && value.bboxes.every(isNormalizedBbox);
|
|
137
|
+
case "releaseNativeLease":
|
|
138
|
+
case "markInferred": return isFiniteNumber(value.frameId);
|
|
139
|
+
case "stop": return true;
|
|
140
|
+
default: return false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/** Discriminated-union guard for {@link WorkerReply} — no `as` casts. */
|
|
144
|
+
function isWorkerReply(value) {
|
|
145
|
+
if (!isRecord(value)) return false;
|
|
146
|
+
switch (value.kind) {
|
|
147
|
+
case "frame": return isFiniteNumber(value.frameId) && isFiniteNumber(value.timestamp) && isFiniteNumber(value.width) && isFiniteNumber(value.height) && isWorkerFrameFormat(value.format) && (value.capturedAt === void 0 || isFiniteNumber(value.capturedAt)) && (value.preRoll === void 0 || typeof value.preRoll === "boolean");
|
|
148
|
+
case "buffer": return isFiniteNumber(value.frameId) && value.bytes instanceof Uint8Array;
|
|
149
|
+
case "nativeCropResult": return isFiniteNumber(value.requestId) && value.bytes instanceof Uint8Array && isFiniteNumber(value.width) && isFiniteNumber(value.height) && (value.source === void 0 || value.source === "lease" || value.source === "tile");
|
|
150
|
+
case "nativeCropMiss": return isFiniteNumber(value.requestId) && (value.reason === void 0 || typeof value.reason === "string");
|
|
151
|
+
case "ended": return true;
|
|
152
|
+
case "ready": return typeof value.warm === "boolean";
|
|
153
|
+
case "error": return typeof value.message === "string" && (value.frameId === void 0 || isFiniteNumber(value.frameId));
|
|
154
|
+
case "log": return isWorkerLogLevel(value.level) && typeof value.message === "string";
|
|
155
|
+
case "preRollReport": return isFiniteNumber(value.offered) && isFiniteNumber(value.inferred) && isFiniteNumber(value.dropped) && isRecord(value.droppedByReason) && isFiniteNumber(value.strideMs) && typeof value.subsampled === "boolean" && isFiniteNumber(value.spanMs);
|
|
156
|
+
case "dialTiming": return isFiniteNumber(value.hwContextMs) && isFiniteNumber(value.demuxerOpenMs) && isFiniteNumber(value.decoderCreateMs) && isFiniteNumber(value.firstDecodeMs) && typeof value.streamInfoProbed === "boolean";
|
|
157
|
+
default: return false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//#endregion
|
|
161
|
+
Object.defineProperty(exports, "formatNativeLeaseKnobs", {
|
|
162
|
+
enumerable: true,
|
|
163
|
+
get: function() {
|
|
164
|
+
return formatNativeLeaseKnobs;
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
Object.defineProperty(exports, "isWorkerReply", {
|
|
168
|
+
enumerable: true,
|
|
169
|
+
get: function() {
|
|
170
|
+
return isWorkerReply;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
Object.defineProperty(exports, "isWorkerRequest", {
|
|
174
|
+
enumerable: true,
|
|
175
|
+
get: function() {
|
|
176
|
+
return isWorkerRequest;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
Object.defineProperty(exports, "logLevelForLine", {
|
|
180
|
+
enumerable: true,
|
|
181
|
+
get: function() {
|
|
182
|
+
return logLevelForLine;
|
|
183
|
+
}
|
|
184
|
+
});
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
//#region src/session-decode/native-lease-knobs.ts
|
|
2
|
+
/** Every knob, in the order the spawn line names them. */
|
|
3
|
+
var NATIVE_LEASE_KNOB_NAMES = [
|
|
4
|
+
"holdFrames",
|
|
5
|
+
"budgetMb",
|
|
6
|
+
"activityMs",
|
|
7
|
+
"admission",
|
|
8
|
+
"tileBudgetMb",
|
|
9
|
+
"sceneBudgetMb"
|
|
10
|
+
];
|
|
11
|
+
/** The numeric knobs — every knob but `admission`. */
|
|
12
|
+
var NATIVE_LEASE_NUMBER_KNOBS = [
|
|
13
|
+
"holdFrames",
|
|
14
|
+
"budgetMb",
|
|
15
|
+
"activityMs",
|
|
16
|
+
"tileBudgetMb",
|
|
17
|
+
"sceneBudgetMb"
|
|
18
|
+
];
|
|
19
|
+
var KNOB_SOURCES = [
|
|
20
|
+
"setting",
|
|
21
|
+
"env",
|
|
22
|
+
"default"
|
|
23
|
+
];
|
|
24
|
+
function isRecord$1(value) {
|
|
25
|
+
return typeof value === "object" && value !== null;
|
|
26
|
+
}
|
|
27
|
+
function isNonNegativeInteger(value) {
|
|
28
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
29
|
+
}
|
|
30
|
+
function isAdmission(value) {
|
|
31
|
+
return value === "all" || value === "inferred";
|
|
32
|
+
}
|
|
33
|
+
function isKnobSource(value) {
|
|
34
|
+
return typeof value === "string" && KNOB_SOURCES.some((s) => s === value);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Shape guard for the wire. The parent already bounded every value through the
|
|
38
|
+
* knob's own Zod schema; what is checked here is what a store constructor would
|
|
39
|
+
* otherwise turn into a silent misconfiguration — a non-integer, a negative
|
|
40
|
+
* budget, a hold of zero (a worker that holds nothing can crop nothing), an
|
|
41
|
+
* admission word that is neither mode, a source that names no level.
|
|
42
|
+
*/
|
|
43
|
+
function isWorkerLeaseKnobs(value) {
|
|
44
|
+
if (!isRecord$1(value) || !isRecord$1(value.values) || !isRecord$1(value.sources)) return false;
|
|
45
|
+
const { values, sources } = value;
|
|
46
|
+
for (const knob of NATIVE_LEASE_NUMBER_KNOBS) if (!isNonNegativeInteger(values[knob])) return false;
|
|
47
|
+
if (!isNonNegativeInteger(values.holdFrames) || values.holdFrames < 1) return false;
|
|
48
|
+
if (!isAdmission(values.admission)) return false;
|
|
49
|
+
return NATIVE_LEASE_KNOB_NAMES.every((knob) => isKnobSource(sources[knob]));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The one-line spawn diagnostic. Names the effective value AND its source for
|
|
53
|
+
* every knob: without the source, a log saying `holdFrames=8` cannot distinguish
|
|
54
|
+
* "the operator's setting arrived" from "someone left a shell variable set", and
|
|
55
|
+
* a setting that silently fails to arrive is exactly the failure the source
|
|
56
|
+
* field exists to make visible.
|
|
57
|
+
*/
|
|
58
|
+
function formatNativeLeaseKnobs(resolved) {
|
|
59
|
+
const part = (knob) => `${knob}=${resolved.values[knob]} source=${resolved.sources[knob]}`;
|
|
60
|
+
return `native lease knobs — ${NATIVE_LEASE_KNOB_NAMES.map(part).join("; ")}`;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/session-decode/worker-protocol.ts
|
|
64
|
+
/**
|
|
65
|
+
* Typed IPC protocol between the per-session decode coordinator (Task 3 —
|
|
66
|
+
* `child_process.fork`s the worker) and the decode-worker child
|
|
67
|
+
* (`decode-worker-child.ts`, Task 2). Pure module: no node-av, no
|
|
68
|
+
* `process.on`/`process.send` here — those live in `decode-worker-child.ts`,
|
|
69
|
+
* which documents why raw IPC is sanctioned for that file.
|
|
70
|
+
*
|
|
71
|
+
* The protocol is a request/response pull: the parent asks for the next
|
|
72
|
+
* frame (`pull`), gets back metadata + an opaque `frameId`, then asks for
|
|
73
|
+
* pixel bytes for that id with an optional ROI (`toBuffer`). No shared
|
|
74
|
+
* memory, no `/dev/shm` — frames travel as IPC messages only.
|
|
75
|
+
*/
|
|
76
|
+
/**
|
|
77
|
+
* Classify a worker diagnostic line into a {@link WorkerLogLevel}. Failure /
|
|
78
|
+
* fault lines surface at `warn` (visible at the default log level so a
|
|
79
|
+
* native-crop failure is finally seen in `addons.getLogs`); routine
|
|
80
|
+
* provenance / transition / lifecycle lines stay `debug`. Pure + exported so
|
|
81
|
+
* the mapping is unit-testable without spawning a worker.
|
|
82
|
+
*/
|
|
83
|
+
function logLevelForLine(line) {
|
|
84
|
+
return /\b(fail(?:ed|ure)?|error|exception|unhandled rejection|corrupt|EIO|EINVAL)\b/i.test(line) ? "warn" : "debug";
|
|
85
|
+
}
|
|
86
|
+
function isRecord(value) {
|
|
87
|
+
return typeof value === "object" && value !== null;
|
|
88
|
+
}
|
|
89
|
+
function isFiniteNumber(value) {
|
|
90
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
91
|
+
}
|
|
92
|
+
function isWorkerFrameFormat(value) {
|
|
93
|
+
return value === "rgb" || value === "gray";
|
|
94
|
+
}
|
|
95
|
+
function isWorkerBufferFormat(value) {
|
|
96
|
+
return isWorkerFrameFormat(value) || value === "jpeg";
|
|
97
|
+
}
|
|
98
|
+
function isWorkerLogLevel(value) {
|
|
99
|
+
return value === "debug" || value === "info" || value === "warn" || value === "error";
|
|
100
|
+
}
|
|
101
|
+
function isWorkerCropRegion(value) {
|
|
102
|
+
return isRecord(value) && isFiniteNumber(value.left) && isFiniteNumber(value.top) && isFiniteNumber(value.width) && isFiniteNumber(value.height);
|
|
103
|
+
}
|
|
104
|
+
function isWorkerResizeTarget(value) {
|
|
105
|
+
return isRecord(value) && isFiniteNumber(value.width) && isFiniteNumber(value.height);
|
|
106
|
+
}
|
|
107
|
+
function isFrameImageOptions(value) {
|
|
108
|
+
if (!isRecord(value)) return false;
|
|
109
|
+
if (value.crop !== void 0 && !isWorkerCropRegion(value.crop)) return false;
|
|
110
|
+
if (value.resize !== void 0 && !isWorkerResizeTarget(value.resize)) return false;
|
|
111
|
+
if (value.format !== void 0 && !isWorkerBufferFormat(value.format)) return false;
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
function isNormalizedBbox(value) {
|
|
115
|
+
return isRecord(value) && isFiniteNumber(value.x) && isFiniteNumber(value.y) && isFiniteNumber(value.w) && isFiniteNumber(value.h);
|
|
116
|
+
}
|
|
117
|
+
function isVideoFrameSource(value) {
|
|
118
|
+
return isRecord(value) && typeof value.restreamUrl === "string" && isFiniteNumber(value.deviceId) && typeof value.codec === "string";
|
|
119
|
+
}
|
|
120
|
+
function isVideoFrameGenOptions(value) {
|
|
121
|
+
if (!isRecord(value)) return false;
|
|
122
|
+
if (value.fps !== void 0 && !isFiniteNumber(value.fps)) return false;
|
|
123
|
+
if (value.format !== void 0 && !isWorkerFrameFormat(value.format)) return false;
|
|
124
|
+
if (value.preRollMs !== void 0 && !isFiniteNumber(value.preRollMs)) return false;
|
|
125
|
+
if (value.preRollMaxFrames !== void 0 && !isFiniteNumber(value.preRollMaxFrames)) return false;
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
/** Discriminated-union guard for {@link WorkerRequest} — no `as` casts. */
|
|
129
|
+
function isWorkerRequest(value) {
|
|
130
|
+
if (!isRecord(value)) return false;
|
|
131
|
+
switch (value.kind) {
|
|
132
|
+
case "start": return isVideoFrameSource(value.source) && isVideoFrameGenOptions(value.opts) && isWorkerLeaseKnobs(value.lease);
|
|
133
|
+
case "pull": return true;
|
|
134
|
+
case "toBuffer": return isFiniteNumber(value.frameId) && (value.opts === void 0 || isFrameImageOptions(value.opts));
|
|
135
|
+
case "nativeCrop": return isFiniteNumber(value.requestId) && isFiniteNumber(value.frameId) && isNormalizedBbox(value.bbox) && (value.maxWidth === void 0 || isFiniteNumber(value.maxWidth));
|
|
136
|
+
case "cutTiles": return isFiniteNumber(value.frameId) && Array.isArray(value.bboxes) && value.bboxes.every(isNormalizedBbox);
|
|
137
|
+
case "releaseNativeLease":
|
|
138
|
+
case "markInferred": return isFiniteNumber(value.frameId);
|
|
139
|
+
case "stop": return true;
|
|
140
|
+
default: return false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/** Discriminated-union guard for {@link WorkerReply} — no `as` casts. */
|
|
144
|
+
function isWorkerReply(value) {
|
|
145
|
+
if (!isRecord(value)) return false;
|
|
146
|
+
switch (value.kind) {
|
|
147
|
+
case "frame": return isFiniteNumber(value.frameId) && isFiniteNumber(value.timestamp) && isFiniteNumber(value.width) && isFiniteNumber(value.height) && isWorkerFrameFormat(value.format) && (value.capturedAt === void 0 || isFiniteNumber(value.capturedAt)) && (value.preRoll === void 0 || typeof value.preRoll === "boolean");
|
|
148
|
+
case "buffer": return isFiniteNumber(value.frameId) && value.bytes instanceof Uint8Array;
|
|
149
|
+
case "nativeCropResult": return isFiniteNumber(value.requestId) && value.bytes instanceof Uint8Array && isFiniteNumber(value.width) && isFiniteNumber(value.height) && (value.source === void 0 || value.source === "lease" || value.source === "tile");
|
|
150
|
+
case "nativeCropMiss": return isFiniteNumber(value.requestId) && (value.reason === void 0 || typeof value.reason === "string");
|
|
151
|
+
case "ended": return true;
|
|
152
|
+
case "ready": return typeof value.warm === "boolean";
|
|
153
|
+
case "error": return typeof value.message === "string" && (value.frameId === void 0 || isFiniteNumber(value.frameId));
|
|
154
|
+
case "log": return isWorkerLogLevel(value.level) && typeof value.message === "string";
|
|
155
|
+
case "preRollReport": return isFiniteNumber(value.offered) && isFiniteNumber(value.inferred) && isFiniteNumber(value.dropped) && isRecord(value.droppedByReason) && isFiniteNumber(value.strideMs) && typeof value.subsampled === "boolean" && isFiniteNumber(value.spanMs);
|
|
156
|
+
case "dialTiming": return isFiniteNumber(value.hwContextMs) && isFiniteNumber(value.demuxerOpenMs) && isFiniteNumber(value.decoderCreateMs) && isFiniteNumber(value.firstDecodeMs) && typeof value.streamInfoProbed === "boolean";
|
|
157
|
+
default: return false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//#endregion
|
|
161
|
+
export { formatNativeLeaseKnobs as i, isWorkerRequest as n, logLevelForLine as r, isWorkerReply as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-pipeline",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.220",
|
|
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",
|