@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.
- package/dist/desktop/app.js +3 -39
- package/dist/desktop/vendor/peer-webrtc.js +240 -33
- package/package.json +2 -2
package/dist/desktop/app.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
window.__DK_UI_VERSION="0.1.
|
|
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) =>
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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 = (
|
|
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 ?
|
|
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 (
|
|
439
|
-
|
|
440
|
-
if (
|
|
441
|
-
|
|
442
|
-
tr.
|
|
443
|
-
|
|
444
|
-
|
|
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
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
}
|
|
464
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
31
|
+
"@decentnetwork/peer-webrtc": "^0.2.16",
|
|
32
32
|
"js-yaml": "^4.1.0",
|
|
33
33
|
"yargs": "^17.7.2"
|
|
34
34
|
},
|