@apocaliss92/nodelink-js 0.1.7

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.
@@ -0,0 +1,277 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ BaichuanRtspServer,
4
+ ReolinkBaichuanApi,
5
+ autoDetectDeviceType
6
+ } from "../chunk-JMT75JNG.js";
7
+ import {
8
+ __require
9
+ } from "../chunk-MC2BRLLE.js";
10
+
11
+ // src/cli/rtsp-server.ts
12
+ function parseArgs() {
13
+ const args = process.argv.slice(2);
14
+ const options = {};
15
+ for (let i = 0; i < args.length; i++) {
16
+ let arg = args[i];
17
+ if (!arg) continue;
18
+ let next = args[i + 1];
19
+ if (arg.includes("=")) {
20
+ const [key, value] = arg.split("=", 2);
21
+ arg = key || arg;
22
+ next = value;
23
+ }
24
+ switch (arg) {
25
+ case "--host":
26
+ if (next) {
27
+ options.host = next;
28
+ if (!args[i].includes("=")) i++;
29
+ }
30
+ break;
31
+ case "--username":
32
+ case "--user":
33
+ case "-u":
34
+ if (next) {
35
+ options.username = next;
36
+ if (!args[i].includes("=")) i++;
37
+ }
38
+ break;
39
+ case "--password":
40
+ case "-p":
41
+ if (next) {
42
+ options.password = next;
43
+ if (!args[i].includes("=")) i++;
44
+ }
45
+ break;
46
+ case "--channel":
47
+ case "-c":
48
+ if (next) {
49
+ options.channel = parseInt(next, 10);
50
+ if (!args[i].includes("=")) i++;
51
+ }
52
+ break;
53
+ case "--profile":
54
+ if (next) {
55
+ if (next === "main" || next === "sub" || next === "ext") {
56
+ options.profile = next;
57
+ }
58
+ if (!args[i].includes("=")) i++;
59
+ }
60
+ break;
61
+ case "--variant":
62
+ if (next) {
63
+ const v = next.trim().toLowerCase();
64
+ if (v === "default" || v === "autotrack" || v === "telephoto") {
65
+ options.variant = v;
66
+ }
67
+ if (!args[i].includes("=")) i++;
68
+ }
69
+ break;
70
+ case "--port":
71
+ if (next) {
72
+ options.port = parseInt(next, 10);
73
+ if (!args[i].includes("=")) i++;
74
+ }
75
+ break;
76
+ case "--path":
77
+ if (next) {
78
+ options.path = next;
79
+ if (!args[i].includes("=")) i++;
80
+ }
81
+ break;
82
+ case "--uid":
83
+ if (next) {
84
+ options.uid = next;
85
+ if (!args[i].includes("=")) i++;
86
+ }
87
+ break;
88
+ case "--transport":
89
+ if (next) {
90
+ if (next === "tcp" || next === "udp" || next === "auto") {
91
+ options.transport = next;
92
+ }
93
+ if (!args[i].includes("=")) i++;
94
+ }
95
+ break;
96
+ case "--help":
97
+ case "-h":
98
+ printHelp();
99
+ process.exit(0);
100
+ break;
101
+ }
102
+ }
103
+ return options;
104
+ }
105
+ function printHelp() {
106
+ console.log(`
107
+ RTSP Server CLI for Reolink Baichuan
108
+
109
+ Usage:
110
+ node dist/cli/rtsp-server.cjs [options]
111
+
112
+ Required options:
113
+ --host <ip> Camera IP address
114
+ --username <user> Username (or -u, --user)
115
+ --password <pass> Password (or -p)
116
+
117
+ Optional options:
118
+ --channel <num> Channel number (default: 0)
119
+ --profile <profile> Stream profile: main, sub, ext (default: main)
120
+ --variant <variant> Native variant: default, autotrack, telephoto (default: default)
121
+ --port <port> RTSP server port (default: 8554)
122
+ --path <path> RTSP path (default: /stream/<profile>)
123
+ --uid <uid> UID for battery cameras
124
+ --transport <type> Transport: tcp, udp, auto (default: auto)
125
+ --help, -h Show this message
126
+
127
+ Examples:
128
+ # Basic RTSP server
129
+ node dist/cli/rtsp-server.cjs --host 192.168.1.100 --username admin --password pass
130
+
131
+ # Specific channel with sub profile
132
+ node dist/cli/rtsp-server.cjs --host 192.168.1.100 --username admin --password pass --channel 1 --profile sub
133
+
134
+ # TrackMix (NVR) tele/autotrack variant
135
+ node dist/cli/rtsp-server.cjs --host 192.168.1.161 --username admin --password pass --channel 2 --profile sub --variant autotrack --port 8554 --path /tele_sub
136
+
137
+ # Custom port
138
+ node dist/cli/rtsp-server.cjs --host 192.168.1.100 --username admin --password pass --port 8555
139
+
140
+ # Battery camera (UDP)
141
+ node dist/cli/rtsp-server.cjs --host 192.168.1.100 --username admin --password pass --uid ABC123 --transport udp
142
+
143
+ # Key=value format (supported)
144
+ node dist/cli/rtsp-server.cjs --host=192.168.1.100 --user=admin --password=pass
145
+ `);
146
+ }
147
+ async function main() {
148
+ const options = parseArgs();
149
+ if (!options.host || !options.username || !options.password) {
150
+ console.error("Error: --host, --username and --password are required");
151
+ console.error("Use --help to see usage");
152
+ process.exit(1);
153
+ }
154
+ const channel = options.channel ?? 0;
155
+ const profile = options.profile ?? "main";
156
+ const variant = options.variant ?? "default";
157
+ const port = options.port ?? 8554;
158
+ const path = options.path ?? `/stream/${profile}`;
159
+ const transport = options.transport ?? "auto";
160
+ console.log(`[RTSP Server] Connecting to ${options.host}...`);
161
+ console.log(
162
+ `[RTSP Server] Channel: ${channel}, Profile: ${profile}, Variant: ${variant}`
163
+ );
164
+ try {
165
+ let detectedTransport = "tcp";
166
+ if (transport === "auto") {
167
+ const detection = await autoDetectDeviceType({
168
+ host: options.host,
169
+ username: options.username,
170
+ password: options.password,
171
+ ...options.uid ? { uid: options.uid } : {},
172
+ logger: console
173
+ });
174
+ detectedTransport = detection.transport;
175
+ console.log(
176
+ `[RTSP Server] Device type: ${detection.type}, Transport: ${detectedTransport}`
177
+ );
178
+ } else {
179
+ detectedTransport = transport;
180
+ }
181
+ const api = new ReolinkBaichuanApi({
182
+ host: options.host,
183
+ username: options.username,
184
+ password: options.password,
185
+ transport: detectedTransport,
186
+ ...options.uid ? { uid: options.uid } : {},
187
+ logger: console
188
+ });
189
+ console.log(`[RTSP Server] Logging in...`);
190
+ await api.login();
191
+ console.log(`[RTSP Server] Login successful`);
192
+ const rtspServer = new BaichuanRtspServer({
193
+ api,
194
+ channel,
195
+ profile,
196
+ ...variant !== "default" ? { variant } : {},
197
+ listenPort: port,
198
+ path,
199
+ logger: console
200
+ });
201
+ console.log(`[RTSP Server] Starting RTSP server...`);
202
+ await rtspServer.start();
203
+ const rtspUrl = rtspServer.getRtspUrl();
204
+ console.log(`[RTSP Server] RTSP server started`);
205
+ console.log(`[RTSP Server] URL: ${rtspUrl}`);
206
+ console.log(`[RTSP Server] Waiting for connections...`);
207
+ console.log(`[RTSP Server] Press Ctrl+C to stop`);
208
+ const shutdown = async () => {
209
+ console.log(`
210
+ [RTSP Server] Shutting down server...`);
211
+ try {
212
+ await rtspServer.stop();
213
+ await api.close();
214
+ console.log(`[RTSP Server] Server stopped`);
215
+ process.exit(0);
216
+ } catch (error) {
217
+ console.error(`[RTSP Server] Error during shutdown:`, error);
218
+ process.exit(1);
219
+ }
220
+ };
221
+ process.on("SIGINT", shutdown);
222
+ process.on("SIGTERM", shutdown);
223
+ try {
224
+ await rtspServer.waitUntilReady(3e4);
225
+ console.log(`[RTSP Server] Server ready and camera active`);
226
+ } catch (error) {
227
+ console.warn(`[RTSP Server] Warning: ${error}`);
228
+ console.log(
229
+ `[RTSP Server] Server is still listening, but camera may not be ready yet`
230
+ );
231
+ }
232
+ } catch (error) {
233
+ console.error(`[RTSP Server] Error:`, error);
234
+ process.exit(1);
235
+ }
236
+ }
237
+ var isMainModule = (() => {
238
+ try {
239
+ if (typeof __require !== "undefined" && typeof __require.main !== "undefined") {
240
+ const mainModule = __require.main;
241
+ if (typeof module !== "undefined" && mainModule === module) {
242
+ return true;
243
+ }
244
+ }
245
+ } catch {
246
+ }
247
+ try {
248
+ const getImportMeta = new Function(
249
+ "return typeof import.meta !== 'undefined' ? import.meta : undefined"
250
+ );
251
+ const meta = getImportMeta();
252
+ if (meta?.url) {
253
+ const filePath = process.argv[1];
254
+ if (filePath) {
255
+ try {
256
+ const url = new URL(meta.url);
257
+ const urlPath = decodeURIComponent(url.pathname);
258
+ const normalizedUrlPath = urlPath.replace(/\/$/, "");
259
+ const normalizedFilePath = filePath.replace(/\/$/, "");
260
+ return normalizedUrlPath === normalizedFilePath || normalizedUrlPath.endsWith(normalizedFilePath) || normalizedFilePath.endsWith(normalizedUrlPath);
261
+ } catch {
262
+ const filename = filePath.split("/").pop() || filePath.split("\\").pop();
263
+ return filename ? meta.url.includes(filename) : false;
264
+ }
265
+ }
266
+ }
267
+ } catch {
268
+ }
269
+ return false;
270
+ })();
271
+ if (isMainModule) {
272
+ main().catch((error) => {
273
+ console.error(`[RTSP Server] Fatal error:`, error);
274
+ process.exit(1);
275
+ });
276
+ }
277
+ //# sourceMappingURL=rtsp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/rtsp-server.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI to start an RTSP server from console\n *\n * Usage:\n * node dist/cli/rtsp-server.cjs --host 192.168.1.100 --username admin --password pass --channel 0 --profile main\n *\n * Options:\n * --host <ip> Camera IP address (required)\n * --username <user> Username (required)\n * --password <pass> Password (required)\n * --channel <num> Channel number (default: 0)\n * --profile <profile> Stream profile: main, sub, ext (default: main)\n * --variant <variant> Native variant: default, autotrack, telephoto (default: default)\n * --port <port> RTSP server port (default: 8554)\n * --path <path> RTSP path (default: /stream/<profile>)\n * --uid <uid> UID for battery cameras (optional)\n * --transport <type> Transport: tcp, udp, auto (default: auto)\n */\n\nimport { ReolinkBaichuanApi } from \"../reolink/baichuan/ReolinkBaichuanApi\";\nimport { BaichuanRtspServer } from \"../baichuan/stream/BaichuanRtspServer\";\nimport { autoDetectDeviceType } from \"../reolink/autodetect\";\nimport type { StreamProfile } from \"../reolink/baichuan/types\";\n\ninterface CliOptions {\n host: string;\n username: string;\n password: string;\n channel?: number;\n profile?: StreamProfile;\n variant?: \"default\" | \"autotrack\" | \"telephoto\";\n port?: number;\n path?: string;\n uid?: string;\n transport?: \"tcp\" | \"udp\" | \"auto\";\n}\n\nfunction parseArgs(): CliOptions {\n const args = process.argv.slice(2);\n const options: Partial<CliOptions> = {};\n\n for (let i = 0; i < args.length; i++) {\n let arg = args[i];\n if (!arg) continue;\n let next = args[i + 1];\n\n // Support --key=value format\n if (arg.includes(\"=\")) {\n const [key, value] = arg.split(\"=\", 2);\n arg = key || arg;\n next = value;\n }\n\n switch (arg) {\n case \"--host\":\n if (next) {\n options.host = next;\n if (!args[i]!.includes(\"=\")) i++;\n }\n break;\n case \"--username\":\n case \"--user\":\n case \"-u\":\n if (next) {\n options.username = next;\n if (!args[i]!.includes(\"=\")) i++;\n }\n break;\n case \"--password\":\n case \"-p\":\n if (next) {\n options.password = next;\n if (!args[i]!.includes(\"=\")) i++;\n }\n break;\n case \"--channel\":\n case \"-c\":\n if (next) {\n options.channel = parseInt(next, 10);\n if (!args[i]!.includes(\"=\")) i++;\n }\n break;\n case \"--profile\":\n if (next) {\n if (next === \"main\" || next === \"sub\" || next === \"ext\") {\n options.profile = next;\n }\n if (!args[i]!.includes(\"=\")) i++;\n }\n break;\n case \"--variant\":\n if (next) {\n const v = next.trim().toLowerCase();\n if (v === \"default\" || v === \"autotrack\" || v === \"telephoto\") {\n options.variant = v as any;\n }\n if (!args[i]!.includes(\"=\")) i++;\n }\n break;\n case \"--port\":\n if (next) {\n options.port = parseInt(next, 10);\n if (!args[i]!.includes(\"=\")) i++;\n }\n break;\n case \"--path\":\n if (next) {\n options.path = next;\n if (!args[i]!.includes(\"=\")) i++;\n }\n break;\n case \"--uid\":\n if (next) {\n options.uid = next;\n if (!args[i]!.includes(\"=\")) i++;\n }\n break;\n case \"--transport\":\n if (next) {\n if (next === \"tcp\" || next === \"udp\" || next === \"auto\") {\n options.transport = next;\n }\n if (!args[i]!.includes(\"=\")) i++;\n }\n break;\n case \"--help\":\n case \"-h\":\n printHelp();\n process.exit(0);\n break;\n }\n }\n\n return options as CliOptions;\n}\n\nfunction printHelp(): void {\n console.log(`\nRTSP Server CLI for Reolink Baichuan\n\nUsage:\n node dist/cli/rtsp-server.cjs [options]\n\nRequired options:\n --host <ip> Camera IP address\n --username <user> Username (or -u, --user)\n --password <pass> Password (or -p)\n\nOptional options:\n --channel <num> Channel number (default: 0)\n --profile <profile> Stream profile: main, sub, ext (default: main)\n --variant <variant> Native variant: default, autotrack, telephoto (default: default)\n --port <port> RTSP server port (default: 8554)\n --path <path> RTSP path (default: /stream/<profile>)\n --uid <uid> UID for battery cameras\n --transport <type> Transport: tcp, udp, auto (default: auto)\n --help, -h Show this message\n\nExamples:\n # Basic RTSP server\n node dist/cli/rtsp-server.cjs --host 192.168.1.100 --username admin --password pass\n\n # Specific channel with sub profile\n node dist/cli/rtsp-server.cjs --host 192.168.1.100 --username admin --password pass --channel 1 --profile sub\n\n # TrackMix (NVR) tele/autotrack variant\n node dist/cli/rtsp-server.cjs --host 192.168.1.161 --username admin --password pass --channel 2 --profile sub --variant autotrack --port 8554 --path /tele_sub\n\n # Custom port\n node dist/cli/rtsp-server.cjs --host 192.168.1.100 --username admin --password pass --port 8555\n\n # Battery camera (UDP)\n node dist/cli/rtsp-server.cjs --host 192.168.1.100 --username admin --password pass --uid ABC123 --transport udp\n\n # Key=value format (supported)\n node dist/cli/rtsp-server.cjs --host=192.168.1.100 --user=admin --password=pass\n`);\n}\n\nasync function main(): Promise<void> {\n const options = parseArgs();\n\n // Validate required options\n if (!options.host || !options.username || !options.password) {\n console.error(\"Error: --host, --username and --password are required\");\n console.error(\"Use --help to see usage\");\n process.exit(1);\n }\n\n const channel = options.channel ?? 0;\n const profile = options.profile ?? \"main\";\n const variant = options.variant ?? \"default\";\n const port = options.port ?? 8554;\n const path = options.path ?? `/stream/${profile}`;\n const transport = options.transport ?? \"auto\";\n\n console.log(`[RTSP Server] Connecting to ${options.host}...`);\n console.log(\n `[RTSP Server] Channel: ${channel}, Profile: ${profile}, Variant: ${variant}`,\n );\n\n try {\n // Auto-detect device type if needed\n let detectedTransport: \"tcp\" | \"udp\" = \"tcp\";\n if (transport === \"auto\") {\n const detection = await autoDetectDeviceType({\n host: options.host,\n username: options.username,\n password: options.password,\n ...(options.uid ? { uid: options.uid } : {}),\n logger: console,\n });\n detectedTransport = detection.transport;\n console.log(\n `[RTSP Server] Device type: ${detection.type}, Transport: ${detectedTransport}`,\n );\n } else {\n detectedTransport = transport;\n }\n\n // Create API instance\n const api = new ReolinkBaichuanApi({\n host: options.host,\n username: options.username,\n password: options.password,\n transport: detectedTransport,\n ...(options.uid ? { uid: options.uid } : {}),\n logger: console,\n });\n\n // Login\n console.log(`[RTSP Server] Logging in...`);\n await api.login();\n console.log(`[RTSP Server] Login successful`);\n\n // Create and start RTSP server\n const rtspServer = new BaichuanRtspServer({\n api,\n channel,\n profile,\n ...(variant !== \"default\" ? { variant } : {}),\n listenPort: port,\n path,\n logger: console,\n });\n\n console.log(`[RTSP Server] Starting RTSP server...`);\n await rtspServer.start();\n\n const rtspUrl = rtspServer.getRtspUrl();\n console.log(`[RTSP Server] RTSP server started`);\n console.log(`[RTSP Server] URL: ${rtspUrl}`);\n console.log(`[RTSP Server] Waiting for connections...`);\n console.log(`[RTSP Server] Press Ctrl+C to stop`);\n\n // Handle graceful shutdown\n const shutdown = async () => {\n console.log(`\\n[RTSP Server] Shutting down server...`);\n try {\n await rtspServer.stop();\n await api.close();\n console.log(`[RTSP Server] Server stopped`);\n process.exit(0);\n } catch (error) {\n console.error(`[RTSP Server] Error during shutdown:`, error);\n process.exit(1);\n }\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n // Wait for server to be ready\n try {\n await rtspServer.waitUntilReady(30000);\n console.log(`[RTSP Server] Server ready and camera active`);\n } catch (error) {\n console.warn(`[RTSP Server] Warning: ${error}`);\n console.log(\n `[RTSP Server] Server is still listening, but camera may not be ready yet`,\n );\n }\n } catch (error) {\n console.error(`[RTSP Server] Error:`, error);\n process.exit(1);\n }\n}\n\n// Execute only if called directly\n// Supports both ESM and CommonJS\nconst isMainModule = (() => {\n // CommonJS check\n try {\n if (\n typeof require !== \"undefined\" &&\n typeof (require as any).main !== \"undefined\"\n ) {\n const mainModule = (require as any).main;\n // @ts-ignore - module may not exist in ESM\n if (typeof module !== \"undefined\" && mainModule === module) {\n return true;\n }\n }\n } catch {\n // module not defined in ESM, continue to ESM check\n }\n // ESM check - use Function constructor to avoid CJS bundler warnings about import.meta\n try {\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n const getImportMeta = new Function(\n \"return typeof import.meta !== 'undefined' ? import.meta : undefined\",\n );\n const meta = getImportMeta() as { url?: string } | undefined;\n if (meta?.url) {\n const filePath = process.argv[1];\n if (filePath) {\n try {\n const url = new URL(meta.url);\n const urlPath = decodeURIComponent(url.pathname);\n // Normalize paths for comparison\n const normalizedUrlPath = urlPath.replace(/\\/$/, \"\");\n const normalizedFilePath = filePath.replace(/\\/$/, \"\");\n return (\n normalizedUrlPath === normalizedFilePath ||\n normalizedUrlPath.endsWith(normalizedFilePath) ||\n normalizedFilePath.endsWith(normalizedUrlPath)\n );\n } catch {\n // Fallback: check if import.meta.url contains the filename\n const filename =\n filePath.split(\"/\").pop() || filePath.split(\"\\\\\").pop();\n return filename ? meta.url.includes(filename) : false;\n }\n }\n }\n } catch {\n // import.meta not available (CJS environment)\n }\n return false;\n})();\n\nif (isMainModule) {\n main().catch((error) => {\n console.error(`[RTSP Server] Fatal error:`, error);\n process.exit(1);\n });\n}\n"],"mappings":"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","names":[]}