UNPKG

@klever-one/web-sdk

Version:

Web SDK for integrating real-time room management and streaming functionality into web applications

1,147 lines 185 kB
"use client"; var N = { exports: {} }, ee; function tt() { return ee || (ee = 1, (function(a) { const e = {}; e.generateIdentifier = function() { return Math.random().toString(36).substring(2, 12); }, e.localCName = e.generateIdentifier(), e.splitLines = function(t) { return t.trim().split(` `).map((s) => s.trim()); }, e.splitSections = function(t) { return t.split(` m=`).map((n, i) => (i > 0 ? "m=" + n : n).trim() + `\r `); }, e.getDescription = function(t) { const s = e.splitSections(t); return s && s[0]; }, e.getMediaSections = function(t) { const s = e.splitSections(t); return s.shift(), s; }, e.matchPrefix = function(t, s) { return e.splitLines(t).filter((n) => n.indexOf(s) === 0); }, e.parseCandidate = function(t) { let s; t.indexOf("a=candidate:") === 0 ? s = t.substring(12).split(" ") : s = t.substring(10).split(" "); const n = { foundation: s[0], component: { 1: "rtp", 2: "rtcp" }[s[1]] || s[1], protocol: s[2].toLowerCase(), priority: parseInt(s[3], 10), ip: s[4], address: s[4], // address is an alias for ip. port: parseInt(s[5], 10), // skip parts[6] == 'typ' type: s[7] }; for (let i = 8; i < s.length; i += 2) switch (s[i]) { case "raddr": n.relatedAddress = s[i + 1]; break; case "rport": n.relatedPort = parseInt(s[i + 1], 10); break; case "tcptype": n.tcpType = s[i + 1]; break; case "ufrag": n.ufrag = s[i + 1], n.usernameFragment = s[i + 1]; break; default: n[s[i]] === void 0 && (n[s[i]] = s[i + 1]); break; } return n; }, e.writeCandidate = function(t) { const s = []; s.push(t.foundation); const n = t.component; n === "rtp" ? s.push(1) : n === "rtcp" ? s.push(2) : s.push(n), s.push(t.protocol.toUpperCase()), s.push(t.priority), s.push(t.address || t.ip), s.push(t.port); const i = t.type; return s.push("typ"), s.push(i), i !== "host" && t.relatedAddress && t.relatedPort && (s.push("raddr"), s.push(t.relatedAddress), s.push("rport"), s.push(t.relatedPort)), t.tcpType && t.protocol.toLowerCase() === "tcp" && (s.push("tcptype"), s.push(t.tcpType)), (t.usernameFragment || t.ufrag) && (s.push("ufrag"), s.push(t.usernameFragment || t.ufrag)), "candidate:" + s.join(" "); }, e.parseIceOptions = function(t) { return t.substring(14).split(" "); }, e.parseRtpMap = function(t) { let s = t.substring(9).split(" "); const n = { payloadType: parseInt(s.shift(), 10) // was: id }; return s = s[0].split("/"), n.name = s[0], n.clockRate = parseInt(s[1], 10), n.channels = s.length === 3 ? parseInt(s[2], 10) : 1, n.numChannels = n.channels, n; }, e.writeRtpMap = function(t) { let s = t.payloadType; t.preferredPayloadType !== void 0 && (s = t.preferredPayloadType); const n = t.channels || t.numChannels || 1; return "a=rtpmap:" + s + " " + t.name + "/" + t.clockRate + (n !== 1 ? "/" + n : "") + `\r `; }, e.parseExtmap = function(t) { const s = t.substring(9).split(" "); return { id: parseInt(s[0], 10), direction: s[0].indexOf("/") > 0 ? s[0].split("/")[1] : "sendrecv", uri: s[1], attributes: s.slice(2).join(" ") }; }, e.writeExtmap = function(t) { return "a=extmap:" + (t.id || t.preferredId) + (t.direction && t.direction !== "sendrecv" ? "/" + t.direction : "") + " " + t.uri + (t.attributes ? " " + t.attributes : "") + `\r `; }, e.parseFmtp = function(t) { const s = {}; let n; const i = t.substring(t.indexOf(" ") + 1).split(";"); for (let o = 0; o < i.length; o++) n = i[o].trim().split("="), s[n[0].trim()] = n[1]; return s; }, e.writeFmtp = function(t) { let s = "", n = t.payloadType; if (t.preferredPayloadType !== void 0 && (n = t.preferredPayloadType), t.parameters && Object.keys(t.parameters).length) { const i = []; Object.keys(t.parameters).forEach((o) => { t.parameters[o] !== void 0 ? i.push(o + "=" + t.parameters[o]) : i.push(o); }), s += "a=fmtp:" + n + " " + i.join(";") + `\r `; } return s; }, e.parseRtcpFb = function(t) { const s = t.substring(t.indexOf(" ") + 1).split(" "); return { type: s.shift(), parameter: s.join(" ") }; }, e.writeRtcpFb = function(t) { let s = "", n = t.payloadType; return t.preferredPayloadType !== void 0 && (n = t.preferredPayloadType), t.rtcpFeedback && t.rtcpFeedback.length && t.rtcpFeedback.forEach((i) => { s += "a=rtcp-fb:" + n + " " + i.type + (i.parameter && i.parameter.length ? " " + i.parameter : "") + `\r `; }), s; }, e.parseSsrcMedia = function(t) { const s = t.indexOf(" "), n = { ssrc: parseInt(t.substring(7, s), 10) }, i = t.indexOf(":", s); return i > -1 ? (n.attribute = t.substring(s + 1, i), n.value = t.substring(i + 1)) : n.attribute = t.substring(s + 1), n; }, e.parseSsrcGroup = function(t) { const s = t.substring(13).split(" "); return { semantics: s.shift(), ssrcs: s.map((n) => parseInt(n, 10)) }; }, e.getMid = function(t) { const s = e.matchPrefix(t, "a=mid:")[0]; if (s) return s.substring(6); }, e.parseFingerprint = function(t) { const s = t.substring(14).split(" "); return { algorithm: s[0].toLowerCase(), // algorithm is case-sensitive in Edge. value: s[1].toUpperCase() // the definition is upper-case in RFC 4572. }; }, e.getDtlsParameters = function(t, s) { return { role: "auto", fingerprints: e.matchPrefix( t + s, "a=fingerprint:" ).map(e.parseFingerprint) }; }, e.writeDtlsParameters = function(t, s) { let n = "a=setup:" + s + `\r `; return t.fingerprints.forEach((i) => { n += "a=fingerprint:" + i.algorithm + " " + i.value + `\r `; }), n; }, e.parseCryptoLine = function(t) { const s = t.substring(9).split(" "); return { tag: parseInt(s[0], 10), cryptoSuite: s[1], keyParams: s[2], sessionParams: s.slice(3) }; }, e.writeCryptoLine = function(t) { return "a=crypto:" + t.tag + " " + t.cryptoSuite + " " + (typeof t.keyParams == "object" ? e.writeCryptoKeyParams(t.keyParams) : t.keyParams) + (t.sessionParams ? " " + t.sessionParams.join(" ") : "") + `\r `; }, e.parseCryptoKeyParams = function(t) { if (t.indexOf("inline:") !== 0) return null; const s = t.substring(7).split("|"); return { keyMethod: "inline", keySalt: s[0], lifeTime: s[1], mkiValue: s[2] ? s[2].split(":")[0] : void 0, mkiLength: s[2] ? s[2].split(":")[1] : void 0 }; }, e.writeCryptoKeyParams = function(t) { return t.keyMethod + ":" + t.keySalt + (t.lifeTime ? "|" + t.lifeTime : "") + (t.mkiValue && t.mkiLength ? "|" + t.mkiValue + ":" + t.mkiLength : ""); }, e.getCryptoParameters = function(t, s) { return e.matchPrefix( t + s, "a=crypto:" ).map(e.parseCryptoLine); }, e.getIceParameters = function(t, s) { const n = e.matchPrefix( t + s, "a=ice-ufrag:" )[0], i = e.matchPrefix( t + s, "a=ice-pwd:" )[0]; return n && i ? { usernameFragment: n.substring(12), password: i.substring(10) } : null; }, e.writeIceParameters = function(t) { let s = "a=ice-ufrag:" + t.usernameFragment + `\r a=ice-pwd:` + t.password + `\r `; return t.iceLite && (s += `a=ice-lite\r `), s; }, e.parseRtpParameters = function(t) { const s = { codecs: [], headerExtensions: [], fecMechanisms: [], rtcp: [] }, i = e.splitLines(t)[0].split(" "); s.profile = i[2]; for (let d = 3; d < i.length; d++) { const c = i[d], p = e.matchPrefix( t, "a=rtpmap:" + c + " " )[0]; if (p) { const g = e.parseRtpMap(p), f = e.matchPrefix( t, "a=fmtp:" + c + " " ); switch (g.parameters = f.length ? e.parseFmtp(f[0]) : {}, g.rtcpFeedback = e.matchPrefix( t, "a=rtcp-fb:" + c + " " ).map(e.parseRtcpFb), s.codecs.push(g), g.name.toUpperCase()) { case "RED": case "ULPFEC": s.fecMechanisms.push(g.name.toUpperCase()); break; } } } e.matchPrefix(t, "a=extmap:").forEach((d) => { s.headerExtensions.push(e.parseExtmap(d)); }); const o = e.matchPrefix(t, "a=rtcp-fb:* ").map(e.parseRtcpFb); return s.codecs.forEach((d) => { o.forEach((c) => { d.rtcpFeedback.find((g) => g.type === c.type && g.parameter === c.parameter) || d.rtcpFeedback.push(c); }); }), s; }, e.writeRtpDescription = function(t, s) { let n = ""; n += "m=" + t + " ", n += s.codecs.length > 0 ? "9" : "0", n += " " + (s.profile || "UDP/TLS/RTP/SAVPF") + " ", n += s.codecs.map((o) => o.preferredPayloadType !== void 0 ? o.preferredPayloadType : o.payloadType).join(" ") + `\r `, n += `c=IN IP4 0.0.0.0\r `, n += `a=rtcp:9 IN IP4 0.0.0.0\r `, s.codecs.forEach((o) => { n += e.writeRtpMap(o), n += e.writeFmtp(o), n += e.writeRtcpFb(o); }); let i = 0; return s.codecs.forEach((o) => { o.maxptime > i && (i = o.maxptime); }), i > 0 && (n += "a=maxptime:" + i + `\r `), s.headerExtensions && s.headerExtensions.forEach((o) => { n += e.writeExtmap(o); }), n; }, e.parseRtpEncodingParameters = function(t) { const s = [], n = e.parseRtpParameters(t), i = n.fecMechanisms.indexOf("RED") !== -1, o = n.fecMechanisms.indexOf("ULPFEC") !== -1, d = e.matchPrefix(t, "a=ssrc:").map((S) => e.parseSsrcMedia(S)).filter((S) => S.attribute === "cname"), c = d.length > 0 && d[0].ssrc; let p; const g = e.matchPrefix(t, "a=ssrc-group:FID").map((S) => S.substring(17).split(" ").map((L) => parseInt(L, 10))); g.length > 0 && g[0].length > 1 && g[0][0] === c && (p = g[0][1]), n.codecs.forEach((S) => { if (S.name.toUpperCase() === "RTX" && S.parameters.apt) { let E = { ssrc: c, codecPayloadType: parseInt(S.parameters.apt, 10) }; c && p && (E.rtx = { ssrc: p }), s.push(E), i && (E = JSON.parse(JSON.stringify(E)), E.fec = { ssrc: c, mechanism: o ? "red+ulpfec" : "red" }, s.push(E)); } }), s.length === 0 && c && s.push({ ssrc: c }); let f = e.matchPrefix(t, "b="); return f.length && (f[0].indexOf("b=TIAS:") === 0 ? f = parseInt(f[0].substring(7), 10) : f[0].indexOf("b=AS:") === 0 ? f = parseInt(f[0].substring(5), 10) * 1e3 * 0.95 - 2e3 * 8 : f = void 0, s.forEach((S) => { S.maxBitrate = f; })), s; }, e.parseRtcpParameters = function(t) { const s = {}, n = e.matchPrefix(t, "a=ssrc:").map((d) => e.parseSsrcMedia(d)).filter((d) => d.attribute === "cname")[0]; n && (s.cname = n.value, s.ssrc = n.ssrc); const i = e.matchPrefix(t, "a=rtcp-rsize"); s.reducedSize = i.length > 0, s.compound = i.length === 0; const o = e.matchPrefix(t, "a=rtcp-mux"); return s.mux = o.length > 0, s; }, e.writeRtcpParameters = function(t) { let s = ""; return t.reducedSize && (s += `a=rtcp-rsize\r `), t.mux && (s += `a=rtcp-mux\r `), t.ssrc !== void 0 && t.cname && (s += "a=ssrc:" + t.ssrc + " cname:" + t.cname + `\r `), s; }, e.parseMsid = function(t) { let s; const n = e.matchPrefix(t, "a=msid:"); if (n.length === 1) return s = n[0].substring(7).split(" "), { stream: s[0], track: s[1] }; const i = e.matchPrefix(t, "a=ssrc:").map((o) => e.parseSsrcMedia(o)).filter((o) => o.attribute === "msid"); if (i.length > 0) return s = i[0].value.split(" "), { stream: s[0], track: s[1] }; }, e.parseSctpDescription = function(t) { const s = e.parseMLine(t), n = e.matchPrefix(t, "a=max-message-size:"); let i; n.length > 0 && (i = parseInt(n[0].substring(19), 10)), isNaN(i) && (i = 65536); const o = e.matchPrefix(t, "a=sctp-port:"); if (o.length > 0) return { port: parseInt(o[0].substring(12), 10), protocol: s.fmt, maxMessageSize: i }; const d = e.matchPrefix(t, "a=sctpmap:"); if (d.length > 0) { const c = d[0].substring(10).split(" "); return { port: parseInt(c[0], 10), protocol: c[1], maxMessageSize: i }; } }, e.writeSctpDescription = function(t, s) { let n = []; return t.protocol !== "DTLS/SCTP" ? n = [ "m=" + t.kind + " 9 " + t.protocol + " " + s.protocol + `\r `, `c=IN IP4 0.0.0.0\r `, "a=sctp-port:" + s.port + `\r ` ] : n = [ "m=" + t.kind + " 9 " + t.protocol + " " + s.port + `\r `, `c=IN IP4 0.0.0.0\r `, "a=sctpmap:" + s.port + " " + s.protocol + ` 65535\r ` ], s.maxMessageSize !== void 0 && n.push("a=max-message-size:" + s.maxMessageSize + `\r `), n.join(""); }, e.generateSessionId = function() { return Math.random().toString().substr(2, 22); }, e.writeSessionBoilerplate = function(t, s, n) { let i; const o = s !== void 0 ? s : 2; return t ? i = t : i = e.generateSessionId(), `v=0\r o=` + (n || "thisisadapterortc") + " " + i + " " + o + ` IN IP4 127.0.0.1\r s=-\r t=0 0\r `; }, e.getDirection = function(t, s) { const n = e.splitLines(t); for (let i = 0; i < n.length; i++) switch (n[i]) { case "a=sendrecv": case "a=sendonly": case "a=recvonly": case "a=inactive": return n[i].substring(2); } return s ? e.getDirection(s) : "sendrecv"; }, e.getKind = function(t) { return e.splitLines(t)[0].split(" ")[0].substring(2); }, e.isRejected = function(t) { return t.split(" ", 2)[1] === "0"; }, e.parseMLine = function(t) { const n = e.splitLines(t)[0].substring(2).split(" "); return { kind: n[0], port: parseInt(n[1], 10), protocol: n[2], fmt: n.slice(3).join(" ") }; }, e.parseOLine = function(t) { const n = e.matchPrefix(t, "o=")[0].substring(2).split(" "); return { username: n[0], sessionId: n[1], sessionVersion: parseInt(n[2], 10), netType: n[3], addressType: n[4], address: n[5] }; }, e.isValidSDP = function(t) { if (typeof t != "string" || t.length === 0) return !1; const s = e.splitLines(t); for (let n = 0; n < s.length; n++) if (s[n].length < 2 || s[n].charAt(1) !== "=") return !1; return !0; }, a.exports = e; })(N)), N.exports; } var te = /* @__PURE__ */ tt(), R, T, H = { d: (a, e) => { for (var t in e) H.o(e, t) && !H.o(a, t) && Object.defineProperty(a, t, { enumerable: !0, get: e[t] }); }, o: (a, e) => Object.prototype.hasOwnProperty.call(a, e) }, u = {}; H.d(u, { Dz: () => He, g$: () => he, Lt: () => de, Q9: () => ce, qf: () => j, hV: () => qe, z$: () => $t, J0: () => Y, De: () => yt, $C: () => U, al: () => Te, _W: () => ye, Gv: () => Oe, m: () => Ue, tz: () => Ce, Nu: () => Ke, zg: () => je, vp: () => Ve, vU: () => l, wF: () => xe, rv: () => We, Nh: () => Ne, ss: () => Xe, qW: () => Ge, QL: () => Ie, cf: () => Ye, eM: () => Le, Yd: () => r, Tk: () => m, iM: () => ae, qy: () => A, ce: () => ht, sK: () => h, Ok: () => v, q5: () => Qe, g: () => qt, xl: () => Re, I: () => ke, bx: () => J, dD: () => Be, Ib: () => _, Az: () => C, Iw: () => k, qY: () => X, db: () => le, mR: () => B, Tn: () => $, rV: () => Fe, gh: () => Me, Mi: () => we, j: () => be, YB: () => Pe, Yt: () => De, i5: () => Ae, x_: () => F, Am: () => Z, eR: () => ue, r8: () => Ee, u3: () => Je, vd: () => me, iV: () => Se, jZ: () => pe, SW: () => fe, ZH: () => ve, Ni: () => Ze, lh: () => ge, ZP: () => _e, bq: () => oe, $f: () => et, eu: () => ze, Ax: () => St, Mc: () => pt }); class r { static GetStackTrace() { const e = new Error(); let t = "No Stack Available for this browser"; return e.stack && (t = e.stack.toString().replace(/Error/g, "")), t; } static SetLoggerVerbosity(e) { this.verboseLogLevel != null && (this.verboseLogLevel = e); } static Log(e, t, s) { if (s > this.verboseLogLevel) return; const n = `Level: Log Msg: ${t} Caller: ${e}`; } static Info(e, t, s) { if (s > this.verboseLogLevel) return; const n = `Level: Info Msg: ${t}`; console.info(n); } static Error(e, t) { const s = `Level: Error Msg: ${t} Caller: ${e}`; } static Warning(e, t) { const s = `Level: Warning Caller: ${e} Msg: ${t}`; } } r.verboseLogLevel = 5, (function(a) { a.LIST_STREAMERS = "listStreamers", a.SUBSCRIBE = "subscribe", a.UNSUBSCRIBE = "unsubscribe", a.ICE_CANDIDATE = "iceCandidate", a.OFFER = "offer", a.ANSWER = "answer", a.DATACHANNELREQUEST = "dataChannelRequest", a.SFURECVDATACHANNELREADY = "peerDataChannelsReady", a.PONG = "pong"; })(R || (R = {})); class A { sendFilter(e, t) { return t; } payload() { return r.Log(r.GetStackTrace(), `Sending => ` + JSON.stringify(this, this.sendFilter, 4), 6), JSON.stringify(this, this.sendFilter); } } class st extends A { constructor() { super(), this.type = R.LIST_STREAMERS; } } class nt extends A { constructor(e) { super(), this.type = R.SUBSCRIBE, this.streamerId = e; } } class rt extends A { constructor() { super(), this.type = R.UNSUBSCRIBE; } } class it extends A { constructor(e) { super(), this.type = R.PONG, this.time = e; } } class at extends A { constructor(e, t) { super(), this.type = R.OFFER, this.minBitrate = 0, this.maxBitrate = 0, e && (this.type = e.type, this.sdp = e.sdp, this.minBitrate = t.minBitrateBps, this.maxBitrate = t.maxBitrateBps); } sendFilter(e, t) { if (e != "minBitrate" && e != "maxBitrate" || !(t <= 0)) return t; } } class ot extends A { constructor(e, t) { super(), this.type = R.ANSWER, this.minBitrate = 0, this.maxBitrate = 0, e && (this.type = e.type, this.sdp = e.sdp, this.minBitrate = t.minBitrateBps, this.maxBitrate = t.maxBitrateBps); } sendFilter(e, t) { if (e != "minBitrate" && e != "maxBitrate" || !(t <= 0)) return t; } } class lt extends A { constructor() { super(), this.type = R.DATACHANNELREQUEST; } } class dt extends A { constructor() { super(), this.type = R.SFURECVDATACHANNELREADY; } } class ct { constructor(e) { this.type = R.ICE_CANDIDATE, this.candidate = e; } payload() { return r.Log(r.GetStackTrace(), `Sending => ` + JSON.stringify(this, void 0, 4), 6), JSON.stringify(this); } } (function(a) { a.CONFIG = "config", a.STREAMER_LIST = "streamerList", a.STREAMER_ID_CHANGED = "streamerIDChanged", a.PLAYER_COUNT = "playerCount", a.OFFER = "offer", a.ANSWER = "answer", a.ICE_CANDIDATE = "iceCandidate", a.PEER_DATA_CHANNELS = "peerDataChannels", a.PING = "ping", a.WARNING = "warning"; })(T || (T = {})); class ae { } class ht extends ae { } class $ { constructor() { this.FromUEMessageHandlers = /* @__PURE__ */ new Map(); } addMessageHandler(e, t) { this.FromUEMessageHandlers.set(e, t); } handleMessage(e, t) { this.FromUEMessageHandlers.has(e) ? this.FromUEMessageHandlers.get(e)(t) : r.Error(r.GetStackTrace(), `Message type of ${e} does not have a message handler registered on the frontend - ignoring message.`); } static setupDefaultHandlers(e) { e.signallingProtocol.addMessageHandler(T.PING, ((t) => { const s = new it((/* @__PURE__ */ new Date()).getTime()).payload(); r.Log(r.GetStackTrace(), T.PING + ": " + t, 6), e.webSocket.send(s); })), e.signallingProtocol.addMessageHandler(T.CONFIG, ((t) => { r.Log(r.GetStackTrace(), T.CONFIG, 6); const s = JSON.parse(t); e.onConfig(s); })), e.signallingProtocol.addMessageHandler(T.STREAMER_LIST, ((t) => { r.Log(r.GetStackTrace(), T.STREAMER_LIST, 6); const s = JSON.parse(t); e.onStreamerList(s); })), e.signallingProtocol.addMessageHandler(T.STREAMER_ID_CHANGED, ((t) => { r.Log(r.GetStackTrace(), T.STREAMER_ID_CHANGED, 6); const s = JSON.parse(t); e.onStreamerIDChanged(s); })), e.signallingProtocol.addMessageHandler(T.PLAYER_COUNT, ((t) => { r.Log(r.GetStackTrace(), T.PLAYER_COUNT, 6); const s = JSON.parse(t); r.Log(r.GetStackTrace(), "Player Count: " + s.count, 6), e.onPlayerCount(s); })), e.signallingProtocol.addMessageHandler(T.ANSWER, ((t) => { r.Log(r.GetStackTrace(), T.ANSWER, 6); const s = JSON.parse(t); e.onWebRtcAnswer(s); })), e.signallingProtocol.addMessageHandler(T.OFFER, ((t) => { r.Log(r.GetStackTrace(), T.OFFER, 6); const s = JSON.parse(t); e.onWebRtcOffer(s); })), e.signallingProtocol.addMessageHandler(T.ICE_CANDIDATE, ((t) => { r.Log(r.GetStackTrace(), T.ICE_CANDIDATE, 6); const s = JSON.parse(t); e.onIceCandidate(s.candidate); })), e.signallingProtocol.addMessageHandler(T.WARNING, ((t) => { r.Warning(r.GetStackTrace(), `Warning received: ${t}`); })), e.signallingProtocol.addMessageHandler(T.PEER_DATA_CHANNELS, ((t) => { r.Log(r.GetStackTrace(), T.PEER_DATA_CHANNELS, 6); const s = JSON.parse(t); e.onWebRtcPeerDataChannels(s); })); } } class oe { constructor() { this.WS_OPEN_STATE = 1, this.onOpen = new EventTarget(), this.onClose = new EventTarget(), this.signallingProtocol = new $(), $.setupDefaultHandlers(this); } connect(e) { r.Log(r.GetStackTrace(), e, 6); try { return this.webSocket = new WebSocket(e), this.webSocket.onopen = (t) => this.handleOnOpen(t), this.webSocket.onerror = () => this.handleOnError(), this.webSocket.onclose = (t) => this.handleOnClose(t), this.webSocket.onmessage = (t) => this.handleOnMessage(t), this.webSocket.onmessagebinary = (t) => this.handleOnMessageBinary(t), !0; } catch (t) { return r.Error(t, t), !1; } } handleOnMessageBinary(e) { e && e.data && e.data.text().then(((t) => { const s = new MessageEvent("messageFromBinary", { data: t }); this.handleOnMessage(s); })).catch(((t) => { r.Error(r.GetStackTrace(), `Failed to parse binary blob from websocket, reason: ${t}`); })); } handleOnMessage(e) { if (e.data && e.data instanceof Blob) return void this.handleOnMessageBinary(e); const t = JSON.parse(e.data); r.Log(r.GetStackTrace(), `received => ` + JSON.stringify(JSON.parse(e.data), void 0, 4), 6), this.signallingProtocol.handleMessage(t.type, e.data); } handleOnOpen(e) { r.Log(r.GetStackTrace(), "Connected to the signalling server via WebSocket", 6), this.onOpen.dispatchEvent(new Event("open")); } handleOnError() { r.Error(r.GetStackTrace(), "WebSocket error"); } handleOnClose(e) { r.Log(r.GetStackTrace(), "Disconnected to the signalling server via WebSocket: " + JSON.stringify(e.code) + " - " + e.reason), this.onClose.dispatchEvent(new CustomEvent("close", { detail: e })); } requestStreamerList() { const e = new st(); this.webSocket.send(e.payload()); } sendSubscribe(e) { const t = new nt(e); this.webSocket.send(t.payload()); } sendUnsubscribe() { const e = new rt(); this.webSocket.send(e.payload()); } sendWebRtcOffer(e, t) { const s = new at(e, t); this.webSocket.send(s.payload()); } sendWebRtcAnswer(e, t) { const s = new ot(e, t); this.webSocket.send(s.payload()); } sendWebRtcDatachannelRequest() { const e = new lt(); this.webSocket.send(e.payload()); } sendSFURecvDataChannelReady() { const e = new dt(); this.webSocket.send(e.payload()); } sendIceCandidate(e) { if (r.Log(r.GetStackTrace(), "Sending Ice Candidate"), this.webSocket && this.webSocket.readyState === this.WS_OPEN_STATE) { const t = new ct(e); this.webSocket.send(t.payload()); } } close() { var e; (e = this.webSocket) === null || e === void 0 || e.close(); } onConfig(e) { } onStreamerList(e) { } onStreamerIDChanged(e) { } onIceCandidate(e) { } onWebRtcAnswer(e) { } onWebRtcOffer(e) { } onWebRtcPeerDataChannels(e) { } onPlayerCount(e) { } } class ut { constructor(e) { this.videoElementProvider = e, this.audioElement = document.createElement("Audio"), this.videoElementProvider.setAudioElement(this.audioElement); } handleOnTrack(e) { if (r.Log(r.GetStackTrace(), "handleOnTrack " + JSON.stringify(e.streams), 6), e.track.id == "probator") return; const t = this.videoElementProvider.getVideoElement(); if (e.track && r.Log(r.GetStackTrace(), "Got track - " + e.track.kind + " id=" + e.track.id + " readyState=" + e.track.readyState, 6), e.track.kind != "audio") return e.track.kind == "video" && t.srcObject !== e.streams[0] ? (t.srcObject = e.streams[0], void r.Log(r.GetStackTrace(), "Set video source from video track ontrack.")) : void 0; this.CreateAudioTrack(e.streams[0]); } CreateAudioTrack(e) { const t = this.videoElementProvider.getVideoElement(); t.srcObject != e && t.srcObject && t.srcObject !== e && (this.audioElement.srcObject = e, r.Log(r.GetStackTrace(), "Created new audio element to play separate audio stream.")); } } class gt { constructor(e) { this.freezeFrameHeight = 0, this.freezeFrameWidth = 0, this.rootDiv = e, this.rootElement = document.createElement("div"), this.rootElement.id = "freezeFrame", this.rootElement.style.display = "none", this.rootElement.style.pointerEvents = "none", this.rootElement.style.position = "absolute", this.rootElement.style.zIndex = "20", this.imageElement = document.createElement("img"), this.imageElement.style.position = "absolute", this.rootElement.appendChild(this.imageElement), this.rootDiv.appendChild(this.rootElement); } setElementForShow() { this.rootElement.style.display = "block"; } setElementForHide() { this.rootElement.style.display = "none"; } updateImageElementSource(e) { const t = btoa(e.reduce(((s, n) => s + String.fromCharCode(n)), "")); this.imageElement.src = "data:image/jpeg;base64," + t; } setDimensionsFromElementAndResize() { this.freezeFrameHeight = this.imageElement.naturalHeight, this.freezeFrameWidth = this.imageElement.naturalWidth, this.resize(); } resize() { if (this.freezeFrameWidth !== 0 && this.freezeFrameHeight !== 0) { let e = 0, t = 0, s = 0, n = 0; const i = this.rootDiv.clientWidth / this.rootDiv.clientHeight, o = this.freezeFrameWidth / this.freezeFrameHeight; i < o ? (e = this.rootDiv.clientWidth, t = Math.floor(this.rootDiv.clientWidth / o), s = Math.floor(0.5 * (this.rootDiv.clientHeight - t)), n = 0) : (e = Math.floor(this.rootDiv.clientHeight * o), t = this.rootDiv.clientHeight, s = 0, n = Math.floor(0.5 * (this.rootDiv.clientWidth - e))), this.rootElement.style.width = this.rootDiv.offsetWidth + "px", this.rootElement.style.height = this.rootDiv.offsetHeight + "px", this.rootElement.style.left = "0px", this.rootElement.style.top = "0px", this.imageElement.style.width = e + "px", this.imageElement.style.height = t + "px", this.imageElement.style.left = n + "px", this.imageElement.style.top = s + "px"; } } } class mt { constructor(e) { this.receiving = !1, this.size = 0, this.jpeg = void 0, this.valid = !1, this.freezeFrameDelay = 50, this.freezeFrame = new gt(e); } showFreezeFrame() { this.valid && this.freezeFrame.setElementForShow(); } hideFreezeFrame() { this.valid = !1, this.freezeFrame.setElementForHide(); } updateFreezeFrameAndShow(e, t) { this.freezeFrame.updateImageElementSource(e), this.freezeFrame.imageElement.onload = () => { this.freezeFrame.setDimensionsFromElementAndResize(), t(); }; } processFreezeFrameMessage(e, t) { this.receiving || (this.receiving = !0, this.valid = !1, this.size = 0, this.jpeg = void 0), this.size = new DataView(e.slice(1, 5).buffer).getInt32(0, !0); const s = e.slice(5); if (this.jpeg) { const n = new Uint8Array(this.jpeg.length + s.length); n.set(this.jpeg, 0), n.set(s, this.jpeg.length), this.jpeg = n; } else this.jpeg = s, this.receiving = !0, r.Log(r.GetStackTrace(), `received first chunk of freeze frame: ${this.jpeg.length}/${this.size}`, 6); this.jpeg.length === this.size ? (this.receiving = !1, this.valid = !0, r.Log(r.GetStackTrace(), `received complete freeze frame ${this.size}`, 6), this.updateFreezeFrameAndShow(this.jpeg, t)) : this.jpeg.length > this.size && (r.Error(r.GetStackTrace(), `received bigger freeze frame than advertised: ${this.jpeg.length}/${this.size}`), this.jpeg = void 0, this.receiving = !1); } } class _ { constructor(e, t, s, n, i = (() => { })) { this.onChange = i, this.onChangeEmit = () => { }, this.id = e, this.description = s, this.label = t, this.value = n; } set label(e) { this._label = e, this.onChangeEmit(this._value); } get label() { return this._label; } get value() { return this._value; } set value(e) { this._value = e, this.onChange(this._value, this), this.onChangeEmit(this._value); } } class C extends _ { constructor(e, t, s, n, i, o = (() => { })) { super(e, t, s, n, o); const d = new URLSearchParams(window.location.search); if (i && d.has(this.id)) { const c = this.getUrlParamFlag(); this.flag = c; } else this.flag = n; this.useUrlParams = i; } getUrlParamFlag() { const e = new URLSearchParams(window.location.search); return !!e.has(this.id) && e.get(this.id) !== "false" && e.get(this.id) !== "False"; } updateURLParams() { if (this.useUrlParams) { const e = new URLSearchParams(window.location.search); this.flag === !0 ? e.set(this.id, "true") : e.set(this.id, "false"), window.history.replaceState({}, "", e.toString() !== "" ? `${location.pathname}?${e}` : `${location.pathname}`); } } enable() { this.flag = !0; } get flag() { return !!this.value; } set flag(e) { this.value = e; } } class k extends _ { constructor(e, t, s, n, i, o, d, c = (() => { })) { super(e, t, s, o, c), this._min = n, this._max = i; const p = new URLSearchParams(window.location.search); if (d && p.has(this.id)) { const g = Number.parseFloat(p.get(this.id)); this.number = Number.isNaN(g) ? o : g; } else this.number = o; this.useUrlParams = d; } updateURLParams() { if (this.useUrlParams) { const e = new URLSearchParams(window.location.search); e.set(this.id, this.number.toString()), window.history.replaceState({}, "", e.toString() !== "" ? `${location.pathname}?${e}` : `${location.pathname}`); } } set number(e) { this.value = this.clamp(e); } get number() { return this.value; } clamp(e) { return this._min == null && this._max == null ? e : this._min == null ? Math.min(this._max, e) : this._max == null ? Math.max(this._min, e) : Math.max(Math.min(this._max, e), this._min); } get min() { return this._min; } get max() { return this._max; } addOnChangedListener(e) { this.onChange = e; } } class le extends _ { constructor(e, t, s, n, i, o = (() => { })) { super(e, t, s, n, o); const d = new URLSearchParams(window.location.search); if (i && d.has(this.id)) { const c = this.getUrlParamText(); this.text = c; } else this.text = n; this.useUrlParams = i; } getUrlParamText() { var e; const t = new URLSearchParams(window.location.search); return t.has(this.id) && (e = t.get(this.id)) !== null && e !== void 0 ? e : ""; } updateURLParams() { if (this.useUrlParams) { const e = new URLSearchParams(window.location.search); e.set(this.id, this.text), window.history.replaceState({}, "", e.toString() !== "" ? `${location.pathname}?${e}` : `${location.pathname}`); } } get text() { return this.value; } set text(e) { this.value = e; } } class X extends _ { constructor(e, t, s, n, i, o, d = (() => { })) { super(e, t, s, n, d), this.options = i; const c = new URLSearchParams(window.location.search), p = o && c.has(this.id) ? this.getUrlParamText() : n; this.selected = p, this.useUrlParams = o; } getUrlParamText() { var e; const t = new URLSearchParams(window.location.search); return t.has(this.id) && (e = t.get(this.id)) !== null && e !== void 0 ? e : ""; } updateURLParams() { if (this.useUrlParams) { const e = new URLSearchParams(window.location.search); e.set(this.id, this.selected), window.history.replaceState({}, "", e.toString() !== "" ? `${location.pathname}?${e}` : `${location.pathname}`); } } addOnChangedListener(e) { this.onChange = e; } get options() { return this._options; } set options(e) { this._options = e, this.onChangeEmit(this.selected); } get selected() { return this.value; } set selected(e) { let t = this.options.filter(((s) => s.indexOf(e) !== -1)); t.length ? this.value = t[0] : (t = this.options.filter(((s) => s.indexOf(e.split(" ")[0]) !== -1)), t.length && (this.value = t[0])); } } class de extends Event { constructor(e) { super("afkWarningActivate"), this.data = e; } } class j extends Event { constructor(e) { super("afkWarningUpdate"), this.data = e; } } class ce extends Event { constructor() { super("afkWarningDeactivate"); } } class he extends Event { constructor() { super("afkTimedOut"); } } class ue extends Event { constructor(e) { super("videoEncoderAvgQP"), this.data = e; } } class ge extends Event { constructor() { super("webRtcSdp"); } } class me extends Event { constructor() { super("webRtcAutoConnect"); } } class pe extends Event { constructor() { super("webRtcConnecting"); } } class Se extends Event { constructor() { super("webRtcConnected"); } } class ve extends Event { constructor() { super("webRtcFailed"); } } class fe extends Event { constructor(e) { super("webRtcDisconnected"), this.data = e; } } class Ce extends Event { constructor(e) { super("dataChannelOpen"), this.data = e; } } class Te extends Event { constructor(e) { super("dataChannelClose"), this.data = e; } } class ye extends Event { constructor(e) { super("dataChannelError"), this.data = e; } } class Ee extends Event { constructor() { super("videoInitialized"); } } class Me extends Event { constructor() { super("streamLoading"); } } class we extends Event { constructor() { super("streamConnect"); } } class be extends Event { constructor() { super("streamDisconnect"); } } class Pe extends Event { constructor() { super("streamReconnect"); } } class Re extends Event { constructor(e) { super("playStreamError"), this.data = e; } } class ke extends Event { constructor() { super("playStream"); } } class J extends Event { constructor(e) { super("playStreamRejected"), this.data = e; } } class Le extends Event { constructor(e) { super("loadFreezeFrame"), this.data = e; } } class xe extends Event { constructor() { super("hideFreezeFrame"); } } class Fe extends Event { constructor(e) { super("statsReceived"), this.data = e; } } class Ae extends Event { constructor(e) { super("streamerListMessage"), this.data = e; } } class De extends Event { constructor(e) { super("StreamerIDChangedMessage"), this.data = e; } } class Ie extends Event { constructor(e) { super("latencyTestResult"), this.data = e; } } class Oe extends Event { constructor(e) { super("dataChannelLatencyTestResponse"), this.data = e; } } class Ue extends Event { constructor(e) { super("dataChannelLatencyTestResult"), this.data = e; } } class Ge extends Event { constructor(e) { super("initialSettings"), this.data = e; } } class B extends Event { constructor(e) { super("settingsChanged"), this.data = e; } } class pt extends Event { constructor() { super("xrSessionStarted"); } } class St extends Event { constructor() { super("xrSessionEnded"); } } class ze extends Event { constructor(e) { super("xrFrame"), this.data = e; } } class Be extends Event { constructor(e) { super("playerCount"), this.data = e; } } class _e extends Event { constructor() { super("webRtcTCPRelayDetected"); } } class Ve extends EventTarget { dispatchEvent(e) { return super.dispatchEvent(e); } addEventListener(e, t) { super.addEventListener(e, t); } removeEventListener(e, t) { super.removeEventListener(e, t); } } class l { } l.AutoConnect = "AutoConnect", l.AutoPlayVideo = "AutoPlayVideo", l.AFKDetection = "TimeoutIfIdle", l.BrowserSendOffer = "OfferToReceive", l.HoveringMouseMode = "HoveringMouse", l.ForceMonoAudio = "ForceMonoAudio", l.ForceTURN = "ForceTURN", l.FakeMouseWithTouches = "FakeMouseWithTouches", l.IsQualityController = "ControlsQuality", l.MatchViewportResolution = "MatchViewportRes", l.StartVideoMuted = "StartVideoMuted", l.SuppressBrowserKeys = "SuppressBrowserKeys", l.UseMic = "UseMic", l.KeyboardInput = "KeyboardInput", l.MouseInput = "MouseInput", l.TouchInput = "TouchInput", l.GamepadInput = "GamepadInput", l.XRControllerInput = "XRControllerInput", l.WaitForStreamer = "WaitForStreamer", l.HideUI = "HideUI"; const vt = (a) => Object.getOwnPropertyNames(l).some(((e) => l[e] === a)); class h { } h.AFKTimeoutSecs = "AFKTimeout", h.AFKCountdownSecs = "AFKCountdown", h.MinQP = "MinQP", h.MaxQP = "MaxQP", h.WebRTCFPS = "WebRTCFPS", h.WebRTCMinBitrate = "WebRTCMinBitrate", h.WebRTCMaxBitrate = "WebRTCMaxBitrate", h.MaxReconnectAttempts = "MaxReconnectAttempts", h.StreamerAutoJoinInterval = "StreamerAutoJoinInterval"; const ft = (a) => Object.getOwnPropertyNames(h).some(((e) => h[e] === a)); class F { } F.SignallingServerUrl = "ss"; const Ct = (a) => Object.getOwnPropertyNames(F).some(((e) => F[e] === a)); class v { } v.PreferredCodec = "PreferredCodec", v.StreamerId = "StreamerId"; const Tt = (a) => Object.getOwnPropertyNames(v).some(((e) => v[e] === a)); class yt { constructor(e = {}) { this.flags = /* @__PURE__ */ new Map(), this.numericParameters = /* @__PURE__ */ new Map(), this.textParameters = /* @__PURE__ */ new Map(), this.optionParameters = /* @__PURE__ */ new Map(); const { initialSettings: t, useUrlParams: s } = e; this._useUrlParams = !!s, this.populateDefaultSettings(this._useUrlParams, t); } get useUrlParams() { return this._useUrlParams; } populateDefaultSettings(e, t) { this.textParameters.set(F.SignallingServerUrl, new le(F.SignallingServerUrl, "Signalling url", "Url of the signalling server", t && t.hasOwnProperty(F.SignallingServerUrl) ? t[F.SignallingServerUrl] : (location.protocol === "https:" ? "wss://" : "ws://") + window.location.hostname + (window.location.port === "80" || window.location.port === "" ? "" : `:${window.location.port}`), e)), this.optionParameters.set(v.StreamerId, new X(v.StreamerId, "Streamer ID", "The ID of the streamer to stream.", t && t.hasOwnProperty(v.StreamerId) ? t[v.StreamerId] : "", [], e)), this.optionParameters.set(v.PreferredCodec, new X(v.PreferredCodec, "Preferred Codec", "The preferred codec to be used during codec negotiation", "H264 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", t && t.hasOwnProperty(v.PreferredCodec) ? [t[v.PreferredCodec]] : (function() { const s = []; if (!RTCRtpReceiver.getCapabilities) return s.push("Only available on Chrome"), s; const n = /(VP\d|H26\d|AV1).*/; return RTCRtpReceiver.getCapabilities("video").codecs.forEach(((i) => { const o = i.mimeType.split("/")[1] + " " + (i.sdpFmtpLine || ""); n.exec(o) !== null && s.push(o); })), s; })(), e)), this.flags.set(l.AutoConnect, new C(l.AutoConnect, "Auto connect to stream", "Whether we should attempt to auto connect to the signalling server or show a click to start prompt.", !(!t || !t.hasOwnProperty(l.AutoConnect)) && t[l.AutoConnect], e)), this.flags.set(l.AutoPlayVideo, new C(l.AutoPlayVideo, "Auto play video", "When video is ready automatically start playing it as opposed to showing a play button.", !t || !t.hasOwnProperty(l.AutoPlayVideo) || t[l.AutoPlayVideo], e)), this.flags.set(l.BrowserSendOffer, new C(l.BrowserSendOffer, "Browser send offer", "Browser will initiate the WebRTC handshake by sending the offer to the streamer", !(!t || !t.hasOwnProperty(l.BrowserSendOffer)) && t[l.BrowserSendOffer], e)), this.flags.set(l.UseMic, new C(l.UseMic, "Use microphone", "Make browser request microphone access and open an input audio track.", !(!t || !t.hasOwnProperty(l.UseMic)) && t[l.UseMic], e)), this.flags.set(l.StartVideoMuted, new C(l.StartVideoMuted, "Start video muted", "Video will start muted if true.", !(!t || !t.hasOwnProperty(l.StartVideoMuted)) && t[l.StartVideoMuted], e)), this.flags.set(l.SuppressBrowserKeys, new C(l.SuppressBrowserKeys, "Suppress browser keys", "Suppress certain browser keys that we use in UE, for example F5 to show shader complexity instead of refresh the page.", !t || !t.hasOwnProperty(l.SuppressBrowserKeys) || t[l.SuppressBrowserKeys], e)), this.flags.set(l.IsQualityController, new C(l.IsQualityController, "Is quality controller?", "True if this peer controls stream quality", !t || !t.hasOwnProperty(l.IsQualityController) || t[l.IsQualityController], e)), this.flags.set(l.ForceMonoAudio, new C(l.ForceMonoAudio, "Force mono audio", "Force browser to request mono audio in the SDP", !(!t || !t.hasOwnProperty(l.ForceMonoAudio)) && t[l.ForceMonoAudio], e)), this.flags.set(l.ForceTURN, new C(l.ForceTURN, "Force TURN", "Only generate TURN/Relayed ICE candidates.", !(!t || !t.hasOwnProperty(l.ForceTURN)) && t[l.ForceTURN], e)), this.flags.set(l.AFKDetection, new C(l.AFKDetection, "AFK if idle", "Timeout the experience if user is AFK for a period.", !(!t || !t.hasOwnProperty(l.AFKDetection)) && t[l.AFKDetection], e)), this.flags.set(l.MatchViewportResolution, new C(l.MatchViewportResolution, "Match viewport resolution", "Pixel Streaming will be instructed to dynamically resize the video stream to match the size of the video element.", !(!t || !t.hasOwnProperty(l.MatchViewportResolution)) && t[l.MatchViewportResolution], e)), this.flags.set(l.HoveringMouseMode, new C(l.HoveringMouseMode, "Control Scheme: Locked Mouse", "Either locked mouse, where the pointer is consumed by the video and locked to it, or hovering mouse, where the mouse is not consumed.", !(!t || !t.hasOwnProperty(l.HoveringMouseMode)) && t[l.HoveringMouseMode], e, ((s, n) => { n.label = `Control Scheme: ${s ? "Hovering" : "Locked"} Mouse`; }))), this.flags.set(l.FakeMouseWithTouches, new C(l.FakeMouseWithTouches, "Fake mouse with touches", "A single finger touch is converted into a mouse event. This allows a non-touch application to be controlled partially via a touch device.", !(!t || !t.hasOwnProperty(l.FakeMouseWithTouches)) && t[l.FakeMouseWithTouches], e)), this.flags.set(l.KeyboardInput, new C(l.KeyboardInput, "Keyboard input", "If enabled, send keyboard events to streamer", !t || !t.hasOwnProperty(l.KeyboardInput) || t[l.KeyboardInput], e)), this.flags.set(l.MouseInput, new C(l.MouseInput, "Mouse input", "If enabled, send mouse events to streamer", !t || !t.hasOwnProperty(l.MouseInput) || t[l.MouseInput], e)), this.flags.set(l.TouchInput, new C(l.TouchInput, "Touch input", "If enabled, send touch events to streamer", !t || !t.hasOwnProperty(l.TouchInput) || t[l.TouchInput], e)), this.flags.set(l.GamepadInput, new C(l.GamepadInput, "Gamepad input", "If enabled, send gamepad events to streamer", !t || !t.hasOwnProperty(l.GamepadInput) || t[l.GamepadInput], e)), this.flags.set(l.XRControllerInput, new C(l.XRControllerInput, "XR controller input", "If enabled, send XR controller events to streamer", !t || !t.hasOwnProperty(l.XRControllerInput) || t[l.XRControllerInput], e)), this.flags.set(l.WaitForStreamer, new C(l.WaitForStreamer, "Wait for streamer", "Will continue trying to connect to the first streamer available.", !t || !t.hasOwnProperty(l.WaitForStreamer) || t[l.WaitForStreamer], e)), this.flags.set(l.HideUI, new C(l.HideUI, "Hide the UI overlay", "Will hide all UI overlay details", !(!t || !t.hasOwnProperty(l.HideUI)) && t[l.HideUI], e)), this.numericParameters.set(h.AFKTimeoutSecs, new k(h.AFKTimeoutSecs, "AFK timeout", "The time (in seconds) it takes for the application to time out if AFK timeout is enabled.", 0, null, t && t.hasOwnProperty(h.AFKTimeoutSecs) ? t[h.AFKTimeoutSecs] : 120, e)), this.numericParameters.set(h.AFKCountdownSecs, new k(h.AFKCountdownSecs, "AFK countdown", "The time (in seconds) for a user to respond before the stream is ended after an AFK timeout.", 10, null, 10, e)), this.numericParameters.set(h.MaxReconnectAttempts, new k(h.MaxReconnectAttempts, "Max Reconnects", "Maximum number of reconnects the application will attempt when a streamer disconnects.", 0, 999, t && t.hasOwnProperty(h.MaxReconnectAttempts) ? t[h.MaxReconnectAttempts] : 3, e)), this.numericParameters.set(h.MinQP, new k(h.MinQP, "Min QP", "The lower bound for the quantization parameter (QP) of the encoder. 0 = Best quality, 51 = worst quality.", 0, 51, t && t.hasOwnProperty(h.MinQP) ? t[h.MinQP] : 0, e)), this.numericParameters.set(h.MaxQP, new k(h.MaxQP, "Max QP", "The upper bound for the quantization parameter (QP) of the encoder. 0 = Best quality, 51 = worst quality.", 0, 51, t && t.hasOwnProperty(h.MaxQP) ? t[h.MaxQP] : 51, e)), this.numericParameters.set(h.WebRTCFPS, new k(h.WebRTCFPS, "Max FPS", "The maximum FPS that WebRTC will try to transmit frames at.", 1, 999, t && t.hasOwnProperty(h.WebRTCFPS) ? t[h.WebRTCFPS] : 60, e)), this.numericParameters.set(h.WebRTCMinBitrate, new k(h.WebRTCMinBitrate, "Min Bitrate (kbps)", "The minimum bitrate that WebRTC should use.", 0, 5e5, t && t.hasOwnProperty(h.WebRTCMinBitrate) ? t[h.WebRTCMinBitrate] : 0, e)), this.numericParameters.set(h.WebRTCMaxBitrate, new k(h.WebRTCMaxBitrate, "Max Bitrate (kbps)", "The maximum bitrate that WebRTC should use.", 0, 5e5, t && t.hasOwnProperty(h.WebRTCMaxBitrate) ? t[h.WebRTCMaxBitrate] : 0, e)), this.numericParameters.set(h.StreamerAutoJoinInterval, new k(h.StreamerAutoJoinInterval, "Streamer Auto Join Interval (ms)", "Delay between retries when waiting for an available streamer.", 500, 9e5, t && t.hasOwnProperty(h.StreamerAutoJoinInterval) ? t[h.StreamerAutoJoinInterval] : 3e3, e)); } _addOnNumericSettingChangedListener(e, t) { this.numericParameters.has(e) && this.numericParameters.get(e).addOnChangedListener(t); } _addOnOptionSettingChangedListener(e, t) { this.optionParameters.has(e) && this.optionParameters.get(e).addOnChangedListener(t); } getNumericSettingValue(e) { if (this.numericParameters.has(e)) return this.numericParameters.get(e).number; throw new Error(`There is no numeric setting with the id of ${e}`); } getTextSettingValue(e) { if (this.textParameters.has(e)) return this.textParameters.get(e).value; throw new Error(`There is no numeric setting with the id of ${e}`); } setNumericSetting(e, t) { if (!this.numericParameters.has(e)) throw new Error(`There is no numeric setting with the id of ${e}`); this.numericParameters.get(e).number = t; } _addOnSettingChangedListener(e, t) { this.flags.has(e) && (this.flags.get(e).onChange = t); } _addOnTextSettingChangedListener(e, t) { this.textParameters.has(e) && (this.textParameters.get(e).onChange = t); } getSettingOption(e) { return this.optionParameters.get(e); } isFlagEnabled(e) { return this.flags.get(e).flag; } setFlagEnabled(e, t) { this.flags.has(e) ? this.flags.get(e).flag = t : r.Warning(r.GetStackTrace(), `Cannot toggle flag called ${e} - it does not exist in the Config.flags map.`); } setTextSetting(e, t) { this.textParameters.has(e) ? this.textParameters.get(e).text = t : r.Warning(r.GetStackTrace(), `Cannot set text setting called ${e} - it does not exist in the Config.textParameters map.`); } setOptionSettingOptions(e, t) { this.optionParameters.has(e) ? this.optionParameters.get(e).options = t : r.Warning(r.GetStackTrace(), `Cannot set text setting called ${e} - it does not exist in the Config.optionParameters map.`); } setOptionSettingValue(e, t) { if (this.optionParameters.has(e)) { const s = this.optionParameters.get(e), n = s.options; n.includes(t) || (n.push(t), s.options = n), s.selected = t; } else r.Warning(r.GetStackTrace(), `Cannot set text setting called ${e} - it does not exist in the Config.enumParameters map.`); } setFlagLabel(e, t) { this.flags.has(e) ? this.flags.get(e).label = t : r.Warning(r.GetStackTrace(), `Cannot set label for flag called ${e} - it does not exist in the Config.flags map.`); } setSettings(e) { for (const t of Object.keys(e)) vt(t) ? this.setFlagEnabled(t, e[t]) : ft(t) ? this.setNumericSetting(t, e[t]) : Ct(t) ? this.setTextSetting(t, e[t]) : Tt(t) && this.setOptionSettingValue(t, e[t]); } getSettings() { const e = {}; for (const [t, s] of this.flags.entries()) e[t] = s.flag; for (const [t, s] of this.numericParameters.entries()) e[t] = s.number; for (cons