@apocaliss92/scrypted-reolink-native 0.5.42 → 0.5.43
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/main.nodejs.js +1 -1
- package/dist/plugin.zip +0 -0
- package/package.json +2 -2
- package/src/camera.ts +163 -5
package/dist/plugin.zip
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apocaliss92/scrypted-reolink-native",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.43",
|
|
4
4
|
"description": "Use any reolink camera with Scrypted, even older/unsupported models without HTTP protocol support",
|
|
5
5
|
"author": "@apocaliss92",
|
|
6
6
|
"license": "Apache",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
]
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@apocaliss92/nodelink-js": "^0.
|
|
47
|
+
"@apocaliss92/nodelink-js": "^0.6.0",
|
|
48
48
|
"@scrypted/common": "file:../../scrypted/common",
|
|
49
49
|
"@scrypted/rtsp": "file:../../scrypted/plugins/rtsp",
|
|
50
50
|
"@scrypted/sdk": "^0.3.118"
|
package/src/camera.ts
CHANGED
|
@@ -683,6 +683,107 @@ export class ReolinkCamera
|
|
|
683
683
|
this.scheduleStreamManagerRestart("compositeDisableTranscode changed");
|
|
684
684
|
},
|
|
685
685
|
},
|
|
686
|
+
// ─── Composite ffmpeg tuning ─────────────────────────────────
|
|
687
|
+
// Encoder + quality knobs. Defaults preserve the previous behavior
|
|
688
|
+
// (libx264 / ultrafast / crf 23 / 1s GOP). Switching the encoder
|
|
689
|
+
// away from libx264 is the single biggest perf win — try the HW
|
|
690
|
+
// encoder for your host: h264_videotoolbox (macOS), h264_qsv or
|
|
691
|
+
// h264_vaapi (Intel/AMD), h264_nvenc (NVIDIA), h264_v4l2m2m
|
|
692
|
+
// (Raspberry Pi). When you change the encoder the libx264-specific
|
|
693
|
+
// preset/CRF knobs are silently dropped — use "Composite: extra
|
|
694
|
+
// output args" to pass the encoder's own options.
|
|
695
|
+
compositeVideoEncoder: {
|
|
696
|
+
title: "Composite: ffmpeg encoder",
|
|
697
|
+
description:
|
|
698
|
+
"Output video encoder. Default libx264 (software). Change to the right hardware encoder for a 5-10× CPU win.",
|
|
699
|
+
type: "string",
|
|
700
|
+
defaultValue: "libx264",
|
|
701
|
+
group: "Composite stream",
|
|
702
|
+
hide: true,
|
|
703
|
+
choices: [
|
|
704
|
+
"libx264",
|
|
705
|
+
"h264_videotoolbox",
|
|
706
|
+
"h264_qsv",
|
|
707
|
+
"h264_vaapi",
|
|
708
|
+
"h264_nvenc",
|
|
709
|
+
"h264_v4l2m2m",
|
|
710
|
+
],
|
|
711
|
+
onPut: async () => {
|
|
712
|
+
this.scheduleStreamManagerRestart("compositeVideoEncoder changed");
|
|
713
|
+
},
|
|
714
|
+
},
|
|
715
|
+
compositeEncoderPreset: {
|
|
716
|
+
title: "Composite: libx264 preset",
|
|
717
|
+
description:
|
|
718
|
+
"Only used when encoder is libx264. ultrafast = least CPU / worst compression; placebo = the opposite. Default ultrafast.",
|
|
719
|
+
type: "string",
|
|
720
|
+
defaultValue: "ultrafast",
|
|
721
|
+
group: "Composite stream",
|
|
722
|
+
hide: true,
|
|
723
|
+
choices: [
|
|
724
|
+
"ultrafast",
|
|
725
|
+
"superfast",
|
|
726
|
+
"veryfast",
|
|
727
|
+
"faster",
|
|
728
|
+
"fast",
|
|
729
|
+
"medium",
|
|
730
|
+
"slow",
|
|
731
|
+
"slower",
|
|
732
|
+
"veryslow",
|
|
733
|
+
"placebo",
|
|
734
|
+
],
|
|
735
|
+
onPut: async () => {
|
|
736
|
+
this.scheduleStreamManagerRestart("compositeEncoderPreset changed");
|
|
737
|
+
},
|
|
738
|
+
},
|
|
739
|
+
compositeCrf: {
|
|
740
|
+
title: "Composite: libx264 CRF (quality)",
|
|
741
|
+
description:
|
|
742
|
+
"Only used when encoder is libx264. 0 = lossless (huge), 23 = visually lossless, 51 = worst. Drop by 2 to roughly halve bitrate at the same quality.",
|
|
743
|
+
type: "number",
|
|
744
|
+
defaultValue: 23,
|
|
745
|
+
group: "Composite stream",
|
|
746
|
+
hide: true,
|
|
747
|
+
onPut: async () => {
|
|
748
|
+
this.scheduleStreamManagerRestart("compositeCrf changed");
|
|
749
|
+
},
|
|
750
|
+
},
|
|
751
|
+
compositeGopSeconds: {
|
|
752
|
+
title: "Composite: keyframe interval (seconds)",
|
|
753
|
+
description:
|
|
754
|
+
"Lower = faster mid-stream join + larger stream; higher = better compression + slower join. Default 1s.",
|
|
755
|
+
type: "number",
|
|
756
|
+
defaultValue: 1,
|
|
757
|
+
group: "Composite stream",
|
|
758
|
+
hide: true,
|
|
759
|
+
onPut: async () => {
|
|
760
|
+
this.scheduleStreamManagerRestart("compositeGopSeconds changed");
|
|
761
|
+
},
|
|
762
|
+
},
|
|
763
|
+
compositeExtraGlobalArgs: {
|
|
764
|
+
title: "Composite: extra global args",
|
|
765
|
+
description:
|
|
766
|
+
"Free-form ffmpeg args inserted BEFORE the inputs. Use for hardware decode hints, e.g. \"-hwaccel videotoolbox\" or \"-hwaccel qsv -qsv_device /dev/dri/renderD128\". Whitespace-separated. Invalid args WILL crash ffmpeg.",
|
|
767
|
+
type: "string",
|
|
768
|
+
defaultValue: "",
|
|
769
|
+
group: "Composite stream",
|
|
770
|
+
hide: true,
|
|
771
|
+
onPut: async () => {
|
|
772
|
+
this.scheduleStreamManagerRestart("compositeExtraGlobalArgs changed");
|
|
773
|
+
},
|
|
774
|
+
},
|
|
775
|
+
compositeExtraOutputArgs: {
|
|
776
|
+
title: "Composite: extra output args",
|
|
777
|
+
description:
|
|
778
|
+
"Free-form ffmpeg args inserted JUST BEFORE the output. Use for encoder-specific options when encoder ≠ libx264, e.g. \"-q:v 23\" (qsv) or \"-preset fast -rc cbr\" (nvenc). Whitespace-separated. Invalid args WILL crash ffmpeg.",
|
|
779
|
+
type: "string",
|
|
780
|
+
defaultValue: "",
|
|
781
|
+
group: "Composite stream",
|
|
782
|
+
hide: true,
|
|
783
|
+
onPut: async () => {
|
|
784
|
+
this.scheduleStreamManagerRestart("compositeExtraOutputArgs changed");
|
|
785
|
+
},
|
|
786
|
+
},
|
|
686
787
|
// ─── E-mail Push ─────────────────────────────────────────────
|
|
687
788
|
// Per-camera knobs that pair with the singleton
|
|
688
789
|
// `Reolink E-mail Push Server` device. Hidden by default and
|
|
@@ -1889,10 +1990,10 @@ export class ReolinkCamera
|
|
|
1889
1990
|
/**
|
|
1890
1991
|
* Initialize or recreate the StreamManager, taking into account multifocal composite options.
|
|
1891
1992
|
*/
|
|
1892
|
-
protected initStreamManager(
|
|
1993
|
+
protected async initStreamManager(
|
|
1893
1994
|
logger?: Console,
|
|
1894
1995
|
forceRecreate: boolean = false,
|
|
1895
|
-
): void {
|
|
1996
|
+
): Promise<void> {
|
|
1896
1997
|
const { username, password } = this.storageSettings.values;
|
|
1897
1998
|
// Ensure logger is always valid - use provided logger or get from device, fallback to console
|
|
1898
1999
|
const validLogger = logger || this.getBaichuanLogger() || console;
|
|
@@ -1917,7 +2018,38 @@ export class ReolinkCamera
|
|
|
1917
2018
|
rtspChannel,
|
|
1918
2019
|
compositeAssumeH264,
|
|
1919
2020
|
compositeDisableTranscode,
|
|
2021
|
+
compositeVideoEncoder,
|
|
2022
|
+
compositeEncoderPreset,
|
|
2023
|
+
compositeCrf,
|
|
2024
|
+
compositeGopSeconds,
|
|
2025
|
+
compositeExtraGlobalArgs,
|
|
2026
|
+
compositeExtraOutputArgs,
|
|
1920
2027
|
} = this.storageSettings.values;
|
|
2028
|
+
// Get the path to the ffmpeg binary Scrypted ships with. The
|
|
2029
|
+
// composite stream spawns ffmpeg directly; on Windows / Electron
|
|
2030
|
+
// the host has a stripped PATH so a bare `ffmpeg` ENOENTs — we
|
|
2031
|
+
// MUST pass the absolute path the SDK knows about.
|
|
2032
|
+
let ffmpegPath: string | undefined;
|
|
2033
|
+
try {
|
|
2034
|
+
ffmpegPath = await sdk.mediaManager.getFFmpegPath();
|
|
2035
|
+
} catch {
|
|
2036
|
+
// Older Scrypted runtimes / weird environments may not expose
|
|
2037
|
+
// this. Fall through to the library's default ("ffmpeg" via PATH);
|
|
2038
|
+
// worst case the composite fails to spawn and the user sees a
|
|
2039
|
+
// friendly error.
|
|
2040
|
+
ffmpegPath = undefined;
|
|
2041
|
+
}
|
|
2042
|
+
// Whitespace-split the free-form extra args. Empty string -> [].
|
|
2043
|
+
const splitArgs = (s: string | undefined): string[] | undefined => {
|
|
2044
|
+
if (typeof s !== "string") return undefined;
|
|
2045
|
+
const arr = s
|
|
2046
|
+
.trim()
|
|
2047
|
+
.split(/\s+/)
|
|
2048
|
+
.filter((a) => a.length > 0);
|
|
2049
|
+
return arr.length > 0 ? arr : undefined;
|
|
2050
|
+
};
|
|
2051
|
+
const extraGlobalArgs = splitArgs(compositeExtraGlobalArgs);
|
|
2052
|
+
const extraOutputArgs = splitArgs(compositeExtraOutputArgs);
|
|
1921
2053
|
|
|
1922
2054
|
// On NVR/Hub, TrackMix lenses are selected via stream variant, not via a separate channel.
|
|
1923
2055
|
// Use rtspChannel for BOTH wide and tele so the library can request tele via streamType/variant.
|
|
@@ -1967,6 +2099,20 @@ export class ReolinkCamera
|
|
|
1967
2099
|
forceH264: true,
|
|
1968
2100
|
assumeH264Inputs: compositeAssumeH264 ?? true,
|
|
1969
2101
|
disableTranscode: compositeDisableTranscode ?? false,
|
|
2102
|
+
// ffmpeg knobs — only include when set so the library defaults stay live.
|
|
2103
|
+
...(ffmpegPath ? { ffmpegPath } : {}),
|
|
2104
|
+
...(compositeVideoEncoder
|
|
2105
|
+
? { videoEncoder: compositeVideoEncoder }
|
|
2106
|
+
: {}),
|
|
2107
|
+
...(compositeEncoderPreset
|
|
2108
|
+
? { encoderPreset: compositeEncoderPreset }
|
|
2109
|
+
: {}),
|
|
2110
|
+
...(typeof compositeCrf === "number" ? { crf: compositeCrf } : {}),
|
|
2111
|
+
...(typeof compositeGopSeconds === "number"
|
|
2112
|
+
? { gopSeconds: compositeGopSeconds }
|
|
2113
|
+
: {}),
|
|
2114
|
+
...(extraGlobalArgs ? { extraGlobalArgs } : {}),
|
|
2115
|
+
...(extraOutputArgs ? { extraOutputArgs } : {}),
|
|
1970
2116
|
};
|
|
1971
2117
|
}
|
|
1972
2118
|
|
|
@@ -1995,7 +2141,7 @@ export class ReolinkCamera
|
|
|
1995
2141
|
logger.log(
|
|
1996
2142
|
"Restarting StreamManager due to PIP/composite settings change",
|
|
1997
2143
|
);
|
|
1998
|
-
this.initStreamManager(logger, true);
|
|
2144
|
+
await this.initStreamManager(logger, true);
|
|
1999
2145
|
|
|
2000
2146
|
// Invalidate snapshot cache for battery/multifocal-battery so that
|
|
2001
2147
|
// the next snapshot reflects the new PIP/composite configuration.
|
|
@@ -3560,7 +3706,7 @@ export class ReolinkCamera
|
|
|
3560
3706
|
const logger = this.getBaichuanLogger();
|
|
3561
3707
|
logger.warn("StreamManager not initialized, initializing now...");
|
|
3562
3708
|
try {
|
|
3563
|
-
this.initStreamManager(logger);
|
|
3709
|
+
await this.initStreamManager(logger);
|
|
3564
3710
|
} catch (e) {
|
|
3565
3711
|
logger.error(
|
|
3566
3712
|
"Failed to initialize StreamManager in getVideoStream",
|
|
@@ -3788,6 +3934,18 @@ export class ReolinkCamera
|
|
|
3788
3934
|
this.storageSettings.settings.pipPosition.hide = !this.isMultiFocal;
|
|
3789
3935
|
this.storageSettings.settings.pipSize.hide = !this.isMultiFocal;
|
|
3790
3936
|
this.storageSettings.settings.pipMargin.hide = !this.isMultiFocal;
|
|
3937
|
+
this.storageSettings.settings.compositeAssumeH264.hide = !this.isMultiFocal;
|
|
3938
|
+
this.storageSettings.settings.compositeDisableTranscode.hide =
|
|
3939
|
+
!this.isMultiFocal;
|
|
3940
|
+
this.storageSettings.settings.compositeVideoEncoder.hide = !this.isMultiFocal;
|
|
3941
|
+
this.storageSettings.settings.compositeEncoderPreset.hide =
|
|
3942
|
+
!this.isMultiFocal;
|
|
3943
|
+
this.storageSettings.settings.compositeCrf.hide = !this.isMultiFocal;
|
|
3944
|
+
this.storageSettings.settings.compositeGopSeconds.hide = !this.isMultiFocal;
|
|
3945
|
+
this.storageSettings.settings.compositeExtraGlobalArgs.hide =
|
|
3946
|
+
!this.isMultiFocal;
|
|
3947
|
+
this.storageSettings.settings.compositeExtraOutputArgs.hide =
|
|
3948
|
+
!this.isMultiFocal;
|
|
3791
3949
|
|
|
3792
3950
|
const hideUid = !this.isBattery || this.isOnNvr || !!this.multiFocalDevice;
|
|
3793
3951
|
this.storageSettings.settings.uid.hide = hideUid;
|
|
@@ -3844,7 +4002,7 @@ export class ReolinkCamera
|
|
|
3844
4002
|
}
|
|
3845
4003
|
|
|
3846
4004
|
try {
|
|
3847
|
-
this.initStreamManager();
|
|
4005
|
+
await this.initStreamManager();
|
|
3848
4006
|
} catch (e) {
|
|
3849
4007
|
logger.error(
|
|
3850
4008
|
"Failed to initialize StreamManager in init",
|