@apocaliss92/scrypted-reolink-native 0.5.43 → 0.5.45

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/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.43",
3
+ "version": "0.5.45",
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.6.0",
47
+ "@apocaliss92/nodelink-js": "^0.6.1",
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
@@ -43,7 +43,43 @@ import sdk, {
43
43
  import { StorageSettings } from "@scrypted/sdk/storage-settings";
44
44
  import crypto from "crypto";
45
45
  import fs from "fs";
46
+ import os from "os";
46
47
  import path from "path";
48
+
49
+ /**
50
+ * Per-platform list of ffmpeg H.264 encoders we offer in the composite
51
+ * settings dropdown. Mirrors `@scrypted/common/src/ffmpeg-hardware-
52
+ * acceleration.ts`'s `getH264EncoderArgs()` but replicated here so we
53
+ * don't take a build dependency on Scrypted's internal common package
54
+ * (the subpath import doesn't resolve cleanly through the file-symlink
55
+ * Scrypted plugins use). The shape mirrors the upstream helper exactly
56
+ * so we can swap to the real one as soon as the resolution issue is
57
+ * addressed upstream.
58
+ *
59
+ * Each value is the full `-c:v <encoder> [extra-args...]` arg list. The
60
+ * code below pulls element [1] for the `-c:v` identifier and propagates
61
+ * the rest through `extraOutputArgs`.
62
+ */
63
+ function getCompositeH264EncoderArgs(): { [label: string]: string[] } {
64
+ const args: { [label: string]: string[] } = {};
65
+ const platform = os.platform();
66
+ if (platform === "darwin") {
67
+ args["VideoToolbox"] = ["-c:v", "h264_videotoolbox"];
68
+ } else if (platform === "win32") {
69
+ args["Intel QuickSync"] = ["-c:v", "h264_qsv"];
70
+ args["AMD"] = ["-c:v", "h264_amf"];
71
+ args["Nvidia"] = ["-c:v", "h264_nvenc"];
72
+ } else if (platform === "linux") {
73
+ args["V4L2 (Raspberry Pi)"] = [
74
+ "-pix_fmt", "yuv420p",
75
+ "-c:v", "h264_v4l2m2m",
76
+ ];
77
+ args["VAAPI"] = ["-c:v", "h264_vaapi"];
78
+ args["Nvidia"] = ["-c:v", "h264_nvenc"];
79
+ }
80
+ args["libx264 (Software)"] = ["-c:v", "libx264"];
81
+ return args;
82
+ }
47
83
  import type { UrlMediaStreamOptions } from "../../scrypted/plugins/rtsp/src/rtsp";
48
84
  import {
49
85
  ReolinkCameraAutotracking,
@@ -692,22 +728,24 @@ export class ReolinkCamera
692
728
  // (Raspberry Pi). When you change the encoder the libx264-specific
693
729
  // preset/CRF knobs are silently dropped — use "Composite: extra
694
730
  // output args" to pass the encoder's own options.
731
+ // Encoder choices come straight from Scrypted's per-platform
732
+ // hardware-acceleration helper, so the dropdown only ever offers
733
+ // encoders that ffmpeg on this host actually supports — Mac sees
734
+ // VideoToolbox, Windows sees QuickSync/AMD/Nvidia, Linux sees
735
+ // V4L2/VAAPI/Nvidia, Raspberry Pi sees its dedicated V4L2 path.
736
+ // The displayed label is human-readable ("VideoToolbox",
737
+ // "Intel QuickSync", "libx264 (Software)") and the actual ffmpeg
738
+ // `-c:v` identifier is resolved at use time via
739
+ // `resolveCompositeVideoEncoder()` below.
695
740
  compositeVideoEncoder: {
696
741
  title: "Composite: ffmpeg encoder",
697
742
  description:
698
- "Output video encoder. Default libx264 (software). Change to the right hardware encoder for a 5-10× CPU win.",
743
+ "Output video encoder. Choices are limited to what ffmpeg supports on this host. Hardware encoders typically reduce CPU 5-10× vs libx264.",
699
744
  type: "string",
700
- defaultValue: "libx264",
745
+ defaultValue: "libx264 (Software)",
701
746
  group: "Composite stream",
702
747
  hide: true,
703
- choices: [
704
- "libx264",
705
- "h264_videotoolbox",
706
- "h264_qsv",
707
- "h264_vaapi",
708
- "h264_nvenc",
709
- "h264_v4l2m2m",
710
- ],
748
+ choices: Object.keys(getCompositeH264EncoderArgs()),
711
749
  onPut: async () => {
712
750
  this.scheduleStreamManagerRestart("compositeVideoEncoder changed");
713
751
  },
@@ -2051,6 +2089,41 @@ export class ReolinkCamera
2051
2089
  const extraGlobalArgs = splitArgs(compositeExtraGlobalArgs);
2052
2090
  const extraOutputArgs = splitArgs(compositeExtraOutputArgs);
2053
2091
 
2092
+ // Resolve the human-readable encoder label the user picked back
2093
+ // into the actual ffmpeg `-c:v` identifier. The helper returns
2094
+ // arrays shaped like ['-c:v', 'h264_videotoolbox', ...extras] —
2095
+ // we pull element [1] for the encoder name and propagate any
2096
+ // additional pix-fmt / pix-encoder args via extraOutputArgs so
2097
+ // they end up just before the output pipe.
2098
+ let resolvedVideoEncoder: string | undefined;
2099
+ let encoderImpliedOutputArgs: string[] = [];
2100
+ if (compositeVideoEncoder) {
2101
+ try {
2102
+ const encoderArgs = getCompositeH264EncoderArgs()[compositeVideoEncoder];
2103
+ // Some entries (V4L2/Raspberry Pi) carry pre-`-c:v` pixel-format
2104
+ // args. Find where `-c:v` is in the array — everything before
2105
+ // becomes encoderImpliedOutputArgs (pixfmt), the element after
2106
+ // `-c:v` is the encoder identifier, and anything after that is
2107
+ // also part of encoderImpliedOutputArgs.
2108
+ const cvIdx = encoderArgs?.indexOf("-c:v") ?? -1;
2109
+ if (encoderArgs && cvIdx >= 0 && encoderArgs[cvIdx + 1]) {
2110
+ resolvedVideoEncoder = encoderArgs[cvIdx + 1]!;
2111
+ // Everything except the `-c:v <encoder>` pair becomes extra
2112
+ // output args, preserving any pixel-format hints the upstream
2113
+ // helper baked in (e.g. yuv420p for V4L2).
2114
+ encoderImpliedOutputArgs = [
2115
+ ...encoderArgs.slice(0, cvIdx),
2116
+ ...encoderArgs.slice(cvIdx + 2),
2117
+ ];
2118
+ }
2119
+ } catch {
2120
+ // ignore; fall back to library default below
2121
+ }
2122
+ }
2123
+ const finalExtraOutputArgs = encoderImpliedOutputArgs.length || extraOutputArgs
2124
+ ? [...encoderImpliedOutputArgs, ...(extraOutputArgs ?? [])]
2125
+ : undefined;
2126
+
2054
2127
  // On NVR/Hub, TrackMix lenses are selected via stream variant, not via a separate channel.
2055
2128
  // Use rtspChannel for BOTH wide and tele so the library can request tele via streamType/variant.
2056
2129
  const wider = this.isOnNvr ? rtspChannel : undefined;
@@ -2101,8 +2174,8 @@ export class ReolinkCamera
2101
2174
  disableTranscode: compositeDisableTranscode ?? false,
2102
2175
  // ffmpeg knobs — only include when set so the library defaults stay live.
2103
2176
  ...(ffmpegPath ? { ffmpegPath } : {}),
2104
- ...(compositeVideoEncoder
2105
- ? { videoEncoder: compositeVideoEncoder }
2177
+ ...(resolvedVideoEncoder
2178
+ ? { videoEncoder: resolvedVideoEncoder }
2106
2179
  : {}),
2107
2180
  ...(compositeEncoderPreset
2108
2181
  ? { encoderPreset: compositeEncoderPreset }
@@ -2112,7 +2185,7 @@ export class ReolinkCamera
2112
2185
  ? { gopSeconds: compositeGopSeconds }
2113
2186
  : {}),
2114
2187
  ...(extraGlobalArgs ? { extraGlobalArgs } : {}),
2115
- ...(extraOutputArgs ? { extraOutputArgs } : {}),
2188
+ ...(finalExtraOutputArgs ? { extraOutputArgs: finalExtraOutputArgs } : {}),
2116
2189
  };
2117
2190
  }
2118
2191