@apocaliss92/nodelink-js 0.3.9 → 0.4.1

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.
@@ -3,10 +3,10 @@ import {
3
3
  BaichuanRtspServer,
4
4
  ReolinkBaichuanApi,
5
5
  autoDetectDeviceType
6
- } from "../chunk-OGIKBDON.js";
6
+ } from "../chunk-SDRNJQ5U.js";
7
7
  import {
8
8
  __require
9
- } from "../chunk-6Q6MK4WG.js";
9
+ } from "../chunk-DUHWTZ7U.js";
10
10
 
11
11
  // src/cli/rtsp-server.ts
12
12
  function parseArgs() {
package/dist/index.cjs CHANGED
@@ -3108,11 +3108,13 @@ __export(DiagnosticsTools_exports, {
3108
3108
  collectMultifocalDiagnostics: () => collectMultifocalDiagnostics,
3109
3109
  collectNativeDiagnostics: () => collectNativeDiagnostics,
3110
3110
  collectNvrDiagnostics: () => collectNvrDiagnostics,
3111
+ computeExpectedStreamCompatibility: () => computeExpectedStreamCompatibility,
3111
3112
  createDiagnosticsBundle: () => createDiagnosticsBundle,
3112
3113
  printNvrDiagnostics: () => printNvrDiagnostics,
3113
3114
  runAllDiagnosticsConsecutively: () => runAllDiagnosticsConsecutively,
3114
3115
  runMultifocalDiagnosticsConsecutively: () => runMultifocalDiagnosticsConsecutively,
3115
3116
  sampleStreams: () => sampleStreams,
3117
+ sanitizeFixtureData: () => sanitizeFixtureData,
3116
3118
  testChannelStreams: () => testChannelStreams
3117
3119
  });
3118
3120
  function safeStringifyError(error) {
@@ -5404,10 +5406,102 @@ async function runAllDiagnosticsConsecutively(params) {
5404
5406
  streamsDir
5405
5407
  };
5406
5408
  }
5409
+ function maskIp(ip) {
5410
+ const parts = ip.split(".");
5411
+ return `${parts[0]}.***.***.***`;
5412
+ }
5413
+ function maskMac(mac) {
5414
+ const sep = mac.includes("-") ? "-" : ":";
5415
+ const parts = mac.split(/[:-]/);
5416
+ return `${parts[0]}${sep}${parts[1]}${sep}**${sep}**${sep}**${sep}**`;
5417
+ }
5418
+ function maskSerial(val) {
5419
+ if (val.length <= 4) return "****";
5420
+ return val.slice(0, 2) + "*".repeat(val.length - 4) + val.slice(-2);
5421
+ }
5422
+ function sanitizeString(s) {
5423
+ let out = s;
5424
+ out = out.replace(/:\/\/([^:@]+):([^@]+)@/g, "://***:***@");
5425
+ out = out.replace(/(password=)[^&\s]*/gi, "$1***");
5426
+ out = out.replace(/(user=)[^&\s]*/gi, "$1***");
5427
+ out = out.replace(IPV4_RE, (match) => maskIp(match));
5428
+ out = out.replace(MAC_RE, (match) => maskMac(match));
5429
+ return out;
5430
+ }
5431
+ function sanitizeFixtureData(value) {
5432
+ if (value === null || value === void 0) return value;
5433
+ if (typeof value === "string") {
5434
+ return sanitizeString(value);
5435
+ }
5436
+ if (Array.isArray(value)) {
5437
+ return value.map(sanitizeFixtureData);
5438
+ }
5439
+ if (typeof value === "object") {
5440
+ const out = {};
5441
+ for (const [k, v] of Object.entries(value)) {
5442
+ const kLower = k.toLowerCase();
5443
+ if (REDACT_KEYS.has(kLower)) {
5444
+ out[k] = "***";
5445
+ } else if (MASK_KEYS.has(kLower) || kLower === "serialnumber") {
5446
+ out[k] = typeof v === "string" ? maskSerial(v) : "***";
5447
+ } else if (kLower === "mac") {
5448
+ out[k] = typeof v === "string" ? maskMac(v) : "***";
5449
+ } else if (kLower === "ip" || kLower === "ipaddress" || kLower === "host") {
5450
+ out[k] = typeof v === "string" ? maskIp(v) : v;
5451
+ } else if (kLower === "name" && typeof v === "string" && k !== "name") {
5452
+ out[k] = v;
5453
+ } else {
5454
+ out[k] = sanitizeFixtureData(v);
5455
+ }
5456
+ }
5457
+ return out;
5458
+ }
5459
+ return value;
5460
+ }
5461
+ function computeExpectedStreamCompatibility(params) {
5462
+ const { channelCount } = params;
5463
+ const profiles = params.profiles ?? ["main", "sub", "ext"];
5464
+ const expectedStreamType = { main: 0, sub: 1, ext: 0 };
5465
+ const allStreams = [];
5466
+ for (let ch = 0; ch < channelCount; ch++) {
5467
+ for (const p of profiles) {
5468
+ allStreams.push({ ch, profile: p, label: channelCount > 1 ? `ch${ch}_${p}` : p });
5469
+ }
5470
+ }
5471
+ const results = [];
5472
+ for (let i = 0; i < allStreams.length; i++) {
5473
+ for (let j = i + 1; j < allStreams.length; j++) {
5474
+ const a = allStreams[i];
5475
+ const b = allStreams[j];
5476
+ const stA = expectedStreamType[a.profile] ?? 0;
5477
+ const stB = expectedStreamType[b.profile] ?? 0;
5478
+ const sameChannel = a.ch === b.ch;
5479
+ let expectedOk;
5480
+ let reason;
5481
+ if (sameChannel && stA === stB) {
5482
+ expectedOk = false;
5483
+ reason = `same streamType (${stA}) on same channel`;
5484
+ } else if (!sameChannel && a.profile === b.profile) {
5485
+ expectedOk = false;
5486
+ reason = `multifocal rejects same profile (${a.profile}) across channels`;
5487
+ } else if (!sameChannel && stA === stB) {
5488
+ expectedOk = false;
5489
+ reason = `same streamType (${stA}) across channels`;
5490
+ } else {
5491
+ expectedOk = true;
5492
+ reason = `different streamTypes (${stA} vs ${stB})`;
5493
+ }
5494
+ results.push({ pair: [a.label, b.label], expectedOk, reason });
5495
+ }
5496
+ }
5497
+ return results;
5498
+ }
5407
5499
  async function captureModelFixtures(params) {
5408
5500
  const { api, channel, outDir } = params;
5409
5501
  const log = params.log ?? console.log;
5410
5502
  mkdirp(outDir);
5503
+ const writeJsonSafe = (filePath, data) => writeJson(filePath, sanitizeFixtureData(data));
5504
+ const writeTextSafe = (filePath, text) => writeText(filePath, sanitizeString(text));
5411
5505
  const calls = {};
5412
5506
  const errors = [];
5413
5507
  async function capture(name, fn, writer) {
@@ -5430,123 +5524,269 @@ async function captureModelFixtures(params) {
5430
5524
  const info = await capture(
5431
5525
  "getInfo",
5432
5526
  () => api.getInfo(channel),
5433
- (v) => writeJson(path4.join(outDir, "device-info.json"), v)
5527
+ (v) => writeJsonSafe(path4.join(outDir, "device-info.json"), v)
5434
5528
  );
5435
5529
  const support = await capture(
5436
5530
  "getSupportInfo",
5437
5531
  () => api.getSupportInfo(),
5438
- (v) => writeJson(path4.join(outDir, "support-info.json"), v)
5532
+ (v) => writeJsonSafe(path4.join(outDir, "support-info.json"), v)
5439
5533
  );
5440
5534
  const abilities = await capture(
5441
5535
  "getAbilityInfo",
5442
5536
  () => api.getAbilityInfo(),
5443
- (v) => writeJson(path4.join(outDir, "ability-info.json"), v)
5537
+ (v) => writeJsonSafe(path4.join(outDir, "ability-info.json"), v)
5444
5538
  );
5445
5539
  await capture(
5446
5540
  "getDeviceCapabilities",
5447
5541
  () => api.getDeviceCapabilities(channel),
5448
- (v) => writeJson(path4.join(outDir, "capabilities.json"), v)
5542
+ (v) => writeJsonSafe(path4.join(outDir, "capabilities.json"), v)
5449
5543
  );
5450
5544
  await capture("cmd289-WhiteLed", () => api.sendXml({
5451
5545
  cmdId: BC_CMD_ID_GET_WHITE_LED,
5452
5546
  channel,
5453
5547
  timeoutMs: 3e3
5454
- }), (v) => writeText(path4.join(outDir, "cmd289-white-led.xml"), v));
5548
+ }), (v) => writeTextSafe(path4.join(outDir, "cmd289-white-led.xml"), v));
5455
5549
  await capture(
5456
5550
  "getStreamMetadata",
5457
5551
  () => api.getStreamMetadata(channel),
5458
- (v) => writeJson(path4.join(outDir, "stream-metadata.json"), v)
5552
+ (v) => writeJsonSafe(path4.join(outDir, "stream-metadata.json"), v)
5459
5553
  );
5460
5554
  await capture(
5461
5555
  "getEncXml",
5462
5556
  () => api.getEncXml(channel),
5463
- (v) => writeText(path4.join(outDir, "enc-config.xml"), v)
5557
+ (v) => writeTextSafe(path4.join(outDir, "enc-config.xml"), v)
5464
5558
  );
5465
5559
  await capture(
5466
5560
  "getPorts",
5467
5561
  () => api.getPorts(),
5468
- (v) => writeJson(path4.join(outDir, "ports.json"), v)
5562
+ (v) => writeJsonSafe(path4.join(outDir, "ports.json"), v)
5469
5563
  );
5470
5564
  await capture(
5471
5565
  "getTalkAbility",
5472
5566
  () => api.getTalkAbility(channel),
5473
- (v) => writeJson(path4.join(outDir, "talk-ability.json"), v)
5567
+ (v) => writeJsonSafe(path4.join(outDir, "talk-ability.json"), v)
5474
5568
  );
5475
5569
  await capture(
5476
5570
  "getTwoWayAudioConfig",
5477
5571
  () => api.getTwoWayAudioConfig(channel),
5478
- (v) => writeJson(path4.join(outDir, "two-way-audio-config.json"), v)
5572
+ (v) => writeJsonSafe(path4.join(outDir, "two-way-audio-config.json"), v)
5479
5573
  );
5480
5574
  await capture(
5481
5575
  "getAiState",
5482
5576
  () => api.getAiState(channel),
5483
- (v) => writeJson(path4.join(outDir, "ai-state.json"), v)
5577
+ (v) => writeJsonSafe(path4.join(outDir, "ai-state.json"), v)
5484
5578
  );
5485
5579
  await capture(
5486
5580
  "getAiCfg",
5487
5581
  () => api.getAiCfg(channel),
5488
- (v) => writeJson(path4.join(outDir, "ai-cfg.json"), v)
5582
+ (v) => writeJsonSafe(path4.join(outDir, "ai-cfg.json"), v)
5489
5583
  );
5490
5584
  await capture(
5491
5585
  "getOsd",
5492
5586
  () => api.getOsd(channel),
5493
- (v) => writeJson(path4.join(outDir, "osd.json"), v)
5587
+ (v) => writeJsonSafe(path4.join(outDir, "osd.json"), v)
5494
5588
  );
5495
5589
  await capture(
5496
5590
  "getMotionAlarm",
5497
5591
  () => api.getMotionAlarm(channel),
5498
- (v) => writeJson(path4.join(outDir, "motion-alarm.json"), v)
5592
+ (v) => writeJsonSafe(path4.join(outDir, "motion-alarm.json"), v)
5499
5593
  );
5500
5594
  await capture(
5501
5595
  "getRecordCfg",
5502
5596
  () => api.getRecordCfg(channel),
5503
- (v) => writeJson(path4.join(outDir, "record-cfg.json"), v)
5597
+ (v) => writeJsonSafe(path4.join(outDir, "record-cfg.json"), v)
5504
5598
  );
5505
5599
  await capture(
5506
5600
  "getVideoInput",
5507
5601
  () => api.getVideoInput(channel),
5508
- (v) => writeJson(path4.join(outDir, "video-input.json"), v)
5602
+ (v) => writeJsonSafe(path4.join(outDir, "video-input.json"), v)
5509
5603
  );
5510
5604
  await capture(
5511
5605
  "getPtzPresets",
5512
5606
  () => api.getPtzPresets(channel),
5513
- (v) => writeJson(path4.join(outDir, "ptz-presets.json"), v)
5607
+ (v) => writeJsonSafe(path4.join(outDir, "ptz-presets.json"), v)
5514
5608
  );
5515
5609
  await capture(
5516
5610
  "getNetworkInfo",
5517
5611
  () => api.getNetworkInfo(),
5518
- (v) => writeJson(path4.join(outDir, "network-info.json"), v)
5612
+ (v) => writeJsonSafe(path4.join(outDir, "network-info.json"), v)
5519
5613
  );
5520
5614
  await capture(
5521
5615
  "getSystemGeneral",
5522
5616
  () => api.getSystemGeneral(),
5523
- (v) => writeJson(path4.join(outDir, "system-general.json"), v)
5617
+ (v) => writeJsonSafe(path4.join(outDir, "system-general.json"), v)
5524
5618
  );
5525
5619
  await capture(
5526
5620
  "getWifiSignal",
5527
5621
  () => api.getWifiSignal(channel),
5528
- (v) => writeJson(path4.join(outDir, "wifi-signal.json"), v)
5622
+ (v) => writeJsonSafe(path4.join(outDir, "wifi-signal.json"), v)
5529
5623
  );
5530
5624
  await capture(
5531
5625
  "getWhiteLedState",
5532
5626
  () => api.getWhiteLedState(channel),
5533
- (v) => writeJson(path4.join(outDir, "white-led-state.json"), v)
5627
+ (v) => writeJsonSafe(path4.join(outDir, "white-led-state.json"), v)
5534
5628
  );
5535
5629
  await capture(
5536
5630
  "getFloodlightOnMotion",
5537
5631
  () => api.getFloodlightOnMotion(channel),
5538
- (v) => writeJson(path4.join(outDir, "floodlight-on-motion.json"), v)
5632
+ (v) => writeJsonSafe(path4.join(outDir, "floodlight-on-motion.json"), v)
5539
5633
  );
5540
5634
  await capture(
5541
5635
  "buildVideoStreamOptions",
5542
5636
  () => api.buildVideoStreamOptions({ channel }),
5543
- (v) => writeJson(path4.join(outDir, "video-stream-options.json"), v)
5637
+ (v) => writeJsonSafe(path4.join(outDir, "video-stream-options.json"), v)
5544
5638
  );
5639
+ await capture(
5640
+ "getDualLensChannelInfo",
5641
+ () => api.getDualLensChannelInfo(channel),
5642
+ (v) => writeJsonSafe(path4.join(outDir, "dual-lens-info.json"), v)
5643
+ );
5644
+ await capture("streamCombinationTest", async () => {
5645
+ let dualLensInfo;
5646
+ try {
5647
+ dualLensInfo = await api.getDualLensChannelInfo(channel);
5648
+ } catch {
5649
+ }
5650
+ const isMultifocal = dualLensInfo?.isDualLens === true;
5651
+ const channelCount = dualLensInfo?.streamChannelCount ?? 1;
5652
+ const allStreams = [];
5653
+ const profiles = ["main", "sub", "ext"];
5654
+ for (let ch = 0; ch < channelCount; ch++) {
5655
+ for (const p of profiles) {
5656
+ const label = channelCount > 1 ? `ch${ch}_${p}` : p;
5657
+ allStreams.push({ ch, profile: p, label });
5658
+ }
5659
+ }
5660
+ const pairs = [];
5661
+ for (let i = 0; i < allStreams.length; i++) {
5662
+ for (let j = i + 1; j < allStreams.length; j++) {
5663
+ pairs.push([allStreams[i], allStreams[j]]);
5664
+ }
5665
+ }
5666
+ const expectedStreamType = { main: 0, sub: 1, ext: 0 };
5667
+ const expectedCompat = [];
5668
+ for (const [a, b] of pairs) {
5669
+ const stA = expectedStreamType[a.profile];
5670
+ const stB = expectedStreamType[b.profile];
5671
+ const sameChannel = a.ch === b.ch;
5672
+ let expectedOk;
5673
+ let reason;
5674
+ if (sameChannel && stA === stB) {
5675
+ expectedOk = false;
5676
+ reason = `same streamType (${stA}) on same channel`;
5677
+ } else if (!sameChannel && a.profile === b.profile) {
5678
+ expectedOk = false;
5679
+ reason = `multifocal rejects same profile (${a.profile}) across channels`;
5680
+ } else if (!sameChannel && stA === stB) {
5681
+ expectedOk = false;
5682
+ reason = `same streamType (${stA}) across channels`;
5683
+ } else {
5684
+ expectedOk = true;
5685
+ reason = `different streamTypes (${stA} vs ${stB})`;
5686
+ }
5687
+ expectedCompat.push({ pair: [a.label, b.label], expectedOk, reason });
5688
+ }
5689
+ const results = [];
5690
+ const TEST_DURATION_MS = 4e3;
5691
+ for (let pairIdx = 0; pairIdx < pairs.length; pairIdx++) {
5692
+ const [a, b] = pairs[pairIdx];
5693
+ const expected = expectedCompat[pairIdx];
5694
+ log(` testing ${a.label}+${b.label} on shared socket...`);
5695
+ let session;
5696
+ try {
5697
+ session = await api.createDedicatedSession(
5698
+ `test:combo:${a.label}_${b.label}`
5699
+ );
5700
+ } catch (e) {
5701
+ const result2 = {
5702
+ pair: [a.label, b.label],
5703
+ ok: false,
5704
+ framesA: 0,
5705
+ framesB: 0,
5706
+ mismatches: 0,
5707
+ error: `session: ${e instanceof Error ? e.message : String(e)}`,
5708
+ durationMs: 0,
5709
+ expectedOk: expected.expectedOk,
5710
+ expectedReason: expected.reason,
5711
+ matchesExpected: !expected.expectedOk
5712
+ // failed as expected if we expected failure
5713
+ };
5714
+ results.push(result2);
5715
+ continue;
5716
+ }
5717
+ const testClient = session.client;
5718
+ let framesA = 0;
5719
+ let framesB = 0;
5720
+ let mismatches = 0;
5721
+ const start = Date.now();
5722
+ const stTypes = {
5723
+ main: /* @__PURE__ */ new Set([0, 2]),
5724
+ sub: /* @__PURE__ */ new Set([1, 3]),
5725
+ ext: /* @__PURE__ */ new Set([0, 2])
5726
+ };
5727
+ const setA = stTypes[a.profile];
5728
+ const setB = stTypes[b.profile];
5729
+ const onFrame = (frame) => {
5730
+ if (frame.header?.cmdId !== BC_CMD_ID_VIDEO) return;
5731
+ const st = frame.header.streamType;
5732
+ if (setA.has(st)) framesA++;
5733
+ else if (setB.has(st)) framesB++;
5734
+ else mismatches++;
5735
+ };
5736
+ testClient.on("frame", onFrame);
5737
+ let error;
5738
+ try {
5739
+ await api.startVideoStream(a.ch, a.profile, { client: testClient });
5740
+ await api.startVideoStream(b.ch, b.profile, { client: testClient });
5741
+ await new Promise((r) => setTimeout(r, TEST_DURATION_MS));
5742
+ await api.stopVideoStream(a.ch, a.profile, { client: testClient }).catch(() => {
5743
+ });
5744
+ await api.stopVideoStream(b.ch, b.profile, { client: testClient }).catch(() => {
5745
+ });
5746
+ } catch (e) {
5747
+ error = e instanceof Error ? e.message : String(e);
5748
+ } finally {
5749
+ testClient.removeListener("frame", onFrame);
5750
+ await session.release().catch(() => {
5751
+ });
5752
+ }
5753
+ const elapsed = Date.now() - start;
5754
+ const ok2 = !error && framesA > 0 && framesB > 0 && mismatches === 0;
5755
+ const result = {
5756
+ pair: [a.label, b.label],
5757
+ ok: ok2,
5758
+ framesA,
5759
+ framesB,
5760
+ mismatches,
5761
+ ...error ? { error } : {},
5762
+ durationMs: elapsed,
5763
+ expectedOk: expected.expectedOk,
5764
+ expectedReason: expected.reason,
5765
+ matchesExpected: ok2 === expected.expectedOk
5766
+ };
5767
+ results.push(result);
5768
+ const matchStr = result.matchesExpected ? "" : " *** UNEXPECTED ***";
5769
+ log(` ${a.label}+${b.label}: ${ok2 ? "OK" : "FAIL"} (expected=${expected.expectedOk ? "OK" : "FAIL"}) A=${framesA} B=${framesB} mismatch=${mismatches}${matchStr}`);
5770
+ }
5771
+ const unexpected = results.filter((r) => !r.matchesExpected);
5772
+ return {
5773
+ isMultifocal,
5774
+ channelCount,
5775
+ results,
5776
+ summary: {
5777
+ total: results.length,
5778
+ ok: results.filter((r) => r.ok).length,
5779
+ failed: results.filter((r) => !r.ok).length,
5780
+ matchesExpected: results.filter((r) => r.matchesExpected).length,
5781
+ unexpected: unexpected.map((r) => `${r.pair[0]}+${r.pair[1]}: got ${r.ok ? "OK" : "FAIL"}, expected ${r.expectedOk ? "OK" : "FAIL"}`)
5782
+ }
5783
+ };
5784
+ }, (v) => writeJsonSafe(path4.join(outDir, "stream-combination-test.json"), v));
5545
5785
  const total = Object.keys(calls).length;
5546
5786
  const ok = Object.values(calls).filter((c) => c.ok).length;
5547
5787
  const failed = total - ok;
5548
5788
  const summary = { total, ok, failed, errors };
5549
- writeJson(path4.join(outDir, "_summary.json"), {
5789
+ writeJsonSafe(path4.join(outDir, "_summary.json"), {
5550
5790
  collectedAt: (/* @__PURE__ */ new Date()).toISOString(),
5551
5791
  model: info?.type ?? "unknown",
5552
5792
  itemNo: info?.itemNo ?? "unknown",
@@ -5570,7 +5810,7 @@ async function captureModelFixtures(params) {
5570
5810
  }
5571
5811
  return { calls, outDir, summary };
5572
5812
  }
5573
- var fs4, path4, import_node_child_process, import_node_path;
5813
+ var fs4, path4, import_node_child_process, import_node_path, REDACT_KEYS, MASK_KEYS, IPV4_RE, MAC_RE;
5574
5814
  var init_DiagnosticsTools = __esm({
5575
5815
  "src/debug/DiagnosticsTools.ts"() {
5576
5816
  "use strict";
@@ -5586,6 +5826,27 @@ var init_DiagnosticsTools = __esm({
5586
5826
  init_H265Converter();
5587
5827
  init_constants();
5588
5828
  init_xml();
5829
+ REDACT_KEYS = /* @__PURE__ */ new Set([
5830
+ "password",
5831
+ "pass",
5832
+ "token",
5833
+ "secret",
5834
+ "apiKey",
5835
+ "api_key"
5836
+ ]);
5837
+ MASK_KEYS = /* @__PURE__ */ new Set([
5838
+ "serialNumber",
5839
+ "serial",
5840
+ "uid",
5841
+ "mac",
5842
+ "ssid",
5843
+ "wifiPassword",
5844
+ "userName",
5845
+ "username",
5846
+ "user"
5847
+ ]);
5848
+ IPV4_RE = /\b(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\b/g;
5849
+ MAC_RE = /\b([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}\b/g;
5589
5850
  }
5590
5851
  });
5591
5852
 
@@ -7663,6 +7924,7 @@ __export(index_exports, {
7663
7924
  collectNativeDiagnostics: () => collectNativeDiagnostics,
7664
7925
  collectNvrDiagnostics: () => collectNvrDiagnostics,
7665
7926
  computeDeviceCapabilities: () => computeDeviceCapabilities,
7927
+ computeExpectedStreamCompatibility: () => computeExpectedStreamCompatibility,
7666
7928
  convertH265ToAnnexB: () => convertToAnnexB2,
7667
7929
  convertToAnnexB: () => convertToAnnexB,
7668
7930
  convertToLengthPrefixed: () => convertToLengthPrefixed,
@@ -7733,6 +7995,7 @@ __export(index_exports, {
7733
7995
  runAllDiagnosticsConsecutively: () => runAllDiagnosticsConsecutively,
7734
7996
  runMultifocalDiagnosticsConsecutively: () => runMultifocalDiagnosticsConsecutively,
7735
7997
  sampleStreams: () => sampleStreams,
7998
+ sanitizeFixtureData: () => sanitizeFixtureData,
7736
7999
  setGlobalLogger: () => setGlobalLogger,
7737
8000
  splitAnnexBToNalPayloads: () => splitAnnexBToNalPayloads,
7738
8001
  splitAnnexBToNals: () => splitAnnexBToNals,
@@ -15426,7 +15689,7 @@ function computeDeviceCapabilities(params) {
15426
15689
  const ptzControlRaw = supportItem ? supportItem.ptzControl : void 0;
15427
15690
  const supportExplicitlyDefinesPtz = ptzTypeRaw !== void 0 || ptzControlRaw !== void 0;
15428
15691
  const ptzExplicitlyDisabledBySupportItem = supportExplicitlyDefinesPtz && !isTruthyNumberLike(ptzTypeRaw) && !isTruthyNumberLike(ptzControlRaw);
15429
- const hasPtzFromSupportItem = isTruthyNumberLike(ptzTypeRaw) || isTruthyNumberLike(ptzControlRaw) || isTruthyNumberLike(supportItem?.ptzPreset);
15692
+ const hasPtzFromSupportItem = isTruthyNumberLike(ptzTypeRaw);
15430
15693
  const ptzDisabledBySupport = (ptzMode === "none" || ptzMode === "0") && !hasPtzFromSupportItem;
15431
15694
  const hasBatteryFromSupport = supportItem ? isTruthyNumberLike(supportItem.battery) : false;
15432
15695
  const ptzPresetRaw = supportItem ? supportItem.ptzPreset : void 0;
@@ -36675,6 +36938,7 @@ var CompositeRtspServer = class extends import_node_events12.EventEmitter {
36675
36938
  collectNativeDiagnostics,
36676
36939
  collectNvrDiagnostics,
36677
36940
  computeDeviceCapabilities,
36941
+ computeExpectedStreamCompatibility,
36678
36942
  convertH265ToAnnexB,
36679
36943
  convertToAnnexB,
36680
36944
  convertToLengthPrefixed,
@@ -36745,6 +37009,7 @@ var CompositeRtspServer = class extends import_node_events12.EventEmitter {
36745
37009
  runAllDiagnosticsConsecutively,
36746
37010
  runMultifocalDiagnosticsConsecutively,
36747
37011
  sampleStreams,
37012
+ sanitizeFixtureData,
36748
37013
  setGlobalLogger,
36749
37014
  splitAnnexBToNalPayloads,
36750
37015
  splitAnnexBToNals,