@streaming-cdn/rtc-web 1.3.16 → 1.3.17

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.
@@ -14,7 +14,7 @@ function ce(a) {
14
14
  }
15
15
  return e;
16
16
  }
17
- const O = {
17
+ const N = {
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 },
@@ -36,41 +36,41 @@ function ue(a) {
36
36
  return !e || e === "none" ? "" : e === "cpu" || e === "bandwidth" ? e : "other";
37
37
  }
38
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;
39
+ const s = { ...he, ...n.thresholds }, o = ["low", "medium", "high"], r = n.ceiling && n.ceiling !== "audio" ? n.ceiling : "high", c = o.indexOf(r), l = o.indexOf(a), d = (n.samplesSeen ?? s.warmupSamples) + 1, u = d <= s.warmupSamples, S = ue(e.qualityLimitationReason), f = e.packetLossPct ?? 0, v = e.rttMs ?? 0, I = e.availableOutgoingBitrateBps, y = N[a].maxBitrate, k = f >= s.criticalLossPct || v >= s.criticalRttMs || S === "cpu", p = k || f >= s.poorLossPct || v >= s.poorRttMs || S === "bandwidth", C = I == null || I >= y * s.sustainRatio, P = f < s.goodLossPct && v < s.goodRttMs && !S && C, L = p ? t + 1 : 0, M = P ? i + 1 : 0, A = { quality: a, poorSamples: L, goodSamples: M, samplesSeen: d, changed: !1 };
40
+ return l > c ? { quality: o[c], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : u ? A : k && l > 0 ? { quality: o[l - 1], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : L >= s.poorSamplesToStepDown && l > 0 ? { quality: o[l - 1], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : M >= s.goodSamplesToStepUp && l < c ? { quality: o[l + 1], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : A;
41
41
  }
42
42
  function pe(a, e) {
43
43
  const t = a instanceof Map ? a : new Map(a);
44
44
  let i = 0, n = 0, s = null, o = null, r = null;
45
- for (const l of t.values()) {
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
- n += Number(l.packetsLost ?? 0);
49
- const y = Number(l.roundTripTime ?? NaN);
50
- Number.isFinite(y) && (o = y * 1e3);
45
+ for (const d of t.values()) {
46
+ const u = String(d.type ?? "");
47
+ if (u === "outbound-rtp" && String(d.kind ?? "") === "video" && (i += Number(d.packetsSent ?? 0), s = d.qualityLimitationReason ?? s), u === "remote-inbound-rtp" && String(d.kind ?? "") === "video") {
48
+ n += Number(d.packetsLost ?? 0);
49
+ const S = Number(d.roundTripTime ?? NaN);
50
+ Number.isFinite(S) && (o = S * 1e3);
51
51
  }
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);
52
+ if (u === "candidate-pair" && (d.nominated === !0 || String(d.state ?? "") === "succeeded")) {
53
+ const S = Number(d.currentRoundTripTime ?? NaN);
54
+ o == null && Number.isFinite(S) && (o = S * 1e3);
55
+ const f = Number(d.availableOutgoingBitrate ?? NaN);
56
56
  Number.isFinite(f) && (r = f);
57
57
  }
58
58
  }
59
59
  const c = { packetsSent: i, packetsLost: n, timestamp: Date.now() };
60
- let d = null;
60
+ let l = null;
61
61
  if (e) {
62
- const l = i - e.packetsSent, u = n - e.packetsLost;
63
- l > 0 && u >= 0 && (d = u / (l + u) * 100);
62
+ const d = i - e.packetsSent, u = n - e.packetsLost;
63
+ d > 0 && u >= 0 && (l = u / (d + u) * 100);
64
64
  }
65
65
  return {
66
- sample: { packetLossPct: d, rttMs: o, availableOutgoingBitrateBps: r, qualityLimitationReason: s },
66
+ sample: { packetLossPct: l, rttMs: o, availableOutgoingBitrateBps: r, qualityLimitationReason: s },
67
67
  counters: c
68
68
  };
69
69
  }
70
70
  const fe = {
71
71
  audio: { active: !1, maxBitrate: 0, maxFramerate: 0, scaleResolutionDownBy: 4 }
72
72
  }, ge = { active: !0, maxBitrate: 4e6, maxFramerate: 30, scaleResolutionDownBy: 1 };
73
- class x {
73
+ class Q {
74
74
  options;
75
75
  socket = null;
76
76
  localStream = null;
@@ -159,7 +159,7 @@ class x {
159
159
  return;
160
160
  }
161
161
  for (const r of this.peers.values()) {
162
- const c = r.connection.getSenders().find((d) => d.track?.kind === s);
162
+ const c = r.connection.getSenders().find((l) => l.track?.kind === s);
163
163
  c ? await c.replaceTrack(n) : r.connection.addTrack(n, this.localStream);
164
164
  }
165
165
  await this.applyVideoQuality();
@@ -168,7 +168,7 @@ class x {
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 = x.clampToCeiling(t.quality, e), t.poorSamples = 0, t.goodSamples = 0;
171
+ t.quality = Q.clampToCeiling(t.quality, e), t.poorSamples = 0, t.goodSamples = 0;
172
172
  await this.applyVideoQuality();
173
173
  }
174
174
  static clampToCeiling(e, t) {
@@ -214,26 +214,26 @@ class x {
214
214
  async openSocket(e) {
215
215
  const { credential: t } = this.options, i = new URL(t.signalingUrl, globalThis.location?.href);
216
216
  i.protocol = i.protocol === "https:" ? "wss:" : "ws:";
217
- const n = new Promise((c, d) => {
218
- this.resolveJoin = c, this.rejectJoin = d;
217
+ const n = new Promise((c, l) => {
218
+ this.resolveJoin = c, this.rejectJoin = l;
219
219
  }), s = new WebSocket(i, ["rtc-client", t.signalingToken]), o = ++this.socketGeneration;
220
220
  this.socket = s;
221
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
- const d = String(c.data);
225
+ const l = String(c.data);
226
226
  this.signalQueue = this.signalQueue.then(async () => {
227
- this.socket !== s || this.socketGeneration !== o || await this.handleSignal(d);
228
- }).catch((l) => {
229
- const u = l instanceof Error ? l.message : "RTC signaling processing failed";
227
+ this.socket !== s || this.socketGeneration !== o || await this.handleSignal(l);
228
+ }).catch((d) => {
229
+ const u = d instanceof Error ? d.message : "RTC signaling processing failed";
230
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;
234
234
  this.socket = null, this.stopHeartbeat(), this.stopQualitySampling(), !this.joined && !e && this.rejectJoin?.(new Error(c.reason || "RTC signaling connection closed"));
235
- const d = !this.stopped && (this.joined || e);
236
- this.joined = !1, d ? (this.resetPeers(), this.options.onEvent("reconnecting", { reason: c.reason, code: c.code, attempt: this.reconnectAttempt + 1 }), this.scheduleReconnect()) : this.stopped || this.options.onEvent("disconnected", { reason: c.reason, code: c.code });
235
+ const l = !this.stopped && (this.joined || e);
236
+ this.joined = !1, l ? (this.resetPeers(), this.options.onEvent("reconnecting", { reason: c.reason, code: c.code, attempt: this.reconnectAttempt + 1 }), this.scheduleReconnect()) : this.stopped || this.options.onEvent("disconnected", { reason: c.reason, code: c.code });
237
237
  });
238
238
  try {
239
239
  await n, this.joined = !0, this.options.onEvent("connected", { participantId: t.participantId, resumed: e });
@@ -313,7 +313,7 @@ class x {
313
313
  makingOffer: !1,
314
314
  offerTask: null,
315
315
  activeNegotiationId: null,
316
- quality: x.startingQuality(this.quality),
316
+ quality: Q.startingQuality(this.quality),
317
317
  poorSamples: 0,
318
318
  goodSamples: 0,
319
319
  samplesSeen: 0,
@@ -325,7 +325,7 @@ class x {
325
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
- n.getTracks().some((d) => d.id === c.track.id) || n.addTrack(c.track), this.options.onEvent("remotestream", { participant: e, stream: n, track: c.track });
328
+ n.getTracks().some((l) => l.id === c.track.id) || n.addTrack(c.track), this.options.onEvent("remotestream", { participant: e, stream: n, track: c.track });
329
329
  }), i.addEventListener("connectionstatechange", () => {
330
330
  ["failed", "closed"].includes(i.connectionState) && this.removePeer(e.participantId), this.options.onEvent("peerconnectionstate", { participant: e, state: i.connectionState });
331
331
  }), s;
@@ -351,7 +351,7 @@ class x {
351
351
  });
352
352
  if (e.connection.signalingState !== "stable") return;
353
353
  await e.connection.setLocalDescription(t);
354
- const i = W();
354
+ const i = _();
355
355
  e.activeNegotiationId = i, this.send({
356
356
  type: "rtc.offer",
357
357
  targetParticipantId: e.identity.participantId,
@@ -391,7 +391,7 @@ class x {
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 ? ge : this.quality === "audio" ? fe.audio : O[e.quality], o = i.getParameters(), r = o.encodings?.length ? o.encodings : [{}];
394
+ const n = !!(t && i.track?.id === t), s = n ? ge : this.quality === "audio" ? fe.audio : N[e.quality], o = i.getParameters(), r = o.encodings?.length ? o.encodings : [{}];
395
395
  o.encodings = r.map((c) => ({ ...c, ...s })), o.degradationPreference = n ? "maintain-resolution" : "maintain-framerate", await i.setParameters(o);
396
396
  }
397
397
  }
@@ -487,7 +487,7 @@ class x {
487
487
  }
488
488
  send(e) {
489
489
  this.socket?.readyState === WebSocket.OPEN && this.socket.send(JSON.stringify({
490
- clientMessageId: e.clientMessageId ?? W(),
490
+ clientMessageId: e.clientMessageId ?? _(),
491
491
  ...e
492
492
  }));
493
493
  }
@@ -495,13 +495,13 @@ class x {
495
495
  for (const t of e?.getTracks() ?? []) t.stop();
496
496
  }
497
497
  }
498
- function W() {
498
+ function _() {
499
499
  return globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
500
500
  }
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 }
501
+ const z = { active: !0, maxBitrate: 4e6, maxFramerate: 30, scaleResolutionDownBy: 1 }, Y = [
502
+ { rid: "a", maxBitrate: N.high.maxBitrate, maxFramerate: N.high.maxFramerate },
503
+ { rid: "b", maxBitrate: N.medium.maxBitrate, maxFramerate: N.medium.maxFramerate, scaleResolutionDownBy: 2 },
504
+ { rid: "c", maxBitrate: N.low.maxBitrate, maxFramerate: N.low.maxFramerate, scaleResolutionDownBy: 4 }
505
505
  ], G = { high: "a", medium: "b", low: "c" };
506
506
  class ye {
507
507
  options;
@@ -638,26 +638,26 @@ class ye {
638
638
  async openSocket(e) {
639
639
  const { credential: t } = this.options, i = new URL(t.signalingUrl, globalThis.location?.href);
640
640
  i.protocol = i.protocol === "https:" ? "wss:" : "ws:";
641
- const n = new Promise((c, d) => {
642
- this.resolveJoin = c, this.rejectJoin = d;
641
+ const n = new Promise((c, l) => {
642
+ this.resolveJoin = c, this.rejectJoin = l;
643
643
  }), s = new WebSocket(i, ["rtc-client", t.signalingToken]), o = ++this.socketGeneration;
644
644
  this.socket = s;
645
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
- const d = String(c.data);
649
+ const l = String(c.data);
650
650
  this.signalQueue = this.signalQueue.then(async () => {
651
- this.socket !== s || this.socketGeneration !== o || await this.handleSignal(d);
652
- }).catch((l) => {
653
- const u = l instanceof Error ? l.message : "RTC signaling processing failed";
651
+ this.socket !== s || this.socketGeneration !== o || await this.handleSignal(l);
652
+ }).catch((d) => {
653
+ const u = d instanceof Error ? d.message : "RTC signaling processing failed";
654
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;
658
658
  this.socket = null, this.stopHeartbeat(), !this.joined && !e && this.rejectJoin?.(new Error(c.reason || "RTC signaling connection closed"));
659
- const d = !this.stopped && (this.joined || e);
660
- this.joined = !1, d ? (this.options.onEvent("reconnecting", { reason: c.reason, code: c.code, attempt: this.reconnectAttempt + 1 }), this.scheduleReconnect()) : this.stopped || this.options.onEvent("disconnected", { reason: c.reason, code: c.code });
659
+ const l = !this.stopped && (this.joined || e);
660
+ this.joined = !1, l ? (this.options.onEvent("reconnecting", { reason: c.reason, code: c.code, attempt: this.reconnectAttempt + 1 }), this.scheduleReconnect()) : this.stopped || this.options.onEvent("disconnected", { reason: c.reason, code: c.code });
661
661
  });
662
662
  try {
663
663
  await n, this.joined = !0, this.options.onEvent("connected", { participantId: t.participantId, resumed: e });
@@ -833,12 +833,12 @@ class ye {
833
833
  const o = this.quality === "audio" ? null : G[this.quality];
834
834
  n.encodings = s.map((r) => {
835
835
  if (i)
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 };
836
+ return { ...r, active: r.rid === "a", ...r.rid === "a" ? { maxBitrate: z.maxBitrate, maxFramerate: z.maxFramerate } : {} };
837
+ const c = Y.find((d) => d.rid === r.rid), l = o != null && String(r.rid ?? "") >= o;
838
+ return { ...r, ...c ?? {}, active: l };
839
839
  });
840
840
  } else {
841
- const o = this.quality === "audio" ? O.audio : O[this.quality], r = i ? $ : o;
841
+ const o = this.quality === "audio" ? N.audio : N[this.quality], r = i ? z : o;
842
842
  n.encodings = s.map((c) => ({ ...c, ...r }));
843
843
  }
844
844
  n.degradationPreference = i ? "maintain-resolution" : "maintain-framerate", await e.setParameters(n);
@@ -945,7 +945,7 @@ function Ne(a, e = {}) {
945
945
  }
946
946
  function o(r) {
947
947
  const c = a.getRemoteStreams();
948
- return r ? c.find((d) => d.participant.participantId === r)?.stream ?? null : c[0]?.stream ?? a.getLocalStream();
948
+ return r ? c.find((l) => l.participant.participantId === r)?.stream ?? null : c[0]?.stream ?? a.getLocalStream();
949
949
  }
950
950
  return {
951
951
  supported: i,
@@ -953,9 +953,9 @@ function Ne(a, e = {}) {
953
953
  if (!i) throw new Error("This browser does not support picture-in-picture");
954
954
  const c = o(r);
955
955
  if (!c) throw new Error("No video stream is available for picture-in-picture");
956
- const d = s();
957
- d.srcObject !== c && (d.srcObject = c), await d.play().catch(() => {
958
- }), await d.requestPictureInPicture();
956
+ const l = s();
957
+ l.srcObject !== c && (l.srcObject = c), await l.play().catch(() => {
958
+ }), await l.requestPictureInPicture();
959
959
  },
960
960
  async exit() {
961
961
  t.pictureInPictureElement && typeof t.exitPictureInPicture == "function" && await t.exitPictureInPicture();
@@ -967,89 +967,89 @@ function Ne(a, e = {}) {
967
967
  }
968
968
  function je(a, e) {
969
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,
970
+ let c = null, l = null, d = null, u = null, S = 0, f = [], v = !1;
971
+ async function I(y, k, p, C = "application/json") {
972
+ const P = await i(`${n}${k}`, {
973
+ method: y,
974
974
  headers: {
975
975
  authorization: `Bearer ${e.credential.signalingToken}`,
976
- "content-type": b
976
+ "content-type": C
977
977
  },
978
- body: k === void 0 ? void 0 : b === "application/json" ? JSON.stringify(k) : k
978
+ body: p === void 0 ? void 0 : C === "application/json" ? JSON.stringify(p) : p
979
979
  });
980
- if (!M.ok) throw new Error(`Recording request failed with HTTP ${M.status}`);
981
- return M.json();
980
+ if (!P.ok) throw new Error(`Recording request failed with HTTP ${P.status}`);
981
+ return P.json();
982
982
  }
983
983
  return {
984
984
  get recording() {
985
- return w;
985
+ return v;
986
986
  },
987
987
  async start() {
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;
988
+ if (v) return;
989
+ u = (await I("POST", "/v1/rtc/recordings")).recordingId;
990
+ const k = t.createElement("canvas");
991
+ k.width = r, k.height = o;
992
+ const p = k.getContext("2d"), C = /* @__PURE__ */ new Map(), P = (T, R) => {
993
+ let b = C.get(T);
994
+ return b || (b = t.createElement("video"), b.muted = !0, b.playsInline = !0, b.srcObject = R, b.play().catch(() => {
995
+ }), C.set(T, b)), b;
996
996
  };
997
- d = setInterval(() => {
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
- ...P ? [{ key: "local", stream: P, label: "me" }] : []
997
+ l = setInterval(() => {
998
+ const T = a.getRemoteStreams(), R = a.getLocalStream(), b = [
999
+ ...T.map((j) => ({ key: j.participant.participantId, stream: j.stream, label: j.participant.displayName })),
1000
+ ...R ? [{ key: "local", stream: R, label: "me" }] : []
1001
1001
  ];
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);
1002
+ p.fillStyle = "#101418", p.fillRect(0, 0, r, o);
1003
+ const O = Math.max(1, Math.ceil(Math.sqrt(b.length))), g = Math.max(1, Math.ceil(b.length / O)), q = r / O, x = o / g;
1004
+ b.forEach((j, J) => {
1005
+ const W = P(j.key, j.stream), B = J % O * q, F = Math.floor(J / O) * x;
1006
+ W.videoWidth > 0 && p.drawImage(W, B + 2, F + 2, q - 4, x - 4), p.fillStyle = "rgba(0,0,0,.6)", p.fillRect(B + 8, F + x - 30, Math.min(q - 16, 12 + j.label.length * 9), 22), p.fillStyle = "#fff", p.font = "14px system-ui", p.fillText(j.label, B + 14, F + x - 14);
1007
1007
  });
1008
1008
  }, 66);
1009
- const I = T.captureStream(15);
1010
- l = new AudioContext();
1011
- const g = l.createMediaStreamDestination(), p = /* @__PURE__ */ new Set(), h = () => {
1012
- const E = [
1013
- ...a.getRemoteStreams().map((P) => P.stream),
1009
+ const L = k.captureStream(15);
1010
+ d = new AudioContext();
1011
+ const M = d.createMediaStreamDestination(), A = /* @__PURE__ */ new Set(), w = () => {
1012
+ const T = [
1013
+ ...a.getRemoteStreams().map((R) => R.stream),
1014
1014
  ...a.getLocalStream() ? [a.getLocalStream()] : []
1015
1015
  ];
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));
1016
+ for (const R of T)
1017
+ for (const b of R.getAudioTracks())
1018
+ A.has(b.id) || (A.add(b.id), d.createMediaStreamSource(new MediaStream([b])).connect(M));
1019
1019
  };
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;
1020
+ w();
1021
+ const E = setInterval(w, 1e3), m = () => clearInterval(E);
1022
+ for (const T of M.stream.getAudioTracks()) L.addTrack(T);
1023
+ c = (e.mediaRecorderFactory ?? ((T, R) => new MediaRecorder(T, R)))(L, { mimeType: s }), f = [], c.addEventListener("dataavailable", (T) => {
1024
+ T.data && T.data.size > 0 && f.push(T.data);
1025
+ }), c.addEventListener("stop", m), c.start(1e3), S = Date.now(), v = !0;
1026
1026
  },
1027
1027
  async stop() {
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
- }), l = null;
1033
- const k = new Blob(f, { type: s });
1028
+ if (!v || !c || !u) throw new Error("The recorder is not running");
1029
+ v = !1;
1030
+ const y = c, k = new Promise((M) => y.addEventListener("stop", () => M(), { once: !0 }));
1031
+ y.stop(), await k, l && clearInterval(l), l = null, await d?.close().catch(() => {
1032
+ }), d = null;
1033
+ const p = new Blob(f, { type: s });
1034
1034
  f = [];
1035
- const b = Math.max(1, Math.round((Date.now() - y) / 1e3)), M = await m(
1035
+ const C = Math.max(1, Math.round((Date.now() - S) / 1e3)), P = await I(
1036
1036
  "PUT",
1037
1037
  `/v1/rtc/recordings/${encodeURIComponent(u)}/media`,
1038
- k,
1038
+ p,
1039
1039
  s
1040
1040
  );
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;
1041
+ await I("POST", `/v1/rtc/recordings/${encodeURIComponent(u)}/complete`, { durationSeconds: C });
1042
+ const L = { recordingId: u, sizeBytes: P.sizeBytes, durationSeconds: C };
1043
+ return u = null, c = null, L;
1044
1044
  },
1045
1045
  dispose() {
1046
- d && clearInterval(d), d = null;
1046
+ l && clearInterval(l), l = null;
1047
1047
  try {
1048
1048
  c?.stop();
1049
1049
  } catch {
1050
1050
  }
1051
- c = null, l?.close().catch(() => {
1052
- }), l = null, w = !1;
1051
+ c = null, d?.close().catch(() => {
1052
+ }), d = null, v = !1;
1053
1053
  }
1054
1054
  };
1055
1055
  }
@@ -1091,17 +1091,19 @@ const Se = ["none", "blur", "aurora", "cybergrid", "bokeh", "sunset", "image"],
1091
1091
  }
1092
1092
  };
1093
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(() => {
1094
+ const t = e.document ?? globalThis.document;
1095
+ let i = e.width ?? 1280, n = e.height ?? 720;
1096
+ const s = !!(e.width || e.height), o = e.frameRate ?? 24, r = a instanceof MediaStreamTrack ? a : a.getVideoTracks()[0];
1097
+ if (!r) throw new Error("A video track is required");
1098
+ let c = e.background ?? "none", l = e.overlay ?? "none", d = e.backgroundImage ?? null, u = e.segmenter ?? null, S = null, f = !1;
1099
+ const v = t.createElement("video");
1100
+ v.muted = !0, v.playsInline = !0, v.srcObject = new MediaStream([r]), v.play().catch(() => {
1099
1101
  });
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) => ({
1102
+ const I = t.createElement("canvas");
1103
+ I.width = i, I.height = n;
1104
+ const y = I.getContext("2d"), k = t.createElement("canvas");
1105
+ k.width = i, k.height = n;
1106
+ const p = k.getContext("2d"), C = () => Array.from({ length: 80 }, (m, h) => ({
1105
1107
  x: (Math.sin(h * 12.9898) * 0.5 + 0.5) * i,
1106
1108
  y: (Math.sin(h * 78.233) * 0.5 + 0.5) * n,
1107
1109
  speed: 0.6 + h % 5 * 0.5,
@@ -1109,48 +1111,57 @@ function Ve(a, e = {}) {
1109
1111
  size: 2 + h % 4,
1110
1112
  hue: h * 47 % 360
1111
1113
  }));
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);
1114
+ let P = C();
1115
+ const L = () => {
1116
+ if (s) return;
1117
+ const m = v.videoWidth, h = v.videoHeight;
1118
+ if (!m || !h) return;
1119
+ const T = Math.min(1, 1280 / Math.max(m, h)), R = Math.round(m * T), b = Math.round(h * T);
1120
+ R === i && b === n || (i = R, n = b, I.width = i, I.height = n, k.width = i, k.height = n, P = C());
1121
+ };
1122
+ v.addEventListener?.("loadedmetadata", L), v.addEventListener?.("resize", L);
1123
+ function M() {
1124
+ if (S) {
1125
+ p.clearRect(0, 0, i, n), p.drawImage(S, 0, 0, i, n), p.globalCompositeOperation = "source-in", p.drawImage(v, 0, 0, i, n), p.globalCompositeOperation = "source-over", y.drawImage(k, 0, 0);
1115
1126
  return;
1116
1127
  }
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
- }
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
- else if (c === "vignette") {
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);
1128
+ const m = i * 0.42, h = m * 9 / 16, T = i - m - 24, R = n - h - 24;
1129
+ y.save(), y.shadowColor = "rgba(0,0,0,.5)", y.shadowBlur = 24, y.beginPath(), y.roundRect(T, R, m, h, 14), y.clip(), y.drawImage(v, T, R, m, h), y.restore();
1130
+ }
1131
+ function A(m) {
1132
+ if (c === "none" ? y.drawImage(v, 0, 0, i, n) : c === "blur" ? (y.filter = "blur(14px)", y.drawImage(v, -16, -16, i + 32, n + 32), y.filter = "none", S && M()) : c === "image" && d ? (y.drawImage(d, 0, 0, i, n), M()) : ((K[c] ?? K.aurora)(y, i, n, m), M()), l === "snow" || l === "confetti")
1133
+ for (const h of P)
1134
+ h.y += h.speed * (l === "confetti" ? 1.6 : 1), h.x += h.drift, h.y > n && (h.y = -6, h.x = Math.random() * i), y.fillStyle = l === "snow" ? "rgba(255,255,255,.85)" : `hsl(${h.hue}, 90%, 60%)`, l === "confetti" ? y.fillRect(h.x, h.y, h.size + 2, h.size) : (y.beginPath(), y.arc(h.x, h.y, h.size / 2, 0, Math.PI * 2), y.fill());
1135
+ else if (l === "vignette") {
1136
+ const h = y.createRadialGradient(i / 2, n / 2, n * 0.4, i / 2, n / 2, n * 0.85);
1137
+ h.addColorStop(0, "rgba(0,0,0,0)"), h.addColorStop(1, "rgba(0,0,0,0.55)"), y.fillStyle = h, y.fillRect(0, 0, i, n);
1127
1138
  }
1128
1139
  }
1129
- const I = setInterval(() => {
1130
- M(Date.now()), l && !y && r !== "none" && (y = !0, l.segment(f).then((p) => {
1131
- u = p;
1140
+ const w = setInterval(() => {
1141
+ A(Date.now()), u && !f && c !== "none" && (f = !0, u.segment(v).then((m) => {
1142
+ S = m;
1132
1143
  }).catch(() => {
1133
- u = null;
1144
+ S = null;
1134
1145
  }).finally(() => {
1135
- y = !1;
1146
+ f = !1;
1136
1147
  }));
1137
- }, Math.round(1e3 / s)), g = w.captureStream(s);
1148
+ }, Math.round(1e3 / o)), E = I.captureStream(o);
1138
1149
  return {
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);
1150
+ track: E.getVideoTracks()[0],
1151
+ stream: E,
1152
+ setBackground(m, h) {
1153
+ c = Se.includes(m) ? m : "none", h !== void 0 && (d = h), c === "none" && (S = null);
1143
1154
  },
1144
- setOverlay(p) {
1145
- c = ke.includes(p) ? p : "none";
1155
+ setOverlay(m) {
1156
+ l = ke.includes(m) ? m : "none";
1146
1157
  },
1147
- setSegmenter(p) {
1148
- l = p, p || (u = null);
1158
+ setSegmenter(m) {
1159
+ u = m, m || (S = null);
1149
1160
  },
1150
1161
  dispose() {
1151
- clearInterval(I), l?.close?.();
1152
- for (const p of g.getTracks()) p.stop();
1153
- f.srcObject = null;
1162
+ clearInterval(w), u?.close?.();
1163
+ for (const m of E.getTracks()) m.stop();
1164
+ v.srcObject = null;
1154
1165
  }
1155
1166
  };
1156
1167
  }
@@ -1169,7 +1180,7 @@ function le() {
1169
1180
  tracked: !1
1170
1181
  };
1171
1182
  }
1172
- function A(a, e) {
1183
+ function D(a, e) {
1173
1184
  const t = a.find((i) => i.categoryName === e);
1174
1185
  return t ? Math.max(0, Math.min(1, t.score)) : 0;
1175
1186
  }
@@ -1181,13 +1192,13 @@ function we(a) {
1181
1192
  }
1182
1193
  function Te(a, e, t = 1) {
1183
1194
  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;
1195
+ const i = we(e), n = (D(a, "eyeLookOutRight") + D(a, "eyeLookInLeft")) / 2, s = (D(a, "eyeLookOutLeft") + D(a, "eyeLookInRight")) / 2, o = (D(a, "eyeLookUpLeft") + D(a, "eyeLookUpRight")) / 2, r = (D(a, "eyeLookDownLeft") + D(a, "eyeLookDownRight")) / 2, c = (D(a, "mouthSmileLeft") + D(a, "mouthSmileRight")) / 2, l = (D(a, "mouthFrownLeft") + D(a, "mouthFrownRight")) / 2, d = D(a, "eyeBlinkLeft"), u = D(a, "eyeBlinkRight"), S = Math.min(1, Math.abs(i.yaw) / 0.35) * Math.max(0, Math.min(1, t)), f = (d + u) / 2;
1185
1196
  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,
1197
+ blinkLeft: d + (f - d) * S,
1198
+ blinkRight: u + (f - u) * S,
1199
+ jawOpen: D(a, "jawOpen"),
1200
+ smile: c - l,
1201
+ browUp: (D(a, "browInnerUp") + D(a, "browOuterUpLeft") + D(a, "browOuterUpRight")) / 3,
1191
1202
  pupilX: n - s,
1192
1203
  pupilY: r - o,
1193
1204
  headYaw: i.yaw,
@@ -1216,30 +1227,30 @@ function be(a, e, t, i, n) {
1216
1227
  n || (a.fillStyle = "#101822", a.fillRect(0, 0, t, i));
1217
1228
  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
1229
  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;
1230
+ const c = Math.max(-1.35, Math.min(1.35, e.headYaw)), l = Math.max(-0.9, Math.min(0.9, e.headPitch)), d = Math.sin(c), u = (A) => Math.sin(A + c) * r, S = (A) => Math.cos(A + c), f = Math.sin(l) * r * 0.22;
1231
+ a.fillStyle = "#3a2a1c", a.beginPath(), a.ellipse(-d * 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(d) * 0.12), r * 1.12, 0, 0, Math.PI * 2), a.fill(), a.fillStyle = "#3a2a1c", a.beginPath(), a.ellipse(-d * r * 0.28, -r * 0.72 + f * 0.4, r * 0.92, r * 0.5, 0, Math.PI, Math.PI * 2), a.fill();
1232
+ const v = 0;
1222
1233
  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,
1234
+ const I = u(v) * 0.9, y = r * 0.12 + f;
1235
+ a.ellipse(I + d * r * 0.14, y, r * 0.11, r * 0.14, 0, 0, Math.PI * 2), a.fill();
1236
+ for (const A of [-1, 1]) {
1237
+ const w = A * 0.42, E = S(w);
1238
+ if (E <= 0.12) continue;
1239
+ const m = u(w) * 0.82, h = Math.max(0.2, E), T = A < 0 ? e.blinkLeft : e.blinkRight, R = Math.max(0.06, 1 - T), b = e.browUp * r * 0.14;
1240
+ a.strokeStyle = "#4a2e18", a.lineWidth = r * 0.07, a.lineCap = "round", a.beginPath(), a.moveTo(m - r * 0.2 * h, -r * 0.42 - b + f), a.quadraticCurveTo(m, -r * 0.52 - b + f, m + r * 0.2 * h, -r * 0.44 - b + f), a.stroke();
1241
+ const O = -r * 0.18 + f;
1242
+ a.fillStyle = "#ffffff", a.beginPath(), a.ellipse(m, O, r * 0.16 * h, r * 0.12 * R, 0, 0, Math.PI * 2), a.fill(), a.fillStyle = "#22303c", a.beginPath(), a.ellipse(
1243
+ m + e.pupilX * r * 0.07 * h,
1244
+ O + e.pupilY * r * 0.05,
1245
+ r * 0.06 * h,
1246
+ r * 0.06 * R,
1236
1247
  0,
1237
1248
  0,
1238
1249
  Math.PI * 2
1239
1250
  ), a.fill();
1240
1251
  }
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");
1252
+ const k = Math.max(0.25, S(0)), p = u(0) * 0.7, C = r * 0.55 * k, P = r * (0.04 + e.jawOpen * 0.34), L = e.smile * r * 0.12, M = r * 0.42 + f;
1253
+ a.fillStyle = "#8c2f2f", a.beginPath(), a.moveTo(p - C / 2, M - L), a.quadraticCurveTo(p, M + P, p + C / 2, M - L), a.quadraticCurveTo(p, M - P * 0.25, p - C / 2, M - L), 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
1254
  }
1244
1255
  const Z = {
1245
1256
  mouthGain: 1.7,
@@ -1257,62 +1268,71 @@ function ee() {
1257
1268
  }
1258
1269
  };
1259
1270
  }
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(() => {
1271
+ const $ = (a) => Math.max(0, Math.min(1, a));
1272
+ function xe(a, e = {}) {
1273
+ const t = e.document ?? globalThis.document;
1274
+ let i = e.width ?? 1280, n = e.height ?? 720;
1275
+ const s = !!(e.width || e.height), o = e.frameRate ?? 24, r = a instanceof MediaStreamTrack ? a : a.getVideoTracks()[0];
1276
+ if (!r) throw new Error("A video track is required");
1277
+ let c = e.tracker ?? null, l = e.renderer ?? ee(), d = e.mode ?? "replace";
1278
+ const u = { ...Z, ...e.tuning }, S = e.backdrop ?? "#101822", f = t.createElement("video");
1279
+ f.muted = !0, f.playsInline = !0, f.srcObject = new MediaStream([r]), f.play().catch(() => {
1267
1280
  });
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;
1281
+ const v = t.createElement("canvas");
1282
+ v.width = i, v.height = n;
1283
+ const I = v.getContext("2d"), y = () => {
1284
+ if (s) return;
1285
+ const w = f.videoWidth, E = f.videoHeight;
1286
+ if (!w || !E) return;
1287
+ const m = Math.min(1, 1280 / Math.max(w, E)), h = Math.round(w * m), T = Math.round(E * m);
1288
+ (!(h === i || T === n) || h !== i || T !== n) && (i = h, n = T, v.width = i, v.height = n);
1289
+ };
1290
+ f.addEventListener?.("loadedmetadata", y), f.addEventListener?.("resize", y);
1291
+ let k = le(), p = null, C = 0;
1292
+ function P(w) {
1293
+ if (w.length <= 454) return;
1294
+ const E = w[10], m = w[152], h = w[234], T = w[454], R = (h.x + T.x) / 2 * i, b = (h.y + T.y) / 2 * n, O = Math.hypot((m.x - E.x) * i, (m.y - E.y) * n), g = Math.max(0.6, Math.cos(k.headPitch)), q = { x: R, y: b, radius: Math.max(24, O / g * 0.8) };
1295
+ p = p ? { x: p.x + (q.x - p.x) * 0.4, y: p.y + (q.y - p.y) * 0.4, radius: p.radius + (q.radius - p.radius) * 0.15 } : q;
1296
+ }
1297
+ function L(w) {
1298
+ if (c && f.readyState >= 2) {
1299
+ let m = null;
1280
1300
  try {
1281
- h = r.detect(y, g);
1301
+ m = c.detect(f, w);
1282
1302
  } catch {
1283
1303
  }
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));
1304
+ const h = Te(m?.categories ?? null, m?.matrix ?? null, u.eyeSync);
1305
+ h.jawOpen = $(h.jawOpen * u.mouthGain), h.blinkLeft = $(h.blinkLeft * u.blinkGain), h.blinkRight = $(h.blinkRight * u.blinkGain), h.tracked ? (C = w, k = X(k, h, u.smoothing), m?.landmarks && P(m.landmarks)) : k.tracked && w - C > u.lostHoldMs && (k = X(k, { ...k, jawOpen: 0, browUp: 0, smile: k.smile * 0.5, blinkLeft: 0.1, blinkRight: 0.1 }, 0.05));
1286
1306
  }
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);
1307
+ d === "overlay" && f.readyState >= 2 ? I.drawImage(f, 0, 0, i, n) : (I.fillStyle = S, I.fillRect(0, 0, i, n));
1308
+ const E = d === "overlay" && p ? { x: p.x, y: p.y + u.avatarLift * p.radius, radius: p.radius * u.avatarScale } : null;
1309
+ l?.render(I, k, i, n, E);
1290
1310
  }
1291
- const M = setInterval(() => b(Date.now()), Math.round(1e3 / s)), I = f.captureStream(s);
1311
+ const M = setInterval(() => L(Date.now()), Math.round(1e3 / o)), A = v.captureStream(o);
1292
1312
  return {
1293
- track: I.getVideoTracks()[0],
1294
- stream: I,
1295
- getRig: () => ({ ...m }),
1296
- setMode(g) {
1297
- d = g === "overlay" ? "overlay" : "replace";
1313
+ track: A.getVideoTracks()[0],
1314
+ stream: A,
1315
+ getRig: () => ({ ...k }),
1316
+ setMode(w) {
1317
+ d = w === "overlay" ? "overlay" : "replace";
1298
1318
  },
1299
- setTracker(g) {
1300
- r?.close?.(), r = g;
1319
+ setTracker(w) {
1320
+ c?.close?.(), c = w;
1301
1321
  },
1302
- setRenderer(g) {
1303
- c?.dispose?.(), c = g ?? ee();
1322
+ setRenderer(w) {
1323
+ l?.dispose?.(), l = w ?? ee();
1304
1324
  },
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);
1325
+ setTuning(w) {
1326
+ for (const E of Object.keys(Z)) {
1327
+ const m = w[E];
1328
+ typeof m == "number" && Number.isFinite(m) && (u[E] = m);
1309
1329
  }
1310
1330
  },
1311
- getTuning: () => ({ ...l }),
1331
+ getTuning: () => ({ ...u }),
1312
1332
  dispose() {
1313
- clearInterval(M), r?.close?.(), c?.dispose?.();
1314
- for (const g of I.getTracks()) g.stop();
1315
- y.srcObject = null;
1333
+ clearInterval(M), c?.close?.(), l?.dispose?.();
1334
+ for (const w of A.getTracks()) w.stop();
1335
+ f.srcObject = null;
1316
1336
  }
1317
1337
  };
1318
1338
  }
@@ -1350,7 +1370,7 @@ class Ce extends EventTarget {
1350
1370
  async initialize() {
1351
1371
  if (this.client) return this;
1352
1372
  try {
1353
- const t = (this.options.transport === "auto" ? this.mode === "meeting" ? "sfu" : "mesh" : this.options.transport ?? "mesh") === "sfu" ? ye : x;
1373
+ const t = (this.options.transport === "auto" ? this.mode === "meeting" ? "sfu" : "mesh" : this.options.transport ?? "mesh") === "sfu" ? ye : Q;
1354
1374
  return this.client = new t({
1355
1375
  credential: {
1356
1376
  signalingToken: this.options.credential.signalingToken,
@@ -1495,42 +1515,42 @@ class Ce extends EventTarget {
1495
1515
  let n = "unavailable";
1496
1516
  if (e.requestMedia !== !1 && navigator.mediaDevices?.getUserMedia)
1497
1517
  try {
1498
- (await navigator.mediaDevices.getUserMedia({ audio: this.options.audio, video: this.options.video })).getTracks().forEach((y) => y.stop()), n = "granted";
1518
+ (await navigator.mediaDevices.getUserMedia({ audio: this.options.audio, video: this.options.video })).getTracks().forEach((S) => S.stop()), n = "granted";
1499
1519
  } catch {
1500
1520
  n = "denied", t.push("media_permission_denied");
1501
1521
  }
1502
1522
  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
1523
  this.options.audio && o === 0 && t.push("microphone_unavailable"), this.options.video && r === 0 && t.push("camera_unavailable");
1504
1524
  const c = e.probeUrl ?? this.options.preflightProbeUrl;
1505
- let d = null;
1525
+ let l = null;
1506
1526
  if (c) {
1507
1527
  const u = performance.now();
1508
1528
  try {
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");
1529
+ const S = await fetch(c, { method: "HEAD", cache: "no-store", credentials: "omit" });
1530
+ l = Math.round(performance.now() - u), S.ok || t.push("network_probe_failed");
1511
1531
  } catch {
1512
1532
  t.push("network_probe_failed");
1513
1533
  }
1514
1534
  }
1515
- const l = {
1535
+ const d = {
1516
1536
  passed: t.length === 0,
1517
1537
  sampledAt: (/* @__PURE__ */ new Date()).toISOString(),
1518
1538
  secureContext: i,
1519
1539
  mediaPermission: n,
1520
1540
  microphoneCount: o,
1521
1541
  cameraCount: r,
1522
- probeLatencyMs: d,
1542
+ probeLatencyMs: l,
1523
1543
  effectiveConnectionType: ae()?.effectiveType ?? null,
1524
1544
  issues: t
1525
1545
  };
1526
- return this.emit("preflight", l), this.options.autoReportStats && await this.reportQuality({
1546
+ return this.emit("preflight", d), this.options.autoReportStats && await this.reportQuality({
1527
1547
  sampleType: "preflight",
1528
- sampledAt: l.sampledAt,
1529
- connectionState: l.passed ? "ready" : "failed",
1530
- rttMs: l.probeLatencyMs,
1531
- effectiveConnectionType: l.effectiveConnectionType
1548
+ sampledAt: d.sampledAt,
1549
+ connectionState: d.passed ? "ready" : "failed",
1550
+ rttMs: d.probeLatencyMs,
1551
+ effectiveConnectionType: d.effectiveConnectionType
1532
1552
  }).catch(() => {
1533
- }), l;
1553
+ }), d;
1534
1554
  }
1535
1555
  async collectQualitySample(e = "runtime") {
1536
1556
  const t = this.options.statsProvider ? await this.options.statsProvider() : {}, i = this.peerConnection ? await Pe(this.peerConnection, this.previousCounters) : null;
@@ -1649,14 +1669,14 @@ class Ce extends EventTarget {
1649
1669
  this.dispatchEvent(new CustomEvent(e, { detail: i })), this.options.onEvent?.(i);
1650
1670
  }
1651
1671
  }
1652
- async function Qe(a) {
1672
+ async function Ue(a) {
1653
1673
  return new Ce(a).initialize();
1654
1674
  }
1655
- let Q = null;
1675
+ let U = null;
1656
1676
  function de() {
1657
- if (Q) return Q;
1677
+ if (U) return U;
1658
1678
  const a = globalThis, e = a.AudioContext ?? a.webkitAudioContext;
1659
- return e ? (Q = new e(), Q) : null;
1679
+ return e ? (U = new e(), U) : null;
1660
1680
  }
1661
1681
  async function Re() {
1662
1682
  const a = de();
@@ -1710,7 +1730,7 @@ class Ie {
1710
1730
  }
1711
1731
  }
1712
1732
  }
1713
- class Ee extends EventTarget {
1733
+ class Me extends EventTarget {
1714
1734
  options;
1715
1735
  socket = null;
1716
1736
  stopped = !1;
@@ -1830,7 +1850,7 @@ class Ee extends EventTarget {
1830
1850
  /** Applies a call state received through the application's own push or signaling channel. */
1831
1851
  handleCallUpdate(e) {
1832
1852
  const t = e.id === this.currentCall?.id || e.id === this.outgoingCallId;
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);
1853
+ 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, Ee(e.status)), ["rejected", "busy", "cancelled", "ended", "failed", "missed"].includes(e.status) && this.releaseMedia(e.id), this.emit("callupdated", e);
1834
1854
  }
1835
1855
  disconnect() {
1836
1856
  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();
@@ -1912,14 +1932,14 @@ class Ee extends EventTarget {
1912
1932
  if (!n) throw new Error("apiBaseUrl is required for call actions");
1913
1933
  const s = new URL(n, globalThis.location?.href), o = await this.resolveToken("initial"), r = new Headers(t.headers);
1914
1934
  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(() => ({}));
1935
+ const c = await fetch(new URL(e, s.origin), { ...t, headers: r }), l = await c.json().catch(() => ({}));
1916
1936
  if (c.status === 401 && this.options.tokenProvider && !i)
1917
1937
  return await this.resolveToken("unauthorized", !0), this.request(e, t, !0);
1918
1938
  if (!c.ok) {
1919
- const l = d.error;
1920
- throw new Error(typeof l == "string" ? l : l?.message || `RTC API failed with HTTP ${c.status}`);
1939
+ const d = l.error;
1940
+ throw new Error(typeof d == "string" ? d : d?.message || `RTC API failed with HTTP ${c.status}`);
1921
1941
  }
1922
- return d;
1942
+ return l;
1923
1943
  }
1924
1944
  renderIncoming(e) {
1925
1945
  if (!this.mount) return;
@@ -2035,8 +2055,8 @@ class Ee extends EventTarget {
2035
2055
  this.dispatchEvent(new CustomEvent(e, { detail: i })), this.options.onEvent?.(i);
2036
2056
  }
2037
2057
  }
2038
- function xe(a) {
2039
- const e = new Ee(a);
2058
+ function Qe(a) {
2059
+ const e = new Me(a);
2040
2060
  return a.autoConnect !== !1 && a.signalingUrl && e.connect(), e;
2041
2061
  }
2042
2062
  function te(a) {
@@ -2055,7 +2075,7 @@ function ie(a, e, t, i) {
2055
2075
  fontWeight: "700"
2056
2076
  }), n;
2057
2077
  }
2058
- function Me(a) {
2078
+ function Ee(a) {
2059
2079
  return {
2060
2080
  rejected: "Call declined",
2061
2081
  busy: "Line busy",
@@ -2074,46 +2094,46 @@ function ne(a) {
2074
2094
  }
2075
2095
  async function Pe(a, e) {
2076
2096
  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;
2097
+ let s = 0, o = 0, r = 0, c = 0, l = 0, d = 0, u = 0, S = 0, f = 0, v = 0, I = 0, y = 0, k = 0, p = null, C = null, P = null, L = null, M = null, A = null;
2098
+ t.forEach((g) => {
2099
+ n.set(g.id, g), g.type === "codec" && i.set(g.id, String(g.mimeType ?? ""));
2100
+ }), t.forEach((g) => {
2101
+ if (g.type === "inbound-rtp" && !g.isRemote && (s += Number(g.bytesReceived ?? 0), r += Math.max(0, Number(g.packetsLost ?? 0)), c += Math.max(0, Number(g.packetsReceived ?? 0)), Number.isFinite(g.jitter) && (l += Number(g.jitter), d += 1), u = Math.max(u, Number(g.framesPerSecond ?? 0)), S = Math.max(S, Number(g.frameWidth ?? 0)), f = Math.max(f, Number(g.frameHeight ?? 0)), v += Number(g.framesDropped ?? 0), I += Number(g.freezeCount ?? 0), y += Number(g.totalFreezesDuration ?? 0), k += Number(g.concealedSamples ?? 0), M ||= i.get(String(g.codecId ?? "")) ?? null), g.type === "outbound-rtp" && !g.isRemote && (o += Number(g.bytesSent ?? 0), A ||= g.qualityLimitationReason ? String(g.qualityLimitationReason) : null, M ||= i.get(String(g.codecId ?? "")) ?? null), g.type === "candidate-pair" && (g.selected || g.nominated) && g.state === "succeeded") {
2102
+ p = Number.isFinite(g.currentRoundTripTime) ? Number(g.currentRoundTripTime) : p, C = Number.isFinite(g.availableOutgoingBitrate) ? Number(g.availableOutgoingBitrate) : C;
2103
+ const q = n.get(g.localCandidateId);
2104
+ P = q?.candidateType ? String(q.candidateType) : P, L = q?.protocol ? String(q.protocol) : L;
2085
2105
  }
2086
2106
  });
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;
2107
+ const w = Date.now(), E = e ? Math.max(1e-3, (w - e.timestamp) / 1e3) : 0, m = e ? Math.max(0, Math.round((s - e.inboundBytes) * 8 / E)) : null, h = e ? Math.max(0, Math.round((o - e.outboundBytes) * 8 / E)) : null, T = r + c, R = e ? Math.max(0, r - e.packetsLost) : r, b = e ? Math.max(0, c - e.packetsReceived) : c, O = R + b;
2088
2108
  return {
2089
- counters: { timestamp: h, inboundBytes: s, outboundBytes: o, packetsLost: r, packetsReceived: c },
2109
+ counters: { timestamp: w, inboundBytes: s, outboundBytes: o, packetsLost: r, packetsReceived: c },
2090
2110
  sample: {
2091
- rttMs: k === null ? null : k * 1e3,
2092
- jitterMs: l ? d / l * 1e3 : null,
2093
- packetLossPct: D ? P / D * 100 : null,
2094
- packetLossCumulativePct: E ? r / E * 100 : null,
2111
+ rttMs: p === null ? null : p * 1e3,
2112
+ jitterMs: d ? l / d * 1e3 : null,
2113
+ packetLossPct: O ? R / O * 100 : null,
2114
+ packetLossCumulativePct: T ? r / T * 100 : null,
2095
2115
  packetsLost: r,
2096
2116
  packetsReceived: c,
2097
- inboundBitrateBps: L,
2098
- outboundBitrateBps: q,
2099
- availableOutgoingBitrateBps: b,
2117
+ inboundBitrateBps: m,
2118
+ outboundBitrateBps: h,
2119
+ availableOutgoingBitrateBps: C,
2100
2120
  framesPerSecond: u || null,
2101
- frameWidth: y || null,
2121
+ frameWidth: S || null,
2102
2122
  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
2123
+ framesDropped: v,
2124
+ freezeCount: I,
2125
+ freezeDurationMs: Math.round(y * 1e3),
2126
+ concealedSamples: k,
2127
+ codec: M,
2128
+ transportProtocol: L,
2129
+ candidateType: P,
2130
+ qualityLimitationReason: A
2111
2131
  }
2112
2132
  };
2113
2133
  }
2114
2134
  function Ae(a) {
2115
2135
  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();
2136
+ const t = H(a.packetLossPct) ?? 0, i = H(a.rttMs) ?? 0, n = H(a.jitterMs) ?? 0, s = String(a.connectionState ?? "unknown").toLowerCase();
2117
2137
  ["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));
2118
2138
  const o = Number(se(4.5 - t * 0.09 - i * 11e-4 - n * 6e-3, 1, 4.5).toFixed(2));
2119
2139
  return { networkScore: e, estimatedMos: o };
@@ -2125,7 +2145,7 @@ function Le() {
2125
2145
  const a = Number(navigator.deviceMemory);
2126
2146
  return Number.isFinite(a) ? a : null;
2127
2147
  }
2128
- function J(a) {
2148
+ function H(a) {
2129
2149
  const e = Number(a);
2130
2150
  return Number.isFinite(e) ? e : null;
2131
2151
  }
@@ -2138,20 +2158,20 @@ function V(a) {
2138
2158
  function re(a, e) {
2139
2159
  return a instanceof Error ? a : new Error(e);
2140
2160
  }
2141
- const De = "1.3.16";
2161
+ const De = "1.3.17";
2142
2162
  export {
2143
2163
  Z as AVATAR_TUNING_DEFAULTS,
2144
2164
  Se as BACKGROUND_PRESETS,
2145
2165
  ke as OVERLAY_EFFECTS,
2146
2166
  Ce as RtcClient,
2147
- Ee as RtcIncomingClient,
2167
+ Me as RtcIncomingClient,
2148
2168
  qe as SPEAKER_NOISE_FLOOR,
2149
2169
  Oe as SPEAKER_TAKEOVER_RATIO,
2150
- Ue as createAvatarPipeline,
2170
+ xe as createAvatarPipeline,
2151
2171
  je as createCallRecorder,
2152
2172
  Ne as createPictureInPictureController,
2153
- Qe as createRtcClient,
2154
- xe as createRtcIncomingClient,
2173
+ Ue as createRtcClient,
2174
+ Qe as createRtcIncomingClient,
2155
2175
  Ve as createVideoEffectsPipeline,
2156
2176
  be as drawAvatar,
2157
2177
  we as headPoseFromMatrix,