@apocaliss92/nodelink-js 0.5.2 → 0.6.0
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/index.cjs +72 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +100 -0
- package/dist/index.d.ts +100 -0
- package/dist/index.js +72 -29
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -35165,10 +35165,18 @@ var CompositeStream = class extends import_node_events6.EventEmitter {
|
|
|
35165
35165
|
}
|
|
35166
35166
|
}
|
|
35167
35167
|
async startFfmpegCompositionFromRtspUrls(mainWidth, mainHeight, pipWidth, pipHeight, position, widerRtspUrl, teleRtspUrl, rtspTransport) {
|
|
35168
|
+
const videoEncoder = this.options.videoEncoder ?? "libx264";
|
|
35169
|
+
const isX264 = videoEncoder === "libx264";
|
|
35170
|
+
const encoderPreset = this.options.encoderPreset ?? "ultrafast";
|
|
35171
|
+
const crf = this.options.crf ?? 23;
|
|
35172
|
+
const gopSeconds = this.options.gopSeconds ?? 1;
|
|
35173
|
+
const assumedFps = 30;
|
|
35174
|
+
const gopFrames = Math.max(1, Math.round(gopSeconds * assumedFps));
|
|
35168
35175
|
const ffmpegArgs = [
|
|
35169
35176
|
"-hide_banner",
|
|
35170
35177
|
"-loglevel",
|
|
35171
35178
|
"error",
|
|
35179
|
+
...this.options.extraGlobalArgs ?? [],
|
|
35172
35180
|
"-fflags",
|
|
35173
35181
|
"+genpts",
|
|
35174
35182
|
// Input 0: wider
|
|
@@ -35189,27 +35197,33 @@ var CompositeStream = class extends import_node_events6.EventEmitter {
|
|
|
35189
35197
|
// Output: always H.264 Annex-B
|
|
35190
35198
|
"-an",
|
|
35191
35199
|
"-c:v",
|
|
35192
|
-
|
|
35200
|
+
videoEncoder,
|
|
35193
35201
|
"-g",
|
|
35194
|
-
|
|
35202
|
+
String(gopFrames),
|
|
35195
35203
|
"-keyint_min",
|
|
35196
|
-
|
|
35204
|
+
String(gopFrames),
|
|
35197
35205
|
"-sc_threshold",
|
|
35198
35206
|
"0",
|
|
35199
|
-
|
|
35200
|
-
|
|
35201
|
-
|
|
35202
|
-
|
|
35203
|
-
|
|
35204
|
-
|
|
35205
|
-
|
|
35206
|
-
|
|
35207
|
+
...isX264 ? [
|
|
35208
|
+
"-x264-params",
|
|
35209
|
+
`aud=1:repeat-headers=1:keyint=${gopFrames}:min-keyint=${gopFrames}:scenecut=0`,
|
|
35210
|
+
"-preset",
|
|
35211
|
+
encoderPreset,
|
|
35212
|
+
"-tune",
|
|
35213
|
+
"zerolatency",
|
|
35214
|
+
"-crf",
|
|
35215
|
+
String(crf)
|
|
35216
|
+
] : [],
|
|
35217
|
+
...this.options.extraOutputArgs ?? [],
|
|
35207
35218
|
"-f",
|
|
35208
35219
|
"h264",
|
|
35209
35220
|
"pipe:1"
|
|
35210
35221
|
];
|
|
35211
|
-
this.
|
|
35212
|
-
this.
|
|
35222
|
+
const ffmpegBin = this.options.ffmpegPath ?? "ffmpeg";
|
|
35223
|
+
this.logger.log?.(
|
|
35224
|
+
`[CompositeStream] Starting ffmpeg (rtsp inputs): bin=${ffmpegBin} args=${ffmpegArgs.join(" ")}`
|
|
35225
|
+
);
|
|
35226
|
+
this.ffmpegProcess = (0, import_node_child_process7.spawn)(ffmpegBin, ffmpegArgs, {
|
|
35213
35227
|
stdio: ["ignore", "pipe", "pipe"]
|
|
35214
35228
|
});
|
|
35215
35229
|
this.ffmpegProcess.on("error", (error) => {
|
|
@@ -35276,10 +35290,18 @@ var CompositeStream = class extends import_node_events6.EventEmitter {
|
|
|
35276
35290
|
"-i",
|
|
35277
35291
|
"pipe:3"
|
|
35278
35292
|
];
|
|
35293
|
+
const videoEncoder = this.options.videoEncoder ?? "libx264";
|
|
35294
|
+
const isX264 = videoEncoder === "libx264";
|
|
35295
|
+
const encoderPreset = this.options.encoderPreset ?? "ultrafast";
|
|
35296
|
+
const crf = this.options.crf ?? 23;
|
|
35297
|
+
const gopSeconds = this.options.gopSeconds ?? 1;
|
|
35298
|
+
const assumedFps = 30;
|
|
35299
|
+
const gopFrames = Math.max(1, Math.round(gopSeconds * assumedFps));
|
|
35279
35300
|
const ffmpegArgs = [
|
|
35280
35301
|
"-hide_banner",
|
|
35281
35302
|
"-loglevel",
|
|
35282
35303
|
"error",
|
|
35304
|
+
...this.options.extraGlobalArgs ?? [],
|
|
35283
35305
|
"-fflags",
|
|
35284
35306
|
"+genpts",
|
|
35285
35307
|
"-probesize",
|
|
@@ -35298,33 +35320,40 @@ var CompositeStream = class extends import_node_events6.EventEmitter {
|
|
|
35298
35320
|
"-map",
|
|
35299
35321
|
"[out]",
|
|
35300
35322
|
"-c:v",
|
|
35301
|
-
|
|
35302
|
-
//
|
|
35303
|
-
//
|
|
35304
|
-
//
|
|
35323
|
+
videoEncoder,
|
|
35324
|
+
// Make the stream easy to join mid-flight: frequent IDRs + in-band
|
|
35325
|
+
// headers + AUD. Without this, a new client may wait many seconds
|
|
35326
|
+
// for the next keyframe.
|
|
35305
35327
|
"-g",
|
|
35306
|
-
|
|
35328
|
+
String(gopFrames),
|
|
35307
35329
|
"-keyint_min",
|
|
35308
|
-
|
|
35330
|
+
String(gopFrames),
|
|
35309
35331
|
"-sc_threshold",
|
|
35310
35332
|
"0",
|
|
35311
|
-
|
|
35312
|
-
|
|
35313
|
-
|
|
35314
|
-
|
|
35315
|
-
|
|
35316
|
-
|
|
35317
|
-
|
|
35318
|
-
|
|
35333
|
+
// libx264-specific knobs. We deliberately skip these for HW encoders
|
|
35334
|
+
// — each one has its own option vocabulary (`-q:v`, `-rc`, etc.)
|
|
35335
|
+
// and the user is expected to express them via extraOutputArgs.
|
|
35336
|
+
...isX264 ? [
|
|
35337
|
+
"-x264-params",
|
|
35338
|
+
`aud=1:repeat-headers=1:keyint=${gopFrames}:min-keyint=${gopFrames}:scenecut=0`,
|
|
35339
|
+
"-preset",
|
|
35340
|
+
encoderPreset,
|
|
35341
|
+
"-tune",
|
|
35342
|
+
"zerolatency",
|
|
35343
|
+
"-crf",
|
|
35344
|
+
String(crf)
|
|
35345
|
+
] : [],
|
|
35346
|
+
...this.options.extraOutputArgs ?? [],
|
|
35319
35347
|
"-f",
|
|
35320
35348
|
"h264",
|
|
35321
35349
|
"pipe:1"
|
|
35322
35350
|
// Output (stdout)
|
|
35323
35351
|
];
|
|
35352
|
+
const ffmpegBin = this.options.ffmpegPath ?? "ffmpeg";
|
|
35324
35353
|
this.logger.log?.(
|
|
35325
|
-
`[CompositeStream] Starting ffmpeg:
|
|
35354
|
+
`[CompositeStream] Starting ffmpeg: bin=${ffmpegBin} args=${ffmpegArgs.join(" ")}`
|
|
35326
35355
|
);
|
|
35327
|
-
this.ffmpegProcess = (0, import_node_child_process7.spawn)(
|
|
35356
|
+
this.ffmpegProcess = (0, import_node_child_process7.spawn)(ffmpegBin, ffmpegArgs, {
|
|
35328
35357
|
stdio: ["pipe", "pipe", "pipe", "pipe"]
|
|
35329
35358
|
});
|
|
35330
35359
|
this.ffmpegProcess.on("error", (error) => {
|
|
@@ -36032,6 +36061,20 @@ async function createRfc4571TcpServerInternal(options) {
|
|
|
36032
36061
|
...forceH264 !== void 0 ? { forceH264 } : defaultForceH264 ? { forceH264: true } : {},
|
|
36033
36062
|
...compositeOptions?.assumeH264Inputs !== void 0 ? { assumeH264Inputs: compositeOptions.assumeH264Inputs } : {},
|
|
36034
36063
|
...compositeOptions?.disableTranscode !== void 0 ? { disableTranscode: compositeOptions.disableTranscode } : {},
|
|
36064
|
+
// Propagate ffmpeg binary path — required when the embedder strips
|
|
36065
|
+
// PATH (Scrypted on Windows, Electron sandboxes, distroless Docker)
|
|
36066
|
+
// and the bundled ffmpeg is at a fixed absolute path only the
|
|
36067
|
+
// embedder knows.
|
|
36068
|
+
...compositeOptions?.ffmpegPath ? { ffmpegPath: compositeOptions.ffmpegPath } : {},
|
|
36069
|
+
// Encoder tuning knobs — see CompositeStreamPipOptions for the
|
|
36070
|
+
// semantic contract on each one. Plumbed verbatim so the
|
|
36071
|
+
// CompositeStream layer can apply defaults.
|
|
36072
|
+
...compositeOptions?.videoEncoder ? { videoEncoder: compositeOptions.videoEncoder } : {},
|
|
36073
|
+
...compositeOptions?.encoderPreset ? { encoderPreset: compositeOptions.encoderPreset } : {},
|
|
36074
|
+
...typeof compositeOptions?.crf === "number" ? { crf: compositeOptions.crf } : {},
|
|
36075
|
+
...typeof compositeOptions?.gopSeconds === "number" ? { gopSeconds: compositeOptions.gopSeconds } : {},
|
|
36076
|
+
...compositeOptions?.extraGlobalArgs ? { extraGlobalArgs: compositeOptions.extraGlobalArgs } : {},
|
|
36077
|
+
...compositeOptions?.extraOutputArgs ? { extraOutputArgs: compositeOptions.extraOutputArgs } : {},
|
|
36035
36078
|
logger
|
|
36036
36079
|
});
|
|
36037
36080
|
isCompositeStream = true;
|