@mega-yfue/eufy-sdk 0.4.0-beta.5 → 0.4.0-beta.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.
@@ -684,8 +684,8 @@ export interface SharedSourceHints {
684
684
  */
685
685
  powered?: "wired" | "battery";
686
686
  /**
687
- * Seconds of already-captured media the pull retains for a later drain; `0`, absent, non-finite and
688
- * negative values retain none.
687
+ * Seconds of already-captured media the pull retains for a later drain; `0`, absent, non-finite,
688
+ * negative, and windows longer than 2,147,483,647 ms retain none.
689
689
  *
690
690
  * Retention costs memory on every frame and only a caller knows whether anything will drain it, so it
691
691
  * is never assumed. Media can only be retained while the pull is running, so a window answers "what did
package/dist/index.js CHANGED
@@ -15178,6 +15178,7 @@ var LOCAL_LOOKUP_PORT = 32108;
15178
15178
  var HEARTBEAT_MS = 5e3;
15179
15179
  var PATH_SILENCE_MS = HEARTBEAT_MS * 3;
15180
15180
  var LOOKUP_RETRY_MS = 1e3;
15181
+ var RECEIVE_BUFFER_BYTES = 4 * 1024 * 1024;
15181
15182
  var CONNECT_TIMEOUT_MS = 15e3;
15182
15183
  var STATION_CHANNEL3 = 255;
15183
15184
  var CMD_GATEWAYINFO = 1100;
@@ -15233,6 +15234,8 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
15233
15234
  connected = false;
15234
15235
  connecting = false;
15235
15236
  closed = false;
15237
+ /** Whether a short receive buffer has been reported, so a reconnect does not repeat the same warning. */
15238
+ receiveBufferReported = false;
15236
15239
  connectAddress;
15237
15240
  seqNumber = 0;
15238
15241
  /**
@@ -15555,6 +15558,26 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
15555
15558
  get isConnected() {
15556
15559
  return this.connected;
15557
15560
  }
15561
+ /**
15562
+ * Ask the OS for {@link RECEIVE_BUFFER_BYTES} on a bound socket, and warn once per session when it grants
15563
+ * less or refuses.
15564
+ *
15565
+ * The request is made here rather than through `createSocket`'s `recvBufferSize`: Node applies that option
15566
+ * inside the bind callback, where a refusal is thrown out of reach of this session and ends the process.
15567
+ */
15568
+ requestReceiveBuffer(socket) {
15569
+ let granted;
15570
+ try {
15571
+ socket.setRecvBufferSize(RECEIVE_BUFFER_BYTES);
15572
+ granted = socket.getRecvBufferSize();
15573
+ } catch {
15574
+ granted = 0;
15575
+ }
15576
+ if (granted >= RECEIVE_BUFFER_BYTES || this.receiveBufferReported)
15577
+ return;
15578
+ this.receiveBufferReported = true;
15579
+ this.logger.warn(`[p2p] ${this.cfg.stationSn} UDP receive buffer below the ${RECEIVE_BUFFER_BYTES} bytes requested` + (granted > 0 ? ` (granted ${granted})` : " (request refused)") + `; live video can lose keyframes. Raise the OS limit (net.core.rmem_max on Linux, kern.ipc.maxsockbuf on BSD) to at least ${RECEIVE_BUFFER_BYTES}.`);
15580
+ }
15558
15581
  /** Open the socket and start the lookup → hole-punch handshake. */
15559
15582
  async connect() {
15560
15583
  if (this.connecting || this.connected)
@@ -15578,6 +15601,7 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
15578
15601
  socket.setBroadcast(true);
15579
15602
  } catch {
15580
15603
  }
15604
+ this.requestReceiveBuffer(socket);
15581
15605
  resolve();
15582
15606
  });
15583
15607
  });
@@ -18197,9 +18221,9 @@ function annexbToJpeg(annexb, spawn2) {
18197
18221
 
18198
18222
  // dist/transport/p2p/shared-live-source.js
18199
18223
  import { EventEmitter as EventEmitter4 } from "node:events";
18200
- function durationMs(seconds) {
18201
- const milliseconds = (seconds ?? 0) * 1e3;
18202
- return Number.isFinite(milliseconds) && milliseconds > 0 ? milliseconds : 0;
18224
+ var MAX_TIMER_DELAY_MS = 2147483647;
18225
+ function timerMs(value, fallback) {
18226
+ return value !== void 0 && Number.isFinite(value) && value >= 1 && value <= MAX_TIMER_DELAY_MS ? value : fallback;
18203
18227
  }
18204
18228
  function sameConfig(a, b) {
18205
18229
  return b !== void 0 && a.codec === b.codec && a.width === b.width && a.height === b.height;
@@ -18452,14 +18476,14 @@ var SharedLiveSource = class {
18452
18476
  tag;
18453
18477
  constructor(opts) {
18454
18478
  this.opts = opts;
18455
- this.lingerMs = opts.lingerMs ?? 8e3;
18479
+ this.lingerMs = opts.lingerMs === 0 ? 1 : timerMs(opts.lingerMs, 8e3);
18456
18480
  this.maxQueue = opts.maxQueue ?? 900;
18457
- this.preBufferMs = durationMs(opts.preBufferSeconds);
18458
- this.warmRetryMs = opts.warmRetryMs ?? 2e3;
18459
- this.warmTimeoutMs = opts.warmTimeoutMs ?? 2e4;
18481
+ this.preBufferMs = timerMs((opts.preBufferSeconds ?? 0) * 1e3, 0);
18482
+ this.warmRetryMs = timerMs(opts.warmRetryMs, 2e3);
18483
+ this.warmTimeoutMs = timerMs(opts.warmTimeoutMs, 2e4);
18460
18484
  this.powered = opts.powered ?? "wired";
18461
- this.batteryBudgetMs = opts.batteryBudgetMs ?? 45e3;
18462
- this.budgetGraceMs = opts.budgetGraceMs ?? 1e4;
18485
+ this.batteryBudgetMs = timerMs(opts.batteryBudgetMs, 45e3);
18486
+ this.budgetGraceMs = timerMs(opts.budgetGraceMs, 1e4);
18463
18487
  this.logger = opts.logger ?? noopLogger;
18464
18488
  this.tag = opts.label ? `[live ${opts.label}]` : "[live]";
18465
18489
  this.traceId = `pull-${++pullSequence}`;
@@ -18707,7 +18731,7 @@ var SharedLiveSource = class {
18707
18731
  if (this.disposed || !this.stream)
18708
18732
  return;
18709
18733
  this.clearBudget();
18710
- this.budgetTimer.arm(ms ?? this.batteryBudgetMs, () => this.onBudgetExpire());
18734
+ this.budgetTimer.arm(timerMs(ms, this.batteryBudgetMs), () => this.onBudgetExpire());
18711
18735
  }
18712
18736
  /** Settle a reuse watch on any frame — the join already holds a decodable picture. */
18713
18737
  settleReuseWatch() {
@@ -18848,7 +18872,7 @@ var SharedLiveSource = class {
18848
18872
  return this.bufferedMedia(seconds).filter((item) => item.kind === "video").map((item) => item.frame);
18849
18873
  }
18850
18874
  bufferedMedia(seconds) {
18851
- const requested = Math.min(durationMs(seconds), this.preBufferMs);
18875
+ const requested = Number.isFinite(seconds) ? Math.min(seconds * 1e3, this.preBufferMs) : 0;
18852
18876
  if (requested <= 0 || !this.ring.length)
18853
18877
  return [];
18854
18878
  const start = this.windowStart(Date.now() - requested);