@decentnetwork/beagle 0.1.47 → 0.1.49

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.
@@ -1,4 +1,4 @@
1
- window.__DK_UI_VERSION="0.1.47";
1
+ window.__DK_UI_VERSION="0.1.49";
2
2
  const ICON_PATHS = {
3
3
  // ---- tab bar (the four must feel like one set) ----
4
4
  users: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
@@ -3977,43 +3977,6 @@ function RtcFileInbox({ T, peers, ctl }) {
3977
3977
  }));
3978
3978
  }
3979
3979
  Object.assign(window, { useRtcFileController, RtcFileInbox });
3980
- const VIDEO_CODEC_KEEP = /^video\/(H264|VP8|rtx|red|ulpfec)$/i;
3981
- const SDP_BUDGET = 8192;
3982
- function trimVideoCodecs(pc) {
3983
- var _a, _b, _c, _d, _e, _f, _g;
3984
- const supported = (_c = (_b = (_a = window.RTCRtpSender) == null ? void 0 : _a.getCapabilities) == null ? void 0 : _b.call(_a, "video")) == null ? void 0 : _c.codecs;
3985
- if (!supported)
3986
- return;
3987
- const keep = supported.filter((c) => VIDEO_CODEC_KEEP.test(c.mimeType));
3988
- if (!keep.length || keep.length === supported.length)
3989
- return;
3990
- for (const t of pc.getTransceivers()) {
3991
- const kind = ((_e = (_d = t.receiver) == null ? void 0 : _d.track) == null ? void 0 : _e.kind) || ((_g = (_f = t.sender) == null ? void 0 : _f.track) == null ? void 0 : _g.kind);
3992
- if (kind !== "video" || !t.setCodecPreferences)
3993
- continue;
3994
- try {
3995
- t.setCodecPreferences(keep);
3996
- } catch (e) {
3997
- console.warn("[call] setCodecPreferences failed", e);
3998
- }
3999
- }
4000
- }
4001
- function createLeanPeerConnection(config) {
4002
- const pc = new RTCPeerConnection(config);
4003
- for (const method of ["createOffer", "createAnswer"]) {
4004
- const original = pc[method].bind(pc);
4005
- pc[method] = async (...args) => {
4006
- trimVideoCodecs(pc);
4007
- const desc = await original(...args);
4008
- const bytes = new TextEncoder().encode(desc.sdp || "").length;
4009
- console[bytes > SDP_BUDGET ? "warn" : "log"](
4010
- `[call] ${method} SDP ${bytes}B / ${SDP_BUDGET}B budget` + (bytes > SDP_BUDGET ? " \u2014 too large for the Carrier invite channel, falling back to the offline path" : "")
4011
- );
4012
- return desc;
4013
- };
4014
- }
4015
- return pc;
4016
- }
4017
3980
  function useCallController(selfId, onCallLog) {
4018
3981
  const [incoming, setIncoming] = React.useState(null);
4019
3982
  const [active, setActive] = React.useState(null);
@@ -4047,7 +4010,7 @@ function useCallController(selfId, onCallLog) {
4047
4010
  const engine = new CallEngine({
4048
4011
  selfId,
4049
4012
  signaling,
4050
- createPeerConnection: (c) => createLeanPeerConnection(c),
4013
+ createPeerConnection: (c) => new RTCPeerConnection(c),
4051
4014
  getLocalMedia: (k) => navigator.mediaDevices.getUserMedia({ audio: k.audio, video: k.video }),
4052
4015
  getDisplayMedia: (c) => navigator.mediaDevices.getDisplayMedia(c || { video: true, audio: false }),
4053
4016
  iceServers: DK_LIVE_ICE_SERVERS,
@@ -4088,6 +4051,7 @@ function useCallController(selfId, onCallLog) {
4088
4051
  setIncoming((i) => i && i.callId === id ? null : i);
4089
4052
  setLocalStream(null);
4090
4053
  setRemoteStream(null);
4054
+ setSharing(false);
4091
4055
  });
4092
4056
  engineRef.current = engine;
4093
4057
  console.log("[call] CallEngine ready with ICE:", DK_LIVE_ICE_SERVERS.map((s) => s.urls));
@@ -44,15 +44,21 @@ var PeerWebRTC = (() => {
44
44
  __export(dist_exports, {
45
45
  BeaglePushClient: () => BeaglePushClient,
46
46
  BroadcastChannelSignaling: () => BroadcastChannelSignaling,
47
+ CARRIER_MAX_INVITE_DATA_LEN: () => CARRIER_MAX_INVITE_DATA_LEN,
47
48
  CallEngine: () => CallEngine,
48
49
  CarrierSignaling: () => CarrierSignaling,
49
50
  Emitter: () => Emitter,
50
51
  SocketIoSignaling: () => SocketIoSignaling,
52
+ byteLength: () => byteLength,
51
53
  decodeSignal: () => decodeSignal,
52
54
  decodeSignalBytesGuard: () => decodeSignalBytesGuard,
53
55
  encodeSignal: () => encodeSignal,
54
56
  encodeSignalBytes: () => encodeSignalBytes,
55
- looksLikeSignal: () => looksLikeSignal
57
+ fitSignalForInvite: () => fitSignalForInvite,
58
+ looksLikeSignal: () => looksLikeSignal,
59
+ mediaDirection: () => mediaDirection,
60
+ shrinkSdpForInvite: () => shrinkSdpForInvite,
61
+ videoIsSending: () => videoIsSending
56
62
  });
57
63
 
58
64
  // node_modules/@decentnetwork/peer-webrtc/dist/emitter.js
@@ -91,6 +97,108 @@ var PeerWebRTC = (() => {
91
97
  };
92
98
  _handlers = new WeakMap();
93
99
 
100
+ // node_modules/@decentnetwork/peer-webrtc/dist/sdp.js
101
+ var CARRIER_MAX_INVITE_DATA_LEN = 8192;
102
+ function mediaSection(sdp, kind) {
103
+ const norm = sdp.replace(/\r\n/g, "\n");
104
+ const start = norm.indexOf(`m=${kind} `);
105
+ if (start < 0)
106
+ return void 0;
107
+ const next = norm.indexOf("\nm=", start + 1);
108
+ return next < 0 ? norm.slice(start) : norm.slice(start, next);
109
+ }
110
+ function mediaDirection(sdp, kind) {
111
+ const block = mediaSection(sdp, kind);
112
+ if (block === void 0)
113
+ return void 0;
114
+ for (const dir of ["sendrecv", "sendonly", "recvonly", "inactive"]) {
115
+ if (block.includes(`a=${dir}`))
116
+ return dir;
117
+ }
118
+ return "sendrecv";
119
+ }
120
+ function videoIsSending(sdp) {
121
+ const dir = mediaDirection(sdp, "video");
122
+ return dir === "sendrecv" || dir === "sendonly";
123
+ }
124
+ function byteLength(text) {
125
+ return new TextEncoder().encode(text).length;
126
+ }
127
+ function videoPayloadTypes(lines) {
128
+ const out = /* @__PURE__ */ new Map();
129
+ for (const line of lines) {
130
+ const m = /^a=rtpmap:(\d+)\s+([A-Za-z0-9-]+)\//.exec(line);
131
+ if (m)
132
+ out.set(m[1], { pt: m[1], name: m[2], fmtp: "" });
133
+ }
134
+ for (const line of lines) {
135
+ const m = /^a=fmtp:(\d+)\s+(.*)$/.exec(line);
136
+ const e = m && out.get(m[1]);
137
+ if (e)
138
+ e.fmtp = m[2];
139
+ }
140
+ return [...out.values()];
141
+ }
142
+ function payloadTypesToDrop(lines, drop) {
143
+ const all = videoPayloadTypes(lines);
144
+ const pts = new Set(all.filter((p) => p.name.toLowerCase() !== "rtx" && drop(p)).map((p) => p.pt));
145
+ for (const p of all) {
146
+ const apt = /(?:^|;|\s)apt=(\d+)/.exec(p.fmtp);
147
+ if (p.name.toLowerCase() === "rtx" && apt && pts.has(apt[1]))
148
+ pts.add(p.pt);
149
+ }
150
+ return pts;
151
+ }
152
+ function stripPayloadTypes(lines, pts) {
153
+ if (pts.size === 0)
154
+ return [...lines];
155
+ const out = [];
156
+ for (const line of lines) {
157
+ if (line.startsWith("m=video ")) {
158
+ const parts = line.split(" ");
159
+ out.push([...parts.slice(0, 3), ...parts.slice(3).filter((pt) => !pts.has(pt))].join(" "));
160
+ continue;
161
+ }
162
+ const m = /^a=(?:rtpmap|rtcp-fb|fmtp):(\d+)\b/.exec(line);
163
+ if (m && pts.has(m[1]))
164
+ continue;
165
+ out.push(line);
166
+ }
167
+ return out;
168
+ }
169
+ function stripCandidates(lines) {
170
+ return lines.filter((l) => !l.startsWith("a=candidate:") && !l.startsWith("a=end-of-candidates"));
171
+ }
172
+ var CODEC_REDUCTIONS = [
173
+ // 1. Codecs the phones have never negotiated.
174
+ (p) => /^(VP9|AV1|AV1X|H265|HEVC)$/i.test(p.name),
175
+ // 2. Redundancy/FEC payloads — nice to have, not required to connect.
176
+ (p) => /^(red|ulpfec|flexfec-03)$/i.test(p.name),
177
+ // 3. Duplicate H264 profiles. Chrome offers six (baseline/main/high ×
178
+ // packetization-mode 0/1) at ~230 bytes each; the phones use constrained
179
+ // baseline (profile-level-id=42…) with packetization-mode=1. Keep those
180
+ // and VP8, drop the rest.
181
+ (p) => /^H264$/i.test(p.name) && !(/profile-level-id=42/i.test(p.fmtp) && /packetization-mode=1/i.test(p.fmtp))
182
+ ];
183
+ function shrinkSdpForInvite(sdp, budget = CARRIER_MAX_INVITE_DATA_LEN, opts = {}) {
184
+ if (byteLength(sdp) <= budget)
185
+ return sdp;
186
+ const crlf = sdp.includes("\r\n");
187
+ const join = (l) => l.join(crlf ? "\r\n" : "\n");
188
+ let lines = sdp.replace(/\r\n/g, "\n").split("\n");
189
+ lines = stripCandidates(lines);
190
+ if (byteLength(join(lines)) <= budget)
191
+ return join(lines);
192
+ if (opts.codecs !== false) {
193
+ for (const reduction of CODEC_REDUCTIONS) {
194
+ lines = stripPayloadTypes(lines, payloadTypesToDrop(lines, reduction));
195
+ if (byteLength(join(lines)) <= budget)
196
+ return join(lines);
197
+ }
198
+ }
199
+ return join(lines);
200
+ }
201
+
94
202
  // node_modules/@decentnetwork/peer-webrtc/dist/signal.js
95
203
  var SDP_TYPES = /* @__PURE__ */ new Set([
96
204
  "offer",
@@ -128,6 +236,24 @@ var PeerWebRTC = (() => {
128
236
  function encodeSignalBytes(signal) {
129
237
  return new TextEncoder().encode(encodeSignal(signal));
130
238
  }
239
+ function fitSignalForInvite(signal, budget = CARRIER_MAX_INVITE_DATA_LEN) {
240
+ let bytes = encodeSignalBytes(signal).length;
241
+ if (bytes <= budget)
242
+ return { signal, bytes, shrunk: false };
243
+ let out = signal;
244
+ if (signal.sdp) {
245
+ const envelope = bytes - byteLength(signal.sdp);
246
+ out = {
247
+ ...signal,
248
+ sdp: shrinkSdpForInvite(signal.sdp, budget - envelope, { codecs: signal.type === "offer" })
249
+ };
250
+ bytes = encodeSignalBytes(out).length;
251
+ }
252
+ if (bytes > budget) {
253
+ throw new Error(`RtcSignal "${signal.type}" is ${bytes}B after shrinking, over the ${budget}B invite cap \u2014 the peer would never receive it`);
254
+ }
255
+ return { signal: out, bytes, shrunk: true };
256
+ }
131
257
  function decodeSignal(input) {
132
258
  const text = (typeof input === "string" ? input : new TextDecoder().decode(input)).replace(/\0+$/u, "").trim();
133
259
  const obj = JSON.parse(text);
@@ -167,10 +293,11 @@ var PeerWebRTC = (() => {
167
293
  var DEFAULT_ICE_SERVERS = [
168
294
  { urls: "stun:stun.l.google.com:19302" }
169
295
  ];
296
+ var LEAN_VIDEO_CODECS = /^video\/(H264|VP8|rtx|red|ulpfec)$/i;
170
297
  var ICE_RESTART_MAX = 3;
171
298
  var ICE_DISCONNECT_GRACE_MS = 4e3;
172
299
  var ICE_FAILED_GRACE_MS = 12e4;
173
- var _opts, _iceServers, _sessions, _restartOffersEnabled, _setOutgoingVideoTrack, setOutgoingVideoTrack_fn, _renegotiate, renegotiate_fn, _restartIce, restartIce_fn, _handleSignal, handleSignal_fn, _onOffer, onOffer_fn, _answerRenegotiation, answerRenegotiation_fn, _onAnswer, onAnswer_fn, _onCandidate, onCandidate_fn, _onBye, onBye_fn, _onAuxiliary, onAuxiliary_fn, _createSession, createSession_fn, _wirePeerConnection, wirePeerConnection_fn, _ensureRemoteStream, ensureRemoteStream_fn, _attachLocalMedia, attachLocalMedia_fn, _flushLocalCandidates, flushLocalCandidates_fn, _drainRemoteCandidates, drainRemoteCandidates_fn, _send, send_fn, _sendByeSafe, sendByeSafe_fn, _cleanup, cleanup_fn, _setState, setState_fn, _normId, normId_fn, _toInfo, _newCallId, newCallId_fn, _log, log_fn;
300
+ var _opts, _iceServers, _sessions, _restartOffersEnabled, _setOutgoingVideoTrack, setOutgoingVideoTrack_fn, _renegotiate, renegotiate_fn, _createOffer, createOffer_fn, _createAnswer, createAnswer_fn, _preferLeanVideoCodecs, preferLeanVideoCodecs_fn, _restartIce, restartIce_fn, _handleSignal, handleSignal_fn, _onOffer, onOffer_fn, _answerRenegotiation, answerRenegotiation_fn, _onAnswer, onAnswer_fn, _onCandidate, onCandidate_fn, _onBye, onBye_fn, _onAuxiliary, onAuxiliary_fn, _createSession, createSession_fn, _wirePeerConnection, wirePeerConnection_fn, _ensureRemoteStream, ensureRemoteStream_fn, _attachLocalMedia, attachLocalMedia_fn, _flushLocalCandidates, flushLocalCandidates_fn, _drainRemoteCandidates, drainRemoteCandidates_fn, _send, send_fn, _sendByeSafe, sendByeSafe_fn, _cleanup, cleanup_fn, _setState, setState_fn, _normId, normId_fn, _toInfo, _newCallId, newCallId_fn, _log, log_fn;
174
301
  var CallEngine = class extends Emitter {
175
302
  constructor(opts) {
176
303
  var _a, _b;
@@ -182,6 +309,20 @@ var PeerWebRTC = (() => {
182
309
  /** Create + send a fresh offer to renegotiate media (e.g. after adding a
183
310
  * screen-share track). The peer applies it via #onOffer's renegotiation path. */
184
311
  __privateAdd(this, _renegotiate);
312
+ /** createOffer with the lean codec set applied (see #preferLeanVideoCodecs). */
313
+ __privateAdd(this, _createOffer);
314
+ /** createAnswer with the lean codec set applied. */
315
+ __privateAdd(this, _createAnswer);
316
+ /**
317
+ * Restrict video to the codecs the peers actually negotiate, so the SDP fits
318
+ * the 8192-byte Carrier invite channel. Chrome otherwise advertises VP9 and
319
+ * AV1 with their profile/rtx/fmtp lines and the offer lands at 8.4-9.8 KB —
320
+ * over the cap, rejected by the transport, invisible to the peer.
321
+ *
322
+ * setCodecPreferences (not SDP munging) keeps the browser the one producing a
323
+ * valid, self-consistent description. No-ops wherever the API is missing.
324
+ */
325
+ __privateAdd(this, _preferLeanVideoCodecs);
185
326
  /** Recover a dead transport with an ICE restart (RFC 8445 §12): a re-offer
186
327
  * carrying fresh ufrag/pwd, sent over the SAME renegotiation path that
187
328
  * screen-share re-offers use — any peer that answers those (web, iOS,
@@ -279,7 +420,7 @@ var PeerWebRTC = (() => {
279
420
  } catch {
280
421
  }
281
422
  }
282
- const offer = await session.pc.createOffer();
423
+ const offer = await __privateMethod(this, _createOffer, createOffer_fn).call(this, session);
283
424
  await session.pc.setLocalDescription(offer);
284
425
  const options = [];
285
426
  if (audio)
@@ -313,7 +454,7 @@ var PeerWebRTC = (() => {
313
454
  session.hasReceivedSdp = true;
314
455
  session.pendingOffer = void 0;
315
456
  await __privateMethod(this, _drainRemoteCandidates, drainRemoteCandidates_fn).call(this, session);
316
- const answer = await session.pc.createAnswer();
457
+ const answer = await __privateMethod(this, _createAnswer, createAnswer_fn).call(this, session);
317
458
  await session.pc.setLocalDescription(answer);
318
459
  await __privateMethod(this, _send, send_fn).call(this, session.peerId, { type: "answer", sdp: answer.sdp, callId });
319
460
  try {
@@ -376,7 +517,14 @@ var PeerWebRTC = (() => {
376
517
  track.addEventListener("ended", () => {
377
518
  void this.stopScreenShare(callId);
378
519
  });
379
- await __privateMethod(this, _renegotiate, renegotiate_fn).call(this, session);
520
+ try {
521
+ await __privateMethod(this, _renegotiate, renegotiate_fn).call(this, session);
522
+ } catch (err) {
523
+ __privateMethod(this, _log, log_fn).call(this, `shareScreen renegotiation failed: ${err.message}`);
524
+ await this.stopScreenShare(callId).catch(() => {
525
+ });
526
+ throw err;
527
+ }
380
528
  __privateMethod(this, _log, log_fn).call(this, `shareScreen started for ${callId}`);
381
529
  }
382
530
  /** Stop screen sharing; re-acquire the camera if there was one. */
@@ -394,7 +542,9 @@ var PeerWebRTC = (() => {
394
542
  }
395
543
  session.hadCamera = false;
396
544
  await __privateMethod(this, _setOutgoingVideoTrack, setOutgoingVideoTrack_fn).call(this, session, (_a = cam == null ? void 0 : cam.getVideoTracks()[0]) != null ? _a : null, cam);
397
- await __privateMethod(this, _renegotiate, renegotiate_fn).call(this, session);
545
+ await __privateMethod(this, _renegotiate, renegotiate_fn).call(this, session).catch((err) => {
546
+ __privateMethod(this, _log, log_fn).call(this, `stopScreenShare renegotiation failed: ${err.message}`);
547
+ });
398
548
  __privateMethod(this, _log, log_fn).call(this, `shareScreen stopped for ${callId}`);
399
549
  }
400
550
  /** True when the call is currently sharing the screen. */
@@ -426,42 +576,94 @@ var PeerWebRTC = (() => {
426
576
  _restartOffersEnabled = new WeakMap();
427
577
  _setOutgoingVideoTrack = new WeakSet();
428
578
  setOutgoingVideoTrack_fn = async function(session, track, stream) {
429
- var _a;
430
- const transceivers = session.pc.getTransceivers();
431
- const tr = (_a = transceivers.find((t) => {
579
+ var _a, _b, _c, _d;
580
+ const transceivers = (_c = (_b = (_a = session.pc).getTransceivers) == null ? void 0 : _b.call(_a)) != null ? _c : [];
581
+ const tr = (_d = transceivers.find((t) => {
432
582
  var _a2;
433
583
  return ((_a2 = t.sender.track) == null ? void 0 : _a2.kind) === "video";
434
- })) != null ? _a : transceivers.find((t) => {
584
+ })) != null ? _d : transceivers.find((t) => {
435
585
  var _a2;
436
586
  return ((_a2 = t.receiver.track) == null ? void 0 : _a2.kind) === "video";
437
587
  });
438
- if (tr) {
439
- await tr.sender.replaceTrack(track);
440
- if (track) {
441
- if (tr.direction === "recvonly")
442
- tr.direction = "sendrecv";
443
- else if (tr.direction === "inactive")
444
- tr.direction = "sendonly";
588
+ if (track) {
589
+ let sending = false;
590
+ if (tr) {
591
+ try {
592
+ await tr.sender.replaceTrack(track);
593
+ if (tr.direction === "recvonly" || tr.direction === "inactive")
594
+ tr.direction = "sendrecv";
595
+ sending = tr.direction === "sendrecv" || tr.direction === "sendonly";
596
+ } catch (err) {
597
+ __privateMethod(this, _log, log_fn).call(this, `replaceTrack/direction failed: ${err.message}`);
598
+ }
599
+ }
600
+ if (!sending) {
601
+ __privateMethod(this, _log, log_fn).call(this, tr ? `video transceiver stuck at ${tr.direction}; addTrack fallback` : "no video m-line; addTrack");
602
+ if (stream)
603
+ session.pc.addTrack(track, stream);
604
+ else
605
+ session.pc.addTrack(track);
606
+ }
607
+ } else if (tr) {
608
+ try {
609
+ await tr.sender.replaceTrack(null);
610
+ if (tr.direction === "sendrecv")
611
+ tr.direction = "recvonly";
612
+ else if (tr.direction === "sendonly")
613
+ tr.direction = "inactive";
614
+ } catch (err) {
615
+ __privateMethod(this, _log, log_fn).call(this, `clear video track failed: ${err.message}`);
445
616
  }
446
- } else if (track && stream) {
447
- session.pc.addTrack(track, stream);
448
617
  }
449
618
  session.localStream = stream;
450
619
  this.emit("localStream", session.callId, stream != null ? stream : new MediaStream());
451
620
  };
452
621
  _renegotiate = new WeakSet();
453
622
  renegotiate_fn = async function(session) {
454
- try {
455
- const offer = await session.pc.createOffer();
456
- await session.pc.setLocalDescription(offer);
457
- const options = [];
458
- if (session.audio)
459
- options.push("audio");
460
- if (session.video || session.screenStream)
461
- options.push("video");
462
- await __privateMethod(this, _send, send_fn).call(this, session.peerId, { type: "offer", sdp: offer.sdp, options, callId: session.callId });
463
- } catch (err) {
464
- __privateMethod(this, _log, log_fn).call(this, `renegotiate failed: ${err.message}`);
623
+ var _a, _b;
624
+ const offer = await __privateMethod(this, _createOffer, createOffer_fn).call(this, session);
625
+ await session.pc.setLocalDescription(offer);
626
+ const options = [];
627
+ if (session.audio)
628
+ options.push("audio");
629
+ if (session.video || session.screenStream)
630
+ options.push("video");
631
+ const sdp = (_a = offer.sdp) != null ? _a : "";
632
+ __privateMethod(this, _log, log_fn).call(this, `renegotiate callId=${session.callId} video=${(_b = mediaDirection(sdp, "video")) != null ? _b : "none"} sdp=${byteLength(sdp)}B`);
633
+ if (session.screenStream && !videoIsSending(sdp)) {
634
+ __privateMethod(this, _log, log_fn).call(this, "renegotiate: WARNING share offer has no sending video m-line \u2014 peer will see black");
635
+ }
636
+ await __privateMethod(this, _send, send_fn).call(this, session.peerId, { type: "offer", sdp: offer.sdp, options, callId: session.callId });
637
+ };
638
+ _createOffer = new WeakSet();
639
+ createOffer_fn = async function(session, opts) {
640
+ __privateMethod(this, _preferLeanVideoCodecs, preferLeanVideoCodecs_fn).call(this, session.pc);
641
+ return session.pc.createOffer(opts);
642
+ };
643
+ _createAnswer = new WeakSet();
644
+ createAnswer_fn = async function(session) {
645
+ __privateMethod(this, _preferLeanVideoCodecs, preferLeanVideoCodecs_fn).call(this, session.pc);
646
+ return session.pc.createAnswer();
647
+ };
648
+ _preferLeanVideoCodecs = new WeakSet();
649
+ preferLeanVideoCodecs_fn = function(pc) {
650
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
651
+ if (__privateGet(this, _opts).leanVideoCodecs === false)
652
+ return;
653
+ const caps = (_b = (_a = globalThis.RTCRtpSender) == null ? void 0 : _a.getCapabilities) == null ? void 0 : _b.call(_a, "video");
654
+ if (!((_c = caps == null ? void 0 : caps.codecs) == null ? void 0 : _c.length))
655
+ return;
656
+ const keep = caps.codecs.filter((c) => LEAN_VIDEO_CODECS.test(c.mimeType));
657
+ if (!keep.length || keep.length === caps.codecs.length)
658
+ return;
659
+ for (const t of (_e = (_d = pc.getTransceivers) == null ? void 0 : _d.call(pc)) != null ? _e : []) {
660
+ const kind = (_j = (_g = (_f = t.receiver) == null ? void 0 : _f.track) == null ? void 0 : _g.kind) != null ? _j : (_i = (_h = t.sender) == null ? void 0 : _h.track) == null ? void 0 : _i.kind;
661
+ if (kind !== "video" || typeof t.setCodecPreferences !== "function")
662
+ continue;
663
+ try {
664
+ t.setCodecPreferences(keep);
665
+ } catch {
666
+ }
465
667
  }
466
668
  };
467
669
  _restartIce = new WeakSet();
@@ -471,7 +673,7 @@ var PeerWebRTC = (() => {
471
673
  session.restartAttempts += 1;
472
674
  __privateMethod(this, _log, log_fn).call(this, `ICE restart ${session.restartAttempts}/${ICE_RESTART_MAX} for call ${session.callId}`);
473
675
  try {
474
- const offer = await session.pc.createOffer({ iceRestart: true });
676
+ const offer = await __privateMethod(this, _createOffer, createOffer_fn).call(this, session, { iceRestart: true });
475
677
  await session.pc.setLocalDescription(offer);
476
678
  const options = [];
477
679
  if (session.audio)
@@ -532,7 +734,7 @@ var PeerWebRTC = (() => {
532
734
  answerRenegotiation_fn = async function(session, sdp) {
533
735
  try {
534
736
  await session.pc.setRemoteDescription({ type: "offer", sdp });
535
- const answer = await session.pc.createAnswer();
737
+ const answer = await __privateMethod(this, _createAnswer, createAnswer_fn).call(this, session);
536
738
  await session.pc.setLocalDescription(answer);
537
739
  await __privateMethod(this, _send, send_fn).call(this, session.peerId, { type: "answer", sdp: answer.sdp, callId: session.callId });
538
740
  } catch (err) {
@@ -764,8 +966,13 @@ var PeerWebRTC = (() => {
764
966
  };
765
967
  _send = new WeakSet();
766
968
  send_fn = async function(peerId, signal) {
969
+ var _a;
767
970
  try {
768
- await __privateGet(this, _opts).signaling.send(peerId, signal);
971
+ const budget = (_a = __privateGet(this, _opts).maxSignalBytes) != null ? _a : CARRIER_MAX_INVITE_DATA_LEN;
972
+ const fitted = fitSignalForInvite(signal, budget);
973
+ if (fitted.shrunk)
974
+ __privateMethod(this, _log, log_fn).call(this, `signal ${signal.type} shrunk to ${fitted.bytes}B (cap ${budget}B)`);
975
+ await __privateGet(this, _opts).signaling.send(peerId, fitted.signal);
769
976
  } catch (err) {
770
977
  __privateMethod(this, _log, log_fn).call(this, `signal send failed (${signal.type} \u2192 ${peerId}): ${err.message}`);
771
978
  throw err;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/beagle",
3
- "version": "0.1.47",
3
+ "version": "0.1.49",
4
4
  "description": "Beagle — P2P chat, file transfer and calls for regular users, on the Decent Network. No admin privilege required.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -28,7 +28,7 @@
28
28
  "@decentnetwork/chat-components": "^0.1.3",
29
29
  "@decentnetwork/lan": "^0.1.276",
30
30
  "@decentnetwork/peer": "^0.1.139",
31
- "@decentnetwork/peer-webrtc": "^0.2.14",
31
+ "@decentnetwork/peer-webrtc": "^0.2.16",
32
32
  "js-yaml": "^4.1.0",
33
33
  "yargs": "^17.7.2"
34
34
  },