@streaming-cdn/rtc-web 1.3.19 → 1.3.21

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 N = {
17
+ const j = {
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 },
@@ -29,15 +29,16 @@ const N = {
29
29
  poorRttMs: 350,
30
30
  goodLossPct: 1,
31
31
  goodRttMs: 250,
32
- sustainRatio: 0.8
32
+ sustainRatio: 0.8,
33
+ bandwidthHeadroomRatio: 1.25
33
34
  };
34
35
  function ue(a) {
35
36
  const e = String(a ?? "").trim().toLowerCase();
36
37
  return !e || e === "none" ? "" : e === "cpu" || e === "bandwidth" ? e : "other";
37
38
  }
38
39
  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), 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, E = P ? i + 1 : 0, A = { quality: a, poorSamples: L, goodSamples: E, 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 } : E >= s.goodSamplesToStepUp && l < c ? { quality: o[l + 1], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : A;
40
+ 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, k = ue(e.qualityLimitationReason), f = e.packetLossPct ?? 0, v = e.rttMs ?? 0, C = e.availableOutgoingBitrateBps, y = j[a].maxBitrate, w = f >= s.criticalLossPct || v >= s.criticalRttMs || k === "cpu", p = k === "bandwidth" && (C == null || C < y * s.bandwidthHeadroomRatio), R = w || f >= s.poorLossPct || v >= s.poorRttMs || p, P = C == null || C >= y * s.sustainRatio, L = f < s.goodLossPct && v < s.goodRttMs && !k && P, I = R ? t + 1 : 0, A = L ? i + 1 : 0, S = { quality: a, poorSamples: I, goodSamples: A, samplesSeen: d, changed: !1 };
41
+ return l > c ? { quality: o[c], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : u ? S : w && l > 0 ? { quality: o[l - 1], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : I >= s.poorSamplesToStepDown && l > 0 ? { quality: o[l - 1], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : A >= s.goodSamplesToStepUp && l < c ? { quality: o[l + 1], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : S;
41
42
  }
42
43
  function pe(a, e) {
43
44
  const t = a instanceof Map ? a : new Map(a);
@@ -46,12 +47,12 @@ function pe(a, e) {
46
47
  const u = String(d.type ?? "");
47
48
  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
49
  n += Number(d.packetsLost ?? 0);
49
- const S = Number(d.roundTripTime ?? NaN);
50
- Number.isFinite(S) && (o = S * 1e3);
50
+ const k = Number(d.roundTripTime ?? NaN);
51
+ Number.isFinite(k) && (o = k * 1e3);
51
52
  }
52
53
  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);
54
+ const k = Number(d.currentRoundTripTime ?? NaN);
55
+ o == null && Number.isFinite(k) && (o = k * 1e3);
55
56
  const f = Number(d.availableOutgoingBitrate ?? NaN);
56
57
  Number.isFinite(f) && (r = f);
57
58
  }
@@ -391,7 +392,7 @@ class Q {
391
392
  async applyPeerVideoQuality(e) {
392
393
  const t = this.screenStream?.getVideoTracks()[0]?.id;
393
394
  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 : N[e.quality], o = i.getParameters(), r = o.encodings?.length ? o.encodings : [{}];
395
+ const n = !!(t && i.track?.id === t), s = n ? ge : this.quality === "audio" ? fe.audio : j[e.quality], o = i.getParameters(), r = o.encodings?.length ? o.encodings : [{}];
395
396
  o.encodings = r.map((c) => ({ ...c, ...s })), o.degradationPreference = n ? "maintain-resolution" : "maintain-framerate", await i.setParameters(o);
396
397
  }
397
398
  }
@@ -498,10 +499,10 @@ class Q {
498
499
  function _() {
499
500
  return globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
500
501
  }
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 }
502
+ const H = { active: !0, maxBitrate: 4e6, maxFramerate: 30, scaleResolutionDownBy: 1 }, Y = [
503
+ { rid: "a", maxBitrate: j.high.maxBitrate, maxFramerate: j.high.maxFramerate },
504
+ { rid: "b", maxBitrate: j.medium.maxBitrate, maxFramerate: j.medium.maxFramerate, scaleResolutionDownBy: 2 },
505
+ { rid: "c", maxBitrate: j.low.maxBitrate, maxFramerate: j.low.maxFramerate, scaleResolutionDownBy: 4 }
505
506
  ], G = { high: "a", medium: "b", low: "c" };
506
507
  class ye {
507
508
  options;
@@ -839,12 +840,12 @@ class ye {
839
840
  const o = this.quality === "audio" ? null : G[this.quality];
840
841
  n.encodings = s.map((r) => {
841
842
  if (i)
842
- return { ...r, active: r.rid === "a", ...r.rid === "a" ? { maxBitrate: z.maxBitrate, maxFramerate: z.maxFramerate } : {} };
843
+ return { ...r, active: r.rid === "a", ...r.rid === "a" ? { maxBitrate: H.maxBitrate, maxFramerate: H.maxFramerate } : {} };
843
844
  const c = Y.find((d) => d.rid === r.rid), l = o != null && String(r.rid ?? "") >= o;
844
845
  return { ...r, ...c ?? {}, active: l };
845
846
  });
846
847
  } else {
847
- const o = this.quality === "audio" ? N.audio : N[this.quality], r = i ? z : o;
848
+ const o = this.quality === "audio" ? j.audio : j[this.quality], r = i ? H : o;
848
849
  n.encodings = s.map((c) => ({ ...c, ...r }));
849
850
  }
850
851
  n.degradationPreference = i ? "maintain-resolution" : "maintain-framerate", await e.setParameters(n);
@@ -973,15 +974,15 @@ function Ne(a, e = {}) {
973
974
  }
974
975
  function je(a, e) {
975
976
  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);
976
- let c = null, l = null, d = null, u = null, S = 0, f = [], v = !1;
977
- async function I(y, k, p, C = "application/json") {
978
- const P = await i(`${n}${k}`, {
977
+ let c = null, l = null, d = null, u = null, k = 0, f = [], v = !1;
978
+ async function C(y, w, p, R = "application/json") {
979
+ const P = await i(`${n}${w}`, {
979
980
  method: y,
980
981
  headers: {
981
982
  authorization: `Bearer ${e.credential.signalingToken}`,
982
- "content-type": C
983
+ "content-type": R
983
984
  },
984
- body: p === void 0 ? void 0 : C === "application/json" ? JSON.stringify(p) : p
985
+ body: p === void 0 ? void 0 : R === "application/json" ? JSON.stringify(p) : p
985
986
  });
986
987
  if (!P.ok) throw new Error(`Recording request failed with HTTP ${P.status}`);
987
988
  return P.json();
@@ -992,60 +993,60 @@ function je(a, e) {
992
993
  },
993
994
  async start() {
994
995
  if (v) return;
995
- u = (await I("POST", "/v1/rtc/recordings")).recordingId;
996
- const k = t.createElement("canvas");
997
- k.width = r, k.height = o;
998
- const p = k.getContext("2d"), C = /* @__PURE__ */ new Map(), P = (T, R) => {
999
- let b = C.get(T);
1000
- return b || (b = t.createElement("video"), b.muted = !0, b.playsInline = !0, b.srcObject = R, b.play().catch(() => {
1001
- }), C.set(T, b)), b;
996
+ u = (await C("POST", "/v1/rtc/recordings")).recordingId;
997
+ const w = t.createElement("canvas");
998
+ w.width = r, w.height = o;
999
+ const p = w.getContext("2d"), R = /* @__PURE__ */ new Map(), P = (T, M) => {
1000
+ let b = R.get(T);
1001
+ return b || (b = t.createElement("video"), b.muted = !0, b.playsInline = !0, b.srcObject = M, b.play().catch(() => {
1002
+ }), R.set(T, b)), b;
1002
1003
  };
1003
1004
  l = setInterval(() => {
1004
- const T = a.getRemoteStreams(), R = a.getLocalStream(), b = [
1005
- ...T.map((j) => ({ key: j.participant.participantId, stream: j.stream, label: j.participant.displayName })),
1006
- ...R ? [{ key: "local", stream: R, label: "me" }] : []
1005
+ const T = a.getRemoteStreams(), M = a.getLocalStream(), b = [
1006
+ ...T.map((q) => ({ key: q.participant.participantId, stream: q.stream, label: q.participant.displayName })),
1007
+ ...M ? [{ key: "local", stream: M, label: "me" }] : []
1007
1008
  ];
1008
1009
  p.fillStyle = "#101418", p.fillRect(0, 0, r, o);
1009
- 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;
1010
- b.forEach((j, J) => {
1011
- const W = P(j.key, j.stream), B = J % O * q, F = Math.floor(J / O) * x;
1012
- 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);
1010
+ const O = Math.max(1, Math.ceil(Math.sqrt(b.length))), V = Math.max(1, Math.ceil(b.length / O)), N = r / O, g = o / V;
1011
+ b.forEach((q, $) => {
1012
+ const J = P(q.key, q.stream), B = $ % O * N, F = Math.floor($ / O) * g;
1013
+ J.videoWidth > 0 && p.drawImage(J, B + 2, F + 2, N - 4, g - 4), p.fillStyle = "rgba(0,0,0,.6)", p.fillRect(B + 8, F + g - 30, Math.min(N - 16, 12 + q.label.length * 9), 22), p.fillStyle = "#fff", p.font = "14px system-ui", p.fillText(q.label, B + 14, F + g - 14);
1013
1014
  });
1014
1015
  }, 66);
1015
- const L = k.captureStream(15);
1016
+ const L = w.captureStream(15);
1016
1017
  d = new AudioContext();
1017
- const E = d.createMediaStreamDestination(), A = /* @__PURE__ */ new Set(), w = () => {
1018
+ const I = d.createMediaStreamDestination(), A = /* @__PURE__ */ new Set(), S = () => {
1018
1019
  const T = [
1019
- ...a.getRemoteStreams().map((R) => R.stream),
1020
+ ...a.getRemoteStreams().map((M) => M.stream),
1020
1021
  ...a.getLocalStream() ? [a.getLocalStream()] : []
1021
1022
  ];
1022
- for (const R of T)
1023
- for (const b of R.getAudioTracks())
1024
- A.has(b.id) || (A.add(b.id), d.createMediaStreamSource(new MediaStream([b])).connect(E));
1023
+ for (const M of T)
1024
+ for (const b of M.getAudioTracks())
1025
+ A.has(b.id) || (A.add(b.id), d.createMediaStreamSource(new MediaStream([b])).connect(I));
1025
1026
  };
1026
- w();
1027
- const M = setInterval(w, 1e3), m = () => clearInterval(M);
1028
- for (const T of E.stream.getAudioTracks()) L.addTrack(T);
1029
- c = (e.mediaRecorderFactory ?? ((T, R) => new MediaRecorder(T, R)))(L, { mimeType: s }), f = [], c.addEventListener("dataavailable", (T) => {
1027
+ S();
1028
+ const E = setInterval(S, 1e3), m = () => clearInterval(E);
1029
+ for (const T of I.stream.getAudioTracks()) L.addTrack(T);
1030
+ c = (e.mediaRecorderFactory ?? ((T, M) => new MediaRecorder(T, M)))(L, { mimeType: s }), f = [], c.addEventListener("dataavailable", (T) => {
1030
1031
  T.data && T.data.size > 0 && f.push(T.data);
1031
- }), c.addEventListener("stop", m), c.start(1e3), S = Date.now(), v = !0;
1032
+ }), c.addEventListener("stop", m), c.start(1e3), k = Date.now(), v = !0;
1032
1033
  },
1033
1034
  async stop() {
1034
1035
  if (!v || !c || !u) throw new Error("The recorder is not running");
1035
1036
  v = !1;
1036
- const y = c, k = new Promise((E) => y.addEventListener("stop", () => E(), { once: !0 }));
1037
- y.stop(), await k, l && clearInterval(l), l = null, await d?.close().catch(() => {
1037
+ const y = c, w = new Promise((I) => y.addEventListener("stop", () => I(), { once: !0 }));
1038
+ y.stop(), await w, l && clearInterval(l), l = null, await d?.close().catch(() => {
1038
1039
  }), d = null;
1039
1040
  const p = new Blob(f, { type: s });
1040
1041
  f = [];
1041
- const C = Math.max(1, Math.round((Date.now() - S) / 1e3)), P = await I(
1042
+ const R = Math.max(1, Math.round((Date.now() - k) / 1e3)), P = await C(
1042
1043
  "PUT",
1043
1044
  `/v1/rtc/recordings/${encodeURIComponent(u)}/media`,
1044
1045
  p,
1045
1046
  s
1046
1047
  );
1047
- await I("POST", `/v1/rtc/recordings/${encodeURIComponent(u)}/complete`, { durationSeconds: C });
1048
- const L = { recordingId: u, sizeBytes: P.sizeBytes, durationSeconds: C };
1048
+ await C("POST", `/v1/rtc/recordings/${encodeURIComponent(u)}/complete`, { durationSeconds: R });
1049
+ const L = { recordingId: u, sizeBytes: P.sizeBytes, durationSeconds: R };
1049
1050
  return u = null, c = null, L;
1050
1051
  },
1051
1052
  dispose() {
@@ -1096,20 +1097,20 @@ const Se = ["none", "blur", "aurora", "cybergrid", "bokeh", "sunset", "image"],
1096
1097
  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);
1097
1098
  }
1098
1099
  };
1099
- function Ve(a, e = {}) {
1100
+ function xe(a, e = {}) {
1100
1101
  const t = e.document ?? globalThis.document;
1101
1102
  let i = e.width ?? 1280, n = e.height ?? 720;
1102
1103
  const s = !!(e.width || e.height), o = e.frameRate ?? 24, r = a instanceof MediaStreamTrack ? a : a.getVideoTracks()[0];
1103
1104
  if (!r) throw new Error("A video track is required");
1104
- let c = e.background ?? "none", l = e.overlay ?? "none", d = e.backgroundImage ?? null, u = e.segmenter ?? null, S = null, f = !1;
1105
+ let c = e.background ?? "none", l = e.overlay ?? "none", d = e.backgroundImage ?? null, u = e.segmenter ?? null, k = null, f = !1;
1105
1106
  const v = t.createElement("video");
1106
1107
  v.muted = !0, v.playsInline = !0, v.srcObject = new MediaStream([r]), v.play().catch(() => {
1107
1108
  });
1108
- const I = t.createElement("canvas");
1109
- I.width = i, I.height = n;
1110
- const y = I.getContext("2d"), k = t.createElement("canvas");
1111
- k.width = i, k.height = n;
1112
- const p = k.getContext("2d"), C = () => Array.from({ length: 80 }, (m, h) => ({
1109
+ const C = t.createElement("canvas");
1110
+ C.width = i, C.height = n;
1111
+ const y = C.getContext("2d"), w = t.createElement("canvas");
1112
+ w.width = i, w.height = n;
1113
+ const p = w.getContext("2d"), R = () => Array.from({ length: 80 }, (m, h) => ({
1113
1114
  x: (Math.sin(h * 12.9898) * 0.5 + 0.5) * i,
1114
1115
  y: (Math.sin(h * 78.233) * 0.5 + 0.5) * n,
1115
1116
  speed: 0.6 + h % 5 * 0.5,
@@ -1117,25 +1118,25 @@ function Ve(a, e = {}) {
1117
1118
  size: 2 + h % 4,
1118
1119
  hue: h * 47 % 360
1119
1120
  }));
1120
- let P = C();
1121
+ let P = R();
1121
1122
  const L = () => {
1122
1123
  if (s) return;
1123
1124
  const m = v.videoWidth, h = v.videoHeight;
1124
1125
  if (!m || !h) return;
1125
- const T = Math.min(1, 1280 / Math.max(m, h)), R = Math.round(m * T), b = Math.round(h * T);
1126
- R === i && b === n || (i = R, n = b, I.width = i, I.height = n, k.width = i, k.height = n, P = C());
1126
+ const T = Math.min(1, 1280 / Math.max(m, h)), M = Math.round(m * T), b = Math.round(h * T);
1127
+ M === i && b === n || (i = M, n = b, C.width = i, C.height = n, w.width = i, w.height = n, P = R());
1127
1128
  };
1128
1129
  v.addEventListener?.("loadedmetadata", L), v.addEventListener?.("resize", L);
1129
- function E() {
1130
- if (S) {
1131
- 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);
1130
+ function I() {
1131
+ if (k) {
1132
+ p.clearRect(0, 0, i, n), p.drawImage(k, 0, 0, i, n), p.globalCompositeOperation = "source-in", p.drawImage(v, 0, 0, i, n), p.globalCompositeOperation = "source-over", y.drawImage(w, 0, 0);
1132
1133
  return;
1133
1134
  }
1134
- const m = i * 0.42, h = m * 9 / 16, T = i - m - 24, R = n - h - 24;
1135
- 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();
1135
+ const m = i * 0.42, h = m * 9 / 16, T = i - m - 24, M = n - h - 24;
1136
+ y.save(), y.shadowColor = "rgba(0,0,0,.5)", y.shadowBlur = 24, y.beginPath(), y.roundRect(T, M, m, h, 14), y.clip(), y.drawImage(v, T, M, m, h), y.restore();
1136
1137
  }
1137
1138
  function A(m) {
1138
- 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 && E()) : c === "image" && d ? (y.drawImage(d, 0, 0, i, n), E()) : ((K[c] ?? K.aurora)(y, i, n, m), E()), l === "snow" || l === "confetti")
1139
+ 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", k && I()) : c === "image" && d ? (y.drawImage(d, 0, 0, i, n), I()) : ((K[c] ?? K.aurora)(y, i, n, m), I()), l === "snow" || l === "confetti")
1139
1140
  for (const h of P)
1140
1141
  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());
1141
1142
  else if (l === "vignette") {
@@ -1143,30 +1144,30 @@ function Ve(a, e = {}) {
1143
1144
  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);
1144
1145
  }
1145
1146
  }
1146
- const w = setInterval(() => {
1147
+ const S = setInterval(() => {
1147
1148
  A(Date.now()), u && !f && c !== "none" && (f = !0, u.segment(v).then((m) => {
1148
- S = m;
1149
+ k = m;
1149
1150
  }).catch(() => {
1150
- S = null;
1151
+ k = null;
1151
1152
  }).finally(() => {
1152
1153
  f = !1;
1153
1154
  }));
1154
- }, Math.round(1e3 / o)), M = I.captureStream(o);
1155
+ }, Math.round(1e3 / o)), E = C.captureStream(o);
1155
1156
  return {
1156
- track: M.getVideoTracks()[0],
1157
- stream: M,
1157
+ track: E.getVideoTracks()[0],
1158
+ stream: E,
1158
1159
  setBackground(m, h) {
1159
- c = Se.includes(m) ? m : "none", h !== void 0 && (d = h), c === "none" && (S = null);
1160
+ c = Se.includes(m) ? m : "none", h !== void 0 && (d = h), c === "none" && (k = null);
1160
1161
  },
1161
1162
  setOverlay(m) {
1162
1163
  l = ke.includes(m) ? m : "none";
1163
1164
  },
1164
1165
  setSegmenter(m) {
1165
- u = m, m || (S = null);
1166
+ u = m, m || (k = null);
1166
1167
  },
1167
1168
  dispose() {
1168
- clearInterval(w), u?.close?.();
1169
- for (const m of M.getTracks()) m.stop();
1169
+ clearInterval(S), u?.close?.();
1170
+ for (const m of E.getTracks()) m.stop();
1170
1171
  v.srcObject = null;
1171
1172
  }
1172
1173
  };
@@ -1198,10 +1199,10 @@ function we(a) {
1198
1199
  }
1199
1200
  function Te(a, e, t = 1) {
1200
1201
  if (!a || a.length === 0) return le();
1201
- 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;
1202
+ 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"), k = Math.min(1, Math.abs(i.yaw) / 0.35) * Math.max(0, Math.min(1, t)), f = (d + u) / 2;
1202
1203
  return {
1203
- blinkLeft: d + (f - d) * S,
1204
- blinkRight: u + (f - u) * S,
1204
+ blinkLeft: d + (f - d) * k,
1205
+ blinkRight: u + (f - u) * k,
1205
1206
  jawOpen: D(a, "jawOpen"),
1206
1207
  smile: c - l,
1207
1208
  browUp: (D(a, "browInnerUp") + D(a, "browOuterUpLeft") + D(a, "browOuterUpRight")) / 3,
@@ -1233,30 +1234,30 @@ function be(a, e, t, i, n) {
1233
1234
  n || (a.fillStyle = "#101822", a.fillRect(0, 0, t, i));
1234
1235
  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;
1235
1236
  a.save(), a.translate(s, o), a.rotate(e.headRoll * 0.6);
1236
- 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;
1237
+ 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, k = (A) => Math.cos(A + c), f = Math.sin(l) * r * 0.22;
1237
1238
  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();
1238
1239
  const v = 0;
1239
1240
  a.fillStyle = "#e5b58a", a.beginPath();
1240
- const I = u(v) * 0.9, y = r * 0.12 + f;
1241
- a.ellipse(I + d * r * 0.14, y, r * 0.11, r * 0.14, 0, 0, Math.PI * 2), a.fill();
1241
+ const C = u(v) * 0.9, y = r * 0.12 + f;
1242
+ a.ellipse(C + d * r * 0.14, y, r * 0.11, r * 0.14, 0, 0, Math.PI * 2), a.fill();
1242
1243
  for (const A of [-1, 1]) {
1243
- const w = A * 0.42, M = S(w);
1244
- if (M <= 0.12) continue;
1245
- const m = u(w) * 0.82, h = Math.max(0.2, M), T = A < 0 ? e.blinkLeft : e.blinkRight, R = Math.max(0.06, 1 - T), b = e.browUp * r * 0.14;
1244
+ const S = A * 0.42, E = k(S);
1245
+ if (E <= 0.12) continue;
1246
+ const m = u(S) * 0.82, h = Math.max(0.2, E), T = A < 0 ? e.blinkLeft : e.blinkRight, M = Math.max(0.06, 1 - T), b = e.browUp * r * 0.14;
1246
1247
  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();
1247
1248
  const O = -r * 0.18 + f;
1248
- 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(
1249
+ a.fillStyle = "#ffffff", a.beginPath(), a.ellipse(m, O, r * 0.16 * h, r * 0.12 * M, 0, 0, Math.PI * 2), a.fill(), a.fillStyle = "#22303c", a.beginPath(), a.ellipse(
1249
1250
  m + e.pupilX * r * 0.07 * h,
1250
1251
  O + e.pupilY * r * 0.05,
1251
1252
  r * 0.06 * h,
1252
- r * 0.06 * R,
1253
+ r * 0.06 * M,
1253
1254
  0,
1254
1255
  0,
1255
1256
  Math.PI * 2
1256
1257
  ), a.fill();
1257
1258
  }
1258
- 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, E = r * 0.42 + f;
1259
- a.fillStyle = "#8c2f2f", a.beginPath(), a.moveTo(p - C / 2, E - L), a.quadraticCurveTo(p, E + P, p + C / 2, E - L), a.quadraticCurveTo(p, E - P * 0.25, p - C / 2, E - 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");
1259
+ const w = Math.max(0.25, k(0)), p = u(0) * 0.7, R = r * 0.55 * w, P = r * (0.04 + e.jawOpen * 0.34), L = e.smile * r * 0.12, I = r * 0.42 + f;
1260
+ a.fillStyle = "#8c2f2f", a.beginPath(), a.moveTo(p - R / 2, I - L), a.quadraticCurveTo(p, I + P, p + R / 2, I - L), a.quadraticCurveTo(p, I - P * 0.25, p - R / 2, I - 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");
1260
1261
  }
1261
1262
  const Z = {
1262
1263
  mouthGain: 1.7,
@@ -1274,70 +1275,70 @@ function ee() {
1274
1275
  }
1275
1276
  };
1276
1277
  }
1277
- const $ = (a) => Math.max(0, Math.min(1, a));
1278
- function xe(a, e = {}) {
1278
+ const z = (a) => Math.max(0, Math.min(1, a));
1279
+ function Ve(a, e = {}) {
1279
1280
  const t = e.document ?? globalThis.document;
1280
1281
  let i = e.width ?? 1280, n = e.height ?? 720;
1281
1282
  const s = !!(e.width || e.height), o = e.frameRate ?? 24, r = a instanceof MediaStreamTrack ? a : a.getVideoTracks()[0];
1282
1283
  if (!r) throw new Error("A video track is required");
1283
1284
  let c = e.tracker ?? null, l = e.renderer ?? ee(), d = e.mode ?? "replace";
1284
- const u = { ...Z, ...e.tuning }, S = e.backdrop ?? "#101822", f = t.createElement("video");
1285
+ const u = { ...Z, ...e.tuning }, k = e.backdrop ?? "#101822", f = t.createElement("video");
1285
1286
  f.muted = !0, f.playsInline = !0, f.srcObject = new MediaStream([r]), f.play().catch(() => {
1286
1287
  });
1287
1288
  const v = t.createElement("canvas");
1288
1289
  v.width = i, v.height = n;
1289
- const I = v.getContext("2d"), y = () => {
1290
+ const C = v.getContext("2d"), y = () => {
1290
1291
  if (s) return;
1291
- const w = f.videoWidth, M = f.videoHeight;
1292
- if (!w || !M) return;
1293
- const m = Math.min(1, 1280 / Math.max(w, M)), h = Math.round(w * m), T = Math.round(M * m);
1292
+ const S = f.videoWidth, E = f.videoHeight;
1293
+ if (!S || !E) return;
1294
+ const m = Math.min(1, 1280 / Math.max(S, E)), h = Math.round(S * m), T = Math.round(E * m);
1294
1295
  (!(h === i || T === n) || h !== i || T !== n) && (i = h, n = T, v.width = i, v.height = n);
1295
1296
  };
1296
1297
  f.addEventListener?.("loadedmetadata", y), f.addEventListener?.("resize", y);
1297
- let k = le(), p = null, C = 0;
1298
- function P(w) {
1299
- if (w.length <= 454) return;
1300
- const M = 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 - M.x) * i, (m.y - M.y) * n), g = Math.max(0.6, Math.cos(k.headPitch)), q = { x: R, y: b, radius: Math.max(24, O / g * 0.8) };
1301
- 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;
1298
+ let w = le(), p = null, R = 0;
1299
+ function P(S) {
1300
+ if (S.length <= 454) return;
1301
+ const E = S[10], m = S[152], h = S[234], T = S[454], M = (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), V = Math.max(0.6, Math.cos(w.headPitch)), N = { x: M, y: b, radius: Math.max(24, O / V * 0.8) };
1302
+ p = p ? { x: p.x + (N.x - p.x) * 0.4, y: p.y + (N.y - p.y) * 0.4, radius: p.radius + (N.radius - p.radius) * 0.15 } : N;
1302
1303
  }
1303
- function L(w) {
1304
+ function L(S) {
1304
1305
  if (c && f.readyState >= 2) {
1305
1306
  let m = null;
1306
1307
  try {
1307
- m = c.detect(f, w);
1308
+ m = c.detect(f, S);
1308
1309
  } catch {
1309
1310
  }
1310
1311
  const h = Te(m?.categories ?? null, m?.matrix ?? null, u.eyeSync);
1311
- 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));
1312
+ h.jawOpen = z(h.jawOpen * u.mouthGain), h.blinkLeft = z(h.blinkLeft * u.blinkGain), h.blinkRight = z(h.blinkRight * u.blinkGain), h.tracked ? (R = S, w = X(w, h, u.smoothing), m?.landmarks && P(m.landmarks)) : w.tracked && S - R > u.lostHoldMs && (w = X(w, { ...w, jawOpen: 0, browUp: 0, smile: w.smile * 0.5, blinkLeft: 0.1, blinkRight: 0.1 }, 0.05));
1312
1313
  }
1313
- d === "overlay" && f.readyState >= 2 ? I.drawImage(f, 0, 0, i, n) : (I.fillStyle = S, I.fillRect(0, 0, i, n));
1314
- const M = p ? { x: p.x, y: p.y + u.avatarLift * p.radius, radius: p.radius * u.avatarScale } : null;
1315
- l?.render(I, k, i, n, M);
1314
+ d === "overlay" && f.readyState >= 2 ? C.drawImage(f, 0, 0, i, n) : (C.fillStyle = k, C.fillRect(0, 0, i, n));
1315
+ const E = p ? { x: p.x, y: p.y + u.avatarLift * p.radius, radius: p.radius * u.avatarScale } : null;
1316
+ l?.render(C, w, i, n, E);
1316
1317
  }
1317
- const E = setInterval(() => L(Date.now()), Math.round(1e3 / o)), A = v.captureStream(o);
1318
+ const I = setInterval(() => L(Date.now()), Math.round(1e3 / o)), A = v.captureStream(o);
1318
1319
  return {
1319
1320
  track: A.getVideoTracks()[0],
1320
1321
  stream: A,
1321
- getRig: () => ({ ...k }),
1322
- setMode(w) {
1323
- d = w === "overlay" ? "overlay" : "replace";
1322
+ getRig: () => ({ ...w }),
1323
+ setMode(S) {
1324
+ d = S === "overlay" ? "overlay" : "replace";
1324
1325
  },
1325
- setTracker(w) {
1326
- c?.close?.(), c = w;
1326
+ setTracker(S) {
1327
+ c?.close?.(), c = S;
1327
1328
  },
1328
- setRenderer(w) {
1329
- l?.dispose?.(), l = w ?? ee();
1329
+ setRenderer(S) {
1330
+ l?.dispose?.(), l = S ?? ee();
1330
1331
  },
1331
- setTuning(w) {
1332
- for (const M of Object.keys(Z)) {
1333
- const m = w[M];
1334
- typeof m == "number" && Number.isFinite(m) && (u[M] = m);
1332
+ setTuning(S) {
1333
+ for (const E of Object.keys(Z)) {
1334
+ const m = S[E];
1335
+ typeof m == "number" && Number.isFinite(m) && (u[E] = m);
1335
1336
  }
1336
1337
  },
1337
1338
  getTuning: () => ({ ...u }),
1338
1339
  dispose() {
1339
- clearInterval(E), c?.close?.(), l?.dispose?.();
1340
- for (const w of A.getTracks()) w.stop();
1340
+ clearInterval(I), c?.close?.(), l?.dispose?.();
1341
+ for (const S of A.getTracks()) S.stop();
1341
1342
  f.srcObject = null;
1342
1343
  }
1343
1344
  };
@@ -1400,7 +1401,7 @@ class Ce extends EventTarget {
1400
1401
  } catch (e) {
1401
1402
  this.state = "failed";
1402
1403
  const t = re(e, "RTC initialization failed");
1403
- throw this.emit("error", V(t)), t;
1404
+ throw this.emit("error", x(t)), t;
1404
1405
  }
1405
1406
  }
1406
1407
  async join() {
@@ -1408,7 +1409,7 @@ class Ce extends EventTarget {
1408
1409
  return this.joinPromise ? this.joinPromise : (this.state = "joining", this.emit("joining", {}), this.joinPromise = e.join().catch((t) => {
1409
1410
  this.state = "failed";
1410
1411
  const i = re(t, "RTC connection failed");
1411
- throw this.emit("error", V(i)), i;
1412
+ throw this.emit("error", x(i)), i;
1412
1413
  }).finally(() => {
1413
1414
  this.joinPromise = null;
1414
1415
  }), this.joinPromise);
@@ -1522,7 +1523,7 @@ class Ce extends EventTarget {
1522
1523
  let n = "unavailable";
1523
1524
  if (e.requestMedia !== !1 && navigator.mediaDevices?.getUserMedia)
1524
1525
  try {
1525
- (await navigator.mediaDevices.getUserMedia({ audio: this.options.audio, video: this.options.video })).getTracks().forEach((S) => S.stop()), n = "granted";
1526
+ (await navigator.mediaDevices.getUserMedia({ audio: this.options.audio, video: this.options.video })).getTracks().forEach((k) => k.stop()), n = "granted";
1526
1527
  } catch {
1527
1528
  n = "denied", t.push("media_permission_denied");
1528
1529
  }
@@ -1533,8 +1534,8 @@ class Ce extends EventTarget {
1533
1534
  if (c) {
1534
1535
  const u = performance.now();
1535
1536
  try {
1536
- const S = await fetch(c, { method: "HEAD", cache: "no-store", credentials: "omit" });
1537
- l = Math.round(performance.now() - u), S.ok || t.push("network_probe_failed");
1537
+ const k = await fetch(c, { method: "HEAD", cache: "no-store", credentials: "omit" });
1538
+ l = Math.round(performance.now() - u), k.ok || t.push("network_probe_failed");
1538
1539
  } catch {
1539
1540
  t.push("network_probe_failed");
1540
1541
  }
@@ -1581,6 +1582,10 @@ class Ce extends EventTarget {
1581
1582
  framesPerSecond: null,
1582
1583
  frameWidth: null,
1583
1584
  frameHeight: null,
1585
+ inboundFrameWidth: null,
1586
+ inboundFrameHeight: null,
1587
+ outboundFrameWidth: null,
1588
+ outboundFrameHeight: null,
1584
1589
  framesDropped: null,
1585
1590
  freezeCount: null,
1586
1591
  freezeDurationMs: null,
@@ -1642,7 +1647,7 @@ class Ce extends EventTarget {
1642
1647
  const i = Date.now(), n = e !== "runtime" || i - this.lastTelemetryAt >= this.options.telemetryInterval;
1643
1648
  this.options.autoReportStats && n && (await this.reportQuality(t), this.lastTelemetryAt = i);
1644
1649
  } catch (t) {
1645
- this.emit("telemetryerror", V(t));
1650
+ this.emit("telemetryerror", x(t));
1646
1651
  } finally {
1647
1652
  this.statsRunning = !1;
1648
1653
  }
@@ -1762,8 +1767,8 @@ class Ee extends EventTarget {
1762
1767
  constructor(e) {
1763
1768
  if (super(), !e.token && !e.tokenProvider) throw new Error("A client token or tokenProvider is required");
1764
1769
  if (e.token && !e.token.startsWith("rtcc_")) throw new Error("A valid RTC client token is required");
1765
- if (!e.signalingUrl && !e.apiBaseUrl && !globalThis.location?.origin)
1766
- throw new Error("signalingUrl or apiBaseUrl is required outside a browser");
1770
+ if (!e.signalingUrl && !e.callActionsUrl && !e.apiBaseUrl && !globalThis.location?.origin)
1771
+ throw new Error("signalingUrl or callActionsUrl is required outside a browser");
1767
1772
  this.options = e, this.currentToken = e.token ?? null, this.currentTokenExpiresAt = e.tokenExpiresAt, this.callAudio = new Ie(e), this.mount = te(e.mount), this.scheduleTokenRefresh();
1768
1773
  }
1769
1774
  connect() {
@@ -1873,7 +1878,7 @@ class Ee extends EventTarget {
1873
1878
  try {
1874
1879
  t = await this.resolveToken(e, e === "reconnect");
1875
1880
  } catch (s) {
1876
- this.emit("tokenerror", V(s)), !this.stopped && this.options.reconnect !== !1 && this.scheduleReconnect();
1881
+ this.emit("tokenerror", x(s)), !this.stopped && this.options.reconnect !== !1 && this.scheduleReconnect();
1877
1882
  return;
1878
1883
  }
1879
1884
  if (this.stopped || this.socket) return;
@@ -1935,8 +1940,8 @@ class Ee extends EventTarget {
1935
1940
  });
1936
1941
  }
1937
1942
  async request(e, t, i = !1) {
1938
- const n = this.options.apiBaseUrl ?? this.options.signalingUrl ?? globalThis.location?.origin;
1939
- if (!n) throw new Error("apiBaseUrl is required for call actions");
1943
+ const n = this.options.callActionsUrl ?? this.options.apiBaseUrl ?? this.options.signalingUrl ?? globalThis.location?.origin;
1944
+ if (!n) throw new Error("callActionsUrl is required for call actions");
1940
1945
  const s = new URL(n, globalThis.location?.href), o = await this.resolveToken("initial"), r = new Headers(t.headers);
1941
1946
  r.set("authorization", `Bearer ${o}`), r.set("content-type", "application/json");
1942
1947
  const c = await fetch(new URL(e, s.origin), { ...t, headers: r }), l = await c.json().catch(() => ({}));
@@ -1971,9 +1976,9 @@ class Ee extends EventTarget {
1971
1976
  Object.assign(s.style, { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "10px" });
1972
1977
  const o = ie("Decline", "#fff", "#a32920", "#d9a09b"), r = ie("Answer", "#fff", "#08745f", "#08745f");
1973
1978
  o.addEventListener("click", () => {
1974
- this.reject(e.id).catch((c) => this.emit("error", V(c)));
1979
+ this.reject(e.id).catch((c) => this.emit("error", x(c)));
1975
1980
  }), r.addEventListener("click", () => {
1976
- this.accept(e.id).catch((c) => this.emit("error", V(c)));
1981
+ this.accept(e.id).catch((c) => this.emit("error", x(c)));
1977
1982
  }), s.appendChild(o), s.appendChild(r), t.appendChild(i), t.appendChild(n), t.appendChild(s), this.mount.replaceChildren(t);
1978
1983
  }
1979
1984
  dismiss(e) {
@@ -2041,7 +2046,7 @@ class Ee extends EventTarget {
2041
2046
  const t = Math.max(0, e - this.refreshSkew(e));
2042
2047
  this.tokenRefreshTimer = setTimeout(() => {
2043
2048
  this.tokenRefreshTimer = null, this.resolveToken("expiring", !0).catch((i) => {
2044
- this.emit("tokenerror", V(i)), this.stopped || (this.tokenRefreshTimer = setTimeout(() => this.scheduleTokenRefresh(), 3e4));
2049
+ this.emit("tokenerror", x(i)), this.stopped || (this.tokenRefreshTimer = setTimeout(() => this.scheduleTokenRefresh(), 3e4));
2045
2050
  });
2046
2051
  }, Math.min(t, 2147e6));
2047
2052
  }
@@ -2055,7 +2060,7 @@ class Ee extends EventTarget {
2055
2060
  this.options.reportSignalingDiagnostics === !1 || this.stopped || this.request("/v1/rtc/client/signaling-events", {
2056
2061
  method: "POST",
2057
2062
  body: JSON.stringify({ ...e, occurredAt: (/* @__PURE__ */ new Date()).toISOString() })
2058
- }).catch((t) => this.emit("diagnosticserror", V(t)));
2063
+ }).catch((t) => this.emit("diagnosticserror", x(t)));
2059
2064
  }
2060
2065
  emit(e, t) {
2061
2066
  const i = { type: e, detail: t, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
@@ -2101,46 +2106,50 @@ function ne(a) {
2101
2106
  }
2102
2107
  async function Pe(a, e) {
2103
2108
  const t = await a.getStats(), i = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
2104
- 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, E = null, A = null;
2109
+ let s = 0, o = 0, r = 0, c = 0, l = 0, d = 0, u = 0, k = 0, f = 0, v = 0, C = 0, y = 0, w = 0, p = 0, R = 0, P = null, L = null, I = null, A = null, S = null, E = null;
2105
2110
  t.forEach((g) => {
2106
2111
  n.set(g.id, g), g.type === "codec" && i.set(g.id, String(g.mimeType ?? ""));
2107
2112
  }), t.forEach((g) => {
2108
- 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), E ||= i.get(String(g.codecId ?? "")) ?? null), g.type === "outbound-rtp" && !g.isRemote && (o += Number(g.bytesSent ?? 0), A ||= g.qualityLimitationReason ? String(g.qualityLimitationReason) : null, E ||= i.get(String(g.codecId ?? "")) ?? null), g.type === "candidate-pair" && (g.selected || g.nominated) && g.state === "succeeded") {
2109
- p = Number.isFinite(g.currentRoundTripTime) ? Number(g.currentRoundTripTime) : p, C = Number.isFinite(g.availableOutgoingBitrate) ? Number(g.availableOutgoingBitrate) : C;
2113
+ 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)), k = Math.max(k, Number(g.frameWidth ?? 0)), C = Math.max(C, Number(g.frameHeight ?? 0)), y += Number(g.framesDropped ?? 0), w += Number(g.freezeCount ?? 0), p += Number(g.totalFreezesDuration ?? 0), R += Number(g.concealedSamples ?? 0), S ||= i.get(String(g.codecId ?? "")) ?? null), g.type === "outbound-rtp" && !g.isRemote && (f = Math.max(f, Number(g.frameWidth ?? 0)), v = Math.max(v, Number(g.frameHeight ?? 0)), o += Number(g.bytesSent ?? 0), E ||= g.qualityLimitationReason ? String(g.qualityLimitationReason) : null, S ||= i.get(String(g.codecId ?? "")) ?? null), g.type === "candidate-pair" && (g.selected || g.nominated) && g.state === "succeeded") {
2114
+ P = Number.isFinite(g.currentRoundTripTime) ? Number(g.currentRoundTripTime) : P, L = Number.isFinite(g.availableOutgoingBitrate) ? Number(g.availableOutgoingBitrate) : L;
2110
2115
  const q = n.get(g.localCandidateId);
2111
- P = q?.candidateType ? String(q.candidateType) : P, L = q?.protocol ? String(q.protocol) : L;
2116
+ I = q?.candidateType ? String(q.candidateType) : I, A = q?.protocol ? String(q.protocol) : A;
2112
2117
  }
2113
2118
  });
2114
- const w = Date.now(), M = e ? Math.max(1e-3, (w - e.timestamp) / 1e3) : 0, m = e ? Math.max(0, Math.round((s - e.inboundBytes) * 8 / M)) : null, h = e ? Math.max(0, Math.round((o - e.outboundBytes) * 8 / M)) : 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;
2119
+ const m = Date.now(), h = e ? Math.max(1e-3, (m - e.timestamp) / 1e3) : 0, T = e ? Math.max(0, Math.round((s - e.inboundBytes) * 8 / h)) : null, M = e ? Math.max(0, Math.round((o - e.outboundBytes) * 8 / h)) : null, b = r + c, O = e ? Math.max(0, r - e.packetsLost) : r, V = e ? Math.max(0, c - e.packetsReceived) : c, N = O + V;
2115
2120
  return {
2116
- counters: { timestamp: w, inboundBytes: s, outboundBytes: o, packetsLost: r, packetsReceived: c },
2121
+ counters: { timestamp: m, inboundBytes: s, outboundBytes: o, packetsLost: r, packetsReceived: c },
2117
2122
  sample: {
2118
- rttMs: p === null ? null : p * 1e3,
2123
+ rttMs: P === null ? null : P * 1e3,
2119
2124
  jitterMs: d ? l / d * 1e3 : null,
2120
- packetLossPct: O ? R / O * 100 : null,
2121
- packetLossCumulativePct: T ? r / T * 100 : null,
2125
+ packetLossPct: N ? O / N * 100 : null,
2126
+ packetLossCumulativePct: b ? r / b * 100 : null,
2122
2127
  packetsLost: r,
2123
2128
  packetsReceived: c,
2124
- inboundBitrateBps: m,
2125
- outboundBitrateBps: h,
2126
- availableOutgoingBitrateBps: C,
2129
+ inboundBitrateBps: T,
2130
+ outboundBitrateBps: M,
2131
+ availableOutgoingBitrateBps: L,
2127
2132
  framesPerSecond: u || null,
2128
- frameWidth: S || null,
2129
- frameHeight: f || null,
2130
- framesDropped: v,
2131
- freezeCount: I,
2132
- freezeDurationMs: Math.round(y * 1e3),
2133
- concealedSamples: k,
2134
- codec: E,
2135
- transportProtocol: L,
2136
- candidateType: P,
2137
- qualityLimitationReason: A
2133
+ frameWidth: k || null,
2134
+ frameHeight: C || null,
2135
+ inboundFrameWidth: k || null,
2136
+ inboundFrameHeight: C || null,
2137
+ outboundFrameWidth: f || null,
2138
+ outboundFrameHeight: v || null,
2139
+ framesDropped: y,
2140
+ freezeCount: w,
2141
+ freezeDurationMs: Math.round(p * 1e3),
2142
+ concealedSamples: R,
2143
+ codec: S,
2144
+ transportProtocol: A,
2145
+ candidateType: I,
2146
+ qualityLimitationReason: E
2138
2147
  }
2139
2148
  };
2140
2149
  }
2141
2150
  function Ae(a) {
2142
2151
  let e = a.mediaScore == null ? 5 : Math.round(se(Number(a.mediaScore), 0, 5));
2143
- const t = H(a.packetLossPct) ?? 0, i = H(a.rttMs) ?? 0, n = H(a.jitterMs) ?? 0, s = String(a.connectionState ?? "unknown").toLowerCase();
2152
+ const t = W(a.packetLossPct) ?? 0, i = W(a.rttMs) ?? 0, n = W(a.jitterMs) ?? 0, s = String(a.connectionState ?? "unknown").toLowerCase();
2144
2153
  ["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));
2145
2154
  const o = Number(se(4.5 - t * 0.09 - i * 11e-4 - n * 6e-3, 1, 4.5).toFixed(2));
2146
2155
  return { networkScore: e, estimatedMos: o };
@@ -2152,20 +2161,20 @@ function Le() {
2152
2161
  const a = Number(navigator.deviceMemory);
2153
2162
  return Number.isFinite(a) ? a : null;
2154
2163
  }
2155
- function H(a) {
2164
+ function W(a) {
2156
2165
  const e = Number(a);
2157
2166
  return Number.isFinite(e) ? e : null;
2158
2167
  }
2159
2168
  function se(a, e, t) {
2160
2169
  return Math.min(t, Math.max(e, a));
2161
2170
  }
2162
- function V(a) {
2171
+ function x(a) {
2163
2172
  return a instanceof Error ? { name: a.name, message: a.message } : { name: "ServiceError", message: String(a ?? "Service request failed") };
2164
2173
  }
2165
2174
  function re(a, e) {
2166
2175
  return a instanceof Error ? a : new Error(e);
2167
2176
  }
2168
- const De = "1.3.19";
2177
+ const De = "1.3.21";
2169
2178
  export {
2170
2179
  Z as AVATAR_TUNING_DEFAULTS,
2171
2180
  Se as BACKGROUND_PRESETS,
@@ -2174,12 +2183,12 @@ export {
2174
2183
  Ee as RtcIncomingClient,
2175
2184
  qe as SPEAKER_NOISE_FLOOR,
2176
2185
  Oe as SPEAKER_TAKEOVER_RATIO,
2177
- xe as createAvatarPipeline,
2186
+ Ve as createAvatarPipeline,
2178
2187
  je as createCallRecorder,
2179
2188
  Ne as createPictureInPictureController,
2180
2189
  Ue as createRtcClient,
2181
2190
  Qe as createRtcIncomingClient,
2182
- Ve as createVideoEffectsPipeline,
2191
+ xe as createVideoEffectsPipeline,
2183
2192
  be as drawAvatar,
2184
2193
  we as headPoseFromMatrix,
2185
2194
  le as neutralRig,