@camstack/addon-pipeline 1.2.305 → 1.2.307
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 +2 -2
- package/dist/audio-analyzer/index.mjs +2 -2
- package/dist/{default-detection-model-BduwEjht.mjs → default-detection-model-BV9bIuOo.mjs} +1 -1
- package/dist/{default-detection-model-BsXfdMCG.js → default-detection-model-DgdiQtQb.js} +1 -1
- package/dist/detection-pipeline/index.js +4 -4
- package/dist/detection-pipeline/index.mjs +4 -4
- package/dist/{dist-D4lbkRUh.js → dist-CyJWk-_f.js} +298 -160
- package/dist/{dist-BdYgTuWJ.mjs → dist-DdVMFlJ6.mjs} +281 -161
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-DTG5A-3e.mjs → node-COu_tHy4.mjs} +1 -1
- package/dist/{node-BMmRQfH_.js → node-HsWG5fGp.js} +1 -1
- package/dist/pipeline-runner/index.js +7 -6
- package/dist/pipeline-runner/index.mjs +7 -6
- package/dist/{process-memory-RnWS9Et5.mjs → process-memory-Bz3oIMzl.mjs} +1 -1
- package/dist/{process-memory-DJrgIn1c.js → process-memory-TQXG7qrJ.js} +1 -1
- package/dist/recorder/index.js +2 -4
- package/dist/recorder/index.mjs +2 -4
- package/dist/{segment-demux-js-BI9zEgk6.js → segment-demux-js-BrKa7tpr.js} +1 -1
- package/dist/{segment-demux-js-CsJMEslt.mjs → segment-demux-js-CEJn4BR0.mjs} +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-Vcuvgik_.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DdYUVQSA.mjs} +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DPHv0v3Q.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-CdKbuxqG.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-C3s1ZFbg.mjs → hostInit-D--a9rVM.mjs} +2 -2
- package/dist/stream-broker/index.js +100 -151
- package/dist/stream-broker/index.mjs +97 -148
- 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-X_j7TiDp.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-CR9IIPsz.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-CyJWk-_f.js");
|
|
7
|
+
const require_node = require("../node-HsWG5fGp.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-BrKa7tpr.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");
|
|
@@ -7081,6 +7081,100 @@ function defaultId() {
|
|
|
7081
7081
|
counter += 1;
|
|
7082
7082
|
return `${Date.now().toString(36)}${counter.toString(36)}`;
|
|
7083
7083
|
}
|
|
7084
|
+
/** A derive that has not finished by now will not finish inside the drain. */
|
|
7085
|
+
var GIF_RENDER_TIMEOUT_MS = 2e4;
|
|
7086
|
+
/**
|
|
7087
|
+
* Derive the gif. `null` on every failure — a notification that lost its gif is
|
|
7088
|
+
* a notification, and one that failed is not.
|
|
7089
|
+
*
|
|
7090
|
+
* The child is guaranteed dead before this settles: these run on every
|
|
7091
|
+
* notification that asks for a gif, and a leaked ffmpeg accumulates on the node
|
|
7092
|
+
* until somebody notices the host is slow.
|
|
7093
|
+
*/
|
|
7094
|
+
async function gifFromMp4(input) {
|
|
7095
|
+
const args = require_dist.gifFromMp4Args({
|
|
7096
|
+
maxWidth: input.maxWidth ?? 640,
|
|
7097
|
+
fps: input.fps ?? 12,
|
|
7098
|
+
speed: input.speed ?? 4
|
|
7099
|
+
});
|
|
7100
|
+
const startedAt = Date.now();
|
|
7101
|
+
try {
|
|
7102
|
+
const bytes = await runGif(input, args);
|
|
7103
|
+
input.logger?.info("nc gif: derived from the notification video", {
|
|
7104
|
+
tags: { deviceId: input.deviceId },
|
|
7105
|
+
meta: {
|
|
7106
|
+
sourceBytes: input.mp4.length,
|
|
7107
|
+
gifBytes: bytes.length,
|
|
7108
|
+
width: input.maxWidth ?? 640,
|
|
7109
|
+
fps: input.fps ?? 12,
|
|
7110
|
+
speed: input.speed ?? 4,
|
|
7111
|
+
encodeMs: Date.now() - startedAt
|
|
7112
|
+
}
|
|
7113
|
+
});
|
|
7114
|
+
return bytes;
|
|
7115
|
+
} catch (err) {
|
|
7116
|
+
input.logger?.warn("nc gif: the derive failed — this notification ships without a gif", {
|
|
7117
|
+
tags: { deviceId: input.deviceId },
|
|
7118
|
+
meta: {
|
|
7119
|
+
sourceBytes: input.mp4.length,
|
|
7120
|
+
error: err instanceof Error ? err.message : String(err)
|
|
7121
|
+
}
|
|
7122
|
+
});
|
|
7123
|
+
return null;
|
|
7124
|
+
}
|
|
7125
|
+
}
|
|
7126
|
+
function runGif(input, args) {
|
|
7127
|
+
return new Promise((resolve, reject) => {
|
|
7128
|
+
const proc = input.spawnFn(input.ffmpegPath ?? "ffmpeg", [...args], { stdio: [
|
|
7129
|
+
"pipe",
|
|
7130
|
+
"pipe",
|
|
7131
|
+
"pipe"
|
|
7132
|
+
] });
|
|
7133
|
+
const chunks = [];
|
|
7134
|
+
let stderrTail = "";
|
|
7135
|
+
let done = false;
|
|
7136
|
+
let timer = null;
|
|
7137
|
+
const settle = (err, out) => {
|
|
7138
|
+
if (done) return;
|
|
7139
|
+
done = true;
|
|
7140
|
+
if (timer !== null) clearTimeout(timer);
|
|
7141
|
+
if (proc.exitCode === null && proc.signalCode === null) try {
|
|
7142
|
+
proc.kill("SIGKILL");
|
|
7143
|
+
} catch {}
|
|
7144
|
+
try {
|
|
7145
|
+
proc.stdout?.removeAllListeners();
|
|
7146
|
+
proc.stderr?.removeAllListeners();
|
|
7147
|
+
proc.stdin?.destroy();
|
|
7148
|
+
} catch {}
|
|
7149
|
+
if (err !== null) reject(err);
|
|
7150
|
+
else resolve(out ?? new Uint8Array(0));
|
|
7151
|
+
};
|
|
7152
|
+
timer = setTimeout(() => settle(/* @__PURE__ */ new Error("gif derive timed out")), GIF_RENDER_TIMEOUT_MS);
|
|
7153
|
+
timer.unref?.();
|
|
7154
|
+
proc.stdout?.on("data", (c) => chunks.push(c));
|
|
7155
|
+
proc.stderr?.on("data", (c) => {
|
|
7156
|
+
stderrTail = (stderrTail + c.toString()).slice(-400);
|
|
7157
|
+
});
|
|
7158
|
+
proc.on("error", (err) => settle(err instanceof Error ? err : new Error(String(err))));
|
|
7159
|
+
proc.on("close", (code) => {
|
|
7160
|
+
if (code !== 0) {
|
|
7161
|
+
settle(/* @__PURE__ */ new Error(`ffmpeg gif derive exited ${code}: ${stderrTail}`));
|
|
7162
|
+
return;
|
|
7163
|
+
}
|
|
7164
|
+
const out = Buffer.concat(chunks);
|
|
7165
|
+
if (out.byteLength === 0) {
|
|
7166
|
+
settle(/* @__PURE__ */ new Error("gif derive produced no bytes"));
|
|
7167
|
+
return;
|
|
7168
|
+
}
|
|
7169
|
+
const bytes = new Uint8Array(out.byteLength);
|
|
7170
|
+
bytes.set(out);
|
|
7171
|
+
settle(null, bytes);
|
|
7172
|
+
});
|
|
7173
|
+
proc.stdin?.on("error", () => {});
|
|
7174
|
+
proc.stdin?.write(Buffer.from(input.mp4));
|
|
7175
|
+
proc.stdin?.end();
|
|
7176
|
+
});
|
|
7177
|
+
}
|
|
7084
7178
|
//#endregion
|
|
7085
7179
|
//#region src/stream-broker/webrtc/nal-utils.ts
|
|
7086
7180
|
var NAL_START_CODE_4B = Buffer.from([
|
|
@@ -7787,15 +7881,6 @@ function eventClipEncodeWidth(sourceWidth, speed) {
|
|
|
7787
7881
|
return Math.min(source, EVENT_CLIP_ENCODE_MAX_WIDTH);
|
|
7788
7882
|
}
|
|
7789
7883
|
/**
|
|
7790
|
-
* Format a frame rate for an ffmpeg filter argument.
|
|
7791
|
-
*
|
|
7792
|
-
* `12 / 4` must reach the filter as `3` and `15 / 4` as `3.75`, not as a float
|
|
7793
|
-
* tail that `av_parse_video_rate` then has to guess at.
|
|
7794
|
-
*/
|
|
7795
|
-
function ffmpegRate(rate) {
|
|
7796
|
-
return String(Math.round(rate * 1e3) / 1e3);
|
|
7797
|
-
}
|
|
7798
|
-
/**
|
|
7799
7884
|
* Whether this render can COPY the camera's own H.264 instead of re-encoding it.
|
|
7800
7885
|
*
|
|
7801
7886
|
* The ring already holds the camera's elementary stream. Re-encoding it is only
|
|
@@ -7831,7 +7916,7 @@ function clipFfmpegArgs(input) {
|
|
|
7831
7916
|
const demuxer = input.hevc === true ? "hevc" : "h264";
|
|
7832
7917
|
const speed = input.speed ?? 2;
|
|
7833
7918
|
const setpts = speed !== 1 ? `,setpts=PTS/${speed}` : "";
|
|
7834
|
-
const gifSetpts = speed !== 1 ? `${setpts},fps=${ffmpegRate(input.fps * speed)}` : setpts;
|
|
7919
|
+
const gifSetpts = speed !== 1 ? `${setpts},fps=${require_dist.ffmpegRate(input.fps * speed)}` : setpts;
|
|
7835
7920
|
if (input.format === "gif") return [
|
|
7836
7921
|
"-y",
|
|
7837
7922
|
"-f",
|
|
@@ -7839,7 +7924,7 @@ function clipFfmpegArgs(input) {
|
|
|
7839
7924
|
"-i",
|
|
7840
7925
|
"pipe:0",
|
|
7841
7926
|
"-filter_complex",
|
|
7842
|
-
`[0:v]fps=${ffmpegRate(input.fps)}${gifSetpts},${scale},split[a][b];[a]palettegen=stats_mode=diff[p];[b][p]paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle`,
|
|
7927
|
+
`[0:v]fps=${require_dist.ffmpegRate(input.fps)}${gifSetpts},${scale},split[a][b];[a]palettegen=stats_mode=diff[p];[b][p]paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle`,
|
|
7843
7928
|
"-loop",
|
|
7844
7929
|
"0",
|
|
7845
7930
|
"-f",
|
|
@@ -7950,142 +8035,6 @@ async function renderPreBufferClip(input) {
|
|
|
7950
8035
|
proc.stdin?.end();
|
|
7951
8036
|
});
|
|
7952
8037
|
}
|
|
7953
|
-
/**
|
|
7954
|
-
* The factor the derive must apply ON TOP of the speed the mp4 already carries.
|
|
7955
|
-
*
|
|
7956
|
-
* The gif is derived from the muxed mp4, so if that mux already ran `setpts` at
|
|
7957
|
-
* the caller's `speed`, applying the absolute gif rate again would compound
|
|
7958
|
-
* them — a 4× gif beside a 2× video would come out at 8×. Discounting here is
|
|
7959
|
-
* what keeps {@link GIF_SPEED} an ABSOLUTE rate against real time whatever the
|
|
7960
|
-
* video does.
|
|
7961
|
-
*/
|
|
7962
|
-
function gifDeriveSpeed(gifSpeed, videoSpeed) {
|
|
7963
|
-
if (!Number.isFinite(videoSpeed) || videoSpeed <= 0) return gifSpeed;
|
|
7964
|
-
return gifSpeed / videoSpeed;
|
|
7965
|
-
}
|
|
7966
|
-
/** A derive that has not finished by now will not finish inside the drain. */
|
|
7967
|
-
var GIF_RENDER_TIMEOUT_MS = 2e4;
|
|
7968
|
-
/**
|
|
7969
|
-
* The filter chain. Extracted so a test can assert the palette pair without
|
|
7970
|
-
* spawning ffmpeg — an argv test cannot see quality, but it can see a filter
|
|
7971
|
-
* that somebody deleted.
|
|
7972
|
-
*/
|
|
7973
|
-
function gifFilterComplex(input) {
|
|
7974
|
-
const speed = input.speed > 0 ? input.speed : 1;
|
|
7975
|
-
if (speed === 1) return `[0:v]fps=${ffmpegRate(input.fps)},scale=${input.maxWidth}:-2:flags=lanczos,split[a][b];[a]palettegen=stats_mode=diff[p];[b][p]paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle`;
|
|
7976
|
-
return `[0:v]fps=${ffmpegRate(input.fps / speed)},setpts=PTS/${speed},fps=${ffmpegRate(input.fps)},scale=${input.maxWidth}:-2:flags=lanczos,split[a][b];[a]palettegen=stats_mode=diff[p];[b][p]paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle`;
|
|
7977
|
-
}
|
|
7978
|
-
/** The full argv, for the same reason. */
|
|
7979
|
-
function gifFromMp4Args(input) {
|
|
7980
|
-
return [
|
|
7981
|
-
"-y",
|
|
7982
|
-
"-v",
|
|
7983
|
-
"error",
|
|
7984
|
-
"-f",
|
|
7985
|
-
"mp4",
|
|
7986
|
-
"-i",
|
|
7987
|
-
"pipe:0",
|
|
7988
|
-
"-filter_complex",
|
|
7989
|
-
gifFilterComplex(input),
|
|
7990
|
-
"-loop",
|
|
7991
|
-
"0",
|
|
7992
|
-
"-f",
|
|
7993
|
-
"gif",
|
|
7994
|
-
"pipe:1"
|
|
7995
|
-
];
|
|
7996
|
-
}
|
|
7997
|
-
/**
|
|
7998
|
-
* Derive the gif. `null` on every failure — a notification that lost its gif is
|
|
7999
|
-
* a notification, and one that failed is not.
|
|
8000
|
-
*
|
|
8001
|
-
* The child is guaranteed dead before this settles: these run on every
|
|
8002
|
-
* notification that asks for a gif, and a leaked ffmpeg accumulates on the node
|
|
8003
|
-
* until somebody notices the host is slow.
|
|
8004
|
-
*/
|
|
8005
|
-
async function gifFromMp4(input) {
|
|
8006
|
-
const args = gifFromMp4Args({
|
|
8007
|
-
maxWidth: input.maxWidth ?? 640,
|
|
8008
|
-
fps: input.fps ?? 12,
|
|
8009
|
-
speed: input.speed ?? 4
|
|
8010
|
-
});
|
|
8011
|
-
const startedAt = Date.now();
|
|
8012
|
-
try {
|
|
8013
|
-
const bytes = await runGif(input, args);
|
|
8014
|
-
input.logger?.info("nc gif: derived from the notification video", {
|
|
8015
|
-
tags: { deviceId: input.deviceId },
|
|
8016
|
-
meta: {
|
|
8017
|
-
sourceBytes: input.mp4.length,
|
|
8018
|
-
gifBytes: bytes.length,
|
|
8019
|
-
width: input.maxWidth ?? 640,
|
|
8020
|
-
fps: input.fps ?? 12,
|
|
8021
|
-
speed: input.speed ?? 4,
|
|
8022
|
-
encodeMs: Date.now() - startedAt
|
|
8023
|
-
}
|
|
8024
|
-
});
|
|
8025
|
-
return bytes;
|
|
8026
|
-
} catch (err) {
|
|
8027
|
-
input.logger?.warn("nc gif: the derive failed — this notification ships without a gif", {
|
|
8028
|
-
tags: { deviceId: input.deviceId },
|
|
8029
|
-
meta: {
|
|
8030
|
-
sourceBytes: input.mp4.length,
|
|
8031
|
-
error: err instanceof Error ? err.message : String(err)
|
|
8032
|
-
}
|
|
8033
|
-
});
|
|
8034
|
-
return null;
|
|
8035
|
-
}
|
|
8036
|
-
}
|
|
8037
|
-
function runGif(input, args) {
|
|
8038
|
-
return new Promise((resolve, reject) => {
|
|
8039
|
-
const proc = input.spawnFn(input.ffmpegPath ?? "ffmpeg", [...args], { stdio: [
|
|
8040
|
-
"pipe",
|
|
8041
|
-
"pipe",
|
|
8042
|
-
"pipe"
|
|
8043
|
-
] });
|
|
8044
|
-
const chunks = [];
|
|
8045
|
-
let stderrTail = "";
|
|
8046
|
-
let done = false;
|
|
8047
|
-
let timer = null;
|
|
8048
|
-
const settle = (err, out) => {
|
|
8049
|
-
if (done) return;
|
|
8050
|
-
done = true;
|
|
8051
|
-
if (timer !== null) clearTimeout(timer);
|
|
8052
|
-
if (proc.exitCode === null && proc.signalCode === null) try {
|
|
8053
|
-
proc.kill("SIGKILL");
|
|
8054
|
-
} catch {}
|
|
8055
|
-
try {
|
|
8056
|
-
proc.stdout?.removeAllListeners();
|
|
8057
|
-
proc.stderr?.removeAllListeners();
|
|
8058
|
-
proc.stdin?.destroy();
|
|
8059
|
-
} catch {}
|
|
8060
|
-
if (err !== null) reject(err);
|
|
8061
|
-
else resolve(out ?? new Uint8Array(0));
|
|
8062
|
-
};
|
|
8063
|
-
timer = setTimeout(() => settle(/* @__PURE__ */ new Error("gif derive timed out")), GIF_RENDER_TIMEOUT_MS);
|
|
8064
|
-
timer.unref?.();
|
|
8065
|
-
proc.stdout?.on("data", (c) => chunks.push(c));
|
|
8066
|
-
proc.stderr?.on("data", (c) => {
|
|
8067
|
-
stderrTail = (stderrTail + c.toString()).slice(-400);
|
|
8068
|
-
});
|
|
8069
|
-
proc.on("error", (err) => settle(err instanceof Error ? err : new Error(String(err))));
|
|
8070
|
-
proc.on("close", (code) => {
|
|
8071
|
-
if (code !== 0) {
|
|
8072
|
-
settle(/* @__PURE__ */ new Error(`ffmpeg gif derive exited ${code}: ${stderrTail}`));
|
|
8073
|
-
return;
|
|
8074
|
-
}
|
|
8075
|
-
const out = Buffer.concat(chunks);
|
|
8076
|
-
if (out.byteLength === 0) {
|
|
8077
|
-
settle(/* @__PURE__ */ new Error("gif derive produced no bytes"));
|
|
8078
|
-
return;
|
|
8079
|
-
}
|
|
8080
|
-
const bytes = new Uint8Array(out.byteLength);
|
|
8081
|
-
bytes.set(out);
|
|
8082
|
-
settle(null, bytes);
|
|
8083
|
-
});
|
|
8084
|
-
proc.stdin?.on("error", () => {});
|
|
8085
|
-
proc.stdin?.write(Buffer.from(input.mp4));
|
|
8086
|
-
proc.stdin?.end();
|
|
8087
|
-
});
|
|
8088
|
-
}
|
|
8089
8038
|
//#endregion
|
|
8090
8039
|
//#region src/stream-broker/stream-broker/sentry-encode.ts
|
|
8091
8040
|
/**
|
|
@@ -19509,7 +19458,7 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
19509
19458
|
deviceId: input.deviceId,
|
|
19510
19459
|
maxWidth: input.gifMaxWidth,
|
|
19511
19460
|
fps: input.gifFps,
|
|
19512
|
-
speed: gifDeriveSpeed(gifSpeed, input.speed),
|
|
19461
|
+
speed: require_dist.gifDeriveSpeed(gifSpeed, input.speed),
|
|
19513
19462
|
...this.logger !== void 0 ? { logger: this.logger } : {},
|
|
19514
19463
|
spawnFn: node_child_process.spawn,
|
|
19515
19464
|
...this.ffmpegConfig.binaryPath !== void 0 ? { ffmpegPath: this.ffmpegConfig.binaryPath } : {}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { r as __toESM } from "../chunk-DnnnRqeS.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { i as NO_COST_CLAIM, n as Fmp4FragmentChild, o as probeFfmpegBinary, r as Fmp4FragmentPlane, t as ChildCostRegistry } from "../node-
|
|
2
|
+
import { An as array, Bn as union, Cn as makeSourceBrokerId, En as parseProfileBrokerId, Fn as number, Ft as rankStreams, H as addonWidgetsSourceCapability, Ht as resolveEgressDecodeHwAccel, In as object, K as batteryCapability, M as RATE_CONTROL_TIGHT, Mn as discriminatedUnion, Pn as literal, Q as declareLogChannel, R as RingBuffer, Rn as record, Sn as makeProfileBrokerId, St as maskUrlCredentials, Vn as EventCategory, X as createHwAccelCache, Xt as streamBrokerCapability, Y as clipExportFailureOf, Z as createLogChannelsProvider, a as BatteryStatusSchema, at as egressTransportFromRequest, bt as logChannelsCapability, cn as DeviceFeature, dn as BOOT_RECOVERY_BACKOFF_MS, en as webrtcSessionCapability, et as deriveBatteryPresence, fn as BaseAddon, ft as ffmpegRate, gn as createEvent, ht as gifFromMp4Args, in as buildFfmpegArgs$1, it as egressTranscodeSharingKey, j as RATE_CONTROL_RELAXED, jn as boolean, kn as _enum, ln as DeviceType, mn as CamProfileSchema, mt as gifDeriveSpeed, o as CLIP_BROKER_PACED_RATES, on as invocationFromEncodeProfile, pn as CAM_PROFILE_ORDER, q as cameraStreamsCapability, s as CLIP_STILL_REASON_CODE_HEADER, sn as isSoftwareDecode, tn as AUDIO_PRESETS, un as errMsg, w as G711_SCALE_CORRECTION_DB, wn as nodePin, x as EncodeProfileSchema, xn as isEvent, yn as expandAudioChunkToF32le, yt as loadContributionCapability, zn as string } from "../dist-DdVMFlJ6.mjs";
|
|
3
|
+
import { i as NO_COST_CLAIM, n as Fmp4FragmentChild, o as probeFfmpegBinary, r as Fmp4FragmentPlane, t as ChildCostRegistry } from "../node-COu_tHy4.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 avccSampleToAnnexB, i as require_mp4box_all, n as demuxSegmentPreferJs, o as buildKeyframeAnnexB, r as runFfmpegOnce, s as parseNalLengthSize, t as demuxSegmentFullJs } from "../segment-demux-js-
|
|
7
|
+
import { a as avccSampleToAnnexB, i as require_mp4box_all, n as demuxSegmentPreferJs, o as buildKeyframeAnnexB, r as runFfmpegOnce, s as parseNalLengthSize, t as demuxSegmentFullJs } from "../segment-demux-js-CEJn4BR0.mjs";
|
|
8
8
|
import { createRequire } from "node:module";
|
|
9
9
|
import * as os from "node:os";
|
|
10
10
|
import { networkInterfaces, tmpdir } from "node:os";
|
|
@@ -7077,6 +7077,100 @@ function defaultId() {
|
|
|
7077
7077
|
counter += 1;
|
|
7078
7078
|
return `${Date.now().toString(36)}${counter.toString(36)}`;
|
|
7079
7079
|
}
|
|
7080
|
+
/** A derive that has not finished by now will not finish inside the drain. */
|
|
7081
|
+
var GIF_RENDER_TIMEOUT_MS = 2e4;
|
|
7082
|
+
/**
|
|
7083
|
+
* Derive the gif. `null` on every failure — a notification that lost its gif is
|
|
7084
|
+
* a notification, and one that failed is not.
|
|
7085
|
+
*
|
|
7086
|
+
* The child is guaranteed dead before this settles: these run on every
|
|
7087
|
+
* notification that asks for a gif, and a leaked ffmpeg accumulates on the node
|
|
7088
|
+
* until somebody notices the host is slow.
|
|
7089
|
+
*/
|
|
7090
|
+
async function gifFromMp4(input) {
|
|
7091
|
+
const args = gifFromMp4Args({
|
|
7092
|
+
maxWidth: input.maxWidth ?? 640,
|
|
7093
|
+
fps: input.fps ?? 12,
|
|
7094
|
+
speed: input.speed ?? 4
|
|
7095
|
+
});
|
|
7096
|
+
const startedAt = Date.now();
|
|
7097
|
+
try {
|
|
7098
|
+
const bytes = await runGif(input, args);
|
|
7099
|
+
input.logger?.info("nc gif: derived from the notification video", {
|
|
7100
|
+
tags: { deviceId: input.deviceId },
|
|
7101
|
+
meta: {
|
|
7102
|
+
sourceBytes: input.mp4.length,
|
|
7103
|
+
gifBytes: bytes.length,
|
|
7104
|
+
width: input.maxWidth ?? 640,
|
|
7105
|
+
fps: input.fps ?? 12,
|
|
7106
|
+
speed: input.speed ?? 4,
|
|
7107
|
+
encodeMs: Date.now() - startedAt
|
|
7108
|
+
}
|
|
7109
|
+
});
|
|
7110
|
+
return bytes;
|
|
7111
|
+
} catch (err) {
|
|
7112
|
+
input.logger?.warn("nc gif: the derive failed — this notification ships without a gif", {
|
|
7113
|
+
tags: { deviceId: input.deviceId },
|
|
7114
|
+
meta: {
|
|
7115
|
+
sourceBytes: input.mp4.length,
|
|
7116
|
+
error: err instanceof Error ? err.message : String(err)
|
|
7117
|
+
}
|
|
7118
|
+
});
|
|
7119
|
+
return null;
|
|
7120
|
+
}
|
|
7121
|
+
}
|
|
7122
|
+
function runGif(input, args) {
|
|
7123
|
+
return new Promise((resolve, reject) => {
|
|
7124
|
+
const proc = input.spawnFn(input.ffmpegPath ?? "ffmpeg", [...args], { stdio: [
|
|
7125
|
+
"pipe",
|
|
7126
|
+
"pipe",
|
|
7127
|
+
"pipe"
|
|
7128
|
+
] });
|
|
7129
|
+
const chunks = [];
|
|
7130
|
+
let stderrTail = "";
|
|
7131
|
+
let done = false;
|
|
7132
|
+
let timer = null;
|
|
7133
|
+
const settle = (err, out) => {
|
|
7134
|
+
if (done) return;
|
|
7135
|
+
done = true;
|
|
7136
|
+
if (timer !== null) clearTimeout(timer);
|
|
7137
|
+
if (proc.exitCode === null && proc.signalCode === null) try {
|
|
7138
|
+
proc.kill("SIGKILL");
|
|
7139
|
+
} catch {}
|
|
7140
|
+
try {
|
|
7141
|
+
proc.stdout?.removeAllListeners();
|
|
7142
|
+
proc.stderr?.removeAllListeners();
|
|
7143
|
+
proc.stdin?.destroy();
|
|
7144
|
+
} catch {}
|
|
7145
|
+
if (err !== null) reject(err);
|
|
7146
|
+
else resolve(out ?? new Uint8Array(0));
|
|
7147
|
+
};
|
|
7148
|
+
timer = setTimeout(() => settle(/* @__PURE__ */ new Error("gif derive timed out")), GIF_RENDER_TIMEOUT_MS);
|
|
7149
|
+
timer.unref?.();
|
|
7150
|
+
proc.stdout?.on("data", (c) => chunks.push(c));
|
|
7151
|
+
proc.stderr?.on("data", (c) => {
|
|
7152
|
+
stderrTail = (stderrTail + c.toString()).slice(-400);
|
|
7153
|
+
});
|
|
7154
|
+
proc.on("error", (err) => settle(err instanceof Error ? err : new Error(String(err))));
|
|
7155
|
+
proc.on("close", (code) => {
|
|
7156
|
+
if (code !== 0) {
|
|
7157
|
+
settle(/* @__PURE__ */ new Error(`ffmpeg gif derive exited ${code}: ${stderrTail}`));
|
|
7158
|
+
return;
|
|
7159
|
+
}
|
|
7160
|
+
const out = Buffer.concat(chunks);
|
|
7161
|
+
if (out.byteLength === 0) {
|
|
7162
|
+
settle(/* @__PURE__ */ new Error("gif derive produced no bytes"));
|
|
7163
|
+
return;
|
|
7164
|
+
}
|
|
7165
|
+
const bytes = new Uint8Array(out.byteLength);
|
|
7166
|
+
bytes.set(out);
|
|
7167
|
+
settle(null, bytes);
|
|
7168
|
+
});
|
|
7169
|
+
proc.stdin?.on("error", () => {});
|
|
7170
|
+
proc.stdin?.write(Buffer.from(input.mp4));
|
|
7171
|
+
proc.stdin?.end();
|
|
7172
|
+
});
|
|
7173
|
+
}
|
|
7080
7174
|
//#endregion
|
|
7081
7175
|
//#region src/stream-broker/webrtc/nal-utils.ts
|
|
7082
7176
|
var NAL_START_CODE_4B = Buffer.from([
|
|
@@ -7783,15 +7877,6 @@ function eventClipEncodeWidth(sourceWidth, speed) {
|
|
|
7783
7877
|
return Math.min(source, EVENT_CLIP_ENCODE_MAX_WIDTH);
|
|
7784
7878
|
}
|
|
7785
7879
|
/**
|
|
7786
|
-
* Format a frame rate for an ffmpeg filter argument.
|
|
7787
|
-
*
|
|
7788
|
-
* `12 / 4` must reach the filter as `3` and `15 / 4` as `3.75`, not as a float
|
|
7789
|
-
* tail that `av_parse_video_rate` then has to guess at.
|
|
7790
|
-
*/
|
|
7791
|
-
function ffmpegRate(rate) {
|
|
7792
|
-
return String(Math.round(rate * 1e3) / 1e3);
|
|
7793
|
-
}
|
|
7794
|
-
/**
|
|
7795
7880
|
* Whether this render can COPY the camera's own H.264 instead of re-encoding it.
|
|
7796
7881
|
*
|
|
7797
7882
|
* The ring already holds the camera's elementary stream. Re-encoding it is only
|
|
@@ -7946,142 +8031,6 @@ async function renderPreBufferClip(input) {
|
|
|
7946
8031
|
proc.stdin?.end();
|
|
7947
8032
|
});
|
|
7948
8033
|
}
|
|
7949
|
-
/**
|
|
7950
|
-
* The factor the derive must apply ON TOP of the speed the mp4 already carries.
|
|
7951
|
-
*
|
|
7952
|
-
* The gif is derived from the muxed mp4, so if that mux already ran `setpts` at
|
|
7953
|
-
* the caller's `speed`, applying the absolute gif rate again would compound
|
|
7954
|
-
* them — a 4× gif beside a 2× video would come out at 8×. Discounting here is
|
|
7955
|
-
* what keeps {@link GIF_SPEED} an ABSOLUTE rate against real time whatever the
|
|
7956
|
-
* video does.
|
|
7957
|
-
*/
|
|
7958
|
-
function gifDeriveSpeed(gifSpeed, videoSpeed) {
|
|
7959
|
-
if (!Number.isFinite(videoSpeed) || videoSpeed <= 0) return gifSpeed;
|
|
7960
|
-
return gifSpeed / videoSpeed;
|
|
7961
|
-
}
|
|
7962
|
-
/** A derive that has not finished by now will not finish inside the drain. */
|
|
7963
|
-
var GIF_RENDER_TIMEOUT_MS = 2e4;
|
|
7964
|
-
/**
|
|
7965
|
-
* The filter chain. Extracted so a test can assert the palette pair without
|
|
7966
|
-
* spawning ffmpeg — an argv test cannot see quality, but it can see a filter
|
|
7967
|
-
* that somebody deleted.
|
|
7968
|
-
*/
|
|
7969
|
-
function gifFilterComplex(input) {
|
|
7970
|
-
const speed = input.speed > 0 ? input.speed : 1;
|
|
7971
|
-
if (speed === 1) return `[0:v]fps=${ffmpegRate(input.fps)},scale=${input.maxWidth}:-2:flags=lanczos,split[a][b];[a]palettegen=stats_mode=diff[p];[b][p]paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle`;
|
|
7972
|
-
return `[0:v]fps=${ffmpegRate(input.fps / speed)},setpts=PTS/${speed},fps=${ffmpegRate(input.fps)},scale=${input.maxWidth}:-2:flags=lanczos,split[a][b];[a]palettegen=stats_mode=diff[p];[b][p]paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle`;
|
|
7973
|
-
}
|
|
7974
|
-
/** The full argv, for the same reason. */
|
|
7975
|
-
function gifFromMp4Args(input) {
|
|
7976
|
-
return [
|
|
7977
|
-
"-y",
|
|
7978
|
-
"-v",
|
|
7979
|
-
"error",
|
|
7980
|
-
"-f",
|
|
7981
|
-
"mp4",
|
|
7982
|
-
"-i",
|
|
7983
|
-
"pipe:0",
|
|
7984
|
-
"-filter_complex",
|
|
7985
|
-
gifFilterComplex(input),
|
|
7986
|
-
"-loop",
|
|
7987
|
-
"0",
|
|
7988
|
-
"-f",
|
|
7989
|
-
"gif",
|
|
7990
|
-
"pipe:1"
|
|
7991
|
-
];
|
|
7992
|
-
}
|
|
7993
|
-
/**
|
|
7994
|
-
* Derive the gif. `null` on every failure — a notification that lost its gif is
|
|
7995
|
-
* a notification, and one that failed is not.
|
|
7996
|
-
*
|
|
7997
|
-
* The child is guaranteed dead before this settles: these run on every
|
|
7998
|
-
* notification that asks for a gif, and a leaked ffmpeg accumulates on the node
|
|
7999
|
-
* until somebody notices the host is slow.
|
|
8000
|
-
*/
|
|
8001
|
-
async function gifFromMp4(input) {
|
|
8002
|
-
const args = gifFromMp4Args({
|
|
8003
|
-
maxWidth: input.maxWidth ?? 640,
|
|
8004
|
-
fps: input.fps ?? 12,
|
|
8005
|
-
speed: input.speed ?? 4
|
|
8006
|
-
});
|
|
8007
|
-
const startedAt = Date.now();
|
|
8008
|
-
try {
|
|
8009
|
-
const bytes = await runGif(input, args);
|
|
8010
|
-
input.logger?.info("nc gif: derived from the notification video", {
|
|
8011
|
-
tags: { deviceId: input.deviceId },
|
|
8012
|
-
meta: {
|
|
8013
|
-
sourceBytes: input.mp4.length,
|
|
8014
|
-
gifBytes: bytes.length,
|
|
8015
|
-
width: input.maxWidth ?? 640,
|
|
8016
|
-
fps: input.fps ?? 12,
|
|
8017
|
-
speed: input.speed ?? 4,
|
|
8018
|
-
encodeMs: Date.now() - startedAt
|
|
8019
|
-
}
|
|
8020
|
-
});
|
|
8021
|
-
return bytes;
|
|
8022
|
-
} catch (err) {
|
|
8023
|
-
input.logger?.warn("nc gif: the derive failed — this notification ships without a gif", {
|
|
8024
|
-
tags: { deviceId: input.deviceId },
|
|
8025
|
-
meta: {
|
|
8026
|
-
sourceBytes: input.mp4.length,
|
|
8027
|
-
error: err instanceof Error ? err.message : String(err)
|
|
8028
|
-
}
|
|
8029
|
-
});
|
|
8030
|
-
return null;
|
|
8031
|
-
}
|
|
8032
|
-
}
|
|
8033
|
-
function runGif(input, args) {
|
|
8034
|
-
return new Promise((resolve, reject) => {
|
|
8035
|
-
const proc = input.spawnFn(input.ffmpegPath ?? "ffmpeg", [...args], { stdio: [
|
|
8036
|
-
"pipe",
|
|
8037
|
-
"pipe",
|
|
8038
|
-
"pipe"
|
|
8039
|
-
] });
|
|
8040
|
-
const chunks = [];
|
|
8041
|
-
let stderrTail = "";
|
|
8042
|
-
let done = false;
|
|
8043
|
-
let timer = null;
|
|
8044
|
-
const settle = (err, out) => {
|
|
8045
|
-
if (done) return;
|
|
8046
|
-
done = true;
|
|
8047
|
-
if (timer !== null) clearTimeout(timer);
|
|
8048
|
-
if (proc.exitCode === null && proc.signalCode === null) try {
|
|
8049
|
-
proc.kill("SIGKILL");
|
|
8050
|
-
} catch {}
|
|
8051
|
-
try {
|
|
8052
|
-
proc.stdout?.removeAllListeners();
|
|
8053
|
-
proc.stderr?.removeAllListeners();
|
|
8054
|
-
proc.stdin?.destroy();
|
|
8055
|
-
} catch {}
|
|
8056
|
-
if (err !== null) reject(err);
|
|
8057
|
-
else resolve(out ?? new Uint8Array(0));
|
|
8058
|
-
};
|
|
8059
|
-
timer = setTimeout(() => settle(/* @__PURE__ */ new Error("gif derive timed out")), GIF_RENDER_TIMEOUT_MS);
|
|
8060
|
-
timer.unref?.();
|
|
8061
|
-
proc.stdout?.on("data", (c) => chunks.push(c));
|
|
8062
|
-
proc.stderr?.on("data", (c) => {
|
|
8063
|
-
stderrTail = (stderrTail + c.toString()).slice(-400);
|
|
8064
|
-
});
|
|
8065
|
-
proc.on("error", (err) => settle(err instanceof Error ? err : new Error(String(err))));
|
|
8066
|
-
proc.on("close", (code) => {
|
|
8067
|
-
if (code !== 0) {
|
|
8068
|
-
settle(/* @__PURE__ */ new Error(`ffmpeg gif derive exited ${code}: ${stderrTail}`));
|
|
8069
|
-
return;
|
|
8070
|
-
}
|
|
8071
|
-
const out = Buffer.concat(chunks);
|
|
8072
|
-
if (out.byteLength === 0) {
|
|
8073
|
-
settle(/* @__PURE__ */ new Error("gif derive produced no bytes"));
|
|
8074
|
-
return;
|
|
8075
|
-
}
|
|
8076
|
-
const bytes = new Uint8Array(out.byteLength);
|
|
8077
|
-
bytes.set(out);
|
|
8078
|
-
settle(null, bytes);
|
|
8079
|
-
});
|
|
8080
|
-
proc.stdin?.on("error", () => {});
|
|
8081
|
-
proc.stdin?.write(Buffer.from(input.mp4));
|
|
8082
|
-
proc.stdin?.end();
|
|
8083
|
-
});
|
|
8084
|
-
}
|
|
8085
8034
|
//#endregion
|
|
8086
8035
|
//#region src/stream-broker/stream-broker/sentry-encode.ts
|
|
8087
8036
|
/**
|
|
@@ -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-DdYUVQSA.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.307",
|
|
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",
|