@apocaliss92/nodelink-js 0.4.14 → 0.4.16
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-WKETZFBI.js → chunk-65HTCC62.js} +137 -90
- package/dist/chunk-65HTCC62.js.map +1 -0
- package/dist/cli/rtsp-server.cjs +136 -89
- package/dist/cli/rtsp-server.cjs.map +1 -1
- package/dist/cli/rtsp-server.js +1 -1
- package/dist/index.cjs +136 -89
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -12
- package/dist/index.d.ts +29 -12
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-WKETZFBI.js.map +0 -1
package/dist/cli/rtsp-server.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -19560,14 +19560,15 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
|
|
|
19560
19560
|
// _registerVideoStreamForDetection (called from BaichuanVideoStream.start).
|
|
19561
19561
|
detectionEventListeners = /* @__PURE__ */ new Set();
|
|
19562
19562
|
detectionEventStreamHooks = /* @__PURE__ */ new Map();
|
|
19563
|
-
// Auto-managed
|
|
19564
|
-
//
|
|
19565
|
-
//
|
|
19566
|
-
//
|
|
19567
|
-
//
|
|
19568
|
-
|
|
19569
|
-
|
|
19570
|
-
|
|
19563
|
+
// Auto-managed substreams for `onObjectDetections` listeners. One entry per
|
|
19564
|
+
// `(channel, profile)` tuple — required for NVR/Hub setups where AI boxes
|
|
19565
|
+
// live on a specific channel, and for callers that need detections off a
|
|
19566
|
+
// profile other than the default `sub`. The substream is opened on the first
|
|
19567
|
+
// listener of a tuple and torn down when the last one for that tuple leaves.
|
|
19568
|
+
objectDetectionSubs = /* @__PURE__ */ new Map();
|
|
19569
|
+
// Single bridge installed into `detectionEventListeners` while at least one
|
|
19570
|
+
// object-detection subscription is active. It routes events to the correct
|
|
19571
|
+
// tuple's listener set based on `event.channel` / `event.profile`.
|
|
19571
19572
|
objectDetectionInternalListener;
|
|
19572
19573
|
simpleEventSubscribeInFlight;
|
|
19573
19574
|
simpleEventUnsubscribeInFlight;
|
|
@@ -21035,87 +21036,129 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
|
|
|
21035
21036
|
* Subscribe to AI object detections (people / vehicle / animal / face boxes
|
|
21036
21037
|
* with class label and confidence) without managing a video stream yourself.
|
|
21037
21038
|
*
|
|
21038
|
-
* Mirrors {@link onSimpleEvent} end-to-end: the
|
|
21039
|
-
*
|
|
21040
|
-
*
|
|
21041
|
-
*
|
|
21042
|
-
*
|
|
21039
|
+
* Mirrors {@link onSimpleEvent} end-to-end: on the first listener for a given
|
|
21040
|
+
* `(channel, profile)` tuple the API ensures the corresponding video stream
|
|
21041
|
+
* is running (the pool socket may already be shared with a regular consumer),
|
|
21042
|
+
* forwards every box-bearing `additionalHeader` to your callback, and tears
|
|
21043
|
+
* the stream down when the last listener for that tuple unsubscribes.
|
|
21044
|
+
*
|
|
21045
|
+
* Defaults — `channel: 0`, `profile: "sub"` — match a single-lens standalone
|
|
21046
|
+
* camera. **For NVR/Hub child cameras you must pass the channel explicitly**,
|
|
21047
|
+
* otherwise the substream opens on channel 0 and never sees the AI boxes for
|
|
21048
|
+
* the other channels. The `sub` profile is recommended (lighter bandwidth)
|
|
21049
|
+
* but `main` / `ext` are accepted if you specifically need detections off a
|
|
21050
|
+
* different feed.
|
|
21043
21051
|
*
|
|
21044
21052
|
* Each event carries normalized `[0, 1]` box coordinates, a class label, and
|
|
21045
21053
|
* a confidence score — render-ready without further conversion.
|
|
21046
21054
|
*/
|
|
21047
|
-
async onObjectDetections(callback) {
|
|
21048
|
-
|
|
21055
|
+
async onObjectDetections(callback, options) {
|
|
21056
|
+
const channel = options?.channel ?? 0;
|
|
21057
|
+
const profile = options?.profile ?? "sub";
|
|
21058
|
+
const key = this.objectDetectionKey(channel, profile);
|
|
21059
|
+
let entry = this.objectDetectionSubs.get(key);
|
|
21060
|
+
if (!entry) {
|
|
21061
|
+
entry = { channel, profile, listeners: /* @__PURE__ */ new Set() };
|
|
21062
|
+
this.objectDetectionSubs.set(key, entry);
|
|
21063
|
+
}
|
|
21064
|
+
entry.listeners.add(callback);
|
|
21049
21065
|
this.logger.debug?.(
|
|
21050
|
-
`[ReolinkBaichuanApi] onObjectDetections: registering listener (total=${
|
|
21066
|
+
`[ReolinkBaichuanApi] onObjectDetections: registering listener for ch${channel}/${profile} (total=${entry.listeners.size})`
|
|
21051
21067
|
);
|
|
21052
|
-
await this.ensureObjectDetectionStream();
|
|
21068
|
+
await this.ensureObjectDetectionStream(key);
|
|
21053
21069
|
}
|
|
21054
21070
|
/**
|
|
21055
|
-
* Remove
|
|
21056
|
-
*
|
|
21071
|
+
* Remove a detection callback for a given `(channel, profile)` tuple — or,
|
|
21072
|
+
* if `options` is omitted, remove the callback from every active tuple. When
|
|
21073
|
+
* `callback` is also omitted, every listener on the targeted tuples is
|
|
21074
|
+
* cleared. The auto-managed substream of a tuple is closed when its last
|
|
21075
|
+
* listener is removed.
|
|
21057
21076
|
*/
|
|
21058
|
-
async offObjectDetections(callback) {
|
|
21059
|
-
|
|
21060
|
-
this.
|
|
21061
|
-
|
|
21062
|
-
|
|
21063
|
-
|
|
21064
|
-
|
|
21065
|
-
|
|
21077
|
+
async offObjectDetections(callback, options) {
|
|
21078
|
+
const targetKeys = options ? [
|
|
21079
|
+
this.objectDetectionKey(
|
|
21080
|
+
options.channel ?? 0,
|
|
21081
|
+
options.profile ?? "sub"
|
|
21082
|
+
)
|
|
21083
|
+
] : [...this.objectDetectionSubs.keys()];
|
|
21084
|
+
for (const key of targetKeys) {
|
|
21085
|
+
const entry = this.objectDetectionSubs.get(key);
|
|
21086
|
+
if (!entry) continue;
|
|
21087
|
+
if (callback) {
|
|
21088
|
+
entry.listeners.delete(callback);
|
|
21089
|
+
} else {
|
|
21090
|
+
entry.listeners.clear();
|
|
21091
|
+
}
|
|
21092
|
+
if (entry.listeners.size === 0) {
|
|
21093
|
+
await this.tearDownObjectDetectionStream(key);
|
|
21094
|
+
}
|
|
21066
21095
|
}
|
|
21067
21096
|
}
|
|
21068
|
-
|
|
21069
|
-
|
|
21070
|
-
|
|
21071
|
-
|
|
21097
|
+
objectDetectionKey(channel, profile) {
|
|
21098
|
+
return `${channel}:${profile}`;
|
|
21099
|
+
}
|
|
21100
|
+
ensureObjectDetectionInternalListener() {
|
|
21101
|
+
if (this.objectDetectionInternalListener) return;
|
|
21102
|
+
const internal = (event) => {
|
|
21103
|
+
const key = this.objectDetectionKey(event.channel, event.profile);
|
|
21104
|
+
const entry = this.objectDetectionSubs.get(key);
|
|
21105
|
+
if (!entry || entry.listeners.size === 0) return;
|
|
21106
|
+
for (const cb of entry.listeners) {
|
|
21107
|
+
try {
|
|
21108
|
+
void Promise.resolve(cb(event)).catch((e) => {
|
|
21109
|
+
(this.logger.warn ?? this.logger.error).call(
|
|
21110
|
+
this.logger,
|
|
21111
|
+
"[ReolinkBaichuanApi] onObjectDetections handler error",
|
|
21112
|
+
formatErrorForLog(e)
|
|
21113
|
+
);
|
|
21114
|
+
});
|
|
21115
|
+
} catch (e) {
|
|
21116
|
+
(this.logger.warn ?? this.logger.error).call(
|
|
21117
|
+
this.logger,
|
|
21118
|
+
"[ReolinkBaichuanApi] onObjectDetections handler error",
|
|
21119
|
+
formatErrorForLog(e)
|
|
21120
|
+
);
|
|
21121
|
+
}
|
|
21122
|
+
}
|
|
21123
|
+
};
|
|
21124
|
+
this.objectDetectionInternalListener = internal;
|
|
21125
|
+
this.detectionEventListeners.add(internal);
|
|
21126
|
+
}
|
|
21127
|
+
maybeDropObjectDetectionInternalListener() {
|
|
21128
|
+
if (this.objectDetectionSubs.size > 0) return;
|
|
21129
|
+
if (!this.objectDetectionInternalListener) return;
|
|
21130
|
+
this.detectionEventListeners.delete(this.objectDetectionInternalListener);
|
|
21131
|
+
this.objectDetectionInternalListener = void 0;
|
|
21132
|
+
}
|
|
21133
|
+
async ensureObjectDetectionStream(key) {
|
|
21134
|
+
const entry = this.objectDetectionSubs.get(key);
|
|
21135
|
+
if (!entry) return;
|
|
21136
|
+
if (entry.stream) return;
|
|
21137
|
+
if (entry.startInFlight) {
|
|
21138
|
+
await entry.startInFlight;
|
|
21072
21139
|
return;
|
|
21073
21140
|
}
|
|
21074
|
-
|
|
21141
|
+
entry.startInFlight = (async () => {
|
|
21075
21142
|
const { BaichuanVideoStream: BaichuanVideoStream2 } = await Promise.resolve().then(() => (init_BaichuanVideoStream(), BaichuanVideoStream_exports));
|
|
21076
|
-
const sessionKey = `live:object-detections:
|
|
21143
|
+
const sessionKey = `live:object-detections:ch${entry.channel}:${entry.profile}`;
|
|
21077
21144
|
const dedicated = await this.createDedicatedSession(sessionKey);
|
|
21078
21145
|
const stream = new BaichuanVideoStream2({
|
|
21079
21146
|
client: dedicated.client,
|
|
21080
21147
|
api: this,
|
|
21081
|
-
channel:
|
|
21082
|
-
profile:
|
|
21148
|
+
channel: entry.channel,
|
|
21149
|
+
profile: entry.profile,
|
|
21083
21150
|
logger: this.logger
|
|
21084
21151
|
});
|
|
21085
|
-
this.
|
|
21086
|
-
for (const cb of this.objectDetectionListeners) {
|
|
21087
|
-
try {
|
|
21088
|
-
void Promise.resolve(cb(event)).catch((e) => {
|
|
21089
|
-
(this.logger.warn ?? this.logger.error).call(
|
|
21090
|
-
this.logger,
|
|
21091
|
-
"[ReolinkBaichuanApi] onObjectDetections handler error",
|
|
21092
|
-
formatErrorForLog(e)
|
|
21093
|
-
);
|
|
21094
|
-
});
|
|
21095
|
-
} catch (e) {
|
|
21096
|
-
(this.logger.warn ?? this.logger.error).call(
|
|
21097
|
-
this.logger,
|
|
21098
|
-
"[ReolinkBaichuanApi] onObjectDetections handler error",
|
|
21099
|
-
formatErrorForLog(e)
|
|
21100
|
-
);
|
|
21101
|
-
}
|
|
21102
|
-
}
|
|
21103
|
-
};
|
|
21104
|
-
this.detectionEventListeners.add(this.objectDetectionInternalListener);
|
|
21152
|
+
this.ensureObjectDetectionInternalListener();
|
|
21105
21153
|
try {
|
|
21106
21154
|
await stream.start();
|
|
21107
21155
|
} catch (e) {
|
|
21108
|
-
if (this.objectDetectionInternalListener) {
|
|
21109
|
-
this.detectionEventListeners.delete(
|
|
21110
|
-
this.objectDetectionInternalListener
|
|
21111
|
-
);
|
|
21112
|
-
this.objectDetectionInternalListener = void 0;
|
|
21113
|
-
}
|
|
21114
21156
|
await dedicated.release().catch(() => {
|
|
21115
21157
|
});
|
|
21158
|
+
this.maybeDropObjectDetectionInternalListener();
|
|
21116
21159
|
throw e;
|
|
21117
21160
|
}
|
|
21118
|
-
|
|
21161
|
+
entry.stream = {
|
|
21119
21162
|
stop: () => stream.stop(),
|
|
21120
21163
|
release: () => dedicated.release()
|
|
21121
21164
|
};
|
|
@@ -21124,35 +21167,36 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
|
|
|
21124
21167
|
);
|
|
21125
21168
|
})();
|
|
21126
21169
|
try {
|
|
21127
|
-
await
|
|
21170
|
+
await entry.startInFlight;
|
|
21128
21171
|
} finally {
|
|
21129
|
-
|
|
21172
|
+
delete entry.startInFlight;
|
|
21130
21173
|
}
|
|
21131
21174
|
}
|
|
21132
|
-
async tearDownObjectDetectionStream() {
|
|
21133
|
-
const
|
|
21134
|
-
|
|
21135
|
-
|
|
21136
|
-
|
|
21137
|
-
|
|
21138
|
-
|
|
21139
|
-
|
|
21140
|
-
|
|
21141
|
-
|
|
21142
|
-
|
|
21143
|
-
|
|
21144
|
-
|
|
21145
|
-
|
|
21146
|
-
|
|
21147
|
-
|
|
21148
|
-
|
|
21149
|
-
|
|
21150
|
-
|
|
21151
|
-
|
|
21152
|
-
|
|
21175
|
+
async tearDownObjectDetectionStream(key) {
|
|
21176
|
+
const entry = this.objectDetectionSubs.get(key);
|
|
21177
|
+
if (!entry) return;
|
|
21178
|
+
const handle = entry.stream;
|
|
21179
|
+
delete entry.stream;
|
|
21180
|
+
this.objectDetectionSubs.delete(key);
|
|
21181
|
+
if (handle) {
|
|
21182
|
+
try {
|
|
21183
|
+
await handle.stop();
|
|
21184
|
+
} catch (e) {
|
|
21185
|
+
this.logger.debug?.(
|
|
21186
|
+
`[ReolinkBaichuanApi] onObjectDetections: stream stop error (key=${key}): ${formatErrorForLog(e)}`
|
|
21187
|
+
);
|
|
21188
|
+
}
|
|
21189
|
+
try {
|
|
21190
|
+
await handle.release();
|
|
21191
|
+
} catch (e) {
|
|
21192
|
+
this.logger.debug?.(
|
|
21193
|
+
`[ReolinkBaichuanApi] onObjectDetections: session release error (key=${key}): ${formatErrorForLog(e)}`
|
|
21194
|
+
);
|
|
21195
|
+
}
|
|
21153
21196
|
}
|
|
21197
|
+
this.maybeDropObjectDetectionInternalListener();
|
|
21154
21198
|
this.logger.debug?.(
|
|
21155
|
-
`[ReolinkBaichuanApi] onObjectDetections: substream torn down`
|
|
21199
|
+
`[ReolinkBaichuanApi] onObjectDetections: substream torn down (key=${key})`
|
|
21156
21200
|
);
|
|
21157
21201
|
}
|
|
21158
21202
|
/**
|
|
@@ -21585,9 +21629,10 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
|
|
|
21585
21629
|
this.stopUdpSleepInference();
|
|
21586
21630
|
this.stopSimpleEventWatchdog();
|
|
21587
21631
|
this.stopSimpleEventResubscribeTimer();
|
|
21588
|
-
this.
|
|
21589
|
-
|
|
21590
|
-
|
|
21632
|
+
for (const key of [...this.objectDetectionSubs.keys()]) {
|
|
21633
|
+
await this.tearDownObjectDetectionStream(key).catch(() => {
|
|
21634
|
+
});
|
|
21635
|
+
}
|
|
21591
21636
|
await this.cleanup();
|
|
21592
21637
|
await this.stopAllActiveStreams();
|
|
21593
21638
|
await this.cleanupSocketPool();
|
|
@@ -28068,6 +28113,7 @@ ${xml}`
|
|
|
28068
28113
|
async setAutoFocus(channel, disable, options) {
|
|
28069
28114
|
const ch = this.normalizeChannel(channel);
|
|
28070
28115
|
const disableVal = disable ? 1 : 0;
|
|
28116
|
+
const extensionXml = buildChannelExtensionXml(ch);
|
|
28071
28117
|
const payloadXml = `<?xml version="1.0" encoding="UTF-8" ?>
|
|
28072
28118
|
<body>
|
|
28073
28119
|
<AutoFocus version="1.1">
|
|
@@ -28078,6 +28124,7 @@ ${xml}`
|
|
|
28078
28124
|
await this.sendXml({
|
|
28079
28125
|
cmdId: BC_CMD_ID_SET_AUTO_FOCUS,
|
|
28080
28126
|
channel: ch,
|
|
28127
|
+
extensionXml,
|
|
28081
28128
|
payloadXml,
|
|
28082
28129
|
...options?.timeoutMs != null ? { timeoutMs: options.timeoutMs } : {}
|
|
28083
28130
|
});
|