@streaming-cdn/rtc-web 1.3.15 → 1.3.16

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 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);
1
+ const qe = 0.02, Oe = 1.4;
2
+ function oe(a, e, t = 0.02, i = 1.4) {
3
+ const n = a.filter((r) => r.level >= t);
4
4
  if (n.length === 0) return null;
5
- const s = n.reduce((o, c) => c.level > o.level ? c : o), a = n.find((o) => o.participantId === e);
6
- return a ? s.participantId === e ? e : s.level >= a.level * i ? s.participantId : e : s.participantId;
5
+ const s = n.reduce((r, c) => c.level > r.level ? c : r), o = n.find((r) => r.participantId === e);
6
+ return o ? s.participantId === e ? e : s.level >= o.level * i ? s.participantId : e : s.participantId;
7
7
  }
8
- function ne(r) {
8
+ function ce(a) {
9
9
  const e = [];
10
- for (const t of r) {
10
+ for (const t of a) {
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 M = {
17
+ const O = {
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
- }, ae = {
22
+ }, he = {
23
23
  warmupSamples: 3,
24
24
  poorSamplesToStepDown: 2,
25
25
  goodSamplesToStepUp: 6,
@@ -31,46 +31,46 @@ const M = {
31
31
  goodRttMs: 250,
32
32
  sustainRatio: 0.8
33
33
  };
34
- function re(r) {
35
- const e = String(r ?? "").trim().toLowerCase();
34
+ function ue(a) {
35
+ const e = String(a ?? "").trim().toLowerCase();
36
36
  return !e || e === "none" ? "" : e === "cpu" || e === "bandwidth" ? e : "other";
37
37
  }
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;
38
+ function me(a, e, t, i, n = {}) {
39
+ const s = { ...he, ...n.thresholds }, o = ["low", "medium", "high"], r = n.ceiling && n.ceiling !== "audio" ? n.ceiling : "high", c = o.indexOf(r), d = o.indexOf(a), l = (n.samplesSeen ?? s.warmupSamples) + 1, u = l <= s.warmupSamples, y = ue(e.qualityLimitationReason), f = e.packetLossPct ?? 0, w = e.rttMs ?? 0, m = e.availableOutgoingBitrateBps, S = O[a].maxBitrate, T = f >= s.criticalLossPct || w >= s.criticalRttMs || y === "cpu", k = T || f >= s.poorLossPct || w >= s.poorRttMs || y === "bandwidth", b = m == null || m >= S * s.sustainRatio, M = f < s.goodLossPct && w < s.goodRttMs && !y && b, I = k ? t + 1 : 0, g = M ? i + 1 : 0, p = { quality: a, poorSamples: I, goodSamples: g, samplesSeen: l, changed: !1 };
40
+ return d > c ? { quality: o[c], poorSamples: 0, goodSamples: 0, samplesSeen: l, changed: !0 } : u ? p : T && d > 0 ? { quality: o[d - 1], poorSamples: 0, goodSamples: 0, samplesSeen: l, changed: !0 } : I >= s.poorSamplesToStepDown && d > 0 ? { quality: o[d - 1], poorSamples: 0, goodSamples: 0, samplesSeen: l, changed: !0 } : g >= s.goodSamplesToStepUp && d < c ? { quality: o[d + 1], poorSamples: 0, goodSamples: 0, samplesSeen: l, changed: !0 } : p;
41
41
  }
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;
42
+ function pe(a, e) {
43
+ const t = a instanceof Map ? a : new Map(a);
44
+ let i = 0, n = 0, s = null, o = null, r = null;
45
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") {
46
+ const u = String(l.type ?? "");
47
+ if (u === "outbound-rtp" && String(l.kind ?? "") === "video" && (i += Number(l.packetsSent ?? 0), s = l.qualityLimitationReason ?? s), u === "remote-inbound-rtp" && String(l.kind ?? "") === "video") {
48
48
  n += Number(l.packetsLost ?? 0);
49
- const v = Number(l.roundTripTime ?? NaN);
50
- Number.isFinite(v) && (a = v * 1e3);
49
+ const y = Number(l.roundTripTime ?? NaN);
50
+ Number.isFinite(y) && (o = y * 1e3);
51
51
  }
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);
52
+ if (u === "candidate-pair" && (l.nominated === !0 || String(l.state ?? "") === "succeeded")) {
53
+ const y = Number(l.currentRoundTripTime ?? NaN);
54
+ o == null && Number.isFinite(y) && (o = y * 1e3);
55
+ const f = Number(l.availableOutgoingBitrate ?? NaN);
56
+ Number.isFinite(f) && (r = f);
57
57
  }
58
58
  }
59
59
  const c = { packetsSent: i, packetsLost: n, timestamp: Date.now() };
60
60
  let d = null;
61
61
  if (e) {
62
- const l = i - e.packetsSent, h = n - e.packetsLost;
63
- l > 0 && h >= 0 && (d = h / (l + h) * 100);
62
+ const l = i - e.packetsSent, u = n - e.packetsLost;
63
+ l > 0 && u >= 0 && (d = u / (l + u) * 100);
64
64
  }
65
65
  return {
66
- sample: { packetLossPct: d, rttMs: a, availableOutgoingBitrateBps: o, qualityLimitationReason: s },
66
+ sample: { packetLossPct: d, rttMs: o, availableOutgoingBitrateBps: r, qualityLimitationReason: s },
67
67
  counters: c
68
68
  };
69
69
  }
70
- const le = {
70
+ const fe = {
71
71
  audio: { active: !1, maxBitrate: 0, maxFramerate: 0, scaleResolutionDownBy: 4 }
72
- }, de = { active: !0, maxBitrate: 4e6, maxFramerate: 30, scaleResolutionDownBy: 1 };
73
- class Q {
72
+ }, ge = { active: !0, maxBitrate: 4e6, maxFramerate: 30, scaleResolutionDownBy: 1 };
73
+ class x {
74
74
  options;
75
75
  socket = null;
76
76
  localStream = null;
@@ -153,14 +153,14 @@ class Q {
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((o) => o.kind === s);
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((o) => o.readyState === "live") || await this.replaceVideoTrack(n);
156
+ const s = e.kind === "audioinput" ? "audio" : "video", o = this.localStream?.getTracks().find((r) => r.kind === s);
157
+ if (this.localStream || (this.localStream = new MediaStream()), o && (this.localStream.removeTrack(o), o.stop()), this.localStream.addTrack(n), s === "video") {
158
+ this.screenStream?.getVideoTracks().some((r) => r.readyState === "live") || await this.replaceVideoTrack(n);
159
159
  return;
160
160
  }
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);
161
+ for (const r of this.peers.values()) {
162
+ const c = r.connection.getSenders().find((d) => d.track?.kind === s);
163
+ c ? await c.replaceTrack(n) : r.connection.addTrack(n, this.localStream);
164
164
  }
165
165
  await this.applyVideoQuality();
166
166
  }
@@ -168,7 +168,7 @@ class Q {
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 = Q.clampToCeiling(t.quality, e), t.poorSamples = 0, t.goodSamples = 0;
171
+ t.quality = x.clampToCeiling(t.quality, e), t.poorSamples = 0, t.goodSamples = 0;
172
172
  await this.applyVideoQuality();
173
173
  }
174
174
  static clampToCeiling(e, t) {
@@ -216,18 +216,18 @@ class Q {
216
216
  i.protocol = i.protocol === "https:" ? "wss:" : "ws:";
217
217
  const n = new Promise((c, d) => {
218
218
  this.resolveJoin = c, this.rejectJoin = d;
219
- }), s = new WebSocket(i, ["rtc-client", t.signalingToken]), a = ++this.socketGeneration;
219
+ }), s = new WebSocket(i, ["rtc-client", t.signalingToken]), o = ++this.socketGeneration;
220
220
  this.socket = s;
221
- const o = setTimeout(() => this.rejectJoin?.(new Error("RTC signaling timed out")), 15e3);
221
+ const r = 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
224
  }), s.addEventListener("message", (c) => {
225
225
  const d = String(c.data);
226
226
  this.signalQueue = this.signalQueue.then(async () => {
227
- this.socket !== s || this.socketGeneration !== a || await this.handleSignal(d);
227
+ this.socket !== s || this.socketGeneration !== o || await this.handleSignal(d);
228
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));
229
+ const u = l instanceof Error ? l.message : "RTC signaling processing failed";
230
+ this.options.onEvent("signalingerror", { message: u }), this.joined || this.rejectJoin?.(new Error(u));
231
231
  });
232
232
  }), s.addEventListener("error", () => this.rejectJoin?.(new Error("RTC signaling connection failed"))), s.addEventListener("close", (c) => {
233
233
  if (this.socket !== s) return;
@@ -238,7 +238,7 @@ class Q {
238
238
  try {
239
239
  await n, this.joined = !0, this.options.onEvent("connected", { participantId: t.participantId, resumed: e });
240
240
  } finally {
241
- clearTimeout(o), this.resolveJoin = null, this.rejectJoin = null;
241
+ clearTimeout(r), this.resolveJoin = null, this.rejectJoin = null;
242
242
  }
243
243
  }
244
244
  async handleSignal(e) {
@@ -270,11 +270,11 @@ class Q {
270
270
  if (i === "rtc.offer" && t.sender && t.description) {
271
271
  const n = this.ensurePeer(t.sender);
272
272
  n.offerTask && await n.offerTask;
273
- const s = n.connection.signalingState !== "stable", a = !this.shouldInitiateOffer(t.sender);
274
- if (s && !a) return;
273
+ const s = n.connection.signalingState !== "stable", o = !this.shouldInitiateOffer(t.sender);
274
+ if (s && !o) return;
275
275
  s && await n.connection.setLocalDescription({ type: "rollback" }), await n.connection.setRemoteDescription(t.description);
276
- const o = await n.connection.createAnswer();
277
- await n.connection.setLocalDescription(o), this.send({
276
+ const r = await n.connection.createAnswer();
277
+ await n.connection.setLocalDescription(r), this.send({
278
278
  type: "rtc.answer",
279
279
  targetParticipantId: t.sender.participantId,
280
280
  negotiationId: t.negotiationId,
@@ -313,7 +313,7 @@ class Q {
313
313
  makingOffer: !1,
314
314
  offerTask: null,
315
315
  activeNegotiationId: null,
316
- quality: Q.startingQuality(this.quality),
316
+ quality: x.startingQuality(this.quality),
317
317
  poorSamples: 0,
318
318
  goodSamples: 0,
319
319
  samplesSeen: 0,
@@ -321,8 +321,8 @@ class Q {
321
321
  };
322
322
  this.peers.set(e.participantId, s);
323
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) => {
324
+ const o = this.screenStream?.getVideoTracks().some((c) => c.readyState === "live") ? this.screenStream : this.localStream, r = o?.getVideoTracks()[0];
325
+ return r && o && (s.videoSender = i.addTrack(r, o)), !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", (c) => {
326
326
  c.candidate && this.send({ type: "rtc.ice", targetParticipantId: e.participantId, candidate: c.candidate.toJSON() });
327
327
  }), i.addEventListener("track", (c) => {
328
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 });
@@ -351,7 +351,7 @@ class Q {
351
351
  });
352
352
  if (e.connection.signalingState !== "stable") return;
353
353
  await e.connection.setLocalDescription(t);
354
- const i = H();
354
+ const i = W();
355
355
  e.activeNegotiationId = i, this.send({
356
356
  type: "rtc.offer",
357
357
  targetParticipantId: e.identity.participantId,
@@ -371,10 +371,10 @@ class Q {
371
371
  async replaceVideoTrack(e) {
372
372
  let t = !1;
373
373
  for (const i of this.peers.values()) {
374
- const n = i.videoSender ?? i.connection.getSenders().find((a) => a.track?.kind === "video") ?? i.connection.getTransceivers().find((a) => a.receiver.track.kind === "video")?.sender, s = i.videoTransceiver ?? i.connection.getTransceivers().find((a) => a.sender === n);
374
+ const n = i.videoSender ?? i.connection.getSenders().find((o) => o.track?.kind === "video") ?? i.connection.getTransceivers().find((o) => o.receiver.track.kind === "video")?.sender, s = i.videoTransceiver ?? i.connection.getTransceivers().find((o) => o.sender === n);
375
375
  if (n) {
376
- const a = e ? this.options.receiveVideo ? "sendrecv" : "sendonly" : this.options.receiveVideo ? "recvonly" : "inactive";
377
- s && s.direction !== a && (s.direction = a, t = !0), await n.replaceTrack(e), i.videoSender = n, s && (i.videoTransceiver = s);
376
+ const o = e ? this.options.receiveVideo ? "sendrecv" : "sendonly" : this.options.receiveVideo ? "recvonly" : "inactive";
377
+ s && s.direction !== o && (s.direction = o, t = !0), await n.replaceTrack(e), i.videoSender = n, s && (i.videoTransceiver = s);
378
378
  } else e && (i.videoSender = i.connection.addTrack(e, this.screenStream ?? this.localStream ?? new MediaStream([e])), t = !0);
379
379
  }
380
380
  t && await this.renegotiateAll(), await this.applyVideoQuality();
@@ -391,8 +391,8 @@ class Q {
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 ? 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);
394
+ const n = !!(t && i.track?.id === t), s = n ? ge : this.quality === "audio" ? fe.audio : O[e.quality], o = i.getParameters(), r = o.encodings?.length ? o.encodings : [{}];
395
+ o.encodings = r.map((c) => ({ ...c, ...s })), o.degradationPreference = n ? "maintain-resolution" : "maintain-framerate", await i.setParameters(o);
396
396
  }
397
397
  }
398
398
  startQualitySampling() {
@@ -411,11 +411,11 @@ class Q {
411
411
  if (i.connection.connectionState === "connected")
412
412
  try {
413
413
  const n = await i.connection.getStats();
414
- for (const s of ne(n.values()))
414
+ for (const s of ce(n.values()))
415
415
  e.push({ participantId: i.identity.participantId, level: s.level });
416
416
  } catch {
417
417
  }
418
- const t = ie(e, this.activeSpeaker);
418
+ const t = oe(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 Q {
428
428
  } catch {
429
429
  continue;
430
430
  }
431
- const { sample: i, counters: n } = ce(t, e.counters);
431
+ const { sample: i, counters: n } = pe(t, e.counters);
432
432
  e.counters = n;
433
- const s = oe(e.quality, i, e.poorSamples, e.goodSamples, {
433
+ const s = me(e.quality, i, e.poorSamples, e.goodSamples, {
434
434
  samplesSeen: e.samplesSeen,
435
435
  ceiling: this.quality
436
436
  });
@@ -487,7 +487,7 @@ class Q {
487
487
  }
488
488
  send(e) {
489
489
  this.socket?.readyState === WebSocket.OPEN && this.socket.send(JSON.stringify({
490
- clientMessageId: e.clientMessageId ?? H(),
490
+ clientMessageId: e.clientMessageId ?? W(),
491
491
  ...e
492
492
  }));
493
493
  }
@@ -495,15 +495,15 @@ class Q {
495
495
  for (const t of e?.getTracks() ?? []) t.stop();
496
496
  }
497
497
  }
498
- function H() {
498
+ function W() {
499
499
  return globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
500
500
  }
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 {
501
+ const $ = { active: !0, maxBitrate: 4e6, maxFramerate: 30, scaleResolutionDownBy: 1 }, Y = [
502
+ { rid: "a", maxBitrate: O.high.maxBitrate, maxFramerate: O.high.maxFramerate },
503
+ { rid: "b", maxBitrate: O.medium.maxBitrate, maxFramerate: O.medium.maxFramerate, scaleResolutionDownBy: 2 },
504
+ { rid: "c", maxBitrate: O.low.maxBitrate, maxFramerate: O.low.maxFramerate, scaleResolutionDownBy: 4 }
505
+ ], G = { high: "a", medium: "b", low: "c" };
506
+ class ye {
507
507
  options;
508
508
  apiBase;
509
509
  socket = null;
@@ -594,13 +594,13 @@ class he {
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((c) => c.kind === s);
598
- if (this.localStream || (this.localStream = new MediaStream()), a && (this.localStream.removeTrack(a), a.stop()), this.localStream.addTrack(n), s === "video") {
597
+ const s = e.kind === "audioinput" ? "audio" : "video", o = this.localStream?.getTracks().find((c) => c.kind === s);
598
+ if (this.localStream || (this.localStream = new MediaStream()), o && (this.localStream.removeTrack(o), o.stop()), this.localStream.addTrack(n), s === "video") {
599
599
  this.screenStream?.getVideoTracks().some((c) => c.readyState === "live") || await this.replaceVideoTrack(n);
600
600
  return;
601
601
  }
602
- const o = this.connection?.getSenders().find((c) => c.track?.kind === "audio");
603
- o && await o.replaceTrack(n);
602
+ const r = this.connection?.getSenders().find((c) => c.track?.kind === "audio");
603
+ r && await r.replaceTrack(n);
604
604
  }
605
605
  /** One uplink serves everyone, so the requested quality applies directly. */
606
606
  async setQuality(e) {
@@ -640,18 +640,18 @@ class he {
640
640
  i.protocol = i.protocol === "https:" ? "wss:" : "ws:";
641
641
  const n = new Promise((c, d) => {
642
642
  this.resolveJoin = c, this.rejectJoin = d;
643
- }), s = new WebSocket(i, ["rtc-client", t.signalingToken]), a = ++this.socketGeneration;
643
+ }), s = new WebSocket(i, ["rtc-client", t.signalingToken]), o = ++this.socketGeneration;
644
644
  this.socket = s;
645
- const o = setTimeout(() => this.rejectJoin?.(new Error("RTC signaling timed out")), 15e3);
645
+ const r = 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
648
  }), s.addEventListener("message", (c) => {
649
649
  const d = String(c.data);
650
650
  this.signalQueue = this.signalQueue.then(async () => {
651
- this.socket !== s || this.socketGeneration !== a || await this.handleSignal(d);
651
+ this.socket !== s || this.socketGeneration !== o || await this.handleSignal(d);
652
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));
653
+ const u = l instanceof Error ? l.message : "RTC signaling processing failed";
654
+ this.options.onEvent("signalingerror", { message: u }), this.joined || this.rejectJoin?.(new Error(u));
655
655
  });
656
656
  }), s.addEventListener("error", () => this.rejectJoin?.(new Error("RTC signaling connection failed"))), s.addEventListener("close", (c) => {
657
657
  if (this.socket !== s) return;
@@ -662,7 +662,7 @@ class he {
662
662
  try {
663
663
  await n, this.joined = !0, this.options.onEvent("connected", { participantId: t.participantId, resumed: e });
664
664
  } finally {
665
- clearTimeout(o), this.resolveJoin = null, this.rejectJoin = null;
665
+ clearTimeout(r), this.resolveJoin = null, this.rejectJoin = null;
666
666
  }
667
667
  }
668
668
  async handleSignal(e) {
@@ -710,30 +710,30 @@ class he {
710
710
  iceServers: this.options.credential.iceServers ?? [],
711
711
  iceTransportPolicy: this.options.iceTransportPolicy ?? "all"
712
712
  });
713
- this.connection = t, t.addEventListener("track", (o) => this.handleRemoteTrack(o)), t.addEventListener("connectionstatechange", () => {
713
+ this.connection = t, t.addEventListener("track", (r) => this.handleRemoteTrack(r)), 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((o) => t.addTransceiver(o, {
718
+ const n = e.map((r) => t.addTransceiver(r, {
719
719
  direction: "sendonly",
720
720
  streams: this.localStream ? [this.localStream] : [],
721
- ...o.kind === "video" ? { sendEncodings: _.map((c) => ({ ...c })) } : {}
721
+ ...r.kind === "video" ? { sendEncodings: Y.map((c) => ({ ...c })) } : {}
722
722
  })), s = await t.createOffer();
723
723
  await t.setLocalDescription(s);
724
- const a = await this.sfuFetch(
724
+ const o = await this.sfuFetch(
725
725
  "POST",
726
726
  `/v1/rtc/sfu/sessions/${encodeURIComponent(i.sessionId)}/tracks`,
727
727
  {
728
728
  sessionDescription: t.localDescription,
729
- tracks: n.map((o) => ({
729
+ tracks: n.map((r) => ({
730
730
  location: "local",
731
- mid: o.mid,
732
- trackName: this.trackName(o.sender.track)
731
+ mid: r.mid,
732
+ trackName: this.trackName(r.sender.track)
733
733
  }))
734
734
  }
735
735
  );
736
- a.sessionDescription && await t.setRemoteDescription(a.sessionDescription), this.videoSender = t.getSenders().find((o) => o.track?.kind === "video") ?? null, await this.applyVideoQuality();
736
+ o.sessionDescription && await t.setRemoteDescription(o.sessionDescription), this.videoSender = t.getSenders().find((r) => r.track?.kind === "video") ?? null, await this.applyVideoQuality();
737
737
  }
738
738
  trackName(e) {
739
739
  return `${this.options.credential.participantId}/${e.kind}`;
@@ -747,13 +747,13 @@ class he {
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((o) => ({ trackName: String(o.trackName ?? ""), simulcast: o.simulcast === !0 })).filter((o) => !!o.trackName), s = n.map((o) => o.trackName);
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);
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 ?? {} });
754
754
  return;
755
755
  }
756
- const a = this.remotes.get(e.participantId) ?? {
756
+ const o = this.remotes.get(e.participantId) ?? {
757
757
  identity: e,
758
758
  stream: new MediaStream(),
759
759
  sessionId: i,
@@ -761,14 +761,14 @@ class he {
761
761
  simulcastNames: /* @__PURE__ */ new Set(),
762
762
  mids: /* @__PURE__ */ new Map()
763
763
  };
764
- a.sessionId = i;
765
- for (const o of n)
766
- o.simulcast && a.simulcastNames.add(o.trackName);
767
- this.remotes.set(e.participantId, a), this.negotiationQueue = this.negotiationQueue.then(async () => {
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" });
764
+ o.sessionId = i;
765
+ for (const r of n)
766
+ r.simulcast && o.simulcastNames.add(r.trackName);
767
+ this.remotes.set(e.participantId, o), this.negotiationQueue = this.negotiationQueue.then(async () => {
768
+ const r = s.filter((c) => !o.trackNames.includes(c));
769
+ r.length !== 0 && await this.subscribe(o, r);
770
+ }).catch((r) => {
771
+ this.options.onEvent("signalingerror", { message: r instanceof Error ? r.message : "SFU subscribe failed" });
772
772
  }), await this.negotiationQueue;
773
773
  }
774
774
  async subscribe(e, t) {
@@ -818,7 +818,7 @@ class he {
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: W[t], priorityOrdering: "asciibetical", ridNotAvailable: "asciibetical" }
821
+ simulcast: { preferredRid: G[t], priorityOrdering: "asciibetical", ridNotAvailable: "asciibetical" }
822
822
  }]
823
823
  });
824
824
  }
@@ -830,16 +830,16 @@ class he {
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 : W[this.quality];
834
- n.encodings = s.map((o) => {
833
+ const o = this.quality === "audio" ? null : G[this.quality];
834
+ n.encodings = s.map((r) => {
835
835
  if (i)
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 };
836
+ return { ...r, active: r.rid === "a", ...r.rid === "a" ? { maxBitrate: $.maxBitrate, maxFramerate: $.maxFramerate } : {} };
837
+ const c = Y.find((l) => l.rid === r.rid), d = o != null && String(r.rid ?? "") >= o;
838
+ return { ...r, ...c ?? {}, active: d };
839
839
  });
840
840
  } else {
841
- const a = this.quality === "audio" ? M.audio : M[this.quality], o = i ? U : a;
842
- n.encodings = s.map((c) => ({ ...c, ...o }));
841
+ const o = this.quality === "audio" ? O.audio : O[this.quality], r = i ? $ : o;
842
+ n.encodings = s.map((c) => ({ ...c, ...r }));
843
843
  }
844
844
  n.degradationPreference = i ? "maintain-resolution" : "maintain-framerate", await e.setParameters(n);
845
845
  }
@@ -905,11 +905,11 @@ class he {
905
905
  return;
906
906
  }
907
907
  const i = [];
908
- for (const s of ne(t.values())) {
909
- const a = s.mid ? this.midToParticipant.get(s.mid) : void 0;
910
- a && i.push({ participantId: a, level: s.level });
908
+ for (const s of ce(t.values())) {
909
+ const o = s.mid ? this.midToParticipant.get(s.mid) : void 0;
910
+ o && i.push({ participantId: o, level: s.level });
911
911
  }
912
- const n = ie(i, this.activeSpeaker);
912
+ const n = oe(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 he {
926
926
  }
927
927
  send(e) {
928
928
  this.socket?.readyState === WebSocket.OPEN && this.socket.send(JSON.stringify({
929
- clientMessageId: e.clientMessageId ?? ue(),
929
+ clientMessageId: e.clientMessageId ?? ve(),
930
930
  ...e
931
931
  }));
932
932
  }
@@ -934,24 +934,24 @@ class he {
934
934
  for (const t of e?.getTracks() ?? []) t.stop();
935
935
  }
936
936
  }
937
- function ue() {
937
+ function ve() {
938
938
  return globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
939
939
  }
940
- function Ee(r, e = {}) {
940
+ function Ne(a, 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(o) {
947
- const c = r.getRemoteStreams();
948
- return o ? c.find((d) => d.participant.participantId === o)?.stream ?? null : c[0]?.stream ?? r.getLocalStream();
946
+ function o(r) {
947
+ const c = a.getRemoteStreams();
948
+ return r ? c.find((d) => d.participant.participantId === r)?.stream ?? null : c[0]?.stream ?? a.getLocalStream();
949
949
  }
950
950
  return {
951
951
  supported: i,
952
- async enter(o) {
952
+ async enter(r) {
953
953
  if (!i) throw new Error("This browser does not support picture-in-picture");
954
- const c = a(o);
954
+ const c = o(r);
955
955
  if (!c) throw new Error("No video stream is available for picture-in-picture");
956
956
  const d = s();
957
957
  d.srcObject !== c && (d.srcObject = c), await d.play().catch(() => {
@@ -965,82 +965,82 @@ function Ee(r, e = {}) {
965
965
  }
966
966
  };
967
967
  }
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,
968
+ function je(a, 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", o = e.height ?? 720, r = Math.round(o * 16 / 9);
970
+ let c = null, d = null, l = null, u = null, y = 0, f = [], w = !1;
971
+ async function m(S, T, k, b = "application/json") {
972
+ const M = await i(`${n}${T}`, {
973
+ method: S,
974
974
  headers: {
975
975
  authorization: `Bearer ${e.credential.signalingToken}`,
976
- "content-type": T
976
+ "content-type": b
977
977
  },
978
- body: y === void 0 ? void 0 : T === "application/json" ? JSON.stringify(y) : y
978
+ body: k === void 0 ? void 0 : b === "application/json" ? JSON.stringify(k) : k
979
979
  });
980
- if (!I.ok) throw new Error(`Recording request failed with HTTP ${I.status}`);
981
- return I.json();
980
+ if (!M.ok) throw new Error(`Recording request failed with HTTP ${M.status}`);
981
+ return M.json();
982
982
  }
983
983
  return {
984
984
  get recording() {
985
- return k;
985
+ return w;
986
986
  },
987
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;
988
+ if (w) return;
989
+ u = (await m("POST", "/v1/rtc/recordings")).recordingId;
990
+ const T = t.createElement("canvas");
991
+ T.width = r, T.height = o;
992
+ const k = T.getContext("2d"), b = /* @__PURE__ */ new Map(), M = (E, P) => {
993
+ let C = b.get(E);
994
+ return C || (C = t.createElement("video"), C.muted = !0, C.playsInline = !0, C.srcObject = P, C.play().catch(() => {
995
+ }), b.set(E, C)), C;
996
996
  };
997
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 })),
998
+ const E = a.getRemoteStreams(), P = a.getLocalStream(), C = [
999
+ ...E.map((j) => ({ key: j.participant.participantId, stream: j.stream, label: j.participant.displayName })),
1000
1000
  ...P ? [{ key: "local", stream: P, label: "me" }] : []
1001
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);
1002
+ k.fillStyle = "#101418", k.fillRect(0, 0, r, o);
1003
+ const D = Math.max(1, Math.ceil(Math.sqrt(C.length))), v = Math.max(1, Math.ceil(C.length / D)), N = r / D, U = o / v;
1004
+ C.forEach((j, H) => {
1005
+ const _ = M(j.key, j.stream), B = H % D * N, F = Math.floor(H / D) * U;
1006
+ _.videoWidth > 0 && k.drawImage(_, B + 2, F + 2, N - 4, U - 4), k.fillStyle = "rgba(0,0,0,.6)", k.fillRect(B + 8, F + U - 30, Math.min(N - 16, 12 + j.label.length * 9), 22), k.fillStyle = "#fff", k.font = "14px system-ui", k.fillText(j.label, B + 14, F + U - 14);
1007
1007
  });
1008
1008
  }, 66);
1009
- const R = S.captureStream(15);
1009
+ const I = T.captureStream(15);
1010
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()] : []
1011
+ const g = l.createMediaStreamDestination(), p = /* @__PURE__ */ new Set(), h = () => {
1012
+ const E = [
1013
+ ...a.getRemoteStreams().map((P) => P.stream),
1014
+ ...a.getLocalStream() ? [a.getLocalStream()] : []
1015
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));
1016
+ for (const P of E)
1017
+ for (const C of P.getAudioTracks())
1018
+ p.has(C.id) || (p.add(C.id), l.createMediaStreamSource(new MediaStream([C])).connect(g));
1019
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;
1020
+ h();
1021
+ const R = setInterval(h, 1e3), L = () => clearInterval(R);
1022
+ for (const E of g.stream.getAudioTracks()) I.addTrack(E);
1023
+ c = (e.mediaRecorderFactory ?? ((E, P) => new MediaRecorder(E, P)))(I, { mimeType: s }), f = [], c.addEventListener("dataavailable", (E) => {
1024
+ E.data && E.data.size > 0 && f.push(E.data);
1025
+ }), c.addEventListener("stop", L), c.start(1e3), y = Date.now(), w = !0;
1026
1026
  },
1027
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(() => {
1028
+ if (!w || !c || !u) throw new Error("The recorder is not running");
1029
+ w = !1;
1030
+ const S = c, T = new Promise((g) => S.addEventListener("stop", () => g(), { once: !0 }));
1031
+ S.stop(), await T, d && clearInterval(d), d = null, await l?.close().catch(() => {
1032
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(
1033
+ const k = new Blob(f, { type: s });
1034
+ f = [];
1035
+ const b = Math.max(1, Math.round((Date.now() - y) / 1e3)), M = await m(
1036
1036
  "PUT",
1037
- `/v1/rtc/recordings/${encodeURIComponent(h)}/media`,
1038
- y,
1037
+ `/v1/rtc/recordings/${encodeURIComponent(u)}/media`,
1038
+ k,
1039
1039
  s
1040
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;
1041
+ await m("POST", `/v1/rtc/recordings/${encodeURIComponent(u)}/complete`, { durationSeconds: b });
1042
+ const I = { recordingId: u, sizeBytes: M.sizeBytes, durationSeconds: b };
1043
+ return u = null, c = null, I;
1044
1044
  },
1045
1045
  dispose() {
1046
1046
  d && clearInterval(d), d = null;
@@ -1049,112 +1049,274 @@ function Re(r, e) {
1049
1049
  } catch {
1050
1050
  }
1051
1051
  c = null, l?.close().catch(() => {
1052
- }), l = null, k = !1;
1052
+ }), l = null, w = !1;
1053
1053
  }
1054
1054
  };
1055
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);
1056
+ const Se = ["none", "blur", "aurora", "cybergrid", "bokeh", "sunset", "image"], ke = ["none", "snow", "confetti", "vignette"], K = {
1057
+ aurora(a, e, t, i) {
1058
+ const n = a.createLinearGradient(0, 0, 0, t);
1059
+ n.addColorStop(0, "#050b1e"), n.addColorStop(1, "#0b2540"), a.fillStyle = n, a.fillRect(0, 0, e, t);
1060
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);
1061
+ a.beginPath();
1062
+ for (let o = 0; o <= e; o += 16) {
1063
+ const r = t * 0.35 + s * 40 + Math.sin(o / 140 + i / 900 + s) * 60;
1064
+ o === 0 ? a.moveTo(o, r) : a.lineTo(o, r);
1065
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();
1066
+ a.lineTo(e, 0), a.lineTo(0, 0), a.closePath(), a.fillStyle = `hsla(${140 + s * 40 + Math.sin(i / 1300) * 20}, 80%, 55%, 0.14)`, a.fill();
1067
1067
  }
1068
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;
1069
+ cybergrid(a, e, t, i) {
1070
+ a.fillStyle = "#0a0118", a.fillRect(0, 0, e, t), a.strokeStyle = "rgba(255,0,180,0.5)", a.lineWidth = 1.5;
1071
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();
1072
+ for (let o = 0; o < 12; o += 1) {
1073
+ const r = n + (o * 34 + i / 18) % (t - n);
1074
+ a.beginPath(), a.moveTo(0, r), a.lineTo(e, r), a.stroke();
1075
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();
1076
+ for (let o = -8; o <= 8; o += 1)
1077
+ a.beginPath(), a.moveTo(e / 2 + o * 24, n), a.lineTo(e / 2 + o * e * 0.12, t), a.stroke();
1078
+ const s = a.createLinearGradient(0, t * 0.1, 0, n);
1079
+ s.addColorStop(0, "#ffd34d"), s.addColorStop(1, "#ff2d78"), a.fillStyle = s, a.beginPath(), a.arc(e / 2, n, t * 0.22, Math.PI, 0), a.fill();
1080
1080
  },
1081
- bokeh(r, e, t, i) {
1082
- r.fillStyle = "#14100c", r.fillRect(0, 0, e, t);
1081
+ bokeh(a, e, t, i) {
1082
+ a.fillStyle = "#14100c", a.fillRect(0, 0, e, t);
1083
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();
1084
+ const s = (Math.sin(n * 12.9898) * 0.5 + 0.5) * e, o = (Math.sin(n * 78.233) * 0.5 + 0.5) * t + Math.sin(i / 1500 + n) * 12, r = 14 + n % 5 * 12;
1085
+ a.fillStyle = `hsla(${35 + n % 4 * 12}, 90%, 60%, ${0.1 + n % 3 * 0.05})`, a.beginPath(), a.arc(s, o, r, 0, Math.PI * 2), a.fill();
1086
1086
  }
1087
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);
1088
+ sunset(a, e, t, i) {
1089
+ const n = a.createLinearGradient(0, 0, 0, t);
1090
+ n.addColorStop(0, "#2b1055"), n.addColorStop(0.55, "#d1548a"), n.addColorStop(1, "#ffb36b"), a.fillStyle = n, a.fillRect(0, 0, e, t), a.fillStyle = "#ffdf8e", a.beginPath(), a.arc(e * 0.5, t * 0.62 + Math.sin(i / 4e3) * 4, t * 0.13, 0, Math.PI * 2), a.fill(), a.fillStyle = "rgba(20,8,40,0.85)", a.fillRect(0, t * 0.78, e, t * 0.22);
1091
1091
  }
1092
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(() => {
1093
+ function Ve(a, e = {}) {
1094
+ const t = e.document ?? globalThis.document, i = e.width ?? 1280, n = e.height ?? 720, s = e.frameRate ?? 24, o = a instanceof MediaStreamTrack ? a : a.getVideoTracks()[0];
1095
+ if (!o) throw new Error("A video track is required");
1096
+ let r = e.background ?? "none", c = e.overlay ?? "none", d = e.backgroundImage ?? null, l = e.segmenter ?? null, u = null, y = !1;
1097
+ const f = t.createElement("video");
1098
+ f.muted = !0, f.playsInline = !0, f.srcObject = new MediaStream([o]), f.play().catch(() => {
1099
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
1100
+ const w = t.createElement("canvas");
1101
+ w.width = i, w.height = n;
1102
+ const m = w.getContext("2d"), S = t.createElement("canvas");
1103
+ S.width = i, S.height = n;
1104
+ const T = S.getContext("2d"), k = Array.from({ length: 80 }, (p, h) => ({
1105
+ x: (Math.sin(h * 12.9898) * 0.5 + 0.5) * i,
1106
+ y: (Math.sin(h * 78.233) * 0.5 + 0.5) * n,
1107
+ speed: 0.6 + h % 5 * 0.5,
1108
+ drift: Math.sin(h) * 0.6,
1109
+ size: 2 + h % 4,
1110
+ hue: h * 47 % 360
1111
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);
1112
+ function b() {
1113
+ if (u) {
1114
+ T.clearRect(0, 0, i, n), T.drawImage(u, 0, 0, i, n), T.globalCompositeOperation = "source-in", T.drawImage(f, 0, 0, i, n), T.globalCompositeOperation = "source-over", m.drawImage(S, 0, 0);
1115
1115
  return;
1116
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();
1117
+ const p = i * 0.42, h = p * 9 / 16, R = i - p - 24, L = n - h - 24;
1118
+ m.save(), m.shadowColor = "rgba(0,0,0,.5)", m.shadowBlur = 24, m.beginPath(), m.roundRect(R, L, p, h, 14), m.clip(), m.drawImage(f, R, L, p, h), m.restore();
1119
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());
1120
+ function M(p) {
1121
+ if (r === "none" ? m.drawImage(f, 0, 0, i, n) : r === "blur" ? (m.filter = "blur(14px)", m.drawImage(f, -16, -16, i + 32, n + 32), m.filter = "none", u && b()) : r === "image" && d ? (m.drawImage(d, 0, 0, i, n), b()) : ((K[r] ?? K.aurora)(m, i, n, p), b()), c === "snow" || c === "confetti")
1122
+ for (const h of k)
1123
+ h.y += h.speed * (c === "confetti" ? 1.6 : 1), h.x += h.drift, h.y > n && (h.y = -6, h.x = Math.random() * i), m.fillStyle = c === "snow" ? "rgba(255,255,255,.85)" : `hsl(${h.hue}, 90%, 60%)`, c === "confetti" ? m.fillRect(h.x, h.y, h.size + 2, h.size) : (m.beginPath(), m.arc(h.x, h.y, h.size / 2, 0, Math.PI * 2), m.fill());
1124
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);
1125
+ const h = m.createRadialGradient(i / 2, n / 2, n * 0.4, i / 2, n / 2, n * 0.85);
1126
+ h.addColorStop(0, "rgba(0,0,0,0)"), h.addColorStop(1, "rgba(0,0,0,0.55)"), m.fillStyle = h, m.fillRect(0, 0, i, n);
1127
1127
  }
1128
1128
  }
1129
- const R = setInterval(() => {
1130
- I(Date.now()), l && !v && o !== "none" && (v = !0, l.segment(g).then((f) => {
1131
- h = f;
1129
+ const I = setInterval(() => {
1130
+ M(Date.now()), l && !y && r !== "none" && (y = !0, l.segment(f).then((p) => {
1131
+ u = p;
1132
1132
  }).catch(() => {
1133
- h = null;
1133
+ u = null;
1134
1134
  }).finally(() => {
1135
- v = !1;
1135
+ y = !1;
1136
1136
  }));
1137
- }, Math.round(1e3 / s)), E = k.captureStream(s);
1137
+ }, Math.round(1e3 / s)), g = w.captureStream(s);
1138
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);
1139
+ track: g.getVideoTracks()[0],
1140
+ stream: g,
1141
+ setBackground(p, h) {
1142
+ r = Se.includes(p) ? p : "none", h !== void 0 && (d = h), r === "none" && (u = null);
1143
1143
  },
1144
- setOverlay(f) {
1145
- c = pe.includes(f) ? f : "none";
1144
+ setOverlay(p) {
1145
+ c = ke.includes(p) ? p : "none";
1146
1146
  },
1147
- setSegmenter(f) {
1148
- l = f, f || (h = null);
1147
+ setSegmenter(p) {
1148
+ l = p, p || (u = null);
1149
1149
  },
1150
1150
  dispose() {
1151
- clearInterval(R), l?.close?.();
1152
- for (const f of E.getTracks()) f.stop();
1153
- g.srcObject = null;
1151
+ clearInterval(I), l?.close?.();
1152
+ for (const p of g.getTracks()) p.stop();
1153
+ f.srcObject = null;
1154
1154
  }
1155
1155
  };
1156
1156
  }
1157
- class fe extends EventTarget {
1157
+ function le() {
1158
+ return {
1159
+ blinkLeft: 0,
1160
+ blinkRight: 0,
1161
+ jawOpen: 0,
1162
+ smile: 0,
1163
+ browUp: 0,
1164
+ pupilX: 0,
1165
+ pupilY: 0,
1166
+ headYaw: 0,
1167
+ headPitch: 0,
1168
+ headRoll: 0,
1169
+ tracked: !1
1170
+ };
1171
+ }
1172
+ function A(a, e) {
1173
+ const t = a.find((i) => i.categoryName === e);
1174
+ return t ? Math.max(0, Math.min(1, t.score)) : 0;
1175
+ }
1176
+ function we(a) {
1177
+ if (!a || a.length < 16) return { yaw: 0, pitch: 0, roll: 0 };
1178
+ a[0], a[4];
1179
+ const e = a[8], t = a[1], i = a[5], n = a[9], s = a[10], o = Math.atan2(e, s), r = Math.asin(Math.max(-1, Math.min(1, -n))), c = Math.atan2(t, i);
1180
+ return { yaw: o, pitch: r, roll: c };
1181
+ }
1182
+ function Te(a, e, t = 1) {
1183
+ if (!a || a.length === 0) return le();
1184
+ const i = we(e), n = (A(a, "eyeLookOutRight") + A(a, "eyeLookInLeft")) / 2, s = (A(a, "eyeLookOutLeft") + A(a, "eyeLookInRight")) / 2, o = (A(a, "eyeLookUpLeft") + A(a, "eyeLookUpRight")) / 2, r = (A(a, "eyeLookDownLeft") + A(a, "eyeLookDownRight")) / 2, c = (A(a, "mouthSmileLeft") + A(a, "mouthSmileRight")) / 2, d = (A(a, "mouthFrownLeft") + A(a, "mouthFrownRight")) / 2, l = A(a, "eyeBlinkLeft"), u = A(a, "eyeBlinkRight"), y = Math.min(1, Math.abs(i.yaw) / 0.35) * Math.max(0, Math.min(1, t)), f = (l + u) / 2;
1185
+ return {
1186
+ blinkLeft: l + (f - l) * y,
1187
+ blinkRight: u + (f - u) * y,
1188
+ jawOpen: A(a, "jawOpen"),
1189
+ smile: c - d,
1190
+ browUp: (A(a, "browInnerUp") + A(a, "browOuterUpLeft") + A(a, "browOuterUpRight")) / 3,
1191
+ pupilX: n - s,
1192
+ pupilY: r - o,
1193
+ headYaw: i.yaw,
1194
+ headPitch: i.pitch,
1195
+ headRoll: i.roll,
1196
+ tracked: !0
1197
+ };
1198
+ }
1199
+ function X(a, e, t = 0.4) {
1200
+ const i = (n, s) => n + (s - n) * t;
1201
+ return {
1202
+ blinkLeft: i(a.blinkLeft, e.blinkLeft),
1203
+ blinkRight: i(a.blinkRight, e.blinkRight),
1204
+ jawOpen: i(a.jawOpen, e.jawOpen),
1205
+ smile: i(a.smile, e.smile),
1206
+ browUp: i(a.browUp, e.browUp),
1207
+ pupilX: i(a.pupilX, e.pupilX),
1208
+ pupilY: i(a.pupilY, e.pupilY),
1209
+ headYaw: i(a.headYaw, e.headYaw),
1210
+ headPitch: i(a.headPitch, e.headPitch),
1211
+ headRoll: i(a.headRoll, e.headRoll),
1212
+ tracked: e.tracked
1213
+ };
1214
+ }
1215
+ function be(a, e, t, i, n) {
1216
+ n || (a.fillStyle = "#101822", a.fillRect(0, 0, t, i));
1217
+ const s = n ? n.x + e.headYaw * n.radius * 0.1 : t / 2 + e.headYaw * t * 0.18, o = n ? n.y + e.headPitch * n.radius * 0.1 : i / 2 + e.headPitch * i * 0.18, r = n ? n.radius : Math.min(t, i) * 0.28;
1218
+ a.save(), a.translate(s, o), a.rotate(e.headRoll * 0.6);
1219
+ const c = Math.max(-1.35, Math.min(1.35, e.headYaw)), d = Math.max(-0.9, Math.min(0.9, e.headPitch)), l = Math.sin(c), u = (p) => Math.sin(p + c) * r, y = (p) => Math.cos(p + c), f = Math.sin(d) * r * 0.22;
1220
+ a.fillStyle = "#3a2a1c", a.beginPath(), a.ellipse(-l * r * 0.35, -r * 0.25, r * 0.98, r * 0.95, 0, 0, Math.PI * 2), a.fill(), a.fillStyle = e.tracked ? "#f2c9a0" : "#5a6470", a.beginPath(), a.ellipse(0, 0, r * (1 - Math.abs(l) * 0.12), r * 1.12, 0, 0, Math.PI * 2), a.fill(), a.fillStyle = "#3a2a1c", a.beginPath(), a.ellipse(-l * r * 0.28, -r * 0.72 + f * 0.4, r * 0.92, r * 0.5, 0, Math.PI, Math.PI * 2), a.fill();
1221
+ const w = 0;
1222
+ a.fillStyle = "#e5b58a", a.beginPath();
1223
+ const m = u(w) * 0.9, S = r * 0.12 + f;
1224
+ a.ellipse(m + l * r * 0.14, S, r * 0.11, r * 0.14, 0, 0, Math.PI * 2), a.fill();
1225
+ for (const p of [-1, 1]) {
1226
+ const h = p * 0.42, R = y(h);
1227
+ if (R <= 0.12) continue;
1228
+ const L = u(h) * 0.82, q = Math.max(0.2, R), E = p < 0 ? e.blinkLeft : e.blinkRight, P = Math.max(0.06, 1 - E), C = e.browUp * r * 0.14;
1229
+ a.strokeStyle = "#4a2e18", a.lineWidth = r * 0.07, a.lineCap = "round", a.beginPath(), a.moveTo(L - r * 0.2 * q, -r * 0.42 - C + f), a.quadraticCurveTo(L, -r * 0.52 - C + f, L + r * 0.2 * q, -r * 0.44 - C + f), a.stroke();
1230
+ const D = -r * 0.18 + f;
1231
+ a.fillStyle = "#ffffff", a.beginPath(), a.ellipse(L, D, r * 0.16 * q, r * 0.12 * P, 0, 0, Math.PI * 2), a.fill(), a.fillStyle = "#22303c", a.beginPath(), a.ellipse(
1232
+ L + e.pupilX * r * 0.07 * q,
1233
+ D + e.pupilY * r * 0.05,
1234
+ r * 0.06 * q,
1235
+ r * 0.06 * P,
1236
+ 0,
1237
+ 0,
1238
+ Math.PI * 2
1239
+ ), a.fill();
1240
+ }
1241
+ const T = Math.max(0.25, y(0)), k = u(0) * 0.7, b = r * 0.55 * T, M = r * (0.04 + e.jawOpen * 0.34), I = e.smile * r * 0.12, g = r * 0.42 + f;
1242
+ a.fillStyle = "#8c2f2f", a.beginPath(), a.moveTo(k - b / 2, g - I), a.quadraticCurveTo(k, g + M, k + b / 2, g - I), a.quadraticCurveTo(k, g - M * 0.25, k - b / 2, g - I), a.closePath(), a.fill(), a.restore(), !e.tracked && !n && (a.fillStyle = "#9fb0bd", a.font = `${Math.round(i * 0.045)}px system-ui`, a.textAlign = "center", a.fillText("No face detected", t / 2, i * 0.9), a.textAlign = "left");
1243
+ }
1244
+ const Z = {
1245
+ mouthGain: 1.7,
1246
+ blinkGain: 1,
1247
+ eyeSync: 1,
1248
+ smoothing: 0.4,
1249
+ avatarScale: 1,
1250
+ avatarLift: 0,
1251
+ lostHoldMs: 400
1252
+ };
1253
+ function ee() {
1254
+ return {
1255
+ render(a, e, t, i, n) {
1256
+ be(a, e, t, i, n ?? void 0);
1257
+ }
1258
+ };
1259
+ }
1260
+ const z = (a) => Math.max(0, Math.min(1, a));
1261
+ function Ue(a, e = {}) {
1262
+ const t = e.document ?? globalThis.document, i = e.width ?? 1280, n = e.height ?? 720, s = e.frameRate ?? 24, o = a instanceof MediaStreamTrack ? a : a.getVideoTracks()[0];
1263
+ if (!o) throw new Error("A video track is required");
1264
+ let r = e.tracker ?? null, c = e.renderer ?? ee(), d = e.mode ?? "replace";
1265
+ const l = { ...Z, ...e.tuning }, u = e.backdrop ?? "#101822", y = t.createElement("video");
1266
+ y.muted = !0, y.playsInline = !0, y.srcObject = new MediaStream([o]), y.play().catch(() => {
1267
+ });
1268
+ const f = t.createElement("canvas");
1269
+ f.width = i, f.height = n;
1270
+ const w = f.getContext("2d");
1271
+ let m = le(), S = null, T = 0;
1272
+ function k(g) {
1273
+ if (g.length <= 454) return;
1274
+ const p = g[10], h = g[152], R = g[234], L = g[454], q = (R.x + L.x) / 2 * i, E = (R.y + L.y) / 2 * n, P = Math.hypot((h.x - p.x) * i, (h.y - p.y) * n), C = Math.max(0.6, Math.cos(m.headPitch)), D = { x: q, y: E, radius: Math.max(24, P / C * 0.8) };
1275
+ S = S ? { x: S.x + (D.x - S.x) * 0.4, y: S.y + (D.y - S.y) * 0.4, radius: S.radius + (D.radius - S.radius) * 0.15 } : D;
1276
+ }
1277
+ function b(g) {
1278
+ if (r && y.readyState >= 2) {
1279
+ let h = null;
1280
+ try {
1281
+ h = r.detect(y, g);
1282
+ } catch {
1283
+ }
1284
+ const R = Te(h?.categories ?? null, h?.matrix ?? null, l.eyeSync);
1285
+ R.jawOpen = z(R.jawOpen * l.mouthGain), R.blinkLeft = z(R.blinkLeft * l.blinkGain), R.blinkRight = z(R.blinkRight * l.blinkGain), R.tracked ? (T = g, m = X(m, R, l.smoothing), h?.landmarks && k(h.landmarks)) : m.tracked && g - T > l.lostHoldMs && (m = X(m, { ...m, jawOpen: 0, browUp: 0, smile: m.smile * 0.5, blinkLeft: 0.1, blinkRight: 0.1 }, 0.05));
1286
+ }
1287
+ d === "overlay" && y.readyState >= 2 ? w.drawImage(y, 0, 0, i, n) : (w.fillStyle = u, w.fillRect(0, 0, i, n));
1288
+ const p = d === "overlay" && S ? { x: S.x, y: S.y + l.avatarLift * S.radius, radius: S.radius * l.avatarScale } : null;
1289
+ c?.render(w, m, i, n, p);
1290
+ }
1291
+ const M = setInterval(() => b(Date.now()), Math.round(1e3 / s)), I = f.captureStream(s);
1292
+ return {
1293
+ track: I.getVideoTracks()[0],
1294
+ stream: I,
1295
+ getRig: () => ({ ...m }),
1296
+ setMode(g) {
1297
+ d = g === "overlay" ? "overlay" : "replace";
1298
+ },
1299
+ setTracker(g) {
1300
+ r?.close?.(), r = g;
1301
+ },
1302
+ setRenderer(g) {
1303
+ c?.dispose?.(), c = g ?? ee();
1304
+ },
1305
+ setTuning(g) {
1306
+ for (const p of Object.keys(Z)) {
1307
+ const h = g[p];
1308
+ typeof h == "number" && Number.isFinite(h) && (l[p] = h);
1309
+ }
1310
+ },
1311
+ getTuning: () => ({ ...l }),
1312
+ dispose() {
1313
+ clearInterval(M), r?.close?.(), c?.dispose?.();
1314
+ for (const g of I.getTracks()) g.stop();
1315
+ y.srcObject = null;
1316
+ }
1317
+ };
1318
+ }
1319
+ class Ce extends EventTarget {
1158
1320
  mode;
1159
1321
  options;
1160
1322
  client = null;
@@ -1188,7 +1350,7 @@ class fe extends EventTarget {
1188
1350
  async initialize() {
1189
1351
  if (this.client) return this;
1190
1352
  try {
1191
- const t = (this.options.transport === "auto" ? this.mode === "meeting" ? "sfu" : "mesh" : this.options.transport ?? "mesh") === "sfu" ? he : Q;
1353
+ const t = (this.options.transport === "auto" ? this.mode === "meeting" ? "sfu" : "mesh" : this.options.transport ?? "mesh") === "sfu" ? ye : x;
1192
1354
  return this.client = new t({
1193
1355
  credential: {
1194
1356
  signalingToken: this.options.credential.signalingToken,
@@ -1207,19 +1369,19 @@ class fe extends EventTarget {
1207
1369
  iceTransportPolicy: this.options.iceTransportPolicy ?? "all",
1208
1370
  localStream: this.options.localStream,
1209
1371
  onEvent: (i, n) => this.handleNativeEvent(i, n)
1210
- }), await this.client.initialize(), this.startStats(), this.emit("initialized", { mode: this.mode, sdkVersion: be }), this.options.autoJoin && await this.join(), this;
1372
+ }), await this.client.initialize(), this.startStats(), this.emit("initialized", { mode: this.mode, sdkVersion: De }), this.options.autoJoin && await this.join(), this;
1211
1373
  } catch (e) {
1212
1374
  this.state = "failed";
1213
- const t = te(e, "RTC initialization failed");
1214
- throw this.emit("error", x(t)), t;
1375
+ const t = re(e, "RTC initialization failed");
1376
+ throw this.emit("error", V(t)), t;
1215
1377
  }
1216
1378
  }
1217
1379
  async join() {
1218
1380
  const e = this.requireClient();
1219
1381
  return this.joinPromise ? this.joinPromise : (this.state = "joining", this.emit("joining", {}), this.joinPromise = e.join().catch((t) => {
1220
1382
  this.state = "failed";
1221
- const i = te(t, "RTC connection failed");
1222
- throw this.emit("error", x(i)), i;
1383
+ const i = re(t, "RTC connection failed");
1384
+ throw this.emit("error", V(i)), i;
1223
1385
  }).finally(() => {
1224
1386
  this.joinPromise = null;
1225
1387
  }), this.joinPromise);
@@ -1257,14 +1419,14 @@ class fe extends EventTarget {
1257
1419
  return navigator.mediaDevices?.enumerateDevices ? navigator.mediaDevices.enumerateDevices() : [];
1258
1420
  }
1259
1421
  getParticipants() {
1260
- return this.requireClient().getParticipants().map(X);
1422
+ return this.requireClient().getParticipants().map(ne);
1261
1423
  }
1262
1424
  getLocalStream() {
1263
1425
  return this.client?.getLocalStream() ?? null;
1264
1426
  }
1265
1427
  getRemoteStreams() {
1266
1428
  return (this.client?.getRemoteStreams() ?? []).map((e) => ({
1267
- participant: X(e.participant),
1429
+ participant: ne(e.participant),
1268
1430
  stream: e.stream
1269
1431
  }));
1270
1432
  }
@@ -1333,19 +1495,19 @@ class fe extends EventTarget {
1333
1495
  let n = "unavailable";
1334
1496
  if (e.requestMedia !== !1 && navigator.mediaDevices?.getUserMedia)
1335
1497
  try {
1336
- (await navigator.mediaDevices.getUserMedia({ audio: this.options.audio, video: this.options.video })).getTracks().forEach((v) => v.stop()), n = "granted";
1498
+ (await navigator.mediaDevices.getUserMedia({ audio: this.options.audio, video: this.options.video })).getTracks().forEach((y) => y.stop()), n = "granted";
1337
1499
  } catch {
1338
1500
  n = "denied", t.push("media_permission_denied");
1339
1501
  }
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");
1502
+ const s = navigator.mediaDevices?.enumerateDevices ? await navigator.mediaDevices.enumerateDevices().catch(() => []) : [], o = s.filter((u) => u.kind === "audioinput").length, r = s.filter((u) => u.kind === "videoinput").length;
1503
+ this.options.audio && o === 0 && t.push("microphone_unavailable"), this.options.video && r === 0 && t.push("camera_unavailable");
1342
1504
  const c = e.probeUrl ?? this.options.preflightProbeUrl;
1343
1505
  let d = null;
1344
1506
  if (c) {
1345
- const h = performance.now();
1507
+ const u = performance.now();
1346
1508
  try {
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");
1509
+ const y = await fetch(c, { method: "HEAD", cache: "no-store", credentials: "omit" });
1510
+ d = Math.round(performance.now() - u), y.ok || t.push("network_probe_failed");
1349
1511
  } catch {
1350
1512
  t.push("network_probe_failed");
1351
1513
  }
@@ -1355,10 +1517,10 @@ class fe extends EventTarget {
1355
1517
  sampledAt: (/* @__PURE__ */ new Date()).toISOString(),
1356
1518
  secureContext: i,
1357
1519
  mediaPermission: n,
1358
- microphoneCount: a,
1359
- cameraCount: o,
1520
+ microphoneCount: o,
1521
+ cameraCount: r,
1360
1522
  probeLatencyMs: d,
1361
- effectiveConnectionType: Z()?.effectiveType ?? null,
1523
+ effectiveConnectionType: ae()?.effectiveType ?? null,
1362
1524
  issues: t
1363
1525
  };
1364
1526
  return this.emit("preflight", l), this.options.autoReportStats && await this.reportQuality({
@@ -1371,7 +1533,7 @@ class fe extends EventTarget {
1371
1533
  }), l;
1372
1534
  }
1373
1535
  async collectQualitySample(e = "runtime") {
1374
- const t = this.options.statsProvider ? await this.options.statsProvider() : {}, i = this.peerConnection ? await ke(this.peerConnection, this.previousCounters) : null;
1536
+ const t = this.options.statsProvider ? await this.options.statsProvider() : {}, i = this.peerConnection ? await Pe(this.peerConnection, this.previousCounters) : null;
1375
1537
  i?.counters && (this.previousCounters = i.counters);
1376
1538
  const s = { ...{
1377
1539
  sampleType: e,
@@ -1400,10 +1562,10 @@ class fe extends EventTarget {
1400
1562
  transportProtocol: null,
1401
1563
  candidateType: null,
1402
1564
  qualityLimitationReason: null,
1403
- deviceMemoryGb: we(),
1404
- effectiveConnectionType: Z()?.effectiveType ?? null
1405
- }, ...i?.sample ?? {}, ...t, sampleType: e, sampledAt: (/* @__PURE__ */ new Date()).toISOString() }, a = Te(s);
1406
- return s.networkScore = a.networkScore, s.estimatedMos = a.estimatedMos, this.latestQuality = s, s;
1565
+ deviceMemoryGb: Le(),
1566
+ effectiveConnectionType: ae()?.effectiveType ?? null
1567
+ }, ...i?.sample ?? {}, ...t, sampleType: e, sampledAt: (/* @__PURE__ */ new Date()).toISOString() }, o = Ae(s);
1568
+ return s.networkScore = o.networkScore, s.estimatedMos = o.estimatedMos, this.latestQuality = s, s;
1407
1569
  }
1408
1570
  async reportQuality(e) {
1409
1571
  const t = this.options.credential.telemetryToken, i = this.options.telemetryEndpoint ?? this.options.credential.telemetryEndpoint;
@@ -1453,7 +1615,7 @@ class fe extends EventTarget {
1453
1615
  const i = Date.now(), n = e !== "runtime" || i - this.lastTelemetryAt >= this.options.telemetryInterval;
1454
1616
  this.options.autoReportStats && n && (await this.reportQuality(t), this.lastTelemetryAt = i);
1455
1617
  } catch (t) {
1456
- this.emit("telemetryerror", x(t));
1618
+ this.emit("telemetryerror", V(t));
1457
1619
  } finally {
1458
1620
  this.statsRunning = !1;
1459
1621
  }
@@ -1470,8 +1632,8 @@ class fe extends EventTarget {
1470
1632
  }
1471
1633
  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);
1472
1634
  this.poorQualitySamples = n ? this.poorQualitySamples + 1 : 0, this.goodQualitySamples = s ? this.goodQualitySamples + 1 : 0;
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"));
1635
+ const o = ["low", "medium", "high"], r = o.indexOf(this.effectiveQuality);
1636
+ i && r > 0 ? (this.poorQualitySamples = 0, await this.applyEffectiveQuality("low", "network")) : this.poorQualitySamples >= 2 && r > 0 ? (this.poorQualitySamples = 0, await this.applyEffectiveQuality(o[r - 1], "network")) : this.goodQualitySamples >= 6 && r >= 0 && r < o.length - 1 && (this.goodQualitySamples = 0, await this.applyEffectiveQuality(o[r + 1], "network"));
1475
1637
  }
1476
1638
  async applyEffectiveQuality(e, t) {
1477
1639
  if (this.effectiveQuality === e && this.client) return;
@@ -1487,21 +1649,21 @@ class fe extends EventTarget {
1487
1649
  this.dispatchEvent(new CustomEvent(e, { detail: i })), this.options.onEvent?.(i);
1488
1650
  }
1489
1651
  }
1490
- async function Me(r) {
1491
- return new fe(r).initialize();
1652
+ async function Qe(a) {
1653
+ return new Ce(a).initialize();
1492
1654
  }
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;
1655
+ let Q = null;
1656
+ function de() {
1657
+ if (Q) return Q;
1658
+ const a = globalThis, e = a.AudioContext ?? a.webkitAudioContext;
1659
+ return e ? (Q = new e(), Q) : null;
1498
1660
  }
1499
- async function ge() {
1500
- const r = se();
1501
- return r ? (r.state === "suspended" && await r.resume().catch(() => {
1502
- }), r.state === "running") : !1;
1661
+ async function Re() {
1662
+ const a = de();
1663
+ return a ? (a.state === "suspended" && await a.resume().catch(() => {
1664
+ }), a.state === "running") : !1;
1503
1665
  }
1504
- class ve {
1666
+ class Ie {
1505
1667
  options;
1506
1668
  media = null;
1507
1669
  cadenceTimer = null;
@@ -1510,7 +1672,7 @@ class ve {
1510
1672
  this.options = e;
1511
1673
  }
1512
1674
  unlock() {
1513
- return ge();
1675
+ return Re();
1514
1676
  }
1515
1677
  startIncoming() {
1516
1678
  this.start("incoming", this.options.ringtoneUrl);
@@ -1538,17 +1700,17 @@ class ve {
1538
1700
  i(), this.cadenceTimer = setInterval(i, e === "incoming" ? 3e3 : 3500);
1539
1701
  }
1540
1702
  playBuiltInTone(e) {
1541
- const t = se();
1703
+ const t = de();
1542
1704
  if (!t || t.state !== "running") return;
1543
- const i = e === "incoming" ? 1.25 : 1, n = e === "incoming" ? [440, 480] : [425], s = t.createGain(), a = t.currentTime;
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);
1545
- for (const o of n) {
1705
+ const i = e === "incoming" ? 1.25 : 1, n = e === "incoming" ? [440, 480] : [425], s = t.createGain(), o = t.currentTime;
1706
+ s.gain.setValueAtTime(1e-4, o), s.gain.exponentialRampToValueAtTime(0.045, o + 0.025), s.gain.setValueAtTime(0.045, o + i - 0.06), s.gain.exponentialRampToValueAtTime(1e-4, o + i), s.connect(t.destination);
1707
+ for (const r of n) {
1546
1708
  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);
1709
+ c.type = "sine", c.frequency.value = r, c.connect(s), this.oscillators.add(c), c.onended = () => this.oscillators.delete(c), c.start(o), c.stop(o + i + 0.02);
1548
1710
  }
1549
1711
  }
1550
1712
  }
1551
- class ye extends EventTarget {
1713
+ class Ee extends EventTarget {
1552
1714
  options;
1553
1715
  socket = null;
1554
1716
  stopped = !1;
@@ -1575,14 +1737,14 @@ class ye extends EventTarget {
1575
1737
  if (e.token && !e.token.startsWith("rtcc_")) throw new Error("A valid RTC client token is required");
1576
1738
  if (!e.signalingUrl && !e.apiBaseUrl && !globalThis.location?.origin)
1577
1739
  throw new Error("signalingUrl or apiBaseUrl is required outside a browser");
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();
1740
+ this.options = e, this.currentToken = e.token ?? null, this.currentTokenExpiresAt = e.tokenExpiresAt, this.callAudio = new Ie(e), this.mount = te(e.mount), this.scheduleTokenRefresh();
1579
1741
  }
1580
1742
  connect() {
1581
1743
  if (!this.options.signalingUrl) throw new Error("signalingUrl is required to connect signaling");
1582
1744
  return this.stopped = !1, this.scheduleTokenRefresh(), this.openSocket("initial"), this;
1583
1745
  }
1584
1746
  setMount(e) {
1585
- this.clearUi(), this.mount = K(e), this.currentCall && this.renderIncoming(this.currentCall);
1747
+ this.clearUi(), this.mount = te(e), this.currentCall && this.renderIncoming(this.currentCall);
1586
1748
  }
1587
1749
  /** Binds media lifetime to a call. Terminal call states automatically leave and destroy it. */
1588
1750
  attachMediaClient(e, t) {
@@ -1610,8 +1772,8 @@ class ye extends EventTarget {
1610
1772
  headers: e.idempotencyKey ? { "idempotency-key": e.idempotencyKey } : void 0,
1611
1773
  body: JSON.stringify(i)
1612
1774
  });
1613
- } catch (a) {
1614
- throw this.callAudio.stop(), a;
1775
+ } catch (o) {
1776
+ throw this.callAudio.stop(), o;
1615
1777
  }
1616
1778
  return !s.credential && s.callerCredential && (s.credential = s.callerCredential), this.outgoingCallId = String(s.call?.id ?? "") || null, this.outgoingCallId && this.activeCallIds.add(this.outgoingCallId), this.emit("outgoingcall", s), s;
1617
1779
  })();
@@ -1668,7 +1830,7 @@ class ye extends EventTarget {
1668
1830
  /** Applies a call state received through the application's own push or signaling channel. */
1669
1831
  handleCallUpdate(e) {
1670
1832
  const t = e.id === this.currentCall?.id || e.id === this.outgoingCallId;
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);
1833
+ 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, Me(e.status)), ["rejected", "busy", "cancelled", "ended", "failed", "missed"].includes(e.status) && this.releaseMedia(e.id), this.emit("callupdated", e);
1672
1834
  }
1673
1835
  disconnect() {
1674
1836
  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();
@@ -1684,7 +1846,7 @@ class ye extends EventTarget {
1684
1846
  try {
1685
1847
  t = await this.resolveToken(e, e === "reconnect");
1686
1848
  } catch (s) {
1687
- this.emit("tokenerror", x(s)), !this.stopped && this.options.reconnect !== !1 && this.scheduleReconnect();
1849
+ this.emit("tokenerror", V(s)), !this.stopped && this.options.reconnect !== !1 && this.scheduleReconnect();
1688
1850
  return;
1689
1851
  }
1690
1852
  if (this.stopped || this.socket) return;
@@ -1692,8 +1854,8 @@ class ye extends EventTarget {
1692
1854
  i.protocol = i.protocol === "https:" ? "wss:" : "ws:";
1693
1855
  const n = new WebSocket(i, ["rtc-client", t]);
1694
1856
  this.socket = n, n.addEventListener("open", () => {
1695
- const s = this.reconnectAttempt > 0, a = this.lastDisconnect;
1696
- this.reconnectAttempt = 0, this.heartbeatDeadline = Date.now() + 45e3, this.emit("signalingconnected", { resumed: s }), a && (this.reportSignalingDiagnostic({ event: "recovered", code: a.code, reason: a.reason, wasClean: a.wasClean, outageMs: Date.now() - a.at }), this.lastDisconnect = null), this.heartbeatTimer && clearInterval(this.heartbeatTimer), this.heartbeatTimer = setInterval(() => {
1857
+ const s = this.reconnectAttempt > 0, o = this.lastDisconnect;
1858
+ this.reconnectAttempt = 0, this.heartbeatDeadline = Date.now() + 45e3, this.emit("signalingconnected", { resumed: s }), o && (this.reportSignalingDiagnostic({ event: "recovered", code: o.code, reason: o.reason, wasClean: o.wasClean, outageMs: Date.now() - o.at }), this.lastDisconnect = null), this.heartbeatTimer && clearInterval(this.heartbeatTimer), this.heartbeatTimer = setInterval(() => {
1697
1859
  if (n.readyState === WebSocket.OPEN) {
1698
1860
  if (Date.now() > this.heartbeatDeadline) {
1699
1861
  n.close(4e3, "Signaling heartbeat timed out");
@@ -1707,14 +1869,14 @@ class ye extends EventTarget {
1707
1869
  }), n.addEventListener("close", (s) => {
1708
1870
  if (this.socket !== n) return;
1709
1871
  this.socket = null, this.heartbeatTimer && clearInterval(this.heartbeatTimer), this.heartbeatTimer = null;
1710
- const a = !this.stopped && this.options.reconnect !== !1, o = {
1872
+ const o = !this.stopped && this.options.reconnect !== !1, r = {
1711
1873
  code: s.code,
1712
1874
  reason: s.reason,
1713
1875
  wasClean: s.wasClean,
1714
- willReconnect: a,
1876
+ willReconnect: o,
1715
1877
  attempt: this.reconnectAttempt + 1
1716
1878
  };
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();
1879
+ o && (this.lastDisconnect = { code: s.code, reason: s.reason, wasClean: s.wasClean, at: Date.now() }), this.emit("signalingdisconnected", r), this.reportSignalingDiagnostic({ event: o ? "reconnecting" : "disconnected", ...r }), o && this.scheduleReconnect();
1718
1880
  }), n.addEventListener("error", () => {
1719
1881
  const s = { message: "RTC signaling connection failed", reconnecting: !this.stopped && this.options.reconnect !== !1, attempt: this.reconnectAttempt + 1 };
1720
1882
  this.emit("signalingerror", s), this.reportSignalingDiagnostic({ event: "error", attempt: s.attempt });
@@ -1748,9 +1910,9 @@ class ye extends EventTarget {
1748
1910
  async request(e, t, i = !1) {
1749
1911
  const n = this.options.apiBaseUrl ?? this.options.signalingUrl ?? globalThis.location?.origin;
1750
1912
  if (!n) throw new Error("apiBaseUrl is required for call actions");
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(() => ({}));
1913
+ const s = new URL(n, globalThis.location?.href), o = await this.resolveToken("initial"), r = new Headers(t.headers);
1914
+ r.set("authorization", `Bearer ${o}`), r.set("content-type", "application/json");
1915
+ const c = await fetch(new URL(e, s.origin), { ...t, headers: r }), d = await c.json().catch(() => ({}));
1754
1916
  if (c.status === 401 && this.options.tokenProvider && !i)
1755
1917
  return await this.resolveToken("unauthorized", !0), this.request(e, t, !0);
1756
1918
  if (!c.ok) {
@@ -1780,12 +1942,12 @@ class ye extends EventTarget {
1780
1942
  n.textContent = e.caller.name, n.style.fontSize = "20px";
1781
1943
  const s = document.createElement("div");
1782
1944
  Object.assign(s.style, { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "10px" });
1783
- const a = Y("Decline", "#fff", "#a32920", "#d9a09b"), o = Y("Answer", "#fff", "#08745f", "#08745f");
1784
- a.addEventListener("click", () => {
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);
1945
+ const o = ie("Decline", "#fff", "#a32920", "#d9a09b"), r = ie("Answer", "#fff", "#08745f", "#08745f");
1946
+ o.addEventListener("click", () => {
1947
+ this.reject(e.id).catch((c) => this.emit("error", V(c)));
1948
+ }), r.addEventListener("click", () => {
1949
+ this.accept(e.id).catch((c) => this.emit("error", V(c)));
1950
+ }), s.appendChild(o), s.appendChild(r), t.appendChild(i), t.appendChild(n), t.appendChild(s), this.mount.replaceChildren(t);
1789
1951
  }
1790
1952
  dismiss(e) {
1791
1953
  e && this.currentCall?.id !== e && this.outgoingCallId !== e || (this.currentCall = null, (!e || this.outgoingCallId === e) && (this.outgoingCallId = null), this.callAudio.stop(), this.clearUi());
@@ -1852,7 +2014,7 @@ class ye extends EventTarget {
1852
2014
  const t = Math.max(0, e - this.refreshSkew(e));
1853
2015
  this.tokenRefreshTimer = setTimeout(() => {
1854
2016
  this.tokenRefreshTimer = null, this.resolveToken("expiring", !0).catch((i) => {
1855
- this.emit("tokenerror", x(i)), this.stopped || (this.tokenRefreshTimer = setTimeout(() => this.scheduleTokenRefresh(), 3e4));
2017
+ this.emit("tokenerror", V(i)), this.stopped || (this.tokenRefreshTimer = setTimeout(() => this.scheduleTokenRefresh(), 3e4));
1856
2018
  });
1857
2019
  }, Math.min(t, 2147e6));
1858
2020
  }
@@ -1866,23 +2028,23 @@ class ye extends EventTarget {
1866
2028
  this.options.reportSignalingDiagnostics === !1 || this.stopped || this.request("/v1/rtc/client/signaling-events", {
1867
2029
  method: "POST",
1868
2030
  body: JSON.stringify({ ...e, occurredAt: (/* @__PURE__ */ new Date()).toISOString() })
1869
- }).catch((t) => this.emit("diagnosticserror", x(t)));
2031
+ }).catch((t) => this.emit("diagnosticserror", V(t)));
1870
2032
  }
1871
2033
  emit(e, t) {
1872
2034
  const i = { type: e, detail: t, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
1873
2035
  this.dispatchEvent(new CustomEvent(e, { detail: i })), this.options.onEvent?.(i);
1874
2036
  }
1875
2037
  }
1876
- function Ae(r) {
1877
- const e = new ye(r);
1878
- return r.autoConnect !== !1 && r.signalingUrl && e.connect(), e;
2038
+ function xe(a) {
2039
+ const e = new Ee(a);
2040
+ return a.autoConnect !== !1 && a.signalingUrl && e.connect(), e;
1879
2041
  }
1880
- function K(r) {
1881
- return r ? typeof r == "string" ? document.querySelector(r) : r : null;
2042
+ function te(a) {
2043
+ return a ? typeof a == "string" ? document.querySelector(a) : a : null;
1882
2044
  }
1883
- function Y(r, e, t, i) {
2045
+ function ie(a, e, t, i) {
1884
2046
  const n = document.createElement("button");
1885
- return n.type = "button", n.textContent = r, Object.assign(n.style, {
2047
+ return n.type = "button", n.textContent = a, Object.assign(n.style, {
1886
2048
  minHeight: "44px",
1887
2049
  border: `1px solid ${i}`,
1888
2050
  borderRadius: "6px",
@@ -1893,7 +2055,7 @@ function Y(r, e, t, i) {
1893
2055
  fontWeight: "700"
1894
2056
  }), n;
1895
2057
  }
1896
- function Se(r) {
2058
+ function Me(a) {
1897
2059
  return {
1898
2060
  rejected: "Call declined",
1899
2061
  busy: "Line busy",
@@ -1901,96 +2063,104 @@ function Se(r) {
1901
2063
  ended: "Call ended",
1902
2064
  failed: "Call failed",
1903
2065
  missed: "No answer"
1904
- }[r] ?? "Call ended";
2066
+ }[a] ?? "Call ended";
1905
2067
  }
1906
- function X(r) {
2068
+ function ne(a) {
1907
2069
  return {
1908
- id: r.participantId,
1909
- name: r.displayName,
2070
+ id: a.participantId,
2071
+ name: a.displayName,
1910
2072
  role: "participant"
1911
2073
  };
1912
2074
  }
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;
2075
+ async function Pe(a, e) {
2076
+ const t = await a.getStats(), i = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
2077
+ let s = 0, o = 0, r = 0, c = 0, d = 0, l = 0, u = 0, y = 0, f = 0, w = 0, m = 0, S = 0, T = 0, k = null, b = null, M = null, I = null, g = null, p = null;
2078
+ t.forEach((v) => {
2079
+ n.set(v.id, v), v.type === "codec" && i.set(v.id, String(v.mimeType ?? ""));
2080
+ }), t.forEach((v) => {
2081
+ if (v.type === "inbound-rtp" && !v.isRemote && (s += Number(v.bytesReceived ?? 0), r += Math.max(0, Number(v.packetsLost ?? 0)), c += Math.max(0, Number(v.packetsReceived ?? 0)), Number.isFinite(v.jitter) && (d += Number(v.jitter), l += 1), u = Math.max(u, Number(v.framesPerSecond ?? 0)), y = Math.max(y, Number(v.frameWidth ?? 0)), f = Math.max(f, Number(v.frameHeight ?? 0)), w += Number(v.framesDropped ?? 0), m += Number(v.freezeCount ?? 0), S += Number(v.totalFreezesDuration ?? 0), T += Number(v.concealedSamples ?? 0), g ||= i.get(String(v.codecId ?? "")) ?? null), v.type === "outbound-rtp" && !v.isRemote && (o += Number(v.bytesSent ?? 0), p ||= v.qualityLimitationReason ? String(v.qualityLimitationReason) : null, g ||= i.get(String(v.codecId ?? "")) ?? null), v.type === "candidate-pair" && (v.selected || v.nominated) && v.state === "succeeded") {
2082
+ k = Number.isFinite(v.currentRoundTripTime) ? Number(v.currentRoundTripTime) : k, b = Number.isFinite(v.availableOutgoingBitrate) ? Number(v.availableOutgoingBitrate) : b;
2083
+ const N = n.get(v.localCandidateId);
2084
+ M = N?.candidateType ? String(N.candidateType) : M, I = N?.protocol ? String(N.protocol) : I;
1923
2085
  }
1924
2086
  });
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;
2087
+ const h = Date.now(), R = e ? Math.max(1e-3, (h - e.timestamp) / 1e3) : 0, L = e ? Math.max(0, Math.round((s - e.inboundBytes) * 8 / R)) : null, q = e ? Math.max(0, Math.round((o - e.outboundBytes) * 8 / R)) : null, E = r + c, P = e ? Math.max(0, r - e.packetsLost) : r, C = e ? Math.max(0, c - e.packetsReceived) : c, D = P + C;
1926
2088
  return {
1927
- counters: { timestamp: u, inboundBytes: s, outboundBytes: a, packetsLost: o, packetsReceived: c },
2089
+ counters: { timestamp: h, inboundBytes: s, outboundBytes: o, packetsLost: r, packetsReceived: c },
1928
2090
  sample: {
1929
- rttMs: y === null ? null : y * 1e3,
2091
+ rttMs: k === null ? null : k * 1e3,
1930
2092
  jitterMs: l ? d / l * 1e3 : null,
1931
- packetLossPct: N ? P / N * 100 : null,
1932
- packetLossCumulativePct: b ? o / b * 100 : null,
1933
- packetsLost: o,
2093
+ packetLossPct: D ? P / D * 100 : null,
2094
+ packetLossCumulativePct: E ? r / E * 100 : null,
2095
+ packetsLost: r,
1934
2096
  packetsReceived: c,
1935
2097
  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
2098
+ outboundBitrateBps: q,
2099
+ availableOutgoingBitrateBps: b,
2100
+ framesPerSecond: u || null,
2101
+ frameWidth: y || null,
2102
+ frameHeight: f || null,
2103
+ framesDropped: w,
2104
+ freezeCount: m,
2105
+ freezeDurationMs: Math.round(S * 1e3),
2106
+ concealedSamples: T,
2107
+ codec: g,
2108
+ transportProtocol: I,
2109
+ candidateType: M,
2110
+ qualityLimitationReason: p
1949
2111
  }
1950
2112
  };
1951
2113
  }
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();
2114
+ function Ae(a) {
2115
+ let e = a.mediaScore == null ? 5 : Math.round(se(Number(a.mediaScore), 0, 5));
2116
+ const t = J(a.packetLossPct) ?? 0, i = J(a.rttMs) ?? 0, n = J(a.jitterMs) ?? 0, s = String(a.connectionState ?? "unknown").toLowerCase();
1955
2117
  ["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));
1956
- const a = Number(ee(4.5 - t * 0.09 - i * 11e-4 - n * 6e-3, 1, 4.5).toFixed(2));
1957
- return { networkScore: e, estimatedMos: a };
2118
+ const o = Number(se(4.5 - t * 0.09 - i * 11e-4 - n * 6e-3, 1, 4.5).toFixed(2));
2119
+ return { networkScore: e, estimatedMos: o };
1958
2120
  }
1959
- function Z() {
2121
+ function ae() {
1960
2122
  return navigator.connection ?? null;
1961
2123
  }
1962
- function we() {
1963
- const r = Number(navigator.deviceMemory);
1964
- return Number.isFinite(r) ? r : null;
2124
+ function Le() {
2125
+ const a = Number(navigator.deviceMemory);
2126
+ return Number.isFinite(a) ? a : null;
1965
2127
  }
1966
- function F(r) {
1967
- const e = Number(r);
2128
+ function J(a) {
2129
+ const e = Number(a);
1968
2130
  return Number.isFinite(e) ? e : null;
1969
2131
  }
1970
- function ee(r, e, t) {
1971
- return Math.min(t, Math.max(e, r));
2132
+ function se(a, e, t) {
2133
+ return Math.min(t, Math.max(e, a));
1972
2134
  }
1973
- function x(r) {
1974
- return r instanceof Error ? { name: r.name, message: r.message } : { name: "ServiceError", message: String(r ?? "Service request failed") };
2135
+ function V(a) {
2136
+ return a instanceof Error ? { name: a.name, message: a.message } : { name: "ServiceError", message: String(a ?? "Service request failed") };
1975
2137
  }
1976
- function te(r, e) {
1977
- return r instanceof Error ? r : new Error(e);
2138
+ function re(a, e) {
2139
+ return a instanceof Error ? a : new Error(e);
1978
2140
  }
1979
- const be = "1.3.15";
2141
+ const De = "1.3.16";
1980
2142
  export {
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
2143
+ Z as AVATAR_TUNING_DEFAULTS,
2144
+ Se as BACKGROUND_PRESETS,
2145
+ ke as OVERLAY_EFFECTS,
2146
+ Ce as RtcClient,
2147
+ Ee as RtcIncomingClient,
2148
+ qe as SPEAKER_NOISE_FLOOR,
2149
+ Oe as SPEAKER_TAKEOVER_RATIO,
2150
+ Ue as createAvatarPipeline,
2151
+ je as createCallRecorder,
2152
+ Ne as createPictureInPictureController,
2153
+ Qe as createRtcClient,
2154
+ xe as createRtcIncomingClient,
2155
+ Ve as createVideoEffectsPipeline,
2156
+ be as drawAvatar,
2157
+ we as headPoseFromMatrix,
2158
+ le as neutralRig,
2159
+ oe as pickActiveSpeaker,
2160
+ Te as rigFromBlendshapes,
2161
+ K as scenePainters,
2162
+ X as smoothRig,
2163
+ ee as stylizedAvatarRenderer,
2164
+ Re as unlockRtcCallAudio,
2165
+ De as version
1996
2166
  };