@apocaliss92/nodelink-js 0.2.3 → 0.2.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 +6 -2
- package/dist/{DiagnosticsTools-FNLGCOVA.js → DiagnosticsTools-2JQRV5FE.js} +2 -2
- package/dist/{chunk-NLTB7GTA.js → chunk-APEEZ4UN.js} +10 -9
- package/dist/{chunk-NLTB7GTA.js.map → chunk-APEEZ4UN.js.map} +1 -1
- package/dist/{chunk-RWYEGEWG.js → chunk-EG5IY3CM.js} +77 -9
- package/dist/chunk-EG5IY3CM.js.map +1 -0
- package/dist/cli/rtsp-server.cjs +82 -13
- package/dist/cli/rtsp-server.cjs.map +1 -1
- package/dist/cli/rtsp-server.js +2 -2
- package/dist/index.cjs +144 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +64 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-RWYEGEWG.js.map +0 -1
- /package/dist/{DiagnosticsTools-FNLGCOVA.js.map → DiagnosticsTools-2JQRV5FE.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -3323,6 +3323,12 @@ interface BaichuanRtspServerOptions {
|
|
|
3323
3323
|
}>;
|
|
3324
3324
|
/** Require authentication for RTSP connections (default: false if no credentials set) */
|
|
3325
3325
|
requireAuth?: boolean;
|
|
3326
|
+
/**
|
|
3327
|
+
* External identifier for dedicated socket session.
|
|
3328
|
+
* When provided, a dedicated BaichuanClient is created for the stream,
|
|
3329
|
+
* isolating it from other streams on the shared socket (avoids streamType mismatch).
|
|
3330
|
+
*/
|
|
3331
|
+
deviceId?: string;
|
|
3326
3332
|
}
|
|
3327
3333
|
/**
|
|
3328
3334
|
* BaichuanRtspServer - RTSP server that serves a Baichuan video stream.
|
|
@@ -3352,6 +3358,8 @@ declare class BaichuanRtspServer extends EventEmitter<{
|
|
|
3352
3358
|
private tcpRtpFraming;
|
|
3353
3359
|
private active;
|
|
3354
3360
|
private flow;
|
|
3361
|
+
private deviceId;
|
|
3362
|
+
private dedicatedSessionRelease;
|
|
3355
3363
|
private authCredentials;
|
|
3356
3364
|
private requireAuth;
|
|
3357
3365
|
private authNonces;
|
|
@@ -3440,7 +3448,9 @@ declare class BaichuanRtspServer extends EventEmitter<{
|
|
|
3440
3448
|
*/
|
|
3441
3449
|
private stopNativeStream;
|
|
3442
3450
|
/**
|
|
3443
|
-
* Remove a client and
|
|
3451
|
+
* Remove a client and schedule native stream stop if no clients remain.
|
|
3452
|
+
* Uses a grace period so rapid reconnects (e.g. Frigate polling) reuse the running stream
|
|
3453
|
+
* and benefit from the prebuffer instead of waiting for a fresh keyframe.
|
|
3444
3454
|
*/
|
|
3445
3455
|
private removeClient;
|
|
3446
3456
|
/**
|
|
@@ -7416,6 +7426,8 @@ declare class BaichuanEventEmitter {
|
|
|
7416
7426
|
*/
|
|
7417
7427
|
declare function createNativeStream(api: ReolinkBaichuanApi, channel: number, profile: StreamProfile, options?: {
|
|
7418
7428
|
variant?: NativeVideoStreamVariant;
|
|
7429
|
+
/** Optional dedicated BaichuanClient for stream isolation. When omitted, uses api.client (shared). */
|
|
7430
|
+
client?: BaichuanClient;
|
|
7419
7431
|
}): AsyncGenerator<{
|
|
7420
7432
|
audio: boolean;
|
|
7421
7433
|
data: Buffer;
|
|
@@ -8169,6 +8181,13 @@ interface BaichuanHlsServerOptions {
|
|
|
8169
8181
|
playlistSize?: number;
|
|
8170
8182
|
/** ffmpeg binary path (default: "ffmpeg") */
|
|
8171
8183
|
ffmpegPath?: string;
|
|
8184
|
+
/**
|
|
8185
|
+
* External video stream from a shared pool (e.g. createRfc4571TcpServer).
|
|
8186
|
+
* When provided, the HLS server subscribes to this stream's events instead
|
|
8187
|
+
* of creating its own via createNativeStream. This allows multiple outputs
|
|
8188
|
+
* (MJPEG, HLS, WebRTC) to share a single camera streaming session.
|
|
8189
|
+
*/
|
|
8190
|
+
externalVideoStream?: BaichuanVideoStream;
|
|
8172
8191
|
/** Logger callback */
|
|
8173
8192
|
logger?: (level: "debug" | "info" | "warn" | "error", message: string) => void;
|
|
8174
8193
|
}
|
|
@@ -8190,6 +8209,7 @@ declare class BaichuanHlsServer extends EventEmitter {
|
|
|
8190
8209
|
private readonly segmentDuration;
|
|
8191
8210
|
private readonly playlistSize;
|
|
8192
8211
|
private readonly ffmpegPath;
|
|
8212
|
+
private readonly externalVideoStream;
|
|
8193
8213
|
private readonly log;
|
|
8194
8214
|
private outputDir;
|
|
8195
8215
|
private createdTempDir;
|
|
@@ -8235,6 +8255,11 @@ declare class BaichuanHlsServer extends EventEmitter {
|
|
|
8235
8255
|
data: Buffer;
|
|
8236
8256
|
contentType: string;
|
|
8237
8257
|
} | null>;
|
|
8258
|
+
/**
|
|
8259
|
+
* Wrap a BaichuanVideoStream's videoAccessUnit events into an async generator
|
|
8260
|
+
* compatible with createNativeStream's output format.
|
|
8261
|
+
*/
|
|
8262
|
+
private wrapVideoStreamAsGenerator;
|
|
8238
8263
|
private pumpNativeToFfmpeg;
|
|
8239
8264
|
private spawnFfmpeg;
|
|
8240
8265
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -994,6 +994,7 @@ export declare class BaichuanHlsServer extends EventEmitter {
|
|
|
994
994
|
private readonly segmentDuration;
|
|
995
995
|
private readonly playlistSize;
|
|
996
996
|
private readonly ffmpegPath;
|
|
997
|
+
private readonly externalVideoStream;
|
|
997
998
|
private readonly log;
|
|
998
999
|
private outputDir;
|
|
999
1000
|
private createdTempDir;
|
|
@@ -1039,6 +1040,11 @@ export declare class BaichuanHlsServer extends EventEmitter {
|
|
|
1039
1040
|
data: Buffer;
|
|
1040
1041
|
contentType: string;
|
|
1041
1042
|
} | null>;
|
|
1043
|
+
/**
|
|
1044
|
+
* Wrap a BaichuanVideoStream's videoAccessUnit events into an async generator
|
|
1045
|
+
* compatible with createNativeStream's output format.
|
|
1046
|
+
*/
|
|
1047
|
+
private wrapVideoStreamAsGenerator;
|
|
1042
1048
|
private pumpNativeToFfmpeg;
|
|
1043
1049
|
private spawnFfmpeg;
|
|
1044
1050
|
}
|
|
@@ -1060,6 +1066,13 @@ export declare interface BaichuanHlsServerOptions {
|
|
|
1060
1066
|
playlistSize?: number;
|
|
1061
1067
|
/** ffmpeg binary path (default: "ffmpeg") */
|
|
1062
1068
|
ffmpegPath?: string;
|
|
1069
|
+
/**
|
|
1070
|
+
* External video stream from a shared pool (e.g. createRfc4571TcpServer).
|
|
1071
|
+
* When provided, the HLS server subscribes to this stream's events instead
|
|
1072
|
+
* of creating its own via createNativeStream. This allows multiple outputs
|
|
1073
|
+
* (MJPEG, HLS, WebRTC) to share a single camera streaming session.
|
|
1074
|
+
*/
|
|
1075
|
+
externalVideoStream?: BaichuanVideoStream;
|
|
1063
1076
|
/** Logger callback */
|
|
1064
1077
|
logger?: (level: "debug" | "info" | "warn" | "error", message: string) => void;
|
|
1065
1078
|
}
|
|
@@ -1298,6 +1311,8 @@ export declare class BaichuanRtspServer extends EventEmitter<{
|
|
|
1298
1311
|
private tcpRtpFraming;
|
|
1299
1312
|
private active;
|
|
1300
1313
|
private flow;
|
|
1314
|
+
private deviceId;
|
|
1315
|
+
private dedicatedSessionRelease;
|
|
1301
1316
|
private authCredentials;
|
|
1302
1317
|
private requireAuth;
|
|
1303
1318
|
private authNonces;
|
|
@@ -1386,7 +1401,9 @@ export declare class BaichuanRtspServer extends EventEmitter<{
|
|
|
1386
1401
|
*/
|
|
1387
1402
|
private stopNativeStream;
|
|
1388
1403
|
/**
|
|
1389
|
-
* Remove a client and
|
|
1404
|
+
* Remove a client and schedule native stream stop if no clients remain.
|
|
1405
|
+
* Uses a grace period so rapid reconnects (e.g. Frigate polling) reuse the running stream
|
|
1406
|
+
* and benefit from the prebuffer instead of waiting for a fresh keyframe.
|
|
1390
1407
|
*/
|
|
1391
1408
|
private removeClient;
|
|
1392
1409
|
/**
|
|
@@ -1440,6 +1457,12 @@ export declare interface BaichuanRtspServerOptions {
|
|
|
1440
1457
|
}>;
|
|
1441
1458
|
/** Require authentication for RTSP connections (default: false if no credentials set) */
|
|
1442
1459
|
requireAuth?: boolean;
|
|
1460
|
+
/**
|
|
1461
|
+
* External identifier for dedicated socket session.
|
|
1462
|
+
* When provided, a dedicated BaichuanClient is created for the stream,
|
|
1463
|
+
* isolating it from other streams on the shared socket (avoids streamType mismatch).
|
|
1464
|
+
*/
|
|
1465
|
+
deviceId?: string;
|
|
1443
1466
|
}
|
|
1444
1467
|
|
|
1445
1468
|
export declare type BaichuanSerialPush = {
|
|
@@ -3290,6 +3313,8 @@ export declare function createMjpegBoundary(): string;
|
|
|
3290
3313
|
*/
|
|
3291
3314
|
export declare function createNativeStream(api: ReolinkBaichuanApi, channel: number, profile: StreamProfile, options?: {
|
|
3292
3315
|
variant?: NativeVideoStreamVariant;
|
|
3316
|
+
/** Optional dedicated BaichuanClient for stream isolation. When omitted, uses api.client (shared). */
|
|
3317
|
+
client?: BaichuanClient;
|
|
3293
3318
|
}): AsyncGenerator<{
|
|
3294
3319
|
audio: boolean;
|
|
3295
3320
|
data: Buffer;
|
package/dist/index.js
CHANGED
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
normalizeUid,
|
|
39
39
|
parseSupportXml,
|
|
40
40
|
setGlobalLogger
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-EG5IY3CM.js";
|
|
42
42
|
import {
|
|
43
43
|
AesStreamDecryptor,
|
|
44
44
|
BC_AES_IV,
|
|
@@ -215,7 +215,7 @@ import {
|
|
|
215
215
|
testChannelStreams,
|
|
216
216
|
xmlEscape,
|
|
217
217
|
zipDirectory
|
|
218
|
-
} from "./chunk-
|
|
218
|
+
} from "./chunk-APEEZ4UN.js";
|
|
219
219
|
|
|
220
220
|
// src/reolink/baichuan/HlsSessionManager.ts
|
|
221
221
|
var withTimeout = async (p, ms, label) => {
|
|
@@ -6494,6 +6494,7 @@ var BaichuanHlsServer = class extends EventEmitter6 {
|
|
|
6494
6494
|
segmentDuration;
|
|
6495
6495
|
playlistSize;
|
|
6496
6496
|
ffmpegPath;
|
|
6497
|
+
externalVideoStream;
|
|
6497
6498
|
log;
|
|
6498
6499
|
outputDir = null;
|
|
6499
6500
|
createdTempDir = false;
|
|
@@ -6520,6 +6521,7 @@ var BaichuanHlsServer = class extends EventEmitter6 {
|
|
|
6520
6521
|
this.outputDir = options.outputDir;
|
|
6521
6522
|
this.createdTempDir = false;
|
|
6522
6523
|
}
|
|
6524
|
+
this.externalVideoStream = options.externalVideoStream;
|
|
6523
6525
|
this.log = options.logger ?? (() => {
|
|
6524
6526
|
});
|
|
6525
6527
|
}
|
|
@@ -6544,12 +6546,16 @@ var BaichuanHlsServer = class extends EventEmitter6 {
|
|
|
6544
6546
|
this.playlistPath = path.join(this.outputDir, "playlist.m3u8");
|
|
6545
6547
|
this.segmentPattern = path.join(this.outputDir, "segment_%05d.ts");
|
|
6546
6548
|
this.log("info", `Starting HLS stream to ${this.outputDir}`);
|
|
6547
|
-
this.
|
|
6548
|
-
this.
|
|
6549
|
-
|
|
6550
|
-
this.
|
|
6551
|
-
|
|
6552
|
-
|
|
6549
|
+
if (this.externalVideoStream) {
|
|
6550
|
+
this.nativeStream = this.wrapVideoStreamAsGenerator(this.externalVideoStream);
|
|
6551
|
+
} else {
|
|
6552
|
+
this.nativeStream = createNativeStream(
|
|
6553
|
+
this.api,
|
|
6554
|
+
this.channel,
|
|
6555
|
+
this.profile,
|
|
6556
|
+
this.variant ? { variant: this.variant } : void 0
|
|
6557
|
+
);
|
|
6558
|
+
}
|
|
6553
6559
|
this.pumpPromise = this.pumpNativeToFfmpeg();
|
|
6554
6560
|
this.startedAt = /* @__PURE__ */ new Date();
|
|
6555
6561
|
this.state = "running";
|
|
@@ -6668,6 +6674,56 @@ var BaichuanHlsServer = class extends EventEmitter6 {
|
|
|
6668
6674
|
// ============================================================================
|
|
6669
6675
|
// Private Methods
|
|
6670
6676
|
// ============================================================================
|
|
6677
|
+
/**
|
|
6678
|
+
* Wrap a BaichuanVideoStream's videoAccessUnit events into an async generator
|
|
6679
|
+
* compatible with createNativeStream's output format.
|
|
6680
|
+
*/
|
|
6681
|
+
async *wrapVideoStreamAsGenerator(videoStream) {
|
|
6682
|
+
const queue = [];
|
|
6683
|
+
let resolve = null;
|
|
6684
|
+
let done = false;
|
|
6685
|
+
const onFrame = (au) => {
|
|
6686
|
+
queue.push(au);
|
|
6687
|
+
resolve?.();
|
|
6688
|
+
resolve = null;
|
|
6689
|
+
};
|
|
6690
|
+
const onClose = () => {
|
|
6691
|
+
done = true;
|
|
6692
|
+
resolve?.();
|
|
6693
|
+
resolve = null;
|
|
6694
|
+
};
|
|
6695
|
+
const onError = () => {
|
|
6696
|
+
done = true;
|
|
6697
|
+
resolve?.();
|
|
6698
|
+
resolve = null;
|
|
6699
|
+
};
|
|
6700
|
+
videoStream.on("videoAccessUnit", onFrame);
|
|
6701
|
+
videoStream.on("close", onClose);
|
|
6702
|
+
videoStream.on("error", onError);
|
|
6703
|
+
try {
|
|
6704
|
+
while (!done) {
|
|
6705
|
+
if (queue.length === 0) {
|
|
6706
|
+
await new Promise((r) => {
|
|
6707
|
+
resolve = r;
|
|
6708
|
+
});
|
|
6709
|
+
}
|
|
6710
|
+
while (queue.length > 0) {
|
|
6711
|
+
const frame = queue.shift();
|
|
6712
|
+
yield {
|
|
6713
|
+
audio: false,
|
|
6714
|
+
data: frame.data,
|
|
6715
|
+
videoType: frame.videoType,
|
|
6716
|
+
isKeyframe: frame.isKeyframe,
|
|
6717
|
+
microseconds: frame.microseconds
|
|
6718
|
+
};
|
|
6719
|
+
}
|
|
6720
|
+
}
|
|
6721
|
+
} finally {
|
|
6722
|
+
videoStream.removeListener("videoAccessUnit", onFrame);
|
|
6723
|
+
videoStream.removeListener("close", onClose);
|
|
6724
|
+
videoStream.removeListener("error", onError);
|
|
6725
|
+
}
|
|
6726
|
+
}
|
|
6671
6727
|
async pumpNativeToFfmpeg() {
|
|
6672
6728
|
if (!this.nativeStream || !this.playlistPath || !this.segmentPattern) {
|
|
6673
6729
|
return;
|