@apocaliss92/scrypted-reolink-native 0.5.35 → 0.5.37

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/plugin.zip CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apocaliss92/scrypted-reolink-native",
3
- "version": "0.5.35",
3
+ "version": "0.5.37",
4
4
  "description": "Use any reolink camera with Scrypted, even older/unsupported models without HTTP protocol support",
5
5
  "author": "@apocaliss92",
6
6
  "license": "Apache",
@@ -44,7 +44,7 @@
44
44
  ]
45
45
  },
46
46
  "dependencies": {
47
- "@apocaliss92/nodelink-js": "^0.4.34",
47
+ "@apocaliss92/nodelink-js": "^0.4.36",
48
48
  "@scrypted/common": "file:../../scrypted/common",
49
49
  "@scrypted/rtsp": "file:../../scrypted/plugins/rtsp",
50
50
  "@scrypted/sdk": "^0.3.118"
package/src/intercom.ts CHANGED
@@ -1,6 +1,22 @@
1
1
  import type { ReolinkBaichuanApi } from "@apocaliss92/nodelink-js" with {
2
2
  "resolution-mode": "import",
3
3
  };
4
+
5
+ // Lazy ESM bridge: scrypted-reolink-native is CJS-compiled but
6
+ // @apocaliss92/nodelink-js is an ESM-only package, so any value
7
+ // (non-type) imports have to go through dynamic import. Cached on the
8
+ // first call so the PCM pump doesn't re-resolve the module per chunk.
9
+ let encodeImaAdpcmFn:
10
+ | ((pcm: Int16Array, blockSizeBytes: number) => Buffer)
11
+ | undefined;
12
+ async function loadEncodeImaAdpcm(): Promise<
13
+ (pcm: Int16Array, blockSizeBytes: number) => Buffer
14
+ > {
15
+ if (encodeImaAdpcmFn) return encodeImaAdpcmFn;
16
+ const mod = await import("@apocaliss92/nodelink-js");
17
+ encodeImaAdpcmFn = mod.encodeImaAdpcm;
18
+ return encodeImaAdpcmFn;
19
+ }
4
20
  import sdk, {
5
21
  FFmpegInput,
6
22
  MediaObject,
@@ -313,12 +329,6 @@ export class ReolinkBaichuanIntercom {
313
329
  return this.stopping;
314
330
  }
315
331
 
316
- private clamp16(x: number): number {
317
- if (x > 32767) return 32767;
318
- if (x < -32768) return -32768;
319
- return x | 0;
320
- }
321
-
322
332
  private enqueuePcm(
323
333
  session: Awaited<ReturnType<ReolinkBaichuanApi["createTalkSession"]>>,
324
334
  pcmChunk: Buffer,
@@ -360,6 +370,7 @@ export class ReolinkBaichuanIntercom {
360
370
  this.pumping = true;
361
371
  this.pumpPromise = (async () => {
362
372
  try {
373
+ const encode = await loadEncodeImaAdpcm();
363
374
  while (true) {
364
375
  if (this.session !== session) return;
365
376
  if (this.pcmBuffer.length < bytesNeeded) return;
@@ -373,7 +384,7 @@ export class ReolinkBaichuanIntercom {
373
384
  chunk.length / 2,
374
385
  );
375
386
 
376
- const adpcmChunk = this.encodeImaAdpcm(pcmSamples, blockSize);
387
+ const adpcmChunk = encode(pcmSamples, blockSize);
377
388
  await session.sendAudio(adpcmChunk);
378
389
  }
379
390
  } catch (e) {
@@ -499,97 +510,4 @@ export class ReolinkBaichuanIntercom {
499
510
  ];
500
511
  }
501
512
 
502
- private encodeImaAdpcm(pcm: Int16Array, blockSizeBytes: number): Buffer {
503
- const samplesPerBlock = blockSizeBytes * 2 + 1;
504
- const totalBlocks = Math.ceil(pcm.length / samplesPerBlock);
505
- const outBlocks: Buffer[] = [];
506
-
507
- const imaIndexTable = Int8Array.from([
508
- -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8,
509
- ]);
510
-
511
- const imaStepTable = Int16Array.from([
512
- 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41,
513
- 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190,
514
- 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
515
- 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499,
516
- 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845,
517
- 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385,
518
- 24623, 27086, 29794, 32767,
519
- ]);
520
-
521
- let sampleIndex = 0;
522
-
523
- for (let b = 0; b < totalBlocks; b++) {
524
- const block = Buffer.alloc(4 + blockSizeBytes);
525
-
526
- // Block header
527
- const first = pcm[sampleIndex] ?? 0;
528
- let predictor = first;
529
- let index = 0;
530
-
531
- block.writeInt16LE(predictor, 0);
532
- block.writeUInt8(index, 2);
533
- block.writeUInt8(0, 3);
534
-
535
- sampleIndex++;
536
-
537
- // Encode samples into nibbles
538
- const codes = new Uint8Array(blockSizeBytes * 2);
539
- for (let i = 0; i < codes.length; i++) {
540
- const sample = pcm[sampleIndex] ?? predictor;
541
- sampleIndex++;
542
-
543
- let diff = sample - predictor;
544
- let sign = 0;
545
- if (diff < 0) {
546
- sign = 8;
547
- diff = -diff;
548
- }
549
-
550
- let step = imaStepTable[index] ?? 7;
551
- let delta = 0;
552
- let vpdiff = step >> 3;
553
-
554
- if (diff >= step) {
555
- delta |= 4;
556
- diff -= step;
557
- vpdiff += step;
558
- }
559
- step >>= 1;
560
- if (diff >= step) {
561
- delta |= 2;
562
- diff -= step;
563
- vpdiff += step;
564
- }
565
- step >>= 1;
566
- if (diff >= step) {
567
- delta |= 1;
568
- vpdiff += step;
569
- }
570
-
571
- if (sign) predictor -= vpdiff;
572
- else predictor += vpdiff;
573
-
574
- predictor = this.clamp16(predictor);
575
-
576
- index += imaIndexTable[delta] ?? 0;
577
- if (index < 0) index = 0;
578
- if (index > 88) index = 88;
579
-
580
- codes[i] = (delta | sign) & 0x0f;
581
- }
582
-
583
- // Pack nibble: low nibble first, then high nibble
584
- for (let i = 0; i < blockSizeBytes; i++) {
585
- const lo = codes[i * 2] ?? 0;
586
- const hi = codes[i * 2 + 1] ?? 0;
587
- block[4 + i] = (lo & 0x0f) | ((hi & 0x0f) << 4);
588
- }
589
-
590
- outBlocks.push(block);
591
- }
592
-
593
- return Buffer.concat(outBlocks);
594
- }
595
513
  }