@apocaliss92/nodelink-js 0.4.1 → 0.4.2
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/{chunk-SDRNJQ5U.js → chunk-TJNPGYJA.js} +88 -34
- package/dist/chunk-TJNPGYJA.js.map +1 -0
- package/dist/cli/rtsp-server.cjs +87 -33
- package/dist/cli/rtsp-server.cjs.map +1 -1
- package/dist/cli/rtsp-server.js +1 -1
- package/dist/index.cjs +87 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -5
- package/dist/index.d.ts +47 -5
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-SDRNJQ5U.js.map +0 -1
package/dist/cli/rtsp-server.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -13410,6 +13410,7 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
|
|
|
13410
13410
|
flow;
|
|
13411
13411
|
deviceId;
|
|
13412
13412
|
dedicatedSessionRelease;
|
|
13413
|
+
externalListener;
|
|
13413
13414
|
// Authentication
|
|
13414
13415
|
authCredentials = [];
|
|
13415
13416
|
requireAuth;
|
|
@@ -13577,6 +13578,7 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
|
|
|
13577
13578
|
this.logger = options.logger ?? console;
|
|
13578
13579
|
this.tcpRtpFraming = options.tcpRtpFraming ?? "rfc4571";
|
|
13579
13580
|
this.deviceId = options.deviceId;
|
|
13581
|
+
this.externalListener = options.externalListener ?? false;
|
|
13580
13582
|
this.authCredentials = options.credentials ?? [];
|
|
13581
13583
|
this.requireAuth = options.requireAuth ?? this.authCredentials.length > 0;
|
|
13582
13584
|
const transport = this.api.client.getTransport();
|
|
@@ -13707,41 +13709,56 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
|
|
|
13707
13709
|
this.streamMetadata = { frameRate: 25 };
|
|
13708
13710
|
this.setFlowVideoType("H264", "metadata unavailable");
|
|
13709
13711
|
}
|
|
13710
|
-
this.
|
|
13711
|
-
this.
|
|
13712
|
-
|
|
13713
|
-
|
|
13714
|
-
|
|
13715
|
-
this.
|
|
13716
|
-
|
|
13717
|
-
|
|
13718
|
-
|
|
13719
|
-
|
|
13720
|
-
|
|
13712
|
+
if (!this.externalListener) {
|
|
13713
|
+
this.clientConnectionServer = net2.createServer((socket) => {
|
|
13714
|
+
this.handleRtspConnection(socket);
|
|
13715
|
+
});
|
|
13716
|
+
await new Promise((resolve, reject) => {
|
|
13717
|
+
this.clientConnectionServer.listen(
|
|
13718
|
+
this.listenPort,
|
|
13719
|
+
this.listenHost,
|
|
13720
|
+
() => {
|
|
13721
|
+
const address = this.clientConnectionServer.address();
|
|
13722
|
+
if (address && typeof address === "object" && "port" in address) {
|
|
13723
|
+
this.listenPort = address.port;
|
|
13724
|
+
}
|
|
13725
|
+
resolve();
|
|
13721
13726
|
}
|
|
13722
|
-
|
|
13723
|
-
|
|
13724
|
-
|
|
13725
|
-
|
|
13726
|
-
reject(error);
|
|
13727
|
+
);
|
|
13728
|
+
this.clientConnectionServer.on("error", (error) => {
|
|
13729
|
+
reject(error);
|
|
13730
|
+
});
|
|
13727
13731
|
});
|
|
13728
|
-
}
|
|
13732
|
+
}
|
|
13729
13733
|
this.active = true;
|
|
13730
13734
|
this.logger.info(
|
|
13731
13735
|
`[BaichuanRtspServer] RTSP server started on ${this.listenHost}:${this.listenPort}, path: ${this.path}`
|
|
13732
13736
|
);
|
|
13733
13737
|
}
|
|
13738
|
+
/**
|
|
13739
|
+
* Accept an externally-routed RTSP connection.
|
|
13740
|
+
* Used in directHandoff mode where RtspProxyServer routes sockets here.
|
|
13741
|
+
* @param socket - The client TCP socket (already authenticated by proxy)
|
|
13742
|
+
* @param initialBuffer - Any bytes already read during path parsing/auth
|
|
13743
|
+
*/
|
|
13744
|
+
acceptConnection(socket, initialBuffer) {
|
|
13745
|
+
if (!this.active) {
|
|
13746
|
+
socket.end("RTSP/1.0 503 Service Unavailable\r\n\r\n");
|
|
13747
|
+
return;
|
|
13748
|
+
}
|
|
13749
|
+
this.handleRtspConnection(socket, initialBuffer);
|
|
13750
|
+
}
|
|
13734
13751
|
/**
|
|
13735
13752
|
* Handle RTSP connection from a client.
|
|
13736
13753
|
*/
|
|
13737
|
-
handleRtspConnection(socket) {
|
|
13754
|
+
handleRtspConnection(socket, initialBuffer) {
|
|
13738
13755
|
const clientId = `${socket.remoteAddress}:${socket.remotePort}`;
|
|
13739
13756
|
const connectTime = Date.now();
|
|
13740
13757
|
this.logger.info(
|
|
13741
13758
|
`[rebroadcast] client connected client=${clientId} path=${this.path} profile=${this.profile} channel=${this.channel}`
|
|
13742
13759
|
);
|
|
13743
13760
|
let sessionId = "";
|
|
13744
|
-
let buffer = Buffer.alloc(0);
|
|
13761
|
+
let buffer = initialBuffer ?? Buffer.alloc(0);
|
|
13745
13762
|
let clientFfmpeg;
|
|
13746
13763
|
let useTcpInterleaved = false;
|
|
13747
13764
|
let clientUdpSocket = null;
|
|
@@ -13826,8 +13843,7 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
|
|
|
13826
13843
|
}
|
|
13827
13844
|
cleanup();
|
|
13828
13845
|
});
|
|
13829
|
-
|
|
13830
|
-
buffer = Buffer.concat([buffer, data]);
|
|
13846
|
+
const processBuffer = async () => {
|
|
13831
13847
|
while (buffer.includes("\r\n\r\n")) {
|
|
13832
13848
|
const endIndex = buffer.indexOf("\r\n\r\n");
|
|
13833
13849
|
const requestText = buffer.subarray(0, endIndex).toString();
|
|
@@ -14102,7 +14118,14 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
|
|
|
14102
14118
|
sendResponse(501, "Not Implemented");
|
|
14103
14119
|
}
|
|
14104
14120
|
}
|
|
14121
|
+
};
|
|
14122
|
+
socket.on("data", (data) => {
|
|
14123
|
+
buffer = Buffer.concat([buffer, data]);
|
|
14124
|
+
void processBuffer();
|
|
14105
14125
|
});
|
|
14126
|
+
if (buffer.includes("\r\n\r\n")) {
|
|
14127
|
+
void processBuffer();
|
|
14128
|
+
}
|
|
14106
14129
|
}
|
|
14107
14130
|
/**
|
|
14108
14131
|
* Generate SDP (Session Description Protocol) for RTSP DESCRIBE.
|
|
@@ -15070,21 +15093,27 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
|
|
|
15070
15093
|
res.seenFirstVideoKeyframe = false;
|
|
15071
15094
|
res.rtpSentVideoConfig = false;
|
|
15072
15095
|
}
|
|
15073
|
-
if (this.dedicatedSessionRelease) {
|
|
15074
|
-
const release = this.dedicatedSessionRelease;
|
|
15075
|
-
this.dedicatedSessionRelease = void 0;
|
|
15076
|
-
release().catch(() => {
|
|
15077
|
-
});
|
|
15078
|
-
}
|
|
15079
15096
|
this.logger.info(
|
|
15080
15097
|
`[rebroadcast] native stream ended (camera sleeping or connection lost) profile=${this.profile} channel=${this.channel} clients=${this.connectedClients.size}`
|
|
15081
15098
|
);
|
|
15082
|
-
|
|
15083
|
-
this.
|
|
15084
|
-
|
|
15085
|
-
|
|
15086
|
-
|
|
15087
|
-
|
|
15099
|
+
const releaseAndRestart = async () => {
|
|
15100
|
+
if (this.dedicatedSessionRelease) {
|
|
15101
|
+
const release = this.dedicatedSessionRelease;
|
|
15102
|
+
this.dedicatedSessionRelease = void 0;
|
|
15103
|
+
try {
|
|
15104
|
+
await release();
|
|
15105
|
+
} catch {
|
|
15106
|
+
}
|
|
15107
|
+
}
|
|
15108
|
+
if (this.connectedClients.size > 0) {
|
|
15109
|
+
this.logger.info(
|
|
15110
|
+
`[rebroadcast] restarting native stream for ${this.connectedClients.size} active client(s)`
|
|
15111
|
+
);
|
|
15112
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
15113
|
+
void this.startNativeStream();
|
|
15114
|
+
}
|
|
15115
|
+
};
|
|
15116
|
+
void releaseAndRestart();
|
|
15088
15117
|
}
|
|
15089
15118
|
});
|
|
15090
15119
|
this.nativeFanout.start();
|
|
@@ -15308,6 +15337,31 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
|
|
|
15308
15337
|
getClientCount() {
|
|
15309
15338
|
return this.connectedClients.size;
|
|
15310
15339
|
}
|
|
15340
|
+
/**
|
|
15341
|
+
* Subscribe to the raw native stream for diagnostic purposes.
|
|
15342
|
+
* The subscriber receives the same frames as RTSP clients.
|
|
15343
|
+
* Counts as a "consumer" for lifecycle — prevents auto-stop while subscribed.
|
|
15344
|
+
* If the native stream is not active, starts it automatically.
|
|
15345
|
+
*/
|
|
15346
|
+
async subscribeDiagnostic(id) {
|
|
15347
|
+
this.connectedClients.add(`diag:${id}`);
|
|
15348
|
+
if (!this.nativeStreamActive) {
|
|
15349
|
+
await this.startNativeStream();
|
|
15350
|
+
}
|
|
15351
|
+
return this.nativeFanout.subscribe(`diag:${id}`);
|
|
15352
|
+
}
|
|
15353
|
+
/**
|
|
15354
|
+
* Unsubscribe a diagnostic session.
|
|
15355
|
+
*/
|
|
15356
|
+
unsubscribeDiagnostic(id) {
|
|
15357
|
+
this.removeClient(`diag:${id}`);
|
|
15358
|
+
}
|
|
15359
|
+
/**
|
|
15360
|
+
* Returns detected audio metadata (available after first audio frame).
|
|
15361
|
+
*/
|
|
15362
|
+
getAudioInfo() {
|
|
15363
|
+
return this.audioInfo;
|
|
15364
|
+
}
|
|
15311
15365
|
};
|
|
15312
15366
|
|
|
15313
15367
|
// src/reolink/baichuan/ReolinkBaichuanApi.ts
|