@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.d.cts
CHANGED
|
@@ -5284,6 +5284,88 @@ interface CompositeStreamPipOptions {
|
|
|
5284
5284
|
teleRtspUrl?: string;
|
|
5285
5285
|
/** ffmpeg `-rtsp_transport` value (default: tcp). */
|
|
5286
5286
|
rtspTransport?: 'tcp' | 'udp';
|
|
5287
|
+
/**
|
|
5288
|
+
* Absolute path to the `ffmpeg` binary the compositor should `spawn()`.
|
|
5289
|
+
*
|
|
5290
|
+
* When unset, falls back to the bare string `"ffmpeg"`, which relies on
|
|
5291
|
+
* the host's `PATH`. This works on standard Linux / macOS Node setups
|
|
5292
|
+
* but fails silently on environments where the embedding process
|
|
5293
|
+
* strips PATH or ships its own ffmpeg in a non-discoverable location:
|
|
5294
|
+
*
|
|
5295
|
+
* - Scrypted on Windows (the Electron host launches plugins with a
|
|
5296
|
+
* minimal PATH; the bundled ffmpeg lives at a static absolute path
|
|
5297
|
+
* only `sdk.mediaManager.getFFmpegPath()` knows about).
|
|
5298
|
+
* - Scrypted on macOS App Store / sandboxed installs.
|
|
5299
|
+
* - Distroless / minimal Docker base images where ffmpeg is mounted
|
|
5300
|
+
* at a fixed path but not in PATH.
|
|
5301
|
+
*
|
|
5302
|
+
* Consumers in any of those environments should resolve the path
|
|
5303
|
+
* themselves (e.g. via the Scrypted SDK) and pass it through here.
|
|
5304
|
+
*/
|
|
5305
|
+
ffmpegPath?: string;
|
|
5306
|
+
/**
|
|
5307
|
+
* Output video encoder name (passed verbatim as `-c:v`). Default
|
|
5308
|
+
* `libx264` — pure software. On a host with hardware-accelerated
|
|
5309
|
+
* H.264 encoding, switching this is the single biggest perf win
|
|
5310
|
+
* available (5-10x less CPU for the same output bitrate). Supported
|
|
5311
|
+
* by ffmpeg in the wild:
|
|
5312
|
+
*
|
|
5313
|
+
* - Intel/AMD QuickSync: `h264_qsv`
|
|
5314
|
+
* - Intel/AMD VAAPI: `h264_vaapi`
|
|
5315
|
+
* - NVIDIA NVENC: `h264_nvenc`
|
|
5316
|
+
* - Apple VideoToolbox: `h264_videotoolbox`
|
|
5317
|
+
* - Raspberry Pi / ARM: `h264_v4l2m2m`
|
|
5318
|
+
*
|
|
5319
|
+
* Caveat: when not `libx264`, the libx264-specific knobs
|
|
5320
|
+
* (`encoderPreset`, `crf`, `x264-params`) are silently dropped because
|
|
5321
|
+
* each HW encoder has its own option vocabulary. Use
|
|
5322
|
+
* {@link extraOutputArgs} to pass encoder-specific options
|
|
5323
|
+
* (e.g. `["-q:v","23"]` for QSV, `["-preset","fast"]` for NVENC).
|
|
5324
|
+
*/
|
|
5325
|
+
videoEncoder?: string;
|
|
5326
|
+
/**
|
|
5327
|
+
* libx264 preset (default `ultrafast`). Only consulted when
|
|
5328
|
+
* {@link videoEncoder} is left at its default (libx264). Valid:
|
|
5329
|
+
* `ultrafast | superfast | veryfast | faster | fast | medium | slow |
|
|
5330
|
+
* slower | veryslow | placebo`. Slower = better compression / more CPU.
|
|
5331
|
+
*/
|
|
5332
|
+
encoderPreset?: string;
|
|
5333
|
+
/**
|
|
5334
|
+
* CRF (constant rate factor) for libx264. Default 23 (visually
|
|
5335
|
+
* lossless-ish). Range 0 (lossless, huge) — 51 (worst, tiny). Lower
|
|
5336
|
+
* by 2 to roughly halve the bitrate at a given quality. Only consulted
|
|
5337
|
+
* when {@link videoEncoder} is libx264.
|
|
5338
|
+
*/
|
|
5339
|
+
crf?: number;
|
|
5340
|
+
/**
|
|
5341
|
+
* Output keyframe interval in seconds. Default 1 — important for
|
|
5342
|
+
* mid-stream join latency (a new HLS / RTSP client only starts
|
|
5343
|
+
* decoding from the next keyframe). Lower = faster join, larger
|
|
5344
|
+
* stream; higher = better compression, slower join.
|
|
5345
|
+
*/
|
|
5346
|
+
gopSeconds?: number;
|
|
5347
|
+
/**
|
|
5348
|
+
* Free-form ffmpeg arguments inserted at the START of the argv (after
|
|
5349
|
+
* `-hide_banner -loglevel`). Use for hardware-accel decode hints that
|
|
5350
|
+
* must appear before any `-i`:
|
|
5351
|
+
*
|
|
5352
|
+
* extraGlobalArgs: ["-hwaccel","videotoolbox"]
|
|
5353
|
+
* extraGlobalArgs: ["-hwaccel","qsv","-qsv_device","/dev/dri/renderD128"]
|
|
5354
|
+
*
|
|
5355
|
+
* No validation — invalid args here WILL crash ffmpeg.
|
|
5356
|
+
*/
|
|
5357
|
+
extraGlobalArgs?: readonly string[];
|
|
5358
|
+
/**
|
|
5359
|
+
* Free-form ffmpeg arguments inserted just BEFORE the `pipe:1` output.
|
|
5360
|
+
* Use for encoder-specific options when {@link videoEncoder} is not
|
|
5361
|
+
* `libx264`:
|
|
5362
|
+
*
|
|
5363
|
+
* extraOutputArgs: ["-q:v","23"] // qsv/vaapi
|
|
5364
|
+
* extraOutputArgs: ["-preset","fast","-rc","cbr"] // nvenc
|
|
5365
|
+
*
|
|
5366
|
+
* No validation — invalid args here WILL crash ffmpeg.
|
|
5367
|
+
*/
|
|
5368
|
+
extraOutputArgs?: readonly string[];
|
|
5287
5369
|
}
|
|
5288
5370
|
type CompositeStreamOptions = {
|
|
5289
5371
|
api: ReolinkBaichuanApi;
|
|
@@ -5326,6 +5408,24 @@ type CompositeStreamOptions = {
|
|
|
5326
5408
|
teleRtspUrl?: string;
|
|
5327
5409
|
/** ffmpeg `-rtsp_transport` value (default: tcp). */
|
|
5328
5410
|
rtspTransport?: 'tcp' | 'udp';
|
|
5411
|
+
/**
|
|
5412
|
+
* Absolute path to the `ffmpeg` binary the compositor should `spawn()`.
|
|
5413
|
+
* Mirrors {@link CompositeStreamPipOptions.ffmpegPath} — see its docstring
|
|
5414
|
+
* for the rationale. Defaults to `"ffmpeg"` (PATH lookup) when unset.
|
|
5415
|
+
*/
|
|
5416
|
+
ffmpegPath?: string;
|
|
5417
|
+
/** See {@link CompositeStreamPipOptions.videoEncoder}. */
|
|
5418
|
+
videoEncoder?: string;
|
|
5419
|
+
/** See {@link CompositeStreamPipOptions.encoderPreset}. */
|
|
5420
|
+
encoderPreset?: string;
|
|
5421
|
+
/** See {@link CompositeStreamPipOptions.crf}. */
|
|
5422
|
+
crf?: number;
|
|
5423
|
+
/** See {@link CompositeStreamPipOptions.gopSeconds}. */
|
|
5424
|
+
gopSeconds?: number;
|
|
5425
|
+
/** See {@link CompositeStreamPipOptions.extraGlobalArgs}. */
|
|
5426
|
+
extraGlobalArgs?: readonly string[];
|
|
5427
|
+
/** See {@link CompositeStreamPipOptions.extraOutputArgs}. */
|
|
5428
|
+
extraOutputArgs?: readonly string[];
|
|
5329
5429
|
/**
|
|
5330
5430
|
* How long to wait for each input stream to produce frames before starting ffmpeg.
|
|
5331
5431
|
* Battery cameras can take several seconds to wake and begin streaming.
|
package/dist/index.d.ts
CHANGED
|
@@ -4145,6 +4145,24 @@ export declare type CompositeStreamOptions = {
|
|
|
4145
4145
|
teleRtspUrl?: string;
|
|
4146
4146
|
/** ffmpeg `-rtsp_transport` value (default: tcp). */
|
|
4147
4147
|
rtspTransport?: 'tcp' | 'udp';
|
|
4148
|
+
/**
|
|
4149
|
+
* Absolute path to the `ffmpeg` binary the compositor should `spawn()`.
|
|
4150
|
+
* Mirrors {@link CompositeStreamPipOptions.ffmpegPath} — see its docstring
|
|
4151
|
+
* for the rationale. Defaults to `"ffmpeg"` (PATH lookup) when unset.
|
|
4152
|
+
*/
|
|
4153
|
+
ffmpegPath?: string;
|
|
4154
|
+
/** See {@link CompositeStreamPipOptions.videoEncoder}. */
|
|
4155
|
+
videoEncoder?: string;
|
|
4156
|
+
/** See {@link CompositeStreamPipOptions.encoderPreset}. */
|
|
4157
|
+
encoderPreset?: string;
|
|
4158
|
+
/** See {@link CompositeStreamPipOptions.crf}. */
|
|
4159
|
+
crf?: number;
|
|
4160
|
+
/** See {@link CompositeStreamPipOptions.gopSeconds}. */
|
|
4161
|
+
gopSeconds?: number;
|
|
4162
|
+
/** See {@link CompositeStreamPipOptions.extraGlobalArgs}. */
|
|
4163
|
+
extraGlobalArgs?: readonly string[];
|
|
4164
|
+
/** See {@link CompositeStreamPipOptions.extraOutputArgs}. */
|
|
4165
|
+
extraOutputArgs?: readonly string[];
|
|
4148
4166
|
/**
|
|
4149
4167
|
* How long to wait for each input stream to produce frames before starting ffmpeg.
|
|
4150
4168
|
* Battery cameras can take several seconds to wake and begin streaming.
|
|
@@ -4192,6 +4210,88 @@ export declare interface CompositeStreamPipOptions {
|
|
|
4192
4210
|
teleRtspUrl?: string;
|
|
4193
4211
|
/** ffmpeg `-rtsp_transport` value (default: tcp). */
|
|
4194
4212
|
rtspTransport?: 'tcp' | 'udp';
|
|
4213
|
+
/**
|
|
4214
|
+
* Absolute path to the `ffmpeg` binary the compositor should `spawn()`.
|
|
4215
|
+
*
|
|
4216
|
+
* When unset, falls back to the bare string `"ffmpeg"`, which relies on
|
|
4217
|
+
* the host's `PATH`. This works on standard Linux / macOS Node setups
|
|
4218
|
+
* but fails silently on environments where the embedding process
|
|
4219
|
+
* strips PATH or ships its own ffmpeg in a non-discoverable location:
|
|
4220
|
+
*
|
|
4221
|
+
* - Scrypted on Windows (the Electron host launches plugins with a
|
|
4222
|
+
* minimal PATH; the bundled ffmpeg lives at a static absolute path
|
|
4223
|
+
* only `sdk.mediaManager.getFFmpegPath()` knows about).
|
|
4224
|
+
* - Scrypted on macOS App Store / sandboxed installs.
|
|
4225
|
+
* - Distroless / minimal Docker base images where ffmpeg is mounted
|
|
4226
|
+
* at a fixed path but not in PATH.
|
|
4227
|
+
*
|
|
4228
|
+
* Consumers in any of those environments should resolve the path
|
|
4229
|
+
* themselves (e.g. via the Scrypted SDK) and pass it through here.
|
|
4230
|
+
*/
|
|
4231
|
+
ffmpegPath?: string;
|
|
4232
|
+
/**
|
|
4233
|
+
* Output video encoder name (passed verbatim as `-c:v`). Default
|
|
4234
|
+
* `libx264` — pure software. On a host with hardware-accelerated
|
|
4235
|
+
* H.264 encoding, switching this is the single biggest perf win
|
|
4236
|
+
* available (5-10x less CPU for the same output bitrate). Supported
|
|
4237
|
+
* by ffmpeg in the wild:
|
|
4238
|
+
*
|
|
4239
|
+
* - Intel/AMD QuickSync: `h264_qsv`
|
|
4240
|
+
* - Intel/AMD VAAPI: `h264_vaapi`
|
|
4241
|
+
* - NVIDIA NVENC: `h264_nvenc`
|
|
4242
|
+
* - Apple VideoToolbox: `h264_videotoolbox`
|
|
4243
|
+
* - Raspberry Pi / ARM: `h264_v4l2m2m`
|
|
4244
|
+
*
|
|
4245
|
+
* Caveat: when not `libx264`, the libx264-specific knobs
|
|
4246
|
+
* (`encoderPreset`, `crf`, `x264-params`) are silently dropped because
|
|
4247
|
+
* each HW encoder has its own option vocabulary. Use
|
|
4248
|
+
* {@link extraOutputArgs} to pass encoder-specific options
|
|
4249
|
+
* (e.g. `["-q:v","23"]` for QSV, `["-preset","fast"]` for NVENC).
|
|
4250
|
+
*/
|
|
4251
|
+
videoEncoder?: string;
|
|
4252
|
+
/**
|
|
4253
|
+
* libx264 preset (default `ultrafast`). Only consulted when
|
|
4254
|
+
* {@link videoEncoder} is left at its default (libx264). Valid:
|
|
4255
|
+
* `ultrafast | superfast | veryfast | faster | fast | medium | slow |
|
|
4256
|
+
* slower | veryslow | placebo`. Slower = better compression / more CPU.
|
|
4257
|
+
*/
|
|
4258
|
+
encoderPreset?: string;
|
|
4259
|
+
/**
|
|
4260
|
+
* CRF (constant rate factor) for libx264. Default 23 (visually
|
|
4261
|
+
* lossless-ish). Range 0 (lossless, huge) — 51 (worst, tiny). Lower
|
|
4262
|
+
* by 2 to roughly halve the bitrate at a given quality. Only consulted
|
|
4263
|
+
* when {@link videoEncoder} is libx264.
|
|
4264
|
+
*/
|
|
4265
|
+
crf?: number;
|
|
4266
|
+
/**
|
|
4267
|
+
* Output keyframe interval in seconds. Default 1 — important for
|
|
4268
|
+
* mid-stream join latency (a new HLS / RTSP client only starts
|
|
4269
|
+
* decoding from the next keyframe). Lower = faster join, larger
|
|
4270
|
+
* stream; higher = better compression, slower join.
|
|
4271
|
+
*/
|
|
4272
|
+
gopSeconds?: number;
|
|
4273
|
+
/**
|
|
4274
|
+
* Free-form ffmpeg arguments inserted at the START of the argv (after
|
|
4275
|
+
* `-hide_banner -loglevel`). Use for hardware-accel decode hints that
|
|
4276
|
+
* must appear before any `-i`:
|
|
4277
|
+
*
|
|
4278
|
+
* extraGlobalArgs: ["-hwaccel","videotoolbox"]
|
|
4279
|
+
* extraGlobalArgs: ["-hwaccel","qsv","-qsv_device","/dev/dri/renderD128"]
|
|
4280
|
+
*
|
|
4281
|
+
* No validation — invalid args here WILL crash ffmpeg.
|
|
4282
|
+
*/
|
|
4283
|
+
extraGlobalArgs?: readonly string[];
|
|
4284
|
+
/**
|
|
4285
|
+
* Free-form ffmpeg arguments inserted just BEFORE the `pipe:1` output.
|
|
4286
|
+
* Use for encoder-specific options when {@link videoEncoder} is not
|
|
4287
|
+
* `libx264`:
|
|
4288
|
+
*
|
|
4289
|
+
* extraOutputArgs: ["-q:v","23"] // qsv/vaapi
|
|
4290
|
+
* extraOutputArgs: ["-preset","fast","-rc","cbr"] // nvenc
|
|
4291
|
+
*
|
|
4292
|
+
* No validation — invalid args here WILL crash ffmpeg.
|
|
4293
|
+
*/
|
|
4294
|
+
extraOutputArgs?: readonly string[];
|
|
4195
4295
|
}
|
|
4196
4296
|
|
|
4197
4297
|
/**
|
package/dist/index.js
CHANGED
|
@@ -2517,10 +2517,18 @@ var CompositeStream = class extends EventEmitter {
|
|
|
2517
2517
|
}
|
|
2518
2518
|
}
|
|
2519
2519
|
async startFfmpegCompositionFromRtspUrls(mainWidth, mainHeight, pipWidth, pipHeight, position, widerRtspUrl, teleRtspUrl, rtspTransport) {
|
|
2520
|
+
const videoEncoder = this.options.videoEncoder ?? "libx264";
|
|
2521
|
+
const isX264 = videoEncoder === "libx264";
|
|
2522
|
+
const encoderPreset = this.options.encoderPreset ?? "ultrafast";
|
|
2523
|
+
const crf = this.options.crf ?? 23;
|
|
2524
|
+
const gopSeconds = this.options.gopSeconds ?? 1;
|
|
2525
|
+
const assumedFps = 30;
|
|
2526
|
+
const gopFrames = Math.max(1, Math.round(gopSeconds * assumedFps));
|
|
2520
2527
|
const ffmpegArgs = [
|
|
2521
2528
|
"-hide_banner",
|
|
2522
2529
|
"-loglevel",
|
|
2523
2530
|
"error",
|
|
2531
|
+
...this.options.extraGlobalArgs ?? [],
|
|
2524
2532
|
"-fflags",
|
|
2525
2533
|
"+genpts",
|
|
2526
2534
|
// Input 0: wider
|
|
@@ -2541,27 +2549,33 @@ var CompositeStream = class extends EventEmitter {
|
|
|
2541
2549
|
// Output: always H.264 Annex-B
|
|
2542
2550
|
"-an",
|
|
2543
2551
|
"-c:v",
|
|
2544
|
-
|
|
2552
|
+
videoEncoder,
|
|
2545
2553
|
"-g",
|
|
2546
|
-
|
|
2554
|
+
String(gopFrames),
|
|
2547
2555
|
"-keyint_min",
|
|
2548
|
-
|
|
2556
|
+
String(gopFrames),
|
|
2549
2557
|
"-sc_threshold",
|
|
2550
2558
|
"0",
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
+
...isX264 ? [
|
|
2560
|
+
"-x264-params",
|
|
2561
|
+
`aud=1:repeat-headers=1:keyint=${gopFrames}:min-keyint=${gopFrames}:scenecut=0`,
|
|
2562
|
+
"-preset",
|
|
2563
|
+
encoderPreset,
|
|
2564
|
+
"-tune",
|
|
2565
|
+
"zerolatency",
|
|
2566
|
+
"-crf",
|
|
2567
|
+
String(crf)
|
|
2568
|
+
] : [],
|
|
2569
|
+
...this.options.extraOutputArgs ?? [],
|
|
2559
2570
|
"-f",
|
|
2560
2571
|
"h264",
|
|
2561
2572
|
"pipe:1"
|
|
2562
2573
|
];
|
|
2563
|
-
this.
|
|
2564
|
-
this.
|
|
2574
|
+
const ffmpegBin = this.options.ffmpegPath ?? "ffmpeg";
|
|
2575
|
+
this.logger.log?.(
|
|
2576
|
+
`[CompositeStream] Starting ffmpeg (rtsp inputs): bin=${ffmpegBin} args=${ffmpegArgs.join(" ")}`
|
|
2577
|
+
);
|
|
2578
|
+
this.ffmpegProcess = spawn3(ffmpegBin, ffmpegArgs, {
|
|
2565
2579
|
stdio: ["ignore", "pipe", "pipe"]
|
|
2566
2580
|
});
|
|
2567
2581
|
this.ffmpegProcess.on("error", (error) => {
|
|
@@ -2628,10 +2642,18 @@ var CompositeStream = class extends EventEmitter {
|
|
|
2628
2642
|
"-i",
|
|
2629
2643
|
"pipe:3"
|
|
2630
2644
|
];
|
|
2645
|
+
const videoEncoder = this.options.videoEncoder ?? "libx264";
|
|
2646
|
+
const isX264 = videoEncoder === "libx264";
|
|
2647
|
+
const encoderPreset = this.options.encoderPreset ?? "ultrafast";
|
|
2648
|
+
const crf = this.options.crf ?? 23;
|
|
2649
|
+
const gopSeconds = this.options.gopSeconds ?? 1;
|
|
2650
|
+
const assumedFps = 30;
|
|
2651
|
+
const gopFrames = Math.max(1, Math.round(gopSeconds * assumedFps));
|
|
2631
2652
|
const ffmpegArgs = [
|
|
2632
2653
|
"-hide_banner",
|
|
2633
2654
|
"-loglevel",
|
|
2634
2655
|
"error",
|
|
2656
|
+
...this.options.extraGlobalArgs ?? [],
|
|
2635
2657
|
"-fflags",
|
|
2636
2658
|
"+genpts",
|
|
2637
2659
|
"-probesize",
|
|
@@ -2650,33 +2672,40 @@ var CompositeStream = class extends EventEmitter {
|
|
|
2650
2672
|
"-map",
|
|
2651
2673
|
"[out]",
|
|
2652
2674
|
"-c:v",
|
|
2653
|
-
|
|
2654
|
-
//
|
|
2655
|
-
//
|
|
2656
|
-
//
|
|
2675
|
+
videoEncoder,
|
|
2676
|
+
// Make the stream easy to join mid-flight: frequent IDRs + in-band
|
|
2677
|
+
// headers + AUD. Without this, a new client may wait many seconds
|
|
2678
|
+
// for the next keyframe.
|
|
2657
2679
|
"-g",
|
|
2658
|
-
|
|
2680
|
+
String(gopFrames),
|
|
2659
2681
|
"-keyint_min",
|
|
2660
|
-
|
|
2682
|
+
String(gopFrames),
|
|
2661
2683
|
"-sc_threshold",
|
|
2662
2684
|
"0",
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2685
|
+
// libx264-specific knobs. We deliberately skip these for HW encoders
|
|
2686
|
+
// — each one has its own option vocabulary (`-q:v`, `-rc`, etc.)
|
|
2687
|
+
// and the user is expected to express them via extraOutputArgs.
|
|
2688
|
+
...isX264 ? [
|
|
2689
|
+
"-x264-params",
|
|
2690
|
+
`aud=1:repeat-headers=1:keyint=${gopFrames}:min-keyint=${gopFrames}:scenecut=0`,
|
|
2691
|
+
"-preset",
|
|
2692
|
+
encoderPreset,
|
|
2693
|
+
"-tune",
|
|
2694
|
+
"zerolatency",
|
|
2695
|
+
"-crf",
|
|
2696
|
+
String(crf)
|
|
2697
|
+
] : [],
|
|
2698
|
+
...this.options.extraOutputArgs ?? [],
|
|
2671
2699
|
"-f",
|
|
2672
2700
|
"h264",
|
|
2673
2701
|
"pipe:1"
|
|
2674
2702
|
// Output (stdout)
|
|
2675
2703
|
];
|
|
2704
|
+
const ffmpegBin = this.options.ffmpegPath ?? "ffmpeg";
|
|
2676
2705
|
this.logger.log?.(
|
|
2677
|
-
`[CompositeStream] Starting ffmpeg:
|
|
2706
|
+
`[CompositeStream] Starting ffmpeg: bin=${ffmpegBin} args=${ffmpegArgs.join(" ")}`
|
|
2678
2707
|
);
|
|
2679
|
-
this.ffmpegProcess = spawn3(
|
|
2708
|
+
this.ffmpegProcess = spawn3(ffmpegBin, ffmpegArgs, {
|
|
2680
2709
|
stdio: ["pipe", "pipe", "pipe", "pipe"]
|
|
2681
2710
|
});
|
|
2682
2711
|
this.ffmpegProcess.on("error", (error) => {
|
|
@@ -3384,6 +3413,20 @@ async function createRfc4571TcpServerInternal(options) {
|
|
|
3384
3413
|
...forceH264 !== void 0 ? { forceH264 } : defaultForceH264 ? { forceH264: true } : {},
|
|
3385
3414
|
...compositeOptions?.assumeH264Inputs !== void 0 ? { assumeH264Inputs: compositeOptions.assumeH264Inputs } : {},
|
|
3386
3415
|
...compositeOptions?.disableTranscode !== void 0 ? { disableTranscode: compositeOptions.disableTranscode } : {},
|
|
3416
|
+
// Propagate ffmpeg binary path — required when the embedder strips
|
|
3417
|
+
// PATH (Scrypted on Windows, Electron sandboxes, distroless Docker)
|
|
3418
|
+
// and the bundled ffmpeg is at a fixed absolute path only the
|
|
3419
|
+
// embedder knows.
|
|
3420
|
+
...compositeOptions?.ffmpegPath ? { ffmpegPath: compositeOptions.ffmpegPath } : {},
|
|
3421
|
+
// Encoder tuning knobs — see CompositeStreamPipOptions for the
|
|
3422
|
+
// semantic contract on each one. Plumbed verbatim so the
|
|
3423
|
+
// CompositeStream layer can apply defaults.
|
|
3424
|
+
...compositeOptions?.videoEncoder ? { videoEncoder: compositeOptions.videoEncoder } : {},
|
|
3425
|
+
...compositeOptions?.encoderPreset ? { encoderPreset: compositeOptions.encoderPreset } : {},
|
|
3426
|
+
...typeof compositeOptions?.crf === "number" ? { crf: compositeOptions.crf } : {},
|
|
3427
|
+
...typeof compositeOptions?.gopSeconds === "number" ? { gopSeconds: compositeOptions.gopSeconds } : {},
|
|
3428
|
+
...compositeOptions?.extraGlobalArgs ? { extraGlobalArgs: compositeOptions.extraGlobalArgs } : {},
|
|
3429
|
+
...compositeOptions?.extraOutputArgs ? { extraOutputArgs: compositeOptions.extraOutputArgs } : {},
|
|
3387
3430
|
logger
|
|
3388
3431
|
});
|
|
3389
3432
|
isCompositeStream = true;
|