@camstack/addon-pipeline 1.1.17 → 1.1.19
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 +1 -1
- package/dist/audio-analyzer/index.mjs +1 -1
- package/dist/audio-codec-nodeav/index.js +1 -1
- package/dist/audio-codec-nodeav/index.mjs +1 -1
- package/dist/decoder-ffmpeg/index.js +1179 -0
- package/dist/decoder-ffmpeg/index.mjs +1162 -0
- package/dist/detection-pipeline/index.js +1 -1
- package/dist/detection-pipeline/index.mjs +1 -1
- package/dist/{dist-CBcVKDyT.mjs → dist-7Yx2dmuV.mjs} +1 -0
- package/dist/{dist-CRzS7bK1.js → dist-BgoBMCez.js} +1 -0
- package/dist/ffmpeg-args-common-CASoNt42.js +68 -0
- package/dist/ffmpeg-args-common-c3p-nWtU.mjs +51 -0
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +1 -1
- package/dist/pipeline-runner/index.mjs +1 -1
- package/dist/recorder/index.js +1 -1
- package/dist/recorder/index.mjs +1 -1
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-Cu2RfLyo.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-w2pP0MYO.mjs} +1 -1
- package/dist/stream-broker/{hostInit-D2VENktw.mjs → hostInit-BUEbBinp.mjs} +1 -1
- package/dist/stream-broker/index.js +68 -73
- package/dist/stream-broker/index.mjs +58 -63
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-ohKbGSOY.js → MaskShapeCanvas-DI4BY7W2-CYmHXacX.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-m6kOetLh.js → MotionZonesSettings-NcxxQN8r-B-BkPQvX.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-BNbgX3su.js → PrivacyMaskSettings-APgPLF7p-DC3Jw85p.js} +1 -1
- package/embed-dist/assets/{index-CqqHOFtM.js → index-B0IQgci0.js} +4 -4
- package/embed-dist/index.html +1 -1
- package/package.json +8 -8
- package/dist/decoder-nodeav/index.js +0 -1393
- package/dist/decoder-nodeav/index.mjs +0 -1385
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-BnQ_awK4.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
6
|
+
const require_dist = require("../dist-BgoBMCez.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
node_fs = require_model_download_service_C_IHWnXx.__toESM(node_fs);
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __require } from "../chunk-BdkLduGY.mjs";
|
|
2
|
-
import { A as nodePin, B as BaseAddon, C as detectionPipelineCapability, J as hydrateSchema, L as supportedRuntimes$1, P as runtimeDevices$1, T as hfModelUrl, W as EventCategory, Z as parseJsonUnknown, a as COCO_TO_MACRO, et as sleep, i as COCO_80_LABELS, j as pipelineExecutorCapability, p as YAMNET_TO_MACRO, q as createEvent, r as AUDIO_MACRO_LABELS, t as APPLE_SA_TO_MACRO, w as evaluateZoneRules, x as defaultDeviceFor$1, z as errMsg } from "../dist-
|
|
2
|
+
import { A as nodePin, B as BaseAddon, C as detectionPipelineCapability, J as hydrateSchema, L as supportedRuntimes$1, P as runtimeDevices$1, T as hfModelUrl, W as EventCategory, Z as parseJsonUnknown, a as COCO_TO_MACRO, et as sleep, i as COCO_80_LABELS, j as pipelineExecutorCapability, p as YAMNET_TO_MACRO, q as createEvent, r as AUDIO_MACRO_LABELS, t as APPLE_SA_TO_MACRO, w as evaluateZoneRules, x as defaultDeviceFor$1, z as errMsg } from "../dist-7Yx2dmuV.mjs";
|
|
3
3
|
import { a as isModelDownloaded, i as ensureModel, n as deleteModelFromDisk } from "../model-download-service-C-IHWnXx-3Mmeob3l.mjs";
|
|
4
4
|
import * as fs from "node:fs";
|
|
5
5
|
import * as path$1 from "node:path";
|
|
@@ -13396,6 +13396,7 @@ var decoderCapability = {
|
|
|
13396
13396
|
name: "decoder",
|
|
13397
13397
|
scope: "system",
|
|
13398
13398
|
mode: "singleton",
|
|
13399
|
+
preferredProvider: "decoder-ffmpeg",
|
|
13399
13400
|
methods: {
|
|
13400
13401
|
supportsCodec: method(object({ codec: string() }), boolean()),
|
|
13401
13402
|
getInfo: method(_void(), object({
|
|
@@ -13396,6 +13396,7 @@ var decoderCapability = {
|
|
|
13396
13396
|
name: "decoder",
|
|
13397
13397
|
scope: "system",
|
|
13398
13398
|
mode: "singleton",
|
|
13399
|
+
preferredProvider: "decoder-ffmpeg",
|
|
13399
13400
|
methods: {
|
|
13400
13401
|
supportsCodec: method(object({ codec: string() }), boolean()),
|
|
13401
13402
|
getInfo: method(_void(), object({
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
//#region src/stream-broker/stream-broker/frame-dropper.ts
|
|
2
|
+
var FrameDropper = class {
|
|
3
|
+
intervalMs;
|
|
4
|
+
lastPassedAt = -Infinity;
|
|
5
|
+
constructor(maxFps) {
|
|
6
|
+
this.intervalMs = maxFps > 0 ? 1e3 / maxFps : 0;
|
|
7
|
+
}
|
|
8
|
+
shouldKeep() {
|
|
9
|
+
if (this.intervalMs === 0) return true;
|
|
10
|
+
const now = Date.now();
|
|
11
|
+
if (now - this.lastPassedAt >= this.intervalMs) {
|
|
12
|
+
this.lastPassedAt = now;
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
setMaxFps(maxFps) {
|
|
18
|
+
this.intervalMs = maxFps > 0 ? 1e3 / maxFps : 0;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/stream-broker/stream-broker/ffmpeg-args-common.ts
|
|
23
|
+
var AUDIO_ENCODER_BY_CODEC = {
|
|
24
|
+
opus: "libopus",
|
|
25
|
+
aac: "aac",
|
|
26
|
+
pcmu: "pcm_mulaw",
|
|
27
|
+
pcma: "pcm_alaw",
|
|
28
|
+
copy: "copy"
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Build the audio-encode args `-c:a <enc> [-b:a Nk] [-ar N] [-ac N]`. Each knob
|
|
32
|
+
* is emitted only when provided, in this fixed order — matching what every
|
|
33
|
+
* broker site already emitted by hand.
|
|
34
|
+
*/
|
|
35
|
+
function audioEncoderArgs(codec, opts = {}) {
|
|
36
|
+
const args = ["-c:a", AUDIO_ENCODER_BY_CODEC[codec]];
|
|
37
|
+
if (opts.bitrateKbps !== void 0) args.push("-b:a", `${opts.bitrateKbps}k`);
|
|
38
|
+
if (opts.sampleRateHz !== void 0) args.push("-ar", String(opts.sampleRateHz));
|
|
39
|
+
if (opts.channels !== void 0) args.push("-ac", String(opts.channels));
|
|
40
|
+
return args;
|
|
41
|
+
}
|
|
42
|
+
/** The `-hide_banner -loglevel <level>` preamble every broker ffmpeg site opens with. */
|
|
43
|
+
function logBannerArgs(level) {
|
|
44
|
+
return [
|
|
45
|
+
"-hide_banner",
|
|
46
|
+
"-loglevel",
|
|
47
|
+
level
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
Object.defineProperty(exports, "FrameDropper", {
|
|
52
|
+
enumerable: true,
|
|
53
|
+
get: function() {
|
|
54
|
+
return FrameDropper;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
Object.defineProperty(exports, "audioEncoderArgs", {
|
|
58
|
+
enumerable: true,
|
|
59
|
+
get: function() {
|
|
60
|
+
return audioEncoderArgs;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
Object.defineProperty(exports, "logBannerArgs", {
|
|
64
|
+
enumerable: true,
|
|
65
|
+
get: function() {
|
|
66
|
+
return logBannerArgs;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//#region src/stream-broker/stream-broker/frame-dropper.ts
|
|
2
|
+
var FrameDropper = class {
|
|
3
|
+
intervalMs;
|
|
4
|
+
lastPassedAt = -Infinity;
|
|
5
|
+
constructor(maxFps) {
|
|
6
|
+
this.intervalMs = maxFps > 0 ? 1e3 / maxFps : 0;
|
|
7
|
+
}
|
|
8
|
+
shouldKeep() {
|
|
9
|
+
if (this.intervalMs === 0) return true;
|
|
10
|
+
const now = Date.now();
|
|
11
|
+
if (now - this.lastPassedAt >= this.intervalMs) {
|
|
12
|
+
this.lastPassedAt = now;
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
setMaxFps(maxFps) {
|
|
18
|
+
this.intervalMs = maxFps > 0 ? 1e3 / maxFps : 0;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/stream-broker/stream-broker/ffmpeg-args-common.ts
|
|
23
|
+
var AUDIO_ENCODER_BY_CODEC = {
|
|
24
|
+
opus: "libopus",
|
|
25
|
+
aac: "aac",
|
|
26
|
+
pcmu: "pcm_mulaw",
|
|
27
|
+
pcma: "pcm_alaw",
|
|
28
|
+
copy: "copy"
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Build the audio-encode args `-c:a <enc> [-b:a Nk] [-ar N] [-ac N]`. Each knob
|
|
32
|
+
* is emitted only when provided, in this fixed order — matching what every
|
|
33
|
+
* broker site already emitted by hand.
|
|
34
|
+
*/
|
|
35
|
+
function audioEncoderArgs(codec, opts = {}) {
|
|
36
|
+
const args = ["-c:a", AUDIO_ENCODER_BY_CODEC[codec]];
|
|
37
|
+
if (opts.bitrateKbps !== void 0) args.push("-b:a", `${opts.bitrateKbps}k`);
|
|
38
|
+
if (opts.sampleRateHz !== void 0) args.push("-ar", String(opts.sampleRateHz));
|
|
39
|
+
if (opts.channels !== void 0) args.push("-ac", String(opts.channels));
|
|
40
|
+
return args;
|
|
41
|
+
}
|
|
42
|
+
/** The `-hide_banner -loglevel <level>` preamble every broker ffmpeg site opens with. */
|
|
43
|
+
function logBannerArgs(level) {
|
|
44
|
+
return [
|
|
45
|
+
"-hide_banner",
|
|
46
|
+
"-loglevel",
|
|
47
|
+
level
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { logBannerArgs as n, FrameDropper as r, audioEncoderArgs as t };
|
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
5
|
+
const require_dist = require("../dist-BgoBMCez.js");
|
|
6
6
|
let node_fs = require("node:fs");
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
//#region src/motion-wasm/wasm-motion-detector.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as BaseAddon, J as hydrateSchema, U as DeviceType, k as motionDetectionCapability, w as evaluateZoneRules } from "../dist-
|
|
1
|
+
import { B as BaseAddon, J as hydrateSchema, U as DeviceType, k as motionDetectionCapability, w as evaluateZoneRules } from "../dist-7Yx2dmuV.mjs";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
//#region src/motion-wasm/wasm-motion-detector.ts
|
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
5
|
+
const require_dist = require("../dist-BgoBMCez.js");
|
|
6
6
|
let _camstack_shm_ring = require("@camstack/shm-ring");
|
|
7
7
|
//#region src/pipeline-runner/frame-queue.ts
|
|
8
8
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as nodePin, B as BaseAddon, M as pipelineRunnerCapability, S as defineCustomActions, W as EventCategory, X as makeSourceBrokerId, at as lazy, ct as object, nt as array, q as createEvent, rt as boolean, st as number, tt as _enum, ut as string, y as customAction, z as errMsg } from "../dist-
|
|
1
|
+
import { A as nodePin, B as BaseAddon, M as pipelineRunnerCapability, S as defineCustomActions, W as EventCategory, X as makeSourceBrokerId, at as lazy, ct as object, nt as array, q as createEvent, rt as boolean, st as number, tt as _enum, ut as string, y as customAction, z as errMsg } from "../dist-7Yx2dmuV.mjs";
|
|
2
2
|
import { FrameRingReaderCache } from "@camstack/shm-ring";
|
|
3
3
|
//#region src/pipeline-runner/frame-queue.ts
|
|
4
4
|
/**
|
package/dist/recorder/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-BnQ_awK4.js");
|
|
2
|
-
const require_dist = require("../dist-
|
|
2
|
+
const require_dist = require("../dist-BgoBMCez.js");
|
|
3
3
|
let node_fs = require("node:fs");
|
|
4
4
|
let node_path = require("node:path");
|
|
5
5
|
node_path = require_model_download_service_C_IHWnXx.__toESM(node_path);
|
package/dist/recorder/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as selectAssignedProfileSlots, B as BaseAddon, F as storageEvictableCapability, J as hydrateSchema, K as createDurableState, N as recordingCapability, O as migrateConfigToBands, U as DeviceType, W as EventCategory, d as RecordingConfigSchema, lt as record, ut as string, z as errMsg } from "../dist-
|
|
1
|
+
import { $ as selectAssignedProfileSlots, B as BaseAddon, F as storageEvictableCapability, J as hydrateSchema, K as createDurableState, N as recordingCapability, O as migrateConfigToBands, U as DeviceType, W as EventCategory, d as RecordingConfigSchema, lt as record, ut as string, z as errMsg } from "../dist-7Yx2dmuV.mjs";
|
|
2
2
|
import { t as createFileDataPlaneHandler } from "../model-download-service-C-IHWnXx-3Mmeob3l.mjs";
|
|
3
3
|
import { promises } from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
@@ -3,7 +3,8 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-BnQ_awK4.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
6
|
+
const require_dist = require("../dist-BgoBMCez.js");
|
|
7
|
+
const require_ffmpeg_args_common = require("../ffmpeg-args-common-CASoNt42.js");
|
|
7
8
|
const require_codec_runtime = require("../codec-runtime-BOk-13PN.js");
|
|
8
9
|
let node_fs = require("node:fs");
|
|
9
10
|
node_fs = require_model_download_service_C_IHWnXx.__toESM(node_fs);
|
|
@@ -308,6 +309,31 @@ var DecoderSessionProxy = class {
|
|
|
308
309
|
* broker supplies a `pullModeUrl` and the plane calls `openStream` once the
|
|
309
310
|
* session exists.
|
|
310
311
|
*/
|
|
312
|
+
/**
|
|
313
|
+
* Collapse a hierarchical Moleculer nodeID (`hub/child-abc`) to its owning
|
|
314
|
+
* node (`hub`). Frame-plane co-location only cares about the physical node, not
|
|
315
|
+
* which forked child within it hosts the session.
|
|
316
|
+
*/
|
|
317
|
+
function collapseNodeId(nodeId) {
|
|
318
|
+
const slash = nodeId.indexOf("/");
|
|
319
|
+
return slash >= 0 ? nodeId.slice(0, slash) : nodeId;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Decide whether a decoder session created on `decoderNodeId` is co-located
|
|
323
|
+
* with the broker whose local node is `brokerNodeId`.
|
|
324
|
+
*
|
|
325
|
+
* The broker's shm frame ring is NODE-LOCAL: a decoder session on any other
|
|
326
|
+
* node can never deliver frame handles to this broker's consumers, so a
|
|
327
|
+
* mis-placed session must be rejected. Both ids are collapsed (`hub/child`→
|
|
328
|
+
* `hub`) before comparison.
|
|
329
|
+
*
|
|
330
|
+
* A `null` `brokerNodeId` means the broker's own node is unknown — enforcement
|
|
331
|
+
* is skipped (legacy behavior, accept any placement).
|
|
332
|
+
*/
|
|
333
|
+
function isDecoderNodeColocated(brokerNodeId, decoderNodeId) {
|
|
334
|
+
if (brokerNodeId === null) return true;
|
|
335
|
+
return collapseNodeId(brokerNodeId) === collapseNodeId(decoderNodeId);
|
|
336
|
+
}
|
|
311
337
|
/** Per-subscription handle-queue capacity. A handle is tiny; 64 absorbs a
|
|
312
338
|
* burst between two `pullFrameHandles` polls without unbounded growth. */
|
|
313
339
|
var HANDLE_QUEUE_CAPACITY = 64;
|
|
@@ -324,6 +350,7 @@ var FrameHandlePlane = class {
|
|
|
324
350
|
decoderApi;
|
|
325
351
|
logger;
|
|
326
352
|
resolveStreamInfo;
|
|
353
|
+
localNodeId;
|
|
327
354
|
subscriptions = /* @__PURE__ */ new Map();
|
|
328
355
|
sessions = /* @__PURE__ */ new Map();
|
|
329
356
|
disposed = false;
|
|
@@ -339,6 +366,7 @@ var FrameHandlePlane = class {
|
|
|
339
366
|
this.decoderApi = options.decoderApi;
|
|
340
367
|
this.logger = options.logger;
|
|
341
368
|
this.resolveStreamInfo = options.resolveStreamInfo;
|
|
369
|
+
this.localNodeId = options.localNodeId;
|
|
342
370
|
}
|
|
343
371
|
/** Number of active handle subscriptions — surfaced for diagnostics. */
|
|
344
372
|
get subscriberCount() {
|
|
@@ -639,6 +667,22 @@ var FrameHandlePlane = class {
|
|
|
639
667
|
...info.numericDeviceId !== void 0 ? { deviceId: info.numericDeviceId } : {},
|
|
640
668
|
tag: `${info.tag}:shm:${format}`
|
|
641
669
|
});
|
|
670
|
+
if (!isDecoderNodeColocated(this.localNodeId, nodeId)) {
|
|
671
|
+
this.logger?.warn("frame-handle plane: decoder session landed on a non-local node — destroying (shm ring is node-local)", { meta: {
|
|
672
|
+
format,
|
|
673
|
+
requestedNode: this.localNodeId,
|
|
674
|
+
gotNode: nodeId,
|
|
675
|
+
sessionId
|
|
676
|
+
} });
|
|
677
|
+
await this.decoderApi.destroySession({ sessionId }).catch((err) => {
|
|
678
|
+
this.logger?.warn("frame-handle plane: failed to destroy mis-placed decoder session", { meta: {
|
|
679
|
+
format,
|
|
680
|
+
sessionId,
|
|
681
|
+
error: require_dist.errMsg(err)
|
|
682
|
+
} });
|
|
683
|
+
});
|
|
684
|
+
return false;
|
|
685
|
+
}
|
|
642
686
|
const proxy = new DecoderSessionProxy(this.decoderApi, sessionId);
|
|
643
687
|
session.proxy = proxy;
|
|
644
688
|
session.nodeId = nodeId;
|
|
@@ -4083,6 +4127,13 @@ var StreamBroker = class StreamBroker {
|
|
|
4083
4127
|
decoderApi;
|
|
4084
4128
|
audioCodecApi;
|
|
4085
4129
|
logger;
|
|
4130
|
+
/**
|
|
4131
|
+
* This broker's OWN local Moleculer node id, threaded from the manager
|
|
4132
|
+
* (`ctx.kernel.localNodeId`). Passed to the `FrameHandlePlane` so it can
|
|
4133
|
+
* reject decoder sessions that land on a different node (the shm frame ring
|
|
4134
|
+
* is node-local). `null` = unknown → co-location enforcement skipped.
|
|
4135
|
+
*/
|
|
4136
|
+
localNodeId;
|
|
4086
4137
|
startedAt = Date.now();
|
|
4087
4138
|
nativeClient = null;
|
|
4088
4139
|
rfc4571Reader = null;
|
|
@@ -4269,11 +4320,12 @@ var StreamBroker = class StreamBroker {
|
|
|
4269
4320
|
static DEFAULT_PRE_BUFFER_SEC = 10;
|
|
4270
4321
|
/** Maximum allowed pre-buffer duration in seconds */
|
|
4271
4322
|
static MAX_PRE_BUFFER_SEC = 30;
|
|
4272
|
-
constructor(deviceId, decoderApi, logger, audioCodecApi) {
|
|
4323
|
+
constructor(deviceId, decoderApi, logger, audioCodecApi, localNodeId) {
|
|
4273
4324
|
this.deviceId = deviceId;
|
|
4274
4325
|
this.decoderApi = decoderApi;
|
|
4275
4326
|
this.audioCodecApi = audioCodecApi ?? null;
|
|
4276
4327
|
this.logger = logger;
|
|
4328
|
+
this.localNodeId = localNodeId ?? null;
|
|
4277
4329
|
this.pipeServer = new StreamPipeServer(logger?.child("pipe-server"));
|
|
4278
4330
|
this.rtspRestreamer = new RtspRestreamer(deviceId);
|
|
4279
4331
|
if (logger) this.rtspRestreamer.setLogger(logger.child("rtsp"));
|
|
@@ -5019,7 +5071,8 @@ var StreamBroker = class StreamBroker {
|
|
|
5019
5071
|
this.frameHandlePlane = new FrameHandlePlane({
|
|
5020
5072
|
decoderApi: this.decoderApi,
|
|
5021
5073
|
logger: this.logger?.child("frame-handle-plane"),
|
|
5022
|
-
resolveStreamInfo: () => this.resolveFrameHandleStreamInfo()
|
|
5074
|
+
resolveStreamInfo: () => this.resolveFrameHandleStreamInfo(),
|
|
5075
|
+
localNodeId: this.localNodeId
|
|
5023
5076
|
});
|
|
5024
5077
|
return this.frameHandlePlane;
|
|
5025
5078
|
}
|
|
@@ -6585,35 +6638,6 @@ var RtspRestreamProviderImpl = class {
|
|
|
6585
6638
|
}
|
|
6586
6639
|
};
|
|
6587
6640
|
//#endregion
|
|
6588
|
-
//#region src/stream-broker/stream-broker/ffmpeg-args-common.ts
|
|
6589
|
-
var AUDIO_ENCODER_BY_CODEC = {
|
|
6590
|
-
opus: "libopus",
|
|
6591
|
-
aac: "aac",
|
|
6592
|
-
pcmu: "pcm_mulaw",
|
|
6593
|
-
pcma: "pcm_alaw",
|
|
6594
|
-
copy: "copy"
|
|
6595
|
-
};
|
|
6596
|
-
/**
|
|
6597
|
-
* Build the audio-encode args `-c:a <enc> [-b:a Nk] [-ar N] [-ac N]`. Each knob
|
|
6598
|
-
* is emitted only when provided, in this fixed order — matching what every
|
|
6599
|
-
* broker site already emitted by hand.
|
|
6600
|
-
*/
|
|
6601
|
-
function audioEncoderArgs(codec, opts = {}) {
|
|
6602
|
-
const args = ["-c:a", AUDIO_ENCODER_BY_CODEC[codec]];
|
|
6603
|
-
if (opts.bitrateKbps !== void 0) args.push("-b:a", `${opts.bitrateKbps}k`);
|
|
6604
|
-
if (opts.sampleRateHz !== void 0) args.push("-ar", String(opts.sampleRateHz));
|
|
6605
|
-
if (opts.channels !== void 0) args.push("-ac", String(opts.channels));
|
|
6606
|
-
return args;
|
|
6607
|
-
}
|
|
6608
|
-
/** The `-hide_banner -loglevel <level>` preamble every broker ffmpeg site opens with. */
|
|
6609
|
-
function logBannerArgs(level) {
|
|
6610
|
-
return [
|
|
6611
|
-
"-hide_banner",
|
|
6612
|
-
"-loglevel",
|
|
6613
|
-
level
|
|
6614
|
-
];
|
|
6615
|
-
}
|
|
6616
|
-
//#endregion
|
|
6617
6641
|
//#region src/stream-broker/stream-broker/ffmpeg-invocation.ts
|
|
6618
6642
|
/** The full set of hwaccel settings (for validation + option surfaces). */
|
|
6619
6643
|
var FFMPEG_HW_ACCEL_SETTINGS = [
|
|
@@ -6673,23 +6697,23 @@ function pickVideoEncoder(target, encoders, hwAccel) {
|
|
|
6673
6697
|
/** Audio encoder args for a transcode target (preset values over the shared low-level builder). */
|
|
6674
6698
|
function pickAudioEncoderArgs(audio) {
|
|
6675
6699
|
switch (audio) {
|
|
6676
|
-
case "aac": return audioEncoderArgs("aac", {
|
|
6700
|
+
case "aac": return require_ffmpeg_args_common.audioEncoderArgs("aac", {
|
|
6677
6701
|
bitrateKbps: 128,
|
|
6678
6702
|
sampleRateHz: 48e3,
|
|
6679
6703
|
channels: 2
|
|
6680
6704
|
});
|
|
6681
|
-
case "opus": return audioEncoderArgs("opus", {
|
|
6705
|
+
case "opus": return require_ffmpeg_args_common.audioEncoderArgs("opus", {
|
|
6682
6706
|
bitrateKbps: 64,
|
|
6683
6707
|
sampleRateHz: 48e3,
|
|
6684
6708
|
channels: 2
|
|
6685
6709
|
});
|
|
6686
|
-
case "pcmu": return audioEncoderArgs("pcmu", {
|
|
6710
|
+
case "pcmu": return require_ffmpeg_args_common.audioEncoderArgs("pcmu", {
|
|
6687
6711
|
sampleRateHz: 8e3,
|
|
6688
6712
|
channels: 1
|
|
6689
6713
|
});
|
|
6690
|
-
case "copy": return audioEncoderArgs("copy");
|
|
6714
|
+
case "copy": return require_ffmpeg_args_common.audioEncoderArgs("copy");
|
|
6691
6715
|
case "none": return ["-an"];
|
|
6692
|
-
default: return audioEncoderArgs("aac", { bitrateKbps: 128 });
|
|
6716
|
+
default: return require_ffmpeg_args_common.audioEncoderArgs("aac", { bitrateKbps: 128 });
|
|
6693
6717
|
}
|
|
6694
6718
|
}
|
|
6695
6719
|
/**
|
|
@@ -6754,7 +6778,7 @@ function buildFfmpegArgs$1(inv) {
|
|
|
6754
6778
|
const threadArgs = inv.threadCount > 0 ? ["-threads", String(inv.threadCount)] : [];
|
|
6755
6779
|
const audioArgs = inv.sink.kind === "stdout" && (inv.sink.container === "h264" || inv.sink.container === "hevc") ? ["-an"] : pickAudioEncoderArgs(inv.audio);
|
|
6756
6780
|
return [
|
|
6757
|
-
...logBannerArgs("warning"),
|
|
6781
|
+
...require_ffmpeg_args_common.logBannerArgs("warning"),
|
|
6758
6782
|
...decodeArgs,
|
|
6759
6783
|
"-rtsp_transport",
|
|
6760
6784
|
"tcp",
|
|
@@ -9643,7 +9667,7 @@ var StreamBrokerManager = class {
|
|
|
9643
9667
|
camStreamId
|
|
9644
9668
|
});
|
|
9645
9669
|
const source = this.buildSourceFromCamStream(cam);
|
|
9646
|
-
const broker = new StreamBroker(brokerId, this.buildDecoderCapApi(deviceId), brokerLogger, buildAudioCodecCapApi(this.api));
|
|
9670
|
+
const broker = new StreamBroker(brokerId, this.buildDecoderCapApi(deviceId), brokerLogger, buildAudioCodecCapApi(this.api), this.localNodeId);
|
|
9647
9671
|
broker.setRestreamers(this.restreamers);
|
|
9648
9672
|
this.applyPreBufferConfig(broker, deviceId, camStreamId, cam);
|
|
9649
9673
|
if (this.deviceOverrides.get(deviceId)?.streamingDebug) broker.setStreamingDebug(true);
|
|
@@ -11555,7 +11579,7 @@ function planAudioSilencePadPackets(input) {
|
|
|
11555
11579
|
* audio plane honours the profile literally.
|
|
11556
11580
|
*/
|
|
11557
11581
|
function buildTranscodeFfmpegArgs(inputFormat, profile, decodeHwAccel, sourceUrl) {
|
|
11558
|
-
const args = [...logBannerArgs("error")];
|
|
11582
|
+
const args = [...require_ffmpeg_args_common.logBannerArgs("error")];
|
|
11559
11583
|
if (profile.inputArgs?.length) args.push(...profile.inputArgs);
|
|
11560
11584
|
if (decodeHwAccel && decodeHwAccel !== "none") args.push("-hwaccel", decodeHwAccel);
|
|
11561
11585
|
args.push("-fflags", "+discardcorrupt", "-rtsp_transport", "tcp", "-i", sourceUrl);
|
|
@@ -11577,7 +11601,7 @@ function buildTranscodeFfmpegArgs(inputFormat, profile, decodeHwAccel, sourceUrl
|
|
|
11577
11601
|
if (profile.audio === "passthrough") args.push("-an");
|
|
11578
11602
|
else {
|
|
11579
11603
|
const a = profile.audio;
|
|
11580
|
-
args.push(...audioEncoderArgs(a.codec, {
|
|
11604
|
+
args.push(...require_ffmpeg_args_common.audioEncoderArgs(a.codec, {
|
|
11581
11605
|
bitrateKbps: a.bitrateKbps,
|
|
11582
11606
|
sampleRateHz: a.sampleRateHz,
|
|
11583
11607
|
channels: a.channels
|
|
@@ -16553,16 +16577,8 @@ var StreamBrokerAddon = class extends require_dist.BaseAddon {
|
|
|
16553
16577
|
logger: this.ctx.logger.child("webrtc"),
|
|
16554
16578
|
getIceServers: async () => {
|
|
16555
16579
|
if (!turnApi.turnProvider) return [];
|
|
16556
|
-
const providersApi = this.ctx.api;
|
|
16557
|
-
try {
|
|
16558
|
-
const providers = await providersApi.addons?.listCapabilityProviders.query({ capName: "turn-provider" });
|
|
16559
|
-
if (!providers || providers.length === 0) return [];
|
|
16560
|
-
} catch {}
|
|
16561
|
-
const TURN_RESOLVE_TIMEOUT_MS = 3e3;
|
|
16562
16580
|
try {
|
|
16563
|
-
const servers = await
|
|
16564
|
-
setTimeout(() => reject(/* @__PURE__ */ new Error("turn-provider getTurnServers timed out")), TURN_RESOLVE_TIMEOUT_MS).unref?.();
|
|
16565
|
-
})]);
|
|
16581
|
+
const servers = await turnApi.turnProvider.getTurnServers.query();
|
|
16566
16582
|
const out = [];
|
|
16567
16583
|
for (const s of servers) {
|
|
16568
16584
|
if (!s.urls || Array.isArray(s.urls) && s.urls.length === 0) continue;
|
|
@@ -16875,27 +16891,6 @@ var StreamBrokerAddon = class extends require_dist.BaseAddon {
|
|
|
16875
16891
|
}
|
|
16876
16892
|
};
|
|
16877
16893
|
//#endregion
|
|
16878
|
-
//#region src/stream-broker/stream-broker/frame-dropper.ts
|
|
16879
|
-
var FrameDropper = class {
|
|
16880
|
-
intervalMs;
|
|
16881
|
-
lastPassedAt = -Infinity;
|
|
16882
|
-
constructor(maxFps) {
|
|
16883
|
-
this.intervalMs = maxFps > 0 ? 1e3 / maxFps : 0;
|
|
16884
|
-
}
|
|
16885
|
-
shouldKeep() {
|
|
16886
|
-
if (this.intervalMs === 0) return true;
|
|
16887
|
-
const now = Date.now();
|
|
16888
|
-
if (now - this.lastPassedAt >= this.intervalMs) {
|
|
16889
|
-
this.lastPassedAt = now;
|
|
16890
|
-
return true;
|
|
16891
|
-
}
|
|
16892
|
-
return false;
|
|
16893
|
-
}
|
|
16894
|
-
setMaxFps(maxFps) {
|
|
16895
|
-
this.intervalMs = maxFps > 0 ? 1e3 / maxFps : 0;
|
|
16896
|
-
}
|
|
16897
|
-
};
|
|
16898
|
-
//#endregion
|
|
16899
16894
|
//#region src/stream-broker/stream-broker/ffmpeg-decoder-session.ts
|
|
16900
16895
|
/** Minimal no-op logger for default parameter */
|
|
16901
16896
|
var noopLogger = {
|
|
@@ -16923,7 +16918,7 @@ function codecToInputFormat(codec) {
|
|
|
16923
16918
|
function buildFfmpegArgs(config) {
|
|
16924
16919
|
const inputFormat = codecToInputFormat(config.codec);
|
|
16925
16920
|
const args = [
|
|
16926
|
-
...logBannerArgs("error"),
|
|
16921
|
+
...require_ffmpeg_args_common.logBannerArgs("error"),
|
|
16927
16922
|
"-fflags",
|
|
16928
16923
|
"+nobuffer+flush_packets",
|
|
16929
16924
|
"-flags",
|
|
@@ -16960,7 +16955,7 @@ var FfmpegDecoderSession = class {
|
|
|
16960
16955
|
constructor(config, logger = noopLogger) {
|
|
16961
16956
|
this.config = { ...config };
|
|
16962
16957
|
this.logger = logger;
|
|
16963
|
-
this.frameDropper = new FrameDropper(config.maxFps);
|
|
16958
|
+
this.frameDropper = new require_ffmpeg_args_common.FrameDropper(config.maxFps);
|
|
16964
16959
|
this.spawnFfmpeg();
|
|
16965
16960
|
}
|
|
16966
16961
|
spawnFfmpeg() {
|