@apocaliss92/nodelink-js 0.6.5 → 0.6.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.
- package/dist/{chunk-WQ2TQCYP.js → chunk-T22QCNBR.js} +114 -28
- package/dist/chunk-T22QCNBR.js.map +1 -0
- package/dist/cli/rtsp-server.cjs +113 -27
- package/dist/cli/rtsp-server.cjs.map +1 -1
- package/dist/cli/rtsp-server.js +1 -1
- package/dist/index.cjs +135 -854
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -196
- package/dist/index.d.ts +10 -175
- package/dist/index.js +21 -823
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-WQ2TQCYP.js.map +0 -1
|
@@ -6433,6 +6433,38 @@ function createRtspFlow(transport, videoType) {
|
|
|
6433
6433
|
return new H265Flow(transport);
|
|
6434
6434
|
}
|
|
6435
6435
|
|
|
6436
|
+
// src/baichuan/stream/rtpVideoTimestamp.ts
|
|
6437
|
+
var U32 = 4294967296;
|
|
6438
|
+
var DEFAULT_VIDEO_CLOCK_RATE = 9e4;
|
|
6439
|
+
function deriveRtpVideoTimestamp(state, frameMicroseconds, clockRate = DEFAULT_VIDEO_CLOCK_RATE) {
|
|
6440
|
+
if (frameMicroseconds === null || frameMicroseconds === void 0 || !Number.isFinite(frameMicroseconds)) {
|
|
6441
|
+
return { timestamp: state.timestamp, state };
|
|
6442
|
+
}
|
|
6443
|
+
const curRaw = frameMicroseconds >>> 0;
|
|
6444
|
+
if (state.baseUnwrappedUs === void 0) {
|
|
6445
|
+
return {
|
|
6446
|
+
timestamp: state.timestamp,
|
|
6447
|
+
state: {
|
|
6448
|
+
...state,
|
|
6449
|
+
unwrappedUs: curRaw,
|
|
6450
|
+
lastRawUs: curRaw,
|
|
6451
|
+
baseUnwrappedUs: curRaw,
|
|
6452
|
+
baseTimestamp: state.timestamp
|
|
6453
|
+
}
|
|
6454
|
+
};
|
|
6455
|
+
}
|
|
6456
|
+
const lastRaw = state.lastRawUs ?? curRaw;
|
|
6457
|
+
let forwardDelta = curRaw - lastRaw >>> 0;
|
|
6458
|
+
if (forwardDelta > U32 / 2) forwardDelta = 0;
|
|
6459
|
+
const unwrappedUs = (state.unwrappedUs ?? curRaw) + forwardDelta;
|
|
6460
|
+
const deltaUs = unwrappedUs - state.baseUnwrappedUs;
|
|
6461
|
+
const timestamp = state.baseTimestamp + Math.round(deltaUs * clockRate / 1e6) >>> 0;
|
|
6462
|
+
return {
|
|
6463
|
+
timestamp,
|
|
6464
|
+
state: { ...state, unwrappedUs, lastRawUs: curRaw, timestamp }
|
|
6465
|
+
};
|
|
6466
|
+
}
|
|
6467
|
+
|
|
6436
6468
|
// src/baichuan/stream/BaichuanRtspServer.ts
|
|
6437
6469
|
var AsyncBoundedQueue = class {
|
|
6438
6470
|
maxItems;
|
|
@@ -7005,7 +7037,10 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends EventEmitter4 {
|
|
|
7005
7037
|
let useTcpInterleaved = false;
|
|
7006
7038
|
let clientUdpSocket = null;
|
|
7007
7039
|
let clientUdpSocketAudio = null;
|
|
7040
|
+
let cleanedUp = false;
|
|
7008
7041
|
const cleanup = () => {
|
|
7042
|
+
if (cleanedUp) return;
|
|
7043
|
+
cleanedUp = true;
|
|
7009
7044
|
const sessionDurationMs = Date.now() - connectTime;
|
|
7010
7045
|
const res = this.clientResources.get(clientId);
|
|
7011
7046
|
const framesSent = res?.framesSent ?? 0;
|
|
@@ -7753,22 +7788,25 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends EventEmitter4 {
|
|
|
7753
7788
|
resources.rtpVideoTimestamp = 0;
|
|
7754
7789
|
if (resources.rtpVideoBaseTimestamp === void 0)
|
|
7755
7790
|
resources.rtpVideoBaseTimestamp = resources.rtpVideoTimestamp;
|
|
7756
|
-
|
|
7791
|
+
const { timestamp, state } = deriveRtpVideoTimestamp(
|
|
7792
|
+
{
|
|
7793
|
+
timestamp: resources.rtpVideoTimestamp,
|
|
7794
|
+
baseTimestamp: resources.rtpVideoBaseTimestamp,
|
|
7795
|
+
unwrappedUs: resources.rtpVideoUnwrappedUs,
|
|
7796
|
+
lastRawUs: resources.rtpVideoLastRawUs,
|
|
7797
|
+
baseUnwrappedUs: resources.rtpVideoBaseUnwrappedUs
|
|
7798
|
+
},
|
|
7799
|
+
frameMicroseconds,
|
|
7800
|
+
videoClockRate
|
|
7801
|
+
);
|
|
7802
|
+
resources.rtpVideoTimestamp = timestamp;
|
|
7803
|
+
resources.rtpVideoBaseTimestamp = state.baseTimestamp;
|
|
7804
|
+
resources.rtpVideoUnwrappedUs = state.unwrappedUs;
|
|
7805
|
+
resources.rtpVideoLastRawUs = state.lastRawUs;
|
|
7806
|
+
resources.rtpVideoBaseUnwrappedUs = state.baseUnwrappedUs;
|
|
7807
|
+
resources.rtpVideoLastTimestamp = timestamp;
|
|
7808
|
+
if (resources.rtpVideoBaseMicroseconds === void 0)
|
|
7757
7809
|
resources.rtpVideoBaseMicroseconds = frameMicroseconds >>> 0;
|
|
7758
|
-
resources.rtpVideoLastTimestamp = resources.rtpVideoTimestamp;
|
|
7759
|
-
return;
|
|
7760
|
-
}
|
|
7761
|
-
const baseUs = resources.rtpVideoBaseMicroseconds >>> 0;
|
|
7762
|
-
const curUs = frameMicroseconds >>> 0;
|
|
7763
|
-
const deltaUs = curUs - baseUs >>> 0;
|
|
7764
|
-
const baseTs = (resources.rtpVideoBaseTimestamp ?? 0) >>> 0;
|
|
7765
|
-
let ts = baseTs + Math.round(deltaUs * videoClockRate / 1e6) >>> 0;
|
|
7766
|
-
const last = resources.rtpVideoLastTimestamp;
|
|
7767
|
-
if (last !== void 0 && ts <= last >>> 0) {
|
|
7768
|
-
ts = (last >>> 0) + 1 >>> 0;
|
|
7769
|
-
}
|
|
7770
|
-
resources.rtpVideoTimestamp = ts;
|
|
7771
|
-
resources.rtpVideoLastTimestamp = ts;
|
|
7772
7810
|
};
|
|
7773
7811
|
const sendVideoAccessUnit = (videoType, accessUnitAnnexB, advanceTimestamp = true) => {
|
|
7774
7812
|
const nals = _BaichuanRtspServer.splitAnnexBNals(accessUnitAnnexB);
|
|
@@ -9905,6 +9943,30 @@ function buildSetNtpXml(current, patch) {
|
|
|
9905
9943
|
);
|
|
9906
9944
|
}
|
|
9907
9945
|
|
|
9946
|
+
// src/reolink/baichuan/utils/channelEnumeration.ts
|
|
9947
|
+
async function resolveBaichuanChannels(deps) {
|
|
9948
|
+
const fromPush = dedupeSorted(deps.pushChannels);
|
|
9949
|
+
if (fromPush.length > 0) return fromPush;
|
|
9950
|
+
const slots = dedupeSorted(deps.supportChnIds);
|
|
9951
|
+
const candidates = slots.length > 0 ? slots : [0];
|
|
9952
|
+
const probed = await Promise.all(
|
|
9953
|
+
candidates.map(
|
|
9954
|
+
async (channel) => await deps.probe(channel) ? channel : void 0
|
|
9955
|
+
)
|
|
9956
|
+
);
|
|
9957
|
+
return dedupeSorted(
|
|
9958
|
+
probed.filter((c) => c !== void 0)
|
|
9959
|
+
);
|
|
9960
|
+
}
|
|
9961
|
+
function dedupeSorted(values) {
|
|
9962
|
+
const set = /* @__PURE__ */ new Set();
|
|
9963
|
+
for (const v of values) {
|
|
9964
|
+
const n = Number(v);
|
|
9965
|
+
if (Number.isFinite(n) && n >= 0) set.add(n);
|
|
9966
|
+
}
|
|
9967
|
+
return [...set].sort((a, b) => a - b);
|
|
9968
|
+
}
|
|
9969
|
+
|
|
9908
9970
|
// src/reolink/baichuan/utils/dst.ts
|
|
9909
9971
|
var parseNumberSafe3 = (text) => {
|
|
9910
9972
|
if (text === void 0) return void 0;
|
|
@@ -15598,13 +15660,21 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
|
|
|
15598
15660
|
* @param options.source - Data source for the channel list (default: `"cgi"`):
|
|
15599
15661
|
* - `"cgi"`: Uses HTTP `GetChannelstatus` — returns the channel list immediately,
|
|
15600
15662
|
* no dependency on async push messages. Recommended for first-call discovery.
|
|
15601
|
-
* - `"baichuan"`:
|
|
15602
|
-
*
|
|
15603
|
-
*
|
|
15604
|
-
*
|
|
15663
|
+
* - `"baichuan"`: HTTP-free discovery. Prefers the cmd_id 145 push cache when
|
|
15664
|
+
* populated; otherwise actively probes the channel slots advertised by Support
|
|
15665
|
+
* (`items[].chnID`) via `getInfo`. Use this for hubs with HTTP disabled.
|
|
15666
|
+
*
|
|
15667
|
+
* When the api was constructed with `nativeOnly`, the source is forced to
|
|
15668
|
+
* `"baichuan"` regardless of this option (no HTTP/CGI is ever attempted).
|
|
15605
15669
|
*/
|
|
15606
15670
|
async getNvrChannelsSummary(options) {
|
|
15607
|
-
const source = options?.source ?? "cgi";
|
|
15671
|
+
const source = this.nativeOnly ? "baichuan" : options?.source ?? "cgi";
|
|
15672
|
+
const support = await this.getSupportInfo().catch(() => {
|
|
15673
|
+
this.logger.error?.(
|
|
15674
|
+
"[ReolinkBaichuanApi] getNvrChannelsSummary: failed to get support info"
|
|
15675
|
+
);
|
|
15676
|
+
return void 0;
|
|
15677
|
+
});
|
|
15608
15678
|
let channels;
|
|
15609
15679
|
const cgiStatusByChannel = /* @__PURE__ */ new Map();
|
|
15610
15680
|
if (options?.channels?.length) {
|
|
@@ -15634,15 +15704,31 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
|
|
|
15634
15704
|
channels = [];
|
|
15635
15705
|
}
|
|
15636
15706
|
} else {
|
|
15637
|
-
const
|
|
15638
|
-
|
|
15707
|
+
const pushChannels = Array.from(
|
|
15708
|
+
this.getChannelInfoFromPushCache().keys()
|
|
15709
|
+
).map((c) => Number(c)).filter((n) => Number.isFinite(n));
|
|
15710
|
+
const supportChnIds = (support?.items ?? []).map((i) => Number(i.chnID)).filter((n) => Number.isFinite(n));
|
|
15711
|
+
const probeTimeoutMs = options?.timeoutMs ?? 2500;
|
|
15712
|
+
channels = await resolveBaichuanChannels({
|
|
15713
|
+
pushChannels,
|
|
15714
|
+
supportChnIds,
|
|
15715
|
+
probe: async (channel) => {
|
|
15716
|
+
try {
|
|
15717
|
+
await this.getInfo(channel, {
|
|
15718
|
+
timeoutMs: probeTimeoutMs,
|
|
15719
|
+
tags: ["type", "name"]
|
|
15720
|
+
});
|
|
15721
|
+
return true;
|
|
15722
|
+
} catch {
|
|
15723
|
+
return false;
|
|
15724
|
+
}
|
|
15725
|
+
}
|
|
15726
|
+
});
|
|
15727
|
+
this.logger.debug?.(
|
|
15728
|
+
`[ReolinkBaichuanApi] getNvrChannelsSummary: baichuan resolved ${channels.length} channel(s): [${channels.join(", ")}]`
|
|
15729
|
+
);
|
|
15639
15730
|
}
|
|
15640
15731
|
channels = channels.sort((a, b) => a - b);
|
|
15641
|
-
const support = await this.getSupportInfo().catch(() => {
|
|
15642
|
-
this.logger.error?.(
|
|
15643
|
-
"[ReolinkBaichuanApi] getNvrChannelsSummary: failed to get support info"
|
|
15644
|
-
);
|
|
15645
|
-
});
|
|
15646
15732
|
const truthyNumberLike = (v) => {
|
|
15647
15733
|
if (typeof v === "number") return v > 0;
|
|
15648
15734
|
if (typeof v === "string") {
|
|
@@ -26004,4 +26090,4 @@ export {
|
|
|
26004
26090
|
tcpReachabilityProbe,
|
|
26005
26091
|
autoDetectDeviceType
|
|
26006
26092
|
};
|
|
26007
|
-
//# sourceMappingURL=chunk-
|
|
26093
|
+
//# sourceMappingURL=chunk-T22QCNBR.js.map
|