@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.
- package/README.md +54 -2
- package/dist/index.d.ts +23 -1
- package/dist/peer-quality.d.ts +2 -0
- package/dist/rtc-web.es.js +173 -164
- package/dist/rtc-web.umd.js +1 -1
- package/package.json +1 -1
package/dist/rtc-web.es.js
CHANGED
|
@@ -14,7 +14,7 @@ function ce(a) {
|
|
|
14
14
|
}
|
|
15
15
|
return e;
|
|
16
16
|
}
|
|
17
|
-
const
|
|
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,
|
|
40
|
-
return l > c ? { quality: o[c], poorSamples: 0, goodSamples: 0, samplesSeen: d, changed: !0 } : u ?
|
|
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
|
|
50
|
-
Number.isFinite(
|
|
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
|
|
54
|
-
o == null && Number.isFinite(
|
|
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 :
|
|
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
|
|
502
|
-
{ rid: "a", maxBitrate:
|
|
503
|
-
{ rid: "b", maxBitrate:
|
|
504
|
-
{ rid: "c", maxBitrate:
|
|
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:
|
|
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" ?
|
|
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,
|
|
977
|
-
async function
|
|
978
|
-
const P = await i(`${n}${
|
|
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":
|
|
983
|
+
"content-type": R
|
|
983
984
|
},
|
|
984
|
-
body: p === void 0 ? void 0 :
|
|
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
|
|
996
|
-
const
|
|
997
|
-
|
|
998
|
-
const p =
|
|
999
|
-
let b =
|
|
1000
|
-
return b || (b = t.createElement("video"), b.muted = !0, b.playsInline = !0, b.srcObject =
|
|
1001
|
-
}),
|
|
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(),
|
|
1005
|
-
...T.map((
|
|
1006
|
-
...
|
|
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))),
|
|
1010
|
-
b.forEach((
|
|
1011
|
-
const
|
|
1012
|
-
|
|
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 =
|
|
1016
|
+
const L = w.captureStream(15);
|
|
1016
1017
|
d = new AudioContext();
|
|
1017
|
-
const
|
|
1018
|
+
const I = d.createMediaStreamDestination(), A = /* @__PURE__ */ new Set(), S = () => {
|
|
1018
1019
|
const T = [
|
|
1019
|
-
...a.getRemoteStreams().map((
|
|
1020
|
+
...a.getRemoteStreams().map((M) => M.stream),
|
|
1020
1021
|
...a.getLocalStream() ? [a.getLocalStream()] : []
|
|
1021
1022
|
];
|
|
1022
|
-
for (const
|
|
1023
|
-
for (const b of
|
|
1024
|
-
A.has(b.id) || (A.add(b.id), d.createMediaStreamSource(new MediaStream([b])).connect(
|
|
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
|
-
|
|
1027
|
-
const
|
|
1028
|
-
for (const T of
|
|
1029
|
-
c = (e.mediaRecorderFactory ?? ((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),
|
|
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,
|
|
1037
|
-
y.stop(), await
|
|
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
|
|
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
|
|
1048
|
-
const L = { recordingId: u, sizeBytes: P.sizeBytes, durationSeconds:
|
|
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
|
|
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,
|
|
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
|
|
1109
|
-
|
|
1110
|
-
const y =
|
|
1111
|
-
|
|
1112
|
-
const p =
|
|
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 =
|
|
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)),
|
|
1126
|
-
|
|
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
|
|
1130
|
-
if (
|
|
1131
|
-
p.clearRect(0, 0, i, n), p.drawImage(
|
|
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,
|
|
1135
|
-
y.save(), y.shadowColor = "rgba(0,0,0,.5)", y.shadowBlur = 24, y.beginPath(), y.roundRect(T,
|
|
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",
|
|
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
|
|
1147
|
+
const S = setInterval(() => {
|
|
1147
1148
|
A(Date.now()), u && !f && c !== "none" && (f = !0, u.segment(v).then((m) => {
|
|
1148
|
-
|
|
1149
|
+
k = m;
|
|
1149
1150
|
}).catch(() => {
|
|
1150
|
-
|
|
1151
|
+
k = null;
|
|
1151
1152
|
}).finally(() => {
|
|
1152
1153
|
f = !1;
|
|
1153
1154
|
}));
|
|
1154
|
-
}, Math.round(1e3 / o)),
|
|
1155
|
+
}, Math.round(1e3 / o)), E = C.captureStream(o);
|
|
1155
1156
|
return {
|
|
1156
|
-
track:
|
|
1157
|
-
stream:
|
|
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" && (
|
|
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 || (
|
|
1166
|
+
u = m, m || (k = null);
|
|
1166
1167
|
},
|
|
1167
1168
|
dispose() {
|
|
1168
|
-
clearInterval(
|
|
1169
|
-
for (const m of
|
|
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"),
|
|
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) *
|
|
1204
|
-
blinkRight: u + (f - u) *
|
|
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,
|
|
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
|
|
1241
|
-
a.ellipse(
|
|
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
|
|
1244
|
-
if (
|
|
1245
|
-
const m = u(
|
|
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 *
|
|
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 *
|
|
1253
|
+
r * 0.06 * M,
|
|
1253
1254
|
0,
|
|
1254
1255
|
0,
|
|
1255
1256
|
Math.PI * 2
|
|
1256
1257
|
), a.fill();
|
|
1257
1258
|
}
|
|
1258
|
-
const
|
|
1259
|
-
a.fillStyle = "#8c2f2f", a.beginPath(), a.moveTo(p -
|
|
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
|
|
1278
|
-
function
|
|
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 },
|
|
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
|
|
1290
|
+
const C = v.getContext("2d"), y = () => {
|
|
1290
1291
|
if (s) return;
|
|
1291
|
-
const
|
|
1292
|
-
if (!
|
|
1293
|
-
const m = Math.min(1, 1280 / Math.max(
|
|
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
|
|
1298
|
-
function P(
|
|
1299
|
-
if (
|
|
1300
|
-
const
|
|
1301
|
-
p = p ? { x: p.x + (
|
|
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(
|
|
1304
|
+
function L(S) {
|
|
1304
1305
|
if (c && f.readyState >= 2) {
|
|
1305
1306
|
let m = null;
|
|
1306
1307
|
try {
|
|
1307
|
-
m = c.detect(f,
|
|
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 =
|
|
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 ?
|
|
1314
|
-
const
|
|
1315
|
-
l?.render(
|
|
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
|
|
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: () => ({ ...
|
|
1322
|
-
setMode(
|
|
1323
|
-
d =
|
|
1322
|
+
getRig: () => ({ ...w }),
|
|
1323
|
+
setMode(S) {
|
|
1324
|
+
d = S === "overlay" ? "overlay" : "replace";
|
|
1324
1325
|
},
|
|
1325
|
-
setTracker(
|
|
1326
|
-
c?.close?.(), c =
|
|
1326
|
+
setTracker(S) {
|
|
1327
|
+
c?.close?.(), c = S;
|
|
1327
1328
|
},
|
|
1328
|
-
setRenderer(
|
|
1329
|
-
l?.dispose?.(), l =
|
|
1329
|
+
setRenderer(S) {
|
|
1330
|
+
l?.dispose?.(), l = S ?? ee();
|
|
1330
1331
|
},
|
|
1331
|
-
setTuning(
|
|
1332
|
-
for (const
|
|
1333
|
-
const m =
|
|
1334
|
-
typeof m == "number" && Number.isFinite(m) && (u[
|
|
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(
|
|
1340
|
-
for (const
|
|
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",
|
|
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",
|
|
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((
|
|
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
|
|
1537
|
-
l = Math.round(performance.now() - u),
|
|
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",
|
|
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
|
|
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",
|
|
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("
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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,
|
|
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)),
|
|
2109
|
-
|
|
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
|
-
|
|
2116
|
+
I = q?.candidateType ? String(q.candidateType) : I, A = q?.protocol ? String(q.protocol) : A;
|
|
2112
2117
|
}
|
|
2113
2118
|
});
|
|
2114
|
-
const
|
|
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:
|
|
2121
|
+
counters: { timestamp: m, inboundBytes: s, outboundBytes: o, packetsLost: r, packetsReceived: c },
|
|
2117
2122
|
sample: {
|
|
2118
|
-
rttMs:
|
|
2123
|
+
rttMs: P === null ? null : P * 1e3,
|
|
2119
2124
|
jitterMs: d ? l / d * 1e3 : null,
|
|
2120
|
-
packetLossPct:
|
|
2121
|
-
packetLossCumulativePct:
|
|
2125
|
+
packetLossPct: N ? O / N * 100 : null,
|
|
2126
|
+
packetLossCumulativePct: b ? r / b * 100 : null,
|
|
2122
2127
|
packetsLost: r,
|
|
2123
2128
|
packetsReceived: c,
|
|
2124
|
-
inboundBitrateBps:
|
|
2125
|
-
outboundBitrateBps:
|
|
2126
|
-
availableOutgoingBitrateBps:
|
|
2129
|
+
inboundBitrateBps: T,
|
|
2130
|
+
outboundBitrateBps: M,
|
|
2131
|
+
availableOutgoingBitrateBps: L,
|
|
2127
2132
|
framesPerSecond: u || null,
|
|
2128
|
-
frameWidth:
|
|
2129
|
-
frameHeight:
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
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 =
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
2191
|
+
xe as createVideoEffectsPipeline,
|
|
2183
2192
|
be as drawAvatar,
|
|
2184
2193
|
we as headPoseFromMatrix,
|
|
2185
2194
|
le as neutralRig,
|