@streaming-cdn/rtc-web 1.3.14 → 1.3.15

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,25 +1,25 @@
1
- const fe = 0.02, ge = 1.4;
2
- function H(c, e, t = 0.02, i = 1.4) {
3
- const n = c.filter((r) => r.level >= t);
1
+ const Ce = 0.02, Ie = 1.4;
2
+ function ie(r, e, t = 0.02, i = 1.4) {
3
+ const n = r.filter((o) => o.level >= t);
4
4
  if (n.length === 0) return null;
5
- const s = n.reduce((r, o) => o.level > r.level ? o : r), a = n.find((r) => r.participantId === e);
5
+ const s = n.reduce((o, c) => c.level > o.level ? c : o), a = n.find((o) => o.participantId === e);
6
6
  return a ? s.participantId === e ? e : s.level >= a.level * i ? s.participantId : e : s.participantId;
7
7
  }
8
- function _(c) {
8
+ function ne(r) {
9
9
  const e = [];
10
- for (const t of c) {
10
+ for (const t of r) {
11
11
  if (String(t.type ?? "") !== "inbound-rtp" || String(t.kind ?? t.mediaType ?? "") !== "audio") continue;
12
12
  const i = Number(t.audioLevel ?? NaN);
13
13
  Number.isFinite(i) && e.push({ mid: typeof t.mid == "string" ? t.mid : null, level: i });
14
14
  }
15
15
  return e;
16
16
  }
17
- const f = {
17
+ const M = {
18
18
  audio: { active: !1, maxBitrate: 0, maxFramerate: 0, scaleResolutionDownBy: 4 },
19
19
  low: { active: !0, maxBitrate: 35e4, maxFramerate: 15, scaleResolutionDownBy: 4 },
20
20
  medium: { active: !0, maxBitrate: 11e5, maxFramerate: 24, scaleResolutionDownBy: 2 },
21
21
  high: { active: !0, maxBitrate: 28e5, maxFramerate: 30, scaleResolutionDownBy: 1 }
22
- }, X = {
22
+ }, ae = {
23
23
  warmupSamples: 3,
24
24
  poorSamplesToStepDown: 2,
25
25
  goodSamplesToStepUp: 6,
@@ -31,46 +31,46 @@ const f = {
31
31
  goodRttMs: 250,
32
32
  sustainRatio: 0.8
33
33
  };
34
- function Z(c) {
35
- const e = String(c ?? "").trim().toLowerCase();
34
+ function re(r) {
35
+ const e = String(r ?? "").trim().toLowerCase();
36
36
  return !e || e === "none" ? "" : e === "cpu" || e === "bandwidth" ? e : "other";
37
37
  }
38
- function ee(c, e, t, i, n = {}) {
39
- const s = { ...X, ...n.thresholds }, a = ["low", "medium", "high"], r = n.ceiling && n.ceiling !== "audio" ? n.ceiling : "high", o = a.indexOf(r), l = a.indexOf(c), d = (n.samplesSeen ?? s.warmupSamples) + 1, u = d <= s.warmupSamples, m = Z(e.qualityLimitationReason), p = e.packetLossPct ?? 0, v = e.rttMs ?? 0, T = e.availableOutgoingBitrateBps, E = f[c].maxBitrate, w = p >= s.criticalLossPct || v >= s.criticalRttMs || m === "cpu", y = w || p >= s.poorLossPct || v >= s.poorRttMs || m === "bandwidth", b = T == null || T >= E * s.sustainRatio, C = p < s.goodLossPct && v < s.goodRttMs && !m && b, S = y ? t + 1 : 0, k = C ? i + 1 : 0, I = { quality: c, poorSamples: S, goodSamples: k, samplesSeen: d, changed: !1 };
40
- return l > o ? { quality: a[o], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : u ? I : w && l > 0 ? { quality: a[l - 1], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : S >= s.poorSamplesToStepDown && l > 0 ? { quality: a[l - 1], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : k >= s.goodSamplesToStepUp && l < o ? { quality: a[l + 1], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : I;
38
+ function oe(r, e, t, i, n = {}) {
39
+ const s = { ...ae, ...n.thresholds }, a = ["low", "medium", "high"], o = n.ceiling && n.ceiling !== "audio" ? n.ceiling : "high", c = a.indexOf(o), d = a.indexOf(r), l = (n.samplesSeen ?? s.warmupSamples) + 1, h = l <= s.warmupSamples, v = re(e.qualityLimitationReason), g = e.packetLossPct ?? 0, k = e.rttMs ?? 0, p = e.availableOutgoingBitrateBps, C = M[r].maxBitrate, S = g >= s.criticalLossPct || k >= s.criticalRttMs || v === "cpu", y = S || g >= s.poorLossPct || k >= s.poorRttMs || v === "bandwidth", T = p == null || p >= C * s.sustainRatio, I = g < s.goodLossPct && k < s.goodRttMs && !v && T, R = y ? t + 1 : 0, E = I ? i + 1 : 0, f = { quality: r, poorSamples: R, goodSamples: E, samplesSeen: l, changed: !1 };
40
+ return d > c ? { quality: a[c], poorSamples: 0, goodSamples: 0, samplesSeen: l, changed: !0 } : h ? f : S && d > 0 ? { quality: a[d - 1], poorSamples: 0, goodSamples: 0, samplesSeen: l, changed: !0 } : R >= s.poorSamplesToStepDown && d > 0 ? { quality: a[d - 1], poorSamples: 0, goodSamples: 0, samplesSeen: l, changed: !0 } : E >= s.goodSamplesToStepUp && d < c ? { quality: a[d + 1], poorSamples: 0, goodSamples: 0, samplesSeen: l, changed: !0 } : f;
41
41
  }
42
- function te(c, e) {
43
- const t = c instanceof Map ? c : new Map(c);
44
- let i = 0, n = 0, s = null, a = null, r = null;
45
- for (const d of t.values()) {
46
- const u = String(d.type ?? "");
47
- if (u === "outbound-rtp" && String(d.kind ?? "") === "video" && (i += Number(d.packetsSent ?? 0), s = d.qualityLimitationReason ?? s), u === "remote-inbound-rtp" && String(d.kind ?? "") === "video") {
48
- n += Number(d.packetsLost ?? 0);
49
- const m = Number(d.roundTripTime ?? NaN);
50
- Number.isFinite(m) && (a = m * 1e3);
42
+ function ce(r, e) {
43
+ const t = r instanceof Map ? r : new Map(r);
44
+ let i = 0, n = 0, s = null, a = null, o = null;
45
+ for (const l of t.values()) {
46
+ const h = String(l.type ?? "");
47
+ if (h === "outbound-rtp" && String(l.kind ?? "") === "video" && (i += Number(l.packetsSent ?? 0), s = l.qualityLimitationReason ?? s), h === "remote-inbound-rtp" && String(l.kind ?? "") === "video") {
48
+ n += Number(l.packetsLost ?? 0);
49
+ const v = Number(l.roundTripTime ?? NaN);
50
+ Number.isFinite(v) && (a = v * 1e3);
51
51
  }
52
- if (u === "candidate-pair" && (d.nominated === !0 || String(d.state ?? "") === "succeeded")) {
53
- const m = Number(d.currentRoundTripTime ?? NaN);
54
- a == null && Number.isFinite(m) && (a = m * 1e3);
55
- const p = Number(d.availableOutgoingBitrate ?? NaN);
56
- Number.isFinite(p) && (r = p);
52
+ if (h === "candidate-pair" && (l.nominated === !0 || String(l.state ?? "") === "succeeded")) {
53
+ const v = Number(l.currentRoundTripTime ?? NaN);
54
+ a == null && Number.isFinite(v) && (a = v * 1e3);
55
+ const g = Number(l.availableOutgoingBitrate ?? NaN);
56
+ Number.isFinite(g) && (o = g);
57
57
  }
58
58
  }
59
- const o = { packetsSent: i, packetsLost: n, timestamp: Date.now() };
60
- let l = null;
59
+ const c = { packetsSent: i, packetsLost: n, timestamp: Date.now() };
60
+ let d = null;
61
61
  if (e) {
62
- const d = i - e.packetsSent, u = n - e.packetsLost;
63
- d > 0 && u >= 0 && (l = u / (d + u) * 100);
62
+ const l = i - e.packetsSent, h = n - e.packetsLost;
63
+ l > 0 && h >= 0 && (d = h / (l + h) * 100);
64
64
  }
65
65
  return {
66
- sample: { packetLossPct: l, rttMs: a, availableOutgoingBitrateBps: r, qualityLimitationReason: s },
67
- counters: o
66
+ sample: { packetLossPct: d, rttMs: a, availableOutgoingBitrateBps: o, qualityLimitationReason: s },
67
+ counters: c
68
68
  };
69
69
  }
70
- const ie = {
70
+ const le = {
71
71
  audio: { active: !1, maxBitrate: 0, maxFramerate: 0, scaleResolutionDownBy: 4 }
72
- }, ne = { active: !0, maxBitrate: 4e6, maxFramerate: 30, scaleResolutionDownBy: 1 };
73
- class A {
72
+ }, de = { active: !0, maxBitrate: 4e6, maxFramerate: 30, scaleResolutionDownBy: 1 };
73
+ class Q {
74
74
  options;
75
75
  socket = null;
76
76
  localStream = null;
@@ -153,14 +153,14 @@ class A {
153
153
  async setDevice(e) {
154
154
  const t = { deviceId: { exact: e.deviceId } }, i = await navigator.mediaDevices.getUserMedia(e.kind === "audioinput" ? { audio: t } : { video: { ...t, width: { ideal: 1920 }, height: { ideal: 1080 }, frameRate: { ideal: 30, max: 30 } } }), n = e.kind === "audioinput" ? i.getAudioTracks()[0] : i.getVideoTracks()[0];
155
155
  if (!n) throw new Error("Selected media device is unavailable");
156
- const s = e.kind === "audioinput" ? "audio" : "video", a = this.localStream?.getTracks().find((r) => r.kind === s);
156
+ const s = e.kind === "audioinput" ? "audio" : "video", a = this.localStream?.getTracks().find((o) => o.kind === s);
157
157
  if (this.localStream || (this.localStream = new MediaStream()), a && (this.localStream.removeTrack(a), a.stop()), this.localStream.addTrack(n), s === "video") {
158
- this.screenStream?.getVideoTracks().some((r) => r.readyState === "live") || await this.replaceVideoTrack(n);
158
+ this.screenStream?.getVideoTracks().some((o) => o.readyState === "live") || await this.replaceVideoTrack(n);
159
159
  return;
160
160
  }
161
- for (const r of this.peers.values()) {
162
- const o = r.connection.getSenders().find((l) => l.track?.kind === s);
163
- o ? await o.replaceTrack(n) : r.connection.addTrack(n, this.localStream);
161
+ for (const o of this.peers.values()) {
162
+ const c = o.connection.getSenders().find((d) => d.track?.kind === s);
163
+ c ? await c.replaceTrack(n) : o.connection.addTrack(n, this.localStream);
164
164
  }
165
165
  await this.applyVideoQuality();
166
166
  }
@@ -168,7 +168,7 @@ class A {
168
168
  this.quality = e;
169
169
  for (const t of this.localStream?.getVideoTracks() ?? []) t.enabled = e !== "audio";
170
170
  for (const t of this.peers.values())
171
- t.quality = A.clampToCeiling(t.quality, e), t.poorSamples = 0, t.goodSamples = 0;
171
+ t.quality = Q.clampToCeiling(t.quality, e), t.poorSamples = 0, t.goodSamples = 0;
172
172
  await this.applyVideoQuality();
173
173
  }
174
174
  static clampToCeiling(e, t) {
@@ -214,31 +214,31 @@ class A {
214
214
  async openSocket(e) {
215
215
  const { credential: t } = this.options, i = new URL(t.signalingUrl, globalThis.location?.href);
216
216
  i.protocol = i.protocol === "https:" ? "wss:" : "ws:";
217
- const n = new Promise((o, l) => {
218
- this.resolveJoin = o, this.rejectJoin = l;
217
+ const n = new Promise((c, d) => {
218
+ this.resolveJoin = c, this.rejectJoin = d;
219
219
  }), s = new WebSocket(i, ["rtc-client", t.signalingToken]), a = ++this.socketGeneration;
220
220
  this.socket = s;
221
- const r = setTimeout(() => this.rejectJoin?.(new Error("RTC signaling timed out")), 15e3);
221
+ const o = setTimeout(() => this.rejectJoin?.(new Error("RTC signaling timed out")), 15e3);
222
222
  s.addEventListener("open", () => {
223
223
  this.heartbeatDeadline = Date.now() + 45e3, this.startHeartbeat(s), this.startQualitySampling(), this.send({ type: "rtc.room.join" });
224
- }), s.addEventListener("message", (o) => {
225
- const l = String(o.data);
224
+ }), s.addEventListener("message", (c) => {
225
+ const d = String(c.data);
226
226
  this.signalQueue = this.signalQueue.then(async () => {
227
- this.socket !== s || this.socketGeneration !== a || await this.handleSignal(l);
228
- }).catch((d) => {
229
- const u = d instanceof Error ? d.message : "RTC signaling processing failed";
230
- this.options.onEvent("signalingerror", { message: u }), this.joined || this.rejectJoin?.(new Error(u));
227
+ this.socket !== s || this.socketGeneration !== a || await this.handleSignal(d);
228
+ }).catch((l) => {
229
+ const h = l instanceof Error ? l.message : "RTC signaling processing failed";
230
+ this.options.onEvent("signalingerror", { message: h }), this.joined || this.rejectJoin?.(new Error(h));
231
231
  });
232
- }), s.addEventListener("error", () => this.rejectJoin?.(new Error("RTC signaling connection failed"))), s.addEventListener("close", (o) => {
232
+ }), s.addEventListener("error", () => this.rejectJoin?.(new Error("RTC signaling connection failed"))), s.addEventListener("close", (c) => {
233
233
  if (this.socket !== s) return;
234
- this.socket = null, this.stopHeartbeat(), this.stopQualitySampling(), !this.joined && !e && this.rejectJoin?.(new Error(o.reason || "RTC signaling connection closed"));
235
- const l = !this.stopped && (this.joined || e);
236
- this.joined = !1, l ? (this.resetPeers(), this.options.onEvent("reconnecting", { reason: o.reason, code: o.code, attempt: this.reconnectAttempt + 1 }), this.scheduleReconnect()) : this.stopped || this.options.onEvent("disconnected", { reason: o.reason, code: o.code });
234
+ this.socket = null, this.stopHeartbeat(), this.stopQualitySampling(), !this.joined && !e && this.rejectJoin?.(new Error(c.reason || "RTC signaling connection closed"));
235
+ const d = !this.stopped && (this.joined || e);
236
+ this.joined = !1, d ? (this.resetPeers(), this.options.onEvent("reconnecting", { reason: c.reason, code: c.code, attempt: this.reconnectAttempt + 1 }), this.scheduleReconnect()) : this.stopped || this.options.onEvent("disconnected", { reason: c.reason, code: c.code });
237
237
  });
238
238
  try {
239
239
  await n, this.joined = !0, this.options.onEvent("connected", { participantId: t.participantId, resumed: e });
240
240
  } finally {
241
- clearTimeout(r), this.resolveJoin = null, this.rejectJoin = null;
241
+ clearTimeout(o), this.resolveJoin = null, this.rejectJoin = null;
242
242
  }
243
243
  }
244
244
  async handleSignal(e) {
@@ -273,8 +273,8 @@ class A {
273
273
  const s = n.connection.signalingState !== "stable", a = !this.shouldInitiateOffer(t.sender);
274
274
  if (s && !a) return;
275
275
  s && await n.connection.setLocalDescription({ type: "rollback" }), await n.connection.setRemoteDescription(t.description);
276
- const r = await n.connection.createAnswer();
277
- await n.connection.setLocalDescription(r), this.send({
276
+ const o = await n.connection.createAnswer();
277
+ await n.connection.setLocalDescription(o), this.send({
278
278
  type: "rtc.answer",
279
279
  targetParticipantId: t.sender.participantId,
280
280
  negotiationId: t.negotiationId,
@@ -313,19 +313,19 @@ class A {
313
313
  makingOffer: !1,
314
314
  offerTask: null,
315
315
  activeNegotiationId: null,
316
- quality: A.startingQuality(this.quality),
316
+ quality: Q.startingQuality(this.quality),
317
317
  poorSamples: 0,
318
318
  goodSamples: 0,
319
319
  samplesSeen: 0,
320
320
  counters: null
321
321
  };
322
322
  this.peers.set(e.participantId, s);
323
- for (const o of this.localStream?.getAudioTracks() ?? []) i.addTrack(o, this.localStream);
324
- const a = this.screenStream?.getVideoTracks().some((o) => o.readyState === "live") ? this.screenStream : this.localStream, r = a?.getVideoTracks()[0];
325
- return r && a && (s.videoSender = i.addTrack(r, a)), !this.localStream?.getAudioTracks().length && this.options.receiveAudio && i.addTransceiver("audio", { direction: "recvonly" }), !r && this.options.receiveVideo && (s.videoTransceiver = i.addTransceiver("video", { direction: "recvonly" }), s.videoSender = s.videoTransceiver.sender), this.applyCodecPreference(i), this.applyVideoQuality(i), i.addEventListener("icecandidate", (o) => {
326
- o.candidate && this.send({ type: "rtc.ice", targetParticipantId: e.participantId, candidate: o.candidate.toJSON() });
327
- }), i.addEventListener("track", (o) => {
328
- n.getTracks().some((l) => l.id === o.track.id) || n.addTrack(o.track), this.options.onEvent("remotestream", { participant: e, stream: n, track: o.track });
323
+ for (const c of this.localStream?.getAudioTracks() ?? []) i.addTrack(c, this.localStream);
324
+ const a = this.screenStream?.getVideoTracks().some((c) => c.readyState === "live") ? this.screenStream : this.localStream, o = a?.getVideoTracks()[0];
325
+ return o && a && (s.videoSender = i.addTrack(o, a)), !this.localStream?.getAudioTracks().length && this.options.receiveAudio && i.addTransceiver("audio", { direction: "recvonly" }), !o && this.options.receiveVideo && (s.videoTransceiver = i.addTransceiver("video", { direction: "recvonly" }), s.videoSender = s.videoTransceiver.sender), this.applyCodecPreference(i), this.applyVideoQuality(i), i.addEventListener("icecandidate", (c) => {
326
+ c.candidate && this.send({ type: "rtc.ice", targetParticipantId: e.participantId, candidate: c.candidate.toJSON() });
327
+ }), i.addEventListener("track", (c) => {
328
+ n.getTracks().some((d) => d.id === c.track.id) || n.addTrack(c.track), this.options.onEvent("remotestream", { participant: e, stream: n, track: c.track });
329
329
  }), i.addEventListener("connectionstatechange", () => {
330
330
  ["failed", "closed"].includes(i.connectionState) && this.removePeer(e.participantId), this.options.onEvent("peerconnectionstate", { participant: e, state: i.connectionState });
331
331
  }), s;
@@ -351,7 +351,7 @@ class A {
351
351
  });
352
352
  if (e.connection.signalingState !== "stable") return;
353
353
  await e.connection.setLocalDescription(t);
354
- const i = L();
354
+ const i = H();
355
355
  e.activeNegotiationId = i, this.send({
356
356
  type: "rtc.offer",
357
357
  targetParticipantId: e.identity.participantId,
@@ -391,8 +391,8 @@ class A {
391
391
  async applyPeerVideoQuality(e) {
392
392
  const t = this.screenStream?.getVideoTracks()[0]?.id;
393
393
  for (const i of e.connection.getSenders().filter((n) => n.track?.kind === "video")) {
394
- const n = !!(t && i.track?.id === t), s = n ? ne : this.quality === "audio" ? ie.audio : f[e.quality], a = i.getParameters(), r = a.encodings?.length ? a.encodings : [{}];
395
- a.encodings = r.map((o) => ({ ...o, ...s })), a.degradationPreference = n ? "maintain-resolution" : "maintain-framerate", await i.setParameters(a);
394
+ const n = !!(t && i.track?.id === t), s = n ? de : this.quality === "audio" ? le.audio : M[e.quality], a = i.getParameters(), o = a.encodings?.length ? a.encodings : [{}];
395
+ a.encodings = o.map((c) => ({ ...c, ...s })), a.degradationPreference = n ? "maintain-resolution" : "maintain-framerate", await i.setParameters(a);
396
396
  }
397
397
  }
398
398
  startQualitySampling() {
@@ -411,11 +411,11 @@ class A {
411
411
  if (i.connection.connectionState === "connected")
412
412
  try {
413
413
  const n = await i.connection.getStats();
414
- for (const s of _(n.values()))
414
+ for (const s of ne(n.values()))
415
415
  e.push({ participantId: i.identity.participantId, level: s.level });
416
416
  } catch {
417
417
  }
418
- const t = H(e, this.activeSpeaker);
418
+ const t = ie(e, this.activeSpeaker);
419
419
  t !== this.activeSpeaker && (this.activeSpeaker = t, this.options.onEvent("activespeaker", { participantId: t }));
420
420
  }
421
421
  async samplePeerQuality() {
@@ -428,9 +428,9 @@ class A {
428
428
  } catch {
429
429
  continue;
430
430
  }
431
- const { sample: i, counters: n } = te(t, e.counters);
431
+ const { sample: i, counters: n } = ce(t, e.counters);
432
432
  e.counters = n;
433
- const s = ee(e.quality, i, e.poorSamples, e.goodSamples, {
433
+ const s = oe(e.quality, i, e.poorSamples, e.goodSamples, {
434
434
  samplesSeen: e.samplesSeen,
435
435
  ceiling: this.quality
436
436
  });
@@ -487,7 +487,7 @@ class A {
487
487
  }
488
488
  send(e) {
489
489
  this.socket?.readyState === WebSocket.OPEN && this.socket.send(JSON.stringify({
490
- clientMessageId: e.clientMessageId ?? L(),
490
+ clientMessageId: e.clientMessageId ?? H(),
491
491
  ...e
492
492
  }));
493
493
  }
@@ -495,15 +495,15 @@ class A {
495
495
  for (const t of e?.getTracks() ?? []) t.stop();
496
496
  }
497
497
  }
498
- function L() {
498
+ function H() {
499
499
  return globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
500
500
  }
501
- const M = { active: !0, maxBitrate: 4e6, maxFramerate: 30, scaleResolutionDownBy: 1 }, j = [
502
- { rid: "a", maxBitrate: f.high.maxBitrate, maxFramerate: f.high.maxFramerate },
503
- { rid: "b", maxBitrate: f.medium.maxBitrate, maxFramerate: f.medium.maxFramerate, scaleResolutionDownBy: 2 },
504
- { rid: "c", maxBitrate: f.low.maxBitrate, maxFramerate: f.low.maxFramerate, scaleResolutionDownBy: 4 }
505
- ], O = { high: "a", medium: "b", low: "c" };
506
- class se {
501
+ const U = { active: !0, maxBitrate: 4e6, maxFramerate: 30, scaleResolutionDownBy: 1 }, _ = [
502
+ { rid: "a", maxBitrate: M.high.maxBitrate, maxFramerate: M.high.maxFramerate },
503
+ { rid: "b", maxBitrate: M.medium.maxBitrate, maxFramerate: M.medium.maxFramerate, scaleResolutionDownBy: 2 },
504
+ { rid: "c", maxBitrate: M.low.maxBitrate, maxFramerate: M.low.maxFramerate, scaleResolutionDownBy: 4 }
505
+ ], W = { high: "a", medium: "b", low: "c" };
506
+ class he {
507
507
  options;
508
508
  apiBase;
509
509
  socket = null;
@@ -594,13 +594,13 @@ class se {
594
594
  async setDevice(e) {
595
595
  const t = { deviceId: { exact: e.deviceId } }, i = await navigator.mediaDevices.getUserMedia(e.kind === "audioinput" ? { audio: t } : { video: { ...t, width: { ideal: 1920 }, height: { ideal: 1080 }, frameRate: { ideal: 30, max: 30 } } }), n = e.kind === "audioinput" ? i.getAudioTracks()[0] : i.getVideoTracks()[0];
596
596
  if (!n) throw new Error("Selected media device is unavailable");
597
- const s = e.kind === "audioinput" ? "audio" : "video", a = this.localStream?.getTracks().find((o) => o.kind === s);
597
+ const s = e.kind === "audioinput" ? "audio" : "video", a = this.localStream?.getTracks().find((c) => c.kind === s);
598
598
  if (this.localStream || (this.localStream = new MediaStream()), a && (this.localStream.removeTrack(a), a.stop()), this.localStream.addTrack(n), s === "video") {
599
- this.screenStream?.getVideoTracks().some((o) => o.readyState === "live") || await this.replaceVideoTrack(n);
599
+ this.screenStream?.getVideoTracks().some((c) => c.readyState === "live") || await this.replaceVideoTrack(n);
600
600
  return;
601
601
  }
602
- const r = this.connection?.getSenders().find((o) => o.track?.kind === "audio");
603
- r && await r.replaceTrack(n);
602
+ const o = this.connection?.getSenders().find((c) => c.track?.kind === "audio");
603
+ o && await o.replaceTrack(n);
604
604
  }
605
605
  /** One uplink serves everyone, so the requested quality applies directly. */
606
606
  async setQuality(e) {
@@ -638,31 +638,31 @@ class se {
638
638
  async openSocket(e) {
639
639
  const { credential: t } = this.options, i = new URL(t.signalingUrl, globalThis.location?.href);
640
640
  i.protocol = i.protocol === "https:" ? "wss:" : "ws:";
641
- const n = new Promise((o, l) => {
642
- this.resolveJoin = o, this.rejectJoin = l;
641
+ const n = new Promise((c, d) => {
642
+ this.resolveJoin = c, this.rejectJoin = d;
643
643
  }), s = new WebSocket(i, ["rtc-client", t.signalingToken]), a = ++this.socketGeneration;
644
644
  this.socket = s;
645
- const r = setTimeout(() => this.rejectJoin?.(new Error("RTC signaling timed out")), 15e3);
645
+ const o = setTimeout(() => this.rejectJoin?.(new Error("RTC signaling timed out")), 15e3);
646
646
  s.addEventListener("open", () => {
647
647
  this.heartbeatDeadline = Date.now() + 45e3, this.startHeartbeat(s), this.send({ type: "rtc.room.join" });
648
- }), s.addEventListener("message", (o) => {
649
- const l = String(o.data);
648
+ }), s.addEventListener("message", (c) => {
649
+ const d = String(c.data);
650
650
  this.signalQueue = this.signalQueue.then(async () => {
651
- this.socket !== s || this.socketGeneration !== a || await this.handleSignal(l);
652
- }).catch((d) => {
653
- const u = d instanceof Error ? d.message : "RTC signaling processing failed";
654
- this.options.onEvent("signalingerror", { message: u }), this.joined || this.rejectJoin?.(new Error(u));
651
+ this.socket !== s || this.socketGeneration !== a || await this.handleSignal(d);
652
+ }).catch((l) => {
653
+ const h = l instanceof Error ? l.message : "RTC signaling processing failed";
654
+ this.options.onEvent("signalingerror", { message: h }), this.joined || this.rejectJoin?.(new Error(h));
655
655
  });
656
- }), s.addEventListener("error", () => this.rejectJoin?.(new Error("RTC signaling connection failed"))), s.addEventListener("close", (o) => {
656
+ }), s.addEventListener("error", () => this.rejectJoin?.(new Error("RTC signaling connection failed"))), s.addEventListener("close", (c) => {
657
657
  if (this.socket !== s) return;
658
- this.socket = null, this.stopHeartbeat(), !this.joined && !e && this.rejectJoin?.(new Error(o.reason || "RTC signaling connection closed"));
659
- const l = !this.stopped && (this.joined || e);
660
- this.joined = !1, l ? (this.options.onEvent("reconnecting", { reason: o.reason, code: o.code, attempt: this.reconnectAttempt + 1 }), this.scheduleReconnect()) : this.stopped || this.options.onEvent("disconnected", { reason: o.reason, code: o.code });
658
+ this.socket = null, this.stopHeartbeat(), !this.joined && !e && this.rejectJoin?.(new Error(c.reason || "RTC signaling connection closed"));
659
+ const d = !this.stopped && (this.joined || e);
660
+ this.joined = !1, d ? (this.options.onEvent("reconnecting", { reason: c.reason, code: c.code, attempt: this.reconnectAttempt + 1 }), this.scheduleReconnect()) : this.stopped || this.options.onEvent("disconnected", { reason: c.reason, code: c.code });
661
661
  });
662
662
  try {
663
663
  await n, this.joined = !0, this.options.onEvent("connected", { participantId: t.participantId, resumed: e });
664
664
  } finally {
665
- clearTimeout(r), this.resolveJoin = null, this.rejectJoin = null;
665
+ clearTimeout(o), this.resolveJoin = null, this.rejectJoin = null;
666
666
  }
667
667
  }
668
668
  async handleSignal(e) {
@@ -710,15 +710,15 @@ class se {
710
710
  iceServers: this.options.credential.iceServers ?? [],
711
711
  iceTransportPolicy: this.options.iceTransportPolicy ?? "all"
712
712
  });
713
- this.connection = t, t.addEventListener("track", (r) => this.handleRemoteTrack(r)), t.addEventListener("connectionstatechange", () => {
713
+ this.connection = t, t.addEventListener("track", (o) => this.handleRemoteTrack(o)), t.addEventListener("connectionstatechange", () => {
714
714
  this.options.onEvent("peerconnectionstate", { participant: this.selfIdentity(), state: t.connectionState });
715
715
  });
716
716
  const i = await this.sfuFetch("POST", "/v1/rtc/sfu/sessions");
717
717
  if (this.sessionId = i.sessionId, e.length === 0) return;
718
- const n = e.map((r) => t.addTransceiver(r, {
718
+ const n = e.map((o) => t.addTransceiver(o, {
719
719
  direction: "sendonly",
720
720
  streams: this.localStream ? [this.localStream] : [],
721
- ...r.kind === "video" ? { sendEncodings: j.map((o) => ({ ...o })) } : {}
721
+ ...o.kind === "video" ? { sendEncodings: _.map((c) => ({ ...c })) } : {}
722
722
  })), s = await t.createOffer();
723
723
  await t.setLocalDescription(s);
724
724
  const a = await this.sfuFetch(
@@ -726,14 +726,14 @@ class se {
726
726
  `/v1/rtc/sfu/sessions/${encodeURIComponent(i.sessionId)}/tracks`,
727
727
  {
728
728
  sessionDescription: t.localDescription,
729
- tracks: n.map((r) => ({
729
+ tracks: n.map((o) => ({
730
730
  location: "local",
731
- mid: r.mid,
732
- trackName: this.trackName(r.sender.track)
731
+ mid: o.mid,
732
+ trackName: this.trackName(o.sender.track)
733
733
  }))
734
734
  }
735
735
  );
736
- a.sessionDescription && await t.setRemoteDescription(a.sessionDescription), this.videoSender = t.getSenders().find((r) => r.track?.kind === "video") ?? null, await this.applyVideoQuality();
736
+ a.sessionDescription && await t.setRemoteDescription(a.sessionDescription), this.videoSender = t.getSenders().find((o) => o.track?.kind === "video") ?? null, await this.applyVideoQuality();
737
737
  }
738
738
  trackName(e) {
739
739
  return `${this.options.credential.participantId}/${e.kind}`;
@@ -747,7 +747,7 @@ class se {
747
747
  e.length !== 0 && this.sendControl("sfu.tracks", { sessionId: this.sessionId, tracks: e });
748
748
  }
749
749
  async handleTrackAnnouncement(e, t) {
750
- const i = String(t?.sessionId ?? ""), n = (t?.tracks ?? []).map((r) => ({ trackName: String(r.trackName ?? ""), simulcast: r.simulcast === !0 })).filter((r) => !!r.trackName), s = n.map((r) => r.trackName);
750
+ const i = String(t?.sessionId ?? ""), n = (t?.tracks ?? []).map((o) => ({ trackName: String(o.trackName ?? ""), simulcast: o.simulcast === !0 })).filter((o) => !!o.trackName), s = n.map((o) => o.trackName);
751
751
  if (!i || s.length === 0 || e.participantId === this.options.credential.participantId) return;
752
752
  if (!this.connection || !this.sessionId) {
753
753
  this.pendingAnnouncements.set(e.participantId, { sender: e, detail: t ?? {} });
@@ -762,13 +762,13 @@ class se {
762
762
  mids: /* @__PURE__ */ new Map()
763
763
  };
764
764
  a.sessionId = i;
765
- for (const r of n)
766
- r.simulcast && a.simulcastNames.add(r.trackName);
765
+ for (const o of n)
766
+ o.simulcast && a.simulcastNames.add(o.trackName);
767
767
  this.remotes.set(e.participantId, a), this.negotiationQueue = this.negotiationQueue.then(async () => {
768
- const r = s.filter((o) => !a.trackNames.includes(o));
769
- r.length !== 0 && await this.subscribe(a, r);
770
- }).catch((r) => {
771
- this.options.onEvent("signalingerror", { message: r instanceof Error ? r.message : "SFU subscribe failed" });
768
+ const o = s.filter((c) => !a.trackNames.includes(c));
769
+ o.length !== 0 && await this.subscribe(a, o);
770
+ }).catch((o) => {
771
+ this.options.onEvent("signalingerror", { message: o instanceof Error ? o.message : "SFU subscribe failed" });
772
772
  }), await this.negotiationQueue;
773
773
  }
774
774
  async subscribe(e, t) {
@@ -818,7 +818,7 @@ class se {
818
818
  n && await this.sfuFetch("PUT", `/v1/rtc/sfu/sessions/${encodeURIComponent(this.sessionId)}/tracks/update`, {
819
819
  tracks: [{
820
820
  mid: n,
821
- simulcast: { preferredRid: O[t], priorityOrdering: "asciibetical", ridNotAvailable: "asciibetical" }
821
+ simulcast: { preferredRid: W[t], priorityOrdering: "asciibetical", ridNotAvailable: "asciibetical" }
822
822
  }]
823
823
  });
824
824
  }
@@ -830,16 +830,16 @@ class se {
830
830
  if (!e) return;
831
831
  const t = this.screenStream?.getVideoTracks()[0]?.id, i = !!(t && e.track?.id === t), n = e.getParameters(), s = n.encodings?.length ? n.encodings : [{}];
832
832
  if (s.length > 1) {
833
- const a = this.quality === "audio" ? null : O[this.quality];
834
- n.encodings = s.map((r) => {
833
+ const a = this.quality === "audio" ? null : W[this.quality];
834
+ n.encodings = s.map((o) => {
835
835
  if (i)
836
- return { ...r, active: r.rid === "a", ...r.rid === "a" ? { maxBitrate: M.maxBitrate, maxFramerate: M.maxFramerate } : {} };
837
- const o = j.find((d) => d.rid === r.rid), l = a != null && String(r.rid ?? "") >= a;
838
- return { ...r, ...o ?? {}, active: l };
836
+ return { ...o, active: o.rid === "a", ...o.rid === "a" ? { maxBitrate: U.maxBitrate, maxFramerate: U.maxFramerate } : {} };
837
+ const c = _.find((l) => l.rid === o.rid), d = a != null && String(o.rid ?? "") >= a;
838
+ return { ...o, ...c ?? {}, active: d };
839
839
  });
840
840
  } else {
841
- const a = this.quality === "audio" ? f.audio : f[this.quality], r = i ? M : a;
842
- n.encodings = s.map((o) => ({ ...o, ...r }));
841
+ const a = this.quality === "audio" ? M.audio : M[this.quality], o = i ? U : a;
842
+ n.encodings = s.map((c) => ({ ...c, ...o }));
843
843
  }
844
844
  n.degradationPreference = i ? "maintain-resolution" : "maintain-framerate", await e.setParameters(n);
845
845
  }
@@ -905,11 +905,11 @@ class se {
905
905
  return;
906
906
  }
907
907
  const i = [];
908
- for (const s of _(t.values())) {
908
+ for (const s of ne(t.values())) {
909
909
  const a = s.mid ? this.midToParticipant.get(s.mid) : void 0;
910
910
  a && i.push({ participantId: a, level: s.level });
911
911
  }
912
- const n = H(i, this.activeSpeaker);
912
+ const n = ie(i, this.activeSpeaker);
913
913
  n !== this.activeSpeaker && (this.activeSpeaker = n, this.options.onEvent("activespeaker", { participantId: n }));
914
914
  }
915
915
  clearTimers() {
@@ -926,7 +926,7 @@ class se {
926
926
  }
927
927
  send(e) {
928
928
  this.socket?.readyState === WebSocket.OPEN && this.socket.send(JSON.stringify({
929
- clientMessageId: e.clientMessageId ?? ae(),
929
+ clientMessageId: e.clientMessageId ?? ue(),
930
930
  ...e
931
931
  }));
932
932
  }
@@ -934,28 +934,28 @@ class se {
934
934
  for (const t of e?.getTracks() ?? []) t.stop();
935
935
  }
936
936
  }
937
- function ae() {
937
+ function ue() {
938
938
  return globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
939
939
  }
940
- function ve(c, e = {}) {
940
+ function Ee(r, e = {}) {
941
941
  const t = e.document ?? globalThis.document, i = !!(t && t.pictureInPictureEnabled);
942
942
  let n = null;
943
943
  function s() {
944
944
  return n || (n = t.createElement("video"), n.muted = !0, n.playsInline = !0, n.style.position = "fixed", n.style.width = "1px", n.style.height = "1px", n.style.opacity = "0", n.style.pointerEvents = "none", n.addEventListener("leavepictureinpicture", () => e.onLeave?.()), t.body.appendChild(n), n);
945
945
  }
946
- function a(r) {
947
- const o = c.getRemoteStreams();
948
- return r ? o.find((l) => l.participant.participantId === r)?.stream ?? null : o[0]?.stream ?? c.getLocalStream();
946
+ function a(o) {
947
+ const c = r.getRemoteStreams();
948
+ return o ? c.find((d) => d.participant.participantId === o)?.stream ?? null : c[0]?.stream ?? r.getLocalStream();
949
949
  }
950
950
  return {
951
951
  supported: i,
952
- async enter(r) {
952
+ async enter(o) {
953
953
  if (!i) throw new Error("This browser does not support picture-in-picture");
954
- const o = a(r);
955
- if (!o) throw new Error("No video stream is available for picture-in-picture");
956
- const l = s();
957
- l.srcObject !== o && (l.srcObject = o), await l.play().catch(() => {
958
- }), await l.requestPictureInPicture();
954
+ const c = a(o);
955
+ if (!c) throw new Error("No video stream is available for picture-in-picture");
956
+ const d = s();
957
+ d.srcObject !== c && (d.srcObject = c), await d.play().catch(() => {
958
+ }), await d.requestPictureInPicture();
959
959
  },
960
960
  async exit() {
961
961
  t.pictureInPictureElement && typeof t.exitPictureInPicture == "function" && await t.exitPictureInPicture();
@@ -965,7 +965,196 @@ function ve(c, e = {}) {
965
965
  }
966
966
  };
967
967
  }
968
- class re extends EventTarget {
968
+ function Re(r, e) {
969
+ const t = e.document ?? globalThis.document, i = e.fetchImplementation ?? globalThis.fetch.bind(globalThis), n = new URL(e.credential.signalingUrl, globalThis.location?.href).origin, s = e.mimeType ?? "video/webm", a = e.height ?? 720, o = Math.round(a * 16 / 9);
970
+ let c = null, d = null, l = null, h = null, v = 0, g = [], k = !1;
971
+ async function p(C, S, y, T = "application/json") {
972
+ const I = await i(`${n}${S}`, {
973
+ method: C,
974
+ headers: {
975
+ authorization: `Bearer ${e.credential.signalingToken}`,
976
+ "content-type": T
977
+ },
978
+ body: y === void 0 ? void 0 : T === "application/json" ? JSON.stringify(y) : y
979
+ });
980
+ if (!I.ok) throw new Error(`Recording request failed with HTTP ${I.status}`);
981
+ return I.json();
982
+ }
983
+ return {
984
+ get recording() {
985
+ return k;
986
+ },
987
+ async start() {
988
+ if (k) return;
989
+ h = (await p("POST", "/v1/rtc/recordings")).recordingId;
990
+ const S = t.createElement("canvas");
991
+ S.width = o, S.height = a;
992
+ const y = S.getContext("2d"), T = /* @__PURE__ */ new Map(), I = (b, P) => {
993
+ let w = T.get(b);
994
+ return w || (w = t.createElement("video"), w.muted = !0, w.playsInline = !0, w.srcObject = P, w.play().catch(() => {
995
+ }), T.set(b, w)), w;
996
+ };
997
+ d = setInterval(() => {
998
+ const b = r.getRemoteStreams(), P = r.getLocalStream(), w = [
999
+ ...b.map((D) => ({ key: D.participant.participantId, stream: D.stream, label: D.participant.displayName })),
1000
+ ...P ? [{ key: "local", stream: P, label: "me" }] : []
1001
+ ];
1002
+ y.fillStyle = "#101418", y.fillRect(0, 0, o, a);
1003
+ const N = Math.max(1, Math.ceil(Math.sqrt(w.length))), m = Math.max(1, Math.ceil(w.length / N)), A = o / N, V = a / m;
1004
+ w.forEach((D, z) => {
1005
+ const J = I(D.key, D.stream), j = z % N * A, B = Math.floor(z / N) * V;
1006
+ J.videoWidth > 0 && y.drawImage(J, j + 2, B + 2, A - 4, V - 4), y.fillStyle = "rgba(0,0,0,.6)", y.fillRect(j + 8, B + V - 30, Math.min(A - 16, 12 + D.label.length * 9), 22), y.fillStyle = "#fff", y.font = "14px system-ui", y.fillText(D.label, j + 14, B + V - 14);
1007
+ });
1008
+ }, 66);
1009
+ const R = S.captureStream(15);
1010
+ l = new AudioContext();
1011
+ const E = l.createMediaStreamDestination(), f = /* @__PURE__ */ new Set(), u = () => {
1012
+ const b = [
1013
+ ...r.getRemoteStreams().map((P) => P.stream),
1014
+ ...r.getLocalStream() ? [r.getLocalStream()] : []
1015
+ ];
1016
+ for (const P of b)
1017
+ for (const w of P.getAudioTracks())
1018
+ f.has(w.id) || (f.add(w.id), l.createMediaStreamSource(new MediaStream([w])).connect(E));
1019
+ };
1020
+ u();
1021
+ const q = setInterval(u, 1e3), L = () => clearInterval(q);
1022
+ for (const b of E.stream.getAudioTracks()) R.addTrack(b);
1023
+ c = (e.mediaRecorderFactory ?? ((b, P) => new MediaRecorder(b, P)))(R, { mimeType: s }), g = [], c.addEventListener("dataavailable", (b) => {
1024
+ b.data && b.data.size > 0 && g.push(b.data);
1025
+ }), c.addEventListener("stop", L), c.start(1e3), v = Date.now(), k = !0;
1026
+ },
1027
+ async stop() {
1028
+ if (!k || !c || !h) throw new Error("The recorder is not running");
1029
+ k = !1;
1030
+ const C = c, S = new Promise((E) => C.addEventListener("stop", () => E(), { once: !0 }));
1031
+ C.stop(), await S, d && clearInterval(d), d = null, await l?.close().catch(() => {
1032
+ }), l = null;
1033
+ const y = new Blob(g, { type: s });
1034
+ g = [];
1035
+ const T = Math.max(1, Math.round((Date.now() - v) / 1e3)), I = await p(
1036
+ "PUT",
1037
+ `/v1/rtc/recordings/${encodeURIComponent(h)}/media`,
1038
+ y,
1039
+ s
1040
+ );
1041
+ await p("POST", `/v1/rtc/recordings/${encodeURIComponent(h)}/complete`, { durationSeconds: T });
1042
+ const R = { recordingId: h, sizeBytes: I.sizeBytes, durationSeconds: T };
1043
+ return h = null, c = null, R;
1044
+ },
1045
+ dispose() {
1046
+ d && clearInterval(d), d = null;
1047
+ try {
1048
+ c?.stop();
1049
+ } catch {
1050
+ }
1051
+ c = null, l?.close().catch(() => {
1052
+ }), l = null, k = !1;
1053
+ }
1054
+ };
1055
+ }
1056
+ const me = ["none", "blur", "aurora", "cybergrid", "bokeh", "sunset", "image"], pe = ["none", "snow", "confetti", "vignette"], G = {
1057
+ aurora(r, e, t, i) {
1058
+ const n = r.createLinearGradient(0, 0, 0, t);
1059
+ n.addColorStop(0, "#050b1e"), n.addColorStop(1, "#0b2540"), r.fillStyle = n, r.fillRect(0, 0, e, t);
1060
+ for (let s = 0; s < 3; s += 1) {
1061
+ r.beginPath();
1062
+ for (let a = 0; a <= e; a += 16) {
1063
+ const o = t * 0.35 + s * 40 + Math.sin(a / 140 + i / 900 + s) * 60;
1064
+ a === 0 ? r.moveTo(a, o) : r.lineTo(a, o);
1065
+ }
1066
+ r.lineTo(e, 0), r.lineTo(0, 0), r.closePath(), r.fillStyle = `hsla(${140 + s * 40 + Math.sin(i / 1300) * 20}, 80%, 55%, 0.14)`, r.fill();
1067
+ }
1068
+ },
1069
+ cybergrid(r, e, t, i) {
1070
+ r.fillStyle = "#0a0118", r.fillRect(0, 0, e, t), r.strokeStyle = "rgba(255,0,180,0.5)", r.lineWidth = 1.5;
1071
+ const n = t * 0.45;
1072
+ for (let a = 0; a < 12; a += 1) {
1073
+ const o = n + (a * 34 + i / 18) % (t - n);
1074
+ r.beginPath(), r.moveTo(0, o), r.lineTo(e, o), r.stroke();
1075
+ }
1076
+ for (let a = -8; a <= 8; a += 1)
1077
+ r.beginPath(), r.moveTo(e / 2 + a * 24, n), r.lineTo(e / 2 + a * e * 0.12, t), r.stroke();
1078
+ const s = r.createLinearGradient(0, t * 0.1, 0, n);
1079
+ s.addColorStop(0, "#ffd34d"), s.addColorStop(1, "#ff2d78"), r.fillStyle = s, r.beginPath(), r.arc(e / 2, n, t * 0.22, Math.PI, 0), r.fill();
1080
+ },
1081
+ bokeh(r, e, t, i) {
1082
+ r.fillStyle = "#14100c", r.fillRect(0, 0, e, t);
1083
+ for (let n = 0; n < 26; n += 1) {
1084
+ const s = (Math.sin(n * 12.9898) * 0.5 + 0.5) * e, a = (Math.sin(n * 78.233) * 0.5 + 0.5) * t + Math.sin(i / 1500 + n) * 12, o = 14 + n % 5 * 12;
1085
+ r.fillStyle = `hsla(${35 + n % 4 * 12}, 90%, 60%, ${0.1 + n % 3 * 0.05})`, r.beginPath(), r.arc(s, a, o, 0, Math.PI * 2), r.fill();
1086
+ }
1087
+ },
1088
+ sunset(r, e, t, i) {
1089
+ const n = r.createLinearGradient(0, 0, 0, t);
1090
+ n.addColorStop(0, "#2b1055"), n.addColorStop(0.55, "#d1548a"), n.addColorStop(1, "#ffb36b"), r.fillStyle = n, r.fillRect(0, 0, e, t), r.fillStyle = "#ffdf8e", r.beginPath(), r.arc(e * 0.5, t * 0.62 + Math.sin(i / 4e3) * 4, t * 0.13, 0, Math.PI * 2), r.fill(), r.fillStyle = "rgba(20,8,40,0.85)", r.fillRect(0, t * 0.78, e, t * 0.22);
1091
+ }
1092
+ };
1093
+ function Pe(r, e = {}) {
1094
+ const t = e.document ?? globalThis.document, i = e.width ?? 1280, n = e.height ?? 720, s = e.frameRate ?? 24, a = r instanceof MediaStreamTrack ? r : r.getVideoTracks()[0];
1095
+ if (!a) throw new Error("A video track is required");
1096
+ let o = e.background ?? "none", c = e.overlay ?? "none", d = e.backgroundImage ?? null, l = e.segmenter ?? null, h = null, v = !1;
1097
+ const g = t.createElement("video");
1098
+ g.muted = !0, g.playsInline = !0, g.srcObject = new MediaStream([a]), g.play().catch(() => {
1099
+ });
1100
+ const k = t.createElement("canvas");
1101
+ k.width = i, k.height = n;
1102
+ const p = k.getContext("2d"), C = t.createElement("canvas");
1103
+ C.width = i, C.height = n;
1104
+ const S = C.getContext("2d"), y = Array.from({ length: 80 }, (f, u) => ({
1105
+ x: (Math.sin(u * 12.9898) * 0.5 + 0.5) * i,
1106
+ y: (Math.sin(u * 78.233) * 0.5 + 0.5) * n,
1107
+ speed: 0.6 + u % 5 * 0.5,
1108
+ drift: Math.sin(u) * 0.6,
1109
+ size: 2 + u % 4,
1110
+ hue: u * 47 % 360
1111
+ }));
1112
+ function T() {
1113
+ if (h) {
1114
+ S.clearRect(0, 0, i, n), S.drawImage(h, 0, 0, i, n), S.globalCompositeOperation = "source-in", S.drawImage(g, 0, 0, i, n), S.globalCompositeOperation = "source-over", p.drawImage(C, 0, 0);
1115
+ return;
1116
+ }
1117
+ const f = i * 0.42, u = f * 9 / 16, q = i - f - 24, L = n - u - 24;
1118
+ p.save(), p.shadowColor = "rgba(0,0,0,.5)", p.shadowBlur = 24, p.beginPath(), p.roundRect(q, L, f, u, 14), p.clip(), p.drawImage(g, q, L, f, u), p.restore();
1119
+ }
1120
+ function I(f) {
1121
+ if (o === "none" ? p.drawImage(g, 0, 0, i, n) : o === "blur" ? (p.filter = "blur(14px)", p.drawImage(g, -16, -16, i + 32, n + 32), p.filter = "none", h && T()) : o === "image" && d ? (p.drawImage(d, 0, 0, i, n), T()) : ((G[o] ?? G.aurora)(p, i, n, f), T()), c === "snow" || c === "confetti")
1122
+ for (const u of y)
1123
+ u.y += u.speed * (c === "confetti" ? 1.6 : 1), u.x += u.drift, u.y > n && (u.y = -6, u.x = Math.random() * i), p.fillStyle = c === "snow" ? "rgba(255,255,255,.85)" : `hsl(${u.hue}, 90%, 60%)`, c === "confetti" ? p.fillRect(u.x, u.y, u.size + 2, u.size) : (p.beginPath(), p.arc(u.x, u.y, u.size / 2, 0, Math.PI * 2), p.fill());
1124
+ else if (c === "vignette") {
1125
+ const u = p.createRadialGradient(i / 2, n / 2, n * 0.4, i / 2, n / 2, n * 0.85);
1126
+ u.addColorStop(0, "rgba(0,0,0,0)"), u.addColorStop(1, "rgba(0,0,0,0.55)"), p.fillStyle = u, p.fillRect(0, 0, i, n);
1127
+ }
1128
+ }
1129
+ const R = setInterval(() => {
1130
+ I(Date.now()), l && !v && o !== "none" && (v = !0, l.segment(g).then((f) => {
1131
+ h = f;
1132
+ }).catch(() => {
1133
+ h = null;
1134
+ }).finally(() => {
1135
+ v = !1;
1136
+ }));
1137
+ }, Math.round(1e3 / s)), E = k.captureStream(s);
1138
+ return {
1139
+ track: E.getVideoTracks()[0],
1140
+ stream: E,
1141
+ setBackground(f, u) {
1142
+ o = me.includes(f) ? f : "none", u !== void 0 && (d = u), o === "none" && (h = null);
1143
+ },
1144
+ setOverlay(f) {
1145
+ c = pe.includes(f) ? f : "none";
1146
+ },
1147
+ setSegmenter(f) {
1148
+ l = f, f || (h = null);
1149
+ },
1150
+ dispose() {
1151
+ clearInterval(R), l?.close?.();
1152
+ for (const f of E.getTracks()) f.stop();
1153
+ g.srcObject = null;
1154
+ }
1155
+ };
1156
+ }
1157
+ class fe extends EventTarget {
969
1158
  mode;
970
1159
  options;
971
1160
  client = null;
@@ -999,7 +1188,7 @@ class re extends EventTarget {
999
1188
  async initialize() {
1000
1189
  if (this.client) return this;
1001
1190
  try {
1002
- const t = (this.options.transport === "auto" ? this.mode === "meeting" ? "sfu" : "mesh" : this.options.transport ?? "mesh") === "sfu" ? se : A;
1191
+ const t = (this.options.transport === "auto" ? this.mode === "meeting" ? "sfu" : "mesh" : this.options.transport ?? "mesh") === "sfu" ? he : Q;
1003
1192
  return this.client = new t({
1004
1193
  credential: {
1005
1194
  signalingToken: this.options.credential.signalingToken,
@@ -1018,19 +1207,19 @@ class re extends EventTarget {
1018
1207
  iceTransportPolicy: this.options.iceTransportPolicy ?? "all",
1019
1208
  localStream: this.options.localStream,
1020
1209
  onEvent: (i, n) => this.handleNativeEvent(i, n)
1021
- }), await this.client.initialize(), this.startStats(), this.emit("initialized", { mode: this.mode, sdkVersion: pe }), this.options.autoJoin && await this.join(), this;
1210
+ }), await this.client.initialize(), this.startStats(), this.emit("initialized", { mode: this.mode, sdkVersion: be }), this.options.autoJoin && await this.join(), this;
1022
1211
  } catch (e) {
1023
1212
  this.state = "failed";
1024
- const t = z(e, "RTC initialization failed");
1025
- throw this.emit("error", g(t)), t;
1213
+ const t = te(e, "RTC initialization failed");
1214
+ throw this.emit("error", x(t)), t;
1026
1215
  }
1027
1216
  }
1028
1217
  async join() {
1029
1218
  const e = this.requireClient();
1030
1219
  return this.joinPromise ? this.joinPromise : (this.state = "joining", this.emit("joining", {}), this.joinPromise = e.join().catch((t) => {
1031
1220
  this.state = "failed";
1032
- const i = z(t, "RTC connection failed");
1033
- throw this.emit("error", g(i)), i;
1221
+ const i = te(t, "RTC connection failed");
1222
+ throw this.emit("error", x(i)), i;
1034
1223
  }).finally(() => {
1035
1224
  this.joinPromise = null;
1036
1225
  }), this.joinPromise);
@@ -1068,14 +1257,14 @@ class re extends EventTarget {
1068
1257
  return navigator.mediaDevices?.enumerateDevices ? navigator.mediaDevices.enumerateDevices() : [];
1069
1258
  }
1070
1259
  getParticipants() {
1071
- return this.requireClient().getParticipants().map(F);
1260
+ return this.requireClient().getParticipants().map(X);
1072
1261
  }
1073
1262
  getLocalStream() {
1074
1263
  return this.client?.getLocalStream() ?? null;
1075
1264
  }
1076
1265
  getRemoteStreams() {
1077
1266
  return (this.client?.getRemoteStreams() ?? []).map((e) => ({
1078
- participant: F(e.participant),
1267
+ participant: X(e.participant),
1079
1268
  stream: e.stream
1080
1269
  }));
1081
1270
  }
@@ -1144,45 +1333,45 @@ class re extends EventTarget {
1144
1333
  let n = "unavailable";
1145
1334
  if (e.requestMedia !== !1 && navigator.mediaDevices?.getUserMedia)
1146
1335
  try {
1147
- (await navigator.mediaDevices.getUserMedia({ audio: this.options.audio, video: this.options.video })).getTracks().forEach((m) => m.stop()), n = "granted";
1336
+ (await navigator.mediaDevices.getUserMedia({ audio: this.options.audio, video: this.options.video })).getTracks().forEach((v) => v.stop()), n = "granted";
1148
1337
  } catch {
1149
1338
  n = "denied", t.push("media_permission_denied");
1150
1339
  }
1151
- const s = navigator.mediaDevices?.enumerateDevices ? await navigator.mediaDevices.enumerateDevices().catch(() => []) : [], a = s.filter((u) => u.kind === "audioinput").length, r = s.filter((u) => u.kind === "videoinput").length;
1152
- this.options.audio && a === 0 && t.push("microphone_unavailable"), this.options.video && r === 0 && t.push("camera_unavailable");
1153
- const o = e.probeUrl ?? this.options.preflightProbeUrl;
1154
- let l = null;
1155
- if (o) {
1156
- const u = performance.now();
1340
+ const s = navigator.mediaDevices?.enumerateDevices ? await navigator.mediaDevices.enumerateDevices().catch(() => []) : [], a = s.filter((h) => h.kind === "audioinput").length, o = s.filter((h) => h.kind === "videoinput").length;
1341
+ this.options.audio && a === 0 && t.push("microphone_unavailable"), this.options.video && o === 0 && t.push("camera_unavailable");
1342
+ const c = e.probeUrl ?? this.options.preflightProbeUrl;
1343
+ let d = null;
1344
+ if (c) {
1345
+ const h = performance.now();
1157
1346
  try {
1158
- const m = await fetch(o, { method: "HEAD", cache: "no-store", credentials: "omit" });
1159
- l = Math.round(performance.now() - u), m.ok || t.push("network_probe_failed");
1347
+ const v = await fetch(c, { method: "HEAD", cache: "no-store", credentials: "omit" });
1348
+ d = Math.round(performance.now() - h), v.ok || t.push("network_probe_failed");
1160
1349
  } catch {
1161
1350
  t.push("network_probe_failed");
1162
1351
  }
1163
1352
  }
1164
- const d = {
1353
+ const l = {
1165
1354
  passed: t.length === 0,
1166
1355
  sampledAt: (/* @__PURE__ */ new Date()).toISOString(),
1167
1356
  secureContext: i,
1168
1357
  mediaPermission: n,
1169
1358
  microphoneCount: a,
1170
- cameraCount: r,
1171
- probeLatencyMs: l,
1172
- effectiveConnectionType: J()?.effectiveType ?? null,
1359
+ cameraCount: o,
1360
+ probeLatencyMs: d,
1361
+ effectiveConnectionType: Z()?.effectiveType ?? null,
1173
1362
  issues: t
1174
1363
  };
1175
- return this.emit("preflight", d), this.options.autoReportStats && await this.reportQuality({
1364
+ return this.emit("preflight", l), this.options.autoReportStats && await this.reportQuality({
1176
1365
  sampleType: "preflight",
1177
- sampledAt: d.sampledAt,
1178
- connectionState: d.passed ? "ready" : "failed",
1179
- rttMs: d.probeLatencyMs,
1180
- effectiveConnectionType: d.effectiveConnectionType
1366
+ sampledAt: l.sampledAt,
1367
+ connectionState: l.passed ? "ready" : "failed",
1368
+ rttMs: l.probeLatencyMs,
1369
+ effectiveConnectionType: l.effectiveConnectionType
1181
1370
  }).catch(() => {
1182
- }), d;
1371
+ }), l;
1183
1372
  }
1184
1373
  async collectQualitySample(e = "runtime") {
1185
- const t = this.options.statsProvider ? await this.options.statsProvider() : {}, i = this.peerConnection ? await he(this.peerConnection, this.previousCounters) : null;
1374
+ const t = this.options.statsProvider ? await this.options.statsProvider() : {}, i = this.peerConnection ? await ke(this.peerConnection, this.previousCounters) : null;
1186
1375
  i?.counters && (this.previousCounters = i.counters);
1187
1376
  const s = { ...{
1188
1377
  sampleType: e,
@@ -1211,9 +1400,9 @@ class re extends EventTarget {
1211
1400
  transportProtocol: null,
1212
1401
  candidateType: null,
1213
1402
  qualityLimitationReason: null,
1214
- deviceMemoryGb: me(),
1215
- effectiveConnectionType: J()?.effectiveType ?? null
1216
- }, ...i?.sample ?? {}, ...t, sampleType: e, sampledAt: (/* @__PURE__ */ new Date()).toISOString() }, a = ue(s);
1403
+ deviceMemoryGb: we(),
1404
+ effectiveConnectionType: Z()?.effectiveType ?? null
1405
+ }, ...i?.sample ?? {}, ...t, sampleType: e, sampledAt: (/* @__PURE__ */ new Date()).toISOString() }, a = Te(s);
1217
1406
  return s.networkScore = a.networkScore, s.estimatedMos = a.estimatedMos, this.latestQuality = s, s;
1218
1407
  }
1219
1408
  async reportQuality(e) {
@@ -1264,7 +1453,7 @@ class re extends EventTarget {
1264
1453
  const i = Date.now(), n = e !== "runtime" || i - this.lastTelemetryAt >= this.options.telemetryInterval;
1265
1454
  this.options.autoReportStats && n && (await this.reportQuality(t), this.lastTelemetryAt = i);
1266
1455
  } catch (t) {
1267
- this.emit("telemetryerror", g(t));
1456
+ this.emit("telemetryerror", x(t));
1268
1457
  } finally {
1269
1458
  this.statsRunning = !1;
1270
1459
  }
@@ -1281,8 +1470,8 @@ class re extends EventTarget {
1281
1470
  }
1282
1471
  const t = String(e.qualityLimitationReason ?? "").toLowerCase(), i = (e.packetLossPct ?? 0) >= 8 || (e.rttMs ?? 0) >= 800 || t === "cpu" || t === "bandwidth", n = i || (e.packetLossPct ?? 0) >= 3 || (e.rttMs ?? 0) >= 350 || e.availableOutgoingBitrateBps != null && e.availableOutgoingBitrateBps < 35e4, s = (e.packetLossPct ?? 100) < 1 && (e.rttMs ?? 1e3) < 180 && !t && (e.availableOutgoingBitrateBps == null || e.availableOutgoingBitrateBps > 1e6);
1283
1472
  this.poorQualitySamples = n ? this.poorQualitySamples + 1 : 0, this.goodQualitySamples = s ? this.goodQualitySamples + 1 : 0;
1284
- const a = ["low", "medium", "high"], r = a.indexOf(this.effectiveQuality);
1285
- i && r > 0 ? (this.poorQualitySamples = 0, await this.applyEffectiveQuality("low", "network")) : this.poorQualitySamples >= 2 && r > 0 ? (this.poorQualitySamples = 0, await this.applyEffectiveQuality(a[r - 1], "network")) : this.goodQualitySamples >= 6 && r >= 0 && r < a.length - 1 && (this.goodQualitySamples = 0, await this.applyEffectiveQuality(a[r + 1], "network"));
1473
+ const a = ["low", "medium", "high"], o = a.indexOf(this.effectiveQuality);
1474
+ i && o > 0 ? (this.poorQualitySamples = 0, await this.applyEffectiveQuality("low", "network")) : this.poorQualitySamples >= 2 && o > 0 ? (this.poorQualitySamples = 0, await this.applyEffectiveQuality(a[o - 1], "network")) : this.goodQualitySamples >= 6 && o >= 0 && o < a.length - 1 && (this.goodQualitySamples = 0, await this.applyEffectiveQuality(a[o + 1], "network"));
1286
1475
  }
1287
1476
  async applyEffectiveQuality(e, t) {
1288
1477
  if (this.effectiveQuality === e && this.client) return;
@@ -1298,21 +1487,21 @@ class re extends EventTarget {
1298
1487
  this.dispatchEvent(new CustomEvent(e, { detail: i })), this.options.onEvent?.(i);
1299
1488
  }
1300
1489
  }
1301
- async function ye(c) {
1302
- return new re(c).initialize();
1490
+ async function Me(r) {
1491
+ return new fe(r).initialize();
1303
1492
  }
1304
- let P = null;
1305
- function W() {
1306
- if (P) return P;
1307
- const c = globalThis, e = c.AudioContext ?? c.webkitAudioContext;
1308
- return e ? (P = new e(), P) : null;
1493
+ let O = null;
1494
+ function se() {
1495
+ if (O) return O;
1496
+ const r = globalThis, e = r.AudioContext ?? r.webkitAudioContext;
1497
+ return e ? (O = new e(), O) : null;
1309
1498
  }
1310
- async function oe() {
1311
- const c = W();
1312
- return c ? (c.state === "suspended" && await c.resume().catch(() => {
1313
- }), c.state === "running") : !1;
1499
+ async function ge() {
1500
+ const r = se();
1501
+ return r ? (r.state === "suspended" && await r.resume().catch(() => {
1502
+ }), r.state === "running") : !1;
1314
1503
  }
1315
- class ce {
1504
+ class ve {
1316
1505
  options;
1317
1506
  media = null;
1318
1507
  cadenceTimer = null;
@@ -1321,7 +1510,7 @@ class ce {
1321
1510
  this.options = e;
1322
1511
  }
1323
1512
  unlock() {
1324
- return oe();
1513
+ return ge();
1325
1514
  }
1326
1515
  startIncoming() {
1327
1516
  this.start("incoming", this.options.ringtoneUrl);
@@ -1349,17 +1538,17 @@ class ce {
1349
1538
  i(), this.cadenceTimer = setInterval(i, e === "incoming" ? 3e3 : 3500);
1350
1539
  }
1351
1540
  playBuiltInTone(e) {
1352
- const t = W();
1541
+ const t = se();
1353
1542
  if (!t || t.state !== "running") return;
1354
1543
  const i = e === "incoming" ? 1.25 : 1, n = e === "incoming" ? [440, 480] : [425], s = t.createGain(), a = t.currentTime;
1355
1544
  s.gain.setValueAtTime(1e-4, a), s.gain.exponentialRampToValueAtTime(0.045, a + 0.025), s.gain.setValueAtTime(0.045, a + i - 0.06), s.gain.exponentialRampToValueAtTime(1e-4, a + i), s.connect(t.destination);
1356
- for (const r of n) {
1357
- const o = t.createOscillator();
1358
- o.type = "sine", o.frequency.value = r, o.connect(s), this.oscillators.add(o), o.onended = () => this.oscillators.delete(o), o.start(a), o.stop(a + i + 0.02);
1545
+ for (const o of n) {
1546
+ const c = t.createOscillator();
1547
+ c.type = "sine", c.frequency.value = o, c.connect(s), this.oscillators.add(c), c.onended = () => this.oscillators.delete(c), c.start(a), c.stop(a + i + 0.02);
1359
1548
  }
1360
1549
  }
1361
1550
  }
1362
- class le extends EventTarget {
1551
+ class ye extends EventTarget {
1363
1552
  options;
1364
1553
  socket = null;
1365
1554
  stopped = !1;
@@ -1386,14 +1575,14 @@ class le extends EventTarget {
1386
1575
  if (e.token && !e.token.startsWith("rtcc_")) throw new Error("A valid RTC client token is required");
1387
1576
  if (!e.signalingUrl && !e.apiBaseUrl && !globalThis.location?.origin)
1388
1577
  throw new Error("signalingUrl or apiBaseUrl is required outside a browser");
1389
- this.options = e, this.currentToken = e.token ?? null, this.currentTokenExpiresAt = e.tokenExpiresAt, this.callAudio = new ce(e), this.mount = B(e.mount), this.scheduleTokenRefresh();
1578
+ this.options = e, this.currentToken = e.token ?? null, this.currentTokenExpiresAt = e.tokenExpiresAt, this.callAudio = new ve(e), this.mount = K(e.mount), this.scheduleTokenRefresh();
1390
1579
  }
1391
1580
  connect() {
1392
1581
  if (!this.options.signalingUrl) throw new Error("signalingUrl is required to connect signaling");
1393
1582
  return this.stopped = !1, this.scheduleTokenRefresh(), this.openSocket("initial"), this;
1394
1583
  }
1395
1584
  setMount(e) {
1396
- this.clearUi(), this.mount = B(e), this.currentCall && this.renderIncoming(this.currentCall);
1585
+ this.clearUi(), this.mount = K(e), this.currentCall && this.renderIncoming(this.currentCall);
1397
1586
  }
1398
1587
  /** Binds media lifetime to a call. Terminal call states automatically leave and destroy it. */
1399
1588
  attachMediaClient(e, t) {
@@ -1479,7 +1668,7 @@ class le extends EventTarget {
1479
1668
  /** Applies a call state received through the application's own push or signaling channel. */
1480
1669
  handleCallUpdate(e) {
1481
1670
  const t = e.id === this.currentCall?.id || e.id === this.outgoingCallId;
1482
- t && e.status === "accepted" ? (this.activeCallIds.add(e.id), this.callAudio.stop(), this.dismiss(e.id)) : t && ["rejected", "busy", "cancelled", "ended", "failed", "missed"].includes(e.status) && this.showTerminal(e.id, de(e.status)), ["rejected", "busy", "cancelled", "ended", "failed", "missed"].includes(e.status) && this.releaseMedia(e.id), this.emit("callupdated", e);
1671
+ t && e.status === "accepted" ? (this.activeCallIds.add(e.id), this.callAudio.stop(), this.dismiss(e.id)) : t && ["rejected", "busy", "cancelled", "ended", "failed", "missed"].includes(e.status) && this.showTerminal(e.id, Se(e.status)), ["rejected", "busy", "cancelled", "ended", "failed", "missed"].includes(e.status) && this.releaseMedia(e.id), this.emit("callupdated", e);
1483
1672
  }
1484
1673
  disconnect() {
1485
1674
  this.stopped = !0, this.reconnectTimer && clearTimeout(this.reconnectTimer), this.heartbeatTimer && clearInterval(this.heartbeatTimer), this.tokenRefreshTimer && clearTimeout(this.tokenRefreshTimer), this.reconnectTimer = null, this.heartbeatTimer = null, this.tokenRefreshTimer = null, this.socket?.close(1e3, "Client disconnected"), this.socket = null, this.callAudio.stop(), this.dismiss();
@@ -1495,7 +1684,7 @@ class le extends EventTarget {
1495
1684
  try {
1496
1685
  t = await this.resolveToken(e, e === "reconnect");
1497
1686
  } catch (s) {
1498
- this.emit("tokenerror", g(s)), !this.stopped && this.options.reconnect !== !1 && this.scheduleReconnect();
1687
+ this.emit("tokenerror", x(s)), !this.stopped && this.options.reconnect !== !1 && this.scheduleReconnect();
1499
1688
  return;
1500
1689
  }
1501
1690
  if (this.stopped || this.socket) return;
@@ -1518,14 +1707,14 @@ class le extends EventTarget {
1518
1707
  }), n.addEventListener("close", (s) => {
1519
1708
  if (this.socket !== n) return;
1520
1709
  this.socket = null, this.heartbeatTimer && clearInterval(this.heartbeatTimer), this.heartbeatTimer = null;
1521
- const a = !this.stopped && this.options.reconnect !== !1, r = {
1710
+ const a = !this.stopped && this.options.reconnect !== !1, o = {
1522
1711
  code: s.code,
1523
1712
  reason: s.reason,
1524
1713
  wasClean: s.wasClean,
1525
1714
  willReconnect: a,
1526
1715
  attempt: this.reconnectAttempt + 1
1527
1716
  };
1528
- a && (this.lastDisconnect = { code: s.code, reason: s.reason, wasClean: s.wasClean, at: Date.now() }), this.emit("signalingdisconnected", r), this.reportSignalingDiagnostic({ event: a ? "reconnecting" : "disconnected", ...r }), a && this.scheduleReconnect();
1717
+ a && (this.lastDisconnect = { code: s.code, reason: s.reason, wasClean: s.wasClean, at: Date.now() }), this.emit("signalingdisconnected", o), this.reportSignalingDiagnostic({ event: a ? "reconnecting" : "disconnected", ...o }), a && this.scheduleReconnect();
1529
1718
  }), n.addEventListener("error", () => {
1530
1719
  const s = { message: "RTC signaling connection failed", reconnecting: !this.stopped && this.options.reconnect !== !1, attempt: this.reconnectAttempt + 1 };
1531
1720
  this.emit("signalingerror", s), this.reportSignalingDiagnostic({ event: "error", attempt: s.attempt });
@@ -1559,16 +1748,16 @@ class le extends EventTarget {
1559
1748
  async request(e, t, i = !1) {
1560
1749
  const n = this.options.apiBaseUrl ?? this.options.signalingUrl ?? globalThis.location?.origin;
1561
1750
  if (!n) throw new Error("apiBaseUrl is required for call actions");
1562
- const s = new URL(n, globalThis.location?.href), a = await this.resolveToken("initial"), r = new Headers(t.headers);
1563
- r.set("authorization", `Bearer ${a}`), r.set("content-type", "application/json");
1564
- const o = await fetch(new URL(e, s.origin), { ...t, headers: r }), l = await o.json().catch(() => ({}));
1565
- if (o.status === 401 && this.options.tokenProvider && !i)
1751
+ const s = new URL(n, globalThis.location?.href), a = await this.resolveToken("initial"), o = new Headers(t.headers);
1752
+ o.set("authorization", `Bearer ${a}`), o.set("content-type", "application/json");
1753
+ const c = await fetch(new URL(e, s.origin), { ...t, headers: o }), d = await c.json().catch(() => ({}));
1754
+ if (c.status === 401 && this.options.tokenProvider && !i)
1566
1755
  return await this.resolveToken("unauthorized", !0), this.request(e, t, !0);
1567
- if (!o.ok) {
1568
- const d = l.error;
1569
- throw new Error(typeof d == "string" ? d : d?.message || `RTC API failed with HTTP ${o.status}`);
1756
+ if (!c.ok) {
1757
+ const l = d.error;
1758
+ throw new Error(typeof l == "string" ? l : l?.message || `RTC API failed with HTTP ${c.status}`);
1570
1759
  }
1571
- return l;
1760
+ return d;
1572
1761
  }
1573
1762
  renderIncoming(e) {
1574
1763
  if (!this.mount) return;
@@ -1591,12 +1780,12 @@ class le extends EventTarget {
1591
1780
  n.textContent = e.caller.name, n.style.fontSize = "20px";
1592
1781
  const s = document.createElement("div");
1593
1782
  Object.assign(s.style, { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "10px" });
1594
- const a = U("Decline", "#fff", "#a32920", "#d9a09b"), r = U("Answer", "#fff", "#08745f", "#08745f");
1783
+ const a = Y("Decline", "#fff", "#a32920", "#d9a09b"), o = Y("Answer", "#fff", "#08745f", "#08745f");
1595
1784
  a.addEventListener("click", () => {
1596
- this.reject(e.id).catch((o) => this.emit("error", g(o)));
1597
- }), r.addEventListener("click", () => {
1598
- this.accept(e.id).catch((o) => this.emit("error", g(o)));
1599
- }), s.appendChild(a), s.appendChild(r), t.appendChild(i), t.appendChild(n), t.appendChild(s), this.mount.replaceChildren(t);
1785
+ this.reject(e.id).catch((c) => this.emit("error", x(c)));
1786
+ }), o.addEventListener("click", () => {
1787
+ this.accept(e.id).catch((c) => this.emit("error", x(c)));
1788
+ }), s.appendChild(a), s.appendChild(o), t.appendChild(i), t.appendChild(n), t.appendChild(s), this.mount.replaceChildren(t);
1600
1789
  }
1601
1790
  dismiss(e) {
1602
1791
  e && this.currentCall?.id !== e && this.outgoingCallId !== e || (this.currentCall = null, (!e || this.outgoingCallId === e) && (this.outgoingCallId = null), this.callAudio.stop(), this.clearUi());
@@ -1663,7 +1852,7 @@ class le extends EventTarget {
1663
1852
  const t = Math.max(0, e - this.refreshSkew(e));
1664
1853
  this.tokenRefreshTimer = setTimeout(() => {
1665
1854
  this.tokenRefreshTimer = null, this.resolveToken("expiring", !0).catch((i) => {
1666
- this.emit("tokenerror", g(i)), this.stopped || (this.tokenRefreshTimer = setTimeout(() => this.scheduleTokenRefresh(), 3e4));
1855
+ this.emit("tokenerror", x(i)), this.stopped || (this.tokenRefreshTimer = setTimeout(() => this.scheduleTokenRefresh(), 3e4));
1667
1856
  });
1668
1857
  }, Math.min(t, 2147e6));
1669
1858
  }
@@ -1677,23 +1866,23 @@ class le extends EventTarget {
1677
1866
  this.options.reportSignalingDiagnostics === !1 || this.stopped || this.request("/v1/rtc/client/signaling-events", {
1678
1867
  method: "POST",
1679
1868
  body: JSON.stringify({ ...e, occurredAt: (/* @__PURE__ */ new Date()).toISOString() })
1680
- }).catch((t) => this.emit("diagnosticserror", g(t)));
1869
+ }).catch((t) => this.emit("diagnosticserror", x(t)));
1681
1870
  }
1682
1871
  emit(e, t) {
1683
1872
  const i = { type: e, detail: t, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
1684
1873
  this.dispatchEvent(new CustomEvent(e, { detail: i })), this.options.onEvent?.(i);
1685
1874
  }
1686
1875
  }
1687
- function Se(c) {
1688
- const e = new le(c);
1689
- return c.autoConnect !== !1 && c.signalingUrl && e.connect(), e;
1876
+ function Ae(r) {
1877
+ const e = new ye(r);
1878
+ return r.autoConnect !== !1 && r.signalingUrl && e.connect(), e;
1690
1879
  }
1691
- function B(c) {
1692
- return c ? typeof c == "string" ? document.querySelector(c) : c : null;
1880
+ function K(r) {
1881
+ return r ? typeof r == "string" ? document.querySelector(r) : r : null;
1693
1882
  }
1694
- function U(c, e, t, i) {
1883
+ function Y(r, e, t, i) {
1695
1884
  const n = document.createElement("button");
1696
- return n.type = "button", n.textContent = c, Object.assign(n.style, {
1885
+ return n.type = "button", n.textContent = r, Object.assign(n.style, {
1697
1886
  minHeight: "44px",
1698
1887
  border: `1px solid ${i}`,
1699
1888
  borderRadius: "6px",
@@ -1704,7 +1893,7 @@ function U(c, e, t, i) {
1704
1893
  fontWeight: "700"
1705
1894
  }), n;
1706
1895
  }
1707
- function de(c) {
1896
+ function Se(r) {
1708
1897
  return {
1709
1898
  rejected: "Call declined",
1710
1899
  busy: "Line busy",
@@ -1712,91 +1901,96 @@ function de(c) {
1712
1901
  ended: "Call ended",
1713
1902
  failed: "Call failed",
1714
1903
  missed: "No answer"
1715
- }[c] ?? "Call ended";
1904
+ }[r] ?? "Call ended";
1716
1905
  }
1717
- function F(c) {
1906
+ function X(r) {
1718
1907
  return {
1719
- id: c.participantId,
1720
- name: c.displayName,
1908
+ id: r.participantId,
1909
+ name: r.displayName,
1721
1910
  role: "participant"
1722
1911
  };
1723
1912
  }
1724
- async function he(c, e) {
1725
- const t = await c.getStats(), i = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
1726
- let s = 0, a = 0, r = 0, o = 0, l = 0, d = 0, u = 0, m = 0, p = 0, v = 0, T = 0, E = 0, w = 0, y = null, b = null, C = null, S = null, k = null, I = null;
1727
- t.forEach((h) => {
1728
- n.set(h.id, h), h.type === "codec" && i.set(h.id, String(h.mimeType ?? ""));
1729
- }), t.forEach((h) => {
1730
- if (h.type === "inbound-rtp" && !h.isRemote && (s += Number(h.bytesReceived ?? 0), r += Math.max(0, Number(h.packetsLost ?? 0)), o += Math.max(0, Number(h.packetsReceived ?? 0)), Number.isFinite(h.jitter) && (l += Number(h.jitter), d += 1), u = Math.max(u, Number(h.framesPerSecond ?? 0)), m = Math.max(m, Number(h.frameWidth ?? 0)), p = Math.max(p, Number(h.frameHeight ?? 0)), v += Number(h.framesDropped ?? 0), T += Number(h.freezeCount ?? 0), E += Number(h.totalFreezesDuration ?? 0), w += Number(h.concealedSamples ?? 0), k ||= i.get(String(h.codecId ?? "")) ?? null), h.type === "outbound-rtp" && !h.isRemote && (a += Number(h.bytesSent ?? 0), I ||= h.qualityLimitationReason ? String(h.qualityLimitationReason) : null, k ||= i.get(String(h.codecId ?? "")) ?? null), h.type === "candidate-pair" && (h.selected || h.nominated) && h.state === "succeeded") {
1731
- y = Number.isFinite(h.currentRoundTripTime) ? Number(h.currentRoundTripTime) : y, b = Number.isFinite(h.availableOutgoingBitrate) ? Number(h.availableOutgoingBitrate) : b;
1732
- const R = n.get(h.localCandidateId);
1733
- C = R?.candidateType ? String(R.candidateType) : C, S = R?.protocol ? String(R.protocol) : S;
1913
+ async function ke(r, e) {
1914
+ const t = await r.getStats(), i = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
1915
+ let s = 0, a = 0, o = 0, c = 0, d = 0, l = 0, h = 0, v = 0, g = 0, k = 0, p = 0, C = 0, S = 0, y = null, T = null, I = null, R = null, E = null, f = null;
1916
+ t.forEach((m) => {
1917
+ n.set(m.id, m), m.type === "codec" && i.set(m.id, String(m.mimeType ?? ""));
1918
+ }), t.forEach((m) => {
1919
+ if (m.type === "inbound-rtp" && !m.isRemote && (s += Number(m.bytesReceived ?? 0), o += Math.max(0, Number(m.packetsLost ?? 0)), c += Math.max(0, Number(m.packetsReceived ?? 0)), Number.isFinite(m.jitter) && (d += Number(m.jitter), l += 1), h = Math.max(h, Number(m.framesPerSecond ?? 0)), v = Math.max(v, Number(m.frameWidth ?? 0)), g = Math.max(g, Number(m.frameHeight ?? 0)), k += Number(m.framesDropped ?? 0), p += Number(m.freezeCount ?? 0), C += Number(m.totalFreezesDuration ?? 0), S += Number(m.concealedSamples ?? 0), E ||= i.get(String(m.codecId ?? "")) ?? null), m.type === "outbound-rtp" && !m.isRemote && (a += Number(m.bytesSent ?? 0), f ||= m.qualityLimitationReason ? String(m.qualityLimitationReason) : null, E ||= i.get(String(m.codecId ?? "")) ?? null), m.type === "candidate-pair" && (m.selected || m.nominated) && m.state === "succeeded") {
1920
+ y = Number.isFinite(m.currentRoundTripTime) ? Number(m.currentRoundTripTime) : y, T = Number.isFinite(m.availableOutgoingBitrate) ? Number(m.availableOutgoingBitrate) : T;
1921
+ const A = n.get(m.localCandidateId);
1922
+ I = A?.candidateType ? String(A.candidateType) : I, R = A?.protocol ? String(A.protocol) : R;
1734
1923
  }
1735
1924
  });
1736
- const D = Date.now(), q = e ? Math.max(1e-3, (D - e.timestamp) / 1e3) : 0, G = e ? Math.max(0, Math.round((s - e.inboundBytes) * 8 / q)) : null, K = e ? Math.max(0, Math.round((a - e.outboundBytes) * 8 / q)) : null, N = r + o, Q = e ? Math.max(0, r - e.packetsLost) : r, Y = e ? Math.max(0, o - e.packetsReceived) : o, V = Q + Y;
1925
+ const u = Date.now(), q = e ? Math.max(1e-3, (u - e.timestamp) / 1e3) : 0, L = e ? Math.max(0, Math.round((s - e.inboundBytes) * 8 / q)) : null, $ = e ? Math.max(0, Math.round((a - e.outboundBytes) * 8 / q)) : null, b = o + c, P = e ? Math.max(0, o - e.packetsLost) : o, w = e ? Math.max(0, c - e.packetsReceived) : c, N = P + w;
1737
1926
  return {
1738
- counters: { timestamp: D, inboundBytes: s, outboundBytes: a, packetsLost: r, packetsReceived: o },
1927
+ counters: { timestamp: u, inboundBytes: s, outboundBytes: a, packetsLost: o, packetsReceived: c },
1739
1928
  sample: {
1740
1929
  rttMs: y === null ? null : y * 1e3,
1741
- jitterMs: d ? l / d * 1e3 : null,
1742
- packetLossPct: V ? Q / V * 100 : null,
1743
- packetLossCumulativePct: N ? r / N * 100 : null,
1744
- packetsLost: r,
1745
- packetsReceived: o,
1746
- inboundBitrateBps: G,
1747
- outboundBitrateBps: K,
1748
- availableOutgoingBitrateBps: b,
1749
- framesPerSecond: u || null,
1750
- frameWidth: m || null,
1751
- frameHeight: p || null,
1752
- framesDropped: v,
1753
- freezeCount: T,
1754
- freezeDurationMs: Math.round(E * 1e3),
1755
- concealedSamples: w,
1756
- codec: k,
1757
- transportProtocol: S,
1758
- candidateType: C,
1759
- qualityLimitationReason: I
1930
+ jitterMs: l ? d / l * 1e3 : null,
1931
+ packetLossPct: N ? P / N * 100 : null,
1932
+ packetLossCumulativePct: b ? o / b * 100 : null,
1933
+ packetsLost: o,
1934
+ packetsReceived: c,
1935
+ inboundBitrateBps: L,
1936
+ outboundBitrateBps: $,
1937
+ availableOutgoingBitrateBps: T,
1938
+ framesPerSecond: h || null,
1939
+ frameWidth: v || null,
1940
+ frameHeight: g || null,
1941
+ framesDropped: k,
1942
+ freezeCount: p,
1943
+ freezeDurationMs: Math.round(C * 1e3),
1944
+ concealedSamples: S,
1945
+ codec: E,
1946
+ transportProtocol: R,
1947
+ candidateType: I,
1948
+ qualityLimitationReason: f
1760
1949
  }
1761
1950
  };
1762
1951
  }
1763
- function ue(c) {
1764
- let e = c.mediaScore == null ? 5 : Math.round($(Number(c.mediaScore), 0, 5));
1765
- const t = x(c.packetLossPct) ?? 0, i = x(c.rttMs) ?? 0, n = x(c.jitterMs) ?? 0, s = String(c.connectionState ?? "unknown").toLowerCase();
1952
+ function Te(r) {
1953
+ let e = r.mediaScore == null ? 5 : Math.round(ee(Number(r.mediaScore), 0, 5));
1954
+ const t = F(r.packetLossPct) ?? 0, i = F(r.rttMs) ?? 0, n = F(r.jitterMs) ?? 0, s = String(r.connectionState ?? "unknown").toLowerCase();
1766
1955
  ["failed", "closed", "disconnected"].includes(s) ? e = 0 : ["reconnecting", "checking"].includes(s) && (e = Math.min(e, 2)), t >= 15 ? e = Math.min(e, 0) : t >= 8 ? e = Math.min(e, 1) : t >= 3 ? e = Math.min(e, 2) : t >= 1 && (e = Math.min(e, 3)), i >= 1200 ? e = Math.min(e, 0) : i >= 800 ? e = Math.min(e, 1) : i >= 400 ? e = Math.min(e, 2) : i >= 250 && (e = Math.min(e, 3)), n >= 150 ? e = Math.min(e, 1) : n >= 80 ? e = Math.min(e, 2) : n >= 40 && (e = Math.min(e, 3));
1767
- const a = Number($(4.5 - t * 0.09 - i * 11e-4 - n * 6e-3, 1, 4.5).toFixed(2));
1956
+ const a = Number(ee(4.5 - t * 0.09 - i * 11e-4 - n * 6e-3, 1, 4.5).toFixed(2));
1768
1957
  return { networkScore: e, estimatedMos: a };
1769
1958
  }
1770
- function J() {
1959
+ function Z() {
1771
1960
  return navigator.connection ?? null;
1772
1961
  }
1773
- function me() {
1774
- const c = Number(navigator.deviceMemory);
1775
- return Number.isFinite(c) ? c : null;
1962
+ function we() {
1963
+ const r = Number(navigator.deviceMemory);
1964
+ return Number.isFinite(r) ? r : null;
1776
1965
  }
1777
- function x(c) {
1778
- const e = Number(c);
1966
+ function F(r) {
1967
+ const e = Number(r);
1779
1968
  return Number.isFinite(e) ? e : null;
1780
1969
  }
1781
- function $(c, e, t) {
1782
- return Math.min(t, Math.max(e, c));
1970
+ function ee(r, e, t) {
1971
+ return Math.min(t, Math.max(e, r));
1783
1972
  }
1784
- function g(c) {
1785
- return c instanceof Error ? { name: c.name, message: c.message } : { name: "ServiceError", message: String(c ?? "Service request failed") };
1973
+ function x(r) {
1974
+ return r instanceof Error ? { name: r.name, message: r.message } : { name: "ServiceError", message: String(r ?? "Service request failed") };
1786
1975
  }
1787
- function z(c, e) {
1788
- return c instanceof Error ? c : new Error(e);
1976
+ function te(r, e) {
1977
+ return r instanceof Error ? r : new Error(e);
1789
1978
  }
1790
- const pe = "1.3.14";
1979
+ const be = "1.3.15";
1791
1980
  export {
1792
- re as RtcClient,
1793
- le as RtcIncomingClient,
1794
- fe as SPEAKER_NOISE_FLOOR,
1795
- ge as SPEAKER_TAKEOVER_RATIO,
1796
- ve as createPictureInPictureController,
1797
- ye as createRtcClient,
1798
- Se as createRtcIncomingClient,
1799
- H as pickActiveSpeaker,
1800
- oe as unlockRtcCallAudio,
1801
- pe as version
1981
+ me as BACKGROUND_PRESETS,
1982
+ pe as OVERLAY_EFFECTS,
1983
+ fe as RtcClient,
1984
+ ye as RtcIncomingClient,
1985
+ Ce as SPEAKER_NOISE_FLOOR,
1986
+ Ie as SPEAKER_TAKEOVER_RATIO,
1987
+ Re as createCallRecorder,
1988
+ Ee as createPictureInPictureController,
1989
+ Me as createRtcClient,
1990
+ Ae as createRtcIncomingClient,
1991
+ Pe as createVideoEffectsPipeline,
1992
+ ie as pickActiveSpeaker,
1993
+ G as scenePainters,
1994
+ ge as unlockRtcCallAudio,
1995
+ be as version
1802
1996
  };