@apocaliss92/nodelink-js 0.3.4 → 0.3.5
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/README.md +48 -82
- package/dist/{chunk-YSEFEQYV.js → chunk-UDS2UR4S.js} +33 -2
- package/dist/chunk-UDS2UR4S.js.map +1 -0
- package/dist/cli/rtsp-server.cjs +32 -1
- package/dist/cli/rtsp-server.cjs.map +1 -1
- package/dist/cli/rtsp-server.js +1 -1
- package/dist/index.cjs +569 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +137 -1
- package/dist/index.d.ts +115 -0
- package/dist/index.js +535 -15
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
- package/dist/chunk-YSEFEQYV.js.map +0 -1
package/README.md
CHANGED
|
@@ -42,10 +42,10 @@ The library includes a **complete web-based management interface** for easy came
|
|
|
42
42
|
- 📡 **NVR / Hub Support** - Add NVRs as first-class entities, discover channels, and manage child cameras. All cameras on an NVR share a single connection (like Scrypted). Connect/disconnect at the NVR level; add or remove cameras at any time via channel discovery
|
|
43
43
|
- 🔋 **Battery Camera Support** - Cameras are auto-detected as battery-powered when they emit sleep/wake events. Per-camera battery mode setting: **Stream Only** (default — camera sleeps when no stream clients) or **Always On** (stays awake while connected). Live awake/sleeping badge on each camera card. Controls and stream discovery are paused while the camera sleeps to avoid unnecessary wake-ups
|
|
44
44
|
- 💡 **Camera Controls** - Toggle floodlight, siren, floodlight-on-motion, siren-on-motion, PTZ auto-tracking, and PIR sensor directly from the camera card. PTZ directional controls and preset navigation via a dedicated modal
|
|
45
|
-
- 📹 **Live Streaming** -
|
|
45
|
+
- 📹 **Live Streaming via go2rtc** - WebRTC, MSE/MP4, HLS, RTSP, and snapshot output powered by an embedded go2rtc restreamer. Stream options are cached so battery cameras show available streams even while sleeping
|
|
46
46
|
- 🔔 **Real-time Events** - Per-camera event viewer with live SSE updates (motion, doorbell, people, vehicle, animal, face, package, day/night, sleep/wake). Events are broadcast via SSE, NDJSON stream, and MQTT
|
|
47
|
-
- 📊 **Real-time Logs** - Monitor camera events and
|
|
48
|
-
- ⚙️ **Settings** - Configure
|
|
47
|
+
- 📊 **Real-time Logs** - Monitor camera events, system logs, and go2rtc process output
|
|
48
|
+
- ⚙️ **Settings** - Configure go2rtc ports, auto-start options, MQTT broker, and Home Assistant discovery
|
|
49
49
|
- 📱 **PWA Support** - Install as a Progressive Web App on mobile devices
|
|
50
50
|
- 🌐 **Responsive Design** - Works on desktop, tablet, and mobile
|
|
51
51
|
|
|
@@ -129,12 +129,12 @@ Recommended example:
|
|
|
129
129
|
services:
|
|
130
130
|
nodelink-manager:
|
|
131
131
|
ports:
|
|
132
|
-
- "3000:3000"
|
|
133
|
-
- "
|
|
134
|
-
- "
|
|
135
|
-
|
|
136
|
-
#
|
|
137
|
-
# -
|
|
132
|
+
- "3000:3000" # Web UI and API
|
|
133
|
+
- "11984:11984" # go2rtc API + dashboard
|
|
134
|
+
- "18554:18554" # go2rtc RTSP output
|
|
135
|
+
- "18555:18555/udp" # go2rtc WebRTC ICE
|
|
136
|
+
# Then configure Settings → go2rtc:
|
|
137
|
+
# - ICE servers if needed for NAT traversal
|
|
138
138
|
```
|
|
139
139
|
|
|
140
140
|
Notes:
|
|
@@ -144,11 +144,16 @@ Notes:
|
|
|
144
144
|
|
|
145
145
|
**Environment Variables:**
|
|
146
146
|
|
|
147
|
-
| Variable
|
|
148
|
-
|
|
|
149
|
-
| `PORT`
|
|
150
|
-
| `RTSP_PORT` | `8554` | RTSP proxy port |
|
|
147
|
+
| Variable | Default | Description |
|
|
148
|
+
| --- | --- | --- |
|
|
149
|
+
| `PORT` | `3000` | HTTP server port |
|
|
151
150
|
| `DATA_PATH` | `/data` | Directory for settings.json and logs |
|
|
151
|
+
| `GO2RTC_PATH` | (auto) | Path to go2rtc binary (falls back to bundled `go2rtc-static`) |
|
|
152
|
+
| `GO2RTC_API_PORT` | `11984` | go2rtc REST API + web dashboard port |
|
|
153
|
+
| `GO2RTC_RTSP_PORT` | `18554` | go2rtc RTSP output port |
|
|
154
|
+
| `GO2RTC_WEBRTC_PORT` | `18555` | go2rtc WebRTC ICE port |
|
|
155
|
+
|
|
156
|
+
Environment variables override `settings.json` values. Ports are also configurable in Settings → go2rtc.
|
|
152
157
|
|
|
153
158
|
**WebRTC / ICE (Docker bridge mode):**
|
|
154
159
|
|
|
@@ -162,88 +167,46 @@ Notes:
|
|
|
162
167
|
| `AUTH_ENABLED` | (unset) | Enable auth when set to `1/true` (or disable with `0/false`). If unset, auth auto-enables when `ADMIN_PASSWORD` is set. |
|
|
163
168
|
| `ADMIN_PASSWORD` | (unset) | Sets the `admin` password. This credential works for both the web login form and HTTP Basic auth. |
|
|
164
169
|
|
|
165
|
-
### Streaming
|
|
166
|
-
|
|
167
|
-
When authentication is enabled (see `AUTH_ENABLED` / `ADMIN_PASSWORD`), **all streaming endpoints are protected**.
|
|
170
|
+
### Streaming via go2rtc
|
|
168
171
|
|
|
169
|
-
|
|
172
|
+
All streaming is handled by an embedded **go2rtc** process (default API port `11984`, RTSP port `18554`). go2rtc provides:
|
|
170
173
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
174
|
+
| Format | URL | Notes |
|
|
175
|
+
|--------|-----|-------|
|
|
176
|
+
| **WebRTC** | `POST http://HOST:11984/api/webrtc?src={name}` | WHEP signaling (SDP offer/answer) |
|
|
177
|
+
| **MSE/MP4** | `http://HOST:11984/api/stream.mp4?src={name}` | Fragmented MP4 for browsers |
|
|
178
|
+
| **HLS** | `http://HOST:11984/api/stream.m3u8?src={name}` | Adaptive streaming |
|
|
179
|
+
| **RTSP** | `rtsp://HOST:18554/{name}` | For VLC, ffmpeg, NVR software |
|
|
180
|
+
| **Snapshot** | `http://HOST:11984/api/frame.jpeg?src={name}` | Single JPEG (requires ffmpeg) |
|
|
181
|
+
| **Dashboard** | `http://HOST:11984/` | go2rtc web UI |
|
|
179
182
|
|
|
180
|
-
|
|
183
|
+
Stream names follow the pattern `{sanitized_camera_name}_{profile}` (e.g. `studio_main`, `garage_sub`).
|
|
181
184
|
|
|
182
|
-
|
|
185
|
+
go2rtc has CORS enabled (`origin: "*"`) so browser-based players can connect directly.
|
|
183
186
|
|
|
184
|
-
|
|
185
|
-
- Credentials: the same **Users** list used by the dashboard.
|
|
186
|
-
- Digest realm: `RTSP Proxy`
|
|
187
|
-
- You can toggle whether auth is required via the Manager UI setting **“Require auth for RTSP connections”**.
|
|
187
|
+
### Authentication
|
|
188
188
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
```bash
|
|
192
|
-
# ffmpeg (Digest)
|
|
193
|
-
ffmpeg -rtsp_transport tcp -i "rtsp://USERNAME:PASSWORD@HOST:8554/camera/main" -f null -
|
|
189
|
+
When authentication is enabled (see `AUTH_ENABLED` / `ADMIN_PASSWORD`), the Manager API endpoints are protected. go2rtc streaming endpoints are currently unauthenticated (accessible on the local network).
|
|
194
190
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
2. **HTTP-based streaming (MJPEG / HLS): token in query string**
|
|
200
|
-
|
|
201
|
-
Browsers cannot reliably attach custom headers (like `Authorization`) to media tags (`<img>`, `<video>`), so MJPEG/HLS streams must be accessed with the auth token in the URL query string:
|
|
202
|
-
|
|
203
|
-
- MJPEG: `/api/mpeg/<camera>/<profile>?token=...`
|
|
204
|
-
- HLS playlist: `/api/hls/<camera>/<profile>/playlist.m3u8?token=...` (and segment requests will inherit the query param)
|
|
191
|
+
- Manager API: `Authorization: Bearer <token>` header or session cookie
|
|
192
|
+
- WebSocket logs: `?token=...` in the WS URL
|
|
205
193
|
|
|
206
194
|
Examples:
|
|
207
195
|
|
|
208
|
-
```text
|
|
209
|
-
MJPEG:
|
|
210
|
-
http://HOST:3000/api/mpeg/camera/main?token=YOUR_TOKEN
|
|
211
|
-
|
|
212
|
-
HLS:
|
|
213
|
-
http://HOST:3000/api/hls/camera/main/playlist.m3u8?token=YOUR_TOKEN
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
Security note: query tokens may end up in logs/history. Treat them like passwords.
|
|
217
|
-
|
|
218
|
-
3. **WebRTC control endpoints: Bearer token in Authorization header**
|
|
219
|
-
|
|
220
|
-
WebRTC signaling uses JSON endpoints (create session, send ICE candidates, send answer) and supports standard Bearer auth:
|
|
221
|
-
|
|
222
196
|
```bash
|
|
223
|
-
#
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
-d '{"username":"admin","password":"YOUR_PASSWORD"}'
|
|
227
|
-
|
|
228
|
-
# 2) Use the returned token for WebRTC signaling
|
|
229
|
-
curl -sS http://HOST:3000/api/webrtc/status \
|
|
230
|
-
-H "Authorization: Bearer YOUR_TOKEN"
|
|
231
|
-
```
|
|
197
|
+
# RTSP via go2rtc (no auth)
|
|
198
|
+
ffmpeg -rtsp_transport tcp -i “rtsp://HOST:18554/studio_main” -f null -
|
|
199
|
+
vlc “rtsp://HOST:18554/studio_main”
|
|
232
200
|
|
|
233
|
-
|
|
201
|
+
# WebRTC WHEP signaling
|
|
202
|
+
curl -X POST “http://HOST:11984/api/webrtc?src=studio_main” \
|
|
203
|
+
-H “Content-Type: application/sdp” \
|
|
204
|
+
--data-binary @offer.sdp
|
|
234
205
|
|
|
235
|
-
|
|
236
|
-
curl -
|
|
237
|
-
-H "Authorization: Bearer YOUR_TOKEN" \
|
|
238
|
-
-H 'content-type: application/json' \
|
|
239
|
-
-d '{}'
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
4. **WebSocket logs: token in query string**
|
|
206
|
+
# Snapshot
|
|
207
|
+
curl -o snap.jpg “http://HOST:11984/api/frame.jpeg?src=studio_main”
|
|
243
208
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
```text
|
|
209
|
+
# WebSocket logs (auth)
|
|
247
210
|
ws://HOST:3000/ws/logs?token=YOUR_TOKEN
|
|
248
211
|
```
|
|
249
212
|
|
|
@@ -262,10 +225,13 @@ The Manager UI exposes a REST API for integrations, scripts, and third-party app
|
|
|
262
225
|
| Category | Endpoints |
|
|
263
226
|
|----------|-----------|
|
|
264
227
|
| **Auth** | `GET /api/auth/config`, `POST /api/auth/login`, `POST /api/auth/personal-token` |
|
|
265
|
-
| **Streaming** |
|
|
228
|
+
| **go2rtc Streaming** | Served directly by go2rtc (default port `11984`): WebRTC, MSE/MP4, HLS, RTSP, Snapshot |
|
|
229
|
+
| **go2rtc Management** | tRPC: `go2rtc.start`, `go2rtc.stop`, `go2rtc.status`, `go2rtc.listStreams` |
|
|
266
230
|
| **Events** | `GET /api/events/sse` (SSE), `GET /api/events/stream` (NDJSON), `GET /api/events/status` |
|
|
267
231
|
| **System** | `GET /api/health`, `GET /api/metrics`, `GET /api/updates` |
|
|
268
232
|
|
|
233
|
+
**Streaming** — All video output (WebRTC, MSE, HLS, RTSP, snapshots) is handled by an embedded go2rtc restreamer. The Manager creates internal RTSP servers per stream and registers them with go2rtc, which provides multi-format output with audio support.
|
|
234
|
+
|
|
269
235
|
**Events** — Real-time camera events (motion, doorbell, people, vehicle, etc.) via Server-Sent Events or NDJSON stream. When MQTT is configured, events are also published to the broker.
|
|
270
236
|
|
|
271
237
|
📖 **[Full Manager API documentation →](./documentation/manager-api.md)**
|
|
@@ -1822,6 +1822,22 @@ var BaichuanClient = class _BaichuanClient extends EventEmitter2 {
|
|
|
1822
1822
|
static coverPreviewBackoffMs = /* @__PURE__ */ new Map();
|
|
1823
1823
|
static COVER_PREVIEW_INITIAL_BACKOFF_MS = 1e3;
|
|
1824
1824
|
static COVER_PREVIEW_MAX_BACKOFF_MS = 3e4;
|
|
1825
|
+
/**
|
|
1826
|
+
* Per-client snapshot (cmd_id=109) serialization queue.
|
|
1827
|
+
*
|
|
1828
|
+
* WHY: On NVR/multi-camera devices sharing one socket, concurrent snapshot requests
|
|
1829
|
+
* can cause JPEG data to mix (even with per-request msgNum filtering):
|
|
1830
|
+
* - Camera A and B both send frames on same socket
|
|
1831
|
+
* - Frame listener is global per socket
|
|
1832
|
+
* - Timing quirks can cause chunk reordering or listener confusion
|
|
1833
|
+
*
|
|
1834
|
+
* FIX: Serialize all cmd_id=109 requests on THIS client instance.
|
|
1835
|
+
* Each snapshot waits for previous one to complete before starting.
|
|
1836
|
+
* This ensures clean frame sequences per request, zero data corruption.
|
|
1837
|
+
*
|
|
1838
|
+
* Impact: Snapshots are ~0–50ms slower per camera (negligible for users).
|
|
1839
|
+
*/
|
|
1840
|
+
snapshotQueueTail = Promise.resolve();
|
|
1825
1841
|
opts;
|
|
1826
1842
|
debugCfg;
|
|
1827
1843
|
logger;
|
|
@@ -4303,6 +4319,20 @@ var BaichuanClient = class _BaichuanClient extends EventEmitter2 {
|
|
|
4303
4319
|
});
|
|
4304
4320
|
}
|
|
4305
4321
|
async sendBinarySnapshot109(params) {
|
|
4322
|
+
const prevTail = this.snapshotQueueTail;
|
|
4323
|
+
let resolve;
|
|
4324
|
+
const newTail = new Promise((r) => {
|
|
4325
|
+
resolve = r;
|
|
4326
|
+
});
|
|
4327
|
+
this.snapshotQueueTail = newTail;
|
|
4328
|
+
try {
|
|
4329
|
+
await prevTail;
|
|
4330
|
+
return await this.sendBinarySnapshot109Impl(params);
|
|
4331
|
+
} finally {
|
|
4332
|
+
resolve();
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
4335
|
+
async sendBinarySnapshot109Impl(params) {
|
|
4306
4336
|
await this.connect();
|
|
4307
4337
|
const channel = params.channel ?? this.opts.channel ?? 0;
|
|
4308
4338
|
const channelId = params.channelIdOverride ?? (params.channel == null ? this.hostChannelId : channel + 1);
|
|
@@ -4362,7 +4392,8 @@ var BaichuanClient = class _BaichuanClient extends EventEmitter2 {
|
|
|
4362
4392
|
};
|
|
4363
4393
|
const onFrame = (frame) => {
|
|
4364
4394
|
if (frame.header.cmdId !== cmdId) return;
|
|
4365
|
-
if (frame.header.msgNum
|
|
4395
|
+
if (frame.header.msgNum !== msgNum) return;
|
|
4396
|
+
if (frame.header.responseCode >= 400) {
|
|
4366
4397
|
fail(
|
|
4367
4398
|
new Error(
|
|
4368
4399
|
`Baichuan snapshot request rejected (cmdId=${cmdId} msgNum=${msgNum} responseCode=${frame.header.responseCode})`
|
|
@@ -21475,4 +21506,4 @@ export {
|
|
|
21475
21506
|
isTcpFailureThatShouldFallbackToUdp,
|
|
21476
21507
|
autoDetectDeviceType
|
|
21477
21508
|
};
|
|
21478
|
-
//# sourceMappingURL=chunk-
|
|
21509
|
+
//# sourceMappingURL=chunk-UDS2UR4S.js.map
|