From 15fd04873a0b54b9a9c6499831ed00b2a494bced Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 17:00:54 +0000 Subject: [PATCH 01/33] refactored, simplified, more odoo --- mail_livekit/README.md | 65 +++++ mail_livekit/__init__.py | 1 + mail_livekit/__manifest__.py | 31 +++ mail_livekit/models/__init__.py | 2 + mail_livekit/models/mail_rtc_session.py | 98 ++++++++ mail_livekit/models/res_config_settings.py | 23 ++ mail_livekit/static/description/icon.png | Bin 0 -> 2030 bytes .../static/lib/livekit/livekit-client.umd.js | 2 + .../discuss/call_participant_video_patch.js | 74 ++++++ .../static/src/discuss/livekit_adapter.js | 114 +++++++++ .../static/src/discuss/livekit_service.js | 232 ++++++++++++++++++ .../static/src/discuss/rtc_livekit_patch.js | 210 ++++++++++++++++ .../src/discuss/thread_actions_patch.js | 19 ++ mail_livekit/streamIssue.md | 38 +++ .../views/livekit_assets_templates.xml | 66 +++++ .../views/res_config_settings_views.xml | 81 ++++++ requirements.txt | 1 + 17 files changed, 1057 insertions(+) create mode 100644 mail_livekit/README.md create mode 100644 mail_livekit/__init__.py create mode 100644 mail_livekit/__manifest__.py create mode 100644 mail_livekit/models/__init__.py create mode 100644 mail_livekit/models/mail_rtc_session.py create mode 100644 mail_livekit/models/res_config_settings.py create mode 100644 mail_livekit/static/description/icon.png create mode 100644 mail_livekit/static/lib/livekit/livekit-client.umd.js create mode 100644 mail_livekit/static/src/discuss/call_participant_video_patch.js create mode 100644 mail_livekit/static/src/discuss/livekit_adapter.js create mode 100644 mail_livekit/static/src/discuss/livekit_service.js create mode 100644 mail_livekit/static/src/discuss/rtc_livekit_patch.js create mode 100644 mail_livekit/static/src/discuss/thread_actions_patch.js create mode 100644 mail_livekit/streamIssue.md create mode 100644 mail_livekit/views/livekit_assets_templates.xml create mode 100644 mail_livekit/views/res_config_settings_views.xml diff --git a/mail_livekit/README.md b/mail_livekit/README.md new file mode 100644 index 00000000..5a9b24da --- /dev/null +++ b/mail_livekit/README.md @@ -0,0 +1,65 @@ +# Discuss LiveKit Integration (Odoo 18) + +This addon integrates **LiveKit** as the media layer (audio/video/screen share) for +**Odoo Discuss calls**, while keeping Odoo’s **native call UI and semantics**. + +It is designed to be safe to install even when LiveKit is not configured. When livekit +has credentials and is enabled its assets will be added to the relevant pages. Upon +toggling livekit, it may be necessary to hard refresh the browser to ensure assets are +reloaded. + +## What it does + +- Replaces the underlying RTC media transport with **LiveKit Rooms**. +- Mirrors LiveKit participation into Odoo’s mail store as **synthetic RTC sessions**, so + the standard Discuss call UI renders normally. + +## Features + +- **Audio + video + group calls** via LiveKit. +- **Screen sharing** bridged into the standard UI. +- **Background blur** using LiveKit track processors (applies immediately). +- **Microphone input selection** (uses Odoo’s existing “Input device” setting and + hot-switches while in-call). +- **Multi-tab coordination** (host/follower model): only one tab publishes media for a + channel. +- **Reconnection handling**: maps LiveKit connection states into the native UI and + avoids excessive toasts. +- **Call invitations / ringing** semantics: triggers the stock incoming call UI/sound + when a call starts in non-channel threads. + +## Configuration + +### Settings UI + +Configure in **Settings → LiveKit Integration**: + +- Enable LiveKit +- LiveKit Server URL +- LiveKit API Key +- LiveKit API Secret + +### `ir.config_parameter` keys + +This addon reads the following configuration parameters: + +- `mail_livekit.livekit_enabled` (boolean) +- `mail_livekit.livekit_server_url` (string) +- `mail_livekit.livekit_api_key` (string) +- `mail_livekit.livekit_api_secret` (string) + +## Notes + +- **Public channels / guests** are supported. +- **Only microphone selection is implemented** (parity with the existing Odoo call + settings UI). Camera/speaker selection are intentionally not added. + +### Bundled vendor JS + +This repo includes a small bundling setup that produces a browser-ready vendor bundle: + +- Output: `static/lib/bundles/livekit_vendor_entry.js` +- Build: `npm install` then `npm run bundle:livekit` + +- If you upgrade LiveKit, upgrade both the client and processors together and test + reconnect + screen share paths. diff --git a/mail_livekit/__init__.py b/mail_livekit/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/mail_livekit/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/mail_livekit/__manifest__.py b/mail_livekit/__manifest__.py new file mode 100644 index 00000000..323d5b1b --- /dev/null +++ b/mail_livekit/__manifest__.py @@ -0,0 +1,31 @@ +{ + "name": "Discuss - Livekit Integration", + "summary": "Integrate LiveKit video conferencing with Odoo Discuss", + "version": "18.0.1.0.0", + "author": "Odoo Community Association (OCA), Solvti Sp. z o.o.", + "license": "LGPL-3", + "category": "Discuss", + "depends": ["mail"], + "website": "https://www.solvti.com", + "data": [ + "views/res_config_settings_views.xml", + "views/livekit_assets_templates.xml", + ], + "assets": { + "mail_livekit.assets_livekit": [ + "mail_livekit/static/lib/livekit/livekit-client.umd.js", + "mail_livekit/static/src/discuss/livekit_service.js", + "mail_livekit/static/src/discuss/livekit_adapter.js", + "mail_livekit/static/src/discuss/rtc_livekit_patch.js", + "mail_livekit/static/src/discuss/thread_actions_patch.js", + "mail_livekit/static/src/discuss/call_participant_video_patch.js", + ], + }, + "external_dependencies": { + "python": ["livekit-api"], + }, + "reusable": False, + "installable": True, + "application": False, + "auto_install": False, +} diff --git a/mail_livekit/models/__init__.py b/mail_livekit/models/__init__.py new file mode 100644 index 00000000..e8d7b781 --- /dev/null +++ b/mail_livekit/models/__init__.py @@ -0,0 +1,2 @@ +from . import res_config_settings +from . import mail_rtc_session diff --git a/mail_livekit/models/mail_rtc_session.py b/mail_livekit/models/mail_rtc_session.py new file mode 100644 index 00000000..966a38bd --- /dev/null +++ b/mail_livekit/models/mail_rtc_session.py @@ -0,0 +1,98 @@ +from livekit.api import AccessToken, VideoGrants + +from odoo import api, fields, models +from odoo.tools.misc import str2bool + +from odoo.addons.mail.tools.discuss import Store + + +class MailRtcSession(models.Model): + _inherit = "discuss.channel.rtc.session" + + livekit_token = fields.Char() + livekit_room_name = fields.Char() + livekit_url = fields.Char() + + @api.model_create_multi + def create(self, vals_list): + livekit_params = self._get_livekit_config_params() + + result = super().create(vals_list) + + if not livekit_params.get("valid"): + return + + for session in result: + session._generate_livekit_token(livekit_params) + + return result + + def _get_livekit_config_params(self): + icp = self.env["ir.config_parameter"].sudo() + raw_enabled = icp.get_param("mail_livekit.livekit_enabled", False) + livekit_enabled = str2bool( + raw_enabled if isinstance(raw_enabled, str) else "False" + ) + livekit_url = icp.get_param("mail_livekit.livekit_server_url") + api_key = icp.get_param("mail_livekit.livekit_api_key") + api_secret = icp.get_param("mail_livekit.livekit_api_secret") + + valid = ( + livekit_enabled + and isinstance(livekit_url, str) + and livekit_url.strip() + and isinstance(api_key, str) + and api_key.strip() + and isinstance(api_secret, str) + and api_secret.strip() + ) + + return { + "valid": valid, + "enabled": livekit_enabled, + "url": livekit_url, + "api_key": api_key, + "api_secret": api_secret, + } + + def _generate_livekit_token(self, livekit_params): + self.ensure_one() + room_name = f"odoo_channel_{self.channel_id.id}" + grants = VideoGrants( + room_join=True, + room=room_name, + can_publish=True, + can_subscribe=True, + ) + + name = ( + self.partner_id.name + if self.partner_id + else "Guest " + str(self.channel_member_id.id) + ) + + token = ( + AccessToken(livekit_params.get("api_key"), livekit_params.get("api_secret")) + .with_identity(str(self.id)) + .with_name(name) + .with_grants(grants) + .to_jwt() + ) + + self.livekit_token = token + self.livekit_room_name = room_name + self.livekit_url = livekit_params.get("url") + + def _to_store(self, store: Store, extra=False): + result = super()._to_store(store, extra) + for rtc_session in self: + if rtc_session.livekit_url: + store.add( + rtc_session, + { + "livekit_token": rtc_session.livekit_token, + "livekit_room_name": rtc_session.livekit_room_name, + "livekit_url": rtc_session.livekit_url, + }, + ) + return result diff --git a/mail_livekit/models/res_config_settings.py b/mail_livekit/models/res_config_settings.py new file mode 100644 index 00000000..699e0fbc --- /dev/null +++ b/mail_livekit/models/res_config_settings.py @@ -0,0 +1,23 @@ +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + livekit_enabled = fields.Boolean( + string="Enable LiveKit", + config_parameter="mail_livekit.livekit_enabled", + ) + + livekit_api_key = fields.Char( + string="LiveKit API Key", + config_parameter="mail_livekit.livekit_api_key", + ) + livekit_api_secret = fields.Char( + string="LiveKit API Secret", + config_parameter="mail_livekit.livekit_api_secret", + ) + livekit_server_url = fields.Char( + string="LiveKit Server URL", + config_parameter="mail_livekit.livekit_server_url", + ) diff --git a/mail_livekit/static/description/icon.png b/mail_livekit/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6e93b800484de97c1dc0d0bf369518583d10a2d1 GIT binary patch literal 2030 zcmeAS@N?(olHy`uVBq!ia0y~yU_1@N9Be?5G`q%D}Rbr9ojDgTN6XhNcK62Z2#ZA_Cz$^9R;7`Sa^69F!@%QoaZLt!Ei7;_ALhvQL9dbJoULW4Z z_q(EQ*Ua^7dXplGE^fQL`}fRLV6y&N^yByK_0t=^d#uj?a}R4|+D8*Q zbqdkbzjJSI+kfu36~p{@8+1((e,t,i)=>t in e?n(e,t,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[t]=i)(e,"symbol"!=typeof t?t+"":t,i);class o{constructor(){i(this,"_locking"),i(this,"_locks"),this._locking=Promise.resolve(),this._locks=0}isLocked(){return this._locks>0}lock(){let e;this._locks+=1;const t=new Promise((t=>e=()=>{this._locks-=1,t()})),n=this._locking.then((()=>e));return this._locking=this._locking.then((()=>t)),n}}function s(e,t){if(!e)throw new Error(t)}const r=34028234663852886e22,a=-34028234663852886e22,c=4294967295,d=2147483647,l=-2147483648;function u(e){if("number"!=typeof e)throw new Error("invalid int 32: "+typeof e);if(!Number.isInteger(e)||e>d||ec||e<0)throw new Error("invalid uint 32: "+e)}function p(e){if("number"!=typeof e)throw new Error("invalid float 32: "+typeof e);if(Number.isFinite(e)&&(e>r||e({no:t.no,name:t.name,localName:e[t.no]}))))}function f(e,t,n){const i=Object.create(null),o=Object.create(null),s=[];for(const e of t){const t=y(e);s.push(t),i[e.name]=t,o[e.no]=t}return{typeName:e,values:s,findName:e=>i[e],findNumber:e=>o[e]}}function k(e,t,n){const i={};for(const e of t){const t=y(e);i[t.localName]=t.no,i[t.no]=t.localName}return v(i,e,t),i}function y(e){return"localName"in e?e:Object.assign(Object.assign({},e),{localName:e.name})}class b{equals(e){return this.getType().runtime.util.equals(this.getType(),this,e)}clone(){return this.getType().runtime.util.clone(this)}fromBinary(e,t){const n=this.getType().runtime.bin,i=n.makeReadOptions(t);return n.readMessage(this,i.readerFactory(e),e.byteLength,i),this}fromJson(e,t){const n=this.getType(),i=n.runtime.json,o=i.makeReadOptions(t);return i.readMessage(n,e,o,this),this}fromJsonString(e,t){let n;try{n=JSON.parse(e)}catch(e){throw new Error("cannot decode ".concat(this.getType().typeName," from JSON: ").concat(e instanceof Error?e.message:String(e)))}return this.fromJson(n,t)}toBinary(e){const t=this.getType().runtime.bin,n=t.makeWriteOptions(e),i=n.writerFactory();return t.writeMessage(this,i,n),i.finish()}toJson(e){const t=this.getType().runtime.json,n=t.makeWriteOptions(e);return t.writeMessage(this,n)}toJsonString(e){var t;const n=this.toJson(e);return JSON.stringify(n,null,null!==(t=null==e?void 0:e.prettySpaces)&&void 0!==t?t:0)}toJSON(){return this.toJson({emitDefaultValues:!0})}getType(){return Object.getPrototypeOf(this).constructor}}function T(){let e=0,t=0;for(let n=0;n<28;n+=7){let i=this.buf[this.pos++];if(e|=(127&i)<>4,0==(128&n))return this.assertBounds(),[e,t];for(let n=3;n<=31;n+=7){let i=this.buf[this.pos++];if(t|=(127&i)<>>i,s=!(o>>>7==0&&0==t),r=255&(s?128|o:o);if(n.push(r),!s)return}const i=e>>>28&15|(7&t)<<4,o=!(t>>3==0);if(n.push(255&(o?128|i:i)),o){for(let e=3;e<31;e+=7){const i=t>>>e,o=!(i>>>7==0),s=255&(o?128|i:i);if(n.push(s),!o)return}n.push(t>>>31&1)}}const S=4294967296;function E(e){const t="-"===e[0];t&&(e=e.slice(1));const n=1e6;let i=0,o=0;function s(t,s){const r=Number(e.slice(t,s));o*=n,i=i*n+r,i>=S&&(o+=i/S|0,i%=S)}return s(-24,-18),s(-18,-12),s(-12,-6),s(-6),t?P(i,o):R(i,o)}function w(e,t){if(({lo:e,hi:t}=function(e,t){return{lo:e>>>0,hi:t>>>0}}(e,t)),t<=2097151)return String(S*t+e);const n=16777215&(e>>>24|t<<8),i=t>>16&65535;let o=(16777215&e)+6777216*n+6710656*i,s=n+8147497*i,r=2*i;const a=1e7;return o>=a&&(s+=Math.floor(o/a),o%=a),s>=a&&(r+=Math.floor(s/a),s%=a),r.toString()+I(s)+I(o)}function R(e,t){return{lo:0|e,hi:0|t}}function P(e,t){return t=~t,e?e=1+~e:t+=1,R(e,t)}const I=e=>{const t=String(e);return"0000000".slice(t.length)+t};function O(e,t){if(e>=0){for(;e>127;)t.push(127&e|128),e>>>=7;t.push(e)}else{for(let n=0;n<9;n++)t.push(127&e|128),e>>=7;t.push(1)}}function _(){let e=this.buf[this.pos++],t=127&e;if(0==(128&e))return this.assertBounds(),t;if(e=this.buf[this.pos++],t|=(127&e)<<7,0==(128&e))return this.assertBounds(),t;if(e=this.buf[this.pos++],t|=(127&e)<<14,0==(128&e))return this.assertBounds(),t;if(e=this.buf[this.pos++],t|=(127&e)<<21,0==(128&e))return this.assertBounds(),t;e=this.buf[this.pos++],t|=(15&e)<<28;for(let t=5;0!=(128&e)&&t<10;t++)e=this.buf[this.pos++];if(0!=(128&e))throw new Error("invalid varint");return this.assertBounds(),t>>>0}const D=function(){const e=new DataView(new ArrayBuffer(8));if("function"==typeof BigInt&&"function"==typeof e.getBigInt64&&"function"==typeof e.getBigUint64&&"function"==typeof e.setBigInt64&&"function"==typeof e.setBigUint64&&("object"!=typeof process||"object"!=typeof process.env||"1"!==process.env.BUF_BIGINT_DISABLE)){const t=BigInt("-9223372036854775808"),n=BigInt("9223372036854775807"),i=BigInt("0"),o=BigInt("18446744073709551615");return{zero:BigInt(0),supported:!0,parse(e){const i="bigint"==typeof e?e:BigInt(e);if(i>n||io||t(e.setInt32(0,t,!0),e.setInt32(4,n,!0),e.getBigInt64(0,!0)),uDec:(t,n)=>(e.setInt32(0,t,!0),e.setInt32(4,n,!0),e.getBigUint64(0,!0))}}const t=e=>s(/^-?[0-9]+$/.test(e),"int64 invalid: ".concat(e)),n=e=>s(/^[0-9]+$/.test(e),"uint64 invalid: ".concat(e));return{zero:"0",supported:!1,parse:e=>("string"!=typeof e&&(e=e.toString()),t(e),e),uParse:e=>("string"!=typeof e&&(e=e.toString()),n(e),e),enc:e=>("string"!=typeof e&&(e=e.toString()),t(e),E(e)),uEnc:e=>("string"!=typeof e&&(e=e.toString()),n(e),E(e)),dec:(e,t)=>function(e,t){let n=R(e,t);const i=2147483648&n.hi;i&&(n=P(n.lo,n.hi));const o=w(n.lo,n.hi);return i?"-"+o:o}(e,t),uDec:(e,t)=>w(e,t)}}();var M,x,A;function N(e,t,n){if(t===n)return!0;if(e==M.BYTES){if(!(t instanceof Uint8Array&&n instanceof Uint8Array))return!1;if(t.length!==n.length)return!1;for(let e=0;e>>0)}raw(e){return this.buf.length&&(this.chunks.push(new Uint8Array(this.buf)),this.buf=[]),this.chunks.push(e),this}uint32(e){for(h(e);e>127;)this.buf.push(127&e|128),e>>>=7;return this.buf.push(e),this}int32(e){return u(e),O(e,this.buf),this}bool(e){return this.buf.push(e?1:0),this}bytes(e){return this.uint32(e.byteLength),this.raw(e)}string(e){let t=this.textEncoder.encode(e);return this.uint32(t.byteLength),this.raw(t)}float(e){p(e);let t=new Uint8Array(4);return new DataView(t.buffer).setFloat32(0,e,!0),this.raw(t)}double(e){let t=new Uint8Array(8);return new DataView(t.buffer).setFloat64(0,e,!0),this.raw(t)}fixed32(e){h(e);let t=new Uint8Array(4);return new DataView(t.buffer).setUint32(0,e,!0),this.raw(t)}sfixed32(e){u(e);let t=new Uint8Array(4);return new DataView(t.buffer).setInt32(0,e,!0),this.raw(t)}sint32(e){return u(e),O(e=(e<<1^e>>31)>>>0,this.buf),this}sfixed64(e){let t=new Uint8Array(8),n=new DataView(t.buffer),i=D.enc(e);return n.setInt32(0,i.lo,!0),n.setInt32(4,i.hi,!0),this.raw(t)}fixed64(e){let t=new Uint8Array(8),n=new DataView(t.buffer),i=D.uEnc(e);return n.setInt32(0,i.lo,!0),n.setInt32(4,i.hi,!0),this.raw(t)}int64(e){let t=D.enc(e);return C(t.lo,t.hi,this.buf),this}sint64(e){let t=D.enc(e),n=t.hi>>31;return C(t.lo<<1^n,(t.hi<<1|t.lo>>>31)^n,this.buf),this}uint64(e){let t=D.uEnc(e);return C(t.lo,t.hi,this.buf),this}}class F{constructor(e,t){this.varint64=T,this.uint32=_,this.buf=e,this.len=e.length,this.pos=0,this.view=new DataView(e.buffer,e.byteOffset,e.byteLength),this.textDecoder=null!=t?t:new TextDecoder}tag(){let e=this.uint32(),t=e>>>3,n=7&e;if(t<=0||n<0||n>5)throw new Error("illegal tag: field no "+t+" wire type "+n);return[t,n]}skip(e,t){let n=this.pos;switch(e){case A.Varint:for(;128&this.buf[this.pos++];);break;case A.Bit64:this.pos+=4;case A.Bit32:this.pos+=4;break;case A.LengthDelimited:let n=this.uint32();this.pos+=n;break;case A.StartGroup:for(;;){const[e,n]=this.tag();if(n===A.EndGroup){if(void 0!==t&&e!==t)throw new Error("invalid end group tag");break}this.skip(n,e)}break;default:throw new Error("cant skip wire type "+e)}return this.assertBounds(),this.buf.subarray(n,this.pos)}assertBounds(){if(this.pos>this.len)throw new RangeError("premature EOF")}int32(){return 0|this.uint32()}sint32(){let e=this.uint32();return e>>>1^-(1&e)}int64(){return D.dec(...this.varint64())}uint64(){return D.uDec(...this.varint64())}sint64(){let[e,t]=this.varint64(),n=-(1&e);return e=(e>>>1|(1&t)<<31)^n,t=t>>>1^n,D.dec(e,t)}bool(){let[e,t]=this.varint64();return 0!==e||0!==t}fixed32(){return this.view.getUint32((this.pos+=4)-4,!0)}sfixed32(){return this.view.getInt32((this.pos+=4)-4,!0)}fixed64(){return D.uDec(this.sfixed32(),this.sfixed32())}sfixed64(){return D.dec(this.sfixed32(),this.sfixed32())}float(){return this.view.getFloat32((this.pos+=4)-4,!0)}double(){return this.view.getFloat64((this.pos+=8)-8,!0)}bytes(){let e=this.uint32(),t=this.pos;return this.pos+=e,this.assertBounds(),this.buf.subarray(t,t+e)}string(){return this.textDecoder.decode(this.bytes())}}function B(e){const t=e.field.localName,n=Object.create(null);return n[t]=function(e){const t=e.field;if(t.repeated)return[];if(void 0!==t.default)return t.default;switch(t.kind){case"enum":return t.T.values[0].no;case"scalar":return L(t.T,t.L);case"message":const e=t.T,n=new e;return e.fieldWrapper?e.fieldWrapper.unwrapField(n):n;case"map":throw"map fields are not allowed to be extensions"}}(e),[n,()=>n[t]]}let V="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""),q=[];for(let e=0;e>4,r=n,s=2;break;case 2:i[o++]=(15&r)<<4|(60&n)>>2,r=n,s=3;break;case 3:i[o++]=(3&r)<<6|n,s=0}}if(1==s)throw Error("invalid base64 string.");return i.subarray(0,o)},enc(e){let t,n="",i=0,o=0;for(let s=0;s>2],o=(3&t)<<4,i=1;break;case 1:n+=V[o|t>>4],o=(15&t)<<2,i=2;break;case 2:n+=V[o|t>>6],n+=V[63&t],i=0}return i&&(n+=V[o],n+="=",1==i&&(n+="=")),n}};function K(e,t,n){J(t,e);const i=t.runtime.bin.makeReadOptions(n),o=function(e,t){if(!t.repeated&&("enum"==t.kind||"scalar"==t.kind)){for(let n=e.length-1;n>=0;--n)if(e[n].no==t.no)return[e[n]];return[]}return e.filter((e=>e.no===t.no))}(e.getType().runtime.bin.listUnknownFields(e),t.field),[s,r]=B(t);for(const e of o)t.runtime.bin.readField(s,i.readerFactory(e.data),t.field,e.wireType,i);return r()}function H(e,t,n,i){J(t,e);const o=t.runtime.bin.makeReadOptions(i),s=t.runtime.bin.makeWriteOptions(i);if(G(e,t)){const n=e.getType().runtime.bin.listUnknownFields(e).filter((e=>e.no!=t.field.no));e.getType().runtime.bin.discardUnknownFields(e);for(const t of n)e.getType().runtime.bin.onUnknownField(e,t.no,t.wireType,t.data)}const r=s.writerFactory();let a=t.field;a.opt||a.repeated||"enum"!=a.kind&&"scalar"!=a.kind||(a=Object.assign(Object.assign({},t.field),{opt:!0})),t.runtime.bin.writeField(a,n,r,s);const c=o.readerFactory(r.finish());for(;c.pose.no==t.field.no))}function J(e,t){s(e.extendee.typeName==t.getType().typeName,"extension ".concat(e.typeName," can only be applied to message ").concat(e.extendee.typeName))}function z(e,t){const n=e.localName;if(e.repeated)return t[n].length>0;if(e.oneof)return t[e.oneof.localName].case===n;switch(e.kind){case"enum":case"scalar":return e.opt||e.req?void 0!==t[n]:"enum"==e.kind?t[n]!==e.T.values[0].no:!U(e.T,t[n]);case"message":return void 0!==t[n];case"map":return Object.keys(t[n]).length>0}}function Q(e,t){const n=e.localName,i=!e.opt&&!e.req;if(e.repeated)t[n]=[];else if(e.oneof)t[e.oneof.localName]={case:void 0};else switch(e.kind){case"map":t[n]={};break;case"enum":t[n]=i?e.T.values[0].no:void 0;break;case"scalar":t[n]=i?L(e.T,e.L):void 0;break;case"message":t[n]=void 0}}function Y(e,t){if(null===e||"object"!=typeof e)return!1;if(!Object.getOwnPropertyNames(b.prototype).every((t=>t in e&&"function"==typeof e[t])))return!1;const n=e.getType();return null!==n&&"function"==typeof n&&"typeName"in n&&"string"==typeof n.typeName&&(void 0===t||n.typeName==t.typeName)}function X(e,t){return Y(t)||!e.fieldWrapper?t:e.fieldWrapper.wrapField(t)}M.DOUBLE,M.FLOAT,M.INT64,M.UINT64,M.INT32,M.UINT32,M.BOOL,M.STRING,M.BYTES;const Z={ignoreUnknownFields:!1},$={emitDefaultValues:!1,enumAsInteger:!1,useProtoFieldName:!1,prettySpaces:0};function ee(e){return e?Object.assign(Object.assign({},Z),e):Z}function te(e){return e?Object.assign(Object.assign({},$),e):$}const ne=Symbol(),ie=Symbol();function oe(e){if(null===e)return"null";switch(typeof e){case"object":return Array.isArray(e)?"array":"object";case"string":return e.length>100?"string":'"'.concat(e.split('"').join('\\"'),'"');default:return String(e)}}function se(e,t,n,i,o){let r=n.localName;if(n.repeated){if(s("map"!=n.kind),null===t)return;if(!Array.isArray(t))throw new Error("cannot decode field ".concat(o.typeName,".").concat(n.name," from JSON: ").concat(oe(t)));const a=e[r];for(const e of t){if(null===e)throw new Error("cannot decode field ".concat(o.typeName,".").concat(n.name," from JSON: ").concat(oe(e)));switch(n.kind){case"message":a.push(n.T.fromJson(e,i));break;case"enum":const t=ce(n.T,e,i.ignoreUnknownFields,!0);t!==ie&&a.push(t);break;case"scalar":try{a.push(ae(n.T,e,n.L,!0))}catch(t){let i="cannot decode field ".concat(o.typeName,".").concat(n.name," from JSON: ").concat(oe(e));throw t instanceof Error&&t.message.length>0&&(i+=": ".concat(t.message)),new Error(i)}}}}else if("map"==n.kind){if(null===t)return;if("object"!=typeof t||Array.isArray(t))throw new Error("cannot decode field ".concat(o.typeName,".").concat(n.name," from JSON: ").concat(oe(t)));const s=e[r];for(const[e,r]of Object.entries(t)){if(null===r)throw new Error("cannot decode field ".concat(o.typeName,".").concat(n.name," from JSON: map value null"));let a;try{a=re(n.K,e)}catch(e){let i="cannot decode map key for field ".concat(o.typeName,".").concat(n.name," from JSON: ").concat(oe(t));throw e instanceof Error&&e.message.length>0&&(i+=": ".concat(e.message)),new Error(i)}switch(n.V.kind){case"message":s[a]=n.V.T.fromJson(r,i);break;case"enum":const e=ce(n.V.T,r,i.ignoreUnknownFields,!0);e!==ie&&(s[a]=e);break;case"scalar":try{s[a]=ae(n.V.T,r,x.BIGINT,!0)}catch(e){let i="cannot decode map value for field ".concat(o.typeName,".").concat(n.name," from JSON: ").concat(oe(t));throw e instanceof Error&&e.message.length>0&&(i+=": ".concat(e.message)),new Error(i)}}}}else switch(n.oneof&&(e=e[n.oneof.localName]={case:r},r="value"),n.kind){case"message":const s=n.T;if(null===t&&"google.protobuf.Value"!=s.typeName)return;let a=e[r];Y(a)?a.fromJson(t,i):(e[r]=a=s.fromJson(t,i),s.fieldWrapper&&!n.oneof&&(e[r]=s.fieldWrapper.unwrapField(a)));break;case"enum":const c=ce(n.T,t,i.ignoreUnknownFields,!1);switch(c){case ne:Q(n,e);break;case ie:break;default:e[r]=c}break;case"scalar":try{const i=ae(n.T,t,n.L,!1);if(i===ne)Q(n,e);else e[r]=i}catch(e){let i="cannot decode field ".concat(o.typeName,".").concat(n.name," from JSON: ").concat(oe(t));throw e instanceof Error&&e.message.length>0&&(i+=": ".concat(e.message)),new Error(i)}}}function re(e,t){if(e===M.BOOL)switch(t){case"true":t=!0;break;case"false":t=!1}return ae(e,t,x.BIGINT,!0).toString()}function ae(e,t,n,i){if(null===t)return i?L(e,n):ne;switch(e){case M.DOUBLE:case M.FLOAT:if("NaN"===t)return Number.NaN;if("Infinity"===t)return Number.POSITIVE_INFINITY;if("-Infinity"===t)return Number.NEGATIVE_INFINITY;if(""===t)break;if("string"==typeof t&&t.trim().length!==t.length)break;if("string"!=typeof t&&"number"!=typeof t)break;const i=Number(t);if(Number.isNaN(i))break;if(!Number.isFinite(i))break;return e==M.FLOAT&&p(i),i;case M.INT32:case M.FIXED32:case M.SFIXED32:case M.SINT32:case M.UINT32:let o;if("number"==typeof t?o=t:"string"==typeof t&&t.length>0&&t.trim().length===t.length&&(o=Number(t)),void 0===o)break;return e==M.UINT32||e==M.FIXED32?h(o):u(o),o;case M.INT64:case M.SFIXED64:case M.SINT64:if("number"!=typeof t&&"string"!=typeof t)break;const s=D.parse(t);return n?s.toString():s;case M.FIXED64:case M.UINT64:if("number"!=typeof t&&"string"!=typeof t)break;const r=D.uParse(t);return n?r.toString():r;case M.BOOL:if("boolean"!=typeof t)break;return t;case M.STRING:if("string"!=typeof t)break;try{encodeURIComponent(t)}catch(e){throw new Error("invalid UTF8")}return t;case M.BYTES:if(""===t)return new Uint8Array(0);if("string"!=typeof t)break;return W.dec(t)}throw new Error}function ce(e,t,n,i){if(null===t)return"google.protobuf.NullValue"==e.typeName?0:i?e.values[0].no:ne;switch(typeof t){case"number":if(Number.isInteger(t))return t;break;case"string":const i=e.findName(t);if(void 0!==i)return i.no;if(n)return ie}throw new Error("cannot decode enum ".concat(e.typeName," from JSON: ").concat(oe(t)))}function de(e){return!(!e.repeated&&"map"!=e.kind)||!e.oneof&&("message"!=e.kind&&(!e.opt&&!e.req))}function le(e,t,n){if("map"==e.kind){s("object"==typeof t&&null!=t);const i={},o=Object.entries(t);switch(e.V.kind){case"scalar":for(const[t,n]of o)i[t.toString()]=he(e.V.T,n);break;case"message":for(const[e,t]of o)i[e.toString()]=t.toJson(n);break;case"enum":const t=e.V.T;for(const[e,s]of o)i[e.toString()]=ue(t,s,n.enumAsInteger)}return n.emitDefaultValues||o.length>0?i:void 0}if(e.repeated){s(Array.isArray(t));const i=[];switch(e.kind){case"scalar":for(let n=0;n0?i:void 0}switch(e.kind){case"scalar":return he(e.T,t);case"enum":return ue(e.T,t,n.enumAsInteger);case"message":return X(e.T,t).toJson(n)}}function ue(e,t,n){var i;if(s("number"==typeof t),"google.protobuf.NullValue"==e.typeName)return null;if(n)return t;const o=e.findNumber(t);return null!==(i=null==o?void 0:o.name)&&void 0!==i?i:t}function he(e,t){switch(e){case M.INT32:case M.SFIXED32:case M.SINT32:case M.FIXED32:case M.UINT32:return s("number"==typeof t),t;case M.FLOAT:case M.DOUBLE:return s("number"==typeof t),Number.isNaN(t)?"NaN":t===Number.POSITIVE_INFINITY?"Infinity":t===Number.NEGATIVE_INFINITY?"-Infinity":t;case M.STRING:return s("string"==typeof t),t;case M.BOOL:return s("boolean"==typeof t),t;case M.UINT64:case M.FIXED64:case M.INT64:case M.SFIXED64:case M.SINT64:return s("bigint"==typeof t||"string"==typeof t||"number"==typeof t),t.toString();case M.BYTES:return s(t instanceof Uint8Array),W.enc(t)}}const pe=Symbol("@bufbuild/protobuf/unknown-fields"),me={readUnknownFields:!0,readerFactory:e=>new F(e)},ge={writeUnknownFields:!0,writerFactory:()=>new j};function ve(e){return e?Object.assign(Object.assign({},me),e):me}function fe(e){return e?Object.assign(Object.assign({},ge),e):ge}function ke(e,t,n,i,o){let{repeated:s,localName:r}=n;switch(n.oneof&&((e=e[n.oneof.localName]).case!=r&&delete e.value,e.case=r,r="value"),n.kind){case"scalar":case"enum":const a="enum"==n.kind?M.INT32:n.T;let c=Te;if("scalar"==n.kind&&n.L>0&&(c=be),s){let n=e[r];if(i==A.LengthDelimited&&a!=M.STRING&&a!=M.BYTES){let e=t.uint32()+t.pos;for(;t.pose.no-t.no))),this.numbersAsc}byMember(){if(!this.members){this.members=[];const e=this.members;let t;for(const n of this.list())n.oneof?n.oneof!==t&&(t=n.oneof,e.push(t)):e.push(n)}return this.members}}function _e(e,t){const n=Me(e);return t?n:Ue(Le(n))}const De=Me;function Me(e){let t=!1;const n=[];for(let i=0;i"".concat(e,"$"),Le=e=>Ae.has(e)?Ne(e):e,Ue=e=>xe.has(e)?Ne(e):e;class je{constructor(e){this.kind="oneof",this.repeated=!1,this.packed=!1,this.opt=!1,this.req=!1,this.default=void 0,this.fields=[],this.name=e,this.localName=_e(e,!1)}addField(e){s(e.oneof===this,"field ".concat(e.name," not one of ").concat(this.name)),this.fields.push(e)}findField(e){if(!this._lookup){this._lookup=Object.create(null);for(let e=0;enew Oe(e,(e=>function(e,t){var n,i,o,s,r,a;const c=[];let d;for(const t of"function"==typeof e?e():e){const e=t;if(e.localName=_e(t.name,void 0!==t.oneof),e.jsonName=null!==(n=t.jsonName)&&void 0!==n?n:De(t.name),e.repeated=null!==(i=t.repeated)&&void 0!==i&&i,"scalar"==t.kind&&(e.L=null!==(o=t.L)&&void 0!==o?o:x.BIGINT),e.delimited=null!==(s=t.delimited)&&void 0!==s&&s,e.req=null!==(r=t.req)&&void 0!==r&&r,e.opt=null!==(a=t.opt)&&void 0!==a&&a,void 0===t.packed&&(e.packed="enum"==t.kind||"scalar"==t.kind&&t.T!=M.BYTES&&t.T!=M.STRING),void 0!==t.oneof){const n="string"==typeof t.oneof?t.oneof:t.oneof.name;d&&d.name==n||(d=new je(n)),e.oneof=d,d.addField(e)}c.push(e)}return c}(e))),Ve=e=>{for(const t of e.getType().fields.byMember()){if(t.opt)continue;const n=t.localName,i=e;if(t.repeated)i[n]=[];else switch(t.kind){case"oneof":i[n]={case:void 0};break;case"enum":i[n]=0;break;case"map":i[n]={};break;case"scalar":i[n]=L(t.T,t.L)}}},{syntax:"proto3",json:{makeReadOptions:ee,makeWriteOptions:te,readMessage(e,t,n,i){if(null==t||Array.isArray(t)||"object"!=typeof t)throw new Error("cannot decode message ".concat(e.typeName," from JSON: ").concat(oe(t)));i=null!=i?i:new e;const o=new Map,s=n.typeRegistry;for(const[r,a]of Object.entries(t)){const t=e.fields.findJsonName(r);if(t){if(t.oneof){if(null===a&&"scalar"==t.kind)continue;const n=o.get(t.oneof);if(void 0!==n)throw new Error("cannot decode message ".concat(e.typeName,' from JSON: multiple keys for oneof "').concat(t.oneof.name,'" present: "').concat(n,'", "').concat(r,'"'));o.set(t.oneof,r)}se(i,a,t,n,e)}else{let t=!1;if((null==s?void 0:s.findExtension)&&r.startsWith("[")&&r.endsWith("]")){const o=s.findExtension(r.substring(1,r.length-1));if(o&&o.extendee.typeName==e.typeName){t=!0;const[e,s]=B(o);se(e,a,o.field,n,o),H(i,o,s(),n)}}if(!t&&!n.ignoreUnknownFields)throw new Error("cannot decode message ".concat(e.typeName,' from JSON: key "').concat(r,'" is unknown'))}}return i},writeMessage(e,t){const n=e.getType(),i={};let o;try{for(o of n.fields.byNumber()){if(!z(o,e)){if(o.req)throw"required field not set";if(!t.emitDefaultValues)continue;if(!de(o))continue}const n=le(o,o.oneof?e[o.oneof.localName].value:e[o.localName],t);void 0!==n&&(i[t.useProtoFieldName?o.name:o.jsonName]=n)}const s=t.typeRegistry;if(null==s?void 0:s.findExtensionFor)for(const o of n.runtime.bin.listUnknownFields(e)){const r=s.findExtensionFor(n.typeName,o.no);if(r&&G(e,r)){const n=K(e,r,t),o=le(r.field,n,t);void 0!==o&&(i[r.field.jsonName]=o)}}}catch(e){const t=o?"cannot encode field ".concat(n.typeName,".").concat(o.name," to JSON"):"cannot encode message ".concat(n.typeName," to JSON"),i=e instanceof Error?e.message:String(e);throw new Error(t+(i.length>0?": ".concat(i):""))}return i},readScalar:(e,t,n)=>ae(e,t,null!=n?n:x.BIGINT,!0),writeScalar(e,t,n){if(void 0!==t)return n||U(e,t)?he(e,t):void 0},debug:oe},bin:{makeReadOptions:ve,makeWriteOptions:fe,listUnknownFields(e){var t;return null!==(t=e[pe])&&void 0!==t?t:[]},discardUnknownFields(e){delete e[pe]},writeUnknownFields(e,t){const n=e[pe];if(n)for(const e of n)t.tag(e.no,e.wireType).raw(e.data)},onUnknownField(e,t,n,i){const o=e;Array.isArray(o[pe])||(o[pe]=[]),o[pe].push({no:t,wireType:n,data:i})},readMessage(e,t,n,i,o){const s=e.getType(),r=o?t.len:t.pos+n;let a,c;for(;t.posY(e,c)?e:new c(e)));else{const e=s[n];c.fieldWrapper?"google.protobuf.BytesValue"===c.typeName?o[n]=Ie(e):o[n]=e:o[n]=Y(e,c)?e:new c(e)}}}},equals:(e,t,n)=>t===n||!(!t||!n)&&e.fields.byMember().every((e=>{const i=t[e.localName],o=n[e.localName];if(e.repeated){if(i.length!==o.length)return!1;switch(e.kind){case"message":return i.every(((t,n)=>e.T.equals(t,o[n])));case"scalar":return i.every(((t,n)=>N(e.T,t,o[n])));case"enum":return i.every(((e,t)=>N(M.INT32,e,o[t])))}throw new Error("repeated cannot contain ".concat(e.kind))}switch(e.kind){case"message":let t=i,n=o;return e.T.fieldWrapper&&(void 0===t||Y(t)||(t=e.T.fieldWrapper.wrapField(t)),void 0===n||Y(n)||(n=e.T.fieldWrapper.wrapField(n))),e.T.equals(t,n);case"enum":return N(M.INT32,i,o);case"scalar":return N(e.T,i,o);case"oneof":if(i.case!==o.case)return!1;const s=e.findField(i.case);if(void 0===s)return!0;switch(s.kind){case"message":return s.T.equals(i.value,o.value);case"enum":return N(M.INT32,i.value,o.value);case"scalar":return N(s.T,i.value,o.value)}throw new Error("oneof cannot contain ".concat(s.kind));case"map":const r=Object.keys(i).concat(Object.keys(o));switch(e.V.kind){case"message":const t=e.V.T;return r.every((e=>t.equals(i[e],o[e])));case"enum":return r.every((e=>N(M.INT32,i[e],o[e])));case"scalar":const n=e.V.T;return r.every((e=>N(n,i[e],o[e])))}}})),clone(e){const t=e.getType(),n=new t,i=n;for(const n of t.fields.byMember()){const t=e[n.localName];let o;if(n.repeated)o=t.map(Pe);else if("map"==n.kind){o=i[n.localName];for(const[e,n]of Object.entries(t))o[e]=Pe(n)}else o="oneof"==n.kind?n.findField(t.case)?{case:t.case,value:Pe(t.value)}:{case:void 0}:Pe(t);i[n.localName]=o}for(const n of t.runtime.bin.listUnknownFields(e))t.runtime.bin.onUnknownField(i,n.no,n.wireType,n.data);return n}}),{newFieldList:Be,initFields:Ve}),makeMessageType(e,t,n){return function(e,t,n,i){var o;const s=null!==(o=null==i?void 0:i.localName)&&void 0!==o?o:t.substring(t.lastIndexOf(".")+1),r={[s]:function(t){e.util.initFields(this),e.util.initPartial(t,this)}}[s];return Object.setPrototypeOf(r.prototype,new b),Object.assign(r,{runtime:e,typeName:t,fields:e.util.newFieldList(n),fromBinary:(e,t)=>(new r).fromBinary(e,t),fromJson:(e,t)=>(new r).fromJson(e,t),fromJsonString:(e,t)=>(new r).fromJsonString(e,t),equals:(t,n)=>e.util.equals(r,t,n)}),r}(this,e,t,n)},makeEnum:k,makeEnumType:f,getEnumType:g,makeExtension(e,t,n){return function(e,t,n,i){let o;return{typeName:t,extendee:n,get field(){if(!o){const n="function"==typeof i?i():i;n.name=t.split(".").pop(),n.jsonName="[".concat(t,"]"),o=e.util.newFieldList([n]).list()[0]}return o},runtime:e}}(this,e,t,n)}});var Be,Ve;class qe extends b{constructor(e){super(),this.seconds=D.zero,this.nanos=0,Fe.util.initPartial(e,this)}fromJson(e,t){if("string"!=typeof e)throw new Error("cannot decode google.protobuf.Timestamp from JSON: ".concat(Fe.json.debug(e)));const n=e.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:Z|\.([0-9]{3,9})Z|([+-][0-9][0-9]:[0-9][0-9]))$/);if(!n)throw new Error("cannot decode google.protobuf.Timestamp from JSON: invalid RFC 3339 string");const i=Date.parse(n[1]+"-"+n[2]+"-"+n[3]+"T"+n[4]+":"+n[5]+":"+n[6]+(n[8]?n[8]:"Z"));if(Number.isNaN(i))throw new Error("cannot decode google.protobuf.Timestamp from JSON: invalid RFC 3339 string");if(iDate.parse("9999-12-31T23:59:59Z"))throw new Error("cannot decode message google.protobuf.Timestamp from JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive");return this.seconds=D.parse(i/1e3),this.nanos=0,n[7]&&(this.nanos=parseInt("1"+n[7]+"0".repeat(9-n[7].length))-1e9),this}toJson(e){const t=1e3*Number(this.seconds);if(tDate.parse("9999-12-31T23:59:59Z"))throw new Error("cannot encode google.protobuf.Timestamp to JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive");if(this.nanos<0)throw new Error("cannot encode google.protobuf.Timestamp to JSON: nanos must not be negative");let n="Z";if(this.nanos>0){const e=(this.nanos+1e9).toString().substring(1);n="000000"===e.substring(3)?"."+e.substring(0,3)+"Z":"000"===e.substring(6)?"."+e.substring(0,6)+"Z":"."+e+"Z"}return new Date(t).toISOString().replace(".000Z",n)}toDate(){return new Date(1e3*Number(this.seconds)+Math.ceil(this.nanos/1e6))}static now(){return qe.fromDate(new Date)}static fromDate(e){const t=e.getTime();return new qe({seconds:D.parse(Math.floor(t/1e3)),nanos:t%1e3*1e6})}static fromBinary(e,t){return(new qe).fromBinary(e,t)}static fromJson(e,t){return(new qe).fromJson(e,t)}static fromJsonString(e,t){return(new qe).fromJsonString(e,t)}static equals(e,t){return Fe.util.equals(qe,e,t)}}qe.runtime=Fe,qe.typeName="google.protobuf.Timestamp",qe.fields=Fe.util.newFieldList((()=>[{no:1,name:"seconds",kind:"scalar",T:3},{no:2,name:"nanos",kind:"scalar",T:5}]));const We=Fe.makeMessageType("livekit.MetricsBatch",(()=>[{no:1,name:"timestamp_ms",kind:"scalar",T:3},{no:2,name:"normalized_timestamp",kind:"message",T:qe},{no:3,name:"str_data",kind:"scalar",T:9,repeated:!0},{no:4,name:"time_series",kind:"message",T:Ke,repeated:!0},{no:5,name:"events",kind:"message",T:Ge,repeated:!0}])),Ke=Fe.makeMessageType("livekit.TimeSeriesMetric",(()=>[{no:1,name:"label",kind:"scalar",T:13},{no:2,name:"participant_identity",kind:"scalar",T:13},{no:3,name:"track_sid",kind:"scalar",T:13},{no:4,name:"samples",kind:"message",T:He,repeated:!0},{no:5,name:"rid",kind:"scalar",T:13}])),He=Fe.makeMessageType("livekit.MetricSample",(()=>[{no:1,name:"timestamp_ms",kind:"scalar",T:3},{no:2,name:"normalized_timestamp",kind:"message",T:qe},{no:3,name:"value",kind:"scalar",T:2}])),Ge=Fe.makeMessageType("livekit.EventMetric",(()=>[{no:1,name:"label",kind:"scalar",T:13},{no:2,name:"participant_identity",kind:"scalar",T:13},{no:3,name:"track_sid",kind:"scalar",T:13},{no:4,name:"start_timestamp_ms",kind:"scalar",T:3},{no:5,name:"end_timestamp_ms",kind:"scalar",T:3,opt:!0},{no:6,name:"normalized_start_timestamp",kind:"message",T:qe},{no:7,name:"normalized_end_timestamp",kind:"message",T:qe,opt:!0},{no:8,name:"metadata",kind:"scalar",T:9},{no:9,name:"rid",kind:"scalar",T:13}])),Je=Fe.makeEnum("livekit.AudioCodec",[{no:0,name:"DEFAULT_AC"},{no:1,name:"OPUS"},{no:2,name:"AAC"},{no:3,name:"AC_MP3"}]),ze=Fe.makeEnum("livekit.VideoCodec",[{no:0,name:"DEFAULT_VC"},{no:1,name:"H264_BASELINE"},{no:2,name:"H264_MAIN"},{no:3,name:"H264_HIGH"},{no:4,name:"VP8"}]),Qe=Fe.makeEnum("livekit.ImageCodec",[{no:0,name:"IC_DEFAULT"},{no:1,name:"IC_JPEG"}]),Ye=Fe.makeEnum("livekit.BackupCodecPolicy",[{no:0,name:"PREFER_REGRESSION"},{no:1,name:"SIMULCAST"},{no:2,name:"REGRESSION"}]),Xe=Fe.makeEnum("livekit.TrackType",[{no:0,name:"AUDIO"},{no:1,name:"VIDEO"},{no:2,name:"DATA"}]),Ze=Fe.makeEnum("livekit.TrackSource",[{no:0,name:"UNKNOWN"},{no:1,name:"CAMERA"},{no:2,name:"MICROPHONE"},{no:3,name:"SCREEN_SHARE"},{no:4,name:"SCREEN_SHARE_AUDIO"}]),$e=Fe.makeEnum("livekit.VideoQuality",[{no:0,name:"LOW"},{no:1,name:"MEDIUM"},{no:2,name:"HIGH"},{no:3,name:"OFF"}]),et=Fe.makeEnum("livekit.ConnectionQuality",[{no:0,name:"POOR"},{no:1,name:"GOOD"},{no:2,name:"EXCELLENT"},{no:3,name:"LOST"}]),tt=Fe.makeEnum("livekit.ClientConfigSetting",[{no:0,name:"UNSET"},{no:1,name:"DISABLED"},{no:2,name:"ENABLED"}]),nt=Fe.makeEnum("livekit.DisconnectReason",[{no:0,name:"UNKNOWN_REASON"},{no:1,name:"CLIENT_INITIATED"},{no:2,name:"DUPLICATE_IDENTITY"},{no:3,name:"SERVER_SHUTDOWN"},{no:4,name:"PARTICIPANT_REMOVED"},{no:5,name:"ROOM_DELETED"},{no:6,name:"STATE_MISMATCH"},{no:7,name:"JOIN_FAILURE"},{no:8,name:"MIGRATION"},{no:9,name:"SIGNAL_CLOSE"},{no:10,name:"ROOM_CLOSED"},{no:11,name:"USER_UNAVAILABLE"},{no:12,name:"USER_REJECTED"},{no:13,name:"SIP_TRUNK_FAILURE"},{no:14,name:"CONNECTION_TIMEOUT"},{no:15,name:"MEDIA_FAILURE"}]),it=Fe.makeEnum("livekit.ReconnectReason",[{no:0,name:"RR_UNKNOWN"},{no:1,name:"RR_SIGNAL_DISCONNECTED"},{no:2,name:"RR_PUBLISHER_FAILED"},{no:3,name:"RR_SUBSCRIBER_FAILED"},{no:4,name:"RR_SWITCH_CANDIDATE"}]),ot=Fe.makeEnum("livekit.SubscriptionError",[{no:0,name:"SE_UNKNOWN"},{no:1,name:"SE_CODEC_UNSUPPORTED"},{no:2,name:"SE_TRACK_NOTFOUND"}]),st=Fe.makeEnum("livekit.AudioTrackFeature",[{no:0,name:"TF_STEREO"},{no:1,name:"TF_NO_DTX"},{no:2,name:"TF_AUTO_GAIN_CONTROL"},{no:3,name:"TF_ECHO_CANCELLATION"},{no:4,name:"TF_NOISE_SUPPRESSION"},{no:5,name:"TF_ENHANCED_NOISE_CANCELLATION"},{no:6,name:"TF_PRECONNECT_BUFFER"}]),rt=Fe.makeMessageType("livekit.Room",(()=>[{no:1,name:"sid",kind:"scalar",T:9},{no:2,name:"name",kind:"scalar",T:9},{no:3,name:"empty_timeout",kind:"scalar",T:13},{no:14,name:"departure_timeout",kind:"scalar",T:13},{no:4,name:"max_participants",kind:"scalar",T:13},{no:5,name:"creation_time",kind:"scalar",T:3},{no:15,name:"creation_time_ms",kind:"scalar",T:3},{no:6,name:"turn_password",kind:"scalar",T:9},{no:7,name:"enabled_codecs",kind:"message",T:at,repeated:!0},{no:8,name:"metadata",kind:"scalar",T:9},{no:9,name:"num_participants",kind:"scalar",T:13},{no:11,name:"num_publishers",kind:"scalar",T:13},{no:10,name:"active_recording",kind:"scalar",T:8},{no:13,name:"version",kind:"message",T:Vt}])),at=Fe.makeMessageType("livekit.Codec",(()=>[{no:1,name:"mime",kind:"scalar",T:9},{no:2,name:"fmtp_line",kind:"scalar",T:9}])),ct=Fe.makeMessageType("livekit.ParticipantPermission",(()=>[{no:1,name:"can_subscribe",kind:"scalar",T:8},{no:2,name:"can_publish",kind:"scalar",T:8},{no:3,name:"can_publish_data",kind:"scalar",T:8},{no:9,name:"can_publish_sources",kind:"enum",T:Fe.getEnumType(Ze),repeated:!0},{no:7,name:"hidden",kind:"scalar",T:8},{no:8,name:"recorder",kind:"scalar",T:8},{no:10,name:"can_update_metadata",kind:"scalar",T:8},{no:11,name:"agent",kind:"scalar",T:8},{no:12,name:"can_subscribe_metrics",kind:"scalar",T:8}])),dt=Fe.makeMessageType("livekit.ParticipantInfo",(()=>[{no:1,name:"sid",kind:"scalar",T:9},{no:2,name:"identity",kind:"scalar",T:9},{no:3,name:"state",kind:"enum",T:Fe.getEnumType(lt)},{no:4,name:"tracks",kind:"message",T:gt,repeated:!0},{no:5,name:"metadata",kind:"scalar",T:9},{no:6,name:"joined_at",kind:"scalar",T:3},{no:17,name:"joined_at_ms",kind:"scalar",T:3},{no:9,name:"name",kind:"scalar",T:9},{no:10,name:"version",kind:"scalar",T:13},{no:11,name:"permission",kind:"message",T:ct},{no:12,name:"region",kind:"scalar",T:9},{no:13,name:"is_publisher",kind:"scalar",T:8},{no:14,name:"kind",kind:"enum",T:Fe.getEnumType(ut)},{no:15,name:"attributes",kind:"map",K:9,V:{kind:"scalar",T:9}},{no:16,name:"disconnect_reason",kind:"enum",T:Fe.getEnumType(nt)},{no:18,name:"kind_details",kind:"enum",T:Fe.getEnumType(ht),repeated:!0}])),lt=Fe.makeEnum("livekit.ParticipantInfo.State",[{no:0,name:"JOINING"},{no:1,name:"JOINED"},{no:2,name:"ACTIVE"},{no:3,name:"DISCONNECTED"}]),ut=Fe.makeEnum("livekit.ParticipantInfo.Kind",[{no:0,name:"STANDARD"},{no:1,name:"INGRESS"},{no:2,name:"EGRESS"},{no:3,name:"SIP"},{no:4,name:"AGENT"},{no:7,name:"CONNECTOR"}]),ht=Fe.makeEnum("livekit.ParticipantInfo.KindDetail",[{no:0,name:"CLOUD_AGENT"},{no:1,name:"FORWARDED"}]),pt=Fe.makeEnum("livekit.Encryption.Type",[{no:0,name:"NONE"},{no:1,name:"GCM"},{no:2,name:"CUSTOM"}]),mt=Fe.makeMessageType("livekit.SimulcastCodecInfo",(()=>[{no:1,name:"mime_type",kind:"scalar",T:9},{no:2,name:"mid",kind:"scalar",T:9},{no:3,name:"cid",kind:"scalar",T:9},{no:4,name:"layers",kind:"message",T:vt,repeated:!0},{no:5,name:"video_layer_mode",kind:"enum",T:Fe.getEnumType(ft)},{no:6,name:"sdp_cid",kind:"scalar",T:9}])),gt=Fe.makeMessageType("livekit.TrackInfo",(()=>[{no:1,name:"sid",kind:"scalar",T:9},{no:2,name:"type",kind:"enum",T:Fe.getEnumType(Xe)},{no:3,name:"name",kind:"scalar",T:9},{no:4,name:"muted",kind:"scalar",T:8},{no:5,name:"width",kind:"scalar",T:13},{no:6,name:"height",kind:"scalar",T:13},{no:7,name:"simulcast",kind:"scalar",T:8},{no:8,name:"disable_dtx",kind:"scalar",T:8},{no:9,name:"source",kind:"enum",T:Fe.getEnumType(Ze)},{no:10,name:"layers",kind:"message",T:vt,repeated:!0},{no:11,name:"mime_type",kind:"scalar",T:9},{no:12,name:"mid",kind:"scalar",T:9},{no:13,name:"codecs",kind:"message",T:mt,repeated:!0},{no:14,name:"stereo",kind:"scalar",T:8},{no:15,name:"disable_red",kind:"scalar",T:8},{no:16,name:"encryption",kind:"enum",T:Fe.getEnumType(pt)},{no:17,name:"stream",kind:"scalar",T:9},{no:18,name:"version",kind:"message",T:Vt},{no:19,name:"audio_features",kind:"enum",T:Fe.getEnumType(st),repeated:!0},{no:20,name:"backup_codec_policy",kind:"enum",T:Fe.getEnumType(Ye)}])),vt=Fe.makeMessageType("livekit.VideoLayer",(()=>[{no:1,name:"quality",kind:"enum",T:Fe.getEnumType($e)},{no:2,name:"width",kind:"scalar",T:13},{no:3,name:"height",kind:"scalar",T:13},{no:4,name:"bitrate",kind:"scalar",T:13},{no:5,name:"ssrc",kind:"scalar",T:13},{no:6,name:"spatial_layer",kind:"scalar",T:5},{no:7,name:"rid",kind:"scalar",T:9}])),ft=Fe.makeEnum("livekit.VideoLayer.Mode",[{no:0,name:"MODE_UNUSED"},{no:1,name:"ONE_SPATIAL_LAYER_PER_STREAM"},{no:2,name:"MULTIPLE_SPATIAL_LAYERS_PER_STREAM"},{no:3,name:"ONE_SPATIAL_LAYER_PER_STREAM_INCOMPLETE_RTCP_SR"}]),kt=Fe.makeMessageType("livekit.DataPacket",(()=>[{no:1,name:"kind",kind:"enum",T:Fe.getEnumType(yt)},{no:4,name:"participant_identity",kind:"scalar",T:9},{no:5,name:"destination_identities",kind:"scalar",T:9,repeated:!0},{no:2,name:"user",kind:"message",T:Et,oneof:"value"},{no:3,name:"speaker",kind:"message",T:Ct,oneof:"value"},{no:6,name:"sip_dtmf",kind:"message",T:wt,oneof:"value"},{no:7,name:"transcription",kind:"message",T:Rt,oneof:"value"},{no:8,name:"metrics",kind:"message",T:We,oneof:"value"},{no:9,name:"chat_message",kind:"message",T:It,oneof:"value"},{no:10,name:"rpc_request",kind:"message",T:Ot,oneof:"value"},{no:11,name:"rpc_ack",kind:"message",T:_t,oneof:"value"},{no:12,name:"rpc_response",kind:"message",T:Dt,oneof:"value"},{no:13,name:"stream_header",kind:"message",T:Ht,oneof:"value"},{no:14,name:"stream_chunk",kind:"message",T:Gt,oneof:"value"},{no:15,name:"stream_trailer",kind:"message",T:Jt,oneof:"value"},{no:18,name:"encrypted_packet",kind:"message",T:bt,oneof:"value"},{no:16,name:"sequence",kind:"scalar",T:13},{no:17,name:"participant_sid",kind:"scalar",T:9}])),yt=Fe.makeEnum("livekit.DataPacket.Kind",[{no:0,name:"RELIABLE"},{no:1,name:"LOSSY"}]),bt=Fe.makeMessageType("livekit.EncryptedPacket",(()=>[{no:1,name:"encryption_type",kind:"enum",T:Fe.getEnumType(pt)},{no:2,name:"iv",kind:"scalar",T:12},{no:3,name:"key_index",kind:"scalar",T:13},{no:4,name:"encrypted_value",kind:"scalar",T:12}])),Tt=Fe.makeMessageType("livekit.EncryptedPacketPayload",(()=>[{no:1,name:"user",kind:"message",T:Et,oneof:"value"},{no:3,name:"chat_message",kind:"message",T:It,oneof:"value"},{no:4,name:"rpc_request",kind:"message",T:Ot,oneof:"value"},{no:5,name:"rpc_ack",kind:"message",T:_t,oneof:"value"},{no:6,name:"rpc_response",kind:"message",T:Dt,oneof:"value"},{no:7,name:"stream_header",kind:"message",T:Ht,oneof:"value"},{no:8,name:"stream_chunk",kind:"message",T:Gt,oneof:"value"},{no:9,name:"stream_trailer",kind:"message",T:Jt,oneof:"value"}])),Ct=Fe.makeMessageType("livekit.ActiveSpeakerUpdate",(()=>[{no:1,name:"speakers",kind:"message",T:St,repeated:!0}])),St=Fe.makeMessageType("livekit.SpeakerInfo",(()=>[{no:1,name:"sid",kind:"scalar",T:9},{no:2,name:"level",kind:"scalar",T:2},{no:3,name:"active",kind:"scalar",T:8}])),Et=Fe.makeMessageType("livekit.UserPacket",(()=>[{no:1,name:"participant_sid",kind:"scalar",T:9},{no:5,name:"participant_identity",kind:"scalar",T:9},{no:2,name:"payload",kind:"scalar",T:12},{no:3,name:"destination_sids",kind:"scalar",T:9,repeated:!0},{no:6,name:"destination_identities",kind:"scalar",T:9,repeated:!0},{no:4,name:"topic",kind:"scalar",T:9,opt:!0},{no:8,name:"id",kind:"scalar",T:9,opt:!0},{no:9,name:"start_time",kind:"scalar",T:4,opt:!0},{no:10,name:"end_time",kind:"scalar",T:4,opt:!0},{no:11,name:"nonce",kind:"scalar",T:12}])),wt=Fe.makeMessageType("livekit.SipDTMF",(()=>[{no:3,name:"code",kind:"scalar",T:13},{no:4,name:"digit",kind:"scalar",T:9}])),Rt=Fe.makeMessageType("livekit.Transcription",(()=>[{no:2,name:"transcribed_participant_identity",kind:"scalar",T:9},{no:3,name:"track_id",kind:"scalar",T:9},{no:4,name:"segments",kind:"message",T:Pt,repeated:!0}])),Pt=Fe.makeMessageType("livekit.TranscriptionSegment",(()=>[{no:1,name:"id",kind:"scalar",T:9},{no:2,name:"text",kind:"scalar",T:9},{no:3,name:"start_time",kind:"scalar",T:4},{no:4,name:"end_time",kind:"scalar",T:4},{no:5,name:"final",kind:"scalar",T:8},{no:6,name:"language",kind:"scalar",T:9}])),It=Fe.makeMessageType("livekit.ChatMessage",(()=>[{no:1,name:"id",kind:"scalar",T:9},{no:2,name:"timestamp",kind:"scalar",T:3},{no:3,name:"edit_timestamp",kind:"scalar",T:3,opt:!0},{no:4,name:"message",kind:"scalar",T:9},{no:5,name:"deleted",kind:"scalar",T:8},{no:6,name:"generated",kind:"scalar",T:8}])),Ot=Fe.makeMessageType("livekit.RpcRequest",(()=>[{no:1,name:"id",kind:"scalar",T:9},{no:2,name:"method",kind:"scalar",T:9},{no:3,name:"payload",kind:"scalar",T:9},{no:4,name:"response_timeout_ms",kind:"scalar",T:13},{no:5,name:"version",kind:"scalar",T:13}])),_t=Fe.makeMessageType("livekit.RpcAck",(()=>[{no:1,name:"request_id",kind:"scalar",T:9}])),Dt=Fe.makeMessageType("livekit.RpcResponse",(()=>[{no:1,name:"request_id",kind:"scalar",T:9},{no:2,name:"payload",kind:"scalar",T:9,oneof:"value"},{no:3,name:"error",kind:"message",T:Mt,oneof:"value"}])),Mt=Fe.makeMessageType("livekit.RpcError",(()=>[{no:1,name:"code",kind:"scalar",T:13},{no:2,name:"message",kind:"scalar",T:9},{no:3,name:"data",kind:"scalar",T:9}])),xt=Fe.makeMessageType("livekit.ParticipantTracks",(()=>[{no:1,name:"participant_sid",kind:"scalar",T:9},{no:2,name:"track_sids",kind:"scalar",T:9,repeated:!0}])),At=Fe.makeMessageType("livekit.ServerInfo",(()=>[{no:1,name:"edition",kind:"enum",T:Fe.getEnumType(Nt)},{no:2,name:"version",kind:"scalar",T:9},{no:3,name:"protocol",kind:"scalar",T:5},{no:4,name:"region",kind:"scalar",T:9},{no:5,name:"node_id",kind:"scalar",T:9},{no:6,name:"debug_info",kind:"scalar",T:9},{no:7,name:"agent_protocol",kind:"scalar",T:5}])),Nt=Fe.makeEnum("livekit.ServerInfo.Edition",[{no:0,name:"Standard"},{no:1,name:"Cloud"}]),Lt=Fe.makeMessageType("livekit.ClientInfo",(()=>[{no:1,name:"sdk",kind:"enum",T:Fe.getEnumType(Ut)},{no:2,name:"version",kind:"scalar",T:9},{no:3,name:"protocol",kind:"scalar",T:5},{no:4,name:"os",kind:"scalar",T:9},{no:5,name:"os_version",kind:"scalar",T:9},{no:6,name:"device_model",kind:"scalar",T:9},{no:7,name:"browser",kind:"scalar",T:9},{no:8,name:"browser_version",kind:"scalar",T:9},{no:9,name:"address",kind:"scalar",T:9},{no:10,name:"network",kind:"scalar",T:9},{no:11,name:"other_sdks",kind:"scalar",T:9}])),Ut=Fe.makeEnum("livekit.ClientInfo.SDK",[{no:0,name:"UNKNOWN"},{no:1,name:"JS"},{no:2,name:"SWIFT"},{no:3,name:"ANDROID"},{no:4,name:"FLUTTER"},{no:5,name:"GO"},{no:6,name:"UNITY"},{no:7,name:"REACT_NATIVE"},{no:8,name:"RUST"},{no:9,name:"PYTHON"},{no:10,name:"CPP"},{no:11,name:"UNITY_WEB"},{no:12,name:"NODE"},{no:13,name:"UNREAL"},{no:14,name:"ESP32"}]),jt=Fe.makeMessageType("livekit.ClientConfiguration",(()=>[{no:1,name:"video",kind:"message",T:Ft},{no:2,name:"screen",kind:"message",T:Ft},{no:3,name:"resume_connection",kind:"enum",T:Fe.getEnumType(tt)},{no:4,name:"disabled_codecs",kind:"message",T:Bt},{no:5,name:"force_relay",kind:"enum",T:Fe.getEnumType(tt)}])),Ft=Fe.makeMessageType("livekit.VideoConfiguration",(()=>[{no:1,name:"hardware_encoder",kind:"enum",T:Fe.getEnumType(tt)}])),Bt=Fe.makeMessageType("livekit.DisabledCodecs",(()=>[{no:1,name:"codecs",kind:"message",T:at,repeated:!0},{no:2,name:"publish",kind:"message",T:at,repeated:!0}])),Vt=Fe.makeMessageType("livekit.TimedVersion",(()=>[{no:1,name:"unix_micro",kind:"scalar",T:3},{no:2,name:"ticks",kind:"scalar",T:5}])),qt=Fe.makeEnum("livekit.DataStream.OperationType",[{no:0,name:"CREATE"},{no:1,name:"UPDATE"},{no:2,name:"DELETE"},{no:3,name:"REACTION"}]),Wt=Fe.makeMessageType("livekit.DataStream.TextHeader",(()=>[{no:1,name:"operation_type",kind:"enum",T:Fe.getEnumType(qt)},{no:2,name:"version",kind:"scalar",T:5},{no:3,name:"reply_to_stream_id",kind:"scalar",T:9},{no:4,name:"attached_stream_ids",kind:"scalar",T:9,repeated:!0},{no:5,name:"generated",kind:"scalar",T:8}]),{localName:"DataStream_TextHeader"}),Kt=Fe.makeMessageType("livekit.DataStream.ByteHeader",(()=>[{no:1,name:"name",kind:"scalar",T:9}]),{localName:"DataStream_ByteHeader"}),Ht=Fe.makeMessageType("livekit.DataStream.Header",(()=>[{no:1,name:"stream_id",kind:"scalar",T:9},{no:2,name:"timestamp",kind:"scalar",T:3},{no:3,name:"topic",kind:"scalar",T:9},{no:4,name:"mime_type",kind:"scalar",T:9},{no:5,name:"total_length",kind:"scalar",T:4,opt:!0},{no:7,name:"encryption_type",kind:"enum",T:Fe.getEnumType(pt)},{no:8,name:"attributes",kind:"map",K:9,V:{kind:"scalar",T:9}},{no:9,name:"text_header",kind:"message",T:Wt,oneof:"content_header"},{no:10,name:"byte_header",kind:"message",T:Kt,oneof:"content_header"}]),{localName:"DataStream_Header"}),Gt=Fe.makeMessageType("livekit.DataStream.Chunk",(()=>[{no:1,name:"stream_id",kind:"scalar",T:9},{no:2,name:"chunk_index",kind:"scalar",T:4},{no:3,name:"content",kind:"scalar",T:12},{no:4,name:"version",kind:"scalar",T:5},{no:5,name:"iv",kind:"scalar",T:12,opt:!0}]),{localName:"DataStream_Chunk"}),Jt=Fe.makeMessageType("livekit.DataStream.Trailer",(()=>[{no:1,name:"stream_id",kind:"scalar",T:9},{no:2,name:"reason",kind:"scalar",T:9},{no:3,name:"attributes",kind:"map",K:9,V:{kind:"scalar",T:9}}]),{localName:"DataStream_Trailer"}),zt=Fe.makeMessageType("livekit.FilterParams",(()=>[{no:1,name:"include_events",kind:"scalar",T:9,repeated:!0},{no:2,name:"exclude_events",kind:"scalar",T:9,repeated:!0}])),Qt=Fe.makeMessageType("livekit.WebhookConfig",(()=>[{no:1,name:"url",kind:"scalar",T:9},{no:2,name:"signing_key",kind:"scalar",T:9},{no:3,name:"filter_params",kind:"message",T:zt}])),Yt=Fe.makeMessageType("livekit.SubscribedAudioCodec",(()=>[{no:1,name:"codec",kind:"scalar",T:9},{no:2,name:"enabled",kind:"scalar",T:8}])),Xt=Fe.makeMessageType("livekit.RoomAgentDispatch",(()=>[{no:1,name:"agent_name",kind:"scalar",T:9},{no:2,name:"metadata",kind:"scalar",T:9}])),Zt=Fe.makeEnum("livekit.EncodedFileType",[{no:0,name:"DEFAULT_FILETYPE"},{no:1,name:"MP4"},{no:2,name:"OGG"},{no:3,name:"MP3"}]),$t=Fe.makeEnum("livekit.SegmentedFileProtocol",[{no:0,name:"DEFAULT_SEGMENTED_FILE_PROTOCOL"},{no:1,name:"HLS_PROTOCOL"}]),en=Fe.makeEnum("livekit.SegmentedFileSuffix",[{no:0,name:"INDEX"},{no:1,name:"TIMESTAMP"}]),tn=Fe.makeEnum("livekit.ImageFileSuffix",[{no:0,name:"IMAGE_SUFFIX_INDEX"},{no:1,name:"IMAGE_SUFFIX_TIMESTAMP"},{no:2,name:"IMAGE_SUFFIX_NONE_OVERWRITE"}]),nn=Fe.makeEnum("livekit.StreamProtocol",[{no:0,name:"DEFAULT_PROTOCOL"},{no:1,name:"RTMP"},{no:2,name:"SRT"}]),on=Fe.makeEnum("livekit.AudioMixing",[{no:0,name:"DEFAULT_MIXING"},{no:1,name:"DUAL_CHANNEL_AGENT"},{no:2,name:"DUAL_CHANNEL_ALTERNATE"}]),sn=Fe.makeEnum("livekit.EncodingOptionsPreset",[{no:0,name:"H264_720P_30"},{no:1,name:"H264_720P_60"},{no:2,name:"H264_1080P_30"},{no:3,name:"H264_1080P_60"},{no:4,name:"PORTRAIT_H264_720P_30"},{no:5,name:"PORTRAIT_H264_720P_60"},{no:6,name:"PORTRAIT_H264_1080P_30"},{no:7,name:"PORTRAIT_H264_1080P_60"}]),rn=Fe.makeMessageType("livekit.RoomCompositeEgressRequest",(()=>[{no:1,name:"room_name",kind:"scalar",T:9},{no:2,name:"layout",kind:"scalar",T:9},{no:3,name:"audio_only",kind:"scalar",T:8},{no:15,name:"audio_mixing",kind:"enum",T:Fe.getEnumType(on)},{no:4,name:"video_only",kind:"scalar",T:8},{no:5,name:"custom_base_url",kind:"scalar",T:9},{no:6,name:"file",kind:"message",T:an,oneof:"output"},{no:7,name:"stream",kind:"message",T:gn,oneof:"output"},{no:10,name:"segments",kind:"message",T:cn,oneof:"output"},{no:8,name:"preset",kind:"enum",T:Fe.getEnumType(sn),oneof:"options"},{no:9,name:"advanced",kind:"message",T:vn,oneof:"options"},{no:11,name:"file_outputs",kind:"message",T:an,repeated:!0},{no:12,name:"stream_outputs",kind:"message",T:gn,repeated:!0},{no:13,name:"segment_outputs",kind:"message",T:cn,repeated:!0},{no:14,name:"image_outputs",kind:"message",T:dn,repeated:!0},{no:16,name:"webhooks",kind:"message",T:Qt,repeated:!0}])),an=Fe.makeMessageType("livekit.EncodedFileOutput",(()=>[{no:1,name:"file_type",kind:"enum",T:Fe.getEnumType(Zt)},{no:2,name:"filepath",kind:"scalar",T:9},{no:6,name:"disable_manifest",kind:"scalar",T:8},{no:3,name:"s3",kind:"message",T:ln,oneof:"output"},{no:4,name:"gcp",kind:"message",T:un,oneof:"output"},{no:5,name:"azure",kind:"message",T:hn,oneof:"output"},{no:7,name:"aliOSS",kind:"message",T:pn,oneof:"output"}])),cn=Fe.makeMessageType("livekit.SegmentedFileOutput",(()=>[{no:1,name:"protocol",kind:"enum",T:Fe.getEnumType($t)},{no:2,name:"filename_prefix",kind:"scalar",T:9},{no:3,name:"playlist_name",kind:"scalar",T:9},{no:11,name:"live_playlist_name",kind:"scalar",T:9},{no:4,name:"segment_duration",kind:"scalar",T:13},{no:10,name:"filename_suffix",kind:"enum",T:Fe.getEnumType(en)},{no:8,name:"disable_manifest",kind:"scalar",T:8},{no:5,name:"s3",kind:"message",T:ln,oneof:"output"},{no:6,name:"gcp",kind:"message",T:un,oneof:"output"},{no:7,name:"azure",kind:"message",T:hn,oneof:"output"},{no:9,name:"aliOSS",kind:"message",T:pn,oneof:"output"}])),dn=Fe.makeMessageType("livekit.ImageOutput",(()=>[{no:1,name:"capture_interval",kind:"scalar",T:13},{no:2,name:"width",kind:"scalar",T:5},{no:3,name:"height",kind:"scalar",T:5},{no:4,name:"filename_prefix",kind:"scalar",T:9},{no:5,name:"filename_suffix",kind:"enum",T:Fe.getEnumType(tn)},{no:6,name:"image_codec",kind:"enum",T:Fe.getEnumType(Qe)},{no:7,name:"disable_manifest",kind:"scalar",T:8},{no:8,name:"s3",kind:"message",T:ln,oneof:"output"},{no:9,name:"gcp",kind:"message",T:un,oneof:"output"},{no:10,name:"azure",kind:"message",T:hn,oneof:"output"},{no:11,name:"aliOSS",kind:"message",T:pn,oneof:"output"}])),ln=Fe.makeMessageType("livekit.S3Upload",(()=>[{no:1,name:"access_key",kind:"scalar",T:9},{no:2,name:"secret",kind:"scalar",T:9},{no:11,name:"session_token",kind:"scalar",T:9},{no:12,name:"assume_role_arn",kind:"scalar",T:9},{no:13,name:"assume_role_external_id",kind:"scalar",T:9},{no:3,name:"region",kind:"scalar",T:9},{no:4,name:"endpoint",kind:"scalar",T:9},{no:5,name:"bucket",kind:"scalar",T:9},{no:6,name:"force_path_style",kind:"scalar",T:8},{no:7,name:"metadata",kind:"map",K:9,V:{kind:"scalar",T:9}},{no:8,name:"tagging",kind:"scalar",T:9},{no:9,name:"content_disposition",kind:"scalar",T:9},{no:10,name:"proxy",kind:"message",T:mn}])),un=Fe.makeMessageType("livekit.GCPUpload",(()=>[{no:1,name:"credentials",kind:"scalar",T:9},{no:2,name:"bucket",kind:"scalar",T:9},{no:3,name:"proxy",kind:"message",T:mn}])),hn=Fe.makeMessageType("livekit.AzureBlobUpload",(()=>[{no:1,name:"account_name",kind:"scalar",T:9},{no:2,name:"account_key",kind:"scalar",T:9},{no:3,name:"container_name",kind:"scalar",T:9}])),pn=Fe.makeMessageType("livekit.AliOSSUpload",(()=>[{no:1,name:"access_key",kind:"scalar",T:9},{no:2,name:"secret",kind:"scalar",T:9},{no:3,name:"region",kind:"scalar",T:9},{no:4,name:"endpoint",kind:"scalar",T:9},{no:5,name:"bucket",kind:"scalar",T:9}])),mn=Fe.makeMessageType("livekit.ProxyConfig",(()=>[{no:1,name:"url",kind:"scalar",T:9},{no:2,name:"username",kind:"scalar",T:9},{no:3,name:"password",kind:"scalar",T:9}])),gn=Fe.makeMessageType("livekit.StreamOutput",(()=>[{no:1,name:"protocol",kind:"enum",T:Fe.getEnumType(nn)},{no:2,name:"urls",kind:"scalar",T:9,repeated:!0}])),vn=Fe.makeMessageType("livekit.EncodingOptions",(()=>[{no:1,name:"width",kind:"scalar",T:5},{no:2,name:"height",kind:"scalar",T:5},{no:3,name:"depth",kind:"scalar",T:5},{no:4,name:"framerate",kind:"scalar",T:5},{no:5,name:"audio_codec",kind:"enum",T:Fe.getEnumType(Je)},{no:6,name:"audio_bitrate",kind:"scalar",T:5},{no:11,name:"audio_quality",kind:"scalar",T:5},{no:7,name:"audio_frequency",kind:"scalar",T:5},{no:8,name:"video_codec",kind:"enum",T:Fe.getEnumType(ze)},{no:9,name:"video_bitrate",kind:"scalar",T:5},{no:12,name:"video_quality",kind:"scalar",T:5},{no:10,name:"key_frame_interval",kind:"scalar",T:1}])),fn=Fe.makeMessageType("livekit.AutoParticipantEgress",(()=>[{no:1,name:"preset",kind:"enum",T:Fe.getEnumType(sn),oneof:"options"},{no:2,name:"advanced",kind:"message",T:vn,oneof:"options"},{no:3,name:"file_outputs",kind:"message",T:an,repeated:!0},{no:4,name:"segment_outputs",kind:"message",T:cn,repeated:!0}])),kn=Fe.makeMessageType("livekit.AutoTrackEgress",(()=>[{no:1,name:"filepath",kind:"scalar",T:9},{no:5,name:"disable_manifest",kind:"scalar",T:8},{no:2,name:"s3",kind:"message",T:ln,oneof:"output"},{no:3,name:"gcp",kind:"message",T:un,oneof:"output"},{no:4,name:"azure",kind:"message",T:hn,oneof:"output"},{no:6,name:"aliOSS",kind:"message",T:pn,oneof:"output"}])),yn=Fe.makeMessageType("livekit.RoomEgress",(()=>[{no:1,name:"room",kind:"message",T:rn},{no:3,name:"participant",kind:"message",T:fn},{no:2,name:"tracks",kind:"message",T:kn}])),bn=Fe.makeMessageType("livekit.RoomConfiguration",(()=>[{no:1,name:"name",kind:"scalar",T:9},{no:2,name:"empty_timeout",kind:"scalar",T:13},{no:3,name:"departure_timeout",kind:"scalar",T:13},{no:4,name:"max_participants",kind:"scalar",T:13},{no:11,name:"metadata",kind:"scalar",T:9},{no:5,name:"egress",kind:"message",T:yn},{no:7,name:"min_playout_delay",kind:"scalar",T:13},{no:8,name:"max_playout_delay",kind:"scalar",T:13},{no:9,name:"sync_streams",kind:"scalar",T:8},{no:10,name:"agents",kind:"message",T:Xt,repeated:!0}])),Tn=Fe.makeEnum("livekit.SignalTarget",[{no:0,name:"PUBLISHER"},{no:1,name:"SUBSCRIBER"}]),Cn=Fe.makeEnum("livekit.StreamState",[{no:0,name:"ACTIVE"},{no:1,name:"PAUSED"}]),Sn=Fe.makeEnum("livekit.CandidateProtocol",[{no:0,name:"UDP"},{no:1,name:"TCP"},{no:2,name:"TLS"}]),En=Fe.makeMessageType("livekit.SignalRequest",(()=>[{no:1,name:"offer",kind:"message",T:An,oneof:"message"},{no:2,name:"answer",kind:"message",T:An,oneof:"message"},{no:3,name:"trickle",kind:"message",T:In,oneof:"message"},{no:4,name:"add_track",kind:"message",T:Pn,oneof:"message"},{no:5,name:"mute",kind:"message",T:On,oneof:"message"},{no:6,name:"subscription",kind:"message",T:Ln,oneof:"message"},{no:7,name:"track_setting",kind:"message",T:Un,oneof:"message"},{no:8,name:"leave",kind:"message",T:Bn,oneof:"message"},{no:10,name:"update_layers",kind:"message",T:qn,oneof:"message"},{no:11,name:"subscription_permission",kind:"message",T:ni,oneof:"message"},{no:12,name:"sync_state",kind:"message",T:si,oneof:"message"},{no:13,name:"simulate",kind:"message",T:ci,oneof:"message"},{no:14,name:"ping",kind:"scalar",T:3,oneof:"message"},{no:15,name:"update_metadata",kind:"message",T:Wn,oneof:"message"},{no:16,name:"ping_req",kind:"message",T:di,oneof:"message"},{no:17,name:"update_audio_track",kind:"message",T:jn,oneof:"message"},{no:18,name:"update_video_track",kind:"message",T:Fn,oneof:"message"}])),wn=Fe.makeMessageType("livekit.SignalResponse",(()=>[{no:1,name:"join",kind:"message",T:_n,oneof:"message"},{no:2,name:"answer",kind:"message",T:An,oneof:"message"},{no:3,name:"offer",kind:"message",T:An,oneof:"message"},{no:4,name:"trickle",kind:"message",T:In,oneof:"message"},{no:5,name:"update",kind:"message",T:Nn,oneof:"message"},{no:6,name:"track_published",kind:"message",T:Mn,oneof:"message"},{no:8,name:"leave",kind:"message",T:Bn,oneof:"message"},{no:9,name:"mute",kind:"message",T:On,oneof:"message"},{no:10,name:"speakers_changed",kind:"message",T:Hn,oneof:"message"},{no:11,name:"room_update",kind:"message",T:Gn,oneof:"message"},{no:12,name:"connection_quality",kind:"message",T:zn,oneof:"message"},{no:13,name:"stream_state_update",kind:"message",T:Yn,oneof:"message"},{no:14,name:"subscribed_quality_update",kind:"message",T:$n,oneof:"message"},{no:15,name:"subscription_permission_update",kind:"message",T:ii,oneof:"message"},{no:16,name:"refresh_token",kind:"scalar",T:9,oneof:"message"},{no:17,name:"track_unpublished",kind:"message",T:xn,oneof:"message"},{no:18,name:"pong",kind:"scalar",T:3,oneof:"message"},{no:19,name:"reconnect",kind:"message",T:Dn,oneof:"message"},{no:20,name:"pong_resp",kind:"message",T:li,oneof:"message"},{no:21,name:"subscription_response",kind:"message",T:pi,oneof:"message"},{no:22,name:"request_response",kind:"message",T:mi,oneof:"message"},{no:23,name:"track_subscribed",kind:"message",T:vi,oneof:"message"},{no:24,name:"room_moved",kind:"message",T:oi,oneof:"message"},{no:25,name:"media_sections_requirement",kind:"message",T:Ti,oneof:"message"},{no:26,name:"subscribed_audio_codec_update",kind:"message",T:ei,oneof:"message"}])),Rn=Fe.makeMessageType("livekit.SimulcastCodec",(()=>[{no:1,name:"codec",kind:"scalar",T:9},{no:2,name:"cid",kind:"scalar",T:9},{no:4,name:"layers",kind:"message",T:vt,repeated:!0},{no:5,name:"video_layer_mode",kind:"enum",T:Fe.getEnumType(ft)}])),Pn=Fe.makeMessageType("livekit.AddTrackRequest",(()=>[{no:1,name:"cid",kind:"scalar",T:9},{no:2,name:"name",kind:"scalar",T:9},{no:3,name:"type",kind:"enum",T:Fe.getEnumType(Xe)},{no:4,name:"width",kind:"scalar",T:13},{no:5,name:"height",kind:"scalar",T:13},{no:6,name:"muted",kind:"scalar",T:8},{no:7,name:"disable_dtx",kind:"scalar",T:8},{no:8,name:"source",kind:"enum",T:Fe.getEnumType(Ze)},{no:9,name:"layers",kind:"message",T:vt,repeated:!0},{no:10,name:"simulcast_codecs",kind:"message",T:Rn,repeated:!0},{no:11,name:"sid",kind:"scalar",T:9},{no:12,name:"stereo",kind:"scalar",T:8},{no:13,name:"disable_red",kind:"scalar",T:8},{no:14,name:"encryption",kind:"enum",T:Fe.getEnumType(pt)},{no:15,name:"stream",kind:"scalar",T:9},{no:16,name:"backup_codec_policy",kind:"enum",T:Fe.getEnumType(Ye)},{no:17,name:"audio_features",kind:"enum",T:Fe.getEnumType(st),repeated:!0}])),In=Fe.makeMessageType("livekit.TrickleRequest",(()=>[{no:1,name:"candidateInit",kind:"scalar",T:9},{no:2,name:"target",kind:"enum",T:Fe.getEnumType(Tn)},{no:3,name:"final",kind:"scalar",T:8}])),On=Fe.makeMessageType("livekit.MuteTrackRequest",(()=>[{no:1,name:"sid",kind:"scalar",T:9},{no:2,name:"muted",kind:"scalar",T:8}])),_n=Fe.makeMessageType("livekit.JoinResponse",(()=>[{no:1,name:"room",kind:"message",T:rt},{no:2,name:"participant",kind:"message",T:dt},{no:3,name:"other_participants",kind:"message",T:dt,repeated:!0},{no:4,name:"server_version",kind:"scalar",T:9},{no:5,name:"ice_servers",kind:"message",T:Kn,repeated:!0},{no:6,name:"subscriber_primary",kind:"scalar",T:8},{no:7,name:"alternative_url",kind:"scalar",T:9},{no:8,name:"client_configuration",kind:"message",T:jt},{no:9,name:"server_region",kind:"scalar",T:9},{no:10,name:"ping_timeout",kind:"scalar",T:5},{no:11,name:"ping_interval",kind:"scalar",T:5},{no:12,name:"server_info",kind:"message",T:At},{no:13,name:"sif_trailer",kind:"scalar",T:12},{no:14,name:"enabled_publish_codecs",kind:"message",T:at,repeated:!0},{no:15,name:"fast_publish",kind:"scalar",T:8}])),Dn=Fe.makeMessageType("livekit.ReconnectResponse",(()=>[{no:1,name:"ice_servers",kind:"message",T:Kn,repeated:!0},{no:2,name:"client_configuration",kind:"message",T:jt},{no:3,name:"server_info",kind:"message",T:At},{no:4,name:"last_message_seq",kind:"scalar",T:13}])),Mn=Fe.makeMessageType("livekit.TrackPublishedResponse",(()=>[{no:1,name:"cid",kind:"scalar",T:9},{no:2,name:"track",kind:"message",T:gt}])),xn=Fe.makeMessageType("livekit.TrackUnpublishedResponse",(()=>[{no:1,name:"track_sid",kind:"scalar",T:9}])),An=Fe.makeMessageType("livekit.SessionDescription",(()=>[{no:1,name:"type",kind:"scalar",T:9},{no:2,name:"sdp",kind:"scalar",T:9},{no:3,name:"id",kind:"scalar",T:13},{no:4,name:"mid_to_track_id",kind:"map",K:9,V:{kind:"scalar",T:9}}])),Nn=Fe.makeMessageType("livekit.ParticipantUpdate",(()=>[{no:1,name:"participants",kind:"message",T:dt,repeated:!0}])),Ln=Fe.makeMessageType("livekit.UpdateSubscription",(()=>[{no:1,name:"track_sids",kind:"scalar",T:9,repeated:!0},{no:2,name:"subscribe",kind:"scalar",T:8},{no:3,name:"participant_tracks",kind:"message",T:xt,repeated:!0}])),Un=Fe.makeMessageType("livekit.UpdateTrackSettings",(()=>[{no:1,name:"track_sids",kind:"scalar",T:9,repeated:!0},{no:3,name:"disabled",kind:"scalar",T:8},{no:4,name:"quality",kind:"enum",T:Fe.getEnumType($e)},{no:5,name:"width",kind:"scalar",T:13},{no:6,name:"height",kind:"scalar",T:13},{no:7,name:"fps",kind:"scalar",T:13},{no:8,name:"priority",kind:"scalar",T:13}])),jn=Fe.makeMessageType("livekit.UpdateLocalAudioTrack",(()=>[{no:1,name:"track_sid",kind:"scalar",T:9},{no:2,name:"features",kind:"enum",T:Fe.getEnumType(st),repeated:!0}])),Fn=Fe.makeMessageType("livekit.UpdateLocalVideoTrack",(()=>[{no:1,name:"track_sid",kind:"scalar",T:9},{no:2,name:"width",kind:"scalar",T:13},{no:3,name:"height",kind:"scalar",T:13}])),Bn=Fe.makeMessageType("livekit.LeaveRequest",(()=>[{no:1,name:"can_reconnect",kind:"scalar",T:8},{no:2,name:"reason",kind:"enum",T:Fe.getEnumType(nt)},{no:3,name:"action",kind:"enum",T:Fe.getEnumType(Vn)},{no:4,name:"regions",kind:"message",T:ui}])),Vn=Fe.makeEnum("livekit.LeaveRequest.Action",[{no:0,name:"DISCONNECT"},{no:1,name:"RESUME"},{no:2,name:"RECONNECT"}]),qn=Fe.makeMessageType("livekit.UpdateVideoLayers",(()=>[{no:1,name:"track_sid",kind:"scalar",T:9},{no:2,name:"layers",kind:"message",T:vt,repeated:!0}])),Wn=Fe.makeMessageType("livekit.UpdateParticipantMetadata",(()=>[{no:1,name:"metadata",kind:"scalar",T:9},{no:2,name:"name",kind:"scalar",T:9},{no:3,name:"attributes",kind:"map",K:9,V:{kind:"scalar",T:9}},{no:4,name:"request_id",kind:"scalar",T:13}])),Kn=Fe.makeMessageType("livekit.ICEServer",(()=>[{no:1,name:"urls",kind:"scalar",T:9,repeated:!0},{no:2,name:"username",kind:"scalar",T:9},{no:3,name:"credential",kind:"scalar",T:9}])),Hn=Fe.makeMessageType("livekit.SpeakersChanged",(()=>[{no:1,name:"speakers",kind:"message",T:St,repeated:!0}])),Gn=Fe.makeMessageType("livekit.RoomUpdate",(()=>[{no:1,name:"room",kind:"message",T:rt}])),Jn=Fe.makeMessageType("livekit.ConnectionQualityInfo",(()=>[{no:1,name:"participant_sid",kind:"scalar",T:9},{no:2,name:"quality",kind:"enum",T:Fe.getEnumType(et)},{no:3,name:"score",kind:"scalar",T:2}])),zn=Fe.makeMessageType("livekit.ConnectionQualityUpdate",(()=>[{no:1,name:"updates",kind:"message",T:Jn,repeated:!0}])),Qn=Fe.makeMessageType("livekit.StreamStateInfo",(()=>[{no:1,name:"participant_sid",kind:"scalar",T:9},{no:2,name:"track_sid",kind:"scalar",T:9},{no:3,name:"state",kind:"enum",T:Fe.getEnumType(Cn)}])),Yn=Fe.makeMessageType("livekit.StreamStateUpdate",(()=>[{no:1,name:"stream_states",kind:"message",T:Qn,repeated:!0}])),Xn=Fe.makeMessageType("livekit.SubscribedQuality",(()=>[{no:1,name:"quality",kind:"enum",T:Fe.getEnumType($e)},{no:2,name:"enabled",kind:"scalar",T:8}])),Zn=Fe.makeMessageType("livekit.SubscribedCodec",(()=>[{no:1,name:"codec",kind:"scalar",T:9},{no:2,name:"qualities",kind:"message",T:Xn,repeated:!0}])),$n=Fe.makeMessageType("livekit.SubscribedQualityUpdate",(()=>[{no:1,name:"track_sid",kind:"scalar",T:9},{no:2,name:"subscribed_qualities",kind:"message",T:Xn,repeated:!0},{no:3,name:"subscribed_codecs",kind:"message",T:Zn,repeated:!0}])),ei=Fe.makeMessageType("livekit.SubscribedAudioCodecUpdate",(()=>[{no:1,name:"track_sid",kind:"scalar",T:9},{no:2,name:"subscribed_audio_codecs",kind:"message",T:Yt,repeated:!0}])),ti=Fe.makeMessageType("livekit.TrackPermission",(()=>[{no:1,name:"participant_sid",kind:"scalar",T:9},{no:2,name:"all_tracks",kind:"scalar",T:8},{no:3,name:"track_sids",kind:"scalar",T:9,repeated:!0},{no:4,name:"participant_identity",kind:"scalar",T:9}])),ni=Fe.makeMessageType("livekit.SubscriptionPermission",(()=>[{no:1,name:"all_participants",kind:"scalar",T:8},{no:2,name:"track_permissions",kind:"message",T:ti,repeated:!0}])),ii=Fe.makeMessageType("livekit.SubscriptionPermissionUpdate",(()=>[{no:1,name:"participant_sid",kind:"scalar",T:9},{no:2,name:"track_sid",kind:"scalar",T:9},{no:3,name:"allowed",kind:"scalar",T:8}])),oi=Fe.makeMessageType("livekit.RoomMovedResponse",(()=>[{no:1,name:"room",kind:"message",T:rt},{no:2,name:"token",kind:"scalar",T:9},{no:3,name:"participant",kind:"message",T:dt},{no:4,name:"other_participants",kind:"message",T:dt,repeated:!0}])),si=Fe.makeMessageType("livekit.SyncState",(()=>[{no:1,name:"answer",kind:"message",T:An},{no:2,name:"subscription",kind:"message",T:Ln},{no:3,name:"publish_tracks",kind:"message",T:Mn,repeated:!0},{no:4,name:"data_channels",kind:"message",T:ai,repeated:!0},{no:5,name:"offer",kind:"message",T:An},{no:6,name:"track_sids_disabled",kind:"scalar",T:9,repeated:!0},{no:7,name:"datachannel_receive_states",kind:"message",T:ri,repeated:!0}])),ri=Fe.makeMessageType("livekit.DataChannelReceiveState",(()=>[{no:1,name:"publisher_sid",kind:"scalar",T:9},{no:2,name:"last_seq",kind:"scalar",T:13}])),ai=Fe.makeMessageType("livekit.DataChannelInfo",(()=>[{no:1,name:"label",kind:"scalar",T:9},{no:2,name:"id",kind:"scalar",T:13},{no:3,name:"target",kind:"enum",T:Fe.getEnumType(Tn)}])),ci=Fe.makeMessageType("livekit.SimulateScenario",(()=>[{no:1,name:"speaker_update",kind:"scalar",T:5,oneof:"scenario"},{no:2,name:"node_failure",kind:"scalar",T:8,oneof:"scenario"},{no:3,name:"migration",kind:"scalar",T:8,oneof:"scenario"},{no:4,name:"server_leave",kind:"scalar",T:8,oneof:"scenario"},{no:5,name:"switch_candidate_protocol",kind:"enum",T:Fe.getEnumType(Sn),oneof:"scenario"},{no:6,name:"subscriber_bandwidth",kind:"scalar",T:3,oneof:"scenario"},{no:7,name:"disconnect_signal_on_resume",kind:"scalar",T:8,oneof:"scenario"},{no:8,name:"disconnect_signal_on_resume_no_messages",kind:"scalar",T:8,oneof:"scenario"},{no:9,name:"leave_request_full_reconnect",kind:"scalar",T:8,oneof:"scenario"}])),di=Fe.makeMessageType("livekit.Ping",(()=>[{no:1,name:"timestamp",kind:"scalar",T:3},{no:2,name:"rtt",kind:"scalar",T:3}])),li=Fe.makeMessageType("livekit.Pong",(()=>[{no:1,name:"last_ping_timestamp",kind:"scalar",T:3},{no:2,name:"timestamp",kind:"scalar",T:3}])),ui=Fe.makeMessageType("livekit.RegionSettings",(()=>[{no:1,name:"regions",kind:"message",T:hi,repeated:!0}])),hi=Fe.makeMessageType("livekit.RegionInfo",(()=>[{no:1,name:"region",kind:"scalar",T:9},{no:2,name:"url",kind:"scalar",T:9},{no:3,name:"distance",kind:"scalar",T:3}])),pi=Fe.makeMessageType("livekit.SubscriptionResponse",(()=>[{no:1,name:"track_sid",kind:"scalar",T:9},{no:2,name:"err",kind:"enum",T:Fe.getEnumType(ot)}])),mi=Fe.makeMessageType("livekit.RequestResponse",(()=>[{no:1,name:"request_id",kind:"scalar",T:13},{no:2,name:"reason",kind:"enum",T:Fe.getEnumType(gi)},{no:3,name:"message",kind:"scalar",T:9},{no:4,name:"trickle",kind:"message",T:In,oneof:"request"},{no:5,name:"add_track",kind:"message",T:Pn,oneof:"request"},{no:6,name:"mute",kind:"message",T:On,oneof:"request"},{no:7,name:"update_metadata",kind:"message",T:Wn,oneof:"request"},{no:8,name:"update_audio_track",kind:"message",T:jn,oneof:"request"},{no:9,name:"update_video_track",kind:"message",T:Fn,oneof:"request"}])),gi=Fe.makeEnum("livekit.RequestResponse.Reason",[{no:0,name:"OK"},{no:1,name:"NOT_FOUND"},{no:2,name:"NOT_ALLOWED"},{no:3,name:"LIMIT_EXCEEDED"},{no:4,name:"QUEUED"},{no:5,name:"UNSUPPORTED_TYPE"},{no:6,name:"UNCLASSIFIED_ERROR"}]),vi=Fe.makeMessageType("livekit.TrackSubscribed",(()=>[{no:1,name:"track_sid",kind:"scalar",T:9}])),fi=Fe.makeMessageType("livekit.ConnectionSettings",(()=>[{no:1,name:"auto_subscribe",kind:"scalar",T:8},{no:2,name:"adaptive_stream",kind:"scalar",T:8},{no:3,name:"subscriber_allow_pause",kind:"scalar",T:8,opt:!0},{no:4,name:"disable_ice_lite",kind:"scalar",T:8}])),ki=Fe.makeMessageType("livekit.JoinRequest",(()=>[{no:1,name:"client_info",kind:"message",T:Lt},{no:2,name:"connection_settings",kind:"message",T:fi},{no:3,name:"metadata",kind:"scalar",T:9},{no:4,name:"participant_attributes",kind:"map",K:9,V:{kind:"scalar",T:9}},{no:5,name:"add_track_requests",kind:"message",T:Pn,repeated:!0},{no:6,name:"publisher_offer",kind:"message",T:An},{no:7,name:"reconnect",kind:"scalar",T:8},{no:8,name:"reconnect_reason",kind:"enum",T:Fe.getEnumType(it)},{no:9,name:"participant_sid",kind:"scalar",T:9},{no:10,name:"sync_state",kind:"message",T:si}])),yi=Fe.makeMessageType("livekit.WrappedJoinRequest",(()=>[{no:1,name:"compression",kind:"enum",T:Fe.getEnumType(bi)},{no:2,name:"join_request",kind:"scalar",T:12}])),bi=Fe.makeEnum("livekit.WrappedJoinRequest.Compression",[{no:0,name:"NONE"},{no:1,name:"GZIP"}]),Ti=Fe.makeMessageType("livekit.MediaSectionsRequirement",(()=>[{no:1,name:"num_audios",kind:"scalar",T:13},{no:2,name:"num_videos",kind:"scalar",T:13}])),Ci=Fe.makeMessageType("livekit.TokenSourceRequest",(()=>[{no:1,name:"room_name",kind:"scalar",T:9,opt:!0},{no:2,name:"participant_name",kind:"scalar",T:9,opt:!0},{no:3,name:"participant_identity",kind:"scalar",T:9,opt:!0},{no:4,name:"participant_metadata",kind:"scalar",T:9,opt:!0},{no:5,name:"participant_attributes",kind:"map",K:9,V:{kind:"scalar",T:9}},{no:6,name:"room_config",kind:"message",T:bn,opt:!0}])),Si=Fe.makeMessageType("livekit.TokenSourceResponse",(()=>[{no:1,name:"server_url",kind:"scalar",T:9},{no:2,name:"participant_token",kind:"scalar",T:9}]));function Ei(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var wi,Ri={exports:{}},Pi=Ri.exports;var Ii,Oi,_i=(wi||(wi=1,function(e){var t,n;t=Pi,n=function(){var e=function(){},t="undefined",n=typeof window!==t&&typeof window.navigator!==t&&/Trident\/|MSIE /.test(window.navigator.userAgent),i=["trace","debug","info","warn","error"],o={},s=null;function r(e,t){var n=e[t];if("function"==typeof n.bind)return n.bind(e);try{return Function.prototype.bind.call(n,e)}catch(t){return function(){return Function.prototype.apply.apply(n,[e,arguments])}}}function a(){console.log&&(console.log.apply?console.log.apply(console,arguments):Function.prototype.apply.apply(console.log,[console,arguments])),console.trace&&console.trace()}function c(){for(var n=this.getLevel(),o=0;o=0&&t<=u.levels.SILENT)return t;throw new TypeError("log.setLevel() called with invalid level: "+e)}"string"==typeof e?h+=":"+e:"symbol"==typeof e&&(h=void 0),u.name=e,u.levels={TRACE:0,DEBUG:1,INFO:2,WARN:3,ERROR:4,SILENT:5},u.methodFactory=n||l,u.getLevel=function(){return null!=d?d:null!=a?a:r},u.setLevel=function(e,n){return d=m(e),!1!==n&&function(e){var n=(i[e]||"silent").toUpperCase();if(typeof window!==t&&h){try{return void(window.localStorage[h]=n)}catch(e){}try{window.document.cookie=encodeURIComponent(h)+"="+n+";"}catch(e){}}}(d),c.call(u)},u.setDefaultLevel=function(e){a=m(e),p()||u.setLevel(e,!1)},u.resetLevel=function(){d=null,function(){if(typeof window!==t&&h){try{window.localStorage.removeItem(h)}catch(e){}try{window.document.cookie=encodeURIComponent(h)+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC"}catch(e){}}}(),c.call(u)},u.enableAll=function(e){u.setLevel(u.levels.TRACE,e)},u.disableAll=function(e){u.setLevel(u.levels.SILENT,e)},u.rebuild=function(){if(s!==u&&(r=m(s.getLevel())),c.call(u),s===u)for(var e in o)o[e].rebuild()},r=m(s?s.getLevel():"WARN");var g=p();null!=g&&(d=m(g)),c.call(u)}(s=new u).getLogger=function(e){if("symbol"!=typeof e&&"string"!=typeof e||""===e)throw new TypeError("You must supply a name when creating a logger.");var t=o[e];return t||(t=o[e]=new u(e,s.methodFactory)),t};var h=typeof window!==t?window.log:void 0;return s.noConflict=function(){return typeof window!==t&&window.log===s&&(window.log=h),s},s.getLoggers=function(){return o},s.default=s,s},e.exports?e.exports=n():t.log=n()}(Ri)),Ri.exports);e.LogLevel=void 0,(Ii=e.LogLevel||(e.LogLevel={}))[Ii.trace=0]="trace",Ii[Ii.debug=1]="debug",Ii[Ii.info=2]="info",Ii[Ii.warn=3]="warn",Ii[Ii.error=4]="error",Ii[Ii.silent=5]="silent",e.LoggerNames=void 0,(Oi=e.LoggerNames||(e.LoggerNames={})).Default="livekit",Oi.Room="livekit-room",Oi.TokenSource="livekit-token-source",Oi.Participant="livekit-participant",Oi.Track="livekit-track",Oi.Publication="livekit-track-publication",Oi.Engine="livekit-engine",Oi.Signal="livekit-signal",Oi.PCManager="livekit-pc-manager",Oi.PCTransport="livekit-pc-transport",Oi.E2EE="lk-e2ee";let Di=_i.getLogger("livekit");const Mi=Object.values(e.LoggerNames).map((e=>_i.getLogger(e)));function xi(e){const t=_i.getLogger(e);return t.setDefaultLevel(Di.getLevel()),t}Di.setDefaultLevel(e.LogLevel.info);const Ai=_i.getLogger("lk-e2ee"),Ni=7e3,Li=[0,300,1200,2700,4800,Ni,Ni,Ni,Ni,Ni];class Ui{constructor(e){this._retryDelays=void 0!==e?[...e]:Li}nextRetryDelayInMs(e){if(e.retryCount>=this._retryDelays.length)return null;const t=this._retryDelays[e.retryCount];return e.retryCount<=1?t:t+1e3*Math.random()}}function ji(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&t.indexOf(i)<0&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(i=Object.getOwnPropertySymbols(e);o=e.length&&(e=void 0),{value:e&&e[i++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function Vi(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e=Bi(e),t={},i("next"),i("throw"),i("return"),t[Symbol.asyncIterator]=function(){return this},t);function i(n){t[n]=e[n]&&function(t){return new Promise((function(i,o){(function(e,t,n,i){Promise.resolve(i).then((function(t){e({value:t,done:n})}),t)})(i,o,(t=e[n](t)).done,t.value)}))}}}"function"==typeof SuppressedError&&SuppressedError;var qi,Wi={exports:{}};var Ki=function(){if(qi)return Wi.exports;qi=1;var e,t="object"==typeof Reflect?Reflect:null,n=t&&"function"==typeof t.apply?t.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)};e=t&&"function"==typeof t.ownKeys?t.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var i=Number.isNaN||function(e){return e!=e};function o(){o.init.call(this)}Wi.exports=o,Wi.exports.once=function(e,t){return new Promise((function(n,i){function o(n){e.removeListener(t,s),i(n)}function s(){"function"==typeof e.removeListener&&e.removeListener("error",o),n([].slice.call(arguments))}m(e,t,s,{once:!0}),"error"!==t&&function(e,t,n){"function"==typeof e.on&&m(e,"error",t,n)}(e,o,{once:!0})}))},o.EventEmitter=o,o.prototype._events=void 0,o.prototype._eventsCount=0,o.prototype._maxListeners=void 0;var s=10;function r(e){if("function"!=typeof e)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof e)}function a(e){return void 0===e._maxListeners?o.defaultMaxListeners:e._maxListeners}function c(e,t,n,i){var o,s,c,d;if(r(n),void 0===(s=e._events)?(s=e._events=Object.create(null),e._eventsCount=0):(void 0!==s.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),s=e._events),c=s[t]),void 0===c)c=s[t]=n,++e._eventsCount;else if("function"==typeof c?c=s[t]=i?[n,c]:[c,n]:i?c.unshift(n):c.push(n),(o=a(e))>0&&c.length>o&&!c.warned){c.warned=!0;var l=new Error("Possible EventEmitter memory leak detected. "+c.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");l.name="MaxListenersExceededWarning",l.emitter=e,l.type=t,l.count=c.length,d=l,console&&console.warn&&console.warn(d)}return e}function d(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function l(e,t,n){var i={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=d.bind(i);return o.listener=n,i.wrapFn=o,o}function u(e,t,n){var i=e._events;if(void 0===i)return[];var o=i[t];return void 0===o?[]:"function"==typeof o?n?[o.listener||o]:[o]:n?function(e){for(var t=new Array(e.length),n=0;n0&&(r=t[0]),r instanceof Error)throw r;var a=new Error("Unhandled error."+(r?" ("+r.message+")":""));throw a.context=r,a}var c=s[e];if(void 0===c)return!1;if("function"==typeof c)n(c,this,t);else{var d=c.length,l=p(c,d);for(i=0;i=0;s--)if(n[s]===t||n[s].listener===t){a=n[s].listener,o=s;break}if(o<0)return this;0===o?n.shift():function(e,t){for(;t+1=0;i--)this.removeListener(e,t[i]);return this},o.prototype.listeners=function(e){return u(this,e,!0)},o.prototype.rawListeners=function(e){return u(this,e,!1)},o.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):h.call(e,t)},o.prototype.listenerCount=h,o.prototype.eventNames=function(){return this._eventsCount>0?e(this._events):[]},Wi.exports}();let Hi=!0,Gi=!0;function Ji(e,t,n){const i=e.match(t);return i&&i.length>=n&&parseFloat(i[n],10)}function zi(e,t,n){if(!e.RTCPeerConnection)return;const i=e.RTCPeerConnection.prototype,o=i.addEventListener;i.addEventListener=function(e,i){if(e!==t)return o.apply(this,arguments);const s=e=>{const t=n(e);t&&(i.handleEvent?i.handleEvent(t):i(t))};return this._eventMap=this._eventMap||{},this._eventMap[t]||(this._eventMap[t]=new Map),this._eventMap[t].set(i,s),o.apply(this,[e,s])};const s=i.removeEventListener;i.removeEventListener=function(e,n){if(e!==t||!this._eventMap||!this._eventMap[t])return s.apply(this,arguments);if(!this._eventMap[t].has(n))return s.apply(this,arguments);const i=this._eventMap[t].get(n);return this._eventMap[t].delete(n),0===this._eventMap[t].size&&delete this._eventMap[t],0===Object.keys(this._eventMap).length&&delete this._eventMap,s.apply(this,[e,i])},Object.defineProperty(i,"on"+t,{get(){return this["_on"+t]},set(e){this["_on"+t]&&(this.removeEventListener(t,this["_on"+t]),delete this["_on"+t]),e&&this.addEventListener(t,this["_on"+t]=e)},enumerable:!0,configurable:!0})}function Qi(e){return"boolean"!=typeof e?new Error("Argument type: "+typeof e+". Please use a boolean."):(Hi=e,e?"adapter.js logging disabled":"adapter.js logging enabled")}function Yi(e){return"boolean"!=typeof e?new Error("Argument type: "+typeof e+". Please use a boolean."):(Gi=!e,"adapter.js deprecation warnings "+(e?"disabled":"enabled"))}function Xi(){if("object"==typeof window){if(Hi)return;"undefined"!=typeof console&&"function"==typeof console.log&&console.log.apply(console,arguments)}}function Zi(e,t){Gi&&console.warn(e+" is deprecated, please use "+t+" instead.")}function $i(e){return"[object Object]"===Object.prototype.toString.call(e)}function eo(e){return $i(e)?Object.keys(e).reduce((function(t,n){const i=$i(e[n]),o=i?eo(e[n]):e[n],s=i&&!Object.keys(o).length;return void 0===o||s?t:Object.assign(t,{[n]:o})}),{}):e}function to(e,t,n){t&&!n.has(t.id)&&(n.set(t.id,t),Object.keys(t).forEach((i=>{i.endsWith("Id")?to(e,e.get(t[i]),n):i.endsWith("Ids")&&t[i].forEach((t=>{to(e,e.get(t),n)}))})))}function no(e,t,n){const i=n?"outbound-rtp":"inbound-rtp",o=new Map;if(null===t)return o;const s=[];return e.forEach((e=>{"track"===e.type&&e.trackIdentifier===t.id&&s.push(e)})),s.forEach((t=>{e.forEach((n=>{n.type===i&&n.trackId===t.id&&to(e,n,o)}))})),o}const io=Xi;function oo(e,t){const n=e&&e.navigator;if(!n.mediaDevices)return;const i=function(e){if("object"!=typeof e||e.mandatory||e.optional)return e;const t={};return Object.keys(e).forEach((n=>{if("require"===n||"advanced"===n||"mediaSource"===n)return;const i="object"==typeof e[n]?e[n]:{ideal:e[n]};void 0!==i.exact&&"number"==typeof i.exact&&(i.min=i.max=i.exact);const o=function(e,t){return e?e+t.charAt(0).toUpperCase()+t.slice(1):"deviceId"===t?"sourceId":t};if(void 0!==i.ideal){t.optional=t.optional||[];let e={};"number"==typeof i.ideal?(e[o("min",n)]=i.ideal,t.optional.push(e),e={},e[o("max",n)]=i.ideal,t.optional.push(e)):(e[o("",n)]=i.ideal,t.optional.push(e))}void 0!==i.exact&&"number"!=typeof i.exact?(t.mandatory=t.mandatory||{},t.mandatory[o("",n)]=i.exact):["min","max"].forEach((e=>{void 0!==i[e]&&(t.mandatory=t.mandatory||{},t.mandatory[o(e,n)]=i[e])}))})),e.advanced&&(t.optional=(t.optional||[]).concat(e.advanced)),t},o=function(e,o){if(t.version>=61)return o(e);if((e=JSON.parse(JSON.stringify(e)))&&"object"==typeof e.audio){const t=function(e,t,n){t in e&&!(n in e)&&(e[n]=e[t],delete e[t])};t((e=JSON.parse(JSON.stringify(e))).audio,"autoGainControl","googAutoGainControl"),t(e.audio,"noiseSuppression","googNoiseSuppression"),e.audio=i(e.audio)}if(e&&"object"==typeof e.video){let s=e.video.facingMode;s=s&&("object"==typeof s?s:{ideal:s});const r=t.version<66;if(s&&("user"===s.exact||"environment"===s.exact||"user"===s.ideal||"environment"===s.ideal)&&(!n.mediaDevices.getSupportedConstraints||!n.mediaDevices.getSupportedConstraints().facingMode||r)){let t;if(delete e.video.facingMode,"environment"===s.exact||"environment"===s.ideal?t=["back","rear"]:"user"!==s.exact&&"user"!==s.ideal||(t=["front"]),t)return n.mediaDevices.enumerateDevices().then((n=>{let r=(n=n.filter((e=>"videoinput"===e.kind))).find((e=>t.some((t=>e.label.toLowerCase().includes(t)))));return!r&&n.length&&t.includes("back")&&(r=n[n.length-1]),r&&(e.video.deviceId=s.exact?{exact:r.deviceId}:{ideal:r.deviceId}),e.video=i(e.video),io("chrome: "+JSON.stringify(e)),o(e)}))}e.video=i(e.video)}return io("chrome: "+JSON.stringify(e)),o(e)},s=function(e){return t.version>=64?e:{name:{PermissionDeniedError:"NotAllowedError",PermissionDismissedError:"NotAllowedError",InvalidStateError:"NotAllowedError",DevicesNotFoundError:"NotFoundError",ConstraintNotSatisfiedError:"OverconstrainedError",TrackStartError:"NotReadableError",MediaDeviceFailedDueToShutdown:"NotAllowedError",MediaDeviceKillSwitchOn:"NotAllowedError",TabCaptureError:"AbortError",ScreenCaptureError:"AbortError",DeviceCaptureError:"AbortError"}[e.name]||e.name,message:e.message,constraint:e.constraint||e.constraintName,toString(){return this.name+(this.message&&": ")+this.message}}};if(n.getUserMedia=function(e,t,i){o(e,(e=>{n.webkitGetUserMedia(e,t,(e=>{i&&i(s(e))}))}))}.bind(n),n.mediaDevices.getUserMedia){const e=n.mediaDevices.getUserMedia.bind(n.mediaDevices);n.mediaDevices.getUserMedia=function(t){return o(t,(t=>e(t).then((e=>{if(t.audio&&!e.getAudioTracks().length||t.video&&!e.getVideoTracks().length)throw e.getTracks().forEach((e=>{e.stop()})),new DOMException("","NotFoundError");return e}),(e=>Promise.reject(s(e))))))}}}function so(e){e.MediaStream=e.MediaStream||e.webkitMediaStream}function ro(e){if("object"==typeof e&&e.RTCPeerConnection&&!("ontrack"in e.RTCPeerConnection.prototype)){Object.defineProperty(e.RTCPeerConnection.prototype,"ontrack",{get(){return this._ontrack},set(e){this._ontrack&&this.removeEventListener("track",this._ontrack),this.addEventListener("track",this._ontrack=e)},enumerable:!0,configurable:!0});const t=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(){return this._ontrackpoly||(this._ontrackpoly=t=>{t.stream.addEventListener("addtrack",(n=>{let i;i=e.RTCPeerConnection.prototype.getReceivers?this.getReceivers().find((e=>e.track&&e.track.id===n.track.id)):{track:n.track};const o=new Event("track");o.track=n.track,o.receiver=i,o.transceiver={receiver:i},o.streams=[t.stream],this.dispatchEvent(o)})),t.stream.getTracks().forEach((n=>{let i;i=e.RTCPeerConnection.prototype.getReceivers?this.getReceivers().find((e=>e.track&&e.track.id===n.id)):{track:n};const o=new Event("track");o.track=n,o.receiver=i,o.transceiver={receiver:i},o.streams=[t.stream],this.dispatchEvent(o)}))},this.addEventListener("addstream",this._ontrackpoly)),t.apply(this,arguments)}}else zi(e,"track",(e=>(e.transceiver||Object.defineProperty(e,"transceiver",{value:{receiver:e.receiver}}),e)))}function ao(e){if("object"==typeof e&&e.RTCPeerConnection&&!("getSenders"in e.RTCPeerConnection.prototype)&&"createDTMFSender"in e.RTCPeerConnection.prototype){const t=function(e,t){return{track:t,get dtmf(){return void 0===this._dtmf&&("audio"===t.kind?this._dtmf=e.createDTMFSender(t):this._dtmf=null),this._dtmf},_pc:e}};if(!e.RTCPeerConnection.prototype.getSenders){e.RTCPeerConnection.prototype.getSenders=function(){return this._senders=this._senders||[],this._senders.slice()};const n=e.RTCPeerConnection.prototype.addTrack;e.RTCPeerConnection.prototype.addTrack=function(e,i){let o=n.apply(this,arguments);return o||(o=t(this,e),this._senders.push(o)),o};const i=e.RTCPeerConnection.prototype.removeTrack;e.RTCPeerConnection.prototype.removeTrack=function(e){i.apply(this,arguments);const t=this._senders.indexOf(e);-1!==t&&this._senders.splice(t,1)}}const n=e.RTCPeerConnection.prototype.addStream;e.RTCPeerConnection.prototype.addStream=function(e){this._senders=this._senders||[],n.apply(this,[e]),e.getTracks().forEach((e=>{this._senders.push(t(this,e))}))};const i=e.RTCPeerConnection.prototype.removeStream;e.RTCPeerConnection.prototype.removeStream=function(e){this._senders=this._senders||[],i.apply(this,[e]),e.getTracks().forEach((e=>{const t=this._senders.find((t=>t.track===e));t&&this._senders.splice(this._senders.indexOf(t),1)}))}}else if("object"==typeof e&&e.RTCPeerConnection&&"getSenders"in e.RTCPeerConnection.prototype&&"createDTMFSender"in e.RTCPeerConnection.prototype&&e.RTCRtpSender&&!("dtmf"in e.RTCRtpSender.prototype)){const t=e.RTCPeerConnection.prototype.getSenders;e.RTCPeerConnection.prototype.getSenders=function(){const e=t.apply(this,[]);return e.forEach((e=>e._pc=this)),e},Object.defineProperty(e.RTCRtpSender.prototype,"dtmf",{get(){return void 0===this._dtmf&&("audio"===this.track.kind?this._dtmf=this._pc.createDTMFSender(this.track):this._dtmf=null),this._dtmf}})}}function co(e){if(!("object"==typeof e&&e.RTCPeerConnection&&e.RTCRtpSender&&e.RTCRtpReceiver))return;if(!("getStats"in e.RTCRtpSender.prototype)){const t=e.RTCPeerConnection.prototype.getSenders;t&&(e.RTCPeerConnection.prototype.getSenders=function(){const e=t.apply(this,[]);return e.forEach((e=>e._pc=this)),e});const n=e.RTCPeerConnection.prototype.addTrack;n&&(e.RTCPeerConnection.prototype.addTrack=function(){const e=n.apply(this,arguments);return e._pc=this,e}),e.RTCRtpSender.prototype.getStats=function(){const e=this;return this._pc.getStats().then((t=>no(t,e.track,!0)))}}if(!("getStats"in e.RTCRtpReceiver.prototype)){const t=e.RTCPeerConnection.prototype.getReceivers;t&&(e.RTCPeerConnection.prototype.getReceivers=function(){const e=t.apply(this,[]);return e.forEach((e=>e._pc=this)),e}),zi(e,"track",(e=>(e.receiver._pc=e.srcElement,e))),e.RTCRtpReceiver.prototype.getStats=function(){const e=this;return this._pc.getStats().then((t=>no(t,e.track,!1)))}}if(!("getStats"in e.RTCRtpSender.prototype)||!("getStats"in e.RTCRtpReceiver.prototype))return;const t=e.RTCPeerConnection.prototype.getStats;e.RTCPeerConnection.prototype.getStats=function(){if(arguments.length>0&&arguments[0]instanceof e.MediaStreamTrack){const e=arguments[0];let t,n,i;return this.getSenders().forEach((n=>{n.track===e&&(t?i=!0:t=n)})),this.getReceivers().forEach((t=>(t.track===e&&(n?i=!0:n=t),t.track===e))),i||t&&n?Promise.reject(new DOMException("There are more than one sender or receiver for the track.","InvalidAccessError")):t?t.getStats():n?n.getStats():Promise.reject(new DOMException("There is no sender or receiver for the track.","InvalidAccessError"))}return t.apply(this,arguments)}}function lo(e){e.RTCPeerConnection.prototype.getLocalStreams=function(){return this._shimmedLocalStreams=this._shimmedLocalStreams||{},Object.keys(this._shimmedLocalStreams).map((e=>this._shimmedLocalStreams[e][0]))};const t=e.RTCPeerConnection.prototype.addTrack;e.RTCPeerConnection.prototype.addTrack=function(e,n){if(!n)return t.apply(this,arguments);this._shimmedLocalStreams=this._shimmedLocalStreams||{};const i=t.apply(this,arguments);return this._shimmedLocalStreams[n.id]?-1===this._shimmedLocalStreams[n.id].indexOf(i)&&this._shimmedLocalStreams[n.id].push(i):this._shimmedLocalStreams[n.id]=[n,i],i};const n=e.RTCPeerConnection.prototype.addStream;e.RTCPeerConnection.prototype.addStream=function(e){this._shimmedLocalStreams=this._shimmedLocalStreams||{},e.getTracks().forEach((e=>{if(this.getSenders().find((t=>t.track===e)))throw new DOMException("Track already exists.","InvalidAccessError")}));const t=this.getSenders();n.apply(this,arguments);const i=this.getSenders().filter((e=>-1===t.indexOf(e)));this._shimmedLocalStreams[e.id]=[e].concat(i)};const i=e.RTCPeerConnection.prototype.removeStream;e.RTCPeerConnection.prototype.removeStream=function(e){return this._shimmedLocalStreams=this._shimmedLocalStreams||{},delete this._shimmedLocalStreams[e.id],i.apply(this,arguments)};const o=e.RTCPeerConnection.prototype.removeTrack;e.RTCPeerConnection.prototype.removeTrack=function(e){return this._shimmedLocalStreams=this._shimmedLocalStreams||{},e&&Object.keys(this._shimmedLocalStreams).forEach((t=>{const n=this._shimmedLocalStreams[t].indexOf(e);-1!==n&&this._shimmedLocalStreams[t].splice(n,1),1===this._shimmedLocalStreams[t].length&&delete this._shimmedLocalStreams[t]})),o.apply(this,arguments)}}function uo(e,t){if(!e.RTCPeerConnection)return;if(e.RTCPeerConnection.prototype.addTrack&&t.version>=65)return lo(e);const n=e.RTCPeerConnection.prototype.getLocalStreams;e.RTCPeerConnection.prototype.getLocalStreams=function(){const e=n.apply(this);return this._reverseStreams=this._reverseStreams||{},e.map((e=>this._reverseStreams[e.id]))};const i=e.RTCPeerConnection.prototype.addStream;e.RTCPeerConnection.prototype.addStream=function(t){if(this._streams=this._streams||{},this._reverseStreams=this._reverseStreams||{},t.getTracks().forEach((e=>{if(this.getSenders().find((t=>t.track===e)))throw new DOMException("Track already exists.","InvalidAccessError")})),!this._reverseStreams[t.id]){const n=new e.MediaStream(t.getTracks());this._streams[t.id]=n,this._reverseStreams[n.id]=t,t=n}i.apply(this,[t])};const o=e.RTCPeerConnection.prototype.removeStream;function s(e,t){let n=t.sdp;return Object.keys(e._reverseStreams||[]).forEach((t=>{const i=e._reverseStreams[t],o=e._streams[i.id];n=n.replace(new RegExp(o.id,"g"),i.id)})),new RTCSessionDescription({type:t.type,sdp:n})}e.RTCPeerConnection.prototype.removeStream=function(e){this._streams=this._streams||{},this._reverseStreams=this._reverseStreams||{},o.apply(this,[this._streams[e.id]||e]),delete this._reverseStreams[this._streams[e.id]?this._streams[e.id].id:e.id],delete this._streams[e.id]},e.RTCPeerConnection.prototype.addTrack=function(t,n){if("closed"===this.signalingState)throw new DOMException("The RTCPeerConnection's signalingState is 'closed'.","InvalidStateError");const i=[].slice.call(arguments,1);if(1!==i.length||!i[0].getTracks().find((e=>e===t)))throw new DOMException("The adapter.js addTrack polyfill only supports a single stream which is associated with the specified track.","NotSupportedError");if(this.getSenders().find((e=>e.track===t)))throw new DOMException("Track already exists.","InvalidAccessError");this._streams=this._streams||{},this._reverseStreams=this._reverseStreams||{};const o=this._streams[n.id];if(o)o.addTrack(t),Promise.resolve().then((()=>{this.dispatchEvent(new Event("negotiationneeded"))}));else{const i=new e.MediaStream([t]);this._streams[n.id]=i,this._reverseStreams[i.id]=n,this.addStream(i)}return this.getSenders().find((e=>e.track===t))},["createOffer","createAnswer"].forEach((function(t){const n=e.RTCPeerConnection.prototype[t],i={[t](){const e=arguments;return arguments.length&&"function"==typeof arguments[0]?n.apply(this,[t=>{const n=s(this,t);e[0].apply(null,[n])},t=>{e[1]&&e[1].apply(null,t)},arguments[2]]):n.apply(this,arguments).then((e=>s(this,e)))}};e.RTCPeerConnection.prototype[t]=i[t]}));const r=e.RTCPeerConnection.prototype.setLocalDescription;e.RTCPeerConnection.prototype.setLocalDescription=function(){return arguments.length&&arguments[0].type?(arguments[0]=function(e,t){let n=t.sdp;return Object.keys(e._reverseStreams||[]).forEach((t=>{const i=e._reverseStreams[t],o=e._streams[i.id];n=n.replace(new RegExp(i.id,"g"),o.id)})),new RTCSessionDescription({type:t.type,sdp:n})}(this,arguments[0]),r.apply(this,arguments)):r.apply(this,arguments)};const a=Object.getOwnPropertyDescriptor(e.RTCPeerConnection.prototype,"localDescription");Object.defineProperty(e.RTCPeerConnection.prototype,"localDescription",{get(){const e=a.get.apply(this);return""===e.type?e:s(this,e)}}),e.RTCPeerConnection.prototype.removeTrack=function(e){if("closed"===this.signalingState)throw new DOMException("The RTCPeerConnection's signalingState is 'closed'.","InvalidStateError");if(!e._pc)throw new DOMException("Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.","TypeError");if(!(e._pc===this))throw new DOMException("Sender was not created by this connection.","InvalidAccessError");let t;this._streams=this._streams||{},Object.keys(this._streams).forEach((n=>{this._streams[n].getTracks().find((t=>e.track===t))&&(t=this._streams[n])})),t&&(1===t.getTracks().length?this.removeStream(this._reverseStreams[t.id]):t.removeTrack(e.track),this.dispatchEvent(new Event("negotiationneeded")))}}function ho(e,t){!e.RTCPeerConnection&&e.webkitRTCPeerConnection&&(e.RTCPeerConnection=e.webkitRTCPeerConnection),e.RTCPeerConnection&&t.version<53&&["setLocalDescription","setRemoteDescription","addIceCandidate"].forEach((function(t){const n=e.RTCPeerConnection.prototype[t],i={[t](){return arguments[0]=new("addIceCandidate"===t?e.RTCIceCandidate:e.RTCSessionDescription)(arguments[0]),n.apply(this,arguments)}};e.RTCPeerConnection.prototype[t]=i[t]}))}function po(e,t){zi(e,"negotiationneeded",(e=>{const n=e.target;if(!(t.version<72||n.getConfiguration&&"plan-b"===n.getConfiguration().sdpSemantics)||"stable"===n.signalingState)return e}))}var mo=Object.freeze({__proto__:null,fixNegotiationNeeded:po,shimAddTrackRemoveTrack:uo,shimAddTrackRemoveTrackWithNative:lo,shimGetSendersWithDtmf:ao,shimGetUserMedia:oo,shimMediaStream:so,shimOnTrack:ro,shimPeerConnection:ho,shimSenderReceiverGetStats:co});function go(e,t){const n=e&&e.navigator,i=e&&e.MediaStreamTrack;if(n.getUserMedia=function(e,t,i){Zi("navigator.getUserMedia","navigator.mediaDevices.getUserMedia"),n.mediaDevices.getUserMedia(e).then(t,i)},!(t.version>55&&"autoGainControl"in n.mediaDevices.getSupportedConstraints())){const e=function(e,t,n){t in e&&!(n in e)&&(e[n]=e[t],delete e[t])},t=n.mediaDevices.getUserMedia.bind(n.mediaDevices);if(n.mediaDevices.getUserMedia=function(n){return"object"==typeof n&&"object"==typeof n.audio&&(n=JSON.parse(JSON.stringify(n)),e(n.audio,"autoGainControl","mozAutoGainControl"),e(n.audio,"noiseSuppression","mozNoiseSuppression")),t(n)},i&&i.prototype.getSettings){const t=i.prototype.getSettings;i.prototype.getSettings=function(){const n=t.apply(this,arguments);return e(n,"mozAutoGainControl","autoGainControl"),e(n,"mozNoiseSuppression","noiseSuppression"),n}}if(i&&i.prototype.applyConstraints){const t=i.prototype.applyConstraints;i.prototype.applyConstraints=function(n){return"audio"===this.kind&&"object"==typeof n&&(n=JSON.parse(JSON.stringify(n)),e(n,"autoGainControl","mozAutoGainControl"),e(n,"noiseSuppression","mozNoiseSuppression")),t.apply(this,[n])}}}}function vo(e){"object"==typeof e&&e.RTCTrackEvent&&"receiver"in e.RTCTrackEvent.prototype&&!("transceiver"in e.RTCTrackEvent.prototype)&&Object.defineProperty(e.RTCTrackEvent.prototype,"transceiver",{get(){return{receiver:this.receiver}}})}function fo(e,t){if("object"!=typeof e||!e.RTCPeerConnection&&!e.mozRTCPeerConnection)return;!e.RTCPeerConnection&&e.mozRTCPeerConnection&&(e.RTCPeerConnection=e.mozRTCPeerConnection),t.version<53&&["setLocalDescription","setRemoteDescription","addIceCandidate"].forEach((function(t){const n=e.RTCPeerConnection.prototype[t],i={[t](){return arguments[0]=new("addIceCandidate"===t?e.RTCIceCandidate:e.RTCSessionDescription)(arguments[0]),n.apply(this,arguments)}};e.RTCPeerConnection.prototype[t]=i[t]}));const n={inboundrtp:"inbound-rtp",outboundrtp:"outbound-rtp",candidatepair:"candidate-pair",localcandidate:"local-candidate",remotecandidate:"remote-candidate"},i=e.RTCPeerConnection.prototype.getStats;e.RTCPeerConnection.prototype.getStats=function(){const[e,o,s]=arguments;return i.apply(this,[e||null]).then((e=>{if(t.version<53&&!o)try{e.forEach((e=>{e.type=n[e.type]||e.type}))}catch(t){if("TypeError"!==t.name)throw t;e.forEach(((t,i)=>{e.set(i,Object.assign({},t,{type:n[t.type]||t.type}))}))}return e})).then(o,s)}}function ko(e){if("object"!=typeof e||!e.RTCPeerConnection||!e.RTCRtpSender)return;if(e.RTCRtpSender&&"getStats"in e.RTCRtpSender.prototype)return;const t=e.RTCPeerConnection.prototype.getSenders;t&&(e.RTCPeerConnection.prototype.getSenders=function(){const e=t.apply(this,[]);return e.forEach((e=>e._pc=this)),e});const n=e.RTCPeerConnection.prototype.addTrack;n&&(e.RTCPeerConnection.prototype.addTrack=function(){const e=n.apply(this,arguments);return e._pc=this,e}),e.RTCRtpSender.prototype.getStats=function(){return this.track?this._pc.getStats(this.track):Promise.resolve(new Map)}}function yo(e){if("object"!=typeof e||!e.RTCPeerConnection||!e.RTCRtpSender)return;if(e.RTCRtpSender&&"getStats"in e.RTCRtpReceiver.prototype)return;const t=e.RTCPeerConnection.prototype.getReceivers;t&&(e.RTCPeerConnection.prototype.getReceivers=function(){const e=t.apply(this,[]);return e.forEach((e=>e._pc=this)),e}),zi(e,"track",(e=>(e.receiver._pc=e.srcElement,e))),e.RTCRtpReceiver.prototype.getStats=function(){return this._pc.getStats(this.track)}}function bo(e){e.RTCPeerConnection&&!("removeStream"in e.RTCPeerConnection.prototype)&&(e.RTCPeerConnection.prototype.removeStream=function(e){Zi("removeStream","removeTrack"),this.getSenders().forEach((t=>{t.track&&e.getTracks().includes(t.track)&&this.removeTrack(t)}))})}function To(e){e.DataChannel&&!e.RTCDataChannel&&(e.RTCDataChannel=e.DataChannel)}function Co(e){if("object"!=typeof e||!e.RTCPeerConnection)return;const t=e.RTCPeerConnection.prototype.addTransceiver;t&&(e.RTCPeerConnection.prototype.addTransceiver=function(){this.setParametersPromises=[];let e=arguments[1]&&arguments[1].sendEncodings;void 0===e&&(e=[]),e=[...e];const n=e.length>0;n&&e.forEach((e=>{if("rid"in e){if(!/^[a-z0-9]{0,16}$/i.test(e.rid))throw new TypeError("Invalid RID value provided.")}if("scaleResolutionDownBy"in e&&!(parseFloat(e.scaleResolutionDownBy)>=1))throw new RangeError("scale_resolution_down_by must be >= 1.0");if("maxFramerate"in e&&!(parseFloat(e.maxFramerate)>=0))throw new RangeError("max_framerate must be >= 0.0")}));const i=t.apply(this,arguments);if(n){const{sender:t}=i,n=t.getParameters();(!("encodings"in n)||1===n.encodings.length&&0===Object.keys(n.encodings[0]).length)&&(n.encodings=e,t.sendEncodings=e,this.setParametersPromises.push(t.setParameters(n).then((()=>{delete t.sendEncodings})).catch((()=>{delete t.sendEncodings}))))}return i})}function So(e){if("object"!=typeof e||!e.RTCRtpSender)return;const t=e.RTCRtpSender.prototype.getParameters;t&&(e.RTCRtpSender.prototype.getParameters=function(){const e=t.apply(this,arguments);return"encodings"in e||(e.encodings=[].concat(this.sendEncodings||[{}])),e})}function Eo(e){if("object"!=typeof e||!e.RTCPeerConnection)return;const t=e.RTCPeerConnection.prototype.createOffer;e.RTCPeerConnection.prototype.createOffer=function(){return this.setParametersPromises&&this.setParametersPromises.length?Promise.all(this.setParametersPromises).then((()=>t.apply(this,arguments))).finally((()=>{this.setParametersPromises=[]})):t.apply(this,arguments)}}function wo(e){if("object"!=typeof e||!e.RTCPeerConnection)return;const t=e.RTCPeerConnection.prototype.createAnswer;e.RTCPeerConnection.prototype.createAnswer=function(){return this.setParametersPromises&&this.setParametersPromises.length?Promise.all(this.setParametersPromises).then((()=>t.apply(this,arguments))).finally((()=>{this.setParametersPromises=[]})):t.apply(this,arguments)}}var Ro=Object.freeze({__proto__:null,shimAddTransceiver:Co,shimCreateAnswer:wo,shimCreateOffer:Eo,shimGetDisplayMedia:function(e,t){e.navigator.mediaDevices&&"getDisplayMedia"in e.navigator.mediaDevices||e.navigator.mediaDevices&&(e.navigator.mediaDevices.getDisplayMedia=function(n){if(!n||!n.video){const e=new DOMException("getDisplayMedia without video constraints is undefined");return e.name="NotFoundError",e.code=8,Promise.reject(e)}return!0===n.video?n.video={mediaSource:t}:n.video.mediaSource=t,e.navigator.mediaDevices.getUserMedia(n)})},shimGetParameters:So,shimGetUserMedia:go,shimOnTrack:vo,shimPeerConnection:fo,shimRTCDataChannel:To,shimReceiverGetStats:yo,shimRemoveStream:bo,shimSenderGetStats:ko});function Po(e){if("object"==typeof e&&e.RTCPeerConnection){if("getLocalStreams"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.getLocalStreams=function(){return this._localStreams||(this._localStreams=[]),this._localStreams}),!("addStream"in e.RTCPeerConnection.prototype)){const t=e.RTCPeerConnection.prototype.addTrack;e.RTCPeerConnection.prototype.addStream=function(e){this._localStreams||(this._localStreams=[]),this._localStreams.includes(e)||this._localStreams.push(e),e.getAudioTracks().forEach((n=>t.call(this,n,e))),e.getVideoTracks().forEach((n=>t.call(this,n,e)))},e.RTCPeerConnection.prototype.addTrack=function(e){for(var n=arguments.length,i=new Array(n>1?n-1:0),o=1;o{this._localStreams?this._localStreams.includes(e)||this._localStreams.push(e):this._localStreams=[e]})),t.apply(this,arguments)}}"removeStream"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.removeStream=function(e){this._localStreams||(this._localStreams=[]);const t=this._localStreams.indexOf(e);if(-1===t)return;this._localStreams.splice(t,1);const n=e.getTracks();this.getSenders().forEach((e=>{n.includes(e.track)&&this.removeTrack(e)}))})}}function Io(e){if("object"==typeof e&&e.RTCPeerConnection&&("getRemoteStreams"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.getRemoteStreams=function(){return this._remoteStreams?this._remoteStreams:[]}),!("onaddstream"in e.RTCPeerConnection.prototype))){Object.defineProperty(e.RTCPeerConnection.prototype,"onaddstream",{get(){return this._onaddstream},set(e){this._onaddstream&&(this.removeEventListener("addstream",this._onaddstream),this.removeEventListener("track",this._onaddstreampoly)),this.addEventListener("addstream",this._onaddstream=e),this.addEventListener("track",this._onaddstreampoly=e=>{e.streams.forEach((e=>{if(this._remoteStreams||(this._remoteStreams=[]),this._remoteStreams.includes(e))return;this._remoteStreams.push(e);const t=new Event("addstream");t.stream=e,this.dispatchEvent(t)}))})}});const t=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(){const e=this;return this._onaddstreampoly||this.addEventListener("track",this._onaddstreampoly=function(t){t.streams.forEach((t=>{if(e._remoteStreams||(e._remoteStreams=[]),e._remoteStreams.indexOf(t)>=0)return;e._remoteStreams.push(t);const n=new Event("addstream");n.stream=t,e.dispatchEvent(n)}))}),t.apply(e,arguments)}}}function Oo(e){if("object"!=typeof e||!e.RTCPeerConnection)return;const t=e.RTCPeerConnection.prototype,n=t.createOffer,i=t.createAnswer,o=t.setLocalDescription,s=t.setRemoteDescription,r=t.addIceCandidate;t.createOffer=function(e,t){const i=arguments.length>=2?arguments[2]:arguments[0],o=n.apply(this,[i]);return t?(o.then(e,t),Promise.resolve()):o},t.createAnswer=function(e,t){const n=arguments.length>=2?arguments[2]:arguments[0],o=i.apply(this,[n]);return t?(o.then(e,t),Promise.resolve()):o};let a=function(e,t,n){const i=o.apply(this,[e]);return n?(i.then(t,n),Promise.resolve()):i};t.setLocalDescription=a,a=function(e,t,n){const i=s.apply(this,[e]);return n?(i.then(t,n),Promise.resolve()):i},t.setRemoteDescription=a,a=function(e,t,n){const i=r.apply(this,[e]);return n?(i.then(t,n),Promise.resolve()):i},t.addIceCandidate=a}function _o(e){const t=e&&e.navigator;if(t.mediaDevices&&t.mediaDevices.getUserMedia){const e=t.mediaDevices,n=e.getUserMedia.bind(e);t.mediaDevices.getUserMedia=e=>n(Do(e))}!t.getUserMedia&&t.mediaDevices&&t.mediaDevices.getUserMedia&&(t.getUserMedia=function(e,n,i){t.mediaDevices.getUserMedia(e).then(n,i)}.bind(t))}function Do(e){return e&&void 0!==e.video?Object.assign({},e,{video:eo(e.video)}):e}function Mo(e){if(!e.RTCPeerConnection)return;const t=e.RTCPeerConnection;e.RTCPeerConnection=function(e,n){if(e&&e.iceServers){const t=[];for(let n=0;nt.generateCertificate})}function xo(e){"object"==typeof e&&e.RTCTrackEvent&&"receiver"in e.RTCTrackEvent.prototype&&!("transceiver"in e.RTCTrackEvent.prototype)&&Object.defineProperty(e.RTCTrackEvent.prototype,"transceiver",{get(){return{receiver:this.receiver}}})}function Ao(e){const t=e.RTCPeerConnection.prototype.createOffer;e.RTCPeerConnection.prototype.createOffer=function(e){if(e){void 0!==e.offerToReceiveAudio&&(e.offerToReceiveAudio=!!e.offerToReceiveAudio);const t=this.getTransceivers().find((e=>"audio"===e.receiver.track.kind));!1===e.offerToReceiveAudio&&t?"sendrecv"===t.direction?t.setDirection?t.setDirection("sendonly"):t.direction="sendonly":"recvonly"===t.direction&&(t.setDirection?t.setDirection("inactive"):t.direction="inactive"):!0!==e.offerToReceiveAudio||t||this.addTransceiver("audio",{direction:"recvonly"}),void 0!==e.offerToReceiveVideo&&(e.offerToReceiveVideo=!!e.offerToReceiveVideo);const n=this.getTransceivers().find((e=>"video"===e.receiver.track.kind));!1===e.offerToReceiveVideo&&n?"sendrecv"===n.direction?n.setDirection?n.setDirection("sendonly"):n.direction="sendonly":"recvonly"===n.direction&&(n.setDirection?n.setDirection("inactive"):n.direction="inactive"):!0!==e.offerToReceiveVideo||n||this.addTransceiver("video",{direction:"recvonly"})}return t.apply(this,arguments)}}function No(e){"object"!=typeof e||e.AudioContext||(e.AudioContext=e.webkitAudioContext)}var Lo,Uo=Object.freeze({__proto__:null,shimAudioContext:No,shimCallbacksAPI:Oo,shimConstraints:Do,shimCreateOfferLegacy:Ao,shimGetUserMedia:_o,shimLocalStreamsAPI:Po,shimRTCIceServerUrls:Mo,shimRemoteStreamsAPI:Io,shimTrackEventTransceiver:xo}),jo={exports:{}};var Fo=(Lo||(Lo=1,function(e){const t={generateIdentifier:function(){return Math.random().toString(36).substring(2,12)}};t.localCName=t.generateIdentifier(),t.splitLines=function(e){return e.trim().split("\n").map((e=>e.trim()))},t.splitSections=function(e){return e.split("\nm=").map(((e,t)=>(t>0?"m="+e:e).trim()+"\r\n"))},t.getDescription=function(e){const n=t.splitSections(e);return n&&n[0]},t.getMediaSections=function(e){const n=t.splitSections(e);return n.shift(),n},t.matchPrefix=function(e,n){return t.splitLines(e).filter((e=>0===e.indexOf(n)))},t.parseCandidate=function(e){let t;t=0===e.indexOf("a=candidate:")?e.substring(12).split(" "):e.substring(10).split(" ");const n={foundation:t[0],component:{1:"rtp",2:"rtcp"}[t[1]]||t[1],protocol:t[2].toLowerCase(),priority:parseInt(t[3],10),ip:t[4],address:t[4],port:parseInt(t[5],10),type:t[7]};for(let e=8;e0?t[0].split("/")[1]:"sendrecv",uri:t[1],attributes:t.slice(2).join(" ")}},t.writeExtmap=function(e){return"a=extmap:"+(e.id||e.preferredId)+(e.direction&&"sendrecv"!==e.direction?"/"+e.direction:"")+" "+e.uri+(e.attributes?" "+e.attributes:"")+"\r\n"},t.parseFmtp=function(e){const t={};let n;const i=e.substring(e.indexOf(" ")+1).split(";");for(let e=0;e{void 0!==e.parameters[t]?i.push(t+"="+e.parameters[t]):i.push(t)})),t+="a=fmtp:"+n+" "+i.join(";")+"\r\n"}return t},t.parseRtcpFb=function(e){const t=e.substring(e.indexOf(" ")+1).split(" ");return{type:t.shift(),parameter:t.join(" ")}},t.writeRtcpFb=function(e){let t="",n=e.payloadType;return void 0!==e.preferredPayloadType&&(n=e.preferredPayloadType),e.rtcpFeedback&&e.rtcpFeedback.length&&e.rtcpFeedback.forEach((e=>{t+="a=rtcp-fb:"+n+" "+e.type+(e.parameter&&e.parameter.length?" "+e.parameter:"")+"\r\n"})),t},t.parseSsrcMedia=function(e){const t=e.indexOf(" "),n={ssrc:parseInt(e.substring(7,t),10)},i=e.indexOf(":",t);return i>-1?(n.attribute=e.substring(t+1,i),n.value=e.substring(i+1)):n.attribute=e.substring(t+1),n},t.parseSsrcGroup=function(e){const t=e.substring(13).split(" ");return{semantics:t.shift(),ssrcs:t.map((e=>parseInt(e,10)))}},t.getMid=function(e){const n=t.matchPrefix(e,"a=mid:")[0];if(n)return n.substring(6)},t.parseFingerprint=function(e){const t=e.substring(14).split(" ");return{algorithm:t[0].toLowerCase(),value:t[1].toUpperCase()}},t.getDtlsParameters=function(e,n){return{role:"auto",fingerprints:t.matchPrefix(e+n,"a=fingerprint:").map(t.parseFingerprint)}},t.writeDtlsParameters=function(e,t){let n="a=setup:"+t+"\r\n";return e.fingerprints.forEach((e=>{n+="a=fingerprint:"+e.algorithm+" "+e.value+"\r\n"})),n},t.parseCryptoLine=function(e){const t=e.substring(9).split(" ");return{tag:parseInt(t[0],10),cryptoSuite:t[1],keyParams:t[2],sessionParams:t.slice(3)}},t.writeCryptoLine=function(e){return"a=crypto:"+e.tag+" "+e.cryptoSuite+" "+("object"==typeof e.keyParams?t.writeCryptoKeyParams(e.keyParams):e.keyParams)+(e.sessionParams?" "+e.sessionParams.join(" "):"")+"\r\n"},t.parseCryptoKeyParams=function(e){if(0!==e.indexOf("inline:"))return null;const t=e.substring(7).split("|");return{keyMethod:"inline",keySalt:t[0],lifeTime:t[1],mkiValue:t[2]?t[2].split(":")[0]:void 0,mkiLength:t[2]?t[2].split(":")[1]:void 0}},t.writeCryptoKeyParams=function(e){return e.keyMethod+":"+e.keySalt+(e.lifeTime?"|"+e.lifeTime:"")+(e.mkiValue&&e.mkiLength?"|"+e.mkiValue+":"+e.mkiLength:"")},t.getCryptoParameters=function(e,n){return t.matchPrefix(e+n,"a=crypto:").map(t.parseCryptoLine)},t.getIceParameters=function(e,n){const i=t.matchPrefix(e+n,"a=ice-ufrag:")[0],o=t.matchPrefix(e+n,"a=ice-pwd:")[0];return i&&o?{usernameFragment:i.substring(12),password:o.substring(10)}:null},t.writeIceParameters=function(e){let t="a=ice-ufrag:"+e.usernameFragment+"\r\na=ice-pwd:"+e.password+"\r\n";return e.iceLite&&(t+="a=ice-lite\r\n"),t},t.parseRtpParameters=function(e){const n={codecs:[],headerExtensions:[],fecMechanisms:[],rtcp:[]},i=t.splitLines(e)[0].split(" ");n.profile=i[2];for(let o=3;o{n.headerExtensions.push(t.parseExtmap(e))}));const o=t.matchPrefix(e,"a=rtcp-fb:* ").map(t.parseRtcpFb);return n.codecs.forEach((e=>{o.forEach((t=>{e.rtcpFeedback.find((e=>e.type===t.type&&e.parameter===t.parameter))||e.rtcpFeedback.push(t)}))})),n},t.writeRtpDescription=function(e,n){let i="";i+="m="+e+" ",i+=n.codecs.length>0?"9":"0",i+=" "+(n.profile||"UDP/TLS/RTP/SAVPF")+" ",i+=n.codecs.map((e=>void 0!==e.preferredPayloadType?e.preferredPayloadType:e.payloadType)).join(" ")+"\r\n",i+="c=IN IP4 0.0.0.0\r\n",i+="a=rtcp:9 IN IP4 0.0.0.0\r\n",n.codecs.forEach((e=>{i+=t.writeRtpMap(e),i+=t.writeFmtp(e),i+=t.writeRtcpFb(e)}));let o=0;return n.codecs.forEach((e=>{e.maxptime>o&&(o=e.maxptime)})),o>0&&(i+="a=maxptime:"+o+"\r\n"),n.headerExtensions&&n.headerExtensions.forEach((e=>{i+=t.writeExtmap(e)})),i},t.parseRtpEncodingParameters=function(e){const n=[],i=t.parseRtpParameters(e),o=-1!==i.fecMechanisms.indexOf("RED"),s=-1!==i.fecMechanisms.indexOf("ULPFEC"),r=t.matchPrefix(e,"a=ssrc:").map((e=>t.parseSsrcMedia(e))).filter((e=>"cname"===e.attribute)),a=r.length>0&&r[0].ssrc;let c;const d=t.matchPrefix(e,"a=ssrc-group:FID").map((e=>e.substring(17).split(" ").map((e=>parseInt(e,10)))));d.length>0&&d[0].length>1&&d[0][0]===a&&(c=d[0][1]),i.codecs.forEach((e=>{if("RTX"===e.name.toUpperCase()&&e.parameters.apt){let t={ssrc:a,codecPayloadType:parseInt(e.parameters.apt,10)};a&&c&&(t.rtx={ssrc:c}),n.push(t),o&&(t=JSON.parse(JSON.stringify(t)),t.fec={ssrc:a,mechanism:s?"red+ulpfec":"red"},n.push(t))}})),0===n.length&&a&&n.push({ssrc:a});let l=t.matchPrefix(e,"b=");return l.length&&(l=0===l[0].indexOf("b=TIAS:")?parseInt(l[0].substring(7),10):0===l[0].indexOf("b=AS:")?1e3*parseInt(l[0].substring(5),10)*.95-16e3:void 0,n.forEach((e=>{e.maxBitrate=l}))),n},t.parseRtcpParameters=function(e){const n={},i=t.matchPrefix(e,"a=ssrc:").map((e=>t.parseSsrcMedia(e))).filter((e=>"cname"===e.attribute))[0];i&&(n.cname=i.value,n.ssrc=i.ssrc);const o=t.matchPrefix(e,"a=rtcp-rsize");n.reducedSize=o.length>0,n.compound=0===o.length;const s=t.matchPrefix(e,"a=rtcp-mux");return n.mux=s.length>0,n},t.writeRtcpParameters=function(e){let t="";return e.reducedSize&&(t+="a=rtcp-rsize\r\n"),e.mux&&(t+="a=rtcp-mux\r\n"),void 0!==e.ssrc&&e.cname&&(t+="a=ssrc:"+e.ssrc+" cname:"+e.cname+"\r\n"),t},t.parseMsid=function(e){let n;const i=t.matchPrefix(e,"a=msid:");if(1===i.length)return n=i[0].substring(7).split(" "),{stream:n[0],track:n[1]};const o=t.matchPrefix(e,"a=ssrc:").map((e=>t.parseSsrcMedia(e))).filter((e=>"msid"===e.attribute));return o.length>0?(n=o[0].value.split(" "),{stream:n[0],track:n[1]}):void 0},t.parseSctpDescription=function(e){const n=t.parseMLine(e),i=t.matchPrefix(e,"a=max-message-size:");let o;i.length>0&&(o=parseInt(i[0].substring(19),10)),isNaN(o)&&(o=65536);const s=t.matchPrefix(e,"a=sctp-port:");if(s.length>0)return{port:parseInt(s[0].substring(12),10),protocol:n.fmt,maxMessageSize:o};const r=t.matchPrefix(e,"a=sctpmap:");if(r.length>0){const e=r[0].substring(10).split(" ");return{port:parseInt(e[0],10),protocol:e[1],maxMessageSize:o}}},t.writeSctpDescription=function(e,t){let n=[];return n="DTLS/SCTP"!==e.protocol?["m="+e.kind+" 9 "+e.protocol+" "+t.protocol+"\r\n","c=IN IP4 0.0.0.0\r\n","a=sctp-port:"+t.port+"\r\n"]:["m="+e.kind+" 9 "+e.protocol+" "+t.port+"\r\n","c=IN IP4 0.0.0.0\r\n","a=sctpmap:"+t.port+" "+t.protocol+" 65535\r\n"],void 0!==t.maxMessageSize&&n.push("a=max-message-size:"+t.maxMessageSize+"\r\n"),n.join("")},t.generateSessionId=function(){return Math.random().toString().substr(2,22)},t.writeSessionBoilerplate=function(e,n,i){let o;const s=void 0!==n?n:2;return o=e||t.generateSessionId(),"v=0\r\no="+(i||"thisisadapterortc")+" "+o+" "+s+" IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\n"},t.getDirection=function(e,n){const i=t.splitLines(e);for(let e=0;e(t.candidate&&Object.defineProperty(t,"candidate",{value:new e.RTCIceCandidate(t.candidate),writable:"false"}),t)))}function Wo(e){!e.RTCIceCandidate||e.RTCIceCandidate&&"relayProtocol"in e.RTCIceCandidate.prototype||zi(e,"icecandidate",(e=>{if(e.candidate){const t=Bo.parseCandidate(e.candidate.candidate);"relay"===t.type&&(e.candidate.relayProtocol={0:"tls",1:"tcp",2:"udp"}[t.priority>>24])}return e}))}function Ko(e,t){if(!e.RTCPeerConnection)return;"sctp"in e.RTCPeerConnection.prototype||Object.defineProperty(e.RTCPeerConnection.prototype,"sctp",{get(){return void 0===this._sctp?null:this._sctp}});const n=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(){if(this._sctp=null,"chrome"===t.browser&&t.version>=76){const{sdpSemantics:e}=this.getConfiguration();"plan-b"===e&&Object.defineProperty(this,"sctp",{get(){return void 0===this._sctp?null:this._sctp},enumerable:!0,configurable:!0})}if(function(e){if(!e||!e.sdp)return!1;const t=Bo.splitSections(e.sdp);return t.shift(),t.some((e=>{const t=Bo.parseMLine(e);return t&&"application"===t.kind&&-1!==t.protocol.indexOf("SCTP")}))}(arguments[0])){const e=function(e){const t=e.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/);if(null===t||t.length<2)return-1;const n=parseInt(t[1],10);return n!=n?-1:n}(arguments[0]),n=function(e){let n=65536;return"firefox"===t.browser&&(n=t.version<57?-1===e?16384:2147483637:t.version<60?57===t.version?65535:65536:2147483637),n}(e),i=function(e,n){let i=65536;"firefox"===t.browser&&57===t.version&&(i=65535);const o=Bo.matchPrefix(e.sdp,"a=max-message-size:");return o.length>0?i=parseInt(o[0].substring(19),10):"firefox"===t.browser&&-1!==n&&(i=2147483637),i}(arguments[0],e);let o;o=0===n&&0===i?Number.POSITIVE_INFINITY:0===n||0===i?Math.max(n,i):Math.min(n,i);const s={};Object.defineProperty(s,"maxMessageSize",{get:()=>o}),this._sctp=s}return n.apply(this,arguments)}}function Ho(e){if(!e.RTCPeerConnection||!("createDataChannel"in e.RTCPeerConnection.prototype))return;function t(e,t){const n=e.send;e.send=function(){const i=arguments[0],o=i.length||i.size||i.byteLength;if("open"===e.readyState&&t.sctp&&o>t.sctp.maxMessageSize)throw new TypeError("Message too large (can send a maximum of "+t.sctp.maxMessageSize+" bytes)");return n.apply(e,arguments)}}const n=e.RTCPeerConnection.prototype.createDataChannel;e.RTCPeerConnection.prototype.createDataChannel=function(){const e=n.apply(this,arguments);return t(e,this),e},zi(e,"datachannel",(e=>(t(e.channel,e.target),e)))}function Go(e){if(!e.RTCPeerConnection||"connectionState"in e.RTCPeerConnection.prototype)return;const t=e.RTCPeerConnection.prototype;Object.defineProperty(t,"connectionState",{get(){return{completed:"connected",checking:"connecting"}[this.iceConnectionState]||this.iceConnectionState},enumerable:!0,configurable:!0}),Object.defineProperty(t,"onconnectionstatechange",{get(){return this._onconnectionstatechange||null},set(e){this._onconnectionstatechange&&(this.removeEventListener("connectionstatechange",this._onconnectionstatechange),delete this._onconnectionstatechange),e&&this.addEventListener("connectionstatechange",this._onconnectionstatechange=e)},enumerable:!0,configurable:!0}),["setLocalDescription","setRemoteDescription"].forEach((e=>{const n=t[e];t[e]=function(){return this._connectionstatechangepoly||(this._connectionstatechangepoly=e=>{const t=e.target;if(t._lastConnectionState!==t.connectionState){t._lastConnectionState=t.connectionState;const n=new Event("connectionstatechange",e);t.dispatchEvent(n)}return e},this.addEventListener("iceconnectionstatechange",this._connectionstatechangepoly)),n.apply(this,arguments)}}))}function Jo(e,t){if(!e.RTCPeerConnection)return;if("chrome"===t.browser&&t.version>=71)return;if("safari"===t.browser&&t._safariVersion>=13.1)return;const n=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(t){if(t&&t.sdp&&-1!==t.sdp.indexOf("\na=extmap-allow-mixed")){const n=t.sdp.split("\n").filter((e=>"a=extmap-allow-mixed"!==e.trim())).join("\n");e.RTCSessionDescription&&t instanceof e.RTCSessionDescription?arguments[0]=new e.RTCSessionDescription({type:t.type,sdp:n}):t.sdp=n}return n.apply(this,arguments)}}function zo(e,t){if(!e.RTCPeerConnection||!e.RTCPeerConnection.prototype)return;const n=e.RTCPeerConnection.prototype.addIceCandidate;n&&0!==n.length&&(e.RTCPeerConnection.prototype.addIceCandidate=function(){return arguments[0]?("chrome"===t.browser&&t.version<78||"firefox"===t.browser&&t.version<68||"safari"===t.browser)&&arguments[0]&&""===arguments[0].candidate?Promise.resolve():n.apply(this,arguments):(arguments[1]&&arguments[1].apply(null),Promise.resolve())})}function Qo(e,t){if(!e.RTCPeerConnection||!e.RTCPeerConnection.prototype)return;const n=e.RTCPeerConnection.prototype.setLocalDescription;n&&0!==n.length&&(e.RTCPeerConnection.prototype.setLocalDescription=function(){let e=arguments[0]||{};if("object"!=typeof e||e.type&&e.sdp)return n.apply(this,arguments);if(e={type:e.type,sdp:e.sdp},!e.type)switch(this.signalingState){case"stable":case"have-local-offer":case"have-remote-pranswer":e.type="offer";break;default:e.type="answer"}if(e.sdp||"offer"!==e.type&&"answer"!==e.type)return n.apply(this,[e]);return("offer"===e.type?this.createOffer:this.createAnswer).apply(this).then((e=>n.apply(this,[e])))})}var Yo=Object.freeze({__proto__:null,removeExtmapAllowMixed:Jo,shimAddIceCandidateNullOrEmpty:zo,shimConnectionState:Go,shimMaxMessageSize:Ko,shimParameterlessSetLocalDescription:Qo,shimRTCIceCandidate:qo,shimRTCIceCandidateRelayProtocol:Wo,shimSendThrowTypeError:Ho});!function(){let{window:e}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{shimChrome:!0,shimFirefox:!0,shimSafari:!0};const n=Xi,i=function(e){const t={browser:null,version:null};if(void 0===e||!e.navigator||!e.navigator.userAgent)return t.browser="Not a browser.",t;const{navigator:n}=e;if(n.userAgentData&&n.userAgentData.brands){const e=n.userAgentData.brands.find((e=>"Chromium"===e.brand));if(e)return{browser:"chrome",version:parseInt(e.version,10)}}if(n.mozGetUserMedia)t.browser="firefox",t.version=parseInt(Ji(n.userAgent,/Firefox\/(\d+)\./,1));else if(n.webkitGetUserMedia||!1===e.isSecureContext&&e.webkitRTCPeerConnection)t.browser="chrome",t.version=parseInt(Ji(n.userAgent,/Chrom(e|ium)\/(\d+)\./,2));else{if(!e.RTCPeerConnection||!n.userAgent.match(/AppleWebKit\/(\d+)\./))return t.browser="Not a supported browser.",t;t.browser="safari",t.version=parseInt(Ji(n.userAgent,/AppleWebKit\/(\d+)\./,1)),t.supportsUnifiedPlan=e.RTCRtpTransceiver&&"currentDirection"in e.RTCRtpTransceiver.prototype,t._safariVersion=Ji(n.userAgent,/Version\/(\d+(\.?\d+))/,1)}return t}(e),o={browserDetails:i,commonShim:Yo,extractVersion:Ji,disableLog:Qi,disableWarnings:Yi,sdp:Vo};switch(i.browser){case"chrome":if(!mo||!ho||!t.shimChrome)return n("Chrome shim is not included in this adapter release."),o;if(null===i.version)return n("Chrome shim can not determine version, not shimming."),o;n("adapter.js shimming chrome."),o.browserShim=mo,zo(e,i),Qo(e),oo(e,i),so(e),ho(e,i),ro(e),uo(e,i),ao(e),co(e),po(e,i),qo(e),Wo(e),Go(e),Ko(e,i),Ho(e),Jo(e,i);break;case"firefox":if(!Ro||!fo||!t.shimFirefox)return n("Firefox shim is not included in this adapter release."),o;n("adapter.js shimming firefox."),o.browserShim=Ro,zo(e,i),Qo(e),go(e,i),fo(e,i),vo(e),bo(e),ko(e),yo(e),To(e),Co(e),So(e),Eo(e),wo(e),qo(e),Go(e),Ko(e,i),Ho(e);break;case"safari":if(!Uo||!t.shimSafari)return n("Safari shim is not included in this adapter release."),o;n("adapter.js shimming safari."),o.browserShim=Uo,zo(e,i),Qo(e),Mo(e),Ao(e),Oo(e),Po(e),Io(e),xo(e),_o(e),No(e),qo(e),Wo(e),Ko(e,i),Ho(e),Jo(e,i);break;default:n("Unsupported browser!")}}({window:"undefined"==typeof window?void 0:window});class Xo extends Promise{constructor(e){super(e)}catch(e){return super.catch(e)}static reject(e){return super.reject(e)}static all(e){return super.all(e)}static race(e){return super.race(e)}}const Zo=/version\/(\d+(\.?_?\d+)+)/i;let $o;function es(e){let t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(void 0===e&&"undefined"==typeof navigator)return;const n=(null!=e?e:navigator.userAgent).toLowerCase();if(void 0===$o||t){const e=ts.find((e=>{let{test:t}=e;return t.test(n)}));$o=null==e?void 0:e.describe(n)}return $o}const ts=[{test:/firefox|iceweasel|fxios/i,describe:e=>({name:"Firefox",version:ns(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i,e),os:e.toLowerCase().includes("fxios")?"iOS":void 0,osVersion:is(e)})},{test:/chrom|crios|crmo/i,describe:e=>({name:"Chrome",version:ns(/(?:chrome|chromium|crios|crmo)\/(\d+(\.?_?\d+)+)/i,e),os:e.toLowerCase().includes("crios")?"iOS":void 0,osVersion:is(e)})},{test:/safari|applewebkit/i,describe:e=>({name:"Safari",version:ns(Zo,e),os:e.includes("mobile/")?"iOS":"macOS",osVersion:is(e)})}];function ns(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1;const i=t.match(e);return i&&i.length>=n&&i[n]||""}function is(e){return e.includes("mac os")?ns(/\(.+?(\d+_\d+(:?_\d+)?)/,e,1).replace(/_/g,"."):void 0}const os="2.17.0";class ss extends Error{constructor(e,t){super(t||"an error has occured"),this.name="LiveKitError",this.code=e}}var rs,as,cs,ds,ls,us,hs;e.ConnectionErrorReason=void 0,(rs=e.ConnectionErrorReason||(e.ConnectionErrorReason={}))[rs.NotAllowed=0]="NotAllowed",rs[rs.ServerUnreachable=1]="ServerUnreachable",rs[rs.InternalError=2]="InternalError",rs[rs.Cancelled=3]="Cancelled",rs[rs.LeaveRequest=4]="LeaveRequest",rs[rs.Timeout=5]="Timeout",rs[rs.WebSocket=6]="WebSocket",rs[rs.ServiceNotFound=7]="ServiceNotFound";class ps extends ss{constructor(t,n,i,o){super(1,t),this.name="ConnectionError",this.status=i,this.reason=n,this.context=o,this.reasonName=e.ConnectionErrorReason[n]}static notAllowed(t,n,i){return new ps(t,e.ConnectionErrorReason.NotAllowed,n,i)}static timeout(t){return new ps(t,e.ConnectionErrorReason.Timeout)}static leaveRequest(t,n){return new ps(t,e.ConnectionErrorReason.LeaveRequest,void 0,n)}static internal(t,n){return new ps(t,e.ConnectionErrorReason.InternalError,void 0,n)}static cancelled(t){return new ps(t,e.ConnectionErrorReason.Cancelled)}static serverUnreachable(t,n){return new ps(t,e.ConnectionErrorReason.ServerUnreachable,n)}static websocket(t,n,i){return new ps(t,e.ConnectionErrorReason.WebSocket,n,i)}static serviceNotFound(t,n){return new ps(t,e.ConnectionErrorReason.ServiceNotFound,void 0,n)}}class ms extends ss{constructor(e){super(21,null!=e?e:"device is unsupported"),this.name="DeviceUnsupportedError"}}class gs extends ss{constructor(e){super(20,null!=e?e:"track is invalid"),this.name="TrackInvalidError"}}class vs extends ss{constructor(e){super(10,null!=e?e:"unsupported server"),this.name="UnsupportedServer"}}class fs extends ss{constructor(e){super(12,null!=e?e:"unexpected connection state"),this.name="UnexpectedConnectionState"}}class ks extends ss{constructor(e){super(13,null!=e?e:"unable to negotiate"),this.name="NegotiationError"}}class ys extends ss{constructor(e,t){super(15,e),this.name="PublishTrackError",this.status=t}}class bs extends ss{constructor(e,t){super(15,e),this.name="SignalRequestError",this.reason=t,this.reasonName="string"==typeof t?t:gi[t]}}e.DataStreamErrorReason=void 0,(as=e.DataStreamErrorReason||(e.DataStreamErrorReason={}))[as.AlreadyOpened=0]="AlreadyOpened",as[as.AbnormalEnd=1]="AbnormalEnd",as[as.DecodeFailed=2]="DecodeFailed",as[as.LengthExceeded=3]="LengthExceeded",as[as.Incomplete=4]="Incomplete",as[as.HandlerAlreadyRegistered=7]="HandlerAlreadyRegistered",as[as.EncryptionTypeMismatch=8]="EncryptionTypeMismatch";class Ts extends ss{constructor(t,n){super(16,t),this.name="DataStreamError",this.reason=n,this.reasonName=e.DataStreamErrorReason[n]}}class Cs extends ss{constructor(e){super(18,e),this.name="SignalReconnectError"}}e.MediaDeviceFailure=void 0,(cs=e.MediaDeviceFailure||(e.MediaDeviceFailure={})).PermissionDenied="PermissionDenied",cs.NotFound="NotFound",cs.DeviceInUse="DeviceInUse",cs.Other="Other",function(e){e.getFailure=function(t){if(t&&"name"in t)return"NotFoundError"===t.name||"DevicesNotFoundError"===t.name?e.NotFound:"NotAllowedError"===t.name||"PermissionDeniedError"===t.name?e.PermissionDenied:"NotReadableError"===t.name||"TrackStartError"===t.name?e.DeviceInUse:e.Other}}(e.MediaDeviceFailure||(e.MediaDeviceFailure={}));class Ss{}Ss.setTimeout=function(){return setTimeout(...arguments)},Ss.setInterval=function(){return setInterval(...arguments)},Ss.clearTimeout=function(){return clearTimeout(...arguments)},Ss.clearInterval=function(){return clearInterval(...arguments)},e.RoomEvent=void 0,(ds=e.RoomEvent||(e.RoomEvent={})).Connected="connected",ds.Reconnecting="reconnecting",ds.SignalReconnecting="signalReconnecting",ds.Reconnected="reconnected",ds.Disconnected="disconnected",ds.ConnectionStateChanged="connectionStateChanged",ds.Moved="moved",ds.MediaDevicesChanged="mediaDevicesChanged",ds.ParticipantConnected="participantConnected",ds.ParticipantDisconnected="participantDisconnected",ds.TrackPublished="trackPublished",ds.TrackSubscribed="trackSubscribed",ds.TrackSubscriptionFailed="trackSubscriptionFailed",ds.TrackUnpublished="trackUnpublished",ds.TrackUnsubscribed="trackUnsubscribed",ds.TrackMuted="trackMuted",ds.TrackUnmuted="trackUnmuted",ds.LocalTrackPublished="localTrackPublished",ds.LocalTrackUnpublished="localTrackUnpublished",ds.LocalAudioSilenceDetected="localAudioSilenceDetected",ds.ActiveSpeakersChanged="activeSpeakersChanged",ds.ParticipantMetadataChanged="participantMetadataChanged",ds.ParticipantNameChanged="participantNameChanged",ds.ParticipantAttributesChanged="participantAttributesChanged",ds.ParticipantActive="participantActive",ds.RoomMetadataChanged="roomMetadataChanged",ds.DataReceived="dataReceived",ds.SipDTMFReceived="sipDTMFReceived",ds.TranscriptionReceived="transcriptionReceived",ds.ConnectionQualityChanged="connectionQualityChanged",ds.TrackStreamStateChanged="trackStreamStateChanged",ds.TrackSubscriptionPermissionChanged="trackSubscriptionPermissionChanged",ds.TrackSubscriptionStatusChanged="trackSubscriptionStatusChanged",ds.AudioPlaybackStatusChanged="audioPlaybackChanged",ds.VideoPlaybackStatusChanged="videoPlaybackChanged",ds.MediaDevicesError="mediaDevicesError",ds.ParticipantPermissionsChanged="participantPermissionsChanged",ds.SignalConnected="signalConnected",ds.RecordingStatusChanged="recordingStatusChanged",ds.ParticipantEncryptionStatusChanged="participantEncryptionStatusChanged",ds.EncryptionError="encryptionError",ds.DCBufferStatusChanged="dcBufferStatusChanged",ds.ActiveDeviceChanged="activeDeviceChanged",ds.ChatMessage="chatMessage",ds.LocalTrackSubscribed="localTrackSubscribed",ds.MetricsReceived="metricsReceived",e.ParticipantEvent=void 0,(ls=e.ParticipantEvent||(e.ParticipantEvent={})).TrackPublished="trackPublished",ls.TrackSubscribed="trackSubscribed",ls.TrackSubscriptionFailed="trackSubscriptionFailed",ls.TrackUnpublished="trackUnpublished",ls.TrackUnsubscribed="trackUnsubscribed",ls.TrackMuted="trackMuted",ls.TrackUnmuted="trackUnmuted",ls.LocalTrackPublished="localTrackPublished",ls.LocalTrackUnpublished="localTrackUnpublished",ls.LocalTrackCpuConstrained="localTrackCpuConstrained",ls.LocalSenderCreated="localSenderCreated",ls.ParticipantMetadataChanged="participantMetadataChanged",ls.ParticipantNameChanged="participantNameChanged",ls.DataReceived="dataReceived",ls.SipDTMFReceived="sipDTMFReceived",ls.TranscriptionReceived="transcriptionReceived",ls.IsSpeakingChanged="isSpeakingChanged",ls.ConnectionQualityChanged="connectionQualityChanged",ls.TrackStreamStateChanged="trackStreamStateChanged",ls.TrackSubscriptionPermissionChanged="trackSubscriptionPermissionChanged",ls.TrackSubscriptionStatusChanged="trackSubscriptionStatusChanged",ls.TrackCpuConstrained="trackCpuConstrained",ls.MediaDevicesError="mediaDevicesError",ls.AudioStreamAcquired="audioStreamAcquired",ls.ParticipantPermissionsChanged="participantPermissionsChanged",ls.PCTrackAdded="pcTrackAdded",ls.AttributesChanged="attributesChanged",ls.LocalTrackSubscribed="localTrackSubscribed",ls.ChatMessage="chatMessage",ls.Active="active",e.EngineEvent=void 0,(us=e.EngineEvent||(e.EngineEvent={})).TransportsCreated="transportsCreated",us.Connected="connected",us.Disconnected="disconnected",us.Resuming="resuming",us.Resumed="resumed",us.Restarting="restarting",us.Restarted="restarted",us.SignalResumed="signalResumed",us.SignalRestarted="signalRestarted",us.Closing="closing",us.MediaTrackAdded="mediaTrackAdded",us.ActiveSpeakersUpdate="activeSpeakersUpdate",us.DataPacketReceived="dataPacketReceived",us.RTPVideoMapUpdate="rtpVideoMapUpdate",us.DCBufferStatusChanged="dcBufferStatusChanged",us.ParticipantUpdate="participantUpdate",us.RoomUpdate="roomUpdate",us.SpeakersChanged="speakersChanged",us.StreamStateChanged="streamStateChanged",us.ConnectionQualityUpdate="connectionQualityUpdate",us.SubscriptionError="subscriptionError",us.SubscriptionPermissionUpdate="subscriptionPermissionUpdate",us.RemoteMute="remoteMute",us.SubscribedQualityUpdate="subscribedQualityUpdate",us.LocalTrackUnpublished="localTrackUnpublished",us.LocalTrackSubscribed="localTrackSubscribed",us.Offline="offline",us.SignalRequestResponse="signalRequestResponse",us.SignalConnected="signalConnected",us.RoomMoved="roomMoved",e.TrackEvent=void 0,(hs=e.TrackEvent||(e.TrackEvent={})).Message="message",hs.Muted="muted",hs.Unmuted="unmuted",hs.Restarted="restarted",hs.Ended="ended",hs.Subscribed="subscribed",hs.Unsubscribed="unsubscribed",hs.CpuConstrained="cpuConstrained",hs.UpdateSettings="updateSettings",hs.UpdateSubscription="updateSubscription",hs.AudioPlaybackStarted="audioPlaybackStarted",hs.AudioPlaybackFailed="audioPlaybackFailed",hs.AudioSilenceDetected="audioSilenceDetected",hs.VisibilityChanged="visibilityChanged",hs.VideoDimensionsChanged="videoDimensionsChanged",hs.VideoPlaybackStarted="videoPlaybackStarted",hs.VideoPlaybackFailed="videoPlaybackFailed",hs.ElementAttached="elementAttached",hs.ElementDetached="elementDetached",hs.UpstreamPaused="upstreamPaused",hs.UpstreamResumed="upstreamResumed",hs.SubscriptionPermissionChanged="subscriptionPermissionChanged",hs.SubscriptionStatusChanged="subscriptionStatusChanged",hs.SubscriptionFailed="subscriptionFailed",hs.TrackProcessorUpdate="trackProcessorUpdate",hs.AudioTrackFeatureUpdate="audioTrackFeatureUpdate",hs.TranscriptionReceived="transcriptionReceived",hs.TimeSyncUpdate="timeSyncUpdate",hs.PreConnectBufferFlushed="preConnectBufferFlushed";class Es{constructor(e,t,n,i,o){if("object"==typeof e)this.width=e.width,this.height=e.height,this.aspectRatio=e.aspectRatio,this.encoding={maxBitrate:e.maxBitrate,maxFramerate:e.maxFramerate,priority:e.priority};else{if(void 0===t||void 0===n)throw new TypeError("Unsupported options: provide at least width, height and maxBitrate");this.width=e,this.height=t,this.aspectRatio=e/t,this.encoding={maxBitrate:n,maxFramerate:i,priority:o}}}get resolution(){return{width:this.width,height:this.height,frameRate:this.encoding.maxFramerate,aspectRatio:this.aspectRatio}}}const ws=["opus","red"],Rs=["vp8","h264"],Ps=["vp8","h264","vp9","av1","h265"];function Is(e){return!!Rs.find((t=>t===e))}const Os=Is;var _s,Ds;e.BackupCodecPolicy=void 0,(_s=e.BackupCodecPolicy||(e.BackupCodecPolicy={}))[_s.PREFER_REGRESSION=0]="PREFER_REGRESSION",_s[_s.SIMULCAST=1]="SIMULCAST",_s[_s.REGRESSION=2]="REGRESSION",e.AudioPresets=void 0,(Ds=e.AudioPresets||(e.AudioPresets={})).telephone={maxBitrate:12e3},Ds.speech={maxBitrate:24e3},Ds.music={maxBitrate:48e3},Ds.musicStereo={maxBitrate:64e3},Ds.musicHighQuality={maxBitrate:96e3},Ds.musicHighQualityStereo={maxBitrate:128e3};const Ms={h90:new Es(160,90,9e4,20),h180:new Es(320,180,16e4,20),h216:new Es(384,216,18e4,20),h360:new Es(640,360,45e4,20),h540:new Es(960,540,8e5,25),h720:new Es(1280,720,17e5,30),h1080:new Es(1920,1080,3e6,30),h1440:new Es(2560,1440,5e6,30),h2160:new Es(3840,2160,8e6,30)},xs={h120:new Es(160,120,7e4,20),h180:new Es(240,180,125e3,20),h240:new Es(320,240,14e4,20),h360:new Es(480,360,33e4,20),h480:new Es(640,480,5e5,20),h540:new Es(720,540,6e5,25),h720:new Es(960,720,13e5,30),h1080:new Es(1440,1080,23e5,30),h1440:new Es(1920,1440,38e5,30)},As={h360fps3:new Es(640,360,2e5,3,"medium"),h360fps15:new Es(640,360,4e5,15,"medium"),h720fps5:new Es(1280,720,8e5,5,"medium"),h720fps15:new Es(1280,720,15e5,15,"medium"),h720fps30:new Es(1280,720,2e6,30,"medium"),h1080fps15:new Es(1920,1080,25e5,15,"medium"),h1080fps30:new Es(1920,1080,5e6,30,"medium"),original:new Es(0,0,7e6,30,"medium")};function Ns(e,t,n){var i,o,s,r;const{optionsWithoutProcessor:a,audioProcessor:c,videoProcessor:d}=Gs(null!=e?e:{}),l=null==t?void 0:t.processor,u=null==n?void 0:n.processor,h=null!=a?a:{};return!0===h.audio&&(h.audio={}),!0===h.video&&(h.video={}),h.audio&&(Ls(h.audio,t),null!==(i=(s=h.audio).deviceId)&&void 0!==i||(s.deviceId={ideal:"default"}),(c||l)&&(h.audio.processor=null!=c?c:l)),h.video&&(Ls(h.video,n),null!==(o=(r=h.video).deviceId)&&void 0!==o||(r.deviceId={ideal:"default"}),(d||u)&&(h.video.processor=null!=d?d:u)),h}function Ls(e,t){return Object.keys(t).forEach((n=>{void 0===e[n]&&(e[n]=t[n])})),e}function Us(e){var t,n,i,o;const s={};if(e.video)if("object"==typeof e.video){const n={},o=n,r=e.video;Object.keys(r).forEach((e=>{if("resolution"===e)Ls(o,r.resolution);else o[e]=r[e]})),s.video=n,null!==(t=(i=s.video).deviceId)&&void 0!==t||(i.deviceId={ideal:"default"})}else s.video=!!e.video&&{deviceId:{ideal:"default"}};else s.video=!1;return e.audio?"object"==typeof e.audio?(s.audio=e.audio,null!==(n=(o=s.audio).deviceId)&&void 0!==n||(o.deviceId={ideal:"default"})):s.audio={deviceId:{ideal:"default"}}:s.audio=!1,s}function js(e){return Fi(this,arguments,void 0,(function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:200;return function*(){const n=Fs();if(n){const i=n.createAnalyser();i.fftSize=2048;const o=i.frequencyBinCount,s=new Uint8Array(o);n.createMediaStreamSource(new MediaStream([e.mediaStreamTrack])).connect(i),yield er(t),i.getByteTimeDomainData(s);const r=s.some((e=>128!==e&&0!==e));return n.close(),!r}return!1}()}))}function Fs(){var e;const t="undefined"!=typeof window&&(window.AudioContext||window.webkitAudioContext);if(t){const n=new t({latencyHint:"interactive"});if("suspended"===n.state&&"undefined"!=typeof window&&(null===(e=window.document)||void 0===e?void 0:e.body)){const e=()=>Fi(this,void 0,void 0,(function*(){var t;try{"suspended"===n.state&&(yield n.resume())}catch(e){console.warn("Error trying to auto-resume audio context",e)}finally{null===(t=window.document.body)||void 0===t||t.removeEventListener("click",e)}}));n.addEventListener("statechange",(()=>{var t;"closed"===n.state&&(null===(t=window.document.body)||void 0===t||t.removeEventListener("click",e))})),window.document.body.addEventListener("click",e)}return n}}function Bs(e){return"audioinput"===e?Ys.Source.Microphone:"videoinput"===e?Ys.Source.Camera:Ys.Source.Unknown}function Vs(e){return e===Ys.Source.Microphone?"audioinput":e===Ys.Source.Camera?"videoinput":void 0}function qs(e){var t,n;let i=null===(t=e.video)||void 0===t||t;return e.resolution&&e.resolution.width>0&&e.resolution.height>0&&(i="boolean"==typeof i?{}:i,i=lr()?Object.assign(Object.assign({},i),{width:{max:e.resolution.width},height:{max:e.resolution.height},frameRate:e.resolution.frameRate}):Object.assign(Object.assign({},i),{width:{ideal:e.resolution.width},height:{ideal:e.resolution.height},frameRate:e.resolution.frameRate})),{audio:null!==(n=e.audio)&&void 0!==n&&n,video:i,controller:e.controller,selfBrowserSurface:e.selfBrowserSurface,surfaceSwitching:e.surfaceSwitching,systemAudio:e.systemAudio,preferCurrentTab:e.preferCurrentTab}}function Ws(e){return e.split("/")[1].toLowerCase()}function Ks(e){const t=[];return e.forEach((e=>{void 0!==e.track&&t.push(new Mn({cid:e.track.mediaStreamID,track:e.trackInfo}))})),t}function Hs(e){return"mediaStreamTrack"in e?{trackID:e.sid,source:e.source,muted:e.isMuted,enabled:e.mediaStreamTrack.enabled,kind:e.kind,streamID:e.mediaStreamID,streamTrackID:e.mediaStreamTrack.id}:{trackID:e.trackSid,enabled:e.isEnabled,muted:e.isMuted,trackInfo:Object.assign({mimeType:e.mimeType,name:e.trackName,encrypted:e.isEncrypted,kind:e.kind,source:e.source},e.track?Hs(e.track):{})}}function Gs(e){const t=Object.assign({},e);let n,i;return"object"==typeof t.audio&&t.audio.processor&&(n=t.audio.processor,t.audio=Object.assign(Object.assign({},t.audio),{processor:void 0})),"object"==typeof t.video&&t.video.processor&&(i=t.video.processor,t.video=Object.assign(Object.assign({},t.video),{processor:void 0})),{audioProcessor:n,videoProcessor:i,optionsWithoutProcessor:(o=t,void 0===o?o:"function"==typeof structuredClone?"object"==typeof o&&null!==o?structuredClone(Object.assign({},o)):structuredClone(o):JSON.parse(JSON.stringify(o)))};var o}function Js(e,t){return e.width*e.height2&&void 0!==arguments[2]?arguments[2]:{};var o;super(),this.attachedElements=[],this.isMuted=!1,this._streamState=Ys.StreamState.Active,this.isInBackground=!1,this._currentBitrate=0,this.log=Di,this.appVisibilityChangedListener=()=>{this.backgroundTimeout&&clearTimeout(this.backgroundTimeout),"hidden"===document.visibilityState?this.backgroundTimeout=setTimeout((()=>this.handleAppVisibilityChanged()),5e3):this.handleAppVisibilityChanged()},this.log=xi(null!==(o=i.loggerName)&&void 0!==o?o:e.LoggerNames.Track),this.loggerContextCb=i.loggerContextCb,this.setMaxListeners(100),this.kind=n,this._mediaStreamTrack=t,this._mediaStreamID=t.id,this.source=Ys.Source.Unknown}get logContext(){var e;return Object.assign(Object.assign({},null===(e=this.loggerContextCb)||void 0===e?void 0:e.call(this)),Hs(this))}get currentBitrate(){return this._currentBitrate}get mediaStreamTrack(){return this._mediaStreamTrack}get mediaStreamID(){return this._mediaStreamID}attach(t){let n="audio";this.kind===Ys.Kind.Video&&(n="video"),0===this.attachedElements.length&&this.kind===Ys.Kind.Video&&this.addAppVisibilityListener(),t||("audio"===n&&(zs.forEach((e=>{null!==e.parentElement||t||(t=e)})),t&&zs.splice(zs.indexOf(t),1)),t||(t=document.createElement(n))),this.attachedElements.includes(t)||this.attachedElements.push(t),Xs(this.mediaStreamTrack,t);const i=t.srcObject.getTracks(),o=i.some((e=>"audio"===e.kind));return t.play().then((()=>{this.emit(o?e.TrackEvent.AudioPlaybackStarted:e.TrackEvent.VideoPlaybackStarted)})).catch((n=>{"NotAllowedError"===n.name?this.emit(o?e.TrackEvent.AudioPlaybackFailed:e.TrackEvent.VideoPlaybackFailed,n):"AbortError"===n.name?Di.debug("".concat(o?"audio":"video"," playback aborted, likely due to new play request")):Di.warn("could not playback ".concat(o?"audio":"video"),n),o&&t&&i.some((e=>"video"===e.kind))&&"NotAllowedError"===n.name&&(t.muted=!0,t.play().catch((()=>{})))})),this.emit(e.TrackEvent.ElementAttached,t),t}detach(t){try{if(t){Zs(this.mediaStreamTrack,t);const n=this.attachedElements.indexOf(t);return n>=0&&(this.attachedElements.splice(n,1),this.recycleElement(t),this.emit(e.TrackEvent.ElementDetached,t)),t}const n=[];return this.attachedElements.forEach((t=>{Zs(this.mediaStreamTrack,t),n.push(t),this.recycleElement(t),this.emit(e.TrackEvent.ElementDetached,t)})),this.attachedElements=[],n}finally{0===this.attachedElements.length&&this.removeAppVisibilityListener()}}stop(){this.stopMonitor(),this._mediaStreamTrack.stop()}enable(){this._mediaStreamTrack.enabled=!0}disable(){this._mediaStreamTrack.enabled=!1}stopMonitor(){this.monitorInterval&&clearInterval(this.monitorInterval),this.timeSyncHandle&&cancelAnimationFrame(this.timeSyncHandle)}updateLoggerOptions(e){e.loggerName&&(this.log=xi(e.loggerName)),e.loggerContextCb&&(this.loggerContextCb=e.loggerContextCb)}recycleElement(e){if(e instanceof HTMLAudioElement){let t=!0;e.pause(),zs.forEach((e=>{e.parentElement||(t=!1)})),t&&zs.push(e)}}handleAppVisibilityChanged(){return Fi(this,void 0,void 0,(function*(){this.isInBackground="hidden"===document.visibilityState,this.isInBackground||this.kind!==Ys.Kind.Video||setTimeout((()=>this.attachedElements.forEach((e=>e.play().catch((()=>{}))))),0)}))}addAppVisibilityListener(){mr()?(this.isInBackground="hidden"===document.visibilityState,document.addEventListener("visibilitychange",this.appVisibilityChangedListener)):this.isInBackground=!1}removeAppVisibilityListener(){mr()&&document.removeEventListener("visibilitychange",this.appVisibilityChangedListener)}}function Xs(e,t){let n,i;n=t.srcObject instanceof MediaStream?t.srcObject:new MediaStream,i="audio"===e.kind?n.getAudioTracks():n.getVideoTracks(),i.includes(e)||(i.forEach((e=>{n.removeTrack(e)})),n.addTrack(e)),lr()&&t instanceof HTMLVideoElement||(t.autoplay=!0),t.muted=0===n.getAudioTracks().length,t instanceof HTMLVideoElement&&(t.playsInline=!0),t.srcObject!==n&&(t.srcObject=n,(lr()||cr())&&t instanceof HTMLVideoElement&&setTimeout((()=>{t.srcObject=n,t.play().catch((()=>{}))}),0))}function Zs(e,t){if(t.srcObject instanceof MediaStream){const n=t.srcObject;n.removeTrack(e),n.getTracks().length>0?t.srcObject=n:t.srcObject=null}}!function(e){let t,n,i;!function(e){e.Audio="audio",e.Video="video",e.Unknown="unknown"}(t=e.Kind||(e.Kind={})),function(e){e.Camera="camera",e.Microphone="microphone",e.ScreenShare="screen_share",e.ScreenShareAudio="screen_share_audio",e.Unknown="unknown"}(n=e.Source||(e.Source={})),function(e){e.Active="active",e.Paused="paused",e.Unknown="unknown"}(i=e.StreamState||(e.StreamState={})),e.kindToProto=function(e){switch(e){case t.Audio:return Xe.AUDIO;case t.Video:return Xe.VIDEO;default:return Xe.DATA}},e.kindFromProto=function(e){switch(e){case Xe.AUDIO:return t.Audio;case Xe.VIDEO:return t.Video;default:return t.Unknown}},e.sourceToProto=function(e){switch(e){case n.Camera:return Ze.CAMERA;case n.Microphone:return Ze.MICROPHONE;case n.ScreenShare:return Ze.SCREEN_SHARE;case n.ScreenShareAudio:return Ze.SCREEN_SHARE_AUDIO;default:return Ze.UNKNOWN}},e.sourceFromProto=function(e){switch(e){case Ze.CAMERA:return n.Camera;case Ze.MICROPHONE:return n.Microphone;case Ze.SCREEN_SHARE:return n.ScreenShare;case Ze.SCREEN_SHARE_AUDIO:return n.ScreenShareAudio;default:return n.Unknown}},e.streamStateFromProto=function(e){switch(e){case Cn.ACTIVE:return i.Active;case Cn.PAUSED:return i.Paused;default:return i.Unknown}}}(Ys||(Ys={}));const $s="https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension";function er(e){return new Xo((t=>Ss.setTimeout(t,e)))}function tr(){return"addTransceiver"in RTCPeerConnection.prototype}function nr(){return"addTrack"in RTCPeerConnection.prototype}function ir(){if(!("getCapabilities"in RTCRtpSender))return!1;if(lr()||cr())return!1;const e=RTCRtpSender.getCapabilities("video");let t=!1;if(e)for(const n of e.codecs)if("video/av1"===n.mimeType.toLowerCase()){t=!0;break}return t}function or(){if(!("getCapabilities"in RTCRtpSender))return!1;if(cr())return!1;if(lr()){const e=es();if((null==e?void 0:e.version)&&Tr(e.version,"16")<0)return!1;if("iOS"===(null==e?void 0:e.os)&&(null==e?void 0:e.osVersion)&&Tr(e.osVersion,"16")<0)return!1}const e=RTCRtpSender.getCapabilities("video");let t=!1;if(e)for(const n of e.codecs)if("video/vp9"===n.mimeType.toLowerCase()){t=!0;break}return t}function sr(e){return"av1"===e||"vp9"===e}function rr(e){return!(!document||ur())&&(e||(e=document.createElement("audio")),"setSinkId"in e)}function ar(){return"undefined"!=typeof RTCPeerConnection&&(tr()||nr())}function cr(){var e;return"Firefox"===(null===(e=es())||void 0===e?void 0:e.name)}function dr(){const e=es();return!!e&&"Chrome"===e.name&&"iOS"!==e.os}function lr(){var e;return"Safari"===(null===(e=es())||void 0===e?void 0:e.name)}function ur(){const e=es();return"Safari"===(null==e?void 0:e.name)||"iOS"===(null==e?void 0:e.os)}function hr(){const e=es();return"Safari"===(null==e?void 0:e.name)&&e.version.startsWith("17.")||"iOS"===(null==e?void 0:e.os)&&!!(null==e?void 0:e.osVersion)&&Tr(e.osVersion,"17")>=0}function pr(){var e,t;return!!mr()&&(null!==(t=null===(e=navigator.userAgentData)||void 0===e?void 0:e.mobile)&&void 0!==t?t:/Tablet|iPad|Mobile|Android|BlackBerry/.test(navigator.userAgent))}function mr(){return"undefined"!=typeof document}function gr(){return"ReactNative"==navigator.product}function vr(e){return e.hostname.endsWith(".livekit.cloud")||e.hostname.endsWith(".livekit.run")}function fr(e){return vr(e)?e.hostname.split(".")[0]:null}function kr(){if(global&&global.LiveKitReactNativeGlobal)return global.LiveKitReactNativeGlobal}function yr(){if(!gr())return;let e=kr();return e?e.platform:void 0}function br(){if(mr())return window.devicePixelRatio;if(gr()){let e=kr();if(e)return e.devicePixelRatio}return 1}function Tr(e,t){const n=e.split("."),i=t.split("."),o=Math.min(n.length,i.length);for(let e=0;es)return 1;if(t(Er||(Er=new ResizeObserver(Cr)),Er);let Rr=null;const Pr=()=>(Rr||(Rr=new IntersectionObserver(Sr,{root:null,rootMargin:"0px"})),Rr);let Ir,Or;function _r(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:16,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:16,n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];const o=document.createElement("canvas");o.width=e,o.height=t;const s=o.getContext("2d");null==s||s.fillRect(0,0,o.width,o.height),i&&s&&(s.beginPath(),s.arc(e/2,t/2,50,0,2*Math.PI,!0),s.closePath(),s.fillStyle="grey",s.fill());const r=o.captureStream(),[a]=r.getTracks();if(!a)throw Error("Could not get empty media stream video track");return a.enabled=n,a}function Dr(){if(!Or){const e=new AudioContext,t=e.createOscillator(),n=e.createGain();n.gain.setValueAtTime(0,0);const i=e.createMediaStreamDestination();if(t.connect(n),n.connect(i),t.start(),[Or]=i.stream.getAudioTracks(),!Or)throw Error("Could not get empty media stream audio track");Or.enabled=!1}return Or.clone()}class Mr{get isResolved(){return this._isResolved}constructor(e,t){this._isResolved=!1,this.onFinally=t,this.promise=new Promise(((t,n)=>Fi(this,void 0,void 0,(function*(){this.resolve=t,this.reject=n,e&&(yield e(t,n))})))).finally((()=>{var e;this._isResolved=!0,null===(e=this.onFinally)||void 0===e||e.call(this)}))}}function xr(e){return Ps.includes(e)}function Ar(e){if("string"==typeof e||"number"==typeof e)return e;if(Array.isArray(e))return e[0];if(void 0!==e.exact)return Array.isArray(e.exact)?e.exact[0]:e.exact;if(void 0!==e.ideal)return Array.isArray(e.ideal)?e.ideal[0]:e.ideal;throw Error("could not unwrap constraint")}function Nr(e){return e.startsWith("ws")?e.replace(/^(ws)/,"http"):e}function Lr(t){switch(t.reason){case e.ConnectionErrorReason.LeaveRequest:return t.context;case e.ConnectionErrorReason.Cancelled:return nt.CLIENT_INITIATED;case e.ConnectionErrorReason.NotAllowed:return nt.USER_REJECTED;case e.ConnectionErrorReason.ServerUnreachable:return nt.JOIN_FAILURE;default:return nt.UNKNOWN_REASON}}function Ur(e){return void 0!==e?Number(e):void 0}function jr(e){return void 0!==e?BigInt(e):void 0}function Fr(e){return!!e&&!(e instanceof MediaStreamTrack)&&e.isLocal}function Br(e){return!!e&&e.kind==Ys.Kind.Audio}function Vr(e){return!!e&&e.kind==Ys.Kind.Video}function qr(e){return Fr(e)&&Vr(e)}function Wr(e){return Fr(e)&&Br(e)}function Kr(e){return!!e&&!e.isLocal}function Hr(e){return!!e&&!e.isLocal}function Gr(e){return Kr(e)&&Vr(e)}function Jr(e){return e.isLocal}function zr(e,t){let n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];const i=function(e,t){const n=new URL(function(e){return e.startsWith("http")?e.replace(/^(http)/,"ws"):e}(e));return t.forEach(((e,t)=>{n.searchParams.set(t,e)})),Yr(n,"rtc")}(e,t);return n?i:Yr(i,"v1")}function Qr(e){return e.endsWith("/")?e:"".concat(e,"/")}function Yr(e,t){return e.pathname="".concat(Qr(e.pathname)).concat(t),e}function Xr(e){if("string"==typeof e)return wn.fromJson(JSON.parse(e),{ignoreUnknownFields:!0});if(e instanceof ArrayBuffer)return wn.fromBinary(new Uint8Array(e));throw new Error("could not decode websocket message: ".concat(typeof e))}const Zr="AES-GCM",$r="lk_e2ee",ea={sharedKey:!1,ratchetSalt:"LKFrameEncryptionKey",ratchetWindowSize:8,failureTolerance:10,keyringSize:16};var ta,na;function ia(){return sa()||oa()}function oa(){return void 0!==window.RTCRtpScriptTransform}function sa(){return void 0!==window.RTCRtpSender&&void 0!==window.RTCRtpSender.prototype.createEncodedStreams}function ra(e){return Fi(this,void 0,void 0,(function*(){let t=new TextEncoder;return yield crypto.subtle.importKey("raw",t.encode(e),{name:"PBKDF2"},!1,["deriveBits","deriveKey"])}))}function aa(e){return Fi(this,void 0,void 0,(function*(){return yield crypto.subtle.importKey("raw",e,"HKDF",!1,["deriveBits","deriveKey"])}))}function ca(e,t){const n=(new TextEncoder).encode(t);switch(e){case"HKDF":return{name:"HKDF",salt:n,hash:"SHA-256",info:new ArrayBuffer(128)};case"PBKDF2":return{name:"PBKDF2",salt:n,hash:"SHA-256",iterations:1e5};default:throw new Error("algorithm ".concat(e," is currently unsupported"))}}e.KeyProviderEvent=void 0,(ta=e.KeyProviderEvent||(e.KeyProviderEvent={})).SetKey="setKey",ta.RatchetRequest="ratchetRequest",ta.KeyRatcheted="keyRatcheted",e.KeyHandlerEvent=void 0,(e.KeyHandlerEvent||(e.KeyHandlerEvent={})).KeyRatcheted="keyRatcheted",e.EncryptionEvent=void 0,(na=e.EncryptionEvent||(e.EncryptionEvent={})).ParticipantEncryptionStatusChanged="participantEncryptionStatusChanged",na.EncryptionError="encryptionError",e.CryptorEvent=void 0,(e.CryptorEvent||(e.CryptorEvent={})).Error="cryptorError";function da(e){var t,n,i,o,s;if("sipDtmf"!==(null===(t=e.value)||void 0===t?void 0:t.case)&&"metrics"!==(null===(n=e.value)||void 0===n?void 0:n.case)&&"speaker"!==(null===(i=e.value)||void 0===i?void 0:i.case)&&"transcription"!==(null===(o=e.value)||void 0===o?void 0:o.case)&&"encryptedPacket"!==(null===(s=e.value)||void 0===s?void 0:s.case))return new Tt({value:e.value})}class la extends Ki.EventEmitter{constructor(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};super(),this.onKeyRatcheted=(e,t,n)=>{Di.debug("key ratcheted event received",{ratchetResult:e,participantId:t,keyIndex:n})},this.keyInfoMap=new Map,this.options=Object.assign(Object.assign({},ea),t),this.on(e.KeyProviderEvent.KeyRatcheted,this.onKeyRatcheted)}onSetEncryptionKey(t,n,i){const o={key:t,participantIdentity:n,keyIndex:i};if(!this.options.sharedKey&&!n)throw new Error("participant identity needs to be passed for encryption key if sharedKey option is false");this.keyInfoMap.set("".concat(null!=n?n:"shared","-").concat(null!=i?i:0),o),this.emit(e.KeyProviderEvent.SetKey,o)}getKeys(){return Array.from(this.keyInfoMap.values())}getOptions(){return this.options}ratchetKey(t,n){this.emit(e.KeyProviderEvent.RatchetRequest,t,n)}}var ua;e.CryptorErrorReason=void 0,(ua=e.CryptorErrorReason||(e.CryptorErrorReason={}))[ua.InvalidKey=0]="InvalidKey",ua[ua.MissingKey=1]="MissingKey",ua[ua.InternalError=2]="InternalError";class ha extends Ki.EventEmitter{constructor(t,n){super(),this.decryptDataRequests=new Map,this.encryptDataRequests=new Map,this.onWorkerMessage=t=>{var n,i;const{kind:o,data:s}=t.data;switch(o){case"error":if(Di.error(s.error.message),s.uuid){const e=this.decryptDataRequests.get(s.uuid);if(null==e?void 0:e.reject){e.reject(s.error);break}const t=this.encryptDataRequests.get(s.uuid);if(null==t?void 0:t.reject){t.reject(s.error);break}}this.emit(e.EncryptionEvent.EncryptionError,s.error,s.participantIdentity);break;case"initAck":s.enabled&&this.keyProvider.getKeys().forEach((e=>{this.postKey(e)}));break;case"enable":if(s.enabled&&this.keyProvider.getKeys().forEach((e=>{this.postKey(e)})),this.encryptionEnabled!==s.enabled&&s.participantIdentity===(null===(n=this.room)||void 0===n?void 0:n.localParticipant.identity))this.emit(e.EncryptionEvent.ParticipantEncryptionStatusChanged,s.enabled,this.room.localParticipant),this.encryptionEnabled=s.enabled;else if(s.participantIdentity){const t=null===(i=this.room)||void 0===i?void 0:i.getParticipantByIdentity(s.participantIdentity);if(!t)throw TypeError("couldn't set encryption status, participant not found".concat(s.participantIdentity));this.emit(e.EncryptionEvent.ParticipantEncryptionStatusChanged,s.enabled,t)}break;case"ratchetKey":this.keyProvider.emit(e.KeyProviderEvent.KeyRatcheted,s.ratchetResult,s.participantIdentity,s.keyIndex);break;case"decryptDataResponse":const t=this.decryptDataRequests.get(s.uuid);(null==t?void 0:t.resolve)&&t.resolve(s);break;case"encryptDataResponse":const o=this.encryptDataRequests.get(s.uuid);(null==o?void 0:o.resolve)&&o.resolve(s)}},this.onWorkerError=t=>{Di.error("e2ee worker encountered an error:",{error:t.error}),this.emit(e.EncryptionEvent.EncryptionError,t.error,void 0)},this.keyProvider=t.keyProvider,this.worker=t.worker,this.encryptionEnabled=!1,this.dataChannelEncryptionEnabled=n}get isEnabled(){return this.encryptionEnabled}get isDataChannelEncryptionEnabled(){return this.isEnabled&&this.dataChannelEncryptionEnabled}setup(e){if(!ia())throw new ms("tried to setup end-to-end encryption on an unsupported browser");if(Di.info("setting up e2ee"),e!==this.room){this.room=e,this.setupEventListeners(e,this.keyProvider);const t={kind:"init",data:{keyProviderOptions:this.keyProvider.getOptions(),loglevel:Ai.getLevel()}};this.worker&&(Di.info("initializing worker",{worker:this.worker}),this.worker.onmessage=this.onWorkerMessage,this.worker.onerror=this.onWorkerError,this.worker.postMessage(t))}}setParticipantCryptorEnabled(e,t){Di.debug("set e2ee to ".concat(e," for participant ").concat(t)),this.postEnable(e,t)}setSifTrailer(e){e&&0!==e.length?this.postSifTrailer(e):Di.warn("ignoring server sent trailer as it's empty")}setupEngine(t){t.on(e.EngineEvent.RTPVideoMapUpdate,(e=>{this.postRTPMap(e)}))}setupEventListeners(t,n){t.on(e.RoomEvent.TrackPublished,((e,t)=>this.setParticipantCryptorEnabled(e.trackInfo.encryption!==pt.NONE,t.identity))),t.on(e.RoomEvent.ConnectionStateChanged,(n=>{n===e.ConnectionState.Connected&&t.remoteParticipants.forEach((e=>{e.trackPublications.forEach((t=>{this.setParticipantCryptorEnabled(t.trackInfo.encryption!==pt.NONE,e.identity)}))}))})).on(e.RoomEvent.TrackUnsubscribed,((e,t,n)=>{var i;const o={kind:"removeTransform",data:{participantIdentity:n.identity,trackId:e.mediaStreamID}};null===(i=this.worker)||void 0===i||i.postMessage(o)})).on(e.RoomEvent.TrackSubscribed,((e,t,n)=>{this.setupE2EEReceiver(e,n.identity,t.trackInfo)})).on(e.RoomEvent.SignalConnected,(()=>{if(!this.room)throw new TypeError("expected room to be present on signal connect");n.getKeys().forEach((e=>{this.postKey(e)})),this.setParticipantCryptorEnabled(this.room.localParticipant.isE2EEEnabled,this.room.localParticipant.identity)})),t.localParticipant.on(e.ParticipantEvent.LocalSenderCreated,((e,t)=>Fi(this,void 0,void 0,(function*(){this.setupE2EESender(t,e)})))),t.localParticipant.on(e.ParticipantEvent.LocalTrackPublished,(e=>{if(!Vr(e.track)||!ur())return;const t={kind:"updateCodec",data:{trackId:e.track.mediaStreamID,codec:Ws(e.trackInfo.codecs[0].mimeType),participantIdentity:this.room.localParticipant.identity}};this.worker.postMessage(t)})),n.on(e.KeyProviderEvent.SetKey,(e=>this.postKey(e))).on(e.KeyProviderEvent.RatchetRequest,((e,t)=>this.postRatchetRequest(e,t)))}encryptData(e){return Fi(this,void 0,void 0,(function*(){if(!this.worker)throw Error("could not encrypt data, worker is missing");const t=crypto.randomUUID(),n={kind:"encryptDataRequest",data:{uuid:t,payload:e,participantIdentity:this.room.localParticipant.identity}},i=new Mr;return i.onFinally=()=>{this.encryptDataRequests.delete(t)},this.encryptDataRequests.set(t,i),this.worker.postMessage(n),i.promise}))}handleEncryptedData(e,t,n,i){if(!this.worker)throw Error("could not handle encrypted data, worker is missing");const o=crypto.randomUUID(),s={kind:"decryptDataRequest",data:{uuid:o,payload:e,iv:t,participantIdentity:n,keyIndex:i}},r=new Mr;return r.onFinally=()=>{this.decryptDataRequests.delete(o)},this.decryptDataRequests.set(o,r),this.worker.postMessage(s),r.promise}postRatchetRequest(e,t){if(!this.worker)throw Error("could not ratchet key, worker is missing");const n={kind:"ratchetRequest",data:{participantIdentity:e,keyIndex:t}};this.worker.postMessage(n)}postKey(e){let{key:t,participantIdentity:n,keyIndex:i}=e;var o;if(!this.worker)throw Error("could not set key, worker is missing");const s={kind:"setKey",data:{participantIdentity:n,isPublisher:n===(null===(o=this.room)||void 0===o?void 0:o.localParticipant.identity),key:t,keyIndex:i}};this.worker.postMessage(s)}postEnable(e,t){if(!this.worker)throw new ReferenceError("failed to enable e2ee, worker is not ready");{const n={kind:"enable",data:{enabled:e,participantIdentity:t}};this.worker.postMessage(n)}}postRTPMap(e){var t;if(!this.worker)throw TypeError("could not post rtp map, worker is missing");if(!(null===(t=this.room)||void 0===t?void 0:t.localParticipant.identity))throw TypeError("could not post rtp map, local participant identity is missing");const n={kind:"setRTPMap",data:{map:e,participantIdentity:this.room.localParticipant.identity}};this.worker.postMessage(n)}postSifTrailer(e){if(!this.worker)throw Error("could not post SIF trailer, worker is missing");const t={kind:"setSifTrailer",data:{trailer:e}};this.worker.postMessage(t)}setupE2EEReceiver(e,t,n){if(e.receiver){if(!(null==n?void 0:n.mimeType)||""===n.mimeType)throw new TypeError("MimeType missing from trackInfo, cannot set up E2EE cryptor");this.handleReceiver(e.receiver,e.mediaStreamID,t,"video"===e.kind?Ws(n.mimeType):void 0)}}setupE2EESender(e,t){Fr(e)&&t?this.handleSender(t,e.mediaStreamID,void 0):t||Di.warn("early return because sender is not ready")}handleReceiver(e,t,n,i){return Fi(this,void 0,void 0,(function*(){if(this.worker){if(oa()&&!dr()){const o={kind:"decode",participantIdentity:n,trackId:t,codec:i};e.transform=new RTCRtpScriptTransform(this.worker,o)}else{if($r in e&&i){const e={kind:"updateCodec",data:{trackId:t,codec:i,participantIdentity:n}};return void this.worker.postMessage(e)}let o=e.writableStream,s=e.readableStream;if(!o||!s){const t=e.createEncodedStreams();e.writableStream=t.writable,o=t.writable,e.readableStream=t.readable,s=t.readable}const r={kind:"decode",data:{readableStream:s,writableStream:o,trackId:t,codec:i,participantIdentity:n,isReuse:$r in e}};this.worker.postMessage(r,[s,o])}e[$r]=!0}}))}handleSender(e,t,n){var i;if(!($r in e)&&this.worker){if(!(null===(i=this.room)||void 0===i?void 0:i.localParticipant.identity)||""===this.room.localParticipant.identity)throw TypeError("local identity needs to be known in order to set up encrypted sender");if(oa()&&!dr()){Di.info("initialize script transform");const i={kind:"encode",participantIdentity:this.room.localParticipant.identity,trackId:t,codec:n};e.transform=new RTCRtpScriptTransform(this.worker,i)}else{Di.info("initialize encoded streams");const i=e.createEncodedStreams(),o={kind:"encode",data:{readableStream:i.readable,writableStream:i.writable,codec:n,trackId:t,participantIdentity:this.room.localParticipant.identity,isReuse:!1}};this.worker.postMessage(o,[i.readable,i.writable])}e[$r]=!0}}}class pa{constructor(){this.failedConnectionAttempts=new Map,this.backOffPromises=new Map}static getInstance(){return this._instance||(this._instance=new pa),this._instance}addFailedConnectionAttempt(e){var t;const n=fr(new URL(e));if(!n)return;let i=null!==(t=this.failedConnectionAttempts.get(n))&&void 0!==t?t:0;this.failedConnectionAttempts.set(n,i+1),this.backOffPromises.set(n,er(Math.min(500*Math.pow(2,i),15e3)))}getBackOffPromise(e){const t=new URL(e),n=t&&fr(t);return n&&this.backOffPromises.get(n)||Promise.resolve()}resetFailedConnectionAttempts(e){const t=new URL(e),n=t&&fr(t);n&&(this.failedConnectionAttempts.set(n,0),this.backOffPromises.set(n,Promise.resolve()))}resetAll(){this.backOffPromises.clear(),this.failedConnectionAttempts.clear()}}pa._instance=null;const ma="default";class ga{constructor(){this._previousDevices=[]}static getInstance(){return void 0===this.instance&&(this.instance=new ga),this.instance}get previousDevices(){return this._previousDevices}getDevices(e){return Fi(this,arguments,void 0,(function(e){var t=this;let n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return function*(){var i;if((null===(i=ga.userMediaPromiseMap)||void 0===i?void 0:i.size)>0){Di.debug("awaiting getUserMedia promise");try{e?yield ga.userMediaPromiseMap.get(e):yield Promise.all(ga.userMediaPromiseMap.values())}catch(e){Di.warn("error waiting for media permissons")}}let o=yield navigator.mediaDevices.enumerateDevices();if(n&&(!lr()||!t.hasDeviceInUse(e))){if(0===o.filter((t=>t.kind===e)).length||o.some((t=>{const n=""===t.label,i=!e||t.kind===e;return n&&i}))){const t={video:"audioinput"!==e&&"audiooutput"!==e,audio:"videoinput"!==e&&{deviceId:{ideal:"default"}}},n=yield navigator.mediaDevices.getUserMedia(t);o=yield navigator.mediaDevices.enumerateDevices(),n.getTracks().forEach((e=>{e.stop()}))}}return t._previousDevices=o,e&&(o=o.filter((t=>t.kind===e))),o}()}))}normalizeDeviceId(e,t,n){return Fi(this,void 0,void 0,(function*(){if(t!==ma)return t;const i=yield this.getDevices(e),o=i.find((e=>e.deviceId===ma));if(!o)return void Di.warn("could not reliably determine default device");const s=i.find((e=>e.deviceId!==ma&&e.groupId===(null!=n?n:o.groupId)));if(s)return null==s?void 0:s.deviceId;Di.warn("could not reliably determine default device")}))}hasDeviceInUse(e){return e?ga.userMediaPromiseMap.has(e):ga.userMediaPromiseMap.size>0}}var va;ga.mediaDeviceKinds=["audioinput","audiooutput","videoinput"],ga.userMediaPromiseMap=new Map,function(e){e[e.WAITING=0]="WAITING",e[e.RUNNING=1]="RUNNING",e[e.COMPLETED=2]="COMPLETED"}(va||(va={}));class fa{constructor(){this.pendingTasks=new Map,this.taskMutex=new o,this.nextTaskIndex=0}run(e){return Fi(this,void 0,void 0,(function*(){const t={id:this.nextTaskIndex++,enqueuedAt:Date.now(),status:va.WAITING};this.pendingTasks.set(t.id,t);const n=yield this.taskMutex.lock();try{return t.executedAt=Date.now(),t.status=va.RUNNING,yield e()}finally{t.status=va.COMPLETED,this.pendingTasks.delete(t.id),n()}}))}flush(){return Fi(this,void 0,void 0,(function*(){return this.run((()=>Fi(this,void 0,void 0,(function*(){}))))}))}snapshot(){return Array.from(this.pendingTasks.values())}}class ka{get readyState(){return this.ws.readyState}constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};var n,i;if(null===(n=t.signal)||void 0===n?void 0:n.aborted)throw new DOMException("This operation was aborted","AbortError");this.url=e;const o=new WebSocket(e,null!==(i=t.protocols)&&void 0!==i?i:[]);o.binaryType="arraybuffer",this.ws=o;const s=function(){let{closeCode:e,reason:t}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return o.close(e,t)};this.opened=new Xo(((e,t)=>{const n=()=>{t(ps.websocket("Encountered websocket error during connection establishment"))};o.onopen=()=>{e({readable:new ReadableStream({start(e){o.onmessage=t=>{let{data:n}=t;return e.enqueue(n)},o.onerror=t=>e.error(t)},cancel:s}),writable:new WritableStream({write(e){o.send(e)},abort(){o.close()},close:s}),protocol:o.protocol,extensions:o.extensions}),o.removeEventListener("error",n)},o.addEventListener("error",n)})),this.closed=new Xo(((e,t)=>{const n=()=>Fi(this,void 0,void 0,(function*(){const n=new Xo((e=>{o.readyState!==WebSocket.CLOSED&&o.addEventListener("close",(t=>{e(t)}),{once:!0})})),i=yield Xo.race([er(250),n]);i?e(i):t(ps.websocket("Encountered unspecified websocket error without a timely close event"))}));o.onclose=t=>{let{code:i,reason:s}=t;e({closeCode:i,reason:s}),o.removeEventListener("error",n)},o.addEventListener("error",n)})),t.signal&&(t.signal.onabort=()=>o.close()),this.close=s}}const ya=["syncState","trickle","offer","answer","simulate","leave"];var ba;!function(e){e[e.CONNECTING=0]="CONNECTING",e[e.CONNECTED=1]="CONNECTED",e[e.RECONNECTING=2]="RECONNECTING",e[e.DISCONNECTING=3]="DISCONNECTING",e[e.DISCONNECTED=4]="DISCONNECTED"}(ba||(ba={}));class Ta{get currentState(){return this.state}get isDisconnected(){return this.state===ba.DISCONNECTING||this.state===ba.DISCONNECTED}get isEstablishingConnection(){return this.state===ba.CONNECTING||this.state===ba.RECONNECTING}getNextRequestId(){return this._requestId+=1,this._requestId}constructor(){let t=arguments.length>0&&void 0!==arguments[0]&&arguments[0],n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};var i;this.rtt=0,this.state=ba.DISCONNECTED,this.log=Di,this._requestId=0,this.useV0SignalPath=!1,this.resetCallbacks=()=>{this.onAnswer=void 0,this.onLeave=void 0,this.onLocalTrackPublished=void 0,this.onLocalTrackUnpublished=void 0,this.onNegotiateRequested=void 0,this.onOffer=void 0,this.onRemoteMuteChanged=void 0,this.onSubscribedQualityUpdate=void 0,this.onTokenRefresh=void 0,this.onTrickle=void 0,this.onClose=void 0,this.onMediaSectionsRequirement=void 0},this.log=xi(null!==(i=n.loggerName)&&void 0!==i?i:e.LoggerNames.Signal),this.loggerContextCb=n.loggerContextCb,this.useJSON=t,this.requestQueue=new fa,this.queuedRequests=[],this.closingLock=new o,this.connectionLock=new o,this.state=ba.DISCONNECTED}get logContext(){var e,t;return null!==(t=null===(e=this.loggerContextCb)||void 0===e?void 0:e.call(this))&&void 0!==t?t:{}}join(e,t,n,i){return Fi(this,arguments,void 0,(function(e,t,n,i){var o=this;let s=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return function*(){o.state=ba.CONNECTING,o.options=n;return yield o.connect(e,t,n,i,s)}()}))}reconnect(e,t,n,i){return Fi(this,void 0,void 0,(function*(){if(!this.options)return void this.log.warn("attempted to reconnect without signal options being set, ignoring",this.logContext);this.state=ba.RECONNECTING,this.clearPingInterval();return yield this.connect(e,t,Object.assign(Object.assign({},this.options),{reconnect:!0,sid:n,reconnectReason:i}),void 0,this.useV0SignalPath)}))}connect(e,t,n,i){return Fi(this,arguments,void 0,(function(e,t,n,i){var o=this;let s=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return function*(){const r=yield o.connectionLock.lock();o.connectOptions=n,o.useV0SignalPath=s;const a=function(){var e;const t=new Lt({sdk:Ut.JS,protocol:16,version:os});return gr()&&(t.os=null!==(e=yr())&&void 0!==e?e:""),t}(),c=s?function(e,t,n){var i;const o=new URLSearchParams;o.set("access_token",e),n.reconnect&&(o.set("reconnect","1"),n.sid&&o.set("sid",n.sid));o.set("auto_subscribe",n.autoSubscribe?"1":"0"),o.set("sdk",gr()?"reactnative":"js"),o.set("version",t.version),o.set("protocol",t.protocol.toString()),t.deviceModel&&o.set("device_model",t.deviceModel);t.os&&o.set("os",t.os);t.osVersion&&o.set("os_version",t.osVersion);t.browser&&o.set("browser",t.browser);t.browserVersion&&o.set("browser_version",t.browserVersion);n.adaptiveStream&&o.set("adaptive_stream","1");n.reconnectReason&&o.set("reconnect_reason",n.reconnectReason.toString());(null===(i=navigator.connection)||void 0===i?void 0:i.type)&&o.set("network",navigator.connection.type);return o}(t,a,n):function(e,t,n){const i=new URLSearchParams;i.set("access_token",e);const o=new ki({clientInfo:t,connectionSettings:new fi({autoSubscribe:!!n.autoSubscribe,adaptiveStream:!!n.adaptiveStream}),reconnect:!!n.reconnect,participantSid:n.sid?n.sid:void 0});n.reconnectReason&&(o.reconnectReason=n.reconnectReason);const s=new yi({joinRequest:o.toBinary()});return i.set("join_request",btoa(new TextDecoder("utf-8").decode(s.toBinary()))),i}(t,a,n),d=zr(e,c,s).toString(),l=(u=d,Yr(new URL(Nr(u)),"validate")).toString();var u;return new Promise(((e,t)=>Fi(o,void 0,void 0,(function*(){var o,s;try{let r=!1;const a=e=>Fi(this,void 0,void 0,(function*(){if(r)return;r=!0;const n=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Unknown reason";if(!(e instanceof AbortSignal))return t;const n=e.reason;switch(typeof n){case"string":return n;case"object":return n instanceof Error?n.message:t;default:return"toString"in n?n.toString():t}}(e instanceof Event?e.currentTarget:e,"Abort handler called");this.streamWriter&&!this.isDisconnected?this.sendLeave().then((()=>this.close(n))).catch((e=>{this.log.error(e),this.close()})):this.close(),c(),t(ps.cancelled(n))}));null==i||i.addEventListener("abort",a);const c=()=>{clearTimeout(u),null==i||i.removeEventListener("abort",a)},u=setTimeout((()=>{a(ps.timeout("room connection has timed out (signal)"))}),n.websocketTimeout),h=(e,t)=>{this.handleSignalConnected(e,u,t)},p=new URL(d);p.searchParams.has("access_token")&&p.searchParams.set("access_token",""),this.log.debug("connecting to ".concat(p),Object.assign({reconnect:n.reconnect,reconnectReason:n.reconnectReason},this.logContext)),this.ws&&(yield this.close(!1)),this.ws=new ka(d);try{this.ws.closed.then((e=>{var n;this.isEstablishingConnection&&t(ps.internal("Websocket got closed during a (re)connection attempt: ".concat(e.reason))),1e3!==e.closeCode&&(this.log.warn("websocket closed",Object.assign(Object.assign({},this.logContext),{reason:e.reason,code:e.closeCode,wasClean:1e3===e.closeCode,state:this.state})),this.state===ba.CONNECTED&&this.handleOnClose(null!==(n=e.reason)&&void 0!==n?n:"Unexpected WS error"))})).catch((e=>{this.isEstablishingConnection&&t(ps.internal("Websocket error during a (re)connection attempt: ".concat(e)))}));const i=yield this.ws.opened.catch((e=>Fi(this,void 0,void 0,(function*(){if(this.state===ba.CONNECTED)this.handleWSError(e),t(e);else{this.state=ba.DISCONNECTED,clearTimeout(u);const n=yield this.handleConnectionError(e,l);t(n)}}))));if(clearTimeout(u),!i)return;const r=i.readable.getReader();this.streamWriter=i.writable.getWriter();const a=yield r.read();if(r.releaseLock(),!a.value)throw ps.internal("no message received as first message");const c=Xr(a.value),d=this.validateFirstMessage(c,null!==(o=n.reconnect)&&void 0!==o&&o);if(!d.isValid)return void t(d.error);"join"===(null===(s=c.message)||void 0===s?void 0:s.case)&&(this.pingTimeoutDuration=c.message.value.pingTimeout,this.pingIntervalDuration=c.message.value.pingInterval,this.pingTimeoutDuration&&this.pingTimeoutDuration>0&&this.log.debug("ping config",Object.assign(Object.assign({},this.logContext),{timeout:this.pingTimeoutDuration,interval:this.pingIntervalDuration})));h(i,d.shouldProcessFirstMessage?c:void 0),e(d.response)}catch(e){t(e)}finally{c()}}finally{r()}}))))}()}))}startReadingLoop(e,t){return Fi(this,void 0,void 0,(function*(){for(t&&this.handleSignalResponse(t);;){this.signalLatency&&(yield er(this.signalLatency));const{done:t,value:n}=yield e.read();if(t)break;const i=Xr(n);this.handleSignalResponse(i)}}))}close(){return Fi(this,arguments,void 0,(function(){var e=this;let t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Close method called on signal client";return function*(){if([ba.DISCONNECTING||ba.DISCONNECTED].includes(e.state))return void e.log.debug("ignoring signal close as it's already in disconnecting state");const i=yield e.closingLock.lock();try{if(e.clearPingInterval(),t&&(e.state=ba.DISCONNECTING),e.ws){e.ws.close({closeCode:1e3,reason:n});const t=e.ws.closed;e.ws=void 0,e.streamWriter=void 0,yield Promise.race([t,er(250)])}}catch(t){e.log.debug("websocket error while closing",Object.assign(Object.assign({},e.logContext),{error:t}))}finally{t&&(e.state=ba.DISCONNECTED),i()}}()}))}sendOffer(e,t){this.log.debug("sending offer",Object.assign(Object.assign({},this.logContext),{offerSdp:e.sdp})),this.sendRequest({case:"offer",value:Sa(e,t)})}sendAnswer(e,t){return this.log.debug("sending answer",Object.assign(Object.assign({},this.logContext),{answerSdp:e.sdp})),this.sendRequest({case:"answer",value:Sa(e,t)})}sendIceCandidate(e,t){return this.log.debug("sending ice candidate",Object.assign(Object.assign({},this.logContext),{candidate:e})),this.sendRequest({case:"trickle",value:new In({candidateInit:JSON.stringify(e),target:t})})}sendMuteTrack(e,t){return this.sendRequest({case:"mute",value:new On({sid:e,muted:t})})}sendAddTrack(e){return this.sendRequest({case:"addTrack",value:e})}sendUpdateLocalMetadata(e,t){return Fi(this,arguments,void 0,(function(e,t){var n=this;let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return function*(){const o=n.getNextRequestId();return yield n.sendRequest({case:"updateMetadata",value:new Wn({requestId:o,metadata:e,name:t,attributes:i})}),o}()}))}sendUpdateTrackSettings(e){this.sendRequest({case:"trackSetting",value:e})}sendUpdateSubscription(e){return this.sendRequest({case:"subscription",value:e})}sendSyncState(e){return this.sendRequest({case:"syncState",value:e})}sendUpdateVideoLayers(e,t){return this.sendRequest({case:"updateLayers",value:new qn({trackSid:e,layers:t})})}sendUpdateSubscriptionPermissions(e,t){return this.sendRequest({case:"subscriptionPermission",value:new ni({allParticipants:e,trackPermissions:t})})}sendSimulateScenario(e){return this.sendRequest({case:"simulate",value:e})}sendPing(){return Promise.all([this.sendRequest({case:"ping",value:D.parse(Date.now())}),this.sendRequest({case:"pingReq",value:new di({timestamp:D.parse(Date.now()),rtt:D.parse(this.rtt)})})])}sendUpdateLocalAudioTrack(e,t){return this.sendRequest({case:"updateAudioTrack",value:new jn({trackSid:e,features:t})})}sendLeave(){return this.sendRequest({case:"leave",value:new Bn({reason:nt.CLIENT_INITIATED,action:Vn.DISCONNECT})})}sendRequest(e){return Fi(this,arguments,void 0,(function(e){var t=this;let n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return function*(){const i=!n&&!function(e){const t=ya.indexOf(e.case)>=0;return Di.trace("request allowed to bypass queue:",{canPass:t,req:e}),t}(e);if(i&&t.state===ba.RECONNECTING)return void t.queuedRequests.push((()=>Fi(t,void 0,void 0,(function*(){yield this.sendRequest(e,!0)}))));if(n||(yield t.requestQueue.flush()),t.signalLatency&&(yield er(t.signalLatency)),t.isDisconnected)return void t.log.debug("skipping signal request (type: ".concat(e.case,") - SignalClient disconnected"));if(!t.streamWriter)return void t.log.error("cannot send signal request before connected, type: ".concat(null==e?void 0:e.case),t.logContext);const o=new En({message:e});try{t.useJSON?yield t.streamWriter.write(o.toJsonString()):yield t.streamWriter.write(o.toBinary())}catch(e){t.log.error("error sending signal message",Object.assign(Object.assign({},t.logContext),{error:e}))}}()}))}handleSignalResponse(e){var t,n;const i=e.message;if(null==i)return void this.log.debug("received unsupported message",this.logContext);let o=!1;if("answer"===i.case){const e=Ca(i.value);this.onAnswer&&this.onAnswer(e,i.value.id,i.value.midToTrackId)}else if("offer"===i.case){const e=Ca(i.value);this.onOffer&&this.onOffer(e,i.value.id,i.value.midToTrackId)}else if("trickle"===i.case){const e=JSON.parse(i.value.candidateInit);this.onTrickle&&this.onTrickle(e,i.value.target)}else"update"===i.case?this.onParticipantUpdate&&this.onParticipantUpdate(null!==(t=i.value.participants)&&void 0!==t?t:[]):"trackPublished"===i.case?this.onLocalTrackPublished&&this.onLocalTrackPublished(i.value):"speakersChanged"===i.case?this.onSpeakersChanged&&this.onSpeakersChanged(null!==(n=i.value.speakers)&&void 0!==n?n:[]):"leave"===i.case?this.onLeave&&this.onLeave(i.value):"mute"===i.case?this.onRemoteMuteChanged&&this.onRemoteMuteChanged(i.value.sid,i.value.muted):"roomUpdate"===i.case?this.onRoomUpdate&&i.value.room&&this.onRoomUpdate(i.value.room):"connectionQuality"===i.case?this.onConnectionQuality&&this.onConnectionQuality(i.value):"streamStateUpdate"===i.case?this.onStreamStateUpdate&&this.onStreamStateUpdate(i.value):"subscribedQualityUpdate"===i.case?this.onSubscribedQualityUpdate&&this.onSubscribedQualityUpdate(i.value):"subscriptionPermissionUpdate"===i.case?this.onSubscriptionPermissionUpdate&&this.onSubscriptionPermissionUpdate(i.value):"refreshToken"===i.case?this.onTokenRefresh&&this.onTokenRefresh(i.value):"trackUnpublished"===i.case?this.onLocalTrackUnpublished&&this.onLocalTrackUnpublished(i.value):"subscriptionResponse"===i.case?this.onSubscriptionError&&this.onSubscriptionError(i.value):"pong"===i.case||("pongResp"===i.case?(this.rtt=Date.now()-Number.parseInt(i.value.lastPingTimestamp.toString()),this.resetPingTimeout(),o=!0):"requestResponse"===i.case?this.onRequestResponse&&this.onRequestResponse(i.value):"trackSubscribed"===i.case?this.onLocalTrackSubscribed&&this.onLocalTrackSubscribed(i.value.trackSid):"roomMoved"===i.case?(this.onTokenRefresh&&this.onTokenRefresh(i.value.token),this.onRoomMoved&&this.onRoomMoved(i.value)):"mediaSectionsRequirement"===i.case?this.onMediaSectionsRequirement&&this.onMediaSectionsRequirement(i.value):this.log.debug("unsupported message",Object.assign(Object.assign({},this.logContext),{msgCase:i.case})));o||this.resetPingTimeout()}setReconnected(){for(;this.queuedRequests.length>0;){const e=this.queuedRequests.shift();e&&this.requestQueue.run(e)}}handleOnClose(e){return Fi(this,void 0,void 0,(function*(){if(this.state===ba.DISCONNECTED)return;const t=this.onClose;yield this.close(void 0,e),this.log.debug("websocket connection closed: ".concat(e),Object.assign(Object.assign({},this.logContext),{reason:e})),t&&t(e)}))}handleWSError(e){this.log.error("websocket error",Object.assign(Object.assign({},this.logContext),{error:e}))}resetPingTimeout(){this.clearPingTimeout(),this.pingTimeoutDuration?this.pingTimeout=Ss.setTimeout((()=>{this.log.warn("ping timeout triggered. last pong received at: ".concat(new Date(Date.now()-1e3*this.pingTimeoutDuration).toUTCString()),this.logContext),this.handleOnClose("ping timeout")}),1e3*this.pingTimeoutDuration):this.log.warn("ping timeout duration not set",this.logContext)}clearPingTimeout(){this.pingTimeout&&Ss.clearTimeout(this.pingTimeout)}startPingInterval(){this.clearPingInterval(),this.resetPingTimeout(),this.pingIntervalDuration?(this.log.debug("start ping interval",this.logContext),this.pingInterval=Ss.setInterval((()=>{this.sendPing()}),1e3*this.pingIntervalDuration)):this.log.warn("ping interval duration not set",this.logContext)}clearPingInterval(){this.log.debug("clearing ping interval",this.logContext),this.clearPingTimeout(),this.pingInterval&&Ss.clearInterval(this.pingInterval)}handleSignalConnected(e,t,n){this.state=ba.CONNECTED,clearTimeout(t),this.startPingInterval(),this.startReadingLoop(e.readable.getReader(),n)}validateFirstMessage(e,t){var n,i,o,s,r;return"join"===(null===(n=e.message)||void 0===n?void 0:n.case)?{isValid:!0,response:e.message.value}:this.state===ba.RECONNECTING&&"leave"!==(null===(i=e.message)||void 0===i?void 0:i.case)?"reconnect"===(null===(o=e.message)||void 0===o?void 0:o.case)?{isValid:!0,response:e.message.value}:(this.log.debug("declaring signal reconnected without reconnect response received",this.logContext),{isValid:!0,response:void 0,shouldProcessFirstMessage:!0}):this.isEstablishingConnection&&"leave"===(null===(s=e.message)||void 0===s?void 0:s.case)?{isValid:!1,error:ps.leaveRequest("Received leave request while trying to (re)connect",e.message.value.reason)}:t?{isValid:!1,error:ps.internal("Unexpected first message")}:{isValid:!1,error:ps.internal("did not receive join response, got ".concat(null===(r=e.message)||void 0===r?void 0:r.case," instead"))}}handleConnectionError(e,t){return Fi(this,void 0,void 0,(function*(){try{const n=yield fetch(t);switch(n.status){case 404:return ps.serviceNotFound("v1 RTC path not found. Consider upgrading your LiveKit server version","v0-rtc");case 401:case 403:const e=yield n.text();return ps.notAllowed(e,n.status)}return e instanceof ps?e:ps.internal("Encountered unknown websocket error during connection: ".concat(e),{status:n.status,statusText:n.statusText})}catch(e){return e instanceof ps?e:ps.serverUnreachable(e instanceof Error?e.message:"server was not reachable")}}))}}function Ca(e){const t={type:"offer",sdp:e.sdp};switch(e.type){case"answer":case"offer":case"pranswer":case"rollback":t.type=e.type}return t}function Sa(e,t){return new An({sdp:e.sdp,type:e.type,id:t})}class Ea{constructor(){this.buffer=[],this._totalSize=0}push(e){this.buffer.push(e),this._totalSize+=e.data.byteLength}pop(){const e=this.buffer.shift();return e&&(this._totalSize-=e.data.byteLength),e}getAll(){return this.buffer.slice()}popToSequence(e){for(;this.buffer.length>0;){if(!(this.buffer[0].sequence<=e))break;this.pop()}}alignBufferedAmount(e){for(;this.buffer.length>0;){const t=this.buffer[0];if(this._totalSize-t.data.byteLength<=e)break;this.pop()}}get length(){return this.buffer.length}}class wa{constructor(e){this._map=new Map,this._lastCleanup=0,this.ttl=e}set(e,t){const n=Date.now();n-this._lastCleanup>this.ttl/2&&this.cleanup();const i=n+this.ttl;return this._map.set(e,{value:t,expiresAt:i}),this}get(e){const t=this._map.get(e);if(t){if(!(t.expiresAt=Date.now()&&e(n.value,t,this.asValueMap())}map(e){this.cleanup();const t=[],n=this.asValueMap();for(const[i,o]of n.entries())t.push(e(o,i,n));return t}asValueMap(){const e=new Map;for(const[t,n]of this._map.entries())n.expiresAt>=Date.now()&&e.set(t,n.value);return e}}var Ra,Pa,Ia,Oa,_a,Da={},Ma={},xa={exports:{}};function Aa(){if(Ra)return xa.exports;Ra=1;var e=xa.exports={v:[{name:"version",reg:/^(\d*)$/}],o:[{name:"origin",reg:/^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/,names:["username","sessionId","sessionVersion","netType","ipVer","address"],format:"%s %s %d %s IP%d %s"}],s:[{name:"name"}],i:[{name:"description"}],u:[{name:"uri"}],e:[{name:"email"}],p:[{name:"phone"}],z:[{name:"timezones"}],r:[{name:"repeats"}],t:[{name:"timing",reg:/^(\d*) (\d*)/,names:["start","stop"],format:"%d %d"}],c:[{name:"connection",reg:/^IN IP(\d) (\S*)/,names:["version","ip"],format:"IN IP%d %s"}],b:[{push:"bandwidth",reg:/^(TIAS|AS|CT|RR|RS):(\d*)/,names:["type","limit"],format:"%s:%s"}],m:[{reg:/^(\w*) (\d*) ([\w/]*)(?: (.*))?/,names:["type","port","protocol","payloads"],format:"%s %d %s %s"}],a:[{push:"rtp",reg:/^rtpmap:(\d*) ([\w\-.]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/,names:["payload","codec","rate","encoding"],format:function(e){return e.encoding?"rtpmap:%d %s/%s/%s":e.rate?"rtpmap:%d %s/%s":"rtpmap:%d %s"}},{push:"fmtp",reg:/^fmtp:(\d*) ([\S| ]*)/,names:["payload","config"],format:"fmtp:%d %s"},{name:"control",reg:/^control:(.*)/,format:"control:%s"},{name:"rtcp",reg:/^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/,names:["port","netType","ipVer","address"],format:function(e){return null!=e.address?"rtcp:%d %s IP%d %s":"rtcp:%d"}},{push:"rtcpFbTrrInt",reg:/^rtcp-fb:(\*|\d*) trr-int (\d*)/,names:["payload","value"],format:"rtcp-fb:%s trr-int %d"},{push:"rtcpFb",reg:/^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/,names:["payload","type","subtype"],format:function(e){return null!=e.subtype?"rtcp-fb:%s %s %s":"rtcp-fb:%s %s"}},{push:"ext",reg:/^extmap:(\d+)(?:\/(\w+))?(?: (urn:ietf:params:rtp-hdrext:encrypt))? (\S*)(?: (\S*))?/,names:["value","direction","encrypt-uri","uri","config"],format:function(e){return"extmap:%d"+(e.direction?"/%s":"%v")+(e["encrypt-uri"]?" %s":"%v")+" %s"+(e.config?" %s":"")}},{name:"extmapAllowMixed",reg:/^(extmap-allow-mixed)/},{push:"crypto",reg:/^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/,names:["id","suite","config","sessionConfig"],format:function(e){return null!=e.sessionConfig?"crypto:%d %s %s %s":"crypto:%d %s %s"}},{name:"setup",reg:/^setup:(\w*)/,format:"setup:%s"},{name:"connectionType",reg:/^connection:(new|existing)/,format:"connection:%s"},{name:"mid",reg:/^mid:([^\s]*)/,format:"mid:%s"},{name:"msid",reg:/^msid:(.*)/,format:"msid:%s"},{name:"ptime",reg:/^ptime:(\d*(?:\.\d*)*)/,format:"ptime:%d"},{name:"maxptime",reg:/^maxptime:(\d*(?:\.\d*)*)/,format:"maxptime:%d"},{name:"direction",reg:/^(sendrecv|recvonly|sendonly|inactive)/},{name:"icelite",reg:/^(ice-lite)/},{name:"iceUfrag",reg:/^ice-ufrag:(\S*)/,format:"ice-ufrag:%s"},{name:"icePwd",reg:/^ice-pwd:(\S*)/,format:"ice-pwd:%s"},{name:"fingerprint",reg:/^fingerprint:(\S*) (\S*)/,names:["type","hash"],format:"fingerprint:%s %s"},{push:"candidates",reg:/^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?(?: network-id (\d*))?(?: network-cost (\d*))?/,names:["foundation","component","transport","priority","ip","port","type","raddr","rport","tcptype","generation","network-id","network-cost"],format:function(e){var t="candidate:%s %d %s %d %s %d typ %s";return t+=null!=e.raddr?" raddr %s rport %d":"%v%v",t+=null!=e.tcptype?" tcptype %s":"%v",null!=e.generation&&(t+=" generation %d"),t+=null!=e["network-id"]?" network-id %d":"%v",t+=null!=e["network-cost"]?" network-cost %d":"%v"}},{name:"endOfCandidates",reg:/^(end-of-candidates)/},{name:"remoteCandidates",reg:/^remote-candidates:(.*)/,format:"remote-candidates:%s"},{name:"iceOptions",reg:/^ice-options:(\S*)/,format:"ice-options:%s"},{push:"ssrcs",reg:/^ssrc:(\d*) ([\w_-]*)(?::(.*))?/,names:["id","attribute","value"],format:function(e){var t="ssrc:%d";return null!=e.attribute&&(t+=" %s",null!=e.value&&(t+=":%s")),t}},{push:"ssrcGroups",reg:/^ssrc-group:([\x21\x23\x24\x25\x26\x27\x2A\x2B\x2D\x2E\w]*) (.*)/,names:["semantics","ssrcs"],format:"ssrc-group:%s %s"},{name:"msidSemantic",reg:/^msid-semantic:\s?(\w*) (\S*)/,names:["semantic","token"],format:"msid-semantic: %s %s"},{push:"groups",reg:/^group:(\w*) (.*)/,names:["type","mids"],format:"group:%s %s"},{name:"rtcpMux",reg:/^(rtcp-mux)/},{name:"rtcpRsize",reg:/^(rtcp-rsize)/},{name:"sctpmap",reg:/^sctpmap:([\w_/]*) (\S*)(?: (\S*))?/,names:["sctpmapNumber","app","maxMessageSize"],format:function(e){return null!=e.maxMessageSize?"sctpmap:%s %s %s":"sctpmap:%s %s"}},{name:"xGoogleFlag",reg:/^x-google-flag:([^\s]*)/,format:"x-google-flag:%s"},{push:"rids",reg:/^rid:([\d\w]+) (\w+)(?: ([\S| ]*))?/,names:["id","direction","params"],format:function(e){return e.params?"rid:%s %s %s":"rid:%s %s"}},{push:"imageattrs",reg:new RegExp("^imageattr:(\\d+|\\*)[\\s\\t]+(send|recv)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*)(?:[\\s\\t]+(recv|send)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*))?"),names:["pt","dir1","attrs1","dir2","attrs2"],format:function(e){return"imageattr:%s %s %s"+(e.dir2?" %s %s":"")}},{name:"simulcast",reg:new RegExp("^simulcast:(send|recv) ([a-zA-Z0-9\\-_~;,]+)(?:\\s?(send|recv) ([a-zA-Z0-9\\-_~;,]+))?$"),names:["dir1","list1","dir2","list2"],format:function(e){return"simulcast:%s %s"+(e.dir2?" %s %s":"")}},{name:"simulcast_03",reg:/^simulcast:[\s\t]+([\S+\s\t]+)$/,names:["value"],format:"simulcast: %s"},{name:"framerate",reg:/^framerate:(\d+(?:$|\.\d+))/,format:"framerate:%s"},{name:"sourceFilter",reg:/^source-filter: *(excl|incl) (\S*) (IP4|IP6|\*) (\S*) (.*)/,names:["filterMode","netType","addressTypes","destAddress","srcList"],format:"source-filter: %s %s %s %s %s"},{name:"bundleOnly",reg:/^(bundle-only)/},{name:"label",reg:/^label:(.+)/,format:"label:%s"},{name:"sctpPort",reg:/^sctp-port:(\d+)$/,format:"sctp-port:%s"},{name:"maxMessageSize",reg:/^max-message-size:(\d+)$/,format:"max-message-size:%s"},{push:"tsRefClocks",reg:/^ts-refclk:([^\s=]*)(?:=(\S*))?/,names:["clksrc","clksrcExt"],format:function(e){return"ts-refclk:%s"+(null!=e.clksrcExt?"=%s":"")}},{name:"mediaClk",reg:/^mediaclk:(?:id=(\S*))? *([^\s=]*)(?:=(\S*))?(?: *rate=(\d+)\/(\d+))?/,names:["id","mediaClockName","mediaClockValue","rateNumerator","rateDenominator"],format:function(e){var t="mediaclk:";return t+=null!=e.id?"id=%s %s":"%v%s",t+=null!=e.mediaClockValue?"=%s":"",t+=null!=e.rateNumerator?" rate=%s":"",t+=null!=e.rateDenominator?"/%s":""}},{name:"keywords",reg:/^keywds:(.+)$/,format:"keywds:%s"},{name:"content",reg:/^content:(.+)/,format:"content:%s"},{name:"bfcpFloorCtrl",reg:/^floorctrl:(c-only|s-only|c-s)/,format:"floorctrl:%s"},{name:"bfcpConfId",reg:/^confid:(\d+)/,format:"confid:%s"},{name:"bfcpUserId",reg:/^userid:(\d+)/,format:"userid:%s"},{name:"bfcpFloorId",reg:/^floorid:(.+) (?:m-stream|mstrm):(.+)/,names:["id","mStream"],format:"floorid:%s mstrm:%s"},{push:"invalid",names:["value"]}]};return Object.keys(e).forEach((function(t){e[t].forEach((function(e){e.reg||(e.reg=/(.*)/),e.format||(e.format="%s")}))})),xa.exports}function Na(){return Pa||(Pa=1,function(e){var t=function(e){return String(Number(e))===e?Number(e):e},n=function(e,n,i){var o=e.name&&e.names;e.push&&!n[e.push]?n[e.push]=[]:o&&!n[e.name]&&(n[e.name]={});var s=e.push?{}:o?n[e.name]:n;!function(e,n,i,o){if(o&&!i)n[o]=t(e[1]);else for(var s=0;s1&&(e[i[0]]=void 0),e};e.parseParams=function(e){return e.split(/;\s?/).reduce(s,{})},e.parseFmtpConfig=e.parseParams,e.parsePayloads=function(e){return e.toString().split(" ").map(Number)},e.parseRemoteCandidates=function(e){for(var n=[],i=e.split(" ").map(t),o=0;o=o)return e;var t=i[n];switch(n+=1,e){case"%%":return"%";case"%s":return String(t);case"%d":return Number(t);case"%v":return""}}))},i=function(e,t,i){var o=[e+"="+(t.format instanceof Function?t.format(t.push?i:i[t.name]):t.format)];if(t.names)for(var s=0;s=c)return c-e}return t}var h=function(){var t=[].slice.call(arguments),n=this;return new Promise((function(i,o){var c=r&&void 0===s;if(void 0!==s&&clearTimeout(s),s=setTimeout((function(){if(s=void 0,d=Date.now(),!r){var i=e.apply(n,t);a&&a(i),l.forEach((function(e){return(0,e.resolve)(i)})),l=[]}}),u()),c){var h=e.apply(n,t);return a&&a(h),i(h)}l.push({resolve:i,reject:o})}))};return h.cancel=function(e){void 0!==s&&clearTimeout(s),l.forEach((function(t){return(0,t.reject)(e)})),l=[]},h}const Fa="negotiationStarted",Ba="negotiationComplete",Va="rtpVideoPayloadTypes";class qa extends Ki.EventEmitter{get pc(){return this._pc||(this._pc=this.createPC()),this._pc}constructor(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};var i;super(),this.log=Di,this.ddExtID=0,this.latestOfferId=0,this.pendingCandidates=[],this.restartingIce=!1,this.renegotiate=!1,this.trackBitrates=[],this.remoteStereoMids=[],this.remoteNackMids=[],this.negotiate=ja((e=>Fi(this,void 0,void 0,(function*(){this.emit(Fa);try{yield this.createAndSendOffer()}catch(t){if(!e)throw t;e(t)}}))),20),this.close=()=>{this._pc&&(this._pc.close(),this._pc.onconnectionstatechange=null,this._pc.oniceconnectionstatechange=null,this._pc.onicegatheringstatechange=null,this._pc.ondatachannel=null,this._pc.onnegotiationneeded=null,this._pc.onsignalingstatechange=null,this._pc.onicecandidate=null,this._pc.ondatachannel=null,this._pc.ontrack=null,this._pc.onconnectionstatechange=null,this._pc.oniceconnectionstatechange=null,this._pc=null)},this.log=xi(null!==(i=n.loggerName)&&void 0!==i?i:e.LoggerNames.PCTransport),this.loggerOptions=n,this.config=t,this._pc=this.createPC(),this.offerLock=new o}createPC(){const e=new RTCPeerConnection(this.config);return e.onicecandidate=e=>{var t;e.candidate&&(null===(t=this.onIceCandidate)||void 0===t||t.call(this,e.candidate))},e.onicecandidateerror=e=>{var t;null===(t=this.onIceCandidateError)||void 0===t||t.call(this,e)},e.oniceconnectionstatechange=()=>{var t;null===(t=this.onIceConnectionStateChange)||void 0===t||t.call(this,e.iceConnectionState)},e.onsignalingstatechange=()=>{var t;null===(t=this.onSignalingStatechange)||void 0===t||t.call(this,e.signalingState)},e.onconnectionstatechange=()=>{var t;null===(t=this.onConnectionStateChange)||void 0===t||t.call(this,e.connectionState)},e.ondatachannel=e=>{var t;null===(t=this.onDataChannel)||void 0===t||t.call(this,e)},e.ontrack=e=>{var t;null===(t=this.onTrack)||void 0===t||t.call(this,e)},e}get logContext(){var e,t;return Object.assign({},null===(t=(e=this.loggerOptions).loggerContextCb)||void 0===t?void 0:t.call(e))}get isICEConnected(){return null!==this._pc&&("connected"===this.pc.iceConnectionState||"completed"===this.pc.iceConnectionState)}addIceCandidate(e){return Fi(this,void 0,void 0,(function*(){if(this.pc.remoteDescription&&!this.restartingIce)return this.pc.addIceCandidate(e);this.pendingCandidates.push(e)}))}setRemoteDescription(e,t){return Fi(this,void 0,void 0,(function*(){var n;if("answer"===e.type&&this.latestOfferId>0&&t>0&&t!==this.latestOfferId)return this.log.warn("ignoring answer for old offer",Object.assign(Object.assign({},this.logContext),{offerId:t,latestOfferId:this.latestOfferId})),!1;let i;if("offer"===e.type){let{stereoMids:t,nackMids:n}=function(e){var t;const n=[],i=[],o=Ua.parse(null!==(t=e.sdp)&&void 0!==t?t:"");let s=0;return o.media.forEach((e=>{var t;const o=Ha(e.mid);"audio"===e.type&&(e.rtp.some((e=>"opus"===e.codec&&(s=e.payload,!0))),(null===(t=e.rtcpFb)||void 0===t?void 0:t.some((e=>e.payload===s&&"nack"===e.type)))&&i.push(o),e.fmtp.some((e=>e.payload===s&&(e.config.includes("sprop-stereo=1")&&n.push(o),!0))))})),{stereoMids:n,nackMids:i}}(e);this.remoteStereoMids=t,this.remoteNackMids=n}else if("answer"===e.type){const t=Ua.parse(null!==(n=e.sdp)&&void 0!==n?n:"");t.media.forEach((e=>{const t=Ha(e.mid);"audio"===e.type&&this.trackBitrates.some((n=>{if(!n.transceiver||t!=n.transceiver.mid)return!1;let i=0;if(e.rtp.some((e=>e.codec.toUpperCase()===n.codec.toUpperCase()&&(i=e.payload,!0))),0===i)return!0;let o=!1;for(const t of e.fmtp)if(t.payload===i){t.config=t.config.split(";").filter((e=>!e.includes("maxaveragebitrate"))).join(";"),n.maxbr>0&&(t.config+=";maxaveragebitrate=".concat(1e3*n.maxbr)),o=!0;break}return o||n.maxbr>0&&e.fmtp.push({payload:i,config:"maxaveragebitrate=".concat(1e3*n.maxbr)}),!0}))})),i=Ua.write(t)}if(yield this.setMungedSDP(e,i,!0),this.pendingCandidates.forEach((e=>{this.pc.addIceCandidate(e)})),this.pendingCandidates=[],this.restartingIce=!1,this.renegotiate)this.renegotiate=!1,yield this.createAndSendOffer();else if("answer"===e.type&&(this.emit(Ba),e.sdp)){Ua.parse(e.sdp).media.forEach((e=>{"video"===e.type&&this.emit(Va,e.rtp)}))}return!0}))}createAndSendOffer(e){return Fi(this,void 0,void 0,(function*(){var t;const n=yield this.offerLock.lock();try{if(void 0===this.onOffer)return;if((null==e?void 0:e.iceRestart)&&(this.log.debug("restarting ICE",this.logContext),this.restartingIce=!0),this._pc&&"have-local-offer"===this._pc.signalingState){const t=this._pc.remoteDescription;if(!(null==e?void 0:e.iceRestart)||!t)return void(this.renegotiate=!0);yield this._pc.setRemoteDescription(t)}else if(!this._pc||"closed"===this._pc.signalingState)return void this.log.warn("could not createOffer with closed peer connection",this.logContext);this.log.debug("starting to negotiate",this.logContext);const n=this.latestOfferId+1;this.latestOfferId=n;const i=yield this.pc.createOffer(e);this.log.debug("original offer",Object.assign({sdp:i.sdp},this.logContext));const o=Ua.parse(null!==(t=i.sdp)&&void 0!==t?t:"");if(o.media.forEach((e=>{Ka(e),"audio"===e.type?Wa(e,["all"],[]):"video"===e.type&&this.trackBitrates.some((t=>{if(!e.msid||!t.cid||!e.msid.includes(t.cid))return!1;let n=0;if(e.rtp.some((e=>e.codec.toUpperCase()===t.codec.toUpperCase()&&(n=e.payload,!0))),0===n)return!0;if(sr(t.codec)&&!lr()&&this.ensureVideoDDExtensionForSVC(e,o),!sr(t.codec))return!0;const i=Math.round(.7*t.maxbr);for(const t of e.fmtp)if(t.payload===n){t.config.includes("x-google-start-bitrate")||(t.config+=";x-google-start-bitrate=".concat(i));break}return!0}))})),this.latestOfferId>n)return void this.log.warn("latestOfferId mismatch",Object.assign(Object.assign({},this.logContext),{latestOfferId:this.latestOfferId,offerId:n}));yield this.setMungedSDP(i,Ua.write(o)),this.onOffer(i,this.latestOfferId)}finally{n()}}))}createAndSetAnswer(){return Fi(this,void 0,void 0,(function*(){var e;const t=yield this.pc.createAnswer(),n=Ua.parse(null!==(e=t.sdp)&&void 0!==e?e:"");return n.media.forEach((e=>{Ka(e),"audio"===e.type&&Wa(e,this.remoteStereoMids,this.remoteNackMids)})),yield this.setMungedSDP(t,Ua.write(n)),t}))}createDataChannel(e,t){return this.pc.createDataChannel(e,t)}addTransceiver(e,t){return this.pc.addTransceiver(e,t)}addTransceiverOfKind(e,t){return this.pc.addTransceiver(e,t)}addTrack(e){if(!this._pc)throw new fs("PC closed, cannot add track");return this._pc.addTrack(e)}setTrackCodecBitrate(e){this.trackBitrates.push(e)}setConfiguration(e){var t;if(!this._pc)throw new fs("PC closed, cannot configure");return null===(t=this._pc)||void 0===t?void 0:t.setConfiguration(e)}canRemoveTrack(){var e;return!!(null===(e=this._pc)||void 0===e?void 0:e.removeTrack)}removeTrack(e){var t;return null===(t=this._pc)||void 0===t?void 0:t.removeTrack(e)}getConnectionState(){var e,t;return null!==(t=null===(e=this._pc)||void 0===e?void 0:e.connectionState)&&void 0!==t?t:"closed"}getICEConnectionState(){var e,t;return null!==(t=null===(e=this._pc)||void 0===e?void 0:e.iceConnectionState)&&void 0!==t?t:"closed"}getSignallingState(){var e,t;return null!==(t=null===(e=this._pc)||void 0===e?void 0:e.signalingState)&&void 0!==t?t:"closed"}getTransceivers(){var e,t;return null!==(t=null===(e=this._pc)||void 0===e?void 0:e.getTransceivers())&&void 0!==t?t:[]}getSenders(){var e,t;return null!==(t=null===(e=this._pc)||void 0===e?void 0:e.getSenders())&&void 0!==t?t:[]}getLocalDescription(){var e;return null===(e=this._pc)||void 0===e?void 0:e.localDescription}getRemoteDescription(){var e;return null===(e=this.pc)||void 0===e?void 0:e.remoteDescription}getStats(){return this.pc.getStats()}getConnectedAddress(){return Fi(this,void 0,void 0,(function*(){var e;if(!this._pc)return;let t="";const n=new Map,i=new Map;if((yield this._pc.getStats()).forEach((e=>{switch(e.type){case"transport":t=e.selectedCandidatePairId;break;case"candidate-pair":""===t&&e.selected&&(t=e.id),n.set(e.id,e);break;case"remote-candidate":i.set(e.id,"".concat(e.address,":").concat(e.port))}})),""===t)return;const o=null===(e=n.get(t))||void 0===e?void 0:e.remoteCandidateId;return void 0!==o?i.get(o):void 0}))}setMungedSDP(e,t,n){return Fi(this,void 0,void 0,(function*(){if(t){const i=e.sdp;e.sdp=t;try{return this.log.debug("setting munged ".concat(n?"remote":"local"," description"),this.logContext),void(n?yield this.pc.setRemoteDescription(e):yield this.pc.setLocalDescription(e))}catch(n){this.log.warn("not able to set ".concat(e.type,", falling back to unmodified sdp"),Object.assign(Object.assign({},this.logContext),{error:n,sdp:t})),e.sdp=i}}try{n?yield this.pc.setRemoteDescription(e):yield this.pc.setLocalDescription(e)}catch(t){let i="unknown error";t instanceof Error?i=t.message:"string"==typeof t&&(i=t);const o={error:i,sdp:e.sdp};throw!n&&this.pc.remoteDescription&&(o.remoteSdp=this.pc.remoteDescription),this.log.error("unable to set ".concat(e.type),Object.assign(Object.assign({},this.logContext),{fields:o})),new ks(i)}}))}ensureVideoDDExtensionForSVC(e,t){var n,i;if(!(null===(n=e.ext)||void 0===n?void 0:n.some((e=>e.uri===$s)))){if(0===this.ddExtID){let e=0;t.media.forEach((t=>{var n;"video"===t.type&&(null===(n=t.ext)||void 0===n||n.forEach((t=>{t.value>e&&(e=t.value)})))})),this.ddExtID=e+1}null===(i=e.ext)||void 0===i||i.push({value:this.ddExtID,uri:$s})}}}function Wa(e,t,n){const i=Ha(e.mid);let o=0;e.rtp.some((e=>"opus"===e.codec&&(o=e.payload,!0))),o>0&&(e.rtcpFb||(e.rtcpFb=[]),n.includes(i)&&!e.rtcpFb.some((e=>e.payload===o&&"nack"===e.type))&&e.rtcpFb.push({payload:o,type:"nack"}),(t.includes(i)||1===t.length&&"all"===t[0])&&e.fmtp.some((e=>e.payload===o&&(e.config.includes("stereo=1")||(e.config+=";stereo=1"),!0))))}function Ka(e){if(e.connection){const t=e.connection.ip.indexOf(":")>=0;(4===e.connection.version&&t||6===e.connection.version&&!t)&&(e.connection.ip="0.0.0.0",e.connection.version=4)}}function Ha(e){return"number"==typeof e?e.toFixed(0):e}const Ga="vp8",Ja={audioPreset:e.AudioPresets.music,dtx:!0,red:!0,forceStereo:!1,simulcast:!0,screenShareEncoding:As.h1080fps15.encoding,stopMicTrackOnMute:!1,videoCodec:Ga,backupCodec:!0,preConnectBuffer:!1},za={deviceId:{ideal:"default"},autoGainControl:!0,echoCancellation:!0,noiseSuppression:!0,voiceIsolation:!0},Qa={deviceId:{ideal:"default"},resolution:Ms.h720.resolution},Ya={adaptiveStream:!1,dynacast:!1,stopLocalTrackOnUnpublish:!0,reconnectPolicy:new Ui,disconnectOnPageLeave:!0,webAudioMix:!1,singlePeerConnection:!0},Xa={autoSubscribe:!0,maxRetries:1,peerConnectionTimeout:15e3,websocketTimeout:15e3};var Za;!function(e){e[e.NEW=0]="NEW",e[e.CONNECTING=1]="CONNECTING",e[e.CONNECTED=2]="CONNECTED",e[e.FAILED=3]="FAILED",e[e.CLOSING=4]="CLOSING",e[e.CLOSED=5]="CLOSED"}(Za||(Za={}));class $a{get needsPublisher(){return this.isPublisherConnectionRequired}get needsSubscriber(){return this.isSubscriberConnectionRequired}get currentState(){return this.state}get mode(){return this._mode}constructor(t,n,i){var s;this.peerConnectionTimeout=Xa.peerConnectionTimeout,this.log=Di,this.updateState=()=>{var e,t;const n=this.state,i=this.requiredTransports.map((e=>e.getConnectionState()));i.every((e=>"connected"===e))?this.state=Za.CONNECTED:i.some((e=>"failed"===e))?this.state=Za.FAILED:i.some((e=>"connecting"===e))?this.state=Za.CONNECTING:i.every((e=>"closed"===e))?this.state=Za.CLOSED:i.some((e=>"closed"===e))?this.state=Za.CLOSING:i.every((e=>"new"===e))&&(this.state=Za.NEW),n!==this.state&&(this.log.debug("pc state change: from ".concat(Za[n]," to ").concat(Za[this.state]),this.logContext),null===(e=this.onStateChange)||void 0===e||e.call(this,this.state,this.publisher.getConnectionState(),null===(t=this.subscriber)||void 0===t?void 0:t.getConnectionState()))},this.log=xi(null!==(s=i.loggerName)&&void 0!==s?s:e.LoggerNames.PCManager),this.loggerOptions=i,this.isPublisherConnectionRequired="subscriber-primary"!==n,this.isSubscriberConnectionRequired="subscriber-primary"===n,this.publisher=new qa(t,i),this._mode=n,"publisher-only"!==n&&(this.subscriber=new qa(t,i),this.subscriber.onConnectionStateChange=this.updateState,this.subscriber.onIceConnectionStateChange=this.updateState,this.subscriber.onSignalingStatechange=this.updateState,this.subscriber.onIceCandidate=e=>{var t;null===(t=this.onIceCandidate)||void 0===t||t.call(this,e,Tn.SUBSCRIBER)},this.subscriber.onDataChannel=e=>{var t;null===(t=this.onDataChannel)||void 0===t||t.call(this,e)},this.subscriber.onTrack=e=>{var t;null===(t=this.onTrack)||void 0===t||t.call(this,e)}),this.publisher.onConnectionStateChange=this.updateState,this.publisher.onIceConnectionStateChange=this.updateState,this.publisher.onSignalingStatechange=this.updateState,this.publisher.onIceCandidate=e=>{var t;null===(t=this.onIceCandidate)||void 0===t||t.call(this,e,Tn.PUBLISHER)},this.publisher.onTrack=e=>{var t;null===(t=this.onTrack)||void 0===t||t.call(this,e)},this.publisher.onOffer=(e,t)=>{var n;null===(n=this.onPublisherOffer)||void 0===n||n.call(this,e,t)},this.state=Za.NEW,this.connectionLock=new o,this.remoteOfferLock=new o}get logContext(){var e,t;return Object.assign({},null===(t=(e=this.loggerOptions).loggerContextCb)||void 0===t?void 0:t.call(e))}requirePublisher(){let e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.isPublisherConnectionRequired=e,this.updateState()}createAndSendPublisherOffer(e){return this.publisher.createAndSendOffer(e)}setPublisherAnswer(e,t){return this.publisher.setRemoteDescription(e,t)}removeTrack(e){return this.publisher.removeTrack(e)}close(){return Fi(this,void 0,void 0,(function*(){var e;if(this.publisher&&"closed"!==this.publisher.getSignallingState()){const e=this.publisher;for(const t of e.getSenders())try{e.canRemoveTrack()&&e.removeTrack(t)}catch(e){this.log.warn("could not removeTrack",Object.assign(Object.assign({},this.logContext),{error:e}))}}yield Promise.all([this.publisher.close(),null===(e=this.subscriber)||void 0===e?void 0:e.close()]),this.updateState()}))}triggerIceRestart(){return Fi(this,void 0,void 0,(function*(){this.subscriber&&(this.subscriber.restartingIce=!0),this.needsPublisher&&(yield this.createAndSendPublisherOffer({iceRestart:!0}))}))}addIceCandidate(e,t){return Fi(this,void 0,void 0,(function*(){var n;t===Tn.PUBLISHER?yield this.publisher.addIceCandidate(e):yield null===(n=this.subscriber)||void 0===n?void 0:n.addIceCandidate(e)}))}createSubscriberAnswerFromOffer(e,t){return Fi(this,void 0,void 0,(function*(){var n,i,o;this.log.debug("received server offer",Object.assign(Object.assign({},this.logContext),{RTCSdpType:e.type,sdp:e.sdp,signalingState:null===(n=this.subscriber)||void 0===n?void 0:n.getSignallingState().toString()}));const s=yield this.remoteOfferLock.lock();try{if(!(yield null===(i=this.subscriber)||void 0===i?void 0:i.setRemoteDescription(e,t)))return;return yield null===(o=this.subscriber)||void 0===o?void 0:o.createAndSetAnswer()}finally{s()}}))}updateConfiguration(e,t){var n;this.publisher.setConfiguration(e),null===(n=this.subscriber)||void 0===n||n.setConfiguration(e),t&&this.triggerIceRestart()}ensurePCTransportConnection(e,t){return Fi(this,void 0,void 0,(function*(){var n;const i=yield this.connectionLock.lock();try{this.isPublisherConnectionRequired&&"connected"!==this.publisher.getConnectionState()&&"connecting"!==this.publisher.getConnectionState()&&(this.log.debug("negotiation required, start negotiating",this.logContext),this.publisher.negotiate()),yield Promise.all(null===(n=this.requiredTransports)||void 0===n?void 0:n.map((n=>this.ensureTransportConnected(n,e,t))))}finally{i()}}))}negotiate(e){return Fi(this,void 0,void 0,(function*(){return new Xo(((t,n)=>Fi(this,void 0,void 0,(function*(){const i=setTimeout((()=>{n(new ks("negotiation timed out"))}),this.peerConnectionTimeout);e.signal.addEventListener("abort",(()=>{clearTimeout(i),n(new ks("negotiation aborted"))})),this.publisher.once(Fa,(()=>{e.signal.aborted||this.publisher.once(Ba,(()=>{clearTimeout(i),t()}))})),yield this.publisher.negotiate((e=>{clearTimeout(i),e instanceof Error?n(e):n(new Error(String(e)))}))}))))}))}addPublisherTransceiver(e,t){return this.publisher.addTransceiver(e,t)}addPublisherTransceiverOfKind(e,t){return this.publisher.addTransceiverOfKind(e,t)}getMidForReceiver(e){const t=(this.subscriber?this.subscriber.getTransceivers():this.publisher.getTransceivers()).find((t=>t.receiver===e));return null==t?void 0:t.mid}addPublisherTrack(e){return this.publisher.addTrack(e)}createPublisherDataChannel(e,t){return this.publisher.createDataChannel(e,t)}getConnectedAddress(e){return e===Tn.PUBLISHER||e===Tn.SUBSCRIBER?this.publisher.getConnectedAddress():this.requiredTransports[0].getConnectedAddress()}get requiredTransports(){const e=[];return this.isPublisherConnectionRequired&&e.push(this.publisher),this.isSubscriberConnectionRequired&&this.subscriber&&e.push(this.subscriber),e}ensureTransportConnected(e,t){return Fi(this,arguments,void 0,(function(e,t){var n=this;let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.peerConnectionTimeout;return function*(){if("connected"!==e.getConnectionState())return new Promise(((e,o)=>Fi(n,void 0,void 0,(function*(){const n=()=>{this.log.warn("abort transport connection",this.logContext),Ss.clearTimeout(s),o(ps.cancelled("room connection has been cancelled"))};(null==t?void 0:t.signal.aborted)&&n(),null==t||t.signal.addEventListener("abort",n);const s=Ss.setTimeout((()=>{null==t||t.signal.removeEventListener("abort",n),o(ps.internal("could not establish pc connection"))}),i);for(;this.state!==Za.CONNECTED;)if(yield er(50),null==t?void 0:t.signal.aborted)return void o(ps.cancelled("room connection has been cancelled"));Ss.clearTimeout(s),null==t||t.signal.removeEventListener("abort",n),e()}))))}()}))}}class ec{static fetchRegionSettings(e,t,n){return Fi(this,void 0,void 0,(function*(){const i=yield ec.fetchLock.lock();try{const i=yield fetch("".concat(function(e){return"".concat(e.protocol.replace("ws","http"),"//").concat(e.host,"/settings")}(e),"/regions"),{headers:{authorization:"Bearer ".concat(t)},signal:n});if(i.ok){const e=function(e){var t;const n=e.get("Cache-Control");if(n){const e=null===(t=n.match(/(?:^|[,\s])max-age=(\d+)/))||void 0===t?void 0:t[1];if(e)return parseInt(e,10)}}(i.headers),t=e?1e3*e:5e3;return{regionSettings:yield i.json(),updatedAtInMs:Date.now(),maxAgeInMs:t}}throw 401===i.status?ps.notAllowed("Could not fetch region settings: ".concat(i.statusText),i.status):ps.internal("Could not fetch region settings: ".concat(i.statusText))}catch(e){throw e instanceof ps?e:(null==n?void 0:n.aborted)?ps.cancelled("Region fetching was aborted"):ps.serverUnreachable("Could not fetch region settings, ".concat(e instanceof Error?"".concat(e.name,": ").concat(e.message):e))}finally{i()}}))}static scheduleRefetch(t,n,i){return Fi(this,void 0,void 0,(function*(){const o=ec.settingsTimeouts.get(t.hostname);clearTimeout(o),ec.settingsTimeouts.set(t.hostname,setTimeout((()=>Fi(this,void 0,void 0,(function*(){try{const e=yield ec.fetchRegionSettings(t,n);ec.updateCachedRegionSettings(t,n,e)}catch(o){if(o instanceof ps&&o.reason===e.ConnectionErrorReason.NotAllowed)return void Di.debug("token is not valid, cancelling auto region refresh");Di.debug("auto refetching of region settings failed",{error:o}),ec.scheduleRefetch(t,n,i)}}))),i))}))}static updateCachedRegionSettings(e,t,n){ec.cache.set(e.hostname,n),ec.scheduleRefetch(e,t,n.maxAgeInMs)}static stopRefetch(e){const t=ec.settingsTimeouts.get(e);t&&(clearTimeout(t),ec.settingsTimeouts.delete(e))}static scheduleCleanup(e){let t=ec.connectionTrackers.get(e);t&&(t.cleanupTimeout&&clearTimeout(t.cleanupTimeout),t.cleanupTimeout=setTimeout((()=>{const t=ec.connectionTrackers.get(e);t&&0===t.connectionCount&&(Di.debug("stopping region refetch after disconnect delay",{hostname:e}),ec.stopRefetch(e)),t&&(t.cleanupTimeout=void 0)}),3e4))}static cancelCleanup(e){const t=ec.connectionTrackers.get(e);(null==t?void 0:t.cleanupTimeout)&&(clearTimeout(t.cleanupTimeout),t.cleanupTimeout=void 0)}notifyConnected(){const e=this.serverUrl.hostname;let t=ec.connectionTrackers.get(e);t||(t={connectionCount:0},ec.connectionTrackers.set(e,t)),t.connectionCount++,ec.cancelCleanup(e)}notifyDisconnected(){const e=this.serverUrl.hostname,t=ec.connectionTrackers.get(e);t&&(t.connectionCount=Math.max(0,t.connectionCount-1),0===t.connectionCount&&ec.scheduleCleanup(e))}constructor(e,t){this.attemptedRegions=[],this.serverUrl=new URL(e),this.token=t}updateToken(e){this.token=e}isCloud(){return vr(this.serverUrl)}getServerUrl(){return this.serverUrl}fetchRegionSettings(e){return Fi(this,void 0,void 0,(function*(){return ec.fetchRegionSettings(this.serverUrl,this.token,e)}))}getNextBestRegionUrl(e){return Fi(this,void 0,void 0,(function*(){if(!this.isCloud())throw Error("region availability is only supported for LiveKit Cloud domains");let t=ec.cache.get(this.serverUrl.hostname);(!t||Date.now()-t.updatedAtInMs>t.maxAgeInMs)&&(t=yield this.fetchRegionSettings(e),ec.updateCachedRegionSettings(this.serverUrl,this.token,t));const n=t.regionSettings.regions.filter((e=>!this.attemptedRegions.find((t=>t.url===e.url))));if(n.length>0){const e=n[0];return this.attemptedRegions.push(e),Di.debug("next region: ".concat(e.region)),e.url}return null}))}resetAttempts(){this.attemptedRegions=[]}setServerReportedRegions(e){ec.updateCachedRegionSettings(this.serverUrl,this.token,e)}}ec.cache=new Map,ec.settingsTimeouts=new Map,ec.connectionTrackers=new Map,ec.fetchLock=new o;class tc extends Error{constructor(e,t,n){super(t),this.code=e,this.message=ic(t,tc.MAX_MESSAGE_BYTES),this.data=n?ic(n,tc.MAX_DATA_BYTES):void 0}static fromProto(e){return new tc(e.code,e.message,e.data)}toProto(){return new Mt({code:this.code,message:this.message,data:this.data})}static builtIn(e,t){return new tc(tc.ErrorCode[e],tc.ErrorMessage[e],t)}}tc.MAX_MESSAGE_BYTES=256,tc.MAX_DATA_BYTES=15360,tc.ErrorCode={APPLICATION_ERROR:1500,CONNECTION_TIMEOUT:1501,RESPONSE_TIMEOUT:1502,RECIPIENT_DISCONNECTED:1503,RESPONSE_PAYLOAD_TOO_LARGE:1504,SEND_FAILED:1505,UNSUPPORTED_METHOD:1400,RECIPIENT_NOT_FOUND:1401,REQUEST_PAYLOAD_TOO_LARGE:1402,UNSUPPORTED_SERVER:1403,UNSUPPORTED_VERSION:1404},tc.ErrorMessage={APPLICATION_ERROR:"Application error in method handler",CONNECTION_TIMEOUT:"Connection timeout",RESPONSE_TIMEOUT:"Response timeout",RECIPIENT_DISCONNECTED:"Recipient disconnected",RESPONSE_PAYLOAD_TOO_LARGE:"Response payload too large",SEND_FAILED:"Failed to send",UNSUPPORTED_METHOD:"Method not supported at destination",RECIPIENT_NOT_FOUND:"Recipient not found",REQUEST_PAYLOAD_TOO_LARGE:"Request payload too large",UNSUPPORTED_SERVER:"RPC not supported by server",UNSUPPORTED_VERSION:"Unsupported RPC version"};function nc(e){return(new TextEncoder).encode(e).length}function ic(e,t){if(nc(e)<=t)return e;let n=0,i=e.length;const o=new TextEncoder;for(;n{this.removeEventListener("dataavailable",n),this.removeEventListener("stop",o),this.removeEventListener("error",s),null==i||i.close(),i=void 0},s=e=>{null==i||i.error(e),this.removeEventListener("dataavailable",n),this.removeEventListener("stop",o),this.removeEventListener("error",s),i=void 0};this.byteStream=new ReadableStream({start:e=>{i=e,n=t=>Fi(this,void 0,void 0,(function*(){let n;if(t.data.arrayBuffer){const e=yield t.data.arrayBuffer();n=new Uint8Array(e)}else{if(!t.data.byteArray)throw new Error("no data available!");n=t.data.byteArray}void 0!==i&&e.enqueue(n)})),this.addEventListener("dataavailable",n)},cancel:()=>{o()}}),this.addEventListener("stop",o),this.addEventListener("error",s)}}class dc extends Ys{get sender(){return this._sender}set sender(e){this._sender=e}get constraints(){return this._constraints}get hasPreConnectBuffer(){return!!this.localTrackRecorder}constructor(t,n,i){let s=arguments.length>3&&void 0!==arguments[3]&&arguments[3];super(t,n,arguments.length>4?arguments[4]:void 0),this.manuallyStopped=!1,this._isUpstreamPaused=!1,this.handleTrackMuteEvent=()=>this.debouncedTrackMuteHandler().catch((()=>this.log.debug("track mute bounce got cancelled by an unmute event",this.logContext))),this.debouncedTrackMuteHandler=ja((()=>Fi(this,void 0,void 0,(function*(){yield this.pauseUpstream()}))),5e3),this.handleTrackUnmuteEvent=()=>Fi(this,void 0,void 0,(function*(){this.debouncedTrackMuteHandler.cancel("unmute"),yield this.resumeUpstream()})),this.handleEnded=()=>{this.isInBackground&&(this.reacquireTrack=!0),this._mediaStreamTrack.removeEventListener("mute",this.handleTrackMuteEvent),this._mediaStreamTrack.removeEventListener("unmute",this.handleTrackUnmuteEvent),this.emit(e.TrackEvent.Ended,this)},this.reacquireTrack=!1,this.providedByUser=s,this.muteLock=new o,this.pauseUpstreamLock=new o,this.trackChangeLock=new o,this.trackChangeLock.lock().then((e=>Fi(this,void 0,void 0,(function*(){try{yield this.setMediaStreamTrack(t,!0)}finally{e()}})))),this._constraints=t.getConstraints(),i&&(this._constraints=i)}get id(){return this._mediaStreamTrack.id}get dimensions(){if(this.kind!==Ys.Kind.Video)return;const{width:e,height:t}=this._mediaStreamTrack.getSettings();return e&&t?{width:e,height:t}:void 0}get isUpstreamPaused(){return this._isUpstreamPaused}get isUserProvided(){return this.providedByUser}get mediaStreamTrack(){var e,t;return null!==(t=null===(e=this.processor)||void 0===e?void 0:e.processedTrack)&&void 0!==t?t:this._mediaStreamTrack}get isLocal(){return!0}getSourceTrackSettings(){return this._mediaStreamTrack.getSettings()}setMediaStreamTrack(e,t){return Fi(this,void 0,void 0,(function*(){var n;if(e===this._mediaStreamTrack&&!t)return;let i;if(this._mediaStreamTrack&&(this.attachedElements.forEach((e=>{Zs(this._mediaStreamTrack,e)})),this.debouncedTrackMuteHandler.cancel("new-track"),this._mediaStreamTrack.removeEventListener("ended",this.handleEnded),this._mediaStreamTrack.removeEventListener("mute",this.handleTrackMuteEvent),this._mediaStreamTrack.removeEventListener("unmute",this.handleTrackUnmuteEvent)),this.mediaStream=new MediaStream([e]),e&&(e.addEventListener("ended",this.handleEnded),e.addEventListener("mute",this.handleTrackMuteEvent),e.addEventListener("unmute",this.handleTrackUnmuteEvent),this._constraints=e.getConstraints()),this.processor&&e){if(this.log.debug("restarting processor",this.logContext),"unknown"===this.kind)throw TypeError("cannot set processor on track of unknown kind");this.processorElement&&(Xs(e,this.processorElement),this.processorElement.muted=!0),yield this.processor.restart({track:e,kind:this.kind,element:this.processorElement}),i=this.processor.processedTrack}this.sender&&"closed"!==(null===(n=this.sender.transport)||void 0===n?void 0:n.state)&&(yield this.sender.replaceTrack(null!=i?i:e)),this.providedByUser||this._mediaStreamTrack===e||this._mediaStreamTrack.stop(),this._mediaStreamTrack=e,e&&(this._mediaStreamTrack.enabled=!this.isMuted,yield this.resumeUpstream(),this.attachedElements.forEach((t=>{Xs(null!=i?i:e,t)})))}))}waitForDimensions(){return Fi(this,arguments,void 0,(function(){var e=this;let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1e3;return function*(){var n;if(e.kind===Ys.Kind.Audio)throw new Error("cannot get dimensions for audio tracks");"iOS"===(null===(n=es())||void 0===n?void 0:n.os)&&(yield er(10));const i=Date.now();for(;Date.now()-i0&&void 0!==arguments[0])||arguments[0];return function*(){if(e.source===Ys.Source.ScreenShare)return;const{deviceId:n,groupId:i}=e._mediaStreamTrack.getSettings(),o=e.kind===Ys.Kind.Audio?"audioinput":"videoinput";return t?ga.getInstance().normalizeDeviceId(o,n,i):n}()}))}mute(){return Fi(this,void 0,void 0,(function*(){return this.setTrackMuted(!0),this}))}unmute(){return Fi(this,void 0,void 0,(function*(){return this.setTrackMuted(!1),this}))}replaceTrack(e,t){return Fi(this,void 0,void 0,(function*(){const n=yield this.trackChangeLock.lock();try{if(!this.sender)throw new gs("unable to replace an unpublished track");let n,i;return"boolean"==typeof t?n=t:void 0!==t&&(n=t.userProvidedTrack,i=t.stopProcessor),this.providedByUser=null==n||n,this.log.debug("replace MediaStreamTrack",this.logContext),yield this.setMediaStreamTrack(e),i&&this.processor&&(yield this.internalStopProcessor()),this}finally{n()}}))}restart(t){return Fi(this,void 0,void 0,(function*(){this.manuallyStopped=!1;const n=yield this.trackChangeLock.lock();try{t||(t=this._constraints);const{deviceId:n,facingMode:i}=t,o=ji(t,["deviceId","facingMode"]);this.log.debug("restarting track with constraints",Object.assign(Object.assign({},this.logContext),{constraints:t}));const s={audio:!1,video:!1};this.kind===Ys.Kind.Video?s.video=!n&&!i||{deviceId:n,facingMode:i}:s.audio=!n||Object.assign({deviceId:n},o),this.attachedElements.forEach((e=>{Zs(this.mediaStreamTrack,e)})),this._mediaStreamTrack.removeEventListener("ended",this.handleEnded),this._mediaStreamTrack.stop();const r=(yield navigator.mediaDevices.getUserMedia(s)).getTracks()[0];return this.kind===Ys.Kind.Video&&(yield r.applyConstraints(o)),r.addEventListener("ended",this.handleEnded),this.log.debug("re-acquired MediaStreamTrack",this.logContext),yield this.setMediaStreamTrack(r),this._constraints=t,this.emit(e.TrackEvent.Restarted,this),this.manuallyStopped&&(this.log.warn("track was stopped during a restart, stopping restarted track",this.logContext),this.stop()),this}finally{n()}}))}setTrackMuted(t){this.log.debug("setting ".concat(this.kind," track ").concat(t?"muted":"unmuted"),this.logContext),this.isMuted===t&&this._mediaStreamTrack.enabled!==t||(this.isMuted=t,this._mediaStreamTrack.enabled=!t,this.emit(t?e.TrackEvent.Muted:e.TrackEvent.Unmuted,this))}get needsReAcquisition(){return"live"!==this._mediaStreamTrack.readyState||this._mediaStreamTrack.muted||!this._mediaStreamTrack.enabled||this.reacquireTrack}handleAppVisibilityChanged(){const e=Object.create(null,{handleAppVisibilityChanged:{get:()=>super.handleAppVisibilityChanged}});return Fi(this,void 0,void 0,(function*(){yield e.handleAppVisibilityChanged.call(this),pr()&&(this.log.debug("visibility changed, is in Background: ".concat(this.isInBackground),this.logContext),this.isInBackground||!this.needsReAcquisition||this.isUserProvided||this.isMuted||(this.log.debug("track needs to be reacquired, restarting ".concat(this.source),this.logContext),yield this.restart(),this.reacquireTrack=!1))}))}stop(){var e;this.manuallyStopped=!0,super.stop(),this._mediaStreamTrack.removeEventListener("ended",this.handleEnded),this._mediaStreamTrack.removeEventListener("mute",this.handleTrackMuteEvent),this._mediaStreamTrack.removeEventListener("unmute",this.handleTrackUnmuteEvent),null===(e=this.processor)||void 0===e||e.destroy(),this.processor=void 0}pauseUpstream(){return Fi(this,void 0,void 0,(function*(){var t;const n=yield this.pauseUpstreamLock.lock();try{if(!0===this._isUpstreamPaused)return;if(!this.sender)return void this.log.warn("unable to pause upstream for an unpublished track",this.logContext);this._isUpstreamPaused=!0,this.emit(e.TrackEvent.UpstreamPaused,this);const n=es();if("Safari"===(null==n?void 0:n.name)&&Tr(n.version,"12.0")<0)throw new ms("pauseUpstream is not supported on Safari < 12.");"closed"!==(null===(t=this.sender.transport)||void 0===t?void 0:t.state)&&(yield this.sender.replaceTrack(null))}finally{n()}}))}resumeUpstream(){return Fi(this,void 0,void 0,(function*(){var t;const n=yield this.pauseUpstreamLock.lock();try{if(!1===this._isUpstreamPaused)return;if(!this.sender)return void this.log.warn("unable to resume upstream for an unpublished track",this.logContext);this._isUpstreamPaused=!1,this.emit(e.TrackEvent.UpstreamResumed,this),"closed"!==(null===(t=this.sender.transport)||void 0===t?void 0:t.state)&&(yield this.sender.replaceTrack(this.mediaStreamTrack))}finally{n()}}))}getRTCStatsReport(){return Fi(this,void 0,void 0,(function*(){var e;if(!(null===(e=this.sender)||void 0===e?void 0:e.getStats))return;return yield this.sender.getStats()}))}setProcessor(t){return Fi(this,arguments,void 0,(function(t){var n=this;let i=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return function*(){var o;const s=yield n.trackChangeLock.lock();try{n.log.debug("setting up processor",n.logContext);const s=document.createElement(n.kind),r={kind:n.kind,track:n._mediaStreamTrack,element:s,audioContext:n.audioContext};if(yield t.init(r),n.log.debug("processor initialized",n.logContext),n.processor&&(yield n.internalStopProcessor()),"unknown"===n.kind)throw TypeError("cannot set processor on track of unknown kind");if(Xs(n._mediaStreamTrack,s),s.muted=!0,s.play().catch((e=>{e instanceof DOMException&&"AbortError"===e.name?(n.log.warn("failed to play processor element, retrying",Object.assign(Object.assign({},n.logContext),{error:e})),setTimeout((()=>{s.play().catch((e=>{n.log.error("failed to play processor element",Object.assign(Object.assign({},n.logContext),{err:e}))}))}),100)):n.log.error("failed to play processor element",Object.assign(Object.assign({},n.logContext),{error:e}))})),n.processor=t,n.processorElement=s,n.processor.processedTrack){for(const e of n.attachedElements)e!==n.processorElement&&i&&(Zs(n._mediaStreamTrack,e),Xs(n.processor.processedTrack,e));yield null===(o=n.sender)||void 0===o?void 0:o.replaceTrack(n.processor.processedTrack)}n.emit(e.TrackEvent.TrackProcessorUpdate,n.processor)}finally{s()}}()}))}getProcessor(){return this.processor}stopProcessor(){return Fi(this,arguments,void 0,(function(){var e=this;let t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];return function*(){const n=yield e.trackChangeLock.lock();try{yield e.internalStopProcessor(t)}finally{n()}}()}))}internalStopProcessor(){return Fi(this,arguments,void 0,(function(){var t=this;let n=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];return function*(){var i,o;t.processor&&(t.log.debug("stopping processor",t.logContext),null===(i=t.processor.processedTrack)||void 0===i||i.stop(),yield t.processor.destroy(),t.processor=void 0,n||(null===(o=t.processorElement)||void 0===o||o.remove(),t.processorElement=void 0),yield t._mediaStreamTrack.applyConstraints(t._constraints),yield t.setMediaStreamTrack(t._mediaStreamTrack,!0),t.emit(e.TrackEvent.TrackProcessorUpdate))}()}))}startPreConnectBuffer(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:100;if(rc)if(this.localTrackRecorder)this.log.warn("preconnect buffer already started");else{{let e="audio/webm;codecs=opus";MediaRecorder.isTypeSupported(e)||(e="video/mp4"),this.localTrackRecorder=new cc(this,{mimeType:e})}this.localTrackRecorder.start(e),this.autoStopPreConnectBuffer=setTimeout((()=>{this.log.warn("preconnect buffer timed out, stopping recording automatically",this.logContext),this.stopPreConnectBuffer()}),1e4)}else this.log.warn("MediaRecorder is not available, cannot start preconnect buffer",this.logContext)}stopPreConnectBuffer(){clearTimeout(this.autoStopPreConnectBuffer),this.localTrackRecorder&&(this.localTrackRecorder.stop(),this.localTrackRecorder=void 0)}getPreConnectBuffer(){var e;return null===(e=this.localTrackRecorder)||void 0===e?void 0:e.byteStream}getPreConnectBufferMimeType(){var e;return null===(e=this.localTrackRecorder)||void 0===e?void 0:e.mimeType}}class lc extends dc{get enhancedNoiseCancellation(){return this.isKrispNoiseFilterEnabled}constructor(t,n){let i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],o=arguments.length>3?arguments[3]:void 0,s=arguments.length>4?arguments[4]:void 0;super(t,Ys.Kind.Audio,n,i,s),this.stopOnMute=!1,this.isKrispNoiseFilterEnabled=!1,this.monitorSender=()=>Fi(this,void 0,void 0,(function*(){if(!this.sender)return void(this._currentBitrate=0);let e;try{e=yield this.getSenderStats()}catch(e){return void this.log.error("could not get audio sender stats",Object.assign(Object.assign({},this.logContext),{error:e}))}e&&this.prevStats&&(this._currentBitrate=sc(e,this.prevStats)),this.prevStats=e})),this.handleKrispNoiseFilterEnable=()=>{this.isKrispNoiseFilterEnabled=!0,this.log.debug("Krisp noise filter enabled",this.logContext),this.emit(e.TrackEvent.AudioTrackFeatureUpdate,this,st.TF_ENHANCED_NOISE_CANCELLATION,!0)},this.handleKrispNoiseFilterDisable=()=>{this.isKrispNoiseFilterEnabled=!1,this.log.debug("Krisp noise filter disabled",this.logContext),this.emit(e.TrackEvent.AudioTrackFeatureUpdate,this,st.TF_ENHANCED_NOISE_CANCELLATION,!1)},this.audioContext=o,this.checkForSilence()}mute(){const e=Object.create(null,{mute:{get:()=>super.mute}});return Fi(this,void 0,void 0,(function*(){const t=yield this.muteLock.lock();try{return this.isMuted?(this.log.debug("Track already muted",this.logContext),this):(this.source===Ys.Source.Microphone&&this.stopOnMute&&!this.isUserProvided&&(this.log.debug("stopping mic track",this.logContext),this._mediaStreamTrack.stop()),yield e.mute.call(this),this)}finally{t()}}))}unmute(){const e=Object.create(null,{unmute:{get:()=>super.unmute}});return Fi(this,void 0,void 0,(function*(){const t=yield this.muteLock.lock();try{if(!this.isMuted)return this.log.debug("Track already unmuted",this.logContext),this;const t=this._constraints.deviceId&&this._mediaStreamTrack.getSettings().deviceId!==Ar(this._constraints.deviceId);return this.source!==Ys.Source.Microphone||!this.stopOnMute&&"ended"!==this._mediaStreamTrack.readyState&&!t||this.isUserProvided||(this.log.debug("reacquiring mic track",this.logContext),yield this.restartTrack()),yield e.unmute.call(this),this}finally{t()}}))}restartTrack(e){return Fi(this,void 0,void 0,(function*(){let t;if(e){const n=Us({audio:e});"boolean"!=typeof n.audio&&(t=n.audio)}yield this.restart(t)}))}restart(e){const t=Object.create(null,{restart:{get:()=>super.restart}});return Fi(this,void 0,void 0,(function*(){const n=yield t.restart.call(this,e);return this.checkForSilence(),n}))}startMonitor(){mr()&&(this.monitorInterval||(this.monitorInterval=setInterval((()=>{this.monitorSender()}),oc)))}setProcessor(t){return Fi(this,void 0,void 0,(function*(){var n;const i=yield this.trackChangeLock.lock();try{if(!gr()&&!this.audioContext)throw Error("Audio context needs to be set on LocalAudioTrack in order to enable processors");this.processor&&(yield this.internalStopProcessor());const i={kind:this.kind,track:this._mediaStreamTrack,audioContext:this.audioContext};this.log.debug("setting up audio processor ".concat(t.name),this.logContext),yield t.init(i),this.processor=t,this.processor.processedTrack&&(yield null===(n=this.sender)||void 0===n?void 0:n.replaceTrack(this.processor.processedTrack),this.processor.processedTrack.addEventListener("enable-lk-krisp-noise-filter",this.handleKrispNoiseFilterEnable),this.processor.processedTrack.addEventListener("disable-lk-krisp-noise-filter",this.handleKrispNoiseFilterDisable)),this.emit(e.TrackEvent.TrackProcessorUpdate,this.processor)}finally{i()}}))}setAudioContext(e){this.audioContext=e}getSenderStats(){return Fi(this,void 0,void 0,(function*(){var e;if(!(null===(e=this.sender)||void 0===e?void 0:e.getStats))return;let t;return(yield this.sender.getStats()).forEach((e=>{"outbound-rtp"===e.type&&(t={type:"audio",streamId:e.id,packetsSent:e.packetsSent,packetsLost:e.packetsLost,bytesSent:e.bytesSent,timestamp:e.timestamp,roundTripTime:e.roundTripTime,jitter:e.jitter})})),t}))}checkForSilence(){return Fi(this,void 0,void 0,(function*(){const t=yield js(this);return t&&(this.isMuted||this.log.debug("silence detected on local audio track",this.logContext),this.emit(e.TrackEvent.AudioSilenceDetected)),t}))}}const uc=Object.values(Ms),hc=Object.values(xs),pc=Object.values(As),mc=[Ms.h180,Ms.h360],gc=[xs.h180,xs.h360],vc=e=>[{scaleResolutionDownBy:2,fps:e.encoding.maxFramerate}].map((t=>{var n,i;return new Es(Math.floor(e.width/t.scaleResolutionDownBy),Math.floor(e.height/t.scaleResolutionDownBy),Math.max(15e4,Math.floor(e.encoding.maxBitrate/(Math.pow(t.scaleResolutionDownBy,2)*((null!==(n=e.encoding.maxFramerate)&&void 0!==n?n:30)/(null!==(i=t.fps)&&void 0!==i?i:30))))),t.fps,e.encoding.priority)})),fc=["q","h","f"];function kc(e,t,n,i){var o,s;let r=null==i?void 0:i.videoEncoding;e&&(r=null==i?void 0:i.screenShareEncoding);const a=null==i?void 0:i.simulcast,c=null==i?void 0:i.scalabilityMode,d=null==i?void 0:i.videoCodec;if(!r&&!a&&!c||!t||!n)return[{}];r||(r=function(e,t,n,i){const o=function(e,t,n){if(e)return pc;const i=t>n?t/n:n/t;if(Math.abs(i-16/9)=r)break}if(i)switch(i){case"av1":case"h265":s=Object.assign({},s),s.maxBitrate=.7*s.maxBitrate;break;case"vp9":s=Object.assign({},s),s.maxBitrate=.85*s.maxBitrate}return s}(e,t,n,d),Di.debug("using video encoding",r));const l=r.maxFramerate,u=new Es(t,n,r.maxBitrate,r.maxFramerate,r.priority);if(c&&sr(d)){const e=new Cc(c),t=[];if(e.spatial>3)throw new Error("unsupported scalabilityMode: ".concat(c));const n=es();if(ur()||gr()||"Chrome"===(null==n?void 0:n.name)&&Tr(null==n?void 0:n.version,"113")<0){const i="h"==e.suffix?2:3,o=function(e){return e||(e=es()),"Safari"===(null==e?void 0:e.name)&&Tr(e.version,"18.3")>0||"iOS"===(null==e?void 0:e.os)&&!!(null==e?void 0:e.osVersion)&&Tr(e.osVersion,"18.3")>0}(n);for(let n=0;n0){const e=p[0];p.length>1&&([,h]=p);const i=Math.max(t,n);if(i>=960&&h)return bc(t,n,[e,h,u],l);if(i>=480)return bc(t,n,[e,u],l)}return bc(t,n,[u])}function yc(e,t){if(e)return vc(t);const{width:n,height:i}=t,o=n>i?n/i:i/n;return Math.abs(o-16/9){if(s>=fc.length)return;const r=Math.min(e,t),a={rid:fc[s],scaleResolutionDownBy:Math.max(1,r/Math.min(n.width,n.height)),maxBitrate:n.encoding.maxBitrate},c=i&&n.encoding.maxFramerate?Math.min(i,n.encoding.maxFramerate):n.encoding.maxFramerate;c&&(a.maxFramerate=c);const d=cr()||0===s;n.encoding.priority&&d&&(a.priority=n.encoding.priority,a.networkPriority=n.encoding.priority),o.push(a)})),gr()&&"ios"===yr()){let e;o.forEach((t=>{e?t.maxFramerate&&t.maxFramerate>e&&(e=t.maxFramerate):e=t.maxFramerate}));let t=!0;o.forEach((n=>{var i;n.maxFramerate!=e&&(t&&(t=!1,Di.info("Simulcast on iOS React-Native requires all encodings to share the same framerate.")),Di.info('Setting framerate of encoding "'.concat(null!==(i=n.rid)&&void 0!==i?i:"",'" to ').concat(e)),n.maxFramerate=e)}))}return o}function Tc(e){if(e)return e.sort(((e,t)=>{const{encoding:n}=e,{encoding:i}=t;return n.maxBitrate>i.maxBitrate?1:n.maxBitratei.maxFramerate?1:-1:0}))}class Cc{constructor(e){const t=e.match(/^L(\d)T(\d)(h|_KEY|_KEY_SHIFT){0,1}$/);if(!t)throw new Error("invalid scalability mode");if(this.spatial=parseInt(t[1]),this.temporal=parseInt(t[2]),t.length>3)switch(t[3]){case"h":case"_KEY":case"_KEY_SHIFT":this.suffix=t[3]}}toString(){var e;return"L".concat(this.spatial,"T").concat(this.temporal).concat(null!==(e=this.suffix)&&void 0!==e?e:"")}}class Sc extends dc{get sender(){return this._sender}set sender(e){this._sender=e,this.degradationPreference&&this.setDegradationPreference(this.degradationPreference)}constructor(t,n){let i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],s=arguments.length>3?arguments[3]:void 0;super(t,Ys.Kind.Video,n,i,s),this.simulcastCodecs=new Map,this.degradationPreference="balanced",this.isCpuConstrained=!1,this.optimizeForPerformance=!1,this.monitorSender=()=>Fi(this,void 0,void 0,(function*(){if(!this.sender)return void(this._currentBitrate=0);let t;try{t=yield this.getSenderStats()}catch(e){return void this.log.error("could not get video sender stats",Object.assign(Object.assign({},this.logContext),{error:e}))}const n=new Map(t.map((e=>[e.rid,e]))),i=t.some((e=>"cpu"===e.qualityLimitationReason));if(i!==this.isCpuConstrained&&(this.isCpuConstrained=i,this.isCpuConstrained&&this.emit(e.TrackEvent.CpuConstrained)),this.prevStats){let e=0;n.forEach(((t,n)=>{var i;const o=null===(i=this.prevStats)||void 0===i?void 0:i.get(n);e+=sc(t,o)})),this._currentBitrate=e}this.prevStats=n})),this.senderLock=new o}get isSimulcast(){return!!(this.sender&&this.sender.getParameters().encodings.length>1)}startMonitor(e){var t;if(this.signalClient=e,!mr())return;const n=null===(t=this.sender)||void 0===t?void 0:t.getParameters();n&&(this.encodings=n.encodings),this.monitorInterval||(this.monitorInterval=setInterval((()=>{this.monitorSender()}),oc))}stop(){this._mediaStreamTrack.getConstraints(),this.simulcastCodecs.forEach((e=>{e.mediaStreamTrack.stop()})),super.stop()}pauseUpstream(){const e=Object.create(null,{pauseUpstream:{get:()=>super.pauseUpstream}});return Fi(this,void 0,void 0,(function*(){var t,n,i,o,s;yield e.pauseUpstream.call(this);try{for(var r,a=!0,c=Vi(this.simulcastCodecs.values());!(t=(r=yield c.next()).done);a=!0){o=r.value,a=!1;const e=o;yield null===(s=e.sender)||void 0===s?void 0:s.replaceTrack(null)}}catch(e){n={error:e}}finally{try{a||t||!(i=c.return)||(yield i.call(c))}finally{if(n)throw n.error}}}))}resumeUpstream(){const e=Object.create(null,{resumeUpstream:{get:()=>super.resumeUpstream}});return Fi(this,void 0,void 0,(function*(){var t,n,i,o,s;yield e.resumeUpstream.call(this);try{for(var r,a=!0,c=Vi(this.simulcastCodecs.values());!(t=(r=yield c.next()).done);a=!0){o=r.value,a=!1;const e=o;yield null===(s=e.sender)||void 0===s?void 0:s.replaceTrack(e.mediaStreamTrack)}}catch(e){n={error:e}}finally{try{a||t||!(i=c.return)||(yield i.call(c))}finally{if(n)throw n.error}}}))}mute(){const e=Object.create(null,{mute:{get:()=>super.mute}});return Fi(this,void 0,void 0,(function*(){const t=yield this.muteLock.lock();try{return this.isMuted?(this.log.debug("Track already muted",this.logContext),this):(this.source!==Ys.Source.Camera||this.isUserProvided||(this.log.debug("stopping camera track",this.logContext),this._mediaStreamTrack.stop()),yield e.mute.call(this),this)}finally{t()}}))}unmute(){const e=Object.create(null,{unmute:{get:()=>super.unmute}});return Fi(this,void 0,void 0,(function*(){const t=yield this.muteLock.lock();try{return this.isMuted?(this.source!==Ys.Source.Camera||this.isUserProvided||(this.log.debug("reacquiring camera track",this.logContext),yield this.restartTrack()),yield e.unmute.call(this),this):(this.log.debug("Track already unmuted",this.logContext),this)}finally{t()}}))}setTrackMuted(e){super.setTrackMuted(e);for(const t of this.simulcastCodecs.values())t.mediaStreamTrack.enabled=!e}getSenderStats(){return Fi(this,void 0,void 0,(function*(){var e;if(!(null===(e=this.sender)||void 0===e?void 0:e.getStats))return[];const t=[],n=yield this.sender.getStats();return n.forEach((e=>{var i;if("outbound-rtp"===e.type){const o={type:"video",streamId:e.id,frameHeight:e.frameHeight,frameWidth:e.frameWidth,framesPerSecond:e.framesPerSecond,framesSent:e.framesSent,firCount:e.firCount,pliCount:e.pliCount,nackCount:e.nackCount,packetsSent:e.packetsSent,bytesSent:e.bytesSent,qualityLimitationReason:e.qualityLimitationReason,qualityLimitationDurations:e.qualityLimitationDurations,qualityLimitationResolutionChanges:e.qualityLimitationResolutionChanges,rid:null!==(i=e.rid)&&void 0!==i?i:e.id,retransmittedPacketsSent:e.retransmittedPacketsSent,targetBitrate:e.targetBitrate,timestamp:e.timestamp},s=n.get(e.remoteId);s&&(o.jitter=s.jitter,o.packetsLost=s.packetsLost,o.roundTripTime=s.roundTripTime),t.push(o)}})),t.sort(((e,t)=>{var n,i;return(null!==(n=t.frameWidth)&&void 0!==n?n:0)-(null!==(i=e.frameWidth)&&void 0!==i?i:0)})),t}))}setPublishingQuality(t){const n=[];for(let i=e.VideoQuality.LOW;i<=e.VideoQuality.HIGH;i+=1)n.push(new Xn({quality:i,enabled:i<=t}));this.log.debug("setting publishing quality. max quality ".concat(t),this.logContext),this.setPublishingLayers(sr(this.codec),n)}restartTrack(e){return Fi(this,void 0,void 0,(function*(){var t,n,i,o,s;let r;if(e){const t=Us({video:e});"boolean"!=typeof t.video&&(r=t.video)}yield this.restart(r),this.isCpuConstrained=!1;try{for(var a,c=!0,d=Vi(this.simulcastCodecs.values());!(t=(a=yield d.next()).done);c=!0){o=a.value,c=!1;const e=o;e.sender&&"closed"!==(null===(s=e.sender.transport)||void 0===s?void 0:s.state)&&(e.mediaStreamTrack=this.mediaStreamTrack.clone(),yield e.sender.replaceTrack(e.mediaStreamTrack))}}catch(e){n={error:e}}finally{try{c||t||!(i=d.return)||(yield i.call(d))}finally{if(n)throw n.error}}}))}setProcessor(e){const t=Object.create(null,{setProcessor:{get:()=>super.setProcessor}});return Fi(this,arguments,void 0,(function(e){var n=this;let i=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return function*(){var o,s,r,a,c,d;if(yield t.setProcessor.call(n,e,i),null===(c=n.processor)||void 0===c?void 0:c.processedTrack)try{for(var l,u=!0,h=Vi(n.simulcastCodecs.values());!(o=(l=yield h.next()).done);u=!0){a=l.value,u=!1;const e=a;yield null===(d=e.sender)||void 0===d?void 0:d.replaceTrack(n.processor.processedTrack)}}catch(e){s={error:e}}finally{try{u||o||!(r=h.return)||(yield r.call(h))}finally{if(s)throw s.error}}}()}))}setDegradationPreference(e){return Fi(this,void 0,void 0,(function*(){if(this.degradationPreference=e,this.sender)try{this.log.debug("setting degradationPreference to ".concat(e),this.logContext);const t=this.sender.getParameters();t.degradationPreference=e,this.sender.setParameters(t)}catch(e){this.log.warn("failed to set degradationPreference",Object.assign({error:e},this.logContext))}}))}addSimulcastTrack(e,t){if(this.simulcastCodecs.has(e))return void this.log.error("".concat(e," already added, skipping adding simulcast codec"),this.logContext);const n={codec:e,mediaStreamTrack:this.mediaStreamTrack.clone(),sender:void 0,encodings:t};return this.simulcastCodecs.set(e,n),n}setSimulcastTrackSender(e,t){const n=this.simulcastCodecs.get(e);n&&(n.sender=t,setTimeout((()=>{this.subscribedCodecs&&this.setPublishingCodecs(this.subscribedCodecs)}),5e3))}setPublishingCodecs(e){return Fi(this,void 0,void 0,(function*(){var t,n,i,o,s,r,a;if(this.log.debug("setting publishing codecs",Object.assign(Object.assign({},this.logContext),{codecs:e,currentCodec:this.codec})),!this.codec&&e.length>0)return yield this.setPublishingLayers(sr(e[0].codec),e[0].qualities),[];this.subscribedCodecs=e;const c=[];try{for(t=!0,n=Vi(e);!(o=(i=yield n.next()).done);t=!0){a=i.value,t=!1;const e=a;if(this.codec&&this.codec!==e.codec){const t=this.simulcastCodecs.get(e.codec);if(this.log.debug("try setPublishingCodec for ".concat(e.codec),Object.assign(Object.assign({},this.logContext),{simulcastCodecInfo:t})),t&&t.sender)t.encodings&&(this.log.debug("try setPublishingLayersForSender ".concat(e.codec),this.logContext),yield Ec(t.sender,t.encodings,e.qualities,this.senderLock,sr(e.codec),this.log,this.logContext));else for(const t of e.qualities)if(t.enabled){c.push(e.codec);break}}else yield this.setPublishingLayers(sr(e.codec),e.qualities)}}catch(e){s={error:e}}finally{try{t||o||!(r=n.return)||(yield r.call(n))}finally{if(s)throw s.error}}return c}))}setPublishingLayers(e,t){return Fi(this,void 0,void 0,(function*(){this.optimizeForPerformance?this.log.info("skipping setPublishingLayers due to optimized publishing performance",Object.assign(Object.assign({},this.logContext),{qualities:t})):(this.log.debug("setting publishing layers",Object.assign(Object.assign({},this.logContext),{qualities:t})),this.sender&&this.encodings&&(yield Ec(this.sender,this.encodings,t,this.senderLock,e,this.log,this.logContext)))}))}prioritizePerformance(){return Fi(this,void 0,void 0,(function*(){if(!this.sender)throw new Error("sender not found");const e=yield this.senderLock.lock();try{this.optimizeForPerformance=!0;const e=this.sender.getParameters();e.encodings=e.encodings.map(((e,t)=>{var n;return Object.assign(Object.assign({},e),{active:0===t,scaleResolutionDownBy:Math.max(1,Math.ceil((null!==(n=this.mediaStreamTrack.getSettings().height)&&void 0!==n?n:360)/360)),scalabilityMode:0===t&&sr(this.codec)?"L1T3":void 0,maxFramerate:0===t?15:0,maxBitrate:0===t?e.maxBitrate:0})})),this.log.debug("setting performance optimised encodings",Object.assign(Object.assign({},this.logContext),{encodings:e.encodings})),this.encodings=e.encodings,yield this.sender.setParameters(e)}catch(e){this.log.error("failed to set performance optimised encodings",Object.assign(Object.assign({},this.logContext),{error:e})),this.optimizeForPerformance=!1}finally{e()}}))}handleAppVisibilityChanged(){const e=Object.create(null,{handleAppVisibilityChanged:{get:()=>super.handleAppVisibilityChanged}});return Fi(this,void 0,void 0,(function*(){yield e.handleAppVisibilityChanged.call(this),pr()&&this.isInBackground&&this.source===Ys.Source.Camera&&(this._mediaStreamTrack.enabled=!1)}))}}function Ec(e,t,n,i,o,s,r){return Fi(this,void 0,void 0,(function*(){const a=yield i.lock();s.debug("setPublishingLayersForSender",Object.assign(Object.assign({},r),{sender:e,qualities:n,senderEncodings:t}));try{const i=e.getParameters(),{encodings:a}=i;if(!a)return;if(a.length!==t.length)return void s.warn("cannot set publishing layers, encodings mismatch",Object.assign(Object.assign({},r),{encodings:a,senderEncodings:t}));let c=!1;if(!1&&a[0].scalabilityMode);else{if(o){n.some((e=>e.enabled))&&n.forEach((e=>e.enabled=!0))}a.forEach(((e,i)=>{var o;let a=null!==(o=e.rid)&&void 0!==o?o:"";""===a&&(a="q");const d=wc(a),l=n.find((e=>e.quality===d));l&&e.active!==l.enabled&&(c=!0,e.active=l.enabled,s.debug("setting layer ".concat(l.quality," to ").concat(e.active?"enabled":"disabled"),r),cr()&&(l.enabled?(e.scaleResolutionDownBy=t[i].scaleResolutionDownBy,e.maxBitrate=t[i].maxBitrate,e.maxFrameRate=t[i].maxFrameRate):(e.scaleResolutionDownBy=4,e.maxBitrate=10,e.maxFrameRate=2)))}))}c&&(i.encodings=a,s.debug("setting encodings",Object.assign(Object.assign({},r),{encodings:i.encodings})),yield e.setParameters(i))}finally{a()}}))}function wc(t){switch(t){case"f":default:return e.VideoQuality.HIGH;case"h":return e.VideoQuality.MEDIUM;case"q":return e.VideoQuality.LOW}}function Rc(t,n,i,o){if(!i)return[new vt({quality:e.VideoQuality.HIGH,width:t,height:n,bitrate:0,ssrc:0})];if(o){const o=i[0].scalabilityMode,s=new Cc(o),r=[],a="h"==s.suffix?1.5:2,c="h"==s.suffix?2:3;for(let o=0;o{var i,o,s;const r=null!==(i=e.scaleResolutionDownBy)&&void 0!==i?i:1;let a=wc(null!==(o=e.rid)&&void 0!==o?o:"");return new vt({quality:a,width:Math.ceil(t/r),height:Math.ceil(n/r),bitrate:null!==(s=e.maxBitrate)&&void 0!==s?s:0,ssrc:0})}))}const Pc="_lossy",Ic="_reliable",Oc="leave-reconnect";var _c;!function(e){e[e.New=0]="New",e[e.Connected=1]="Connected",e[e.Disconnected=2]="Disconnected",e[e.Reconnecting=3]="Reconnecting",e[e.Closed=4]="Closed"}(_c||(_c={}));class Dc extends Ki.EventEmitter{get isClosed(){return this._isClosed}get pendingReconnect(){return!!this.reconnectTimeout}constructor(t){var n;super(),this.options=t,this.rtcConfig={},this.peerConnectionTimeout=Xa.peerConnectionTimeout,this.fullReconnectOnNext=!1,this.latestRemoteOfferId=0,this.subscriberPrimary=!1,this.pcState=_c.New,this._isClosed=!0,this.pendingTrackResolvers={},this.reconnectAttempts=0,this.reconnectStart=0,this.attemptingReconnect=!1,this.joinAttempts=0,this.maxJoinAttempts=1,this.shouldFailNext=!1,this.log=Di,this.reliableDataSequence=1,this.reliableMessageBuffer=new Ea,this.reliableReceivedState=new wa(3e4),this.lossyDataStatCurrentBytes=0,this.lossyDataStatByterate=0,this.lossyDataDropCount=0,this.midToTrackId={},this.isWaitingForNetworkReconnect=!1,this.handleDataChannel=e=>Fi(this,[e],void 0,(function(e){var t=this;let{channel:n}=e;return function*(){if(n){if(n.label===Ic)t.reliableDCSub=n;else{if(n.label!==Pc)return;t.lossyDCSub=n}t.log.debug("on data channel ".concat(n.id,", ").concat(n.label),t.logContext),n.onmessage=t.handleDataMessage}}()})),this.handleDataMessage=t=>Fi(this,void 0,void 0,(function*(){var n,i,o,s,r;const a=yield this.dataProcessLock.lock();try{let a;if(t.data instanceof ArrayBuffer)a=t.data;else{if(!(t.data instanceof Blob))return void this.log.error("unsupported data type",Object.assign(Object.assign({},this.logContext),{data:t.data}));a=yield t.data.arrayBuffer()}const c=kt.fromBinary(new Uint8Array(a));if(c.sequence>0&&""!==c.participantSid){const e=this.reliableReceivedState.get(c.participantSid);if(e&&c.sequence<=e)return;this.reliableReceivedState.set(c.participantSid,c.sequence)}if("speaker"===(null===(n=c.value)||void 0===n?void 0:n.case))this.emit(e.EngineEvent.ActiveSpeakersUpdate,c.value.value.speakers);else if("encryptedPacket"===(null===(i=c.value)||void 0===i?void 0:i.case)){if(!this.e2eeManager)return void this.log.error("Received encrypted packet but E2EE not set up",this.logContext);const t=yield null===(o=this.e2eeManager)||void 0===o?void 0:o.handleEncryptedData(c.value.value.encryptedValue,c.value.value.iv,c.participantIdentity,c.value.value.keyIndex),n=Tt.fromBinary(t.payload),i=new kt({value:n.value,participantIdentity:c.participantIdentity,participantSid:c.participantSid});"user"===(null===(s=i.value)||void 0===s?void 0:s.case)&&Mc(i,i.value.value),this.emit(e.EngineEvent.DataPacketReceived,i,c.value.value.encryptionType)}else"user"===(null===(r=c.value)||void 0===r?void 0:r.case)&&Mc(c,c.value.value),this.emit(e.EngineEvent.DataPacketReceived,c,pt.NONE)}finally{a()}})),this.handleDataError=e=>{const t=0===e.currentTarget.maxRetransmits?"lossy":"reliable";if(e instanceof ErrorEvent&&e.error){const{error:n}=e.error;this.log.error("DataChannel error on ".concat(t,": ").concat(e.message),Object.assign(Object.assign({},this.logContext),{error:n}))}else this.log.error("Unknown DataChannel error on ".concat(t),Object.assign(Object.assign({},this.logContext),{event:e}))},this.handleBufferedAmountLow=e=>{const t=0===e.currentTarget.maxRetransmits?yt.LOSSY:yt.RELIABLE;this.updateAndEmitDCBufferStatus(t)},this.handleDisconnect=(t,n)=>{if(this._isClosed)return;this.log.warn("".concat(t," disconnected"),this.logContext),0===this.reconnectAttempts&&(this.reconnectStart=Date.now());const i=t=>{this.log.warn("could not recover connection after ".concat(this.reconnectAttempts," attempts, ").concat(t,"ms. giving up"),this.logContext),this.emit(e.EngineEvent.Disconnected),this.close()},o=Date.now()-this.reconnectStart;let s=this.getNextRetryDelay({elapsedMs:o,retryCount:this.reconnectAttempts});null!==s?(t===Oc&&(s=0),this.log.debug("reconnecting in ".concat(s,"ms"),this.logContext),this.clearReconnectTimeout(),this.token&&this.regionUrlProvider&&this.regionUrlProvider.updateToken(this.token),this.reconnectTimeout=Ss.setTimeout((()=>this.attemptReconnect(n).finally((()=>this.reconnectTimeout=void 0))),s)):i(o)},this.waitForRestarted=()=>new Promise(((t,n)=>{this.pcState===_c.Connected&&t();const i=()=>{this.off(e.EngineEvent.Disconnected,o),t()},o=()=>{this.off(e.EngineEvent.Restarted,i),n()};this.once(e.EngineEvent.Restarted,i),this.once(e.EngineEvent.Disconnected,o)})),this.updateAndEmitDCBufferStatus=t=>{if(t===yt.RELIABLE){const e=this.dataChannelForKind(t);e&&this.reliableMessageBuffer.alignBufferedAmount(e.bufferedAmount)}const n=this.isBufferStatusLow(t);void 0!==n&&n!==this.dcBufferStatus.get(t)&&(this.dcBufferStatus.set(t,n),this.emit(e.EngineEvent.DCBufferStatusChanged,n,t))},this.isBufferStatusLow=e=>{const t=this.dataChannelForKind(e);if(t)return t.bufferedAmount<=t.bufferedAmountLowThreshold},this.handleBrowserOnLine=()=>Fi(this,void 0,void 0,(function*(){if(!this.url)return;(yield fetch(Nr(this.url),{method:"HEAD"}).then((e=>e.ok)).catch((()=>!1)))&&(this.log.info("detected network reconnected"),(this.client.currentState===ba.RECONNECTING||this.isWaitingForNetworkReconnect&&this.client.currentState===ba.CONNECTED)&&(this.clearReconnectTimeout(),this.attemptReconnect(it.RR_SIGNAL_DISCONNECTED),this.isWaitingForNetworkReconnect=!1))})),this.handleBrowserOffline=()=>Fi(this,void 0,void 0,(function*(){if(this.url)try{yield Promise.race([fetch(Nr(this.url),{method:"HEAD"}),er(4e3).then((()=>Promise.reject()))])}catch(e){!1===window.navigator.onLine&&(this.log.info("detected network interruption"),this.isWaitingForNetworkReconnect=!0)}})),this.log=xi(null!==(n=t.loggerName)&&void 0!==n?n:e.LoggerNames.Engine),this.loggerOptions={loggerName:t.loggerName,loggerContextCb:()=>this.logContext},this.client=new Ta(void 0,this.loggerOptions),this.client.signalLatency=this.options.expSignalLatency,this.reconnectPolicy=this.options.reconnectPolicy,this.closingLock=new o,this.dataProcessLock=new o,this.dcBufferStatus=new Map([[yt.LOSSY,!0],[yt.RELIABLE,!0]]),this.client.onParticipantUpdate=t=>this.emit(e.EngineEvent.ParticipantUpdate,t),this.client.onConnectionQuality=t=>this.emit(e.EngineEvent.ConnectionQualityUpdate,t),this.client.onRoomUpdate=t=>this.emit(e.EngineEvent.RoomUpdate,t),this.client.onSubscriptionError=t=>this.emit(e.EngineEvent.SubscriptionError,t),this.client.onSubscriptionPermissionUpdate=t=>this.emit(e.EngineEvent.SubscriptionPermissionUpdate,t),this.client.onSpeakersChanged=t=>this.emit(e.EngineEvent.SpeakersChanged,t),this.client.onStreamStateUpdate=t=>this.emit(e.EngineEvent.StreamStateChanged,t),this.client.onRequestResponse=t=>this.emit(e.EngineEvent.SignalRequestResponse,t)}get logContext(){var e,t,n,i,o,s;return{room:null===(t=null===(e=this.latestJoinResponse)||void 0===e?void 0:e.room)||void 0===t?void 0:t.name,roomID:null===(i=null===(n=this.latestJoinResponse)||void 0===n?void 0:n.room)||void 0===i?void 0:i.sid,participant:null===(s=null===(o=this.latestJoinResponse)||void 0===o?void 0:o.participant)||void 0===s?void 0:s.identity,pID:this.participantSid}}join(t,n,i,o){return Fi(this,arguments,void 0,(function(t,n,i,o){var s=this;let r=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return function*(){s.url=t,s.token=n,s.signalOpts=i,s.maxJoinAttempts=i.maxRetries;try{s.joinAttempts+=1,s.setupSignalClientCallbacks();const a=yield s.client.join(t,n,i,o,r);return s._isClosed=!1,s.latestJoinResponse=a,s.subscriberPrimary=a.subscriberPrimary,s.pcManager||(yield s.configure(a,!r)),s.subscriberPrimary&&!a.fastPublish||s.negotiate().catch((e=>{Di.error(e,s.logContext)})),s.registerOnLineListener(),s.clientConfiguration=a.clientConfiguration,s.emit(e.EngineEvent.SignalConnected,a),a}catch(a){if(a instanceof ps)if(a.reason===e.ConnectionErrorReason.ServerUnreachable){if(s.log.warn("Couldn't connect to server, attempt ".concat(s.joinAttempts," of ").concat(s.maxJoinAttempts),s.logContext),s.joinAttempts{e&&(e.close(),e.onbufferedamountlow=null,e.onclose=null,e.onclosing=null,e.onerror=null,e.onmessage=null,e.onopen=null)};t(this.lossyDC),t(this.lossyDCSub),t(this.reliableDC),t(this.reliableDCSub),this.lossyDC=void 0,this.lossyDCSub=void 0,this.reliableDC=void 0,this.reliableDCSub=void 0,this.reliableMessageBuffer=new Ea,this.reliableDataSequence=1,this.reliableReceivedState.clear()}))}cleanupLossyDataStats(){this.lossyDataStatByterate=0,this.lossyDataStatCurrentBytes=0,this.lossyDataStatInterval&&(clearInterval(this.lossyDataStatInterval),this.lossyDataStatInterval=void 0),this.lossyDataDropCount=0}cleanupClient(){return Fi(this,void 0,void 0,(function*(){yield this.client.close(),this.client.resetCallbacks()}))}addTrack(e){if(this.pendingTrackResolvers[e.cid])throw new gs("a track with the same ID has already been published");return new Promise(((t,n)=>{const i=setTimeout((()=>{delete this.pendingTrackResolvers[e.cid],n(ps.timeout("publication of local track timed out, no response from server"))}),1e4);this.pendingTrackResolvers[e.cid]={resolve:e=>{clearTimeout(i),t(e)},reject:()=>{clearTimeout(i),n(new Error("Cancelled publication by calling unpublish"))}},this.client.sendAddTrack(e)}))}removeTrack(e){if(e.track&&this.pendingTrackResolvers[e.track.id]){const{reject:t}=this.pendingTrackResolvers[e.track.id];t&&t(),delete this.pendingTrackResolvers[e.track.id]}try{return this.pcManager.removeTrack(e),!0}catch(e){this.log.warn("failed to remove track",Object.assign(Object.assign({},this.logContext),{error:e}))}return!1}updateMuteStatus(e,t){this.client.sendMuteTrack(e,t)}get dataSubscriberReadyState(){var e;return null===(e=this.reliableDCSub)||void 0===e?void 0:e.readyState}getConnectedServerAddress(){return Fi(this,void 0,void 0,(function*(){var e;return null===(e=this.pcManager)||void 0===e?void 0:e.getConnectedAddress()}))}setRegionUrlProvider(e){this.regionUrlProvider=e}configure(t,n){return Fi(this,void 0,void 0,(function*(){var i,o;if(this.pcManager&&this.pcManager.currentState!==Za.NEW)return;this.participantSid=null===(i=t.participant)||void 0===i?void 0:i.sid;const s=this.makeRTCConfiguration(t);var r;this.pcManager=new $a(s,n?"publisher-only":t.subscriberPrimary?"subscriber-primary":"publisher-primary",this.loggerOptions),this.emit(e.EngineEvent.TransportsCreated,this.pcManager.publisher,this.pcManager.subscriber),this.pcManager.onIceCandidate=(e,t)=>{this.client.sendIceCandidate(e,t)},this.pcManager.onPublisherOffer=(e,t)=>{this.client.sendOffer(e,t)},this.pcManager.onDataChannel=this.handleDataChannel,this.pcManager.onStateChange=(n,i,o)=>Fi(this,void 0,void 0,(function*(){if(this.log.debug("primary PC state changed ".concat(n),this.logContext),["closed","disconnected","failed"].includes(i)&&(this.publisherConnectionPromise=void 0),n===Za.CONNECTED){const n=this.pcState===_c.New;this.pcState=_c.Connected,n&&this.emit(e.EngineEvent.Connected,t)}else n===Za.FAILED&&(this.pcState!==_c.Connected&&this.pcState!==_c.Reconnecting||(this.pcState=_c.Disconnected,this.handleDisconnect("peerconnection failed","failed"===o?it.RR_SUBSCRIBER_FAILED:it.RR_PUBLISHER_FAILED)));const s=this.client.isDisconnected||this.client.currentState===ba.RECONNECTING,r=[Za.FAILED,Za.CLOSING,Za.CLOSED].includes(n);s&&r&&!this._isClosed&&this.emit(e.EngineEvent.Offline)})),this.pcManager.onTrack=t=>{0!==t.streams.length&&this.emit(e.EngineEvent.MediaTrackAdded,t.track,t.streams[0],t.receiver)},void 0!==(r=null===(o=t.serverInfo)||void 0===o?void 0:o.protocol)&&r>13||this.createDataChannels()}))}setupSignalClientCallbacks(){this.client.onAnswer=(e,t,n)=>Fi(this,void 0,void 0,(function*(){this.pcManager&&(this.log.debug("received server answer",Object.assign(Object.assign({},this.logContext),{RTCSdpType:e.type,sdp:e.sdp,midToTrackId:n})),this.midToTrackId=n,yield this.pcManager.setPublisherAnswer(e,t))})),this.client.onTrickle=(e,t)=>{this.pcManager&&(this.log.debug("got ICE candidate from peer",Object.assign(Object.assign({},this.logContext),{candidate:e,target:t})),this.pcManager.addIceCandidate(e,t))},this.client.onOffer=(e,t,n)=>Fi(this,void 0,void 0,(function*(){if(this.latestRemoteOfferId=t,!this.pcManager)return;this.midToTrackId=n;const i=yield this.pcManager.createSubscriberAnswerFromOffer(e,t);i&&this.client.sendAnswer(i,t)})),this.client.onLocalTrackPublished=e=>{var t;if(this.log.debug("received trackPublishedResponse",Object.assign(Object.assign({},this.logContext),{cid:e.cid,track:null===(t=e.track)||void 0===t?void 0:t.sid})),!this.pendingTrackResolvers[e.cid])return void this.log.error("missing track resolver for ".concat(e.cid),Object.assign(Object.assign({},this.logContext),{cid:e.cid}));const{resolve:n}=this.pendingTrackResolvers[e.cid];delete this.pendingTrackResolvers[e.cid],n(e.track)},this.client.onLocalTrackUnpublished=t=>{this.emit(e.EngineEvent.LocalTrackUnpublished,t)},this.client.onLocalTrackSubscribed=t=>{this.emit(e.EngineEvent.LocalTrackSubscribed,t)},this.client.onTokenRefresh=e=>{var t;this.token=e,null===(t=this.regionUrlProvider)||void 0===t||t.updateToken(e)},this.client.onRemoteMuteChanged=(t,n)=>{this.emit(e.EngineEvent.RemoteMute,t,n)},this.client.onSubscribedQualityUpdate=t=>{this.emit(e.EngineEvent.SubscribedQualityUpdate,t)},this.client.onRoomMoved=t=>{var n;this.participantSid=null===(n=t.participant)||void 0===n?void 0:n.sid,this.latestJoinResponse&&(this.latestJoinResponse.room=t.room),this.emit(e.EngineEvent.RoomMoved,t)},this.client.onMediaSectionsRequirement=e=>{var t,n;const i={direction:"recvonly"};for(let n=0;n{this.handleDisconnect("signal",it.RR_SIGNAL_DISCONNECTED)},this.client.onLeave=t=>{switch(this.log.debug("client leave request",Object.assign(Object.assign({},this.logContext),{reason:null==t?void 0:t.reason})),t.regions&&this.regionUrlProvider&&(this.log.debug("updating regions",this.logContext),this.regionUrlProvider.setServerReportedRegions({updatedAtInMs:Date.now(),maxAgeInMs:5e3,regionSettings:t.regions})),t.action){case Vn.DISCONNECT:this.emit(e.EngineEvent.Disconnected,null==t?void 0:t.reason),this.close();break;case Vn.RECONNECT:this.fullReconnectOnNext=!0,this.handleDisconnect(Oc);break;case Vn.RESUME:this.handleDisconnect(Oc)}}}makeRTCConfiguration(e){var t;const n=Object.assign({},this.rtcConfig);if((null===(t=this.signalOpts)||void 0===t?void 0:t.e2eeEnabled)&&(this.log.debug("E2EE - setting up transports with insertable streams",this.logContext),n.encodedInsertableStreams=!0),e.iceServers&&!n.iceServers){const t=[];e.iceServers.forEach((e=>{const n={urls:e.urls};e.username&&(n.username=e.username),e.credential&&(n.credential=e.credential),t.push(n)})),n.iceServers=t}return e.clientConfiguration&&e.clientConfiguration.forceRelay===tt.ENABLED&&(n.iceTransportPolicy="relay"),n.sdpSemantics="unified-plan",n.continualGatheringPolicy="gather_continually",n}createDataChannels(){this.pcManager&&(this.lossyDC&&(this.lossyDC.onmessage=null,this.lossyDC.onerror=null),this.reliableDC&&(this.reliableDC.onmessage=null,this.reliableDC.onerror=null),this.lossyDC=this.pcManager.createPublisherDataChannel(Pc,{ordered:!1,maxRetransmits:0}),this.reliableDC=this.pcManager.createPublisherDataChannel(Ic,{ordered:!0}),this.lossyDC.onmessage=this.handleDataMessage,this.reliableDC.onmessage=this.handleDataMessage,this.lossyDC.onerror=this.handleDataError,this.reliableDC.onerror=this.handleDataError,this.lossyDC.bufferedAmountLowThreshold=65535,this.reliableDC.bufferedAmountLowThreshold=65535,this.lossyDC.onbufferedamountlow=this.handleBufferedAmountLow,this.reliableDC.onbufferedamountlow=this.handleBufferedAmountLow,this.cleanupLossyDataStats(),this.lossyDataStatInterval=setInterval((()=>{this.lossyDataStatByterate=this.lossyDataStatCurrentBytes,this.lossyDataStatCurrentBytes=0;const e=this.dataChannelForKind(yt.LOSSY);if(e){const t=this.lossyDataStatByterate/10;e.bufferedAmountLowThreshold=Math.min(Math.max(t,8192),262144)}}),1e3))}createSender(e,t,n){return Fi(this,void 0,void 0,(function*(){if(tr()){return yield this.createTransceiverRTCRtpSender(e,t,n)}if(nr()){this.log.warn("using add-track fallback",this.logContext);return yield this.createRTCRtpSender(e.mediaStreamTrack)}throw new fs("Required webRTC APIs not supported on this device")}))}createSimulcastSender(e,t,n,i){return Fi(this,void 0,void 0,(function*(){if(tr())return this.createSimulcastTransceiverSender(e,t,n,i);if(nr())return this.log.debug("using add-track fallback",this.logContext),this.createRTCRtpSender(e.mediaStreamTrack);throw new fs("Cannot stream on this device")}))}createTransceiverRTCRtpSender(e,t,n){return Fi(this,void 0,void 0,(function*(){if(!this.pcManager)throw new fs("publisher is closed");const i=[];e.mediaStream&&i.push(e.mediaStream),Vr(e)&&(e.codec=t.videoCodec);const o={direction:"sendonly",streams:i};n&&(o.sendEncodings=n);return(yield this.pcManager.addPublisherTransceiver(e.mediaStreamTrack,o)).sender}))}createSimulcastTransceiverSender(e,t,n,i){return Fi(this,void 0,void 0,(function*(){if(!this.pcManager)throw new fs("publisher is closed");const o={direction:"sendonly"};i&&(o.sendEncodings=i);const s=yield this.pcManager.addPublisherTransceiver(t.mediaStreamTrack,o);if(n.videoCodec)return e.setSimulcastTrackSender(n.videoCodec,s.sender),s.sender}))}createRTCRtpSender(e){return Fi(this,void 0,void 0,(function*(){if(!this.pcManager)throw new fs("publisher is closed");return this.pcManager.addPublisherTrack(e)}))}attemptReconnect(t){return Fi(this,void 0,void 0,(function*(){var n,i,o;if(!this._isClosed)if(this.attemptingReconnect)Di.warn("already attempting reconnect, returning early",this.logContext);else{(null===(n=this.clientConfiguration)||void 0===n?void 0:n.resumeConnection)!==tt.DISABLED&&(null!==(o=null===(i=this.pcManager)||void 0===i?void 0:i.currentState)&&void 0!==o?o:Za.NEW)!==Za.NEW||(this.fullReconnectOnNext=!0);try{this.attemptingReconnect=!0,this.fullReconnectOnNext?yield this.restartConnection():yield this.resumeConnection(t),this.clearPendingReconnect(),this.fullReconnectOnNext=!1}catch(t){this.reconnectAttempts+=1;let n=!0;t instanceof fs?(this.log.debug("received unrecoverable error",Object.assign(Object.assign({},this.logContext),{error:t})),n=!1):t instanceof Cs||(this.fullReconnectOnNext=!0),n?this.handleDisconnect("reconnect",it.RR_UNKNOWN):(this.log.info("could not recover connection after ".concat(this.reconnectAttempts," attempts, ").concat(Date.now()-this.reconnectStart,"ms. giving up"),this.logContext),this.emit(e.EngineEvent.Disconnected),yield this.close())}finally{this.attemptingReconnect=!1}}}))}getNextRetryDelay(e){try{return this.reconnectPolicy.nextRetryDelayInMs(e)}catch(e){this.log.warn("encountered error in reconnect policy",Object.assign(Object.assign({},this.logContext),{error:e}))}return null}restartConnection(t){return Fi(this,void 0,void 0,(function*(){var n,i,o;try{if(!this.url||!this.token)throw new fs("could not reconnect, url or token not saved");let i;this.log.info("reconnecting, attempt: ".concat(this.reconnectAttempts),this.logContext),this.emit(e.EngineEvent.Restarting),this.client.isDisconnected||(yield this.client.sendLeave()),yield this.cleanupPeerConnections(),yield this.cleanupClient();try{if(!this.signalOpts)throw this.log.warn("attempted connection restart, without signal options present",this.logContext),new Cs;i=yield this.join(null!=t?t:this.url,this.token,this.signalOpts,void 0,!this.options.singlePeerConnection)}catch(t){if(t instanceof ps&&t.reason===e.ConnectionErrorReason.NotAllowed)throw new fs("could not reconnect, token might be expired");throw new Cs}if(this.shouldFailNext)throw this.shouldFailNext=!1,new Error("simulated failure");if(this.client.setReconnected(),this.emit(e.EngineEvent.SignalRestarted,i),yield this.waitForPCReconnected(),this.client.currentState!==ba.CONNECTED)throw new Cs("Signal connection got severed during reconnect");null===(n=this.regionUrlProvider)||void 0===n||n.resetAttempts(),this.emit(e.EngineEvent.Restarted)}catch(e){const t=yield null===(i=this.regionUrlProvider)||void 0===i?void 0:i.getNextBestRegionUrl();if(t)return void(yield this.restartConnection(t));throw null===(o=this.regionUrlProvider)||void 0===o||o.resetAttempts(),e}}))}resumeConnection(t){return Fi(this,void 0,void 0,(function*(){var n;if(!this.url||!this.token)throw new fs("could not reconnect, url or token not saved");if(!this.pcManager)throw new fs("publisher and subscriber connections unset");let i;this.log.info("resuming signal connection, attempt ".concat(this.reconnectAttempts),this.logContext),this.emit(e.EngineEvent.Resuming);try{this.setupSignalClientCallbacks(),i=yield this.client.reconnect(this.url,this.token,this.participantSid,t)}catch(t){let n="";if(t instanceof Error&&(n=t.message,this.log.error(t.message,Object.assign(Object.assign({},this.logContext),{error:t}))),t instanceof ps&&t.reason===e.ConnectionErrorReason.NotAllowed)throw new fs("could not reconnect, token might be expired");if(t instanceof ps&&t.reason===e.ConnectionErrorReason.LeaveRequest)throw t;throw new Cs(n)}if(this.emit(e.EngineEvent.SignalResumed),i){const e=this.makeRTCConfiguration(i);this.pcManager.updateConfiguration(e),this.latestJoinResponse&&(this.latestJoinResponse.serverInfo=i.serverInfo)}else this.log.warn("Did not receive reconnect response",this.logContext);if(this.shouldFailNext)throw this.shouldFailNext=!1,new Error("simulated failure");if(yield this.pcManager.triggerIceRestart(),yield this.waitForPCReconnected(),this.client.currentState!==ba.CONNECTED)throw new Cs("Signal connection got severed during reconnect");this.client.setReconnected(),"open"===(null===(n=this.reliableDC)||void 0===n?void 0:n.readyState)&&null===this.reliableDC.id&&this.createDataChannels(),(null==i?void 0:i.lastMessageSeq)&&this.resendReliableMessagesForResume(i.lastMessageSeq),this.emit(e.EngineEvent.Resumed)}))}waitForPCInitialConnection(e,t){return Fi(this,void 0,void 0,(function*(){if(!this.pcManager)throw new fs("PC manager is closed");yield this.pcManager.ensurePCTransportConnection(t,e)}))}waitForPCReconnected(){return Fi(this,void 0,void 0,(function*(){this.pcState=_c.Reconnecting,this.log.debug("waiting for peer connection to reconnect",this.logContext);try{if(yield er(2e3),!this.pcManager)throw new fs("PC manager is closed");yield this.pcManager.ensurePCTransportConnection(void 0,this.peerConnectionTimeout),this.pcState=_c.Connected}catch(e){throw this.pcState=_c.Disconnected,ps.internal("could not establish PC connection, ".concat(e.message))}}))}publishRpcResponse(e,t,n,i){return Fi(this,void 0,void 0,(function*(){const o=new kt({destinationIdentities:[e],kind:yt.RELIABLE,value:{case:"rpcResponse",value:new Dt({requestId:t,value:i?{case:"error",value:i.toProto()}:{case:"payload",value:null!=n?n:""}})}});yield this.sendDataPacket(o,yt.RELIABLE)}))}publishRpcAck(e,t){return Fi(this,void 0,void 0,(function*(){const n=new kt({destinationIdentities:[e],kind:yt.RELIABLE,value:{case:"rpcAck",value:new _t({requestId:t})}});yield this.sendDataPacket(n,yt.RELIABLE)}))}sendDataPacket(e,t){return Fi(this,void 0,void 0,(function*(){if(yield this.ensurePublisherConnected(t),this.e2eeManager&&this.e2eeManager.isDataChannelEncryptionEnabled){const t=da(e);if(t){const n=yield this.e2eeManager.encryptData(t.toBinary());e.value={case:"encryptedPacket",value:new bt({encryptedValue:n.payload,iv:n.iv,keyIndex:n.keyIndex})}}}t===yt.RELIABLE&&(e.sequence=this.reliableDataSequence,this.reliableDataSequence+=1);const n=e.toBinary(),i=this.dataChannelForKind(t);if(i){if(t===yt.RELIABLE)yield this.waitForBufferStatusLow(t),this.reliableMessageBuffer.push({data:n,sequence:e.sequence});else{if(!this.isBufferStatusLow(t))return this.lossyDataDropCount+=1,void(this.lossyDataDropCount%100==0&&this.log.warn("dropping lossy data channel messages, total dropped: ".concat(this.lossyDataDropCount),this.logContext));this.lossyDataStatCurrentBytes+=n.byteLength}if(this.attemptingReconnect)return;i.send(n)}this.updateAndEmitDCBufferStatus(t)}))}resendReliableMessagesForResume(e){return Fi(this,void 0,void 0,(function*(){yield this.ensurePublisherConnected(yt.RELIABLE);const t=this.dataChannelForKind(yt.RELIABLE);t&&(this.reliableMessageBuffer.popToSequence(e),this.reliableMessageBuffer.getAll().forEach((e=>{t.send(e.data)}))),this.updateAndEmitDCBufferStatus(yt.RELIABLE)}))}waitForBufferStatusLow(t){return new Xo(((n,i)=>Fi(this,void 0,void 0,(function*(){if(this.isBufferStatusLow(t))n();else{const o=()=>i(new fs("engine closed"));for(this.once(e.EngineEvent.Closing,o);!this.dcBufferStatus.get(t);)yield er(10);this.off(e.EngineEvent.Closing,o),n()}}))))}ensureDataTransportConnected(e){return Fi(this,arguments,void 0,(function(e){var t=this;let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.subscriberPrimary;return function*(){var i;if(!t.pcManager)throw new fs("PC manager is closed");const o=n?t.pcManager.subscriber:t.pcManager.publisher,s=n?"Subscriber":"Publisher";if(!o)throw ps.internal("".concat(s," connection not set"));let r=!1;n||t.dataChannelForKind(e,n)||(t.createDataChannels(),r=!0),r||n||t.pcManager.publisher.isICEConnected||"checking"===t.pcManager.publisher.getICEConnectionState()||(r=!0),r&&t.negotiate().catch((e=>{Di.error(e,t.logContext)}));const a=t.dataChannelForKind(e,n);if("open"===(null==a?void 0:a.readyState))return;const c=(new Date).getTime()+t.peerConnectionTimeout;for(;(new Date).getTime()Fi(this,void 0,void 0,(function*(){if(!this.pcManager)return void n(new ks("PC manager is closed"));this.pcManager.requirePublisher(),0!=this.pcManager.publisher.getTransceivers().length||this.lossyDC||this.reliableDC||this.createDataChannels();const i=new AbortController,o=()=>{i.abort(),this.log.debug("engine disconnected while negotiation was ongoing",this.logContext),t()};this.isClosed&&n(new ks("cannot negotiate on closed engine")),this.on(e.EngineEvent.Closing,o),this.pcManager.publisher.once(Va,(t=>{const n=new Map;t.forEach((e=>{const t=e.codec.toLowerCase();xr(t)&&n.set(e.payload,t)})),this.emit(e.EngineEvent.RTPVideoMapUpdate,n)}));try{yield this.pcManager.negotiate(i),t()}catch(e){e instanceof ks&&(this.fullReconnectOnNext=!0),this.handleDisconnect("negotiation",it.RR_UNKNOWN),e instanceof Error?n(e):n(new Error(String(e)))}finally{this.off(e.EngineEvent.Closing,o)}}))))}))}dataChannelForKind(e,t){if(t){if(e===yt.LOSSY)return this.lossyDCSub;if(e===yt.RELIABLE)return this.reliableDCSub}else{if(e===yt.LOSSY)return this.lossyDC;if(e===yt.RELIABLE)return this.reliableDC}}sendSyncState(e,t){var n,i,o,s;if(!this.pcManager)return void this.log.warn("sync state cannot be sent without peer connection setup",this.logContext);const r=this.pcManager.publisher.getLocalDescription(),a=this.pcManager.publisher.getRemoteDescription(),c=null===(n=this.pcManager.subscriber)||void 0===n?void 0:n.getRemoteDescription(),d=null===(i=this.pcManager.subscriber)||void 0===i?void 0:i.getLocalDescription(),l=null===(s=null===(o=this.signalOpts)||void 0===o?void 0:o.autoSubscribe)||void 0===s||s,u=new Array,h=new Array;e.forEach((e=>{e.isDesired!==l&&u.push(e.trackSid),e.isEnabled||h.push(e.trackSid)})),this.client.sendSyncState(new si({answer:"publisher-only"===this.pcManager.mode?a?Sa({sdp:a.sdp,type:a.type}):void 0:d?Sa({sdp:d.sdp,type:d.type}):void 0,offer:"publisher-only"===this.pcManager.mode?r?Sa({sdp:r.sdp,type:r.type}):void 0:c?Sa({sdp:c.sdp,type:c.type}):void 0,subscription:new Ln({trackSids:u,subscribe:!l,participantTracks:[]}),publishTracks:Ks(t),dataChannels:this.dataChannelsInfo(),trackSidsDisabled:h,datachannelReceiveStates:this.reliableReceivedState.map(((e,t)=>new ri({publisherSid:t,lastSeq:e})))}))}failNext(){this.shouldFailNext=!0}dataChannelsInfo(){const e=[],t=(t,n)=>{void 0!==(null==t?void 0:t.id)&&null!==t.id&&e.push(new ai({label:t.label,id:t.id,target:n}))};return t(this.dataChannelForKind(yt.LOSSY),Tn.PUBLISHER),t(this.dataChannelForKind(yt.RELIABLE),Tn.PUBLISHER),t(this.dataChannelForKind(yt.LOSSY,!0),Tn.SUBSCRIBER),t(this.dataChannelForKind(yt.RELIABLE,!0),Tn.SUBSCRIBER),e}clearReconnectTimeout(){this.reconnectTimeout&&Ss.clearTimeout(this.reconnectTimeout)}clearPendingReconnect(){this.clearReconnectTimeout(),this.reconnectAttempts=0}registerOnLineListener(){mr()&&(window.addEventListener("online",this.handleBrowserOnLine),window.addEventListener("offline",this.handleBrowserOffline))}deregisterOnLineListener(){mr()&&(window.removeEventListener("online",this.handleBrowserOnLine),window.removeEventListener("offline",this.handleBrowserOffline))}getTrackIdForReceiver(e){var t;const n=null===(t=this.pcManager)||void 0===t?void 0:t.getMidForReceiver(e);if(n){const e=Object.entries(this.midToTrackId).find((e=>{let[t]=e;return t===n}));if(e)return e[1]}}}function Mc(e,t){const n=e.participantIdentity?e.participantIdentity:t.participantIdentity;e.participantIdentity=n,t.participantIdentity=n;const i=0!==e.destinationIdentities.length?e.destinationIdentities:t.destinationIdentities;e.destinationIdentities=i,t.destinationIdentities=i}class xc{get info(){return this._info}validateBytesReceived(){let t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if("number"==typeof this.totalByteSize&&0!==this.totalByteSize){if(t&&this.bytesReceivedthis.totalByteSize)throw new Ts("Extra chunk(s) received - expected ".concat(this.totalByteSize," bytes of data total, received ").concat(this.bytesReceived," bytes"),e.DataStreamErrorReason.LengthExceeded)}}constructor(e,t,n,i){this.reader=t,this.totalByteSize=n,this._info=e,this.bytesReceived=0,this.outOfBandFailureRejectingFuture=i}}class Ac extends xc{handleChunkReceived(e){var t;this.bytesReceived+=e.content.byteLength,this.validateBytesReceived();const n=this.totalByteSize?this.bytesReceived/this.totalByteSize:void 0;null===(t=this.onProgress)||void 0===t||t.call(this,n)}[Symbol.asyncIterator](){const e=this.reader.getReader();let t=new Mr,n=null,i=null;if(this.signal){const e=this.signal;i=()=>{var n;null===(n=t.reject)||void 0===n||n.call(t,e.reason)},e.addEventListener("abort",i),n=e}const o=()=>{e.releaseLock(),n&&i&&n.removeEventListener("abort",i),this.signal=void 0};return{next:()=>Fi(this,void 0,void 0,(function*(){var n,i;try{const{done:o,value:s}=yield Promise.race([e.read(),t.promise,null!==(i=null===(n=this.outOfBandFailureRejectingFuture)||void 0===n?void 0:n.promise)&&void 0!==i?i:new Promise((()=>{}))]);return o?(this.validateBytesReceived(!0),{done:!0,value:void 0}):(this.handleChunkReceived(s),{done:!1,value:s.content})}catch(e){throw o(),e}})),return(){return Fi(this,void 0,void 0,(function*(){return o(),{done:!0,value:void 0}}))}}}withAbortSignal(e){return this.signal=e,this}readAll(){return Fi(this,arguments,void 0,(function(){var e=this;let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return function*(){var n,i,o,s;let r=new Set;const a=t.signal?e.withAbortSignal(t.signal):e;try{for(var c,d=!0,l=Vi(a);!(n=(c=yield l.next()).done);d=!0){s=c.value,d=!1;const e=s;r.add(e)}}catch(e){i={error:e}}finally{try{d||n||!(o=l.return)||(yield o.call(l))}finally{if(i)throw i.error}}return Array.from(r)}()}))}}class Nc extends xc{constructor(e,t,n,i){super(e,t,n,i),this.receivedChunks=new Map}handleChunkReceived(e){var t;const n=Ur(e.chunkIndex),i=this.receivedChunks.get(n);if(i&&i.version>e.version)return;this.receivedChunks.set(n,e),this.bytesReceived+=e.content.byteLength,this.validateBytesReceived();const o=this.totalByteSize?this.bytesReceived/this.totalByteSize:void 0;null===(t=this.onProgress)||void 0===t||t.call(this,o)}[Symbol.asyncIterator](){const t=this.reader.getReader(),n=new TextDecoder("utf-8",{fatal:!0});let i=new Mr,o=null,s=null;if(this.signal){const e=this.signal;s=()=>{var t;null===(t=i.reject)||void 0===t||t.call(i,e.reason)},e.addEventListener("abort",s),o=e}const r=()=>{t.releaseLock(),o&&s&&o.removeEventListener("abort",s),this.signal=void 0};return{next:()=>Fi(this,void 0,void 0,(function*(){var o,s;try{const{done:r,value:a}=yield Promise.race([t.read(),i.promise,null!==(s=null===(o=this.outOfBandFailureRejectingFuture)||void 0===o?void 0:o.promise)&&void 0!==s?s:new Promise((()=>{}))]);if(r)return this.validateBytesReceived(!0),{done:!0,value:void 0};{let t;this.handleChunkReceived(a);try{t=n.decode(a.content)}catch(t){throw new Ts("Cannot decode datastream chunk ".concat(a.chunkIndex," as text: ").concat(t),e.DataStreamErrorReason.DecodeFailed)}return{done:!1,value:t}}}catch(e){throw r(),e}})),return(){return Fi(this,void 0,void 0,(function*(){return r(),{done:!0,value:void 0}}))}}}withAbortSignal(e){return this.signal=e,this}readAll(){return Fi(this,arguments,void 0,(function(){var e=this;let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return function*(){var n,i,o,s;let r="";const a=t.signal?e.withAbortSignal(t.signal):e;try{for(var c,d=!0,l=Vi(a);!(n=(c=yield l.next()).done);d=!0){s=c.value,d=!1;r+=s}}catch(e){i={error:e}}finally{try{d||n||!(o=l.return)||(yield o.call(l))}finally{if(i)throw i.error}}return r}()}))}}class Lc{constructor(){this.log=Di,this.byteStreamControllers=new Map,this.textStreamControllers=new Map,this.byteStreamHandlers=new Map,this.textStreamHandlers=new Map}registerTextStreamHandler(t,n){if(this.textStreamHandlers.has(t))throw new Ts('A text stream handler for topic "'.concat(t,'" has already been set.'),e.DataStreamErrorReason.HandlerAlreadyRegistered);this.textStreamHandlers.set(t,n)}unregisterTextStreamHandler(e){this.textStreamHandlers.delete(e)}registerByteStreamHandler(t,n){if(this.byteStreamHandlers.has(t))throw new Ts('A byte stream handler for topic "'.concat(t,'" has already been set.'),e.DataStreamErrorReason.HandlerAlreadyRegistered);this.byteStreamHandlers.set(t,n)}unregisterByteStreamHandler(e){this.byteStreamHandlers.delete(e)}clearControllers(){this.byteStreamControllers.clear(),this.textStreamControllers.clear()}validateParticipantHasNoActiveDataStreams(t){var n,i,o,s;const r=Array.from(this.textStreamControllers.entries()).filter((e=>e[1].sendingParticipantIdentity===t)),a=Array.from(this.byteStreamControllers.entries()).filter((e=>e[1].sendingParticipantIdentity===t));if(r.length>0||a.length>0){const c=new Ts("Participant ".concat(t," unexpectedly disconnected in the middle of sending data"),e.DataStreamErrorReason.AbnormalEnd);for(const[e,t]of a)null===(i=(n=t.outOfBandFailureRejectingFuture).reject)||void 0===i||i.call(n,c),this.byteStreamControllers.delete(e);for(const[e,t]of r)null===(s=(o=t.outOfBandFailureRejectingFuture).reject)||void 0===s||s.call(o,c),this.textStreamControllers.delete(e)}}handleDataStreamPacket(e,t){return Fi(this,void 0,void 0,(function*(){switch(e.value.case){case"streamHeader":return this.handleStreamHeader(e.value.value,e.participantIdentity,t);case"streamChunk":return this.handleStreamChunk(e.value.value,t);case"streamTrailer":return this.handleStreamTrailer(e.value.value,t);default:throw new Error('DataPacket of value "'.concat(e.value.case,'" is not data stream related!'))}}))}handleStreamHeader(t,n,i){return Fi(this,void 0,void 0,(function*(){var o;if("byteHeader"===t.contentHeader.case){const s=this.byteStreamHandlers.get(t.topic);if(!s)return void this.log.debug("ignoring incoming byte stream due to no handler for topic",t.topic);let r;const a=new Mr;a.promise.catch((e=>{this.log.error(e)}));const c={id:t.streamId,name:null!==(o=t.contentHeader.value.name)&&void 0!==o?o:"unknown",mimeType:t.mimeType,size:t.totalLength?Number(t.totalLength):void 0,topic:t.topic,timestamp:Ur(t.timestamp),attributes:t.attributes,encryptionType:i},d=new ReadableStream({start:i=>{if(r=i,this.textStreamControllers.has(t.streamId))throw new Ts("A data stream read is already in progress for a stream with id ".concat(t.streamId,"."),e.DataStreamErrorReason.AlreadyOpened);this.byteStreamControllers.set(t.streamId,{info:c,controller:r,startTime:Date.now(),sendingParticipantIdentity:n,outOfBandFailureRejectingFuture:a})}});s(new Ac(c,d,Ur(t.totalLength),a),{identity:n})}else if("textHeader"===t.contentHeader.case){const o=this.textStreamHandlers.get(t.topic);if(!o)return void this.log.debug("ignoring incoming text stream due to no handler for topic",t.topic);let s;const r=new Mr;r.promise.catch((e=>{this.log.error(e)}));const a={id:t.streamId,mimeType:t.mimeType,size:t.totalLength?Number(t.totalLength):void 0,topic:t.topic,timestamp:Number(t.timestamp),attributes:t.attributes,encryptionType:i},c=new ReadableStream({start:i=>{if(s=i,this.textStreamControllers.has(t.streamId))throw new Ts("A data stream read is already in progress for a stream with id ".concat(t.streamId,"."),e.DataStreamErrorReason.AlreadyOpened);this.textStreamControllers.set(t.streamId,{info:a,controller:s,startTime:Date.now(),sendingParticipantIdentity:n,outOfBandFailureRejectingFuture:r})}});o(new Nc(a,c,Ur(t.totalLength),r),{identity:n})}}))}handleStreamChunk(t,n){const i=this.byteStreamControllers.get(t.streamId);i&&(i.info.encryptionType!==n?(i.controller.error(new Ts("Encryption type mismatch for stream ".concat(t.streamId,". Expected ").concat(n,", got ").concat(i.info.encryptionType),e.DataStreamErrorReason.EncryptionTypeMismatch)),this.byteStreamControllers.delete(t.streamId)):t.content.length>0&&i.controller.enqueue(t));const o=this.textStreamControllers.get(t.streamId);o&&(o.info.encryptionType!==n?(o.controller.error(new Ts("Encryption type mismatch for stream ".concat(t.streamId,". Expected ").concat(n,", got ").concat(o.info.encryptionType),e.DataStreamErrorReason.EncryptionTypeMismatch)),this.textStreamControllers.delete(t.streamId)):t.content.length>0&&o.controller.enqueue(t))}handleStreamTrailer(t,n){const i=this.textStreamControllers.get(t.streamId);i&&(i.info.encryptionType!==n?i.controller.error(new Ts("Encryption type mismatch for stream ".concat(t.streamId,". Expected ").concat(n,", got ").concat(i.info.encryptionType),e.DataStreamErrorReason.EncryptionTypeMismatch)):(i.info.attributes=Object.assign(Object.assign({},i.info.attributes),t.attributes),i.controller.close(),this.textStreamControllers.delete(t.streamId)));const o=this.byteStreamControllers.get(t.streamId);o&&(o.info.encryptionType!==n?o.controller.error(new Ts("Encryption type mismatch for stream ".concat(t.streamId,". Expected ").concat(n,", got ").concat(o.info.encryptionType),e.DataStreamErrorReason.EncryptionTypeMismatch)):(o.info.attributes=Object.assign(Object.assign({},o.info.attributes),t.attributes),o.controller.close()),this.byteStreamControllers.delete(t.streamId))}}class Uc{constructor(e,t,n){this.writableStream=e,this.defaultWriter=e.getWriter(),this.onClose=n,this.info=t}write(e){return this.defaultWriter.write(e)}close(){return Fi(this,void 0,void 0,(function*(){var e;yield this.defaultWriter.close(),this.defaultWriter.releaseLock(),null===(e=this.onClose)||void 0===e||e.call(this)}))}}class jc extends Uc{}class Fc extends Uc{}class Bc{constructor(e,t){this.engine=e,this.log=t}setupEngine(e){this.engine=e}sendText(e,t){return Fi(this,void 0,void 0,(function*(){var n;const i=crypto.randomUUID(),o=(new TextEncoder).encode(e).byteLength,s=null===(n=null==t?void 0:t.attachments)||void 0===n?void 0:n.map((()=>crypto.randomUUID())),r=new Array(s?s.length+1:1).fill(0),a=(e,n)=>{var i;r[n]=e;const o=r.reduce(((e,t)=>e+t),0);null===(i=null==t?void 0:t.onProgress)||void 0===i||i.call(t,o)},c=yield this.streamText({streamId:i,totalSize:o,destinationIdentities:null==t?void 0:t.destinationIdentities,topic:null==t?void 0:t.topic,attachedStreamIds:s,attributes:null==t?void 0:t.attributes});return yield c.write(e),a(1,0),yield c.close(),(null==t?void 0:t.attachments)&&s&&(yield Promise.all(t.attachments.map(((e,n)=>Fi(this,void 0,void 0,(function*(){return this._sendFile(s[n],e,{topic:t.topic,mimeType:e.type,onProgress:e=>{a(e,n+1)}})})))))),c.info}))}streamText(t){return Fi(this,void 0,void 0,(function*(){var n,i,o;const s=null!==(n=null==t?void 0:t.streamId)&&void 0!==n?n:crypto.randomUUID(),r={id:s,mimeType:"text/plain",timestamp:Date.now(),topic:null!==(i=null==t?void 0:t.topic)&&void 0!==i?i:"",size:null==t?void 0:t.totalSize,attributes:null==t?void 0:t.attributes,encryptionType:(null===(o=this.engine.e2eeManager)||void 0===o?void 0:o.isDataChannelEncryptionEnabled)?pt.GCM:pt.NONE},a=new Ht({streamId:s,mimeType:r.mimeType,topic:r.topic,timestamp:jr(r.timestamp),totalLength:jr(null==t?void 0:t.totalSize),attributes:r.attributes,contentHeader:{case:"textHeader",value:new Wt({version:null==t?void 0:t.version,attachedStreamIds:null==t?void 0:t.attachedStreamIds,replyToStreamId:null==t?void 0:t.replyToStreamId,operationType:"update"===(null==t?void 0:t.type)?qt.UPDATE:qt.CREATE})}}),c=null==t?void 0:t.destinationIdentities,d=new kt({destinationIdentities:c,value:{case:"streamHeader",value:a}});yield this.engine.sendDataPacket(d,yt.RELIABLE);let l=0;const u=this.engine,h=new WritableStream({write(e){return Fi(this,void 0,void 0,(function*(){for(const t of function(e,t){const n=[];let i=(new TextEncoder).encode(e);for(;i.length>t;){let e=t;for(;e>0;){const t=i[e];if(void 0!==t&&128!=(192&t))break;e--}n.push(i.slice(0,e)),i=i.slice(e)}return i.length>0&&n.push(i),n}(e,15e3)){const e=new Gt({content:t,streamId:s,chunkIndex:jr(l)}),n=new kt({destinationIdentities:c,value:{case:"streamChunk",value:e}});yield u.sendDataPacket(n,yt.RELIABLE),l+=1}}))},close(){return Fi(this,void 0,void 0,(function*(){const e=new Jt({streamId:s}),t=new kt({destinationIdentities:c,value:{case:"streamTrailer",value:e}});yield u.sendDataPacket(t,yt.RELIABLE)}))},abort(e){console.log("Sink error:",e)}});let p=()=>Fi(this,void 0,void 0,(function*(){yield m.close()}));u.once(e.EngineEvent.Closing,p);const m=new jc(h,r,(()=>this.engine.off(e.EngineEvent.Closing,p)));return m}))}sendFile(e,t){return Fi(this,void 0,void 0,(function*(){const n=crypto.randomUUID();return yield this._sendFile(n,e,t),{id:n}}))}_sendFile(e,t,n){return Fi(this,void 0,void 0,(function*(){var i;const o=yield this.streamBytes({streamId:e,totalSize:t.size,name:t.name,mimeType:null!==(i=null==n?void 0:n.mimeType)&&void 0!==i?i:t.type,topic:null==n?void 0:n.topic,destinationIdentities:null==n?void 0:n.destinationIdentities}),s=t.stream().getReader();for(;;){const{done:e,value:t}=yield s.read();if(e)break;yield o.write(t)}return yield o.close(),o.info}))}streamBytes(e){return Fi(this,void 0,void 0,(function*(){var t,n,i,s,r,a;const c=null!==(t=null==e?void 0:e.streamId)&&void 0!==t?t:crypto.randomUUID(),d=null==e?void 0:e.destinationIdentities,l={id:c,mimeType:null!==(n=null==e?void 0:e.mimeType)&&void 0!==n?n:"application/octet-stream",topic:null!==(i=null==e?void 0:e.topic)&&void 0!==i?i:"",timestamp:Date.now(),attributes:null==e?void 0:e.attributes,size:null==e?void 0:e.totalSize,name:null!==(s=null==e?void 0:e.name)&&void 0!==s?s:"unknown",encryptionType:(null===(r=this.engine.e2eeManager)||void 0===r?void 0:r.isDataChannelEncryptionEnabled)?pt.GCM:pt.NONE},u=new Ht({totalLength:jr(null!==(a=l.size)&&void 0!==a?a:0),mimeType:l.mimeType,streamId:c,topic:l.topic,timestamp:jr(Date.now()),attributes:l.attributes,contentHeader:{case:"byteHeader",value:new Kt({name:l.name})}}),h=new kt({destinationIdentities:d,value:{case:"streamHeader",value:u}});yield this.engine.sendDataPacket(h,yt.RELIABLE);let p=0;const m=new o,g=this.engine,v=this.log,f=new WritableStream({write(e){return Fi(this,void 0,void 0,(function*(){const t=yield m.lock();let n=0;try{for(;n{i.track===this._mediaStreamTrack&&(t.removeEventListener("removetrack",n),this.receiver&&"playoutDelayHint"in this.receiver&&(this.receiver.playoutDelayHint=void 0),this.receiver=void 0,this._currentBitrate=0,this.emit(e.TrackEvent.Ended,this))};t.addEventListener("removetrack",n)}start(){this.startMonitor(),super.enable()}stop(){this.stopMonitor(),super.disable()}getRTCStatsReport(){return Fi(this,void 0,void 0,(function*(){var e;if(!(null===(e=this.receiver)||void 0===e?void 0:e.getStats))return;return yield this.receiver.getStats()}))}setPlayoutDelay(e){this.receiver?"playoutDelayHint"in this.receiver?this.receiver.playoutDelayHint=e:this.log.warn("Playout delay not supported in this browser"):this.log.warn("Cannot set playout delay, track already ended")}getPlayoutDelay(){if(this.receiver){if("playoutDelayHint"in this.receiver)return this.receiver.playoutDelayHint;this.log.warn("Playout delay not supported in this browser")}else this.log.warn("Cannot get playout delay, track already ended");return 0}startMonitor(){this.monitorInterval||(this.monitorInterval=setInterval((()=>this.monitorReceiver()),oc)),"undefined"!=typeof RTCRtpReceiver&&"getSynchronizationSources"in RTCRtpReceiver&&this.registerTimeSyncUpdate()}registerTimeSyncUpdate(){const t=()=>{var n;this.timeSyncHandle=requestAnimationFrame((()=>t()));const i=null===(n=this.receiver)||void 0===n?void 0:n.getSynchronizationSources()[0];if(i){const{timestamp:t,rtpTimestamp:n}=i;n&&this.rtpTimestamp!==n&&(this.emit(e.TrackEvent.TimeSyncUpdate,{timestamp:t,rtpTimestamp:n}),this.rtpTimestamp=n)}};t()}}class qc extends Vc{constructor(e,t,n,i,o,s){super(e,t,Ys.Kind.Audio,n,s),this.monitorReceiver=()=>Fi(this,void 0,void 0,(function*(){if(!this.receiver)return void(this._currentBitrate=0);const e=yield this.getReceiverStats();e&&this.prevStats&&this.receiver&&(this._currentBitrate=sc(e,this.prevStats)),this.prevStats=e})),this.audioContext=i,this.webAudioPluginNodes=[],o&&(this.sinkId=o.deviceId)}setVolume(e){var t;for(const n of this.attachedElements)this.audioContext?null===(t=this.gainNode)||void 0===t||t.gain.setTargetAtTime(e,0,.1):n.volume=e;gr()&&this._mediaStreamTrack._setVolume(e),this.elementVolume=e}getVolume(){if(this.elementVolume)return this.elementVolume;if(gr())return 1;let e=0;return this.attachedElements.forEach((t=>{t.volume>e&&(e=t.volume)})),e}setSinkId(e){return Fi(this,void 0,void 0,(function*(){this.sinkId=e,yield Promise.all(this.attachedElements.map((t=>{if(rr(t))return t.setSinkId(e)})))}))}attach(e){const t=0===this.attachedElements.length;return e?super.attach(e):e=super.attach(),this.sinkId&&rr(e)&&e.setSinkId(this.sinkId).catch((e=>{this.log.error("Failed to set sink id on remote audio track",e,this.logContext)})),this.audioContext&&t&&(this.log.debug("using audio context mapping",this.logContext),this.connectWebAudio(this.audioContext,e),e.volume=0,e.muted=!0),this.elementVolume&&this.setVolume(this.elementVolume),e}detach(e){let t;return e?(t=super.detach(e),this.audioContext&&(this.attachedElements.length>0?this.connectWebAudio(this.audioContext,this.attachedElements[0]):this.disconnectWebAudio())):(t=super.detach(),this.disconnectWebAudio()),t}setAudioContext(e){this.audioContext=e,e&&this.attachedElements.length>0?this.connectWebAudio(e,this.attachedElements[0]):e||this.disconnectWebAudio()}setWebAudioPlugins(e){this.webAudioPluginNodes=e,this.attachedElements.length>0&&this.audioContext&&this.connectWebAudio(this.audioContext,this.attachedElements[0])}connectWebAudio(t,n){this.disconnectWebAudio(),this.sourceNode=t.createMediaStreamSource(n.srcObject);let i=this.sourceNode;this.webAudioPluginNodes.forEach((e=>{i.connect(e),i=e})),this.gainNode=t.createGain(),i.connect(this.gainNode),this.gainNode.connect(t.destination),this.elementVolume&&this.gainNode.gain.setTargetAtTime(this.elementVolume,0,.1),"running"!==t.state&&t.resume().then((()=>{"running"!==t.state&&this.emit(e.TrackEvent.AudioPlaybackFailed,new Error("Audio Context couldn't be started automatically"))})).catch((t=>{this.emit(e.TrackEvent.AudioPlaybackFailed,t)}))}disconnectWebAudio(){var e,t;null===(e=this.gainNode)||void 0===e||e.disconnect(),null===(t=this.sourceNode)||void 0===t||t.disconnect(),this.gainNode=void 0,this.sourceNode=void 0}getReceiverStats(){return Fi(this,void 0,void 0,(function*(){if(!this.receiver||!this.receiver.getStats)return;let e;return(yield this.receiver.getStats()).forEach((t=>{"inbound-rtp"===t.type&&(e={type:"audio",streamId:t.id,timestamp:t.timestamp,jitter:t.jitter,bytesReceived:t.bytesReceived,concealedSamples:t.concealedSamples,concealmentEvents:t.concealmentEvents,silentConcealedSamples:t.silentConcealedSamples,silentConcealmentEvents:t.silentConcealmentEvents,totalAudioEnergy:t.totalAudioEnergy,totalSamplesDuration:t.totalSamplesDuration})})),e}))}}class Wc extends Vc{constructor(e,t,n,i,o){super(e,t,Ys.Kind.Video,n,o),this.elementInfos=[],this.monitorReceiver=()=>Fi(this,void 0,void 0,(function*(){if(!this.receiver)return void(this._currentBitrate=0);const e=yield this.getReceiverStats();e&&this.prevStats&&this.receiver&&(this._currentBitrate=sc(e,this.prevStats)),this.prevStats=e})),this.debouncedHandleResize=ja((()=>{this.updateDimensions()}),100),this.adaptiveStreamSettings=i}get isAdaptiveStream(){return void 0!==this.adaptiveStreamSettings}setStreamState(e){super.setStreamState(e),this.log.debug("setStreamState",e),this.isAdaptiveStream&&e===Ys.StreamState.Active&&this.updateVisibility()}get mediaStreamTrack(){return this._mediaStreamTrack}setMuted(e){super.setMuted(e),this.attachedElements.forEach((t=>{e?Zs(this._mediaStreamTrack,t):Xs(this._mediaStreamTrack,t)}))}attach(e){if(e?super.attach(e):e=super.attach(),this.adaptiveStreamSettings&&void 0===this.elementInfos.find((t=>t.element===e))){const t=new Kc(e);this.observeElementInfo(t)}return e}observeElementInfo(e){this.adaptiveStreamSettings&&void 0===this.elementInfos.find((t=>t===e))?(e.handleResize=()=>{this.debouncedHandleResize()},e.handleVisibilityChanged=()=>{this.updateVisibility()},this.elementInfos.push(e),e.observe(),this.debouncedHandleResize(),this.updateVisibility()):this.log.warn("visibility resize observer not triggered",this.logContext)}stopObservingElementInfo(e){if(!this.isAdaptiveStream)return void this.log.warn("stopObservingElementInfo ignored",this.logContext);const t=this.elementInfos.filter((t=>t===e));for(const e of t)e.stopObserving();this.elementInfos=this.elementInfos.filter((t=>t!==e)),this.updateVisibility(),this.debouncedHandleResize()}detach(e){let t=[];if(e)return this.stopObservingElement(e),super.detach(e);t=super.detach();for(const e of t)this.stopObservingElement(e);return t}getDecoderImplementation(){var e;return null===(e=this.prevStats)||void 0===e?void 0:e.decoderImplementation}getReceiverStats(){return Fi(this,void 0,void 0,(function*(){if(!this.receiver||!this.receiver.getStats)return;const e=yield this.receiver.getStats();let t,n="",i=new Map;return e.forEach((e=>{"inbound-rtp"===e.type?(n=e.codecId,t={type:"video",streamId:e.id,framesDecoded:e.framesDecoded,framesDropped:e.framesDropped,framesReceived:e.framesReceived,packetsReceived:e.packetsReceived,packetsLost:e.packetsLost,frameWidth:e.frameWidth,frameHeight:e.frameHeight,pliCount:e.pliCount,firCount:e.firCount,nackCount:e.nackCount,jitter:e.jitter,timestamp:e.timestamp,bytesReceived:e.bytesReceived,decoderImplementation:e.decoderImplementation}):"codec"===e.type&&i.set(e.id,e)})),t&&""!==n&&i.get(n)&&(t.mimeType=i.get(n).mimeType),t}))}stopObservingElement(e){const t=this.elementInfos.filter((t=>t.element===e));for(const e of t)this.stopObservingElementInfo(e)}handleAppVisibilityChanged(){const e=Object.create(null,{handleAppVisibilityChanged:{get:()=>super.handleAppVisibilityChanged}});return Fi(this,void 0,void 0,(function*(){yield e.handleAppVisibilityChanged.call(this),this.isAdaptiveStream&&this.updateVisibility()}))}updateVisibility(t){var n,i;const o=this.elementInfos.reduce(((e,t)=>Math.max(e,t.visibilityChangedAt||0)),0),s=!(null!==(i=null===(n=this.adaptiveStreamSettings)||void 0===n?void 0:n.pauseVideoInBackground)&&void 0!==i&&!i)&&this.isInBackground,r=this.elementInfos.some((e=>e.pictureInPicture)),a=this.elementInfos.some((e=>e.visible))&&!s||r;(this.lastVisible!==a||t)&&(!a&&Date.now()-o<100?Ss.setTimeout((()=>{this.updateVisibility()}),100):(this.lastVisible=a,this.emit(e.TrackEvent.VisibilityChanged,a,this)))}updateDimensions(){var t,n;let i=0,o=0;const s=this.getPixelDensity();for(const e of this.elementInfos){const t=e.width()*s,n=e.height()*s;t+n>i+o&&(i=t,o=n)}(null===(t=this.lastDimensions)||void 0===t?void 0:t.width)===i&&(null===(n=this.lastDimensions)||void 0===n?void 0:n.height)===o||(this.lastDimensions={width:i,height:o},this.emit(e.TrackEvent.VideoDimensionsChanged,this.lastDimensions,this))}getPixelDensity(){var e;const t=null===(e=this.adaptiveStreamSettings)||void 0===e?void 0:e.pixelDensity;if("screen"===t)return br();if(!t){return br()>2?2:1}return t}}class Kc{get visible(){return this.isPiP||this.isIntersecting}get pictureInPicture(){return this.isPiP}constructor(e,t){this.onVisibilityChanged=e=>{var t;const{target:n,isIntersecting:i}=e;n===this.element&&(this.isIntersecting=i,this.isPiP=Hc(this.element),this.visibilityChangedAt=Date.now(),null===(t=this.handleVisibilityChanged)||void 0===t||t.call(this))},this.onEnterPiP=()=>{var e,t,n;null===(t=null===(e=window.documentPictureInPicture)||void 0===e?void 0:e.window)||void 0===t||t.addEventListener("pagehide",this.onLeavePiP),this.isPiP=Hc(this.element),null===(n=this.handleVisibilityChanged)||void 0===n||n.call(this)},this.onLeavePiP=()=>{var e;this.isPiP=Hc(this.element),null===(e=this.handleVisibilityChanged)||void 0===e||e.call(this)},this.element=e,this.isIntersecting=null!=t?t:Gc(e),this.isPiP=mr()&&Hc(e),this.visibilityChangedAt=0}width(){return this.element.clientWidth}height(){return this.element.clientHeight}observe(){var e,t,n;this.isIntersecting=Gc(this.element),this.isPiP=Hc(this.element),this.element.handleResize=()=>{var e;null===(e=this.handleResize)||void 0===e||e.call(this)},this.element.handleVisibilityChanged=this.onVisibilityChanged,Pr().observe(this.element),wr().observe(this.element),this.element.addEventListener("enterpictureinpicture",this.onEnterPiP),this.element.addEventListener("leavepictureinpicture",this.onLeavePiP),null===(e=window.documentPictureInPicture)||void 0===e||e.addEventListener("enter",this.onEnterPiP),null===(n=null===(t=window.documentPictureInPicture)||void 0===t?void 0:t.window)||void 0===n||n.addEventListener("pagehide",this.onLeavePiP)}stopObserving(){var e,t,n,i,o;null===(e=Pr())||void 0===e||e.unobserve(this.element),null===(t=wr())||void 0===t||t.unobserve(this.element),this.element.removeEventListener("enterpictureinpicture",this.onEnterPiP),this.element.removeEventListener("leavepictureinpicture",this.onLeavePiP),null===(n=window.documentPictureInPicture)||void 0===n||n.removeEventListener("enter",this.onEnterPiP),null===(o=null===(i=window.documentPictureInPicture)||void 0===i?void 0:i.window)||void 0===o||o.removeEventListener("pagehide",this.onLeavePiP)}}function Hc(e){var t,n;return document.pictureInPictureElement===e||!!(null===(t=window.documentPictureInPicture)||void 0===t?void 0:t.window)&&Gc(e,null===(n=window.documentPictureInPicture)||void 0===n?void 0:n.window)}function Gc(e,t){const n=t||window;let i=e.offsetTop,o=e.offsetLeft;const s=e.offsetWidth,r=e.offsetHeight,{hidden:a}=e,{display:c}=getComputedStyle(e);for(;e.offsetParent;)i+=(e=e.offsetParent).offsetTop,o+=e.offsetLeft;return in.pageYOffset&&o+s>n.pageXOffset&&!a&&"none"!==c}class Jc extends Ki.EventEmitter{constructor(t,n,i,o){var s;super(),this.metadataMuted=!1,this.encryption=pt.NONE,this.log=Di,this.handleMuted=()=>{this.emit(e.TrackEvent.Muted)},this.handleUnmuted=()=>{this.emit(e.TrackEvent.Unmuted)},this.log=xi(null!==(s=null==o?void 0:o.loggerName)&&void 0!==s?s:e.LoggerNames.Publication),this.loggerContextCb=this.loggerContextCb,this.setMaxListeners(100),this.kind=t,this.trackSid=n,this.trackName=i,this.source=Ys.Source.Unknown}setTrack(t){this.track&&(this.track.off(e.TrackEvent.Muted,this.handleMuted),this.track.off(e.TrackEvent.Unmuted,this.handleUnmuted)),this.track=t,t&&(t.on(e.TrackEvent.Muted,this.handleMuted),t.on(e.TrackEvent.Unmuted,this.handleUnmuted))}get logContext(){var e;return Object.assign(Object.assign({},null===(e=this.loggerContextCb)||void 0===e?void 0:e.call(this)),Hs(this))}get isMuted(){return this.metadataMuted}get isEnabled(){return!0}get isSubscribed(){return void 0!==this.track}get isEncrypted(){return this.encryption!==pt.NONE}get audioTrack(){if(Br(this.track))return this.track}get videoTrack(){if(Vr(this.track))return this.track}updateInfo(e){this.trackSid=e.sid,this.trackName=e.name,this.source=Ys.sourceFromProto(e.source),this.mimeType=e.mimeType,this.kind===Ys.Kind.Video&&e.width>0&&(this.dimensions={width:e.width,height:e.height},this.simulcasted=e.simulcast),this.encryption=e.encryption,this.trackInfo=e,this.log.debug("update publication info",Object.assign(Object.assign({},this.logContext),{info:e}))}}!function(e){var t,n;(t=e.SubscriptionStatus||(e.SubscriptionStatus={})).Desired="desired",t.Subscribed="subscribed",t.Unsubscribed="unsubscribed",(n=e.PermissionStatus||(e.PermissionStatus={})).Allowed="allowed",n.NotAllowed="not_allowed"}(Jc||(Jc={}));class zc extends Jc{get isUpstreamPaused(){var e;return null===(e=this.track)||void 0===e?void 0:e.isUpstreamPaused}constructor(t,n,i,o){super(t,n.sid,n.name,o),this.track=void 0,this.handleTrackEnded=()=>{this.emit(e.TrackEvent.Ended)},this.handleCpuConstrained=()=>{this.track&&Vr(this.track)&&this.emit(e.TrackEvent.CpuConstrained,this.track)},this.updateInfo(n),this.setTrack(i)}setTrack(t){this.track&&(this.track.off(e.TrackEvent.Ended,this.handleTrackEnded),this.track.off(e.TrackEvent.CpuConstrained,this.handleCpuConstrained)),super.setTrack(t),t&&(t.on(e.TrackEvent.Ended,this.handleTrackEnded),t.on(e.TrackEvent.CpuConstrained,this.handleCpuConstrained))}get isMuted(){return this.track?this.track.isMuted:super.isMuted}get audioTrack(){return super.audioTrack}get videoTrack(){return super.videoTrack}get isLocal(){return!0}mute(){return Fi(this,void 0,void 0,(function*(){var e;return null===(e=this.track)||void 0===e?void 0:e.mute()}))}unmute(){return Fi(this,void 0,void 0,(function*(){var e;return null===(e=this.track)||void 0===e?void 0:e.unmute()}))}pauseUpstream(){return Fi(this,void 0,void 0,(function*(){var e;yield null===(e=this.track)||void 0===e?void 0:e.pauseUpstream()}))}resumeUpstream(){return Fi(this,void 0,void 0,(function*(){var e;yield null===(e=this.track)||void 0===e?void 0:e.resumeUpstream()}))}getTrackFeatures(){var e;if(Br(this.track)){const t=this.track.getSourceTrackSettings(),n=new Set;return t.autoGainControl&&n.add(st.TF_AUTO_GAIN_CONTROL),t.echoCancellation&&n.add(st.TF_ECHO_CANCELLATION),t.noiseSuppression&&n.add(st.TF_NOISE_SUPPRESSION),t.channelCount&&t.channelCount>1&&n.add(st.TF_STEREO),(null===(e=this.options)||void 0===e?void 0:e.dtx)||n.add(st.TF_NO_DTX),this.track.enhancedNoiseCancellation&&n.add(st.TF_ENHANCED_NOISE_CANCELLATION),Array.from(n.values())}return[]}}function Qc(e,t){return Fi(this,void 0,void 0,(function*(){null!=e||(e={});let n=!1;const{audioProcessor:i,videoProcessor:o,optionsWithoutProcessor:s}=Gs(e);let r=s.audio,a=s.video;if(i&&"object"==typeof s.audio&&(s.audio.processor=i),o&&"object"==typeof s.video&&(s.video.processor=o),e.audio&&"object"==typeof s.audio&&"string"==typeof s.audio.deviceId){const e=s.audio.deviceId;s.audio.deviceId={exact:e},n=!0,r=Object.assign(Object.assign({},s.audio),{deviceId:{ideal:e}})}if(s.video&&"object"==typeof s.video&&"string"==typeof s.video.deviceId){const e=s.video.deviceId;s.video.deviceId={exact:e},n=!0,a=Object.assign(Object.assign({},s.video),{deviceId:{ideal:e}})}!0===s.audio?s.audio={deviceId:"default"}:"object"==typeof s.audio&&null!==s.audio&&(s.audio=Object.assign(Object.assign({},s.audio),{deviceId:s.audio.deviceId||"default"})),!0===s.video?s.video={deviceId:"default"}:"object"!=typeof s.video||s.video.deviceId||(s.video.deviceId="default");const c=Ns(s,za,Qa),d=Us(c),l=navigator.mediaDevices.getUserMedia(d);s.audio&&(ga.userMediaPromiseMap.set("audioinput",l),l.catch((()=>ga.userMediaPromiseMap.delete("audioinput")))),s.video&&(ga.userMediaPromiseMap.set("videoinput",l),l.catch((()=>ga.userMediaPromiseMap.delete("videoinput"))));try{const e=yield l;return yield Promise.all(e.getTracks().map((n=>Fi(this,void 0,void 0,(function*(){const s="audio"===n.kind;let r,a=s?c.audio:c.video;"boolean"!=typeof a&&a||(a={});const l=s?d.audio:d.video;"boolean"!=typeof l&&(r=l);const u=n.getSettings().deviceId;(null==r?void 0:r.deviceId)&&Ar(r.deviceId)!==u?r.deviceId=u:r||(r={deviceId:u});const h=function(e,t,n){switch(e.kind){case"audio":return new lc(e,t,!1,void 0,n);case"video":return new Sc(e,t,!1,n);default:throw new gs("unsupported track type: ".concat(e.kind))}}(n,r,t);return h.kind===Ys.Kind.Video?h.source=Ys.Source.Camera:h.kind===Ys.Kind.Audio&&(h.source=Ys.Source.Microphone),h.mediaStream=e,Br(h)&&i?yield h.setProcessor(i):Vr(h)&&o&&(yield h.setProcessor(o)),h})))))}catch(i){if(!n)throw i;return Qc(Object.assign(Object.assign({},e),{audio:r,video:a}),t)}}))}function Yc(e){return Fi(this,void 0,void 0,(function*(){return(yield Qc({audio:!1,video:null==e||e}))[0]}))}function Xc(e){return Fi(this,void 0,void 0,(function*(){return(yield Qc({audio:null==e||e,video:!1}))[0]}))}var Zc,$c;e.ConnectionQuality=void 0,(Zc=e.ConnectionQuality||(e.ConnectionQuality={})).Excellent="excellent",Zc.Good="good",Zc.Poor="poor",Zc.Lost="lost",Zc.Unknown="unknown";class ed extends Ki.EventEmitter{get logContext(){var e,t;return Object.assign({},null===(t=null===(e=this.loggerOptions)||void 0===e?void 0:e.loggerContextCb)||void 0===t?void 0:t.call(e))}get isEncrypted(){return this.trackPublications.size>0&&Array.from(this.trackPublications.values()).every((e=>e.isEncrypted))}get isAgent(){var e;return(null===(e=this.permissions)||void 0===e?void 0:e.agent)||this.kind===ut.AGENT}get isActive(){var e;return(null===(e=this.participantInfo)||void 0===e?void 0:e.state)===lt.ACTIVE}get kind(){return this._kind}get attributes(){return Object.freeze(Object.assign({},this._attributes))}constructor(t,n,i,o,s,r){let a=arguments.length>6&&void 0!==arguments[6]?arguments[6]:ut.STANDARD;var c;super(),this.audioLevel=0,this.isSpeaking=!1,this._connectionQuality=e.ConnectionQuality.Unknown,this.log=Di,this.log=xi(null!==(c=null==r?void 0:r.loggerName)&&void 0!==c?c:e.LoggerNames.Participant),this.loggerOptions=r,this.setMaxListeners(100),this.sid=t,this.identity=n,this.name=i,this.metadata=o,this.audioTrackPublications=new Map,this.videoTrackPublications=new Map,this.trackPublications=new Map,this._kind=a,this._attributes=null!=s?s:{}}getTrackPublications(){return Array.from(this.trackPublications.values())}getTrackPublication(e){for(const[,t]of this.trackPublications)if(t.source===e)return t}getTrackPublicationByName(e){for(const[,t]of this.trackPublications)if(t.trackName===e)return t}waitUntilActive(){return this.isActive?Promise.resolve():(this.activeFuture||(this.activeFuture=new Mr,this.once(e.ParticipantEvent.Active,(()=>{var e,t;null===(t=null===(e=this.activeFuture)||void 0===e?void 0:e.resolve)||void 0===t||t.call(e),this.activeFuture=void 0}))),this.activeFuture.promise)}get connectionQuality(){return this._connectionQuality}get isCameraEnabled(){var e;const t=this.getTrackPublication(Ys.Source.Camera);return!(null===(e=null==t?void 0:t.isMuted)||void 0===e||e)}get isMicrophoneEnabled(){var e;const t=this.getTrackPublication(Ys.Source.Microphone);return!(null===(e=null==t?void 0:t.isMuted)||void 0===e||e)}get isScreenShareEnabled(){return!!this.getTrackPublication(Ys.Source.ScreenShare)}get isLocal(){return!1}get joinedAt(){return this.participantInfo?new Date(1e3*Number.parseInt(this.participantInfo.joinedAt.toString())):new Date}updateInfo(t){var n;return!(this.participantInfo&&this.participantInfo.sid===t.sid&&this.participantInfo.version>t.version)&&(this.identity=t.identity,this.sid=t.sid,this._setName(t.name),this._setMetadata(t.metadata),this._setAttributes(t.attributes),t.state===lt.ACTIVE&&(null===(n=this.participantInfo)||void 0===n?void 0:n.state)!==lt.ACTIVE&&this.emit(e.ParticipantEvent.Active),t.permission&&this.setPermissions(t.permission),this.participantInfo=t,!0)}_setMetadata(t){const n=this.metadata!==t,i=this.metadata;this.metadata=t,n&&this.emit(e.ParticipantEvent.ParticipantMetadataChanged,i)}_setName(t){const n=this.name!==t;this.name=t,n&&this.emit(e.ParticipantEvent.ParticipantNameChanged,t)}_setAttributes(t){const n=function(e,t){var n;void 0===e&&(e={}),void 0===t&&(t={});const i=[...Object.keys(t),...Object.keys(e)],o={};for(const s of i)e[s]!==t[s]&&(o[s]=null!==(n=t[s])&&void 0!==n?n:"");return o}(this.attributes,t);this._attributes=t,Object.keys(n).length>0&&this.emit(e.ParticipantEvent.AttributesChanged,n)}setPermissions(t){var n,i,o,s,r,a;const c=this.permissions,d=t.canPublish!==(null===(n=this.permissions)||void 0===n?void 0:n.canPublish)||t.canSubscribe!==(null===(i=this.permissions)||void 0===i?void 0:i.canSubscribe)||t.canPublishData!==(null===(o=this.permissions)||void 0===o?void 0:o.canPublishData)||t.hidden!==(null===(s=this.permissions)||void 0===s?void 0:s.hidden)||t.recorder!==(null===(r=this.permissions)||void 0===r?void 0:r.recorder)||t.canPublishSources.length!==this.permissions.canPublishSources.length||t.canPublishSources.some(((e,t)=>{var n;return e!==(null===(n=this.permissions)||void 0===n?void 0:n.canPublishSources[t])}))||t.canSubscribeMetrics!==(null===(a=this.permissions)||void 0===a?void 0:a.canSubscribeMetrics);return this.permissions=t,d&&this.emit(e.ParticipantEvent.ParticipantPermissionsChanged,c),d}setIsSpeaking(t){t!==this.isSpeaking&&(this.isSpeaking=t,t&&(this.lastSpokeAt=new Date),this.emit(e.ParticipantEvent.IsSpeakingChanged,t))}setConnectionQuality(t){const n=this._connectionQuality;this._connectionQuality=function(t){switch(t){case et.EXCELLENT:return e.ConnectionQuality.Excellent;case et.GOOD:return e.ConnectionQuality.Good;case et.POOR:return e.ConnectionQuality.Poor;case et.LOST:return e.ConnectionQuality.Lost;default:return e.ConnectionQuality.Unknown}}(t),n!==this._connectionQuality&&this.emit(e.ParticipantEvent.ConnectionQualityChanged,this._connectionQuality)}setDisconnected(){var e,t;this.activeFuture&&(null===(t=(e=this.activeFuture).reject)||void 0===t||t.call(e,new Error("Participant disconnected")),this.activeFuture=void 0)}setAudioContext(e){this.audioContext=e,this.audioTrackPublications.forEach((t=>Br(t.track)&&t.track.setAudioContext(e)))}addTrackPublication(t){t.on(e.TrackEvent.Muted,(()=>{this.emit(e.ParticipantEvent.TrackMuted,t)})),t.on(e.TrackEvent.Unmuted,(()=>{this.emit(e.ParticipantEvent.TrackUnmuted,t)}));const n=t;switch(n.track&&(n.track.sid=t.trackSid),this.trackPublications.set(t.trackSid,t),t.kind){case Ys.Kind.Audio:this.audioTrackPublications.set(t.trackSid,t);break;case Ys.Kind.Video:this.videoTrackPublications.set(t.trackSid,t)}}}class td extends ed{constructor(t,n,i,o,s,r){super(t,n,void 0,void 0,void 0,{loggerName:o.loggerName,loggerContextCb:()=>this.engine.logContext}),this.pendingPublishing=new Set,this.pendingPublishPromises=new Map,this.participantTrackPermissions=[],this.allParticipantsAllowedToSubscribe=!0,this.encryptionType=pt.NONE,this.enabledPublishVideoCodecs=[],this.pendingAcks=new Map,this.pendingResponses=new Map,this.handleReconnecting=()=>{this.reconnectFuture||(this.reconnectFuture=new Mr)},this.handleReconnected=()=>{var e,t;null===(t=null===(e=this.reconnectFuture)||void 0===e?void 0:e.resolve)||void 0===t||t.call(e),this.reconnectFuture=void 0,this.updateTrackSubscriptionPermissions()},this.handleClosing=()=>{var e,t,n,i,o,s;this.reconnectFuture&&(this.reconnectFuture.promise.catch((e=>this.log.warn(e.message,this.logContext))),null===(t=null===(e=this.reconnectFuture)||void 0===e?void 0:e.reject)||void 0===t||t.call(e,new Error("Got disconnected during reconnection attempt")),this.reconnectFuture=void 0),this.signalConnectedFuture&&(null===(i=(n=this.signalConnectedFuture).reject)||void 0===i||i.call(n,new Error("Got disconnected without signal connected")),this.signalConnectedFuture=void 0),null===(s=null===(o=this.activeAgentFuture)||void 0===o?void 0:o.reject)||void 0===s||s.call(o,new Error("Got disconnected without active agent present")),this.activeAgentFuture=void 0,this.firstActiveAgent=void 0},this.handleSignalConnected=e=>{var t,n;e.participant&&this.updateInfo(e.participant),this.signalConnectedFuture||(this.signalConnectedFuture=new Mr),null===(n=(t=this.signalConnectedFuture).resolve)||void 0===n||n.call(t)},this.handleSignalRequestResponse=e=>{const{requestId:t,reason:n,message:i}=e,o=this.pendingSignalRequests.get(t);o&&(n!==gi.OK&&o.reject(new bs(i,n)),this.pendingSignalRequests.delete(t))},this.handleDataPacket=e=>{switch(e.value.case){case"rpcResponse":let t=e.value.value,n=null,i=null;"payload"===t.value.case?n=t.value.value:"error"===t.value.case&&(i=tc.fromProto(t.value.value)),this.handleIncomingRpcResponse(t.requestId,n,i);break;case"rpcAck":let o=e.value.value;this.handleIncomingRpcAck(o.requestId)}},this.updateTrackSubscriptionPermissions=()=>{this.log.debug("updating track subscription permissions",Object.assign(Object.assign({},this.logContext),{allParticipantsAllowed:this.allParticipantsAllowedToSubscribe,participantTrackPermissions:this.participantTrackPermissions})),this.engine.client.sendUpdateSubscriptionPermissions(this.allParticipantsAllowedToSubscribe,this.participantTrackPermissions.map((e=>function(e){var t,n,i;if(!e.participantSid&&!e.participantIdentity)throw new Error("Invalid track permission, must provide at least one of participantIdentity and participantSid");return new ti({participantIdentity:null!==(t=e.participantIdentity)&&void 0!==t?t:"",participantSid:null!==(n=e.participantSid)&&void 0!==n?n:"",allTracks:null!==(i=e.allowAll)&&void 0!==i&&i,trackSids:e.allowedTrackSids||[]})}(e))))},this.onTrackUnmuted=e=>{this.onTrackMuted(e,e.isUpstreamPaused)},this.onTrackMuted=(e,t)=>{void 0===t&&(t=!0),e.sid?this.engine.updateMuteStatus(e.sid,t):this.log.error("could not update mute status for unpublished track",Object.assign(Object.assign({},this.logContext),Hs(e)))},this.onTrackUpstreamPaused=e=>{this.log.debug("upstream paused",Object.assign(Object.assign({},this.logContext),Hs(e))),this.onTrackMuted(e,!0)},this.onTrackUpstreamResumed=e=>{this.log.debug("upstream resumed",Object.assign(Object.assign({},this.logContext),Hs(e))),this.onTrackMuted(e,e.isMuted)},this.onTrackFeatureUpdate=e=>{const t=this.audioTrackPublications.get(e.sid);t?this.engine.client.sendUpdateLocalAudioTrack(t.trackSid,t.getTrackFeatures()):this.log.warn("Could not update local audio track settings, missing publication for track ".concat(e.sid),this.logContext)},this.onTrackCpuConstrained=(t,n)=>{this.log.debug("track cpu constrained",Object.assign(Object.assign({},this.logContext),Hs(n))),this.emit(e.ParticipantEvent.LocalTrackCpuConstrained,t,n)},this.handleSubscribedQualityUpdate=e=>Fi(this,void 0,void 0,(function*(){var t,n,i,o,s;if(!(null===(s=this.roomOptions)||void 0===s?void 0:s.dynacast))return;const r=this.videoTrackPublications.get(e.trackSid);if(!r)return void this.log.warn("received subscribed quality update for unknown track",Object.assign(Object.assign({},this.logContext),{trackSid:e.trackSid}));if(!r.videoTrack)return;const a=yield r.videoTrack.setPublishingCodecs(e.subscribedCodecs);try{for(var c,d=!0,l=Vi(a);!(t=(c=yield l.next()).done);d=!0){o=c.value,d=!1;const e=o;Os(e)&&(this.log.debug("publish ".concat(e," for ").concat(r.videoTrack.sid),Object.assign(Object.assign({},this.logContext),Hs(r))),yield this.publishAdditionalCodecForTrack(r.videoTrack,e,r.options))}}catch(e){n={error:e}}finally{try{d||t||!(i=l.return)||(yield i.call(l))}finally{if(n)throw n.error}}})),this.handleLocalTrackUnpublished=e=>{const t=this.trackPublications.get(e.trackSid);t?this.unpublishTrack(t.track):this.log.warn("received unpublished event for unknown track",Object.assign(Object.assign({},this.logContext),{trackSid:e.trackSid}))},this.handleTrackEnded=e=>Fi(this,void 0,void 0,(function*(){if(e.source===Ys.Source.ScreenShare||e.source===Ys.Source.ScreenShareAudio)this.log.debug("unpublishing local track due to TrackEnded",Object.assign(Object.assign({},this.logContext),Hs(e))),this.unpublishTrack(e);else if(e.isUserProvided)yield e.mute();else if(Wr(e)||qr(e))try{if(mr())try{const t=yield null===navigator||void 0===navigator?void 0:navigator.permissions.query({name:e.source===Ys.Source.Camera?"camera":"microphone"});if(t&&"denied"===t.state)throw this.log.warn("user has revoked access to ".concat(e.source),Object.assign(Object.assign({},this.logContext),Hs(e))),t.onchange=()=>{"denied"!==t.state&&(e.isMuted||e.restartTrack(),t.onchange=null)},new Error("GetUserMedia Permission denied")}catch(e){}e.isMuted||(this.log.debug("track ended, attempting to use a different device",Object.assign(Object.assign({},this.logContext),Hs(e))),Wr(e)?yield e.restartTrack({deviceId:"default"}):yield e.restartTrack())}catch(t){this.log.warn("could not restart track, muting instead",Object.assign(Object.assign({},this.logContext),Hs(e))),yield e.mute()}})),this.audioTrackPublications=new Map,this.videoTrackPublications=new Map,this.trackPublications=new Map,this.engine=i,this.roomOptions=o,this.setupEngine(i),this.activeDeviceMap=new Map([["audioinput","default"],["videoinput","default"],["audiooutput","default"]]),this.pendingSignalRequests=new Map,this.rpcHandlers=s,this.roomOutgoingDataStreamManager=r}get lastCameraError(){return this.cameraError}get lastMicrophoneError(){return this.microphoneError}get isE2EEEnabled(){return this.encryptionType!==pt.NONE}getTrackPublication(e){const t=super.getTrackPublication(e);if(t)return t}getTrackPublicationByName(e){const t=super.getTrackPublicationByName(e);if(t)return t}setupEngine(t){var n;this.engine=t,this.engine.on(e.EngineEvent.RemoteMute,((e,t)=>{const n=this.trackPublications.get(e);n&&n.track&&(t?n.mute():n.unmute())})),(null===(n=this.signalConnectedFuture)||void 0===n?void 0:n.isResolved)&&(this.signalConnectedFuture=void 0),this.engine.on(e.EngineEvent.Connected,this.handleReconnected).on(e.EngineEvent.SignalConnected,this.handleSignalConnected).on(e.EngineEvent.SignalRestarted,this.handleReconnected).on(e.EngineEvent.SignalResumed,this.handleReconnected).on(e.EngineEvent.Restarting,this.handleReconnecting).on(e.EngineEvent.Resuming,this.handleReconnecting).on(e.EngineEvent.LocalTrackUnpublished,this.handleLocalTrackUnpublished).on(e.EngineEvent.SubscribedQualityUpdate,this.handleSubscribedQualityUpdate).on(e.EngineEvent.Closing,this.handleClosing).on(e.EngineEvent.SignalRequestResponse,this.handleSignalRequestResponse).on(e.EngineEvent.DataPacketReceived,this.handleDataPacket)}setMetadata(e){return Fi(this,void 0,void 0,(function*(){yield this.requestMetadataUpdate({metadata:e})}))}setName(e){return Fi(this,void 0,void 0,(function*(){yield this.requestMetadataUpdate({name:e})}))}setAttributes(e){return Fi(this,void 0,void 0,(function*(){yield this.requestMetadataUpdate({attributes:e})}))}requestMetadataUpdate(e){return Fi(this,arguments,void 0,(function(e){var t=this;let{metadata:n,name:i,attributes:o}=e;return function*(){return new Xo(((e,s)=>Fi(t,void 0,void 0,(function*(){var t,r;try{let a=!1;const c=yield this.engine.client.sendUpdateLocalMetadata(null!==(t=null!=n?n:this.metadata)&&void 0!==t?t:"",null!==(r=null!=i?i:this.name)&&void 0!==r?r:"",o),d=performance.now();for(this.pendingSignalRequests.set(c,{resolve:e,reject:e=>{s(e),a=!0},values:{name:i,metadata:n,attributes:o}});performance.now()-d<5e3&&!a;){if((!i||this.name===i)&&(!n||this.metadata===n)&&(!o||Object.entries(o).every((e=>{let[t,n]=e;return this.attributes[t]===n||""===n&&!this.attributes[t]}))))return this.pendingSignalRequests.delete(c),void e();yield er(50)}s(new bs("Request to update local metadata timed out","TimeoutError"))}catch(e){e instanceof Error?s(e):s(new Error(String(e)))}}))))}()}))}setCameraEnabled(e,t,n){return this.setTrackEnabled(Ys.Source.Camera,e,t,n)}setMicrophoneEnabled(e,t,n){return this.setTrackEnabled(Ys.Source.Microphone,e,t,n)}setScreenShareEnabled(e,t,n){return this.setTrackEnabled(Ys.Source.ScreenShare,e,t,n)}setE2EEEnabled(e){return Fi(this,void 0,void 0,(function*(){this.encryptionType=e?pt.GCM:pt.NONE,yield this.republishAllTracks(void 0,!1)}))}setTrackEnabled(t,n,i,o){return Fi(this,void 0,void 0,(function*(){var s,r;this.log.debug("setTrackEnabled",Object.assign(Object.assign({},this.logContext),{source:t,enabled:n})),this.republishPromise&&(yield this.republishPromise);let a=this.getTrackPublication(t);if(n)if(a)yield a.unmute();else{let n;if(this.pendingPublishing.has(t)){const e=yield this.waitForPendingPublicationOfSource(t);return e||this.log.info("waiting for pending publication promise timed out",Object.assign(Object.assign({},this.logContext),{source:t})),yield null==e?void 0:e.unmute(),e}this.pendingPublishing.add(t);try{switch(t){case Ys.Source.Camera:n=yield this.createTracks({video:null===(s=i)||void 0===s||s});break;case Ys.Source.Microphone:n=yield this.createTracks({audio:null===(r=i)||void 0===r||r});break;case Ys.Source.ScreenShare:n=yield this.createScreenTracks(Object.assign({},i));break;default:throw new gs(t)}}catch(i){throw null==n||n.forEach((e=>{e.stop()})),i instanceof Error&&this.emit(e.ParticipantEvent.MediaDevicesError,i,Vs(t)),this.pendingPublishing.delete(t),i}for(const e of n){const n=Object.assign(Object.assign({},this.roomOptions.publishDefaults),i);t===Ys.Source.Microphone&&Br(e)&&n.preConnectBuffer&&(this.log.info("starting preconnect buffer for microphone",Object.assign({},this.logContext)),e.startPreConnectBuffer())}try{const e=[];for(const t of n)this.log.info("publishing track",Object.assign(Object.assign({},this.logContext),Hs(t))),e.push(this.publishTrack(t,o));const t=yield Promise.all(e);[a]=t}catch(e){throw null==n||n.forEach((e=>{e.stop()})),e}finally{this.pendingPublishing.delete(t)}}else if(!(null==a?void 0:a.track)&&this.pendingPublishing.has(t)&&(a=yield this.waitForPendingPublicationOfSource(t),a||this.log.info("waiting for pending publication promise timed out",Object.assign(Object.assign({},this.logContext),{source:t}))),a&&a.track)if(t===Ys.Source.ScreenShare){a=yield this.unpublishTrack(a.track);const e=this.getTrackPublication(Ys.Source.ScreenShareAudio);e&&e.track&&this.unpublishTrack(e.track)}else yield a.mute();return a}))}enableCameraAndMicrophone(){return Fi(this,void 0,void 0,(function*(){if(!this.pendingPublishing.has(Ys.Source.Camera)&&!this.pendingPublishing.has(Ys.Source.Microphone)){this.pendingPublishing.add(Ys.Source.Camera),this.pendingPublishing.add(Ys.Source.Microphone);try{const e=yield this.createTracks({audio:!0,video:!0});yield Promise.all(e.map((e=>this.publishTrack(e))))}finally{this.pendingPublishing.delete(Ys.Source.Camera),this.pendingPublishing.delete(Ys.Source.Microphone)}}}))}createTracks(t){return Fi(this,void 0,void 0,(function*(){var n,i;null!=t||(t={});const o=Ns(t,null===(n=this.roomOptions)||void 0===n?void 0:n.audioCaptureDefaults,null===(i=this.roomOptions)||void 0===i?void 0:i.videoCaptureDefaults);try{const t=yield Qc(o,{loggerName:this.roomOptions.loggerName,loggerContextCb:()=>this.logContext});return t.map((t=>(Br(t)&&(this.microphoneError=void 0,t.setAudioContext(this.audioContext),t.source=Ys.Source.Microphone,this.emit(e.ParticipantEvent.AudioStreamAcquired)),Vr(t)&&(this.cameraError=void 0,t.source=Ys.Source.Camera),t)))}catch(e){throw e instanceof Error&&(t.audio&&(this.microphoneError=e),t.video&&(this.cameraError=e)),e}}))}createScreenTracks(t){return Fi(this,void 0,void 0,(function*(){if(void 0===t&&(t={}),void 0===navigator.mediaDevices.getDisplayMedia)throw new ms("getDisplayMedia not supported");void 0!==t.resolution||hr()||(t.resolution=As.h1080fps30.resolution);const n=qs(t),i=yield navigator.mediaDevices.getDisplayMedia(n),o=i.getVideoTracks();if(0===o.length)throw new gs("no video track found");const s=new Sc(o[0],void 0,!1,{loggerName:this.roomOptions.loggerName,loggerContextCb:()=>this.logContext});s.source=Ys.Source.ScreenShare,t.contentHint&&(s.mediaStreamTrack.contentHint=t.contentHint);const r=[s];if(i.getAudioTracks().length>0){this.emit(e.ParticipantEvent.AudioStreamAcquired);const t=new lc(i.getAudioTracks()[0],void 0,!1,this.audioContext,{loggerName:this.roomOptions.loggerName,loggerContextCb:()=>this.logContext});t.source=Ys.Source.ScreenShareAudio,r.push(t)}return r}))}publishTrack(e,t){return Fi(this,void 0,void 0,(function*(){return this.publishOrRepublishTrack(e,t)}))}publishOrRepublishTrack(e,t){return Fi(this,arguments,void 0,(function(e,t){var n=this;let i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return function*(){var o,s,r,a;let c,d;if(Wr(e)&&e.setAudioContext(n.audioContext),yield null===(o=n.reconnectFuture)||void 0===o?void 0:o.promise,n.republishPromise&&!i&&(yield n.republishPromise),Fr(e)&&n.pendingPublishPromises.has(e)&&(yield n.pendingPublishPromises.get(e)),e instanceof MediaStreamTrack)c=e.getConstraints();else{let t;switch(c=e.constraints,e.source){case Ys.Source.Microphone:t="audioinput";break;case Ys.Source.Camera:t="videoinput"}t&&n.activeDeviceMap.has(t)&&(c=Object.assign(Object.assign({},c),{deviceId:n.activeDeviceMap.get(t)}))}if(e instanceof MediaStreamTrack)switch(e.kind){case"audio":e=new lc(e,c,!0,n.audioContext,{loggerName:n.roomOptions.loggerName,loggerContextCb:()=>n.logContext});break;case"video":e=new Sc(e,c,!0,{loggerName:n.roomOptions.loggerName,loggerContextCb:()=>n.logContext});break;default:throw new gs("unsupported MediaStreamTrack kind ".concat(e.kind))}else e.updateLoggerOptions({loggerName:n.roomOptions.loggerName,loggerContextCb:()=>n.logContext});if(n.trackPublications.forEach((t=>{t.track&&t.track===e&&(d=t)})),d)return n.log.warn("track has already been published, skipping",Object.assign(Object.assign({},n.logContext),Hs(d))),d;const l=Object.assign(Object.assign({},n.roomOptions.publishDefaults),t),u="channelCount"in e.mediaStreamTrack.getSettings()&&2===e.mediaStreamTrack.getSettings().channelCount||2===e.mediaStreamTrack.getConstraints().channelCount,h=null!==(s=l.forceStereo)&&void 0!==s?s:u;h&&(void 0===l.dtx&&n.log.info("Opus DTX will be disabled for stereo tracks by default. Enable them explicitly to make it work.",Object.assign(Object.assign({},n.logContext),Hs(e))),void 0===l.red&&n.log.info("Opus RED will be disabled for stereo tracks by default. Enable them explicitly to make it work."),null!==(r=l.dtx)&&void 0!==r||(l.dtx=!1),null!==(a=l.red)&&void 0!==a||(l.red=!1)),!function(){const e=es(),t="17.2";if(e)return"Safari"!==e.name&&"iOS"!==e.os||!!("iOS"===e.os&&e.osVersion&&Tr(e.osVersion,t)>=0)||"Safari"===e.name&&Tr(e.version,t)>=0}()&&n.roomOptions.e2ee&&(n.log.info("End-to-end encryption is set up, simulcast publishing will be disabled on Safari versions and iOS browsers running iOS < v17.2",Object.assign({},n.logContext)),l.simulcast=!1),l.source&&(e.source=l.source);const p=new Promise(((t,i)=>Fi(n,void 0,void 0,(function*(){try{if(this.engine.client.currentState!==ba.CONNECTED){this.log.debug("deferring track publication until signal is connected",Object.assign(Object.assign({},this.logContext),{track:Hs(e)}));let n=!1;const o=setTimeout((()=>{n=!0,e.stop(),i(new ys("publishing rejected as engine not connected within timeout",408))}),15e3);if(yield this.waitUntilEngineConnected(),clearTimeout(o),n)return;const s=yield this.publish(e,l,h);t(s)}else try{const n=yield this.publish(e,l,h);t(n)}catch(e){i(e)}}catch(e){i(e)}}))));n.pendingPublishPromises.set(e,p);try{return yield p}catch(e){throw e}finally{n.pendingPublishPromises.delete(e)}}()}))}waitUntilEngineConnected(){return this.signalConnectedFuture||(this.signalConnectedFuture=new Mr),this.signalConnectedFuture.promise}hasPermissionsToPublish(e){if(!this.permissions)return this.log.warn("no permissions present for publishing track",Object.assign(Object.assign({},this.logContext),Hs(e))),!1;const{canPublish:t,canPublishSources:n}=this.permissions;return!(!t||0!==n.length&&!n.map((e=>function(e){switch(e){case Ze.CAMERA:return Ys.Source.Camera;case Ze.MICROPHONE:return Ys.Source.Microphone;case Ze.SCREEN_SHARE:return Ys.Source.ScreenShare;case Ze.SCREEN_SHARE_AUDIO:return Ys.Source.ScreenShareAudio;default:return Ys.Source.Unknown}}(e))).includes(e.source))||(this.log.warn("insufficient permissions to publish",Object.assign(Object.assign({},this.logContext),Hs(e))),!1)}publish(t,n,i){return Fi(this,void 0,void 0,(function*(){var o,s,r,a,c,d,l,u,h,p;if(!this.hasPermissionsToPublish(t))throw new ys("failed to publish track, insufficient permissions",403);Array.from(this.trackPublications.values()).find((e=>Fr(t)&&e.source===t.source))&&t.source!==Ys.Source.Unknown&&this.log.info("publishing a second track with the same source: ".concat(t.source),Object.assign(Object.assign({},this.logContext),Hs(t))),n.stopMicTrackOnMute&&Br(t)&&(t.stopOnMute=!0),t.source===Ys.Source.ScreenShare&&cr()&&(n.simulcast=!1),"av1"!==n.videoCodec||ir()||(n.videoCodec=void 0),"vp9"!==n.videoCodec||or()||(n.videoCodec=void 0),void 0===n.videoCodec&&(n.videoCodec=Ga),this.enabledPublishVideoCodecs.length>0&&(this.enabledPublishVideoCodecs.some((e=>n.videoCodec===Ws(e.mime)))||(n.videoCodec=Ws(this.enabledPublishVideoCodecs[0].mime)));const m=n.videoCodec;t.on(e.TrackEvent.Muted,this.onTrackMuted),t.on(e.TrackEvent.Unmuted,this.onTrackUnmuted),t.on(e.TrackEvent.Ended,this.handleTrackEnded),t.on(e.TrackEvent.UpstreamPaused,this.onTrackUpstreamPaused),t.on(e.TrackEvent.UpstreamResumed,this.onTrackUpstreamResumed),t.on(e.TrackEvent.AudioTrackFeatureUpdate,this.onTrackFeatureUpdate);const g=[],v=!(null===(o=n.dtx)||void 0===o||o),f=t.getSourceTrackSettings();f.autoGainControl&&g.push(st.TF_AUTO_GAIN_CONTROL),f.echoCancellation&&g.push(st.TF_ECHO_CANCELLATION),f.noiseSuppression&&g.push(st.TF_NOISE_SUPPRESSION),f.channelCount&&f.channelCount>1&&g.push(st.TF_STEREO),v&&g.push(st.TF_NO_DTX),Wr(t)&&t.hasPreConnectBuffer&&g.push(st.TF_PRECONNECT_BUFFER);const k=new Pn({cid:t.mediaStreamTrack.id,name:n.name,type:Ys.kindToProto(t.kind),muted:t.isMuted,source:Ys.sourceToProto(t.source),disableDtx:v,encryption:this.encryptionType,stereo:i,disableRed:this.isE2EEEnabled||!(null===(s=n.red)||void 0===s||s),stream:null==n?void 0:n.stream,backupCodecPolicy:null==n?void 0:n.backupCodecPolicy,audioFeatures:g});let y;if(t.kind===Ys.Kind.Video){let e={width:0,height:0};try{e=yield t.waitForDimensions()}catch(n){const i=null!==(a=null===(r=this.roomOptions.videoCaptureDefaults)||void 0===r?void 0:r.resolution)&&void 0!==a?a:Ms.h720.resolution;e={width:i.width,height:i.height},this.log.error("could not determine track dimensions, using defaults",Object.assign(Object.assign(Object.assign({},this.logContext),Hs(t)),{dims:e}))}k.width=e.width,k.height=e.height,qr(t)&&(sr(m)&&(t.source===Ys.Source.ScreenShare&&(n.scalabilityMode="L1T3","contentHint"in t.mediaStreamTrack&&(t.mediaStreamTrack.contentHint="motion",this.log.info("forcing contentHint to motion for screenshare with SVC codecs",Object.assign(Object.assign({},this.logContext),Hs(t))))),n.scalabilityMode=null!==(c=n.scalabilityMode)&&void 0!==c?c:"L3T3_KEY"),k.simulcastCodecs=[new Rn({codec:m,cid:t.mediaStreamTrack.id})],!0===n.backupCodec&&(n.backupCodec={codec:Ga}),n.backupCodec&&m!==n.backupCodec.codec&&k.encryption===pt.NONE&&(this.roomOptions.dynacast||(this.roomOptions.dynacast=!0),k.simulcastCodecs.push(new Rn({codec:n.backupCodec.codec,cid:""})))),y=kc(t.source===Ys.Source.ScreenShare,k.width,k.height,n),k.layers=Rc(k.width,k.height,y,sr(n.videoCodec))}else t.kind===Ys.Kind.Audio&&(y=[{maxBitrate:null===(d=n.audioPreset)||void 0===d?void 0:d.maxBitrate,priority:null!==(u=null===(l=n.audioPreset)||void 0===l?void 0:l.priority)&&void 0!==u?u:"high",networkPriority:null!==(p=null===(h=n.audioPreset)||void 0===h?void 0:h.priority)&&void 0!==p?p:"high"}]);if(!this.engine||this.engine.isClosed)throw new fs("cannot publish track when not connected");const b=()=>Fi(this,void 0,void 0,(function*(){var i,o,s;if(!this.engine.pcManager)throw new fs("pcManager is not ready");if(t.sender=yield this.engine.createSender(t,n,y),this.emit(e.ParticipantEvent.LocalSenderCreated,t.sender,t),qr(t)&&(null!==(i=n.degradationPreference)&&void 0!==i||(n.degradationPreference=function(e){return e.source===Ys.Source.ScreenShare||e.constraints.height&&Ar(e.constraints.height)>=1080?"maintain-resolution":"balanced"}(t)),t.setDegradationPreference(n.degradationPreference)),y)if(cr()&&t.kind===Ys.Kind.Audio){let e;for(const n of this.engine.pcManager.publisher.getTransceivers())if(n.sender===t.sender){e=n;break}e&&this.engine.pcManager.publisher.setTrackCodecBitrate({transceiver:e,codec:"opus",maxbr:(null===(o=y[0])||void 0===o?void 0:o.maxBitrate)?y[0].maxBitrate/1e3:0})}else t.codec&&sr(t.codec)&&(null===(s=y[0])||void 0===s?void 0:s.maxBitrate)&&this.engine.pcManager.publisher.setTrackCodecBitrate({cid:k.cid,codec:t.codec,maxbr:y[0].maxBitrate/1e3});yield this.engine.negotiate()}));let T;const C=new Promise(((e,n)=>Fi(this,void 0,void 0,(function*(){var i;try{T=yield this.engine.addTrack(k),e(T)}catch(e){t.sender&&(null===(i=this.engine.pcManager)||void 0===i?void 0:i.publisher)&&(this.engine.pcManager.publisher.removeTrack(t.sender),yield this.engine.negotiate().catch((e=>{this.log.error("failed to negotiate after removing track due to failed add track request",Object.assign(Object.assign(Object.assign({},this.logContext),Hs(t)),{error:e}))}))),n(e)}}))));if(this.enabledPublishVideoCodecs.length>0){const e=yield Promise.all([C,b()]);T=e[0]}else{let e;if(T=yield C,T.codecs.forEach((t=>{void 0===e&&(e=t.mimeType)})),e&&t.kind===Ys.Kind.Video){const i=Ws(e);i!==m&&(this.log.debug("falling back to server selected codec",Object.assign(Object.assign(Object.assign({},this.logContext),Hs(t)),{codec:i})),n.videoCodec=i,y=kc(t.source===Ys.Source.ScreenShare,k.width,k.height,n))}yield b()}const S=new zc(t.kind,T,t,{loggerName:this.roomOptions.loggerName,loggerContextCb:()=>this.logContext});if(S.on(e.TrackEvent.CpuConstrained,(e=>this.onTrackCpuConstrained(e,S))),S.options=n,t.sid=T.sid,this.log.debug("publishing ".concat(t.kind," with encodings"),Object.assign(Object.assign({},this.logContext),{encodings:y,trackInfo:T})),qr(t)?t.startMonitor(this.engine.client):Wr(t)&&t.startMonitor(),this.addTrackPublication(S),this.emit(e.ParticipantEvent.LocalTrackPublished,S),Wr(t)&&T.audioFeatures.includes(st.TF_PRECONNECT_BUFFER)){const n=t.getPreConnectBuffer(),i=t.getPreConnectBufferMimeType();if(this.on(e.ParticipantEvent.LocalTrackSubscribed,(e=>{if(e.trackSid===T.sid){if(!t.hasPreConnectBuffer)return void this.log.warn("subscribe event came to late, buffer already closed",this.logContext);this.log.debug("finished recording preconnect buffer",Object.assign(Object.assign({},this.logContext),Hs(t))),t.stopPreConnectBuffer()}})),n){const e=new Promise(((e,o)=>Fi(this,void 0,void 0,(function*(){var s,r,a,c,d,l;try{this.log.debug("waiting for agent",Object.assign(Object.assign({},this.logContext),Hs(t)));const m=setTimeout((()=>{o(new Error("agent not active within 10 seconds"))}),1e4),g=yield this.waitUntilActiveAgentPresent();clearTimeout(m),this.log.debug("sending preconnect buffer",Object.assign(Object.assign({},this.logContext),Hs(t)));const v=yield this.streamBytes({name:"preconnect-buffer",mimeType:i,topic:"lk.agent.pre-connect-audio-buffer",destinationIdentities:[g.identity],attributes:{trackId:S.trackSid,sampleRate:String(null!==(d=f.sampleRate)&&void 0!==d?d:"48000"),channels:String(null!==(l=f.channelCount)&&void 0!==l?l:"1")}});try{for(var u,h=!0,p=Vi(n);!(s=(u=yield p.next()).done);h=!0){c=u.value,h=!1;const e=c;yield v.write(e)}}catch(e){r={error:e}}finally{try{h||s||!(a=p.return)||(yield a.call(p))}finally{if(r)throw r.error}}yield v.close(),e()}catch(e){o(e)}}))));e.then((()=>{this.log.debug("preconnect buffer sent successfully",Object.assign(Object.assign({},this.logContext),Hs(t)))})).catch((e=>{this.log.error("error sending preconnect buffer",Object.assign(Object.assign(Object.assign({},this.logContext),Hs(t)),{error:e}))}))}}return S}))}get isLocal(){return!0}publishAdditionalCodecForTrack(e,t,n){return Fi(this,void 0,void 0,(function*(){var i;if(this.encryptionType!==pt.NONE)return;let o;if(this.trackPublications.forEach((t=>{t.track&&t.track===e&&(o=t)})),!o)throw new gs("track is not published");if(!qr(e))throw new gs("track is not a video track");const s=Object.assign(Object.assign({},null===(i=this.roomOptions)||void 0===i?void 0:i.publishDefaults),n),r=function(e,t,n){var i,o,s,r;if(!n.backupCodec||!0===n.backupCodec||n.backupCodec.codec===n.videoCodec)return;t!==n.backupCodec.codec&&Di.warn("requested a different codec than specified as backup",{serverRequested:t,backup:n.backupCodec.codec}),n.videoCodec=t,n.videoEncoding=n.backupCodec.encoding;const a=e.mediaStreamTrack.getSettings(),c=null!==(i=a.width)&&void 0!==i?i:null===(o=e.dimensions)||void 0===o?void 0:o.width,d=null!==(s=a.height)&&void 0!==s?s:null===(r=e.dimensions)||void 0===r?void 0:r.height;return e.source===Ys.Source.ScreenShare&&n.simulcast&&(n.simulcast=!1),kc(e.source===Ys.Source.ScreenShare,c,d,n)}(e,t,s);if(!r)return void this.log.info("backup codec has been disabled, ignoring request to add additional codec for track",Object.assign(Object.assign({},this.logContext),Hs(e)));const a=e.addSimulcastTrack(t,r);if(!a)return;const c=new Pn({cid:a.mediaStreamTrack.id,type:Ys.kindToProto(e.kind),muted:e.isMuted,source:Ys.sourceToProto(e.source),sid:e.sid,simulcastCodecs:[{codec:s.videoCodec,cid:a.mediaStreamTrack.id}]});if(c.layers=Rc(c.width,c.height,r),!this.engine||this.engine.isClosed)throw new fs("cannot publish track when not connected");const d=(yield Promise.all([this.engine.addTrack(c),(()=>Fi(this,void 0,void 0,(function*(){yield this.engine.createSimulcastSender(e,a,s,r),yield this.engine.negotiate()})))()]))[0];this.log.debug("published ".concat(t," for track ").concat(e.sid),Object.assign(Object.assign({},this.logContext),{encodings:r,trackInfo:d}))}))}unpublishTrack(t,n){return Fi(this,void 0,void 0,(function*(){var i,o;if(Fr(t)){const e=this.pendingPublishPromises.get(t);e&&(this.log.info("awaiting publish promise before attempting to unpublish",Object.assign(Object.assign({},this.logContext),Hs(t))),yield e)}const s=this.getPublicationForTrack(t),r=s?Hs(s):void 0;if(this.log.debug("unpublishing track",Object.assign(Object.assign({},this.logContext),r)),!s||!s.track)return void this.log.warn("track was not unpublished because no publication was found",Object.assign(Object.assign({},this.logContext),r));(t=s.track).off(e.TrackEvent.Muted,this.onTrackMuted),t.off(e.TrackEvent.Unmuted,this.onTrackUnmuted),t.off(e.TrackEvent.Ended,this.handleTrackEnded),t.off(e.TrackEvent.UpstreamPaused,this.onTrackUpstreamPaused),t.off(e.TrackEvent.UpstreamResumed,this.onTrackUpstreamResumed),t.off(e.TrackEvent.AudioTrackFeatureUpdate,this.onTrackFeatureUpdate),void 0===n&&(n=null===(o=null===(i=this.roomOptions)||void 0===i?void 0:i.stopLocalTrackOnUnpublish)||void 0===o||o),n?t.stop():t.stopMonitor();let a=!1;const c=t.sender;if(t.sender=void 0,this.engine.pcManager&&this.engine.pcManager.currentStatethis.unpublishTrack(e))))).filter((e=>!!e))}))}republishAllTracks(e){return Fi(this,arguments,void 0,(function(e){var t=this;let n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return function*(){t.republishPromise&&(yield t.republishPromise),t.republishPromise=new Xo(((i,o)=>Fi(t,void 0,void 0,(function*(){try{const t=[];this.trackPublications.forEach((n=>{n.track&&(e&&(n.options=Object.assign(Object.assign({},n.options),e)),t.push(n))})),yield Promise.all(t.map((e=>Fi(this,void 0,void 0,(function*(){const t=e.track;yield this.unpublishTrack(t,!1),!n||t.isMuted||t.source===Ys.Source.ScreenShare||t.source===Ys.Source.ScreenShareAudio||!Wr(t)&&!qr(t)||t.isUserProvided||(this.log.debug("restarting existing track",Object.assign(Object.assign({},this.logContext),{track:e.trackSid})),yield t.restartTrack()),yield this.publishOrRepublishTrack(t,e.options,!0)}))))),i()}catch(e){e instanceof Error?o(e):o(new Error(String(e)))}finally{this.republishPromise=void 0}})))),yield t.republishPromise}()}))}publishData(e){return Fi(this,arguments,void 0,(function(e){var t=this;let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return function*(){const i=n.reliable?yt.RELIABLE:yt.LOSSY,o=n.destinationIdentities,s=n.topic;let r=new Et({participantIdentity:t.identity,payload:e,destinationIdentities:o,topic:s});const a=new kt({kind:i,value:{case:"user",value:r}});yield t.engine.sendDataPacket(a,i)}()}))}publishDtmf(e,t){return Fi(this,void 0,void 0,(function*(){const n=new kt({kind:yt.RELIABLE,value:{case:"sipDtmf",value:new wt({code:e,digit:t})}});yield this.engine.sendDataPacket(n,yt.RELIABLE)}))}sendChatMessage(t,n){return Fi(this,void 0,void 0,(function*(){const i={id:crypto.randomUUID(),message:t,timestamp:Date.now(),attachedFiles:null==n?void 0:n.attachments},o=new kt({value:{case:"chatMessage",value:new It(Object.assign(Object.assign({},i),{timestamp:D.parse(i.timestamp)}))}});return yield this.engine.sendDataPacket(o,yt.RELIABLE),this.emit(e.ParticipantEvent.ChatMessage,i),i}))}editChatMessage(t,n){return Fi(this,void 0,void 0,(function*(){const i=Object.assign(Object.assign({},n),{message:t,editTimestamp:Date.now()}),o=new kt({value:{case:"chatMessage",value:new It(Object.assign(Object.assign({},i),{timestamp:D.parse(i.timestamp),editTimestamp:D.parse(i.editTimestamp)}))}});return yield this.engine.sendDataPacket(o,yt.RELIABLE),this.emit(e.ParticipantEvent.ChatMessage,i),i}))}sendText(e,t){return Fi(this,void 0,void 0,(function*(){return this.roomOutgoingDataStreamManager.sendText(e,t)}))}streamText(e){return Fi(this,void 0,void 0,(function*(){return this.roomOutgoingDataStreamManager.streamText(e)}))}sendFile(e,t){return Fi(this,void 0,void 0,(function*(){return this.roomOutgoingDataStreamManager.sendFile(e,t)}))}streamBytes(e){return Fi(this,void 0,void 0,(function*(){return this.roomOutgoingDataStreamManager.streamBytes(e)}))}performRpc(e){let{destinationIdentity:t,method:n,payload:i,responseTimeout:o=15e3}=e;return new Xo(((e,s)=>Fi(this,void 0,void 0,(function*(){var r,a,c,d;if(nc(i)>15360)return void s(tc.builtIn("REQUEST_PAYLOAD_TOO_LARGE"));if((null===(a=null===(r=this.engine.latestJoinResponse)||void 0===r?void 0:r.serverInfo)||void 0===a?void 0:a.version)&&Tr(null===(d=null===(c=this.engine.latestJoinResponse)||void 0===c?void 0:c.serverInfo)||void 0===d?void 0:d.version,"1.8.0")<0)return void s(tc.builtIn("UNSUPPORTED_SERVER"));const l=Math.max(o,8e3),u=crypto.randomUUID();yield this.publishRpcRequest(t,u,n,i,l);const h=setTimeout((()=>{this.pendingAcks.delete(u),s(tc.builtIn("CONNECTION_TIMEOUT")),this.pendingResponses.delete(u),clearTimeout(p)}),7e3);this.pendingAcks.set(u,{resolve:()=>{clearTimeout(h)},participantIdentity:t});const p=setTimeout((()=>{this.pendingResponses.delete(u),s(tc.builtIn("RESPONSE_TIMEOUT"))}),o);this.pendingResponses.set(u,{resolve:(t,n)=>{clearTimeout(p),this.pendingAcks.has(u)&&(this.log.warn("RPC response received before ack",u),this.pendingAcks.delete(u),clearTimeout(h)),n?s(n):e(null!=t?t:"")},participantIdentity:t})}))))}registerRpcMethod(e,t){this.rpcHandlers.has(e)&&this.log.warn("you're overriding the RPC handler for method ".concat(e,", in the future this will throw an error")),this.rpcHandlers.set(e,t)}unregisterRpcMethod(e){this.rpcHandlers.delete(e)}setTrackSubscriptionPermissions(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];this.participantTrackPermissions=t,this.allParticipantsAllowedToSubscribe=e,this.engine.client.isDisconnected||this.updateTrackSubscriptionPermissions()}handleIncomingRpcAck(e){const t=this.pendingAcks.get(e);t?(t.resolve(),this.pendingAcks.delete(e)):console.error("Ack received for unexpected RPC request",e)}handleIncomingRpcResponse(e,t,n){const i=this.pendingResponses.get(e);i?(i.resolve(t,n),this.pendingResponses.delete(e)):console.error("Response received for unexpected RPC request",e)}publishRpcRequest(e,t,n,i,o){return Fi(this,void 0,void 0,(function*(){const s=new kt({destinationIdentities:[e],kind:yt.RELIABLE,value:{case:"rpcRequest",value:new Ot({id:t,method:n,payload:i,responseTimeoutMs:o,version:1})}});yield this.engine.sendDataPacket(s,yt.RELIABLE)}))}handleParticipantDisconnected(e){for(const[t,{participantIdentity:n}]of this.pendingAcks)n===e&&this.pendingAcks.delete(t);for(const[t,{participantIdentity:n,resolve:i}]of this.pendingResponses)n===e&&(i(null,tc.builtIn("RECIPIENT_DISCONNECTED")),this.pendingResponses.delete(t))}setEnabledPublishCodecs(e){this.enabledPublishVideoCodecs=e.filter((e=>"video"===e.mime.split("/")[0].toLowerCase()))}updateInfo(e){return!!super.updateInfo(e)&&(e.tracks.forEach((e=>{var t,n;const i=this.trackPublications.get(e.sid);if(i){const o=i.isMuted||null!==(n=null===(t=i.track)||void 0===t?void 0:t.isUpstreamPaused)&&void 0!==n&&n;o!==e.muted&&(this.log.debug("updating server mute state after reconcile",Object.assign(Object.assign(Object.assign({},this.logContext),Hs(i)),{mutedOnServer:o})),this.engine.client.sendMuteTrack(e.sid,o))}})),!0)}setActiveAgent(e){var t,n,i,o;this.firstActiveAgent=e,e&&!this.firstActiveAgent&&(this.firstActiveAgent=e),e?null===(n=null===(t=this.activeAgentFuture)||void 0===t?void 0:t.resolve)||void 0===n||n.call(t,e):null===(o=null===(i=this.activeAgentFuture)||void 0===i?void 0:i.reject)||void 0===o||o.call(i,new Error("Agent disconnected")),this.activeAgentFuture=void 0}waitUntilActiveAgentPresent(){return this.firstActiveAgent?Promise.resolve(this.firstActiveAgent):(this.activeAgentFuture||(this.activeAgentFuture=new Mr),this.activeAgentFuture.promise)}getPublicationForTrack(e){let t;return this.trackPublications.forEach((n=>{const i=n.track;i&&(e instanceof MediaStreamTrack?(Wr(i)||qr(i))&&i.mediaStreamTrack===e&&(t=n):e===i&&(t=n))})),t}waitForPendingPublicationOfSource(e){return Fi(this,void 0,void 0,(function*(){const t=Date.now();for(;Date.now(){let[n]=t;return n.source===e}));if(t)return t[1];yield er(20)}}))}}class nd extends Jc{constructor(t,n,i,o){super(t,n.sid,n.name,o),this.track=void 0,this.allowed=!0,this.requestedDisabled=void 0,this.visible=!0,this.handleEnded=t=>{this.setTrack(void 0),this.emit(e.TrackEvent.Ended,t)},this.handleVisibilityChange=e=>{this.log.debug("adaptivestream video visibility ".concat(this.trackSid,", visible=").concat(e),this.logContext),this.visible=e,this.emitTrackUpdate()},this.handleVideoDimensionsChange=e=>{this.log.debug("adaptivestream video dimensions ".concat(e.width,"x").concat(e.height),this.logContext),this.videoDimensionsAdaptiveStream=e,this.emitTrackUpdate()},this.subscribed=i,this.updateInfo(n)}setSubscribed(t){const n=this.subscriptionStatus,i=this.permissionStatus;this.subscribed=t,t&&(this.allowed=!0);const o=new Ln({trackSids:[this.trackSid],subscribe:this.subscribed,participantTracks:[new xt({participantSid:"",trackSids:[this.trackSid]})]});this.emit(e.TrackEvent.UpdateSubscription,o),this.emitSubscriptionUpdateIfChanged(n),this.emitPermissionUpdateIfChanged(i)}get subscriptionStatus(){return!1===this.subscribed?Jc.SubscriptionStatus.Unsubscribed:super.isSubscribed?Jc.SubscriptionStatus.Subscribed:Jc.SubscriptionStatus.Desired}get permissionStatus(){return this.allowed?Jc.PermissionStatus.Allowed:Jc.PermissionStatus.NotAllowed}get isSubscribed(){return!1!==this.subscribed&&super.isSubscribed}get isDesired(){return!1!==this.subscribed}get isEnabled(){return void 0!==this.requestedDisabled?!this.requestedDisabled:!this.isAdaptiveStream||this.visible}get isLocal(){return!1}setEnabled(e){this.isManualOperationAllowed()&&this.requestedDisabled!==!e&&(this.requestedDisabled=!e,this.emitTrackUpdate())}setVideoQuality(e){this.isManualOperationAllowed()&&this.requestedMaxQuality!==e&&(this.requestedMaxQuality=e,this.requestedVideoDimensions=void 0,this.emitTrackUpdate())}setVideoDimensions(e){var t,n;this.isManualOperationAllowed()&&((null===(t=this.requestedVideoDimensions)||void 0===t?void 0:t.width)===e.width&&(null===(n=this.requestedVideoDimensions)||void 0===n?void 0:n.height)===e.height||(Gr(this.track)&&(this.requestedVideoDimensions=e),this.requestedMaxQuality=void 0,this.emitTrackUpdate()))}setVideoFPS(e){this.isManualOperationAllowed()&&Gr(this.track)&&this.fps!==e&&(this.fps=e,this.emitTrackUpdate())}get videoQuality(){var t;return null!==(t=this.requestedMaxQuality)&&void 0!==t?t:e.VideoQuality.HIGH}setTrack(t){const n=this.subscriptionStatus,i=this.permissionStatus,o=this.track;o!==t&&(o&&(o.off(e.TrackEvent.VideoDimensionsChanged,this.handleVideoDimensionsChange),o.off(e.TrackEvent.VisibilityChanged,this.handleVisibilityChange),o.off(e.TrackEvent.Ended,this.handleEnded),o.detach(),o.stopMonitor(),this.emit(e.TrackEvent.Unsubscribed,o)),super.setTrack(t),t&&(t.sid=this.trackSid,t.on(e.TrackEvent.VideoDimensionsChanged,this.handleVideoDimensionsChange),t.on(e.TrackEvent.VisibilityChanged,this.handleVisibilityChange),t.on(e.TrackEvent.Ended,this.handleEnded),this.emit(e.TrackEvent.Subscribed,t)),this.emitPermissionUpdateIfChanged(i),this.emitSubscriptionUpdateIfChanged(n))}setAllowed(e){const t=this.subscriptionStatus,n=this.permissionStatus;this.allowed=e,this.emitPermissionUpdateIfChanged(n),this.emitSubscriptionUpdateIfChanged(t)}setSubscriptionError(t){this.emit(e.TrackEvent.SubscriptionFailed,t)}updateInfo(t){super.updateInfo(t);const n=this.metadataMuted;this.metadataMuted=t.muted,this.track?this.track.setMuted(t.muted):n!==t.muted&&this.emit(t.muted?e.TrackEvent.Muted:e.TrackEvent.Unmuted)}emitSubscriptionUpdateIfChanged(t){const n=this.subscriptionStatus;t!==n&&this.emit(e.TrackEvent.SubscriptionStatusChanged,n,t)}emitPermissionUpdateIfChanged(t){this.permissionStatus!==t&&this.emit(e.TrackEvent.SubscriptionPermissionChanged,this.permissionStatus,t)}isManualOperationAllowed(){return!!this.isDesired||(this.log.warn("cannot update track settings when not subscribed",this.logContext),!1)}get isAdaptiveStream(){return Gr(this.track)&&this.track.isAdaptiveStream}emitTrackUpdate(){const t=new Un({trackSids:[this.trackSid],disabled:!this.isEnabled,fps:this.fps});if(this.kind===Ys.Kind.Video){let s=this.requestedVideoDimensions;if(void 0!==this.videoDimensionsAdaptiveStream)if(s){Js(this.videoDimensionsAdaptiveStream,s)&&(this.log.debug("using adaptive stream dimensions instead of requested",Object.assign(Object.assign({},this.logContext),this.videoDimensionsAdaptiveStream)),s=this.videoDimensionsAdaptiveStream)}else if(void 0!==this.requestedMaxQuality&&this.trackInfo){const e=(n=this.trackInfo,i=this.requestedMaxQuality,null===(o=n.layers)||void 0===o?void 0:o.find((e=>e.quality===i)));e&&Js(this.videoDimensionsAdaptiveStream,e)&&(this.log.debug("using adaptive stream dimensions instead of max quality layer",Object.assign(Object.assign({},this.logContext),this.videoDimensionsAdaptiveStream)),s=this.videoDimensionsAdaptiveStream)}else this.log.debug("using adaptive stream dimensions",Object.assign(Object.assign({},this.logContext),this.videoDimensionsAdaptiveStream)),s=this.videoDimensionsAdaptiveStream;s?(t.width=Math.ceil(s.width),t.height=Math.ceil(s.height)):void 0!==this.requestedMaxQuality?(this.log.debug("using requested max quality",Object.assign(Object.assign({},this.logContext),{quality:this.requestedMaxQuality})),t.quality=this.requestedMaxQuality):(this.log.debug("using default quality",Object.assign(Object.assign({},this.logContext),{quality:e.VideoQuality.HIGH})),t.quality=e.VideoQuality.HIGH)}var n,i,o;this.emit(e.TrackEvent.UpdateSettings,t)}}class id extends ed{static fromParticipantInfo(e,t,n){return new id(e,t.sid,t.identity,t.name,t.metadata,t.attributes,n,t.kind)}get logContext(){return Object.assign(Object.assign({},super.logContext),{rpID:this.sid,remoteParticipant:this.identity})}constructor(e,t,n,i,o,s,r){super(t,n||"",i,o,s,r,arguments.length>7&&void 0!==arguments[7]?arguments[7]:ut.STANDARD),this.signalClient=e,this.trackPublications=new Map,this.audioTrackPublications=new Map,this.videoTrackPublications=new Map,this.volumeMap=new Map}addTrackPublication(t){super.addTrackPublication(t),t.on(e.TrackEvent.UpdateSettings,(e=>{this.log.debug("send update settings",Object.assign(Object.assign(Object.assign({},this.logContext),Hs(t)),{settings:e})),this.signalClient.sendUpdateTrackSettings(e)})),t.on(e.TrackEvent.UpdateSubscription,(e=>{e.participantTracks.forEach((e=>{e.participantSid=this.sid})),this.signalClient.sendUpdateSubscription(e)})),t.on(e.TrackEvent.SubscriptionPermissionChanged,(n=>{this.emit(e.ParticipantEvent.TrackSubscriptionPermissionChanged,t,n)})),t.on(e.TrackEvent.SubscriptionStatusChanged,(n=>{this.emit(e.ParticipantEvent.TrackSubscriptionStatusChanged,t,n)})),t.on(e.TrackEvent.Subscribed,(n=>{this.emit(e.ParticipantEvent.TrackSubscribed,n,t)})),t.on(e.TrackEvent.Unsubscribed,(n=>{this.emit(e.ParticipantEvent.TrackUnsubscribed,n,t)})),t.on(e.TrackEvent.SubscriptionFailed,(n=>{this.emit(e.ParticipantEvent.TrackSubscriptionFailed,t.trackSid,n)}))}getTrackPublication(e){const t=super.getTrackPublication(e);if(t)return t}getTrackPublicationByName(e){const t=super.getTrackPublicationByName(e);if(t)return t}setVolume(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Ys.Source.Microphone;this.volumeMap.set(t,e);const n=this.getTrackPublication(t);n&&n.track&&n.track.setVolume(e)}getVolume(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Ys.Source.Microphone;const t=this.getTrackPublication(e);return t&&t.track?t.track.getVolume():this.volumeMap.get(e)}addSubscribedMediaTrack(t,n,i,o,s,r){let a=this.getTrackPublicationBySid(n);if(a||n.startsWith("TR")||this.trackPublications.forEach((e=>{a||t.kind!==e.kind.toString()||(a=e)})),!a)return 0===r?(this.log.error("could not find published track",Object.assign(Object.assign({},this.logContext),{trackSid:n})),void this.emit(e.ParticipantEvent.TrackSubscriptionFailed,n)):(void 0===r&&(r=20),void setTimeout((()=>{this.addSubscribedMediaTrack(t,n,i,o,s,r-1)}),150));if("ended"===t.readyState)return this.log.error("unable to subscribe because MediaStreamTrack is ended. Do not call MediaStreamTrack.stop()",Object.assign(Object.assign({},this.logContext),Hs(a))),void this.emit(e.ParticipantEvent.TrackSubscriptionFailed,n);let c;return c="video"===t.kind?new Wc(t,n,o,s):new qc(t,n,o,this.audioContext,this.audioOutput),c.source=a.source,c.isMuted=a.isMuted,c.setMediaStream(i),c.start(),a.setTrack(c),this.volumeMap.has(a.source)&&Kr(c)&&Br(c)&&c.setVolume(this.volumeMap.get(a.source)),a}get hasMetadata(){return!!this.participantInfo}getTrackPublicationBySid(e){return this.trackPublications.get(e)}updateInfo(t){if(!super.updateInfo(t))return!1;const n=new Map,i=new Map;return t.tracks.forEach((e=>{var t,o;let s=this.getTrackPublicationBySid(e.sid);if(s)s.updateInfo(e);else{const n=Ys.kindFromProto(e.type);if(!n)return;s=new nd(n,e,null===(t=this.signalClient.connectOptions)||void 0===t?void 0:t.autoSubscribe,{loggerContextCb:()=>this.logContext,loggerName:null===(o=this.loggerOptions)||void 0===o?void 0:o.loggerName}),s.updateInfo(e),i.set(e.sid,s);const r=Array.from(this.trackPublications.values()).find((e=>e.source===(null==s?void 0:s.source)));r&&s.source!==Ys.Source.Unknown&&this.log.debug("received a second track publication for ".concat(this.identity," with the same source: ").concat(s.source),Object.assign(Object.assign({},this.logContext),{oldTrack:Hs(r),newTrack:Hs(s)})),this.addTrackPublication(s)}n.set(e.sid,s)})),this.trackPublications.forEach((e=>{n.has(e.trackSid)||(this.log.trace("detected removed track on remote participant, unpublishing",Object.assign(Object.assign({},this.logContext),Hs(e))),this.unpublishTrack(e.trackSid,!0))})),i.forEach((t=>{this.emit(e.ParticipantEvent.TrackPublished,t)})),!0}unpublishTrack(t,n){const i=this.trackPublications.get(t);if(!i)return;const{track:o}=i;switch(o&&(o.stop(),i.setTrack(void 0)),this.trackPublications.delete(t),i.kind){case Ys.Kind.Audio:this.audioTrackPublications.delete(t);break;case Ys.Kind.Video:this.videoTrackPublications.delete(t)}n&&this.emit(e.ParticipantEvent.TrackUnpublished,i)}setAudioOutput(e){return Fi(this,void 0,void 0,(function*(){this.audioOutput=e;const t=[];this.audioTrackPublications.forEach((n=>{var i;Br(n.track)&&Kr(n.track)&&t.push(n.track.setSinkId(null!==(i=e.deviceId)&&void 0!==i?i:"default"))})),yield Promise.all(t)}))}emit(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),i=1;iFi(this,void 0,void 0,(function*(){var o;if(!ar())throw gr()?Error("WebRTC isn't detected, have you called registerGlobals?"):Error("LiveKit doesn't seem to be supported on this browser. Try to update your browser and make sure no browser extensions are disabling webRTC.");const s=yield this.disconnectLock.lock();if(this.state===e.ConnectionState.Connected)return this.log.info("already connected to room ".concat(this.name),this.logContext),s(),Promise.resolve();if(this.connectFuture)return s(),this.connectFuture.promise;this.setAndEmitConnectionState(e.ConnectionState.Connecting),(null===(o=this.regionUrlProvider)||void 0===o?void 0:o.getServerUrl().toString())!==Qr(t)&&(this.regionUrl=void 0,this.regionUrlProvider=void 0),vr(new URL(t))&&(void 0===this.regionUrlProvider?this.regionUrlProvider=new ec(t,n):this.regionUrlProvider.updateToken(n),this.regionUrlProvider.fetchRegionSettings().then((e=>{var t;null===(t=this.regionUrlProvider)||void 0===t||t.setServerReportedRegions(e)})).catch((e=>{this.log.warn("could not fetch region settings",Object.assign(Object.assign({},this.logContext),{error:e}))})));const r=(o,a,c)=>Fi(this,void 0,void 0,(function*(){var d,l;this.abortController&&this.abortController.abort();const u=new AbortController;this.abortController=u,null==s||s();try{if(yield pa.getInstance().getBackOffPromise(t),u.signal.aborted)throw ps.cancelled("Connection attempt aborted");yield this.attemptConnection(null!=c?c:t,n,i,u),this.abortController=void 0,o()}catch(n){if(this.regionUrlProvider&&n instanceof ps&&n.reason!==e.ConnectionErrorReason.Cancelled&&n.reason!==e.ConnectionErrorReason.NotAllowed){let i=null;try{this.log.debug("Fetching next region"),i=yield this.regionUrlProvider.getNextBestRegionUrl(null===(d=this.abortController)||void 0===d?void 0:d.signal)}catch(t){if(t instanceof ps&&(401===t.status||t.reason===e.ConnectionErrorReason.Cancelled))return this.handleDisconnect(this.options.stopLocalTrackOnUnpublish),void a(t)}[e.ConnectionErrorReason.InternalError,e.ConnectionErrorReason.ServerUnreachable,e.ConnectionErrorReason.Timeout].includes(n.reason)&&(this.log.debug("Adding failed connection attempt to back off"),pa.getInstance().addFailedConnectionAttempt(t)),i&&!(null===(l=this.abortController)||void 0===l?void 0:l.signal.aborted)?(this.log.info("Initial connection failed with ConnectionError: ".concat(n.message,". Retrying with another region: ").concat(i),this.logContext),this.recreateEngine(),yield r(o,a,i)):(this.handleDisconnect(this.options.stopLocalTrackOnUnpublish,Lr(n)),a(n))}else{let e=nt.UNKNOWN_REASON;n instanceof ps&&(e=Lr(n)),this.handleDisconnect(this.options.stopLocalTrackOnUnpublish,e),a(n)}}})),a=this.regionUrl;return this.regionUrl=void 0,this.connectFuture=new Mr(((e,t)=>{r(e,t,a)}),(()=>{this.clearConnectionFutures()})),this.connectFuture.promise})),this.connectSignal=(e,t,n,i,o,s)=>Fi(this,void 0,void 0,(function*(){var r,a,c;const d=yield n.join(e,t,{autoSubscribe:i.autoSubscribe,adaptiveStream:"object"==typeof o.adaptiveStream||o.adaptiveStream,maxRetries:i.maxRetries,e2eeEnabled:!!this.e2eeManager,websocketTimeout:i.websocketTimeout},s.signal,!o.singlePeerConnection);let l=d.serverInfo;if(l||(l={version:d.serverVersion,region:d.serverRegion}),this.serverInfo=l,this.log.debug("connected to Livekit Server ".concat(Object.entries(l).map((e=>{let[t,n]=e;return"".concat(t,": ").concat(n)})).join(", ")),{room:null===(r=d.room)||void 0===r?void 0:r.name,roomSid:null===(a=d.room)||void 0===a?void 0:a.sid,identity:null===(c=d.participant)||void 0===c?void 0:c.identity}),!l.version)throw new vs("unknown server version");return"0.15.1"===l.version&&this.options.dynacast&&(this.log.debug("disabling dynacast due to server version",this.logContext),o.dynacast=!1),d})),this.applyJoinResponse=e=>{const t=e.participant;if(this.localParticipant.sid=t.sid,this.localParticipant.identity=t.identity,this.localParticipant.setEnabledPublishCodecs(e.enabledPublishCodecs),this.e2eeManager)try{this.e2eeManager.setSifTrailer(e.sifTrailer)}catch(e){this.log.error(e instanceof Error?e.message:"Could not set SifTrailer",Object.assign(Object.assign({},this.logContext),{error:e}))}this.handleParticipantUpdates([t,...e.otherParticipants]),e.room&&this.handleRoomUpdate(e.room)},this.attemptConnection=(t,n,i,o)=>Fi(this,void 0,void 0,(function*(){var s,r;this.state===e.ConnectionState.Reconnecting||this.isResuming||(null===(s=this.engine)||void 0===s?void 0:s.pendingReconnect)?(this.log.info("Reconnection attempt replaced by new connection attempt",this.logContext),this.recreateEngine()):this.maybeCreateEngine(),(null===(r=this.regionUrlProvider)||void 0===r?void 0:r.isCloud())&&this.engine.setRegionUrlProvider(this.regionUrlProvider),this.acquireAudioContext(),this.connOptions=Object.assign(Object.assign({},Xa),i),this.connOptions.rtcConfig&&(this.engine.rtcConfig=this.connOptions.rtcConfig),this.connOptions.peerConnectionTimeout&&(this.engine.peerConnectionTimeout=this.connOptions.peerConnectionTimeout);try{const i=yield this.connectSignal(t,n,this.engine,this.connOptions,this.options,o);this.applyJoinResponse(i),this.setupLocalParticipantEvents(),this.emit(e.RoomEvent.SignalConnected)}catch(e){yield this.engine.close(),this.recreateEngine();const t=o.signal.aborted?ps.cancelled("Signal connection aborted"):ps.serverUnreachable("could not establish signal connection");throw e instanceof Error&&(t.message="".concat(t.message,": ").concat(e.message)),e instanceof ps&&(t.reason=e.reason,t.status=e.status),this.log.debug("error trying to establish signal connection",Object.assign(Object.assign({},this.logContext),{error:e})),t}if(o.signal.aborted)throw yield this.engine.close(),this.recreateEngine(),ps.cancelled("Connection attempt aborted");try{yield this.engine.waitForPCInitialConnection(this.connOptions.peerConnectionTimeout,o)}catch(e){throw yield this.engine.close(),this.recreateEngine(),e}mr()&&this.options.disconnectOnPageLeave&&(window.addEventListener("pagehide",this.onPageLeave),window.addEventListener("beforeunload",this.onPageLeave)),mr()&&window.addEventListener("freeze",this.onPageLeave),this.setAndEmitConnectionState(e.ConnectionState.Connected),this.emit(e.RoomEvent.Connected),pa.getInstance().resetFailedConnectionAttempts(t),this.registerConnectionReconcile(),this.regionUrlProvider&&this.regionUrlProvider.notifyConnected()})),this.disconnect=function(){for(var t=arguments.length,i=new Array(t),o=0;o0&&void 0!==arguments[0])||arguments[0];return function*(){var i,o,s;const r=yield t.disconnectLock.lock();try{if(t.state===e.ConnectionState.Disconnected)return void t.log.debug("already disconnected",t.logContext);if(t.log.info("disconnect from room",Object.assign({},t.logContext)),t.state===e.ConnectionState.Connecting||t.state===e.ConnectionState.Reconnecting||t.isResuming){const e="Abort connection attempt due to user initiated disconnect";t.log.warn(e,t.logContext),null===(i=t.abortController)||void 0===i||i.abort(e),null===(s=null===(o=t.connectFuture)||void 0===o?void 0:o.reject)||void 0===s||s.call(o,ps.cancelled("Client initiated disconnect")),t.connectFuture=void 0}t.engine&&(t.engine.client.isDisconnected||(yield t.engine.client.sendLeave()),yield t.engine.close()),t.handleDisconnect(n,nt.CLIENT_INITIATED),t.engine=void 0}finally{r()}}()}))},this.onPageLeave=()=>Fi(this,void 0,void 0,(function*(){this.log.info("Page leave detected, disconnecting",this.logContext),yield this.disconnect()})),this.startAudio=()=>Fi(this,void 0,void 0,(function*(){const t=[],n=es();if(n&&"iOS"===n.os){const n="livekit-dummy-audio-el";let i=document.getElementById(n);if(!i){i=document.createElement("audio"),i.id=n,i.autoplay=!0,i.hidden=!0;const t=Dr();t.enabled=!0;const o=new MediaStream([t]);i.srcObject=o,document.addEventListener("visibilitychange",(()=>{i&&(i.srcObject=document.hidden?null:o,document.hidden||(this.log.debug("page visible again, triggering startAudio to resume playback and update playback status",this.logContext),this.startAudio()))})),document.body.append(i),this.once(e.RoomEvent.Disconnected,(()=>{null==i||i.remove(),i=null}))}t.push(i)}this.remoteParticipants.forEach((e=>{e.audioTrackPublications.forEach((e=>{e.track&&e.track.attachedElements.forEach((e=>{t.push(e)}))}))}));try{yield Promise.all([this.acquireAudioContext(),...t.map((e=>(e.muted=!1,e.play())))]),this.handleAudioPlaybackStarted()}catch(e){throw this.handleAudioPlaybackFailed(e),e}})),this.startVideo=()=>Fi(this,void 0,void 0,(function*(){const e=[];for(const t of this.remoteParticipants.values())t.videoTrackPublications.forEach((t=>{var n;null===(n=t.track)||void 0===n||n.attachedElements.forEach((t=>{e.includes(t)||e.push(t)}))}));yield Promise.all(e.map((e=>e.play()))).then((()=>{this.handleVideoPlaybackStarted()})).catch((e=>{"NotAllowedError"===e.name?this.handleVideoPlaybackFailed():this.log.warn("Resuming video playback failed, make sure you call `startVideo` directly in a user gesture handler",this.logContext)}))})),this.handleRestarting=()=>{this.clearConnectionReconcile(),this.isResuming=!1;for(const e of this.remoteParticipants.values())this.handleParticipantDisconnected(e.identity,e);this.setAndEmitConnectionState(e.ConnectionState.Reconnecting)&&this.emit(e.RoomEvent.Reconnecting)},this.handleSignalRestarted=t=>Fi(this,void 0,void 0,(function*(){this.log.debug("signal reconnected to server, region ".concat(t.serverRegion),Object.assign(Object.assign({},this.logContext),{region:t.serverRegion})),this.bufferedEvents=[],this.applyJoinResponse(t);try{yield this.localParticipant.republishAllTracks(void 0,!0)}catch(e){this.log.error("error trying to re-publish tracks after reconnection",Object.assign(Object.assign({},this.logContext),{error:e}))}try{yield this.engine.waitForRestarted(),this.log.debug("fully reconnected to server",Object.assign(Object.assign({},this.logContext),{region:t.serverRegion}))}catch(e){return}this.setAndEmitConnectionState(e.ConnectionState.Connected),this.emit(e.RoomEvent.Reconnected),this.registerConnectionReconcile(),this.emitBufferedEvents()})),this.handleParticipantUpdates=e=>{e.forEach((e=>{var t;if(e.identity===this.localParticipant.identity)return void this.localParticipant.updateInfo(e);""===e.identity&&(e.identity=null!==(t=this.sidToIdentity.get(e.sid))&&void 0!==t?t:"");let n=this.remoteParticipants.get(e.identity);e.state===lt.DISCONNECTED?this.handleParticipantDisconnected(e.identity,n):n=this.getOrCreateParticipant(e.identity,e)}))},this.handleActiveSpeakersUpdate=t=>{const n=[],i={};t.forEach((e=>{if(i[e.sid]=!0,e.sid===this.localParticipant.sid)this.localParticipant.audioLevel=e.level,this.localParticipant.setIsSpeaking(!0),n.push(this.localParticipant);else{const t=this.getRemoteParticipantBySid(e.sid);t&&(t.audioLevel=e.level,t.setIsSpeaking(!0),n.push(t))}})),i[this.localParticipant.sid]||(this.localParticipant.audioLevel=0,this.localParticipant.setIsSpeaking(!1)),this.remoteParticipants.forEach((e=>{i[e.sid]||(e.audioLevel=0,e.setIsSpeaking(!1))})),this.activeSpeakers=n,this.emitWhenConnected(e.RoomEvent.ActiveSpeakersChanged,n)},this.handleSpeakersChanged=t=>{const n=new Map;this.activeSpeakers.forEach((e=>{const t=this.remoteParticipants.get(e.identity);t&&t.sid!==e.sid||n.set(e.sid,e)})),t.forEach((e=>{let t=this.getRemoteParticipantBySid(e.sid);e.sid===this.localParticipant.sid&&(t=this.localParticipant),t&&(t.audioLevel=e.level,t.setIsSpeaking(e.active),e.active?n.set(e.sid,t):n.delete(e.sid))}));const i=Array.from(n.values());i.sort(((e,t)=>t.audioLevel-e.audioLevel)),this.activeSpeakers=i,this.emitWhenConnected(e.RoomEvent.ActiveSpeakersChanged,i)},this.handleStreamStateUpdate=t=>{t.streamStates.forEach((t=>{const n=this.getRemoteParticipantBySid(t.participantSid);if(!n)return;const i=n.getTrackPublicationBySid(t.trackSid);if(!i||!i.track)return;const o=Ys.streamStateFromProto(t.state);i.track.setStreamState(o),o!==i.track.streamState&&(n.emit(e.ParticipantEvent.TrackStreamStateChanged,i,i.track.streamState),this.emitWhenConnected(e.RoomEvent.TrackStreamStateChanged,i,i.track.streamState,n))}))},this.handleSubscriptionPermissionUpdate=e=>{const t=this.getRemoteParticipantBySid(e.participantSid);if(!t)return;const n=t.getTrackPublicationBySid(e.trackSid);n&&n.setAllowed(e.allowed)},this.handleSubscriptionError=e=>{const t=Array.from(this.remoteParticipants.values()).find((t=>t.trackPublications.has(e.trackSid)));if(!t)return;const n=t.getTrackPublicationBySid(e.trackSid);n&&n.setSubscriptionError(e.err)},this.handleDataPacket=(e,t)=>{const n=this.remoteParticipants.get(e.participantIdentity);if("user"===e.value.case)this.handleUserPacket(n,e.value.value,e.kind,t);else if("transcription"===e.value.case)this.handleTranscription(n,e.value.value);else if("sipDtmf"===e.value.case)this.handleSipDtmf(n,e.value.value);else if("chatMessage"===e.value.case)this.handleChatMessage(n,e.value.value);else if("metrics"===e.value.case)this.handleMetrics(e.value.value,n);else if("streamHeader"===e.value.case||"streamChunk"===e.value.case||"streamTrailer"===e.value.case)this.handleDataStream(e,t);else if("rpcRequest"===e.value.case){const t=e.value.value;this.handleIncomingRpcRequest(e.participantIdentity,t.id,t.method,t.payload,t.responseTimeoutMs,t.version)}},this.handleUserPacket=(t,n,i,o)=>{this.emit(e.RoomEvent.DataReceived,n.payload,t,i,n.topic,o),null==t||t.emit(e.ParticipantEvent.DataReceived,n.payload,i,o)},this.handleSipDtmf=(t,n)=>{this.emit(e.RoomEvent.SipDTMFReceived,n,t),null==t||t.emit(e.ParticipantEvent.SipDTMFReceived,n)},this.handleTranscription=(t,n)=>{const i=n.transcribedParticipantIdentity===this.localParticipant.identity?this.localParticipant:this.getParticipantByIdentity(n.transcribedParticipantIdentity),o=null==i?void 0:i.trackPublications.get(n.trackId),s=function(e,t){return e.segments.map((e=>{let{id:n,text:i,language:o,startTime:s,endTime:r,final:a}=e;var c;const d=null!==(c=t.get(n))&&void 0!==c?c:Date.now(),l=Date.now();return a?t.delete(n):t.set(n,d),{id:n,text:i,startTime:Number.parseInt(s.toString()),endTime:Number.parseInt(r.toString()),final:a,language:o,firstReceivedTime:d,lastReceivedTime:l}}))}(n,this.transcriptionReceivedTimes);null==o||o.emit(e.TrackEvent.TranscriptionReceived,s),null==i||i.emit(e.ParticipantEvent.TranscriptionReceived,s,o),this.emit(e.RoomEvent.TranscriptionReceived,s,i,o)},this.handleChatMessage=(t,n)=>{const i=function(e){const{id:t,timestamp:n,message:i,editTimestamp:o}=e;return{id:t,timestamp:Number.parseInt(n.toString()),editTimestamp:o?Number.parseInt(o.toString()):void 0,message:i}}(n);this.emit(e.RoomEvent.ChatMessage,i,t)},this.handleMetrics=(t,n)=>{this.emit(e.RoomEvent.MetricsReceived,t,n)},this.handleDataStream=(e,t)=>{this.incomingDataStreamManager.handleDataStreamPacket(e,t)},this.bufferedSegments=new Map,this.handleAudioPlaybackStarted=()=>{this.canPlaybackAudio||(this.audioEnabled=!0,this.emit(e.RoomEvent.AudioPlaybackStatusChanged,!0))},this.handleAudioPlaybackFailed=t=>{this.log.warn("could not playback audio",Object.assign(Object.assign({},this.logContext),{error:t})),this.canPlaybackAudio&&(this.audioEnabled=!1,this.emit(e.RoomEvent.AudioPlaybackStatusChanged,!1))},this.handleVideoPlaybackStarted=()=>{this.isVideoPlaybackBlocked&&(this.isVideoPlaybackBlocked=!1,this.emit(e.RoomEvent.VideoPlaybackStatusChanged,!0))},this.handleVideoPlaybackFailed=()=>{this.isVideoPlaybackBlocked||(this.isVideoPlaybackBlocked=!0,this.emit(e.RoomEvent.VideoPlaybackStatusChanged,!1))},this.handleDeviceChange=()=>Fi(this,void 0,void 0,(function*(){var t;"iOS"!==(null===(t=es())||void 0===t?void 0:t.os)&&(yield this.selectDefaultDevices()),this.emit(e.RoomEvent.MediaDevicesChanged)})),this.handleRoomUpdate=t=>{const n=this.roomInfo;this.roomInfo=t,n&&n.metadata!==t.metadata&&this.emitWhenConnected(e.RoomEvent.RoomMetadataChanged,t.metadata),(null==n?void 0:n.activeRecording)!==t.activeRecording&&this.emitWhenConnected(e.RoomEvent.RecordingStatusChanged,t.activeRecording)},this.handleConnectionQualityUpdate=e=>{e.updates.forEach((e=>{if(e.participantSid===this.localParticipant.sid)return void this.localParticipant.setConnectionQuality(e.quality);const t=this.getRemoteParticipantBySid(e.participantSid);t&&t.setConnectionQuality(e.quality)}))},this.onLocalParticipantMetadataChanged=t=>{this.emit(e.RoomEvent.ParticipantMetadataChanged,t,this.localParticipant)},this.onLocalParticipantNameChanged=t=>{this.emit(e.RoomEvent.ParticipantNameChanged,t,this.localParticipant)},this.onLocalAttributesChanged=t=>{this.emit(e.RoomEvent.ParticipantAttributesChanged,t,this.localParticipant)},this.onLocalTrackMuted=t=>{this.emit(e.RoomEvent.TrackMuted,t,this.localParticipant)},this.onLocalTrackUnmuted=t=>{this.emit(e.RoomEvent.TrackUnmuted,t,this.localParticipant)},this.onTrackProcessorUpdate=e=>{var t;null===(t=null==e?void 0:e.onPublish)||void 0===t||t.call(e,this)},this.onLocalTrackPublished=t=>Fi(this,void 0,void 0,(function*(){var n,i,o,s,r,a;if(null===(n=t.track)||void 0===n||n.on(e.TrackEvent.TrackProcessorUpdate,this.onTrackProcessorUpdate),null===(i=t.track)||void 0===i||i.on(e.TrackEvent.Restarted,this.onLocalTrackRestarted),null===(r=null===(s=null===(o=t.track)||void 0===o?void 0:o.getProcessor())||void 0===s?void 0:s.onPublish)||void 0===r||r.call(s,this),this.emit(e.RoomEvent.LocalTrackPublished,t,this.localParticipant),Wr(t.track)){(yield t.track.checkForSilence())&&this.emit(e.RoomEvent.LocalAudioSilenceDetected,t)}const c=yield null===(a=t.track)||void 0===a?void 0:a.getDeviceId(!1),d=Vs(t.source);d&&c&&c!==this.localParticipant.activeDeviceMap.get(d)&&(this.localParticipant.activeDeviceMap.set(d,c),this.emit(e.RoomEvent.ActiveDeviceChanged,d,c))})),this.onLocalTrackUnpublished=t=>{var n,i;null===(n=t.track)||void 0===n||n.off(e.TrackEvent.TrackProcessorUpdate,this.onTrackProcessorUpdate),null===(i=t.track)||void 0===i||i.off(e.TrackEvent.Restarted,this.onLocalTrackRestarted),this.emit(e.RoomEvent.LocalTrackUnpublished,t,this.localParticipant)},this.onLocalTrackRestarted=t=>Fi(this,void 0,void 0,(function*(){const n=yield t.getDeviceId(!1),i=Vs(t.source);i&&n&&n!==this.localParticipant.activeDeviceMap.get(i)&&(this.log.debug("local track restarted, setting ".concat(i," ").concat(n," active"),this.logContext),this.localParticipant.activeDeviceMap.set(i,n),this.emit(e.RoomEvent.ActiveDeviceChanged,i,n))})),this.onLocalConnectionQualityChanged=t=>{this.emit(e.RoomEvent.ConnectionQualityChanged,t,this.localParticipant)},this.onMediaDevicesError=(t,n)=>{this.emit(e.RoomEvent.MediaDevicesError,t,n)},this.onLocalParticipantPermissionsChanged=t=>{this.emit(e.RoomEvent.ParticipantPermissionsChanged,t,this.localParticipant)},this.onLocalChatMessageSent=t=>{this.emit(e.RoomEvent.ChatMessage,t,this.localParticipant)},this.setMaxListeners(100),this.remoteParticipants=new Map,this.sidToIdentity=new Map,this.options=Object.assign(Object.assign({},Ya),t),this.log=xi(null!==(i=this.options.loggerName)&&void 0!==i?i:e.LoggerNames.Room),this.transcriptionReceivedTimes=new Map,this.options.audioCaptureDefaults=Object.assign(Object.assign({},za),null==t?void 0:t.audioCaptureDefaults),this.options.videoCaptureDefaults=Object.assign(Object.assign({},Qa),null==t?void 0:t.videoCaptureDefaults),this.options.publishDefaults=Object.assign(Object.assign({},Ja),null==t?void 0:t.publishDefaults),this.maybeCreateEngine(),this.incomingDataStreamManager=new Lc,this.outgoingDataStreamManager=new Bc(this.engine,this.log),this.disconnectLock=new o,this.localParticipant=new td("","",this.engine,this.options,this.rpcHandlers,this.outgoingDataStreamManager),(this.options.e2ee||this.options.encryption)&&this.setupE2EE(),this.engine.e2eeManager=this.e2eeManager,this.options.videoCaptureDefaults.deviceId&&this.localParticipant.activeDeviceMap.set("videoinput",Ar(this.options.videoCaptureDefaults.deviceId)),this.options.audioCaptureDefaults.deviceId&&this.localParticipant.activeDeviceMap.set("audioinput",Ar(this.options.audioCaptureDefaults.deviceId)),(null===(s=this.options.audioOutput)||void 0===s?void 0:s.deviceId)&&this.switchActiveDevice("audiooutput",Ar(this.options.audioOutput.deviceId)).catch((e=>this.log.warn("Could not set audio output: ".concat(e.message),this.logContext))),mr()){const e=new AbortController;null===(a=null===(r=navigator.mediaDevices)||void 0===r?void 0:r.addEventListener)||void 0===a||a.call(r,"devicechange",this.handleDeviceChange,{signal:e.signal}),od.cleanupRegistry&&od.cleanupRegistry.register(this,(()=>{e.abort()}))}}registerTextStreamHandler(e,t){return this.incomingDataStreamManager.registerTextStreamHandler(e,t)}unregisterTextStreamHandler(e){return this.incomingDataStreamManager.unregisterTextStreamHandler(e)}registerByteStreamHandler(e,t){return this.incomingDataStreamManager.registerByteStreamHandler(e,t)}unregisterByteStreamHandler(e){return this.incomingDataStreamManager.unregisterByteStreamHandler(e)}registerRpcMethod(e,t){if(this.rpcHandlers.has(e))throw Error("RPC handler already registered for method ".concat(e,", unregisterRpcMethod before trying to register again"));this.rpcHandlers.set(e,t)}unregisterRpcMethod(e){this.rpcHandlers.delete(e)}setE2EEEnabled(e){return Fi(this,void 0,void 0,(function*(){if(!this.e2eeManager)throw Error("e2ee not configured, please set e2ee settings within the room options");yield Promise.all([this.localParticipant.setE2EEEnabled(e)]),""!==this.localParticipant.identity&&this.e2eeManager.setParticipantCryptorEnabled(e,this.localParticipant.identity)}))}setupE2EE(){var t;const n=!!this.options.encryption,i=this.options.encryption||this.options.e2ee;i&&("e2eeManager"in i?(this.e2eeManager=i.e2eeManager,this.e2eeManager.isDataChannelEncryptionEnabled=n):this.e2eeManager=new ha(i,n),this.e2eeManager.on(e.EncryptionEvent.ParticipantEncryptionStatusChanged,((t,n)=>{Jr(n)&&(this.isE2EEEnabled=t),this.emit(e.RoomEvent.ParticipantEncryptionStatusChanged,t,n)})),this.e2eeManager.on(e.EncryptionEvent.EncryptionError,((t,n)=>{const i=n?this.getParticipantByIdentity(n):void 0;this.emit(e.RoomEvent.EncryptionError,t,i)})),null===(t=this.e2eeManager)||void 0===t||t.setup(this))}get logContext(){var e;return{room:this.name,roomID:null===(e=this.roomInfo)||void 0===e?void 0:e.sid,participant:this.localParticipant.identity,pID:this.localParticipant.sid}}get isRecording(){var e,t;return null!==(t=null===(e=this.roomInfo)||void 0===e?void 0:e.activeRecording)&&void 0!==t&&t}getSid(){return this.state===e.ConnectionState.Disconnected?Xo.resolve(""):this.roomInfo&&""!==this.roomInfo.sid?Xo.resolve(this.roomInfo.sid):new Xo(((t,n)=>{const i=n=>{""!==n.sid&&(this.engine.off(e.EngineEvent.RoomUpdate,i),t(n.sid))};this.engine.on(e.EngineEvent.RoomUpdate,i),this.once(e.RoomEvent.Disconnected,(()=>{this.engine.off(e.EngineEvent.RoomUpdate,i),n(new fs("Room disconnected before room server id was available"))}))}))}get name(){var e,t;return null!==(t=null===(e=this.roomInfo)||void 0===e?void 0:e.name)&&void 0!==t?t:""}get metadata(){var e;return null===(e=this.roomInfo)||void 0===e?void 0:e.metadata}get numParticipants(){var e,t;return null!==(t=null===(e=this.roomInfo)||void 0===e?void 0:e.numParticipants)&&void 0!==t?t:0}get numPublishers(){var e,t;return null!==(t=null===(e=this.roomInfo)||void 0===e?void 0:e.numPublishers)&&void 0!==t?t:0}maybeCreateEngine(){this.engine&&!this.engine.isClosed||(this.engine=new Dc(this.options),this.engine.e2eeManager=this.e2eeManager,this.engine.on(e.EngineEvent.ParticipantUpdate,this.handleParticipantUpdates).on(e.EngineEvent.RoomUpdate,this.handleRoomUpdate).on(e.EngineEvent.SpeakersChanged,this.handleSpeakersChanged).on(e.EngineEvent.StreamStateChanged,this.handleStreamStateUpdate).on(e.EngineEvent.ConnectionQualityUpdate,this.handleConnectionQualityUpdate).on(e.EngineEvent.SubscriptionError,this.handleSubscriptionError).on(e.EngineEvent.SubscriptionPermissionUpdate,this.handleSubscriptionPermissionUpdate).on(e.EngineEvent.MediaTrackAdded,((e,t,n)=>{this.onTrackAdded(e,t,n)})).on(e.EngineEvent.Disconnected,(e=>{this.handleDisconnect(this.options.stopLocalTrackOnUnpublish,e)})).on(e.EngineEvent.ActiveSpeakersUpdate,this.handleActiveSpeakersUpdate).on(e.EngineEvent.DataPacketReceived,this.handleDataPacket).on(e.EngineEvent.Resuming,(()=>{this.clearConnectionReconcile(),this.isResuming=!0,this.log.info("Resuming signal connection",this.logContext),this.setAndEmitConnectionState(e.ConnectionState.SignalReconnecting)&&this.emit(e.RoomEvent.SignalReconnecting)})).on(e.EngineEvent.Resumed,(()=>{this.registerConnectionReconcile(),this.isResuming=!1,this.log.info("Resumed signal connection",this.logContext),this.updateSubscriptions(),this.emitBufferedEvents(),this.setAndEmitConnectionState(e.ConnectionState.Connected)&&this.emit(e.RoomEvent.Reconnected)})).on(e.EngineEvent.SignalResumed,(()=>{this.bufferedEvents=[],(this.state===e.ConnectionState.Reconnecting||this.isResuming)&&this.sendSyncState()})).on(e.EngineEvent.Restarting,this.handleRestarting).on(e.EngineEvent.SignalRestarted,this.handleSignalRestarted).on(e.EngineEvent.Offline,(()=>{this.setAndEmitConnectionState(e.ConnectionState.Reconnecting)&&this.emit(e.RoomEvent.Reconnecting)})).on(e.EngineEvent.DCBufferStatusChanged,((t,n)=>{this.emit(e.RoomEvent.DCBufferStatusChanged,t,n)})).on(e.EngineEvent.LocalTrackSubscribed,(t=>{const n=this.localParticipant.getTrackPublications().find((e=>{let{trackSid:n}=e;return n===t}));n?(this.localParticipant.emit(e.ParticipantEvent.LocalTrackSubscribed,n),this.emitWhenConnected(e.RoomEvent.LocalTrackSubscribed,n,this.localParticipant)):this.log.warn("could not find local track subscription for subscribed event",this.logContext)})).on(e.EngineEvent.RoomMoved,(t=>{this.log.debug("room moved",t),t.room&&this.handleRoomUpdate(t.room),this.remoteParticipants.forEach(((e,t)=>{this.handleParticipantDisconnected(t,e)})),this.emit(e.RoomEvent.Moved,t.room.name),t.participant?this.handleParticipantUpdates([t.participant,...t.otherParticipants]):this.handleParticipantUpdates(t.otherParticipants)})),this.localParticipant&&this.localParticipant.setupEngine(this.engine),this.e2eeManager&&this.e2eeManager.setupEngine(this.engine),this.outgoingDataStreamManager&&this.outgoingDataStreamManager.setupEngine(this.engine))}static getLocalDevices(e){let t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return ga.getInstance().getDevices(e,t)}prepareConnection(t,n){return Fi(this,void 0,void 0,(function*(){if(this.state===e.ConnectionState.Disconnected){this.log.debug("prepareConnection to ".concat(t),this.logContext);try{if(vr(new URL(t))&&n){this.regionUrlProvider=new ec(t,n);const i=yield this.regionUrlProvider.getNextBestRegionUrl();i&&this.state===e.ConnectionState.Disconnected&&(this.regionUrl=i,yield fetch(Nr(i),{method:"HEAD"}),this.log.debug("prepared connection to ".concat(i),this.logContext))}else yield fetch(Nr(t),{method:"HEAD"})}catch(e){this.log.warn("could not prepare connection",Object.assign(Object.assign({},this.logContext),{error:e}))}}}))}getParticipantByIdentity(e){return this.localParticipant.identity===e?this.localParticipant:this.remoteParticipants.get(e)}clearConnectionFutures(){this.connectFuture=void 0}simulateScenario(e,t){return Fi(this,void 0,void 0,(function*(){let n,i=()=>Fi(this,void 0,void 0,(function*(){}));switch(e){case"signal-reconnect":yield this.engine.client.handleOnClose("simulate disconnect");break;case"speaker":n=new ci({scenario:{case:"speakerUpdate",value:3}});break;case"node-failure":n=new ci({scenario:{case:"nodeFailure",value:!0}});break;case"server-leave":n=new ci({scenario:{case:"serverLeave",value:!0}});break;case"migration":n=new ci({scenario:{case:"migration",value:!0}});break;case"resume-reconnect":this.engine.failNext(),yield this.engine.client.handleOnClose("simulate resume-disconnect");break;case"disconnect-signal-on-resume":i=()=>Fi(this,void 0,void 0,(function*(){yield this.engine.client.handleOnClose("simulate resume-disconnect")})),n=new ci({scenario:{case:"disconnectSignalOnResume",value:!0}});break;case"disconnect-signal-on-resume-no-messages":i=()=>Fi(this,void 0,void 0,(function*(){yield this.engine.client.handleOnClose("simulate resume-disconnect")})),n=new ci({scenario:{case:"disconnectSignalOnResumeNoMessages",value:!0}});break;case"full-reconnect":this.engine.fullReconnectOnNext=!0,yield this.engine.client.handleOnClose("simulate full-reconnect");break;case"force-tcp":case"force-tls":n=new ci({scenario:{case:"switchCandidateProtocol",value:"force-tls"===e?2:1}}),i=()=>Fi(this,void 0,void 0,(function*(){const e=this.engine.client.onLeave;e&&e(new Bn({reason:nt.CLIENT_INITIATED,action:Vn.RECONNECT}))}));break;case"subscriber-bandwidth":if(void 0===t||"number"!=typeof t)throw new Error("subscriber-bandwidth requires a number as argument");n=new ci({scenario:{case:"subscriberBandwidth",value:jr(t)}});break;case"leave-full-reconnect":n=new ci({scenario:{case:"leaveRequestFullReconnect",value:!0}})}n&&(yield this.engine.client.sendSimulateScenario(n),yield i())}))}get canPlaybackAudio(){return this.audioEnabled}get canPlaybackVideo(){return!this.isVideoPlaybackBlocked}getActiveDevice(e){return this.localParticipant.activeDeviceMap.get(e)}switchActiveDevice(t,n){return Fi(this,arguments,void 0,(function(t,n){var i=this;let o=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];return function*(){var s,r,a,c,d,l,u;let h=!0,p=!1;const m=o?{exact:n}:n;if("audioinput"===t){p=0===i.localParticipant.audioTrackPublications.size;const e=null!==(s=i.getActiveDevice(t))&&void 0!==s?s:i.options.audioCaptureDefaults.deviceId;i.options.audioCaptureDefaults.deviceId=m;const n=Array.from(i.localParticipant.audioTrackPublications.values()).filter((e=>e.source===Ys.Source.Microphone));try{h=(yield Promise.all(n.map((e=>{var t;return null===(t=e.audioTrack)||void 0===t?void 0:t.setDeviceId(m)})))).every((e=>!0===e))}catch(t){throw i.options.audioCaptureDefaults.deviceId=e,t}const o=n.some((e=>{var t,n;return null!==(n=null===(t=e.track)||void 0===t?void 0:t.isMuted)&&void 0!==n&&n}));h&&o&&(p=!0)}else if("videoinput"===t){p=0===i.localParticipant.videoTrackPublications.size;const e=null!==(r=i.getActiveDevice(t))&&void 0!==r?r:i.options.videoCaptureDefaults.deviceId;i.options.videoCaptureDefaults.deviceId=m;const n=Array.from(i.localParticipant.videoTrackPublications.values()).filter((e=>e.source===Ys.Source.Camera));try{h=(yield Promise.all(n.map((e=>{var t;return null===(t=e.videoTrack)||void 0===t?void 0:t.setDeviceId(m)})))).every((e=>!0===e))}catch(t){throw i.options.videoCaptureDefaults.deviceId=e,t}const o=n.some((e=>{var t,n;return null!==(n=null===(t=e.track)||void 0===t?void 0:t.isMuted)&&void 0!==n&&n}));h&&o&&(p=!0)}else if("audiooutput"===t){if(p=!0,!rr()&&!i.options.webAudioMix||i.options.webAudioMix&&i.audioContext&&!("setSinkId"in i.audioContext))throw new Error("cannot switch audio output, the current browser does not support it");i.options.webAudioMix&&(n=null!==(a=yield ga.getInstance().normalizeDeviceId("audiooutput",n))&&void 0!==a?a:""),null!==(c=(u=i.options).audioOutput)&&void 0!==c||(u.audioOutput={});const e=null!==(d=i.getActiveDevice(t))&&void 0!==d?d:i.options.audioOutput.deviceId;i.options.audioOutput.deviceId=n;try{i.options.webAudioMix&&(null===(l=i.audioContext)||void 0===l||l.setSinkId(n)),yield Promise.all(Array.from(i.remoteParticipants.values()).map((e=>e.setAudioOutput({deviceId:n}))))}catch(t){throw i.options.audioOutput.deviceId=e,t}}return p&&(i.localParticipant.activeDeviceMap.set(t,n),i.emit(e.RoomEvent.ActiveDeviceChanged,t,n)),h}()}))}setupLocalParticipantEvents(){this.localParticipant.on(e.ParticipantEvent.ParticipantMetadataChanged,this.onLocalParticipantMetadataChanged).on(e.ParticipantEvent.ParticipantNameChanged,this.onLocalParticipantNameChanged).on(e.ParticipantEvent.AttributesChanged,this.onLocalAttributesChanged).on(e.ParticipantEvent.TrackMuted,this.onLocalTrackMuted).on(e.ParticipantEvent.TrackUnmuted,this.onLocalTrackUnmuted).on(e.ParticipantEvent.LocalTrackPublished,this.onLocalTrackPublished).on(e.ParticipantEvent.LocalTrackUnpublished,this.onLocalTrackUnpublished).on(e.ParticipantEvent.ConnectionQualityChanged,this.onLocalConnectionQualityChanged).on(e.ParticipantEvent.MediaDevicesError,this.onMediaDevicesError).on(e.ParticipantEvent.AudioStreamAcquired,this.startAudio).on(e.ParticipantEvent.ChatMessage,this.onLocalChatMessageSent).on(e.ParticipantEvent.ParticipantPermissionsChanged,this.onLocalParticipantPermissionsChanged)}recreateEngine(){var e;null===(e=this.engine)||void 0===e||e.close(),this.engine=void 0,this.isResuming=!1,this.remoteParticipants.clear(),this.sidToIdentity.clear(),this.bufferedEvents=[],this.maybeCreateEngine()}onTrackAdded(t,n,i){if(this.state===e.ConnectionState.Connecting||this.state===e.ConnectionState.Reconnecting){const o=()=>{this.log.debug("deferring on track for later",{mediaTrackId:t.id,mediaStreamId:n.id,tracksInStream:n.getTracks().map((e=>e.id))}),this.onTrackAdded(t,n,i),s()},s=()=>{this.off(e.RoomEvent.Reconnected,o),this.off(e.RoomEvent.Connected,o),this.off(e.RoomEvent.Disconnected,s)};return this.once(e.RoomEvent.Reconnected,o),this.once(e.RoomEvent.Connected,o),void this.once(e.RoomEvent.Disconnected,s)}if(this.state===e.ConnectionState.Disconnected)return void this.log.warn("skipping incoming track after Room disconnected",this.logContext);if("ended"===t.readyState)return void this.log.info("skipping incoming track as it already ended",this.logContext);const o=function(e){const t=e.split("|");return t.length>1?[t[0],e.substr(t[0].length+1)]:[e,""]}(n.id),s=o[0];let r=o[1],a=t.id;if(r&&r.startsWith("TR")&&(a=r),s===this.localParticipant.sid)return void this.log.warn("tried to create RemoteParticipant for local participant",this.logContext);const c=Array.from(this.remoteParticipants.values()).find((e=>e.sid===s));if(!c)return void this.log.error("Tried to add a track for a participant, that's not present. Sid: ".concat(s),this.logContext);if(!a.startsWith("TR")){const e=this.engine.getTrackIdForReceiver(i);if(!e)return void this.log.error("Tried to add a track whose 'sid' could not be found for a participant, that's not present. Sid: ".concat(s),this.logContext);a=e}let d;a.startsWith("TR")||this.log.warn("Tried to add a track whose 'sid' could not be determined for a participant, that's not present. Sid: ".concat(s,", streamId: ").concat(r,", trackId: ").concat(a),Object.assign(Object.assign({},this.logContext),{rpID:s,streamId:r,trackId:a})),this.options.adaptiveStream&&(d="object"==typeof this.options.adaptiveStream?this.options.adaptiveStream:{});const l=c.addSubscribedMediaTrack(t,a,n,i,d);(null==l?void 0:l.isEncrypted)&&!this.e2eeManager&&this.emit(e.RoomEvent.EncryptionError,new Error("Encrypted ".concat(l.source," track received from participant ").concat(c.sid,", but room does not have encryption enabled!")))}handleDisconnect(){let t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],n=arguments.length>1?arguments[1]:void 0;var i,o;if(this.clearConnectionReconcile(),this.isResuming=!1,this.bufferedEvents=[],this.transcriptionReceivedTimes.clear(),this.incomingDataStreamManager.clearControllers(),this.state!==e.ConnectionState.Disconnected){this.regionUrl=void 0,this.regionUrlProvider&&this.regionUrlProvider.notifyDisconnected();try{this.remoteParticipants.forEach((e=>{e.trackPublications.forEach((t=>{e.unpublishTrack(t.trackSid)}))})),this.localParticipant.trackPublications.forEach((e=>{var n,i,o;e.track&&this.localParticipant.unpublishTrack(e.track,t),t?(null===(n=e.track)||void 0===n||n.detach(),null===(i=e.track)||void 0===i||i.stop()):null===(o=e.track)||void 0===o||o.stopMonitor()})),this.localParticipant.off(e.ParticipantEvent.ParticipantMetadataChanged,this.onLocalParticipantMetadataChanged).off(e.ParticipantEvent.ParticipantNameChanged,this.onLocalParticipantNameChanged).off(e.ParticipantEvent.AttributesChanged,this.onLocalAttributesChanged).off(e.ParticipantEvent.TrackMuted,this.onLocalTrackMuted).off(e.ParticipantEvent.TrackUnmuted,this.onLocalTrackUnmuted).off(e.ParticipantEvent.LocalTrackPublished,this.onLocalTrackPublished).off(e.ParticipantEvent.LocalTrackUnpublished,this.onLocalTrackUnpublished).off(e.ParticipantEvent.ConnectionQualityChanged,this.onLocalConnectionQualityChanged).off(e.ParticipantEvent.MediaDevicesError,this.onMediaDevicesError).off(e.ParticipantEvent.AudioStreamAcquired,this.startAudio).off(e.ParticipantEvent.ChatMessage,this.onLocalChatMessageSent).off(e.ParticipantEvent.ParticipantPermissionsChanged,this.onLocalParticipantPermissionsChanged),this.localParticipant.trackPublications.clear(),this.localParticipant.videoTrackPublications.clear(),this.localParticipant.audioTrackPublications.clear(),this.remoteParticipants.clear(),this.sidToIdentity.clear(),this.activeSpeakers=[],this.audioContext&&"boolean"==typeof this.options.webAudioMix&&(this.audioContext.close(),this.audioContext=void 0),mr()&&(window.removeEventListener("beforeunload",this.onPageLeave),window.removeEventListener("pagehide",this.onPageLeave),window.removeEventListener("freeze",this.onPageLeave),null===(o=null===(i=navigator.mediaDevices)||void 0===i?void 0:i.removeEventListener)||void 0===o||o.call(i,"devicechange",this.handleDeviceChange))}finally{this.setAndEmitConnectionState(e.ConnectionState.Disconnected),this.emit(e.RoomEvent.Disconnected,n)}}}handleParticipantDisconnected(t,n){var i;this.remoteParticipants.delete(t),n&&(this.incomingDataStreamManager.validateParticipantHasNoActiveDataStreams(t),n.trackPublications.forEach((e=>{n.unpublishTrack(e.trackSid,!0)})),this.emit(e.RoomEvent.ParticipantDisconnected,n),n.setDisconnected(),null===(i=this.localParticipant)||void 0===i||i.handleParticipantDisconnected(n.identity))}handleIncomingRpcRequest(e,t,n,i,o,s){return Fi(this,void 0,void 0,(function*(){if(yield this.engine.publishRpcAck(e,t),1!==s)return void(yield this.engine.publishRpcResponse(e,t,null,tc.builtIn("UNSUPPORTED_VERSION")));const r=this.rpcHandlers.get(n);if(!r)return void(yield this.engine.publishRpcResponse(e,t,null,tc.builtIn("UNSUPPORTED_METHOD")));let a=null,c=null;try{const s=yield r({requestId:t,callerIdentity:e,payload:i,responseTimeout:o});nc(s)>15360?(a=tc.builtIn("RESPONSE_PAYLOAD_TOO_LARGE"),this.log.warn("RPC Response payload too large for ".concat(n))):c=s}catch(e){e instanceof tc?a=e:(this.log.warn("Uncaught error returned by RPC handler for ".concat(n,". Returning APPLICATION_ERROR instead."),e),a=tc.builtIn("APPLICATION_ERROR"))}yield this.engine.publishRpcResponse(e,t,c,a)}))}selectDefaultDevices(){return Fi(this,void 0,void 0,(function*(){var t,n,i;const o=ga.getInstance().previousDevices,s=yield ga.getInstance().getDevices(void 0,!1),r=es();if("Chrome"===(null==r?void 0:r.name)&&"iOS"!==r.os)for(let t of s){const n=o.find((e=>e.deviceId===t.deviceId));n&&""!==n.label&&n.kind===t.kind&&n.label!==t.label&&"default"===this.getActiveDevice(t.kind)&&this.emit(e.RoomEvent.ActiveDeviceChanged,t.kind,t.deviceId)}const a=["audiooutput","audioinput","videoinput"];for(let e of a){const r=Bs(e),a=this.localParticipant.getTrackPublication(r);if(a&&(null===(t=a.track)||void 0===t?void 0:t.isUserProvided))continue;const c=s.filter((t=>t.kind===e)),d=this.getActiveDevice(e);d===(null===(n=o.filter((t=>t.kind===e))[0])||void 0===n?void 0:n.deviceId)&&c.length>0&&(null===(i=c[0])||void 0===i?void 0:i.deviceId)!==d?yield this.switchActiveDevice(e,c[0].deviceId):"audioinput"===e&&!ur()||"videoinput"===e||!(c.length>0)||c.find((t=>t.deviceId===this.getActiveDevice(e)))||"audiooutput"===e&&ur()||(yield this.switchActiveDevice(e,c[0].deviceId))}}))}acquireAudioContext(){return Fi(this,void 0,void 0,(function*(){var t,n;if("boolean"!=typeof this.options.webAudioMix&&this.options.webAudioMix.audioContext?this.audioContext=this.options.webAudioMix.audioContext:this.audioContext&&"closed"!==this.audioContext.state||(this.audioContext=null!==(t=Fs())&&void 0!==t?t:void 0),this.options.webAudioMix&&this.remoteParticipants.forEach((e=>e.setAudioContext(this.audioContext))),this.localParticipant.setAudioContext(this.audioContext),this.audioContext&&"suspended"===this.audioContext.state)try{yield Promise.race([this.audioContext.resume(),er(200)])}catch(e){this.log.warn("Could not resume audio context",Object.assign(Object.assign({},this.logContext),{error:e}))}const i="running"===(null===(n=this.audioContext)||void 0===n?void 0:n.state);i!==this.canPlaybackAudio&&(this.audioEnabled=i,this.emit(e.RoomEvent.AudioPlaybackStatusChanged,i))}))}createParticipant(e,t){var n;let i;return i=t?id.fromParticipantInfo(this.engine.client,t,{loggerContextCb:()=>this.logContext,loggerName:this.options.loggerName}):new id(this.engine.client,"",e,void 0,void 0,void 0,{loggerContextCb:()=>this.logContext,loggerName:this.options.loggerName}),this.options.webAudioMix&&i.setAudioContext(this.audioContext),(null===(n=this.options.audioOutput)||void 0===n?void 0:n.deviceId)&&i.setAudioOutput(this.options.audioOutput).catch((e=>this.log.warn("Could not set audio output: ".concat(e.message),this.logContext))),i}getOrCreateParticipant(t,n){if(this.remoteParticipants.has(t)){const e=this.remoteParticipants.get(t);if(n){e.updateInfo(n)&&this.sidToIdentity.set(n.sid,n.identity)}return e}const i=this.createParticipant(t,n);return this.remoteParticipants.set(t,i),this.sidToIdentity.set(n.sid,n.identity),this.emitWhenConnected(e.RoomEvent.ParticipantConnected,i),i.on(e.ParticipantEvent.TrackPublished,(t=>{this.emitWhenConnected(e.RoomEvent.TrackPublished,t,i)})).on(e.ParticipantEvent.TrackSubscribed,((t,n)=>{t.kind===Ys.Kind.Audio?(t.on(e.TrackEvent.AudioPlaybackStarted,this.handleAudioPlaybackStarted),t.on(e.TrackEvent.AudioPlaybackFailed,this.handleAudioPlaybackFailed)):t.kind===Ys.Kind.Video&&(t.on(e.TrackEvent.VideoPlaybackFailed,this.handleVideoPlaybackFailed),t.on(e.TrackEvent.VideoPlaybackStarted,this.handleVideoPlaybackStarted)),this.emit(e.RoomEvent.TrackSubscribed,t,n,i)})).on(e.ParticipantEvent.TrackUnpublished,(t=>{this.emit(e.RoomEvent.TrackUnpublished,t,i)})).on(e.ParticipantEvent.TrackUnsubscribed,((t,n)=>{this.emit(e.RoomEvent.TrackUnsubscribed,t,n,i)})).on(e.ParticipantEvent.TrackMuted,(t=>{this.emitWhenConnected(e.RoomEvent.TrackMuted,t,i)})).on(e.ParticipantEvent.TrackUnmuted,(t=>{this.emitWhenConnected(e.RoomEvent.TrackUnmuted,t,i)})).on(e.ParticipantEvent.ParticipantMetadataChanged,(t=>{this.emitWhenConnected(e.RoomEvent.ParticipantMetadataChanged,t,i)})).on(e.ParticipantEvent.ParticipantNameChanged,(t=>{this.emitWhenConnected(e.RoomEvent.ParticipantNameChanged,t,i)})).on(e.ParticipantEvent.AttributesChanged,(t=>{this.emitWhenConnected(e.RoomEvent.ParticipantAttributesChanged,t,i)})).on(e.ParticipantEvent.ConnectionQualityChanged,(t=>{this.emitWhenConnected(e.RoomEvent.ConnectionQualityChanged,t,i)})).on(e.ParticipantEvent.ParticipantPermissionsChanged,(t=>{this.emitWhenConnected(e.RoomEvent.ParticipantPermissionsChanged,t,i)})).on(e.ParticipantEvent.TrackSubscriptionStatusChanged,((t,n)=>{this.emitWhenConnected(e.RoomEvent.TrackSubscriptionStatusChanged,t,n,i)})).on(e.ParticipantEvent.TrackSubscriptionFailed,((t,n)=>{this.emit(e.RoomEvent.TrackSubscriptionFailed,t,i,n)})).on(e.ParticipantEvent.TrackSubscriptionPermissionChanged,((t,n)=>{this.emitWhenConnected(e.RoomEvent.TrackSubscriptionPermissionChanged,t,n,i)})).on(e.ParticipantEvent.Active,(()=>{this.emitWhenConnected(e.RoomEvent.ParticipantActive,i),i.kind===ut.AGENT&&this.localParticipant.setActiveAgent(i)})),n&&i.updateInfo(n),i}sendSyncState(){const e=Array.from(this.remoteParticipants.values()).reduce(((e,t)=>(e.push(...t.getTrackPublications()),e)),[]),t=this.localParticipant.getTrackPublications();this.engine.sendSyncState(e,t)}updateSubscriptions(){for(const e of this.remoteParticipants.values())for(const t of e.videoTrackPublications.values())t.isSubscribed&&Hr(t)&&t.emitTrackUpdate()}getRemoteParticipantBySid(e){const t=this.sidToIdentity.get(e);if(t)return this.remoteParticipants.get(t)}registerConnectionReconcile(){this.clearConnectionReconcile();let e=0;this.connectionReconcileInterval=Ss.setInterval((()=>{this.engine&&!this.engine.isClosed&&this.engine.verifyTransport()?e=0:(e++,this.log.warn("detected connection state mismatch",Object.assign(Object.assign({},this.logContext),{numFailures:e,engine:this.engine?{closed:this.engine.isClosed,transportsConnected:this.engine.verifyTransport()}:void 0})),e>=3&&(this.recreateEngine(),this.handleDisconnect(this.options.stopLocalTrackOnUnpublish,nt.STATE_MISMATCH)))}),4e3)}clearConnectionReconcile(){this.connectionReconcileInterval&&Ss.clearInterval(this.connectionReconcileInterval)}setAndEmitConnectionState(t){return t!==this.state&&(this.state=t,this.emit(e.RoomEvent.ConnectionStateChanged,this.state),!0)}emitBufferedEvents(){this.bufferedEvents.forEach((e=>{let[t,n]=e;this.emit(t,...n)})),this.bufferedEvents=[]}emitWhenConnected(t){for(var n=arguments.length,i=new Array(n>1?n-1:0),o=1;othis.logContext}),{loggerName:this.options.loggerName,loggerContextCb:()=>this.logContext});this.localParticipant.addTrackPublication(t),this.localParticipant.emit(e.ParticipantEvent.LocalTrackPublished,t)}if(r.audio){const t=new zc(Ys.Kind.Audio,new gt({source:Ze.MICROPHONE,sid:Math.floor(1e4*Math.random()).toString(),type:Xe.AUDIO}),new lc(r.useRealTracks&&(null===(o=navigator.mediaDevices)||void 0===o?void 0:o.getUserMedia)?(yield navigator.mediaDevices.getUserMedia({audio:!0})).getAudioTracks()[0]:Dr(),void 0,!1,this.audioContext,{loggerName:this.options.loggerName,loggerContextCb:()=>this.logContext}),{loggerName:this.options.loggerName,loggerContextCb:()=>this.logContext});this.localParticipant.addTrackPublication(t),this.localParticipant.emit(e.ParticipantEvent.LocalTrackPublished,t)}for(let e=0;e1?n-1:0),o=1;ovoid 0!==e));t!==e.RoomEvent.TrackSubscribed&&t!==e.RoomEvent.TrackUnsubscribed||this.log.trace("subscribe trace: ".concat(t),Object.assign(Object.assign({},this.logContext),{event:t,args:n})),this.log.debug("room event ".concat(t),Object.assign(Object.assign({},this.logContext),{event:t,args:n}))}return super.emit(t,...i)}}function sd(e){return e.map((e=>{if(e)return Array.isArray(e)?sd(e):"object"==typeof e?"logContext"in e?e.logContext:void 0:e}))}od.cleanupRegistry="undefined"!=typeof FinalizationRegistry&&new FinalizationRegistry((e=>{e()}));var rd,ad=Object.freeze({__proto__:null,Convert:class{static toAgentAttributes(e){return JSON.parse(e)}static agentAttributesToJson(e){return JSON.stringify(e)}static toTranscriptionAttributes(e){return JSON.parse(e)}static transcriptionAttributesToJson(e){return JSON.stringify(e)}}});e.CheckStatus=void 0,(rd=e.CheckStatus||(e.CheckStatus={}))[rd.IDLE=0]="IDLE",rd[rd.RUNNING=1]="RUNNING",rd[rd.SKIPPED=2]="SKIPPED",rd[rd.SUCCESS=3]="SUCCESS",rd[rd.FAILED=4]="FAILED";class cd extends Ki.EventEmitter{constructor(t,n){let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};super(),this.status=e.CheckStatus.IDLE,this.logs=[],this.options={},this.url=t,this.token=n,this.name=this.constructor.name,this.room=new od(i.roomOptions),this.connectOptions=i.connectOptions,this.options=i}run(t){return Fi(this,void 0,void 0,(function*(){if(this.status!==e.CheckStatus.IDLE)throw Error("check is running already");this.setStatus(e.CheckStatus.RUNNING);try{yield this.perform()}catch(e){e instanceof Error&&(this.options.errorsAsWarnings?this.appendWarning(e.message):this.appendError(e.message))}return yield this.disconnect(),yield new Promise((e=>setTimeout(e,500))),this.status!==e.CheckStatus.SKIPPED&&this.setStatus(this.isSuccess()?e.CheckStatus.SUCCESS:e.CheckStatus.FAILED),t&&t(),this.getInfo()}))}isSuccess(){return!this.logs.some((e=>"error"===e.level))}connect(t){return Fi(this,void 0,void 0,(function*(){return this.room.state===e.ConnectionState.Connected||(t||(t=this.url),yield this.room.connect(t,this.token,this.connectOptions)),this.room}))}disconnect(){return Fi(this,void 0,void 0,(function*(){this.room&&this.room.state!==e.ConnectionState.Disconnected&&(yield this.room.disconnect(),yield new Promise((e=>setTimeout(e,500))))}))}skip(){this.setStatus(e.CheckStatus.SKIPPED)}switchProtocol(t){return Fi(this,void 0,void 0,(function*(){let n=!1,i=!1;if(this.room.on(e.RoomEvent.Reconnecting,(()=>{n=!0})),this.room.once(e.RoomEvent.Reconnected,(()=>{i=!0})),this.room.simulateScenario("force-".concat(t)),yield new Promise((e=>setTimeout(e,1e3))),!n)return;const o=Date.now()+1e4;for(;Date.now().5*(e.duration-t.duration)+.5*(e.rtt-t.rtt)));const i=t[0];this.bestStats=i,this.appendMessage("best Cloud region: ".concat(i.region))}))}getInfo(){const e=super.getInfo();return e.data=this.bestStats,e}checkCloudRegion(e){return Fi(this,void 0,void 0,(function*(){var t,n;yield this.connect(e),"tcp"===this.options.protocol&&(yield this.switchProtocol("tcp"));const i=null===(t=this.room.serverInfo)||void 0===t?void 0:t.region;if(!i)throw new Error("Region not found");const o=yield this.room.localParticipant.streamText({topic:"test"}),s="A".repeat(1e3),r=Date.now();for(let e=0;e<1e3;e++)yield o.write(s);yield o.close();const a=Date.now(),c=yield null===(n=this.room.engine.pcManager)||void 0===n?void 0:n.publisher.getStats(),d={region:i,rtt:1e4,duration:a-r};return null==c||c.forEach((e=>{"candidate-pair"===e.type&&e.nominated&&(d.rtt=1e3*e.currentRoundTripTime)})),yield this.disconnect(),d}))}}const ld=1e4;class ud extends cd{get description(){return"Connection via UDP vs TCP"}perform(){return Fi(this,void 0,void 0,(function*(){const e=yield this.checkConnectionProtocol("udp"),t=yield this.checkConnectionProtocol("tcp");this.bestStats=e,e.qualityLimitationDurations.bandwidth-t.qualityLimitationDurations.bandwidth>.5||(e.packetsLost-t.packetsLost)/e.packetsSent>.01?(this.appendMessage("best connection quality via tcp"),this.bestStats=t):this.appendMessage("best connection quality via udp");const n=this.bestStats;this.appendMessage("upstream bitrate: ".concat((n.bitrateTotal/n.count/1e3/1e3).toFixed(2)," mbps")),this.appendMessage("RTT: ".concat((n.rttTotal/n.count*1e3).toFixed(2)," ms")),this.appendMessage("jitter: ".concat((n.jitterTotal/n.count*1e3).toFixed(2)," ms")),n.packetsLost>0&&this.appendWarning("packets lost: ".concat((n.packetsLost/n.packetsSent*100).toFixed(2),"%")),n.qualityLimitationDurations.bandwidth>1&&this.appendWarning("bandwidth limited ".concat((n.qualityLimitationDurations.bandwidth/10*100).toFixed(2),"%")),n.qualityLimitationDurations.cpu>0&&this.appendWarning("cpu limited ".concat((n.qualityLimitationDurations.cpu/10*100).toFixed(2),"%"))}))}getInfo(){const e=super.getInfo();return e.data=this.bestStats,e}checkConnectionProtocol(e){return Fi(this,void 0,void 0,(function*(){yield this.connect(),"tcp"===e?yield this.switchProtocol("tcp"):yield this.switchProtocol("udp");const t=document.createElement("canvas");t.width=1280,t.height=720;const n=t.getContext("2d");if(!n)throw new Error("Could not get canvas context");let i=0;const o=()=>{i=(i+1)%360,n.fillStyle="hsl(".concat(i,", 100%, 50%)"),n.fillRect(0,0,t.width,t.height),requestAnimationFrame(o)};o();const s=t.captureStream(30).getVideoTracks()[0],r=(yield this.room.localParticipant.publishTrack(s,{simulcast:!1,degradationPreference:"maintain-resolution",videoEncoding:{maxBitrate:2e6}})).track,a={protocol:e,packetsLost:0,packetsSent:0,qualityLimitationDurations:{},rttTotal:0,jitterTotal:0,bitrateTotal:0,count:0},c=setInterval((()=>Fi(this,void 0,void 0,(function*(){const e=yield r.getRTCStatsReport();null==e||e.forEach((e=>{"outbound-rtp"===e.type?(a.packetsSent=e.packetsSent,a.qualityLimitationDurations=e.qualityLimitationDurations,a.bitrateTotal+=e.targetBitrate,a.count++):"remote-inbound-rtp"===e.type&&(a.packetsLost=e.packetsLost,a.rttTotal+=e.roundTripTime,a.jitterTotal+=e.jitter)}))}))),1e3);return yield new Promise((e=>setTimeout(e,ld))),clearInterval(c),s.stop(),t.remove(),yield this.disconnect(),a}))}}class hd extends cd{get description(){return"Can publish audio"}perform(){return Fi(this,void 0,void 0,(function*(){var e;const t=yield this.connect(),n=yield Xc();if(yield js(n,1e3))throw new Error("unable to detect audio from microphone");this.appendMessage("detected audio from microphone"),t.localParticipant.publishTrack(n),yield new Promise((e=>setTimeout(e,3e3)));const i=yield null===(e=n.sender)||void 0===e?void 0:e.getStats();if(!i)throw new Error("Could not get RTCStats");let o=0;if(i.forEach((e=>{"outbound-rtp"!==e.type||"audio"!==e.kind&&(e.kind||"audio"!==e.mediaType)||(o=e.packetsSent)})),0===o)throw new Error("Could not determine packets are sent");this.appendMessage("published ".concat(o," audio packets"))}))}}class pd extends cd{get description(){return"Can publish video"}perform(){return Fi(this,void 0,void 0,(function*(){var e;const t=yield this.connect(),n=yield Yc();yield this.checkForVideo(n.mediaStreamTrack),t.localParticipant.publishTrack(n),yield new Promise((e=>setTimeout(e,5e3)));const i=yield null===(e=n.sender)||void 0===e?void 0:e.getStats();if(!i)throw new Error("Could not get RTCStats");let o=0;if(i.forEach((e=>{"outbound-rtp"!==e.type||"video"!==e.kind&&(e.kind||"video"!==e.mediaType)||(o+=e.packetsSent)})),0===o)throw new Error("Could not determine packets are sent");this.appendMessage("published ".concat(o," video packets"))}))}checkForVideo(e){return Fi(this,void 0,void 0,(function*(){const t=new MediaStream;t.addTrack(e.clone());const n=document.createElement("video");n.srcObject=t,n.muted=!0,n.autoplay=!0,n.playsInline=!0,n.setAttribute("playsinline","true"),document.body.appendChild(n),yield new Promise((t=>{n.onplay=()=>{setTimeout((()=>{var i,o,s,r;const a=document.createElement("canvas"),c=e.getSettings(),d=null!==(o=null!==(i=c.width)&&void 0!==i?i:n.videoWidth)&&void 0!==o?o:1280,l=null!==(r=null!==(s=c.height)&&void 0!==s?s:n.videoHeight)&&void 0!==r?r:720;a.width=d,a.height=l;const u=a.getContext("2d");u.drawImage(n,0,0);const h=u.getImageData(0,0,a.width,a.height).data;let p=!0;for(let e=0;ee.stop())),n.remove()}))}}class md extends cd{get description(){return"Resuming connection after interruption"}perform(){return Fi(this,void 0,void 0,(function*(){var t;const n=yield this.connect();let i,o=!1,s=!1;const r=new Promise((e=>{setTimeout(e,5e3),i=e})),a=()=>{o=!0};n.on(e.RoomEvent.SignalReconnecting,a).on(e.RoomEvent.Reconnecting,a).on(e.RoomEvent.Reconnected,(()=>{s=!0,i(!0)})),null===(t=n.engine.client.ws)||void 0===t||t.close();const c=n.engine.client.onClose;if(c&&c(""),yield r,!o)throw new Error("Did not attempt to reconnect");if(!s||n.state!==e.ConnectionState.Connected)throw this.appendWarning("reconnection is only possible in Redis-based configurations"),new Error("Not able to reconnect")}))}}class gd extends cd{get description(){return"Can connect via TURN"}perform(){return Fi(this,void 0,void 0,(function*(){var e,t,n;vr(new URL(this.url))&&(this.appendMessage("Using region specific url"),this.url=null!==(e=yield new ec(this.url,this.token).getNextBestRegionUrl())&&void 0!==e?e:this.url);const i=new Ta,o=yield i.join(this.url,this.token,{autoSubscribe:!0,maxRetries:0,e2eeEnabled:!1,websocketTimeout:15e3},void 0,!0);let s=!1,r=!1,a=!1;for(let e of o.iceServers)for(let t of e.urls)t.startsWith("turn:")?(r=!0,a=!0):t.startsWith("turns:")&&(r=!0,a=!0,s=!0),t.startsWith("stun:")&&(a=!0);a?r&&!s&&this.appendWarning("TURN is configured server side, but TURN/TLS is unavailable."):this.appendWarning("No STUN servers configured on server side."),yield i.close(),(null===(n=null===(t=this.connectOptions)||void 0===t?void 0:t.rtcConfig)||void 0===n?void 0:n.iceServers)||r?yield this.room.connect(this.url,this.token,{rtcConfig:{iceTransportPolicy:"relay"}}):(this.appendWarning("No TURN servers configured."),this.skip(),yield new Promise((e=>setTimeout(e,0))))}))}}class vd extends cd{get description(){return"Establishing WebRTC connection"}perform(){return Fi(this,void 0,void 0,(function*(){let t=!1,n=!1;this.room.on(e.RoomEvent.SignalConnected,(()=>{var e;const i=this.room.engine.client.onTrickle;this.room.engine.client.onTrickle=(e,o)=>{if(e.candidate){const i=new RTCIceCandidate(e);let o="".concat(i.protocol," ").concat(i.address,":").concat(i.port," ").concat(i.type);i.address&&(!function(e){const t=e.split(".");if(4===t.length){if("10"===t[0])return!0;if("192"===t[0]&&"168"===t[1])return!0;if("172"===t[0]){const e=parseInt(t[1],10);if(e>=16&&e<=31)return!0}}return!1}(i.address)?"tcp"===i.protocol&&"passive"===i.tcpType?(t=!0,o+=" (passive)"):"udp"===i.protocol&&(n=!0):o+=" (private)"),this.appendMessage(o)}i&&i(e,o)},(null===(e=this.room.engine.pcManager)||void 0===e?void 0:e.subscriber)&&(this.room.engine.pcManager.subscriber.onIceCandidateError=e=>{e instanceof RTCPeerConnectionIceErrorEvent&&this.appendWarning("error with ICE candidate: ".concat(e.errorCode," ").concat(e.errorText," ").concat(e.url))})}));try{yield this.connect(),Di.info("now the room is connected")}catch(e){throw this.appendWarning("ports need to be open on firewall in order to connect."),e}t||this.appendWarning("Server is not configured for ICE/TCP"),n||this.appendWarning("No public IPv4 UDP candidates were found. Your server is likely not configured correctly")}))}}class fd extends cd{get description(){return"Connecting to signal connection via WebSocket"}perform(){return Fi(this,void 0,void 0,(function*(){var e,t,n;(this.url.startsWith("ws:")||this.url.startsWith("http:"))&&this.appendWarning("Server is insecure, clients may block connections to it");let i,o=new Ta;try{i=yield o.join(this.url,this.token,{autoSubscribe:!0,maxRetries:0,e2eeEnabled:!1,websocketTimeout:15e3},void 0,!0)}catch(e){if(vr(new URL(this.url))){this.appendMessage("Initial connection failed with error ".concat(e.message,". Retrying with region fallback"));const t=new ec(this.url,this.token),n=yield t.getNextBestRegionUrl();n&&(i=yield o.join(n,this.token,{autoSubscribe:!0,maxRetries:0,e2eeEnabled:!1,websocketTimeout:15e3},void 0,!0),this.appendMessage("Fallback to region worked. To avoid initial connections failing, ensure you're calling room.prepareConnection() ahead of time"))}}i?(this.appendMessage("Connected to server, version ".concat(i.serverVersion,".")),(null===(e=i.serverInfo)||void 0===e?void 0:e.edition)===Nt.Cloud&&(null===(t=i.serverInfo)||void 0===t?void 0:t.region)&&this.appendMessage("LiveKit Cloud: ".concat(null===(n=i.serverInfo)||void 0===n?void 0:n.region))):this.appendError("Websocket connection could not be established"),yield o.close()}))}}class kd extends Ki.EventEmitter{constructor(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};super(),this.options={},this.checkResults=new Map,this.url=e,this.token=t,this.options=n}getNextCheckId(){const t=this.checkResults.size;return this.checkResults.set(t,{logs:[],status:e.CheckStatus.IDLE,name:"",description:""}),t}updateCheck(e,t){this.checkResults.set(e,t),this.emit("checkUpdate",e,t)}isSuccess(){return Array.from(this.checkResults.values()).every((t=>t.status!==e.CheckStatus.FAILED))}getResults(){return Array.from(this.checkResults.values())}createAndRunCheck(e){return Fi(this,void 0,void 0,(function*(){const t=this.getNextCheckId(),n=new e(this.url,this.token,this.options),i=e=>{this.updateCheck(t,e)};n.on("update",i);const o=yield n.run();return n.off("update",i),o}))}checkWebsocket(){return Fi(this,void 0,void 0,(function*(){return this.createAndRunCheck(fd)}))}checkWebRTC(){return Fi(this,void 0,void 0,(function*(){return this.createAndRunCheck(vd)}))}checkTURN(){return Fi(this,void 0,void 0,(function*(){return this.createAndRunCheck(gd)}))}checkReconnect(){return Fi(this,void 0,void 0,(function*(){return this.createAndRunCheck(md)}))}checkPublishAudio(){return Fi(this,void 0,void 0,(function*(){return this.createAndRunCheck(hd)}))}checkPublishVideo(){return Fi(this,void 0,void 0,(function*(){return this.createAndRunCheck(pd)}))}checkConnectionProtocol(){return Fi(this,void 0,void 0,(function*(){const e=yield this.createAndRunCheck(ud);if(e.data&&"protocol"in e.data){const t=e.data;this.options.protocol=t.protocol}return e}))}checkCloudRegion(){return Fi(this,void 0,void 0,(function*(){return this.createAndRunCheck(dd)}))}}class yd{}class bd{}function Td(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var i=n.call(e,t);if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}new TextEncoder;const Cd=new TextDecoder;function Sd(e){if(Uint8Array.fromBase64)return Uint8Array.fromBase64("string"==typeof e?e:Cd.decode(e),{alphabet:"base64url"});let t=e;t instanceof Uint8Array&&(t=Cd.decode(t)),t=t.replace(/-/g,"+").replace(/_/g,"/");try{return function(e){if(Uint8Array.fromBase64)return Uint8Array.fromBase64(e);const t=atob(e),n=new Uint8Array(t.length);for(let e=0;e2&&void 0!==arguments[2]?arguments[2]:"unspecified",i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"unspecified";super(e,{cause:{claim:n,reason:i,payload:t}}),Td(this,"code","ERR_JWT_CLAIM_VALIDATION_FAILED"),Td(this,"claim",void 0),Td(this,"reason",void 0),Td(this,"payload",void 0),this.claim=n,this.reason=i,this.payload=t}},"code","ERR_JWT_CLAIM_VALIDATION_FAILED");Td(class extends Ed{constructor(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"unspecified",i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"unspecified";super(e,{cause:{claim:n,reason:i,payload:t}}),Td(this,"code","ERR_JWT_EXPIRED"),Td(this,"claim",void 0),Td(this,"reason",void 0),Td(this,"payload",void 0),this.claim=n,this.reason=i,this.payload=t}},"code","ERR_JWT_EXPIRED");Td(class extends Ed{constructor(){super(...arguments),Td(this,"code","ERR_JOSE_ALG_NOT_ALLOWED")}},"code","ERR_JOSE_ALG_NOT_ALLOWED");Td(class extends Ed{constructor(){super(...arguments),Td(this,"code","ERR_JOSE_NOT_SUPPORTED")}},"code","ERR_JOSE_NOT_SUPPORTED");Td(class extends Ed{constructor(){super(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"decryption operation failed",arguments.length>1?arguments[1]:void 0),Td(this,"code","ERR_JWE_DECRYPTION_FAILED")}},"code","ERR_JWE_DECRYPTION_FAILED");Td(class extends Ed{constructor(){super(...arguments),Td(this,"code","ERR_JWE_INVALID")}},"code","ERR_JWE_INVALID");Td(class extends Ed{constructor(){super(...arguments),Td(this,"code","ERR_JWS_INVALID")}},"code","ERR_JWS_INVALID");class wd extends Ed{constructor(){super(...arguments),Td(this,"code","ERR_JWT_INVALID")}}Td(wd,"code","ERR_JWT_INVALID");Td(class extends Ed{constructor(){super(...arguments),Td(this,"code","ERR_JWK_INVALID")}},"code","ERR_JWK_INVALID");Td(class extends Ed{constructor(){super(...arguments),Td(this,"code","ERR_JWKS_INVALID")}},"code","ERR_JWKS_INVALID");Td(class extends Ed{constructor(){super(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"no applicable key found in the JSON Web Key Set",arguments.length>1?arguments[1]:void 0),Td(this,"code","ERR_JWKS_NO_MATCHING_KEY")}},"code","ERR_JWKS_NO_MATCHING_KEY");Td(class extends Ed{constructor(){super(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"multiple matching keys found in the JSON Web Key Set",arguments.length>1?arguments[1]:void 0),Td(this,Symbol.asyncIterator,void 0),Td(this,"code","ERR_JWKS_MULTIPLE_MATCHING_KEYS")}},"code","ERR_JWKS_MULTIPLE_MATCHING_KEYS");Td(class extends Ed{constructor(){super(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"request timed out",arguments.length>1?arguments[1]:void 0),Td(this,"code","ERR_JWKS_TIMEOUT")}},"code","ERR_JWKS_TIMEOUT");Td(class extends Ed{constructor(){super(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"signature verification failed",arguments.length>1?arguments[1]:void 0),Td(this,"code","ERR_JWS_SIGNATURE_VERIFICATION_FAILED")}},"code","ERR_JWS_SIGNATURE_VERIFICATION_FAILED");const Rd=e=>"object"==typeof e&&null!==e;function Pd(e){if("string"!=typeof e)throw new wd("JWTs must use Compact JWS serialization, JWT must be a string");const{1:t,length:n}=e.split(".");if(5===n)throw new wd("Only JWTs using Compact JWS serialization can be decoded");if(3!==n)throw new wd("Invalid JWT");if(!t)throw new wd("JWTs must contain a payload");let i,o;try{i=Sd(t)}catch(e){throw new wd("Failed to base64url decode the payload")}try{o=JSON.parse(Cd.decode(i))}catch(e){throw new wd("Failed to parse the decoded payload as JSON")}if(!function(e){if(!Rd(e)||"[object Object]"!==Object.prototype.toString.call(e))return!1;if(null===Object.getPrototypeOf(e))return!0;let t=e;for(;null!==Object.getPrototypeOf(t);)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}(o))throw new wd("Invalid JWT Claims Set");return o}const Id=1e3;function Od(e){const t=Pd(e),{roomConfig:n}=t,i=ji(t,["roomConfig"]);return Object.assign(Object.assign({},i),{roomConfig:t.roomConfig?bn.fromJson(t.roomConfig):void 0})}class _d extends bd{constructor(){super(...arguments),this.cachedFetchOptions=null,this.cachedResponse=null,this.fetchMutex=new o}isSameAsCachedFetchOptions(e){if(!this.cachedFetchOptions)return!1;for(const t of Object.keys(this.cachedFetchOptions))switch(t){case"roomName":case"participantName":case"participantIdentity":case"participantMetadata":case"participantAttributes":case"agentName":case"agentMetadata":if(this.cachedFetchOptions[t]!==e[t])return!1;break;default:throw new Error("Options key ".concat(t," not being checked for equality!"))}return!0}shouldReturnCachedValueFromFetch(e){return!!this.cachedResponse&&(!!function(e){const t=Od(e.participantToken);if(!(null==t?void 0:t.nbf)||!(null==t?void 0:t.exp))return!0;const n=new Date,i=t.nbf*Id,o=new Date(i),s=t.exp*Id,r=new Date(s-6e4);return o<=n&&r>n}(this.cachedResponse)&&!this.isSameAsCachedFetchOptions(e))}getCachedResponseJwtPayload(){return this.cachedResponse?Od(this.cachedResponse.participantToken):null}fetch(e){return Fi(this,void 0,void 0,(function*(){const t=yield this.fetchMutex.lock();try{if(this.shouldReturnCachedValueFromFetch(e))return this.cachedResponse.toJson();this.cachedFetchOptions=e;const t=yield this.update(e);return this.cachedResponse=t,t.toJson()}finally{t()}}))}}class Dd extends yd{constructor(e){super(),this.literalOrFn=e}fetch(){return Fi(this,void 0,void 0,(function*(){return"function"==typeof this.literalOrFn?this.literalOrFn():this.literalOrFn}))}}class Md extends _d{constructor(e){super(),this.customFn=e}update(e){return Fi(this,void 0,void 0,(function*(){const t=this.customFn(e);let n;return n=t instanceof Promise?yield t:t,Si.fromJson(n,{ignoreUnknownFields:!0})}))}}class xd extends _d{constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};super(),this.url=e,this.endpointOptions=t}createRequestFromOptions(e){var t,n,i;const o=new Ci;for(const s of Object.keys(e))switch(s){case"roomName":case"participantName":case"participantIdentity":case"participantMetadata":o[s]=e[s];break;case"participantAttributes":o.participantAttributes=null!==(t=e.participantAttributes)&&void 0!==t?t:{};break;case"agentName":o.roomConfig=null!==(n=o.roomConfig)&&void 0!==n?n:new bn,0===o.roomConfig.agents.length&&o.roomConfig.agents.push(new Xt),o.roomConfig.agents[0].agentName=e.agentName;break;case"agentMetadata":o.roomConfig=null!==(i=o.roomConfig)&&void 0!==i?i:new bn,0===o.roomConfig.agents.length&&o.roomConfig.agents.push(new Xt),o.roomConfig.agents[0].metadata=e.agentMetadata;break;default:throw new Error("Options key ".concat(s," not being included in forming request!"))}return o}update(e){return Fi(this,void 0,void 0,(function*(){var t;const n=this.createRequestFromOptions(e),i=yield fetch(this.url,Object.assign(Object.assign({},this.endpointOptions),{method:null!==(t=this.endpointOptions.method)&&void 0!==t?t:"POST",headers:Object.assign({"Content-Type":"application/json"},this.endpointOptions.headers),body:n.toJsonString({useProtoFieldName:!0})}));if(!i.ok)throw new Error("Error generating token from endpoint ".concat(this.url,": received ").concat(i.status," / ").concat(yield i.text()));const o=yield i.json();return Si.fromJson(o,{ignoreUnknownFields:!0})}))}}class Ad extends xd{constructor(e,t){const{baseUrl:n="https://cloud-api.livekit.io"}=t,i=ji(t,["baseUrl"]);super("".concat(n,"/api/v2/sandbox/connection-details"),Object.assign(Object.assign({},i),{headers:{"X-Sandbox-ID":e}}))}}const Nd={literal:e=>new Dd(e),custom:e=>new Md(e),endpoint(e){return new xd(e,arguments.length>1&&void 0!==arguments[1]?arguments[1]:{})},sandboxTokenServer(e){return new Ad(e,arguments.length>1&&void 0!==arguments[1]?arguments[1]:{})}};const Ld=new Map([["obs virtual camera",{facingMode:"environment",confidence:"medium"}]]),Ud=new Map([["iphone",{facingMode:"environment",confidence:"medium"}],["ipad",{facingMode:"environment",confidence:"medium"}]]);function jd(e){var t;const n=e.trim().toLowerCase();if(""!==n)return Ld.has(n)?Ld.get(n):null===(t=Array.from(Ud.entries()).find((e=>{let[t]=e;return n.includes(t)})))||void 0===t?void 0:t[1]}e.BaseKeyProvider=la,e.Checker=cd,e.ConnectionCheck=kd,e.ConnectionError=ps,e.CriticalTimers=Ss,e.CryptorError=class extends ss{constructor(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:e.CryptorErrorReason.InternalError,i=arguments.length>2?arguments[2]:void 0;super(40,t),this.reason=n,this.participantIdentity=i}},e.DataPacket_Kind=yt,e.DataStreamError=Ts,e.DefaultReconnectPolicy=Ui,e.DeviceUnsupportedError=ms,e.DisconnectReason=nt,e.Encryption_Type=pt,e.ExternalE2EEKeyProvider=class extends la{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};super(Object.assign(Object.assign({},e),{sharedKey:!0,ratchetWindowSize:0,failureTolerance:-1}))}setKey(e){return Fi(this,void 0,void 0,(function*(){const t="string"==typeof e?yield ra(e):yield aa(e);this.onSetEncryptionKey(t)}))}},e.LivekitError=ss,e.LocalAudioTrack=lc,e.LocalParticipant=td,e.LocalTrack=dc,e.LocalTrackPublication=zc,e.LocalTrackRecorder=cc,e.LocalVideoTrack=Sc,e.Mutex=o,e.NegotiationError=ks,e.Participant=ed,e.ParticipantKind=ut,e.PublishDataError=class extends ss{constructor(e){super(14,null!=e?e:"unable to publish data"),this.name="PublishDataError"}},e.PublishTrackError=ys,e.RemoteAudioTrack=qc,e.RemoteParticipant=id,e.RemoteTrack=Vc,e.RemoteTrackPublication=nd,e.RemoteVideoTrack=Wc,e.Room=od,e.RpcError=tc,e.ScreenSharePresets=As,e.SignalReconnectError=Cs,e.SignalRequestError=bs,e.SimulatedError=class extends ss{constructor(){super(-1,arguments.length>0&&void 0!==arguments[0]?arguments[0]:"Simulated failure"),this.name="simulated"}},e.SubscriptionError=ot,e.TokenSource=Nd,e.TokenSourceConfigurable=bd,e.TokenSourceFixed=yd,e.Track=Ys,e.TrackInvalidError=gs,e.TrackPublication=Jc,e.TrackType=Xe,e.UnexpectedConnectionState=fs,e.UnsupportedServer=vs,e.VideoPreset=Es,e.VideoPresets=Ms,e.VideoPresets43=xs,e.areTokenSourceFetchOptionsEqual=function(e,t){const n=new Set([...Object.keys(e),...Object.keys(t)]);for(const i of n)switch(i){case"roomName":case"participantName":case"participantIdentity":case"participantMetadata":case"participantAttributes":case"agentName":case"agentMetadata":if(e[i]!==t[i])return!1;break;default:throw new Error("Options key ".concat(i," not being checked for equality!"))}return!0},e.asEncryptablePacket=da,e.attachToElement=Xs,e.attributes=ad,e.audioCodecs=ws,e.compareVersions=Tr,e.createAudioAnalyser=function(e,t){const n=Object.assign({cloneTrack:!1,fftSize:2048,smoothingTimeConstant:.8,minDecibels:-100,maxDecibels:-80},t),i=Fs();if(!i)throw new Error("Audio Context not supported on this browser");const o=n.cloneTrack?e.mediaStreamTrack.clone():e.mediaStreamTrack,s=i.createMediaStreamSource(new MediaStream([o])),r=i.createAnalyser();r.minDecibels=n.minDecibels,r.maxDecibels=n.maxDecibels,r.fftSize=n.fftSize,r.smoothingTimeConstant=n.smoothingTimeConstant,s.connect(r);const a=new Uint8Array(r.frequencyBinCount);return{calculateVolume:()=>{r.getByteFrequencyData(a);let e=0;for(const t of a)e+=Math.pow(t/255,2);return Math.sqrt(e/a.length)},analyser:r,cleanup:()=>Fi(this,void 0,void 0,(function*(){yield i.close(),n.cloneTrack&&o.stop()}))}},e.createE2EEKey=function(){return window.crypto.getRandomValues(new Uint8Array(32))},e.createKeyMaterialFromBuffer=aa,e.createKeyMaterialFromString=ra,e.createLocalAudioTrack=Xc,e.createLocalScreenTracks=function(e){return Fi(this,void 0,void 0,(function*(){if(void 0===e&&(e={}),void 0!==e.resolution||hr()||(e.resolution=As.h1080fps30.resolution),void 0===navigator.mediaDevices.getDisplayMedia)throw new ms("getDisplayMedia not supported");const t=qs(e),n=yield navigator.mediaDevices.getDisplayMedia(t),i=n.getVideoTracks();if(0===i.length)throw new gs("no video track found");const o=new Sc(i[0],void 0,!1);o.source=Ys.Source.ScreenShare;const s=[o];if(n.getAudioTracks().length>0){const e=new lc(n.getAudioTracks()[0],void 0,!1);e.source=Ys.Source.ScreenShareAudio,s.push(e)}return s}))},e.createLocalTracks=Qc,e.createLocalVideoTrack=Yc,e.decodeTokenPayload=Od,e.deriveKeys=function(e,t){return Fi(this,void 0,void 0,(function*(){const n=ca(e.algorithm.name,t),i=yield crypto.subtle.deriveKey(n,e,{name:Zr,length:128},!1,["encrypt","decrypt"]);return{material:e,encryptionKey:i}}))},e.detachTrack=Zs,e.facingModeFromDeviceLabel=jd,e.facingModeFromLocalTrack=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};var n;const i=Fr(e)?e.mediaStreamTrack:e,o=i.getSettings();let s={facingMode:null!==(n=t.defaultFacingMode)&&void 0!==n?n:"user",confidence:"low"};if("facingMode"in o){const e=o.facingMode;Di.trace("rawFacingMode",{rawFacingMode:e}),e&&"string"==typeof e&&function(e){const t=["user","environment","left","right"];return void 0===e||t.includes(e)}(e)&&(s={facingMode:e,confidence:"high"})}if(["low","medium"].includes(s.confidence)){Di.trace("Try to get facing mode from device label: (".concat(i.label,")"));const e=jd(i.label);void 0!==e&&(s=e)}return s},e.getBrowser=es,e.getEmptyAudioStreamTrack=Dr,e.getEmptyVideoStreamTrack=function(){return Ir||(Ir=_r()),Ir.clone()},e.getLogger=xi,e.importKey=function(e){return Fi(this,arguments,void 0,(function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{name:Zr},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"encrypt";return function*(){return crypto.subtle.importKey("raw",e,t,!1,"derive"===n?["deriveBits","deriveKey"]:["encrypt","decrypt"])}()}))},e.isAudioCodec=function(e){return ws.includes(e)},e.isAudioTrack=Br,e.isBackupCodec=Os,e.isBackupVideoCodec=Is,e.isBrowserSupported=ar,e.isE2EESupported=ia,e.isInsertableStreamSupported=sa,e.isLocalParticipant=Jr,e.isLocalTrack=Fr,e.isRemoteParticipant=function(e){return!e.isLocal},e.isRemoteTrack=Kr,e.isScriptTransformSupported=oa,e.isVideoCodec=xr,e.isVideoFrame=function(e){return"type"in e},e.isVideoTrack=Vr,e.needsRbspUnescaping=function(e){for(var t=0;t=3&&!e[i]&&!e[i+1]&&3==e[i+2]?(t.push(e[i++]),t.push(e[i++]),i++):t.push(e[i++]);return new Uint8Array(t)},e.protocolVersion=16,e.ratchet=function(e,t){return Fi(this,void 0,void 0,(function*(){const n=ca(e.algorithm.name,t);return crypto.subtle.deriveBits(n,e,256)}))},e.setLogExtension=function(t,n){(n?[n]:Mi).forEach((n=>{const i=n.methodFactory;n.methodFactory=(n,o,s)=>{const r=i(n,o,s),a=e.LogLevel[n],c=a>=o&&a{n?r(e,n):r(e),c&&t(a,e,n)}},n.setLevel(n.getLevel())}))},e.setLogLevel=function(e,t){if(t)_i.getLogger(t).setLevel(e);else for(const t of Mi)t.setLevel(e)},e.supportsAV1=ir,e.supportsAdaptiveStream=function(){return void 0!==typeof ResizeObserver&&void 0!==typeof IntersectionObserver},e.supportsAudioOutputSelection=function(){return rr()},e.supportsDynacast=function(){return tr()},e.supportsVP9=or,e.version=os,e.videoCodecs=Ps,e.writeRbsp=function(e){const t=[];for(var n=0,i=0;i=2&&(t.push(3),n=0),t.push(o),0==o?++n:n=0}return new Uint8Array(t)}})); +//# sourceMappingURL=livekit-client.umd.js.map diff --git a/mail_livekit/static/src/discuss/call_participant_video_patch.js b/mail_livekit/static/src/discuss/call_participant_video_patch.js new file mode 100644 index 00000000..0b9d45f0 --- /dev/null +++ b/mail_livekit/static/src/discuss/call_participant_video_patch.js @@ -0,0 +1,74 @@ +/** @odoo-module */ + +import {onWillUnmount, useExternalListener} from "@odoo/owl"; +import {CallParticipantVideo} from "@mail/discuss/call/common/call_participant_video"; +import {patch} from "@web/core/utils/patch"; + +patch(CallParticipantVideo.prototype, { + setup() { + super.setup(...arguments); + this.livekitTrack = null; + + // Subscribe to track rebind events + useExternalListener(this.env.bus, "LIVEKIT:TRACK:REBIND", (event) => { + const {sessionId, type} = event.detail; + if (this.props.session?.id === sessionId && this.props.type === type) { + console.log( + `LIVEKIT:TRACK:REBIND for session ${sessionId}, type ${type}` + ); + this._update(); + } + }); + + onWillUnmount(() => { + // Detach LiveKit track on unmount + if (this.livekitTrack && this.root.el) { + this.livekitTrack.detach(this.root.el); + } + this.livekitTrack = null; + }); + }, + + _update() { + if (!this.root.el) { + return; + } + + const rtcSession = this.props.session; + const type = this.props.type; + + if (!rtcSession) { + this.root.el.srcObject = undefined; + this.root.el.load(); + return; + } + + // Check for LiveKit track first + const livekitTrack = rtcSession.livekitTracks?.get(type); + + if (livekitTrack) { + console.log( + `Attaching LiveKit track for session ${rtcSession.id}, type ${type}` + ); + + // Detach old track if different + if (this.livekitTrack && this.livekitTrack !== livekitTrack) { + this.livekitTrack.detach(this.root.el); + } + + // Attach new LiveKit track directly to video element + livekitTrack.attach(this.root.el); + this.livekitTrack = livekitTrack; + + // Don't call load() - LiveKit handles playback + } else { + // Fallback to standard Odoo MediaStream pattern + if (rtcSession.getStream(type)) { + this.root.el.srcObject = rtcSession.getStream(type); + } else { + this.root.el.srcObject = undefined; + } + this.root.el.load(); + } + }, +}); diff --git a/mail_livekit/static/src/discuss/livekit_adapter.js b/mail_livekit/static/src/discuss/livekit_adapter.js new file mode 100644 index 00000000..c59f5197 --- /dev/null +++ b/mail_livekit/static/src/discuss/livekit_adapter.js @@ -0,0 +1,114 @@ +import {Source, livekitService} from "./livekit_service"; + +export class LiveKitAdapter { + livekitService = null; + _listeners = []; + _isDisconnecting = false; + + getSfuConsumerStats() { + return []; + } + + addSfu() { + return; + } + + removeSfu() { + return; + } + + addEventListener(name, f) { + this._listeners.push({name, f}); + } + + _emit(name, payload) { + if (this._isDisconnecting) return; + for (const {f} of this._listeners) { + f({detail: {name, payload}}); + } + } + + async updateUpload(source, track) { + const livekitSource = + source === "audio" + ? Source.MICROPHONE + : source === "camera" + ? Source.CAMERA + : Source.SCREEN; + livekitService?.setTrackEnabled(livekitSource, Boolean(track), track); + } + + updateDownload() { + // Implement selective subscription if needed + } + + updateInfo(info) { + livekitService.publishInfo(info); + } + + handleTrackSubscribed(participantId, source, track) { + if (source === Source.MICROPHONE) { + return this._emit("track", { + sessionId: participantId, + type: "audio", + track: track.mediaStreamTrack, + active: true, + }); + } + this._emit("trackSubscribed", { + sessionId: participantId, + type: source === Source.SCREEN ? "screen" : source, + track: track, + }); + } + + handleTrackMuted(participantId, source, track, muted) { + const type = + source === Source.MICROPHONE + ? "audio" + : source === Source.SCREEN + ? "screen" + : "camera"; + if (muted) { + return this._emit("track", { + sessionId: participantId, + type: type, + track: track, + active: false, + }); + } + return this.handleTrackSubscribed(participantId, source, track); + } + + addLivekitListeners() { + livekitService.subscribeToInfoChange("adapter", (info) => { + this._emit("info_change", info); + }); + livekitService.subscribeToTrackSubscribed( + "adapter", + (participantId, source, track) => + this.handleTrackSubscribed(participantId, source, track) + ); + livekitService.subscribeToTrackMuted( + "adapter", + (participantId, source, track, muted) => + this.handleTrackMuted(participantId, source, track, muted) + ); + } + + async connect(livekit_url, token) { + await livekitService?.connect(livekit_url, token); + this.addLivekitListeners(); + } + + async disconnect() { + this._isDisconnecting = true; + await livekitService?.disconnect(); + this._listeners = []; + this._isDisconnecting = false; + } + + isConnected() { + return livekitService.connected; + } +} diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js new file mode 100644 index 00000000..e321dd92 --- /dev/null +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -0,0 +1,232 @@ +const {Room, VideoPresets, RoomEvent} = window.LivekitClient; + +// This script should be the only contact point with Livekit SDK + +let debug = false; + +function log(...args) { + if (debug) { + console.log("[LivekitService]", ...args); + } +} + +class LivekitService { + room = null; + infoChangeListeners = new Map(); + trackSubscribedListeners = new Map(); + trackMutedListeners = new Map(); + containerElement = null; + initiated = false; + connected = false; + + _start() { + const urlParams = new URLSearchParams(window.location.search); + debug = urlParams.get("debug") !== null; + log("LivekitService started with debug =", debug); + } + + subscribeToTrackSubscribed(name, listener) { + this.trackSubscribedListeners.set(name, listener); + } + + handleTrackMuted(publication, participant) { + log("Track muted", publication, participant); + for (const listener of this.trackMutedListeners.values()) { + listener(participant.identity, publication.source, publication.track, true); + } + } + + handleTrackUnmuted(publication, participant) { + log("Track unmuted", publication, participant); + for (const listener of this.trackMutedListeners.values()) { + listener( + participant.identity, + publication.source, + publication.track, + false + ); + } + } + + handleTrackSubscribed(track, publication, participant) { + log("Track subscribed", track, publication, participant); + for (const listener of this.trackSubscribedListeners.values()) { + listener(participant.identity, publication.source, track); + } + } + + handleTrackUnsubscribed(track, publication, participant) { + log("Track unsubscribed", track, publication, participant); + track.detach(); + } + + handleLocalTrackUnpublished(publication, participant) { + log("Local track unpublished", publication, participant); + publication.track.detach(); + } + + handleActiveSpeakerChange(speakers) { + log("Active speakers changed", speakers); + } + + handleDisconnect() { + log("Disconnected from LiveKit room"); + } + + // Requires functions that accept info as parameter + subscribeToInfoChange(name, listener) { + log("Subscribing to info change:", name); + this.infoChangeListeners.set(name, listener); + } + + // Requires functions that accept info as parameter + subscribeToTrackMuted(name, listener) { + log("Subscribing to track muted:", name); + this.trackMutedListeners.set(name, listener); + } + + handleInfoChange(info) { + log("Info change received:", info); + for (const listener of this.infoChangeListeners.values()) { + listener(info); + } + } + + async connect(url, token) { + if (this.initiated || (this.room && this.room.isConnected)) { + log("Already connected or connecting to LiveKit"); + return; + } + + this.initiated = true; + this._start(); + log("Connecting to LiveKit:", url); + this.room = new Room({ + adaptiveStream: true, + dynacast: true, + videoCaptureDefaults: { + resolution: VideoPresets.h720.resolution, + }, + }); + + this.room.prepareConnection(url, token); + + this.room + .on(RoomEvent.TrackSubscribed, (...args) => + this.handleTrackSubscribed(...args) + ) + .on(RoomEvent.TrackUnsubscribed, (...args) => + this.handleTrackUnsubscribed(...args) + ) + .on(RoomEvent.ActiveSpeakersChanged, (...args) => + this.handleActiveSpeakerChange(...args) + ) + .on(RoomEvent.Disconnected, (...args) => this.handleDisconnect(...args)) + .on(RoomEvent.LocalTrackUnpublished, (...args) => + this.handleLocalTrackUnpublished(...args) + ) + .on(RoomEvent.DataReceived, (payload, participant) => { + if (!participant) return; + if (payload.byteLength === 0) return; + const data = JSON.parse(new TextDecoder().decode(payload)); + if (data.type === "info_change") { + this.handleInfoChange({[participant.identity]: data.info}); + } + }) + .on(RoomEvent.TrackMuted, (...args) => this.handleTrackMuted(...args)) + .on(RoomEvent.TrackUnmuted, (...args) => this.handleTrackUnmuted(...args)); + + try { + await this.room.connect(url, token); + log("Connected to LiveKit room"); + this.connected = true; + } catch (error) { + log("Failed to connect to LiveKit room:", error); + this.room = null; + } + } + + async disconnect() { + log("Clearing info change listeners"); + this.infoChangeListeners.clear(); + this.trackSubscribedListeners.clear(); + log("Disconnecting from LiveKit"); + await this.room?.disconnect(); + this.room = null; + this.initiated = false; + this.connected = false; + } + + async setCameraEnabled(enabled) { + log("Setting camera enabled:", enabled, this.room); + await this.room?.localParticipant?.setCameraEnabled(enabled); + } + + async setBlurEnabled(enabled) { + log("Setting blur enabled:", enabled, this.room); + } + + async setScreenShareEnabled(enabled) { + log("Setting screen share enabled:", enabled, this.room); + await this.room?.localParticipant?.setScreenShareEnabled(enabled); + } + + async setMicrophoneEnabled(enabled) { + log("Setting microphone enabled:", enabled, this.room); + await this.room?.localParticipant?.setMicrophoneEnabled(enabled); + } + + async setTrackEnabled(source, enabled, mediaStreamTrack = null) { + log("Setting track enabled:", source, enabled, this.room); + const publication = this.room?.localParticipant.getTrackPublication(source); + + if (mediaStreamTrack) { + if (enabled && !publication) { + log("Publishing new track for source:", source); + await this.room?.localParticipant.publishTrack(mediaStreamTrack, { + source, + }); + } else if (enabled && publication) { + await publication.track.replaceTrack(mediaStreamTrack); + publication?.track?.unmute(); + } + } else if (publication) { + await publication.track.mute(); + } + } + + getTrack(participantId, source) { + const participant = this.room?.remoteParticipants.get(participantId); + if (participant) { + const publication = participant.getTrackPublication(source); + return publication?.track; + } + return null; + } + + async publishInfo(info) { + log("Publishing info change:", info); + const data = JSON.stringify({type: "info_change", info}); + const payload = new TextEncoder().encode(data); + await this.room?.localParticipant.publishData(payload, {reliable: true}); + } + + async switchAudioInputDevice(deviceId) { + log("Switching audio input device to:", deviceId); + await this.room?.switchActiveDevice("audioinput", deviceId); + } +} + +export const livekitService = new LivekitService(); + +const Source = { + CAMERA: window.LivekitClient.Track.Source.Camera, + MICROPHONE: window.LivekitClient.Track.Source.Microphone, + SCREEN: window.LivekitClient.Track.Source.ScreenShare, +}; + +console.log("Livekit Source constants:", Source); + +Object.freeze(Source); + +export {Source}; diff --git a/mail_livekit/static/src/discuss/rtc_livekit_patch.js b/mail_livekit/static/src/discuss/rtc_livekit_patch.js new file mode 100644 index 00000000..f832ec2b --- /dev/null +++ b/mail_livekit/static/src/discuss/rtc_livekit_patch.js @@ -0,0 +1,210 @@ +/** @odoo-module */ +import {CONNECTION_TYPES, Rtc, rtcService} from "@mail/discuss/call/common/rtc_service"; +import {LiveKitAdapter} from "./livekit_adapter"; +import {PeerToPeer} from "@mail/discuss/call/common/peer_to_peer"; +import {RtcSession} from "@mail/discuss/call/common/rtc_session_model"; +import {Source} from "./livekit_service"; +import {_t} from "@web/core/l10n/translation"; +import {browser} from "@web/core/browser/browser"; +import {patch} from "@web/core/utils/patch"; + +patch(RtcSession.prototype, { + livekit_token: undefined, + livekit_room_name: undefined, + livekit_url: undefined, + + setup() { + super.setup(...arguments); + // Store LiveKit tracks separately from MediaStreams + this.livekitTracks = new Map(); + }, +}); + +patch(PeerToPeer.prototype, { + async handleNotification() { + console.log("message intercepted"); + }, + + _dataChannelupdateInBroadcast() { + console.log("message intercepted"); + }, +}); + +patch(Rtc.prototype, { + start() { + super.start(); + browser.addEventListener("pagehide", () => { + if (this.state.channel) { + const data = JSON.stringify({ + params: {channel_id: this.state.channel.id}, + }); + const blob = new Blob([data], {type: "application/json"}); + browser.navigator.sendBeacon("/mail/rtc/channel/leave_call", blob); + this.network?.disconnect(); + } + }); + }, + + async _initConnection() { + this.selfSession.connectionState = "selecting network type"; + this.network?.disconnect(); + this.network = new LiveKitAdapter(); + this.state.connectionType = CONNECTION_TYPES.SERVER; + + this.network.addEventListener("update", (event) => { + try { + this._handleNetworkUpdates(event); + } catch (error) { + if (!error.message?.includes("closed")) { + console.error("Error in network update:", error); + } + } + }); + this.network.addEventListener("updateTrack", async (event) => { + if (event.detail.name === "trackSubscribed") { + const {sessionId, type, track} = event.detail.payload; + console.log( + `Track subscribed for session ${sessionId}, type ${type}. Triggering rebind.` + ); + const rtcSession = await this.store.RtcSession.getWhenReady(sessionId); + + // Store LiveKit track separately + rtcSession.livekitTracks.set(type, track); + + // Create dummy MediaStream for UI rendering (hasVideo check) + const dummyStream = new window.MediaStream(); + rtcSession.videoStreams.set(type, dummyStream); + await rtcSession.updateStreamState(type, true); + + // Trigger bus event to notify CallParticipantVideo to attach track + this.store.env.bus.trigger("LIVEKIT:TRACK:REBIND", { + sessionId: rtcSession.id, + type: type, + }); + } + }); + if (this.state.channel) { + await this.call(); + await this.updateUpload(); + } + }, + + async updateUpload() { + console.log("Updating uploads for tracks..."); + await this.network?.updateUpload(Source.MICROPHONE, this.state.audioTrack); + await this.network?.updateUpload(Source.CAMERA, this.state.cameraTrack); + await this.network?.updateUpload(Source.SCREEN, this.state.screenTrack); + + // Trigger rebind for local tracks after upload + if (this.selfSession) { + this.store.env.bus.trigger("LIVEKIT:TRACK:REBIND", { + sessionId: this.selfSession.id, + type: "local", + }); + } + }, + + async call() { + if (this.network.isConnected()) { + return; + } + try { + console.log("Connecting to LiveKit server..."); + await this.network.connect( + this.selfSession.livekit_url, + this.selfSession.livekit_token + ); + this.selfSession.connectionState = "connected"; + } catch (error) { + console.error("Failed to connect to LiveKit server:", error); + this.selfSession.connectionState = "failed"; + } + }, + + async _loadSfu() { + // No-op + }, + + _handleSfuClientStateChange() { + // No-op + }, + + async _upgradeConnection() { + // No-op + }, + + async _downgradeConnection() { + // No-op + }, + + async leaveCall(...args) { + this.network?.disconnect(); + return super.leaveCall(...args); + }, + + updateActiveSession(session, videoType, {addVideo = false} = {}) { + this.state.channel ??= session.channel; + return super.updateActiveSession(session, videoType, {addVideo}); + }, + + clear() { + this.network?.disconnect(); + return super.clear(); + }, +}); + +patch(rtcService, { + dependencies: [ + "bus_service", + "discuss.p2p", + "discuss.ptt_extension", + "mail.sound_effects", + "mail.store", + "notification", + ], + start(env, services) { + const store = env.services["mail.store"]; + const rtc = store.rtc; + + rtc.bus = services.bus_service; + rtc.p2pService = services["discuss.p2p"]; + rtc.p2pService.acceptOffer = async () => { + // Always reject P2P offers when LiveKit is enabled + return false; + }; + services.bus_service.subscribe( + "discuss.channel.rtc.session/sfu_hot_swap", + async () => { + // Ignore SFU hot-swap for LiveKit + } + ); + services.bus_service.subscribe( + "discuss.channel.rtc.session/ended", + ({sessionId}) => { + if (rtc.selfSession?.id === sessionId) { + rtc.endCall(); + services.notification.add( + _t("Disconnected from the RTC call by the server"), + { + type: "warning", + } + ); + } + } + ); + services.bus_service.subscribe("res.users.settings.volumes", (payload) => { + if (payload) { + rtc.store.Volume.insert(payload); + } + }); + services.bus_service.subscribe( + "discuss.channel.rtc.session/update_and_broadcast", + (payload) => { + const {data} = payload; + // Apply updates even for active channel since LiveKit does not use P2P for real-time + rtc.store.insert(data); + } + ); + return rtc; + }, +}); diff --git a/mail_livekit/static/src/discuss/thread_actions_patch.js b/mail_livekit/static/src/discuss/thread_actions_patch.js new file mode 100644 index 00000000..c70f052d --- /dev/null +++ b/mail_livekit/static/src/discuss/thread_actions_patch.js @@ -0,0 +1,19 @@ +/** @odoo-module */ +import {patch} from "@web/core/utils/patch"; +import {threadActionsRegistry} from "@mail/core/common/thread_actions"; + +// Extend the "settings" action condition to also show in the Discuss app +const settingsAction = threadActionsRegistry.get("settings"); +if (settingsAction) { + const originalCondition = settingsAction.condition; + patch(settingsAction, { + condition(component) { + const baseCondition = originalCondition.call(this, component); + // Also allow settings in the Discuss app + return ( + baseCondition || + (component.thread?.allowCalls && component.env.inDiscussApp) + ); + }, + }); +} diff --git a/mail_livekit/streamIssue.md b/mail_livekit/streamIssue.md new file mode 100644 index 00000000..6be13007 --- /dev/null +++ b/mail_livekit/streamIssue.md @@ -0,0 +1,38 @@ +Problem Summary: "Skipping incoming track as it already ended" The Error Receiver side +error: "skipping incoming track as it already ended" + +Occurs when sender toggles camera on Appears in receiver's console, not sender's Video +feed breaks for receivers Root Cause Identified Odoo's behavior when toggling camera: + +Camera OFF: Odoo calls updateUpload("camera", undefined) → triggers unpublish Camera ON: +Odoo calls updateUpload("camera", newTrack) → triggers publish with brand new +MediaStreamTrack (different ID) Odoo immediately stops the old track after creating the +new one (via setVideo() or closeStream()) The race condition: + +LiveKit unpublishes old track → publishes new track (async operations) Meanwhile, Odoo +stops the MediaStreamTrack we're trying to publish Track ends before/during LiveKit's +publish operation Receivers attempt to subscribe to an already-ended track What We've +Tried (All Failed) Track cloning - Clone tracks immediately to prevent Odoo from +stopping them + +Result: Clones still end somehow Delayed unpublish - Wait 500ms before unpublishing to +give receivers time + +Result: Error persists Keep old clones alive - Don't stop old clones, accumulate them + +Result: Error persists Use replaceTrack() - Avoid unpublish/publish cycle, keep same +publication + +Current approach: Uses LiveKit's LocalTrack.replaceTrack() to swap underlying +MediaStreamTrack Result: Unknown (just implemented) Key Observations from Logs This +suggests: The track is alive when published on sender side, but ends between publish and +receiver subscription. + +The Critical Question Why does the track end after successful publish? + +Is Odoo stopping it even after we clone it? Is the clone somehow linked to the +original's lifecycle? Is LiveKit stopping it during internal operations? Is there a +timing issue with the WebRTC negotiation? Expected Behavior When sender toggles camera: + +Old video publication should be replaced seamlessly Receivers should receive a live +track Video should continue without interruption diff --git a/mail_livekit/views/livekit_assets_templates.xml b/mail_livekit/views/livekit_assets_templates.xml new file mode 100644 index 00000000..d214c3f4 --- /dev/null +++ b/mail_livekit/views/livekit_assets_templates.xml @@ -0,0 +1,66 @@ + + + + + + + + diff --git a/mail_livekit/views/res_config_settings_views.xml b/mail_livekit/views/res_config_settings_views.xml new file mode 100644 index 00000000..7b7a7cbc --- /dev/null +++ b/mail_livekit/views/res_config_settings_views.xml @@ -0,0 +1,81 @@ + + + + res.config.settings.view.form.inherit.livekit + res.config.settings + + + +
+

LiveKit Video Conferencing

+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ Configure your LiveKit credentials to enable video conferencing in Discuss channels. + Get your credentials from your LiveKit Cloud dashboard or self-hosted server. +
+
+
+
+
+
+
+
+
+
diff --git a/requirements.txt b/requirements.txt index e69de29b..ed27228a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -0,0 +1 @@ +livekit-api==1.1.0 From 02a47ca0d0790decb4a16171fe7dd7b77a6b061f Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 17:05:33 +0000 Subject: [PATCH 02/33] updated readme --- mail_livekit/README.md | 125 ++++++++++++++++++++++++++++------------- 1 file changed, 86 insertions(+), 39 deletions(-) diff --git a/mail_livekit/README.md b/mail_livekit/README.md index 5a9b24da..02996e58 100644 --- a/mail_livekit/README.md +++ b/mail_livekit/README.md @@ -1,32 +1,69 @@ # Discuss LiveKit Integration (Odoo 18) -This addon integrates **LiveKit** as the media layer (audio/video/screen share) for -**Odoo Discuss calls**, while keeping Odoo’s **native call UI and semantics**. - -It is designed to be safe to install even when LiveKit is not configured. When livekit -has credentials and is enabled its assets will be added to the relevant pages. Upon -toggling livekit, it may be necessary to hard refresh the browser to ensure assets are -reloaded. - -## What it does - -- Replaces the underlying RTC media transport with **LiveKit Rooms**. -- Mirrors LiveKit participation into Odoo’s mail store as **synthetic RTC sessions**, so - the standard Discuss call UI renders normally. - -## Features - -- **Audio + video + group calls** via LiveKit. -- **Screen sharing** bridged into the standard UI. -- **Background blur** using LiveKit track processors (applies immediately). -- **Microphone input selection** (uses Odoo’s existing “Input device” setting and - hot-switches while in-call). -- **Multi-tab coordination** (host/follower model): only one tab publishes media for a - channel. -- **Reconnection handling**: maps LiveKit connection states into the native UI and - avoids excessive toasts. -- **Call invitations / ringing** semantics: triggers the stock incoming call UI/sound - when a call starts in non-channel threads. +This addon integrates **LiveKit** as the WebRTC transport layer for **Odoo Discuss +calls**, replacing Odoo's built-in P2P and SFU connections while preserving the native +call UI and user experience. + +## Architecture + +### Core Components + +The integration uses a layered architecture that bridges LiveKit's media handling with +Odoo's RTC semantics: + +**LiveKit Service** (`livekit_service.js`) + +- Singleton wrapper around LiveKit SDK Room API +- Manages connection lifecycle, track publishing, and event subscriptions +- Provides abstraction for camera, microphone, and screen share controls +- Handles LiveKit-specific events (TrackSubscribed, TrackMuted, etc.) + +**LiveKit Adapter** (`livekit_adapter.js`) + +- Translates between LiveKit events and Odoo's Network interface +- Emits Odoo-compatible events (`track`, `trackSubscribed`, `info_change`) +- Maps LiveKit Source types (CAMERA, MICROPHONE, SCREEN) to Odoo types (camera, audio, + screen) +- Handles audio track special case (uses MediaStreamTrack for Odoo audio processing) + +**RTC Patch** (`rtc_livekit_patch.js`) + +- Patches Odoo's `Rtc` and `RtcSession` models to use LiveKit +- Replaces `_initConnection()` to instantiate LiveKitAdapter instead of P2P/SFU +- Disables P2P offer acceptance and SFU hot-swap handling +- Stores LiveKit tracks in separate Map (`session.livekitTracks`) +- Creates dummy MediaStream for UI rendering while actual video uses LiveKit tracks +- Implements event-driven track binding via `LIVEKIT:TRACK:REBIND` bus events + +**Video Component Patch** (`call_participant_video_patch.js`) + +- Patches `CallParticipantVideo` to handle LiveKit track attachment +- Overrides `_update()` to use LiveKit's `track.attach()` API directly +- Listens for `LIVEKIT:TRACK:REBIND` events to rebind tracks on changes +- Properly detaches tracks on component unmount to prevent memory leaks + +### Track Lifecycle + +**Video/Screen Tracks:** + +1. LiveKit emits `TrackSubscribed` event with LiveKit Track object +2. Adapter forwards to RTC patch as `trackSubscribed` event +3. RTC patch stores track in `session.livekitTracks` Map +4. RTC patch creates dummy MediaStream in `session.videoStreams` (triggers UI rendering) +5. RTC patch fires `LIVEKIT:TRACK:REBIND` bus event +6. CallParticipantVideo receives event and calls `_update()` +7. `_update()` checks for LiveKit track and uses `track.attach(videoElement)` directly + +**Audio Tracks:** + +- Uses MediaStreamTrack extraction for compatibility with Odoo's audio processing +- Flows through standard Odoo RTC track handling + +**Why Dummy MediaStream?** + +- Odoo's UI checks `hasVideo` which requires `videoStream` existence +- LiveKit tracks must use `.attach()` API, not MediaStream `srcObject` +- Solution: dummy stream for rendering triggers, LiveKit track for actual video ## Configuration @@ -41,25 +78,35 @@ Configure in **Settings → LiveKit Integration**: ### `ir.config_parameter` keys -This addon reads the following configuration parameters: - - `mail_livekit.livekit_enabled` (boolean) - `mail_livekit.livekit_server_url` (string) - `mail_livekit.livekit_api_key` (string) - `mail_livekit.livekit_api_secret` (string) -## Notes +## Implementation Notes + +### Dual Storage Pattern + +RtcSession maintains two track storage systems: + +- `videoStreams` (Map): Dummy MediaStreams for UI rendering compatibility +- `livekitTracks` (Map): Actual LiveKit Track objects for video attachment + +### Event Bus Pattern + +Uses Odoo's `env.bus` for event propagation: + +- `store.env.bus.trigger("LIVEKIT:TRACK:REBIND", {sessionId, type})` +- `useExternalListener(this.env.bus, "LIVEKIT:TRACK:REBIND", callback)` -- **Public channels / guests** are supported. -- **Only microphone selection is implemented** (parity with the existing Odoo call - settings UI). Camera/speaker selection are intentionally not added. +This matches Odoo's existing patterns (e.g., `RTC-SERVICE:PLAY_MEDIA`) -### Bundled vendor JS +### Bundled Livekit SDK 2.17 -This repo includes a small bundling setup that produces a browser-ready vendor bundle: +- Includes LiveKit client SDK and processors -- Output: `static/lib/bundles/livekit_vendor_entry.js` -- Build: `npm install` then `npm run bundle:livekit` +## Limitations -- If you upgrade LiveKit, upgrade both the client and processors together and test - reconnect + screen share paths. +- P2P connections are disabled when LiveKit is active +- SFU hot-swap is not applicable (LiveKit maintains single connection) +- Microphone device switching implemented; camera/speaker selection not added From ae002726384fe2fd5e1ca4000d004aebb8626709 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 17:28:35 +0000 Subject: [PATCH 03/33] imporved muting --- mail_livekit/static/src/discuss/livekit_service.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index e321dd92..2cfc3065 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -58,6 +58,9 @@ class LivekitService { handleTrackUnsubscribed(track, publication, participant) { log("Track unsubscribed", track, publication, participant); track.detach(); + for (const listener of this.trackMutedListeners.values()) { + listener(participant.identity, publication.source, publication.track, true); + } } handleLocalTrackUnpublished(publication, participant) { From 56b9c225ab4879f90f5cf175909d1f65c907b2aa Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 17:34:36 +0000 Subject: [PATCH 04/33] null check --- mail_livekit/__manifest__.py | 2 +- mail_livekit/static/src/discuss/rtc_livekit_patch.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mail_livekit/__manifest__.py b/mail_livekit/__manifest__.py index 323d5b1b..104cb505 100644 --- a/mail_livekit/__manifest__.py +++ b/mail_livekit/__manifest__.py @@ -1,7 +1,7 @@ { "name": "Discuss - Livekit Integration", "summary": "Integrate LiveKit video conferencing with Odoo Discuss", - "version": "18.0.1.0.0", + "version": "18.0.1.0.1", "author": "Odoo Community Association (OCA), Solvti Sp. z o.o.", "license": "LGPL-3", "category": "Discuss", diff --git a/mail_livekit/static/src/discuss/rtc_livekit_patch.js b/mail_livekit/static/src/discuss/rtc_livekit_patch.js index f832ec2b..a5dcd96f 100644 --- a/mail_livekit/static/src/discuss/rtc_livekit_patch.js +++ b/mail_livekit/static/src/discuss/rtc_livekit_patch.js @@ -105,7 +105,7 @@ patch(Rtc.prototype, { }, async call() { - if (this.network.isConnected()) { + if (this.network?.isConnected()) { return; } try { From 5b77aa01592c7823a6ea8ab8b46c72235bf9c780 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 17:40:13 +0000 Subject: [PATCH 05/33] add UI check --- mail_livekit/static/src/discuss/livekit_service.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index 2cfc3065..d7a0bb1e 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -137,7 +137,12 @@ class LivekitService { } }) .on(RoomEvent.TrackMuted, (...args) => this.handleTrackMuted(...args)) - .on(RoomEvent.TrackUnmuted, (...args) => this.handleTrackUnmuted(...args)); + .on(RoomEvent.TrackUnmuted, (...args) => this.handleTrackUnmuted(...args)) + .on(RoomEvent.AudioPlaybackStatusChanged, () => { + if (!this.room?.canPlaybackAudio) { + log("Issue with audi playback: requires UI interaction"); + } + }); try { await this.room.connect(url, token); From 13e91639011f4c9e86dda75612841cc2cadaa4d9 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 18:52:01 +0000 Subject: [PATCH 06/33] add audio element to DOM --- .../static/src/discuss/livekit_service.js | 26 +++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index d7a0bb1e..4cb5b6f1 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -50,6 +50,10 @@ class LivekitService { handleTrackSubscribed(track, publication, participant) { log("Track subscribed", track, publication, participant); + if (track.kind == "audio") { + log("Attaching audio track to DOM"); + document.body.appendChild(track.attach()); + } for (const listener of this.trackSubscribedListeners.values()) { listener(participant.identity, publication.source, track); } @@ -165,25 +169,6 @@ class LivekitService { this.connected = false; } - async setCameraEnabled(enabled) { - log("Setting camera enabled:", enabled, this.room); - await this.room?.localParticipant?.setCameraEnabled(enabled); - } - - async setBlurEnabled(enabled) { - log("Setting blur enabled:", enabled, this.room); - } - - async setScreenShareEnabled(enabled) { - log("Setting screen share enabled:", enabled, this.room); - await this.room?.localParticipant?.setScreenShareEnabled(enabled); - } - - async setMicrophoneEnabled(enabled) { - log("Setting microphone enabled:", enabled, this.room); - await this.room?.localParticipant?.setMicrophoneEnabled(enabled); - } - async setTrackEnabled(source, enabled, mediaStreamTrack = null) { log("Setting track enabled:", source, enabled, this.room); const publication = this.room?.localParticipant.getTrackPublication(source); @@ -193,12 +178,15 @@ class LivekitService { log("Publishing new track for source:", source); await this.room?.localParticipant.publishTrack(mediaStreamTrack, { source, + simulcast: true, }); } else if (enabled && publication) { + log("Replacing track for source:", source); await publication.track.replaceTrack(mediaStreamTrack); publication?.track?.unmute(); } } else if (publication) { + log("Muting/unmuting existing track for source:", source); await publication.track.mute(); } } From 7a01676459dee7e6338010bc305fc788c07e5de6 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 18:58:17 +0000 Subject: [PATCH 07/33] null check --- mail_livekit/static/src/discuss/rtc_livekit_patch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mail_livekit/static/src/discuss/rtc_livekit_patch.js b/mail_livekit/static/src/discuss/rtc_livekit_patch.js index a5dcd96f..129f7e44 100644 --- a/mail_livekit/static/src/discuss/rtc_livekit_patch.js +++ b/mail_livekit/static/src/discuss/rtc_livekit_patch.js @@ -105,7 +105,7 @@ patch(Rtc.prototype, { }, async call() { - if (this.network?.isConnected()) { + if (!this.network || this.network.isConnected()) { return; } try { From 75b2fa4ec64518e30949581513698ba8274e3876 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 19:10:13 +0000 Subject: [PATCH 08/33] updated manifest --- mail_livekit/__manifest__.py | 2 +- odoo.conf | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 odoo.conf diff --git a/mail_livekit/__manifest__.py b/mail_livekit/__manifest__.py index 104cb505..a8099bb5 100644 --- a/mail_livekit/__manifest__.py +++ b/mail_livekit/__manifest__.py @@ -6,7 +6,7 @@ "license": "LGPL-3", "category": "Discuss", "depends": ["mail"], - "website": "https://www.solvti.com", + "website": "https://github.com/Nitrokey/odoo-modules/", "data": [ "views/res_config_settings_views.xml", "views/livekit_assets_templates.xml", diff --git a/odoo.conf b/odoo.conf new file mode 100644 index 00000000..b110b1c9 --- /dev/null +++ b/odoo.conf @@ -0,0 +1,26 @@ +[options] +admin_passwd = odoo +db_host = postgres +db_port = 5432 +db_user = odoo +db_password = odoo +db_name = lkint +http_port = 8069 +gevent_port = 8072 +data_dir = /code/data +addons_path = + /code/odoo/addons, + /code/enterprise, + /code/design-themes, + /code/repos/tutorials, + /code/repos/nitrokey-odoo-modules, +list_db = False +limit_time_real = 2000 +limit_time_cpu = 2000 +#dev_mode = True +#server_wide_modules = web,queue_job +# workers = 2 +# proxy_mode = True + +# [queue_job] +# channels = root:2 From fd9f0102708a1b87bce6f6685e4ac4f4109fbae1 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 19:39:17 +0000 Subject: [PATCH 09/33] added additional mute handling --- .../static/src/discuss/livekit_service.js | 19 +++++++++++++- odoo.conf | 26 ------------------- 2 files changed, 18 insertions(+), 27 deletions(-) delete mode 100644 odoo.conf diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index 4cb5b6f1..a01ff3f4 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -183,7 +183,9 @@ class LivekitService { } else if (enabled && publication) { log("Replacing track for source:", source); await publication.track.replaceTrack(mediaStreamTrack); - publication?.track?.unmute(); + if (publication.mediaStreamTrack.enabled) { + publication?.track?.unmute(); + } } } else if (publication) { log("Muting/unmuting existing track for source:", source); @@ -205,6 +207,21 @@ class LivekitService { const data = JSON.stringify({type: "info_change", info}); const payload = new TextEncoder().encode(data); await this.room?.localParticipant.publishData(payload, {reliable: true}); + await this.setMicrophoneMuted(info.isSelfMuted); + } + + async setMicrophoneMuted(muted) { + log("Setting microphone mute to:", muted); + const publication = this.room?.localParticipant.getTrackPublication( + window.LivekitClient.Track.Source.Microphone + ); + if (publication && publication.track.isMuted !== muted) { + if (muted) { + await publication.track.mute(); + } else { + await publication.track.unmute(); + } + } } async switchAudioInputDevice(deviceId) { diff --git a/odoo.conf b/odoo.conf deleted file mode 100644 index b110b1c9..00000000 --- a/odoo.conf +++ /dev/null @@ -1,26 +0,0 @@ -[options] -admin_passwd = odoo -db_host = postgres -db_port = 5432 -db_user = odoo -db_password = odoo -db_name = lkint -http_port = 8069 -gevent_port = 8072 -data_dir = /code/data -addons_path = - /code/odoo/addons, - /code/enterprise, - /code/design-themes, - /code/repos/tutorials, - /code/repos/nitrokey-odoo-modules, -list_db = False -limit_time_real = 2000 -limit_time_cpu = 2000 -#dev_mode = True -#server_wide_modules = web,queue_job -# workers = 2 -# proxy_mode = True - -# [queue_job] -# channels = root:2 From e67797e88e4bd5cd9cca2cf2198aa939c91f62ae Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 19:43:44 +0000 Subject: [PATCH 10/33] added additional mute handling --- mail_livekit/static/src/discuss/livekit_service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index a01ff3f4..57009bf8 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -183,7 +183,7 @@ class LivekitService { } else if (enabled && publication) { log("Replacing track for source:", source); await publication.track.replaceTrack(mediaStreamTrack); - if (publication.mediaStreamTrack.enabled) { + if (mediaStreamTrack?.enabled) { publication?.track?.unmute(); } } From 6191fa204e96146bc373d3db84b14d9d3fcb867c Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 19:49:35 +0000 Subject: [PATCH 11/33] added additional mute handling --- mail_livekit/static/src/discuss/livekit_service.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index 57009bf8..b817b6fc 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -183,7 +183,11 @@ class LivekitService { } else if (enabled && publication) { log("Replacing track for source:", source); await publication.track.replaceTrack(mediaStreamTrack); - if (mediaStreamTrack?.enabled) { + if ( + mediaStreamTrack?.enabled || + publication.track.source !== + window.LivekitClient.Track.Source.Microphone + ) { publication?.track?.unmute(); } } From 603551a1a16fc9d6137d9cb408d81dc9346e5d01 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 20:11:01 +0000 Subject: [PATCH 12/33] improved clean up --- mail_livekit/static/src/discuss/livekit_adapter.js | 6 +++--- mail_livekit/static/src/discuss/rtc_livekit_patch.js | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/mail_livekit/static/src/discuss/livekit_adapter.js b/mail_livekit/static/src/discuss/livekit_adapter.js index c59f5197..255ed146 100644 --- a/mail_livekit/static/src/discuss/livekit_adapter.js +++ b/mail_livekit/static/src/discuss/livekit_adapter.js @@ -51,13 +51,13 @@ export class LiveKitAdapter { return this._emit("track", { sessionId: participantId, type: "audio", - track: track.mediaStreamTrack, - active: true, + track: track?.mediaStreamTrack, + active: !track?.isMuted, }); } this._emit("trackSubscribed", { sessionId: participantId, - type: source === Source.SCREEN ? "screen" : source, + type: source === Source.SCREEN ? "screen" : "camera", track: track, }); } diff --git a/mail_livekit/static/src/discuss/rtc_livekit_patch.js b/mail_livekit/static/src/discuss/rtc_livekit_patch.js index 129f7e44..58d2f1f6 100644 --- a/mail_livekit/static/src/discuss/rtc_livekit_patch.js +++ b/mail_livekit/static/src/discuss/rtc_livekit_patch.js @@ -149,6 +149,12 @@ patch(Rtc.prototype, { clear() { this.network?.disconnect(); + for (const session of this.state.channel.rtcSessions) { + session.livekitTracks.clear(); + } + if (this.selfSession?.livekitTracks) { + this.selfSession.livekitTracks.clear(); + } return super.clear(); }, }); From ec67a70c36740fe86f7c677b37d0d73bef5f8f21 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 20:14:57 +0000 Subject: [PATCH 13/33] nullcheck --- mail_livekit/static/src/discuss/rtc_livekit_patch.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mail_livekit/static/src/discuss/rtc_livekit_patch.js b/mail_livekit/static/src/discuss/rtc_livekit_patch.js index 58d2f1f6..6b9b6f31 100644 --- a/mail_livekit/static/src/discuss/rtc_livekit_patch.js +++ b/mail_livekit/static/src/discuss/rtc_livekit_patch.js @@ -149,8 +149,10 @@ patch(Rtc.prototype, { clear() { this.network?.disconnect(); - for (const session of this.state.channel.rtcSessions) { - session.livekitTracks.clear(); + if (this.state.channel) { + for (const session of this.state.channel.rtcSessions) { + session.livekitTracks.clear(); + } } if (this.selfSession?.livekitTracks) { this.selfSession.livekitTracks.clear(); From 76fd25e8ad07b5086523582616278b53dd8e0879 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 21:04:23 +0000 Subject: [PATCH 14/33] address various possible errors --- .../static/src/discuss/livekit_adapter.js | 2 +- .../static/src/discuss/livekit_service.js | 78 +++++++++++++++---- .../static/src/discuss/rtc_livekit_patch.js | 41 +++++++++- 3 files changed, 100 insertions(+), 21 deletions(-) diff --git a/mail_livekit/static/src/discuss/livekit_adapter.js b/mail_livekit/static/src/discuss/livekit_adapter.js index 255ed146..9682f8dd 100644 --- a/mail_livekit/static/src/discuss/livekit_adapter.js +++ b/mail_livekit/static/src/discuss/livekit_adapter.js @@ -35,7 +35,7 @@ export class LiveKitAdapter { : source === "camera" ? Source.CAMERA : Source.SCREEN; - livekitService?.setTrackEnabled(livekitSource, Boolean(track), track); + await livekitService?.setTrackEnabled(livekitSource, Boolean(track), track); } updateDownload() { diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index b817b6fc..bfcd3c30 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -19,6 +19,10 @@ class LivekitService { initiated = false; connected = false; + _get_audio_element(identity) { + return document.getElementById(`livekit-audio-${identity}`); + } + _start() { const urlParams = new URLSearchParams(window.location.search); debug = urlParams.get("debug") !== null; @@ -49,10 +53,23 @@ class LivekitService { } handleTrackSubscribed(track, publication, participant) { + if ( + this.room?.localParticipant && + participant.sid === this.room.localParticipant.sid + ) { + log("Ignoring own track subscription"); + return; + } + log("Track subscribed", track, publication, participant); + if (track.kind == "audio") { - log("Attaching audio track to DOM"); - document.body.appendChild(track.attach()); + let audioElement = this._get_audio_element(participant.identity); + audioElement?.remove(); + + audioElement = track.attach(); + audioElement.id = `livekit-audio-${participant.identity}`; + document.body.appendChild(audioElement); } for (const listener of this.trackSubscribedListeners.values()) { listener(participant.identity, publication.source, track); @@ -62,6 +79,12 @@ class LivekitService { handleTrackUnsubscribed(track, publication, participant) { log("Track unsubscribed", track, publication, participant); track.detach(); + + if (track.kind === "audio") { + const audioElement = this._get_audio_element(participant.identity); + audioElement?.remove(); + } + for (const listener of this.trackMutedListeners.values()) { listener(participant.identity, publication.source, publication.track, true); } @@ -78,6 +101,7 @@ class LivekitService { handleDisconnect() { log("Disconnected from LiveKit room"); + this.connected = false; } // Requires functions that accept info as parameter @@ -116,7 +140,7 @@ class LivekitService { }, }); - this.room.prepareConnection(url, token); + await this.room.prepareConnection(url, token); this.room .on(RoomEvent.TrackSubscribed, (...args) => @@ -144,7 +168,7 @@ class LivekitService { .on(RoomEvent.TrackUnmuted, (...args) => this.handleTrackUnmuted(...args)) .on(RoomEvent.AudioPlaybackStatusChanged, () => { if (!this.room?.canPlaybackAudio) { - log("Issue with audi playback: requires UI interaction"); + log("Issue with audio playback: requires UI interaction"); } }); @@ -162,36 +186,52 @@ class LivekitService { log("Clearing info change listeners"); this.infoChangeListeners.clear(); this.trackSubscribedListeners.clear(); + this.trackMutedListeners.clear(); log("Disconnecting from LiveKit"); - await this.room?.disconnect(); + + if (this.room) { + for (const [, participant] of this.room.remoteParticipants) { + const audioElement = this._get_audio_element(participant.identity); + audioElement?.remove(); + } + } + const roomToDisconnect = this.room; this.room = null; this.initiated = false; this.connected = false; + + if (roomToDisconnect) { + await roomToDisconnect.disconnect(); + } } async setTrackEnabled(source, enabled, mediaStreamTrack = null) { log("Setting track enabled:", source, enabled, this.room); + if (!this.room?.localParticipant) { + log("Cannot set track - no local participant"); + return; + } const publication = this.room?.localParticipant.getTrackPublication(source); - if (mediaStreamTrack) { - if (enabled && !publication) { + if (mediaStreamTrack && enabled) { + if (!publication) { log("Publishing new track for source:", source); await this.room?.localParticipant.publishTrack(mediaStreamTrack, { source, - simulcast: true, + simulcast: source !== window.LivekitClient.Track.Source.Microphone, // Only use simulcast for video }); - } else if (enabled && publication) { + } else if (publication.track) { log("Replacing track for source:", source); await publication.track.replaceTrack(mediaStreamTrack); if ( - mediaStreamTrack?.enabled || publication.track.source !== - window.LivekitClient.Track.Source.Microphone + window.LivekitClient.Track.Source.Microphone || + mediaStreamTrack?.enabled ) { publication?.track?.unmute(); } } - } else if (publication) { + } else if (!enabled && publication?.track) { log("Muting/unmuting existing track for source:", source); await publication.track.mute(); } @@ -208,10 +248,14 @@ class LivekitService { async publishInfo(info) { log("Publishing info change:", info); - const data = JSON.stringify({type: "info_change", info}); - const payload = new TextEncoder().encode(data); - await this.room?.localParticipant.publishData(payload, {reliable: true}); - await this.setMicrophoneMuted(info.isSelfMuted); + try { + const data = JSON.stringify({type: "info_change", info}); + const payload = new TextEncoder().encode(data); + await this.room?.localParticipant.publishData(payload, {reliable: true}); + await this.setMicrophoneMuted(info.isSelfMuted); + } catch (error) { + log("Error publishing info:", error); + } } async setMicrophoneMuted(muted) { @@ -219,7 +263,7 @@ class LivekitService { const publication = this.room?.localParticipant.getTrackPublication( window.LivekitClient.Track.Source.Microphone ); - if (publication && publication.track.isMuted !== muted) { + if (publication?.track && publication.track.isMuted !== muted) { if (muted) { await publication.track.mute(); } else { diff --git a/mail_livekit/static/src/discuss/rtc_livekit_patch.js b/mail_livekit/static/src/discuss/rtc_livekit_patch.js index 6b9b6f31..4cfdd473 100644 --- a/mail_livekit/static/src/discuss/rtc_livekit_patch.js +++ b/mail_livekit/static/src/discuss/rtc_livekit_patch.js @@ -63,9 +63,19 @@ patch(Rtc.prototype, { this.network.addEventListener("updateTrack", async (event) => { if (event.detail.name === "trackSubscribed") { const {sessionId, type, track} = event.detail.payload; + + if ( + this.selfSession && + String(sessionId) === String(this.selfSession.id) + ) { + console.log(`Ignoring own track subscription for ${type}`); + return; + } + console.log( `Track subscribed for session ${sessionId}, type ${type}. Triggering rebind.` ); + const rtcSession = await this.store.RtcSession.getWhenReady(sessionId); // Store LiveKit track separately @@ -92,8 +102,14 @@ patch(Rtc.prototype, { async updateUpload() { console.log("Updating uploads for tracks..."); await this.network?.updateUpload(Source.MICROPHONE, this.state.audioTrack); - await this.network?.updateUpload(Source.CAMERA, this.state.cameraTrack); - await this.network?.updateUpload(Source.SCREEN, this.state.screenTrack); + await this.network?.updateUpload( + Source.CAMERA, + this.state.sendCamera ? this.state.cameraTrack : null + ); + await this.network?.updateUpload( + Source.SCREEN, + this.state.sendScreen ? this.state.screenTrack : null + ); // Trigger rebind for local tracks after upload if (this.selfSession) { @@ -149,12 +165,31 @@ patch(Rtc.prototype, { clear() { this.network?.disconnect(); + // Clear LiveKit tracks from all sessions if (this.state.channel) { for (const session of this.state.channel.rtcSessions) { - session.livekitTracks.clear(); + if (session.livekitTracks) { + // Detach all tracks before clearing + for (const track of session.livekitTracks.values()) { + try { + track?.detach?.(); + } catch (e) { + console.warn("Error detaching track:", e); + } + } + session.livekitTracks.clear(); + } } } if (this.selfSession?.livekitTracks) { + // Detach all tracks before clearing + for (const track of this.selfSession.livekitTracks.values()) { + try { + track?.detach?.(); + } catch (e) { + console.warn("Error detaching track:", e); + } + } this.selfSession.livekitTracks.clear(); } return super.clear(); From 28872b170258f04ab97559f3af17da117a58cca6 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 21:08:42 +0000 Subject: [PATCH 15/33] address various possible errors --- .../discuss/call_participant_video_patch.js | 7 +++++-- .../static/src/discuss/livekit_service.js | 21 ++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/mail_livekit/static/src/discuss/call_participant_video_patch.js b/mail_livekit/static/src/discuss/call_participant_video_patch.js index 0b9d45f0..3c7c3a15 100644 --- a/mail_livekit/static/src/discuss/call_participant_video_patch.js +++ b/mail_livekit/static/src/discuss/call_participant_video_patch.js @@ -51,9 +51,12 @@ patch(CallParticipantVideo.prototype, { `Attaching LiveKit track for session ${rtcSession.id}, type ${type}` ); - // Detach old track if different if (this.livekitTrack && this.livekitTrack !== livekitTrack) { - this.livekitTrack.detach(this.root.el); + try { + this.livekitTrack.detach(this.root.el); + } catch (e) { + console.warn("Error detaching old track:", e); + } } // Attach new LiveKit track directly to video element diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index bfcd3c30..f7b0325f 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -124,11 +124,22 @@ class LivekitService { } async connect(url, token) { - if (this.initiated || (this.room && this.room.isConnected)) { + if (this.initiated) { log("Already connected or connecting to LiveKit"); return; } + // If there's an existing room, disconnect it WITHOUT clearing listeners + if (this.room) { + log("Disconnecting existing room before reconnecting"); + const roomToDisconnect = this.room; + this.room = null; + this.connected = false; + await roomToDisconnect.disconnect(); + // Note: We don't clear listeners or set initiated=false here + // because we're reconnecting + } + this.initiated = true; this._start(); log("Connecting to LiveKit:", url); @@ -179,11 +190,19 @@ class LivekitService { } catch (error) { log("Failed to connect to LiveKit room:", error); this.room = null; + this.initiated = false; // Reset on failure + this.connected = false; + throw error; } } async disconnect() { log("Clearing info change listeners"); + + if (!this.room && !this.initiated) { + log("Already disconnected"); + return; + } this.infoChangeListeners.clear(); this.trackSubscribedListeners.clear(); this.trackMutedListeners.clear(); From 3341aba95924f720066b371e5b0279e4822a179f Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 21:10:33 +0000 Subject: [PATCH 16/33] address various possible errors --- mail_livekit/static/src/discuss/livekit_service.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index f7b0325f..c5c6ddc7 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -187,6 +187,7 @@ class LivekitService { await this.room.connect(url, token); log("Connected to LiveKit room"); this.connected = true; + this.initiated = false; } catch (error) { log("Failed to connect to LiveKit room:", error); this.room = null; @@ -197,12 +198,12 @@ class LivekitService { } async disconnect() { - log("Clearing info change listeners"); - if (!this.room && !this.initiated) { log("Already disconnected"); return; } + + log("Clearing info change listeners"); this.infoChangeListeners.clear(); this.trackSubscribedListeners.clear(); this.trackMutedListeners.clear(); From 2b42989cea69dc305297eb5ab7bca9bd9eda02c9 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 21:11:00 +0000 Subject: [PATCH 17/33] address various possible errors --- mail_livekit/static/src/discuss/livekit_service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index c5c6ddc7..6c15d065 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -191,7 +191,7 @@ class LivekitService { } catch (error) { log("Failed to connect to LiveKit room:", error); this.room = null; - this.initiated = false; // Reset on failure + this.initiated = false; this.connected = false; throw error; } @@ -238,7 +238,7 @@ class LivekitService { log("Publishing new track for source:", source); await this.room?.localParticipant.publishTrack(mediaStreamTrack, { source, - simulcast: source !== window.LivekitClient.Track.Source.Microphone, // Only use simulcast for video + simulcast: source !== window.LivekitClient.Track.Source.Microphone, }); } else if (publication.track) { log("Replacing track for source:", source); From 316a2af87881a020f6a93da6c9fac4afdd902181 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 21:23:59 +0000 Subject: [PATCH 18/33] address various possible errors --- mail_livekit/static/src/discuss/livekit_service.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index 6c15d065..238d91cb 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -69,6 +69,7 @@ class LivekitService { audioElement = track.attach(); audioElement.id = `livekit-audio-${participant.identity}`; + audioElement.classList.add("livekit-audio-element"); document.body.appendChild(audioElement); } for (const listener of this.trackSubscribedListeners.values()) { @@ -208,13 +209,11 @@ class LivekitService { this.trackSubscribedListeners.clear(); this.trackMutedListeners.clear(); log("Disconnecting from LiveKit"); - - if (this.room) { - for (const [, participant] of this.room.remoteParticipants) { - const audioElement = this._get_audio_element(participant.identity); - audioElement?.remove(); - } - } + const allLivekitAudio = document.querySelectorAll(".livekit-audio-element"); + allLivekitAudio.forEach((element) => { + log("Removing orphaned audio element:", element.id); + element.remove(); + }); const roomToDisconnect = this.room; this.room = null; this.initiated = false; From 6e287d206d3ce227597abea9d1aa59234f2e571b Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Tue, 20 Jan 2026 21:27:36 +0000 Subject: [PATCH 19/33] extended clean up --- .../static/src/discuss/livekit_service.js | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index 238d91cb..65315fe6 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -204,16 +204,44 @@ class LivekitService { return; } + log("Disconnecting from LiveKit"); + + // Unpublish and stop all local tracks before disconnecting + if (this.room?.localParticipant) { + log("Unpublishing all local tracks"); + const localTracks = Array.from( + this.room.localParticipant.trackPublications.values() + ); + + for (const publication of localTracks) { + if (publication.track) { + log("Stopping and unpublishing track:", publication.source); + try { + // Stop the track first + publication.track.stop(); + // Then unpublish it + await this.room.localParticipant.unpublishTrack( + publication.track + ); + } catch (e) { + log("Error unpublishing track:", e); + } + } + } + } + log("Clearing info change listeners"); this.infoChangeListeners.clear(); this.trackSubscribedListeners.clear(); this.trackMutedListeners.clear(); - log("Disconnecting from LiveKit"); + + log("Removing all audio elements"); const allLivekitAudio = document.querySelectorAll(".livekit-audio-element"); allLivekitAudio.forEach((element) => { log("Removing orphaned audio element:", element.id); element.remove(); }); + const roomToDisconnect = this.room; this.room = null; this.initiated = false; From 39ad781415fcf51edfb6b5df5f096949657ebb6b Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Wed, 21 Jan 2026 08:08:17 +0000 Subject: [PATCH 20/33] committed to livekit managing audio streams --- mail_livekit/models/mail_rtc_session.py | 8 +- .../discuss/call_participant_video_patch.js | 31 +++- .../static/src/discuss/livekit_adapter.js | 37 ++-- .../static/src/discuss/livekit_service.js | 52 +++--- .../static/src/discuss/rtc_livekit_patch.js | 161 +++++++++++------- odoo.conf | 25 +++ 6 files changed, 209 insertions(+), 105 deletions(-) create mode 100644 odoo.conf diff --git a/mail_livekit/models/mail_rtc_session.py b/mail_livekit/models/mail_rtc_session.py index 966a38bd..fdd553fd 100644 --- a/mail_livekit/models/mail_rtc_session.py +++ b/mail_livekit/models/mail_rtc_session.py @@ -71,9 +71,15 @@ def _generate_livekit_token(self, livekit_params): else "Guest " + str(self.channel_member_id.id) ) + identity = ( + f"partner:{self.partner_id.id}" + if self.partner_id + else f"guest:{self.channel_member_id.id}" + ) + token = ( AccessToken(livekit_params.get("api_key"), livekit_params.get("api_secret")) - .with_identity(str(self.id)) + .with_identity(identity) .with_name(name) .with_grants(grants) .to_jwt() diff --git a/mail_livekit/static/src/discuss/call_participant_video_patch.js b/mail_livekit/static/src/discuss/call_participant_video_patch.js index 3c7c3a15..46c6b828 100644 --- a/mail_livekit/static/src/discuss/call_participant_video_patch.js +++ b/mail_livekit/static/src/discuss/call_participant_video_patch.js @@ -5,27 +5,44 @@ import {CallParticipantVideo} from "@mail/discuss/call/common/call_participant_v import {patch} from "@web/core/utils/patch"; patch(CallParticipantVideo.prototype, { + setIdentity() { + this.identity = this.props.session + ? this.props.session.partnerId + ? `partner:${this.props.session.partnerId}` + : `guest:${this.props.session.channelMember.id}` + : null; + }, + + removeLiveKitTrack() { + if (this.livekitTrack) { + this.livekitTrack.detach(); + } + this.livekitTrack = null; + }, + setup() { super.setup(...arguments); this.livekitTrack = null; + this.setIdentity(); + // Subscribe to track rebind events useExternalListener(this.env.bus, "LIVEKIT:TRACK:REBIND", (event) => { - const {sessionId, type} = event.detail; - if (this.props.session?.id === sessionId && this.props.type === type) { + const {sessionId, identity, type} = event.detail; + if (this.props.identity == identity && this.props.type === type) { console.log( - `LIVEKIT:TRACK:REBIND for session ${sessionId}, type ${type}` + `LIVEKIT:TRACK:REBIND for identity ${identity}, type ${type}` ); + if (sessionId && this.props.session.id !== sessionId) { + this.removeLiveKitTrack(); + } this._update(); } }); onWillUnmount(() => { // Detach LiveKit track on unmount - if (this.livekitTrack && this.root.el) { - this.livekitTrack.detach(this.root.el); - } - this.livekitTrack = null; + this.removeLiveKitTrack(); }); }, diff --git a/mail_livekit/static/src/discuss/livekit_adapter.js b/mail_livekit/static/src/discuss/livekit_adapter.js index 9682f8dd..5d3f7620 100644 --- a/mail_livekit/static/src/discuss/livekit_adapter.js +++ b/mail_livekit/static/src/discuss/livekit_adapter.js @@ -47,22 +47,15 @@ export class LiveKitAdapter { } handleTrackSubscribed(participantId, source, track) { - if (source === Source.MICROPHONE) { - return this._emit("track", { - sessionId: participantId, - type: "audio", - track: track?.mediaStreamTrack, - active: !track?.isMuted, - }); - } this._emit("trackSubscribed", { - sessionId: participantId, + identity: participantId, type: source === Source.SCREEN ? "screen" : "camera", track: track, }); } handleTrackMuted(participantId, source, track, muted) { + console.log("Track muted event:", participantId, source, track, muted); const type = source === Source.MICROPHONE ? "audio" @@ -71,7 +64,7 @@ export class LiveKitAdapter { : "camera"; if (muted) { return this._emit("track", { - sessionId: participantId, + identity: participantId, type: type, track: track, active: false, @@ -82,17 +75,33 @@ export class LiveKitAdapter { addLivekitListeners() { livekitService.subscribeToInfoChange("adapter", (info) => { + console.log("received Info change event:", info); this._emit("info_change", info); }); livekitService.subscribeToTrackSubscribed( "adapter", - (participantId, source, track) => - this.handleTrackSubscribed(participantId, source, track) + (participantId, source, track) => { + console.log( + "received Track subscribed event:", + participantId, + source, + track + ); + this.handleTrackSubscribed(participantId, source, track); + } ); livekitService.subscribeToTrackMuted( "adapter", - (participantId, source, track, muted) => - this.handleTrackMuted(participantId, source, track, muted) + (participantId, source, track, muted) => { + console.log( + "received Track muted event:", + participantId, + source, + track, + muted + ); + this.handleTrackMuted(participantId, source, track, muted); + } ); } diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index 65315fe6..8f275443 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -2,6 +2,16 @@ const {Room, VideoPresets, RoomEvent} = window.LivekitClient; // This script should be the only contact point with Livekit SDK +const Source = { + CAMERA: window.LivekitClient.Track.Source.Camera, + MICROPHONE: window.LivekitClient.Track.Source.Microphone, + SCREEN: window.LivekitClient.Track.Source.ScreenShare, +}; + +console.log("Livekit Source constants:", Source); + +Object.freeze(Source); + let debug = false; function log(...args) { @@ -19,8 +29,12 @@ class LivekitService { initiated = false; connected = false; - _get_audio_element(identity) { - return document.getElementById(`livekit-audio-${identity}`); + _formAudioElementId(identity) { + return `livekit-audio-${identity}`; + } + + get audioElementClass() { + return "livekit-audio-element"; } _start() { @@ -64,16 +78,18 @@ class LivekitService { log("Track subscribed", track, publication, participant); if (track.kind == "audio") { - let audioElement = this._get_audio_element(participant.identity); + const audioElementId = this._formAudioElementId(participant.identity); + let audioElement = document.getElementById(audioElementId); audioElement?.remove(); audioElement = track.attach(); - audioElement.id = `livekit-audio-${participant.identity}`; - audioElement.classList.add("livekit-audio-element"); + audioElement.id = audioElementId; + audioElement.classList.add(this.audioElementClass); document.body.appendChild(audioElement); - } - for (const listener of this.trackSubscribedListeners.values()) { - listener(participant.identity, publication.source, track); + } else { + for (const listener of this.trackSubscribedListeners.values()) { + listener(participant.identity, publication.source, track); + } } } @@ -82,7 +98,8 @@ class LivekitService { track.detach(); if (track.kind === "audio") { - const audioElement = this._get_audio_element(participant.identity); + const audioElementId = this._formAudioElementId(participant.identity); + const audioElement = document.getElementById(audioElementId); audioElement?.remove(); } @@ -265,14 +282,13 @@ class LivekitService { log("Publishing new track for source:", source); await this.room?.localParticipant.publishTrack(mediaStreamTrack, { source, - simulcast: source !== window.LivekitClient.Track.Source.Microphone, + simulcast: source !== Source.Microphone, }); } else if (publication.track) { log("Replacing track for source:", source); await publication.track.replaceTrack(mediaStreamTrack); if ( - publication.track.source !== - window.LivekitClient.Track.Source.Microphone || + publication.track.source !== Source.Microphone || mediaStreamTrack?.enabled ) { publication?.track?.unmute(); @@ -308,7 +324,7 @@ class LivekitService { async setMicrophoneMuted(muted) { log("Setting microphone mute to:", muted); const publication = this.room?.localParticipant.getTrackPublication( - window.LivekitClient.Track.Source.Microphone + Source.Microphone ); if (publication?.track && publication.track.isMuted !== muted) { if (muted) { @@ -327,14 +343,4 @@ class LivekitService { export const livekitService = new LivekitService(); -const Source = { - CAMERA: window.LivekitClient.Track.Source.Camera, - MICROPHONE: window.LivekitClient.Track.Source.Microphone, - SCREEN: window.LivekitClient.Track.Source.ScreenShare, -}; - -console.log("Livekit Source constants:", Source); - -Object.freeze(Source); - export {Source}; diff --git a/mail_livekit/static/src/discuss/rtc_livekit_patch.js b/mail_livekit/static/src/discuss/rtc_livekit_patch.js index 4cfdd473..d57dca61 100644 --- a/mail_livekit/static/src/discuss/rtc_livekit_patch.js +++ b/mail_livekit/static/src/discuss/rtc_livekit_patch.js @@ -45,54 +45,96 @@ patch(Rtc.prototype, { }); }, - async _initConnection() { - this.selfSession.connectionState = "selecting network type"; - this.network?.disconnect(); - this.network = new LiveKitAdapter(); - this.state.connectionType = CONNECTION_TYPES.SERVER; - - this.network.addEventListener("update", (event) => { - try { - this._handleNetworkUpdates(event); - } catch (error) { - if (!error.message?.includes("closed")) { - console.error("Error in network update:", error); + identityToSessionId(identity) { + // Convert LiveKit identity back to session ID + if (identity.startsWith("partner:")) { + const partnerId = parseInt(identity.split(":")[1], 10); + // Find the session with this partner ID + for (const session of this.state.channel.rtcSessions) { + if (session.partnerId === partnerId) { + return session.id; } } - }); - this.network.addEventListener("updateTrack", async (event) => { - if (event.detail.name === "trackSubscribed") { - const {sessionId, type, track} = event.detail.payload; - - if ( - this.selfSession && - String(sessionId) === String(this.selfSession.id) - ) { - console.log(`Ignoring own track subscription for ${type}`); - return; + } else if (identity.startsWith("guest:")) { + const guestId = parseInt(identity.split(":")[1], 10); + // Find the session with this channel member ID + for (const session of this.state.channel.rtcSessions) { + if (session.channelMember.id === guestId) { + return session.id; } + } + } + return identity; + }, - console.log( - `Track subscribed for session ${sessionId}, type ${type}. Triggering rebind.` - ); + fixEventIds(eventdata) { + if (eventdata.detail.payload.identity && !eventdata.detail.payload.sessionId) { + eventdata.detail.payload.sessionId = this.identityToSessionId( + eventdata.detail.payload.identity + ); + } + if ( + eventdata.detail.name == "info_change" && + Object.keys(eventdata.detail.payload)[0].includes(":") + ) { + const fixedIdentity = this.identityToSessionId( + Object.keys(eventdata.detail.payload)[0] + ); + eventdata.detail.payload = { + [fixedIdentity]: + eventdata.detail.payload[Object.keys(eventdata.detail.payload)[0]], + }; + } + }, - const rtcSession = await this.store.RtcSession.getWhenReady(sessionId); + async _handleNetworkUpdates(eventdata) { + console.log("LIVEKIT: Network update received", eventdata); + this.fixEventIds(eventdata); + return super._handleNetworkUpdates(eventdata); + }, - // Store LiveKit track separately - rtcSession.livekitTracks.set(type, track); + async handleTrackSubscribed(eventdata) { + console.log("LIVEKIT: Track subscribed event received", eventdata); + this.fixEventIds(eventdata); + if (eventdata.detail.name === "trackSubscribed") { + const {identity, type, track} = eventdata.detail.payload; + const sessionId = this.identityToSessionId(identity); - // Create dummy MediaStream for UI rendering (hasVideo check) - const dummyStream = new window.MediaStream(); - rtcSession.videoStreams.set(type, dummyStream); - await rtcSession.updateStreamState(type, true); + console.log( + `Track subscribed for session ${sessionId}, type ${type}. Triggering rebind.` + ); + + const rtcSession = await this.store.RtcSession.getWhenReady(sessionId); + + // Store LiveKit track separately + rtcSession.livekitTracks.set(type, track); + + // Create dummy MediaStream for UI rendering (hasVideo check) + const dummyStream = new window.MediaStream(); + rtcSession.videoStreams.set(type, dummyStream); + await rtcSession.updateStreamState(type, true); + + // Trigger bus event to notify CallParticipantVideo to attach track + this.store.env.bus.trigger("LIVEKIT:TRACK:REBIND", { + sessionId: rtcSession.id, + type: type, + identity: identity, + }); + } + }, + + async _initConnection() { + this.selfSession.connectionState = "selecting network type"; + await this.network?.disconnect(); + this.network = new LiveKitAdapter(); + this.state.connectionType = CONNECTION_TYPES.SERVER; + + this.network.addEventListener("update", this._handleNetworkUpdates.bind(this)); + this.network.addEventListener( + "updateTrack", + this.handleTrackSubscribed.bind(this) + ); - // Trigger bus event to notify CallParticipantVideo to attach track - this.store.env.bus.trigger("LIVEKIT:TRACK:REBIND", { - sessionId: rtcSession.id, - type: type, - }); - } - }); if (this.state.channel) { await this.call(); await this.updateUpload(); @@ -163,35 +205,34 @@ patch(Rtc.prototype, { return super.updateActiveSession(session, videoType, {addVideo}); }, - clear() { - this.network?.disconnect(); - // Clear LiveKit tracks from all sessions - if (this.state.channel) { - for (const session of this.state.channel.rtcSessions) { - if (session.livekitTracks) { - // Detach all tracks before clearing - for (const track of session.livekitTracks.values()) { - try { - track?.detach?.(); - } catch (e) { - console.warn("Error detaching track:", e); - } - } - session.livekitTracks.clear(); + _clearRemoteLiveKitTracks(channel) { + for (const session of channel.rtcSessions) { + if (session.livekitTracks) { + // Detach all tracks before clearing + for (const track of session.livekitTracks.values()) { + track?.detach?.(); } + session.livekitTracks.clear(); } } + }, + + _clearLocalLiveKitTracks() { if (this.selfSession?.livekitTracks) { // Detach all tracks before clearing for (const track of this.selfSession.livekitTracks.values()) { - try { - track?.detach?.(); - } catch (e) { - console.warn("Error detaching track:", e); - } + track?.detach?.(); } this.selfSession.livekitTracks.clear(); } + }, + + clear() { + this.network?.disconnect(); + if (this.state.channel) { + this._clearRemoteLiveKitTracks(this.state.channel); + } + this._clearLocalLiveKitTracks(); return super.clear(); }, }); diff --git a/odoo.conf b/odoo.conf new file mode 100644 index 00000000..5e4fdbca --- /dev/null +++ b/odoo.conf @@ -0,0 +1,25 @@ +[options] +admin_passwd = odoo +db_host = postgres +db_port = 5432 +db_user = odoo +db_password = odoo +db_name = lkint +http_port = 8069 +gevent_port = 8072 +data_dir = /code/data +addons_path = + /code/odoo/addons, + /code/enterprise, + /code/design-themes, + /code/repos/nitrokey-odoo-modules, +list_db = False +limit_time_real = 2000 +limit_time_cpu = 2000 +#dev_mode = True +#server_wide_modules = web,queue_job +# workers = 2 +# proxy_mode = True + +# [queue_job] +# channels = root:2 From 81ce7783b579494827e58703ee35cb37f242b7b7 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Wed, 21 Jan 2026 08:37:26 +0000 Subject: [PATCH 21/33] tied voulme control to audio elements --- mail_livekit/__manifest__.py | 1 + .../src/discuss/call_context_menu_patch.js | 22 +++++++++++++++++++ .../static/src/discuss/livekit_adapter.js | 9 +++++++- .../static/src/discuss/livekit_service.js | 12 +++++----- .../static/src/discuss/rtc_livekit_patch.js | 22 +++++++++++++++++++ 5 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 mail_livekit/static/src/discuss/call_context_menu_patch.js diff --git a/mail_livekit/__manifest__.py b/mail_livekit/__manifest__.py index a8099bb5..129dee4e 100644 --- a/mail_livekit/__manifest__.py +++ b/mail_livekit/__manifest__.py @@ -19,6 +19,7 @@ "mail_livekit/static/src/discuss/rtc_livekit_patch.js", "mail_livekit/static/src/discuss/thread_actions_patch.js", "mail_livekit/static/src/discuss/call_participant_video_patch.js", + "mail_livekit/static/src/discuss/call_context_menu_patch.js", ], }, "external_dependencies": { diff --git a/mail_livekit/static/src/discuss/call_context_menu_patch.js b/mail_livekit/static/src/discuss/call_context_menu_patch.js new file mode 100644 index 00000000..a1bf7742 --- /dev/null +++ b/mail_livekit/static/src/discuss/call_context_menu_patch.js @@ -0,0 +1,22 @@ +// Create new file: mail_livekit/static/src/discuss/call/common/call_context_menu_patch.js + +import {CallContextMenu} from "@mail/discuss/call/common/call_context_menu"; +import {patch} from "@web/core/utils/patch"; + +patch(CallContextMenu.prototype, { + onChangeVolume(ev) { + super.onChangeVolume(ev); + + // Immediately apply volume to LiveKit audio element + const volume = Number(ev.target.value); + const identity = this.props.rtcSession.partnerId + ? `partner:${this.props.rtcSession.partnerId}` + : `guest:${this.props.rtcSession.channelMember.id}`; + const audioElementId = `livekit-audio-${identity}`; + const audioElement = document.getElementById(audioElementId); + + if (audioElement) { + audioElement.volume = volume; + } + }, +}); diff --git a/mail_livekit/static/src/discuss/livekit_adapter.js b/mail_livekit/static/src/discuss/livekit_adapter.js index 5d3f7620..490f3287 100644 --- a/mail_livekit/static/src/discuss/livekit_adapter.js +++ b/mail_livekit/static/src/discuss/livekit_adapter.js @@ -46,7 +46,14 @@ export class LiveKitAdapter { livekitService.publishInfo(info); } - handleTrackSubscribed(participantId, source, track) { + handleTrackSubscribed(participantId, source, track, audioElement = null) { + if (track.kind === "audio") { + return this._emit("setAudioVolume", { + identity: participantId, + element: audioElement, + }); + } + this._emit("trackSubscribed", { identity: participantId, type: source === Source.SCREEN ? "screen" : "camera", diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index 8f275443..f4bfd902 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -77,19 +77,21 @@ class LivekitService { log("Track subscribed", track, publication, participant); + let audioElement = null; + if (track.kind == "audio") { const audioElementId = this._formAudioElementId(participant.identity); - let audioElement = document.getElementById(audioElementId); + audioElement = document.getElementById(audioElementId); audioElement?.remove(); audioElement = track.attach(); audioElement.id = audioElementId; audioElement.classList.add(this.audioElementClass); document.body.appendChild(audioElement); - } else { - for (const listener of this.trackSubscribedListeners.values()) { - listener(participant.identity, publication.source, track); - } + } + + for (const listener of this.trackSubscribedListeners.values()) { + listener(participant.identity, publication.source, track, audioElement); } } diff --git a/mail_livekit/static/src/discuss/rtc_livekit_patch.js b/mail_livekit/static/src/discuss/rtc_livekit_patch.js index d57dca61..c2c17f02 100644 --- a/mail_livekit/static/src/discuss/rtc_livekit_patch.js +++ b/mail_livekit/static/src/discuss/rtc_livekit_patch.js @@ -33,6 +33,7 @@ patch(PeerToPeer.prototype, { patch(Rtc.prototype, { start() { super.start(); + browser.addEventListener("pagehide", () => { if (this.state.channel) { const data = JSON.stringify({ @@ -93,6 +94,27 @@ patch(Rtc.prototype, { return super._handleNetworkUpdates(eventdata); }, + async setAudioVolume(sessionId, element = null) { + const rtcSession = await this.store.RtcSession.getWhenReady(sessionId); + if (element) { + rtcSession.audioElement = element; + } + const volumeSetting = this.store.Volume.getForPartnerId(rtcSession.partnerId); + const volume = volumeSetting ? volumeSetting.volume / 100 : 1.0; + if (rtcSession.audioElement) { + rtcSession.audioElement.volume = volume; + } + }, + + async handleSetAudioVolume(eventdata) { + console.log("LIVEKIT: Set audio volume event received", eventdata); + this.fixEventIds(eventdata); + return this.setAudioVolume( + eventdata.detail.payload.sessionId, + eventdata.detail.payload.element + ); + }, + async handleTrackSubscribed(eventdata) { console.log("LIVEKIT: Track subscribed event received", eventdata); this.fixEventIds(eventdata); From 60127620d78b57fa9f06a590217306c186185c1a Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Wed, 21 Jan 2026 08:52:52 +0000 Subject: [PATCH 22/33] trigger rebind on connect --- .../static/src/discuss/rtc_livekit_patch.js | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/mail_livekit/static/src/discuss/rtc_livekit_patch.js b/mail_livekit/static/src/discuss/rtc_livekit_patch.js index c2c17f02..91c5f7a5 100644 --- a/mail_livekit/static/src/discuss/rtc_livekit_patch.js +++ b/mail_livekit/static/src/discuss/rtc_livekit_patch.js @@ -184,6 +184,29 @@ patch(Rtc.prototype, { } }, + async _triggerRebind(channel) { + if (!channel) return; + + for (const session of this.state.channel.rtcSessions) { + if (session.eq(this.selfSession)) { + continue; + } + // Check if session has livekit tracks that need to be rebound + if (session.livekitTracks && session.livekitTracks.size > 0) { + for (const [type, track] of session.livekitTracks.entries()) { + console.log( + `Rebinding existing track for session ${session.id}, type ${type}, track ${track}` + ); + this.store.env.bus.trigger("LIVEKIT:TRACK:REBIND", { + sessionId: session.id, + type: type, + identity: `partner:${session.partnerId}`, + }); + } + } + } + }, + async call() { if (!this.network || this.network.isConnected()) { return; @@ -195,6 +218,8 @@ patch(Rtc.prototype, { this.selfSession.livekit_token ); this.selfSession.connectionState = "connected"; + + this._triggerRebind(this.state.channel); } catch (error) { console.error("Failed to connect to LiveKit server:", error); this.selfSession.connectionState = "failed"; From 56b3e3c76eecc2634cda063ea747f8ecd8aef9fc Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Wed, 21 Jan 2026 09:16:31 +0000 Subject: [PATCH 23/33] changed rebind logic --- .../static/src/discuss/rtc_livekit_patch.js | 53 ++++++++++++------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/mail_livekit/static/src/discuss/rtc_livekit_patch.js b/mail_livekit/static/src/discuss/rtc_livekit_patch.js index 91c5f7a5..5db6cdc0 100644 --- a/mail_livekit/static/src/discuss/rtc_livekit_patch.js +++ b/mail_livekit/static/src/discuss/rtc_livekit_patch.js @@ -184,24 +184,41 @@ patch(Rtc.prototype, { } }, - async _triggerRebind(channel) { - if (!channel) return; + async _triggerRebind() { + if (this.state.channel && this.network.livekitService?.room) { + const room = this.network.livekitService.room; + + for (const [identity, participant] of room.remoteParticipants.entries()) { + console.log(`Processing existing participant: ${identity}`); + + // Process audio tracks + const audioTracks = Array.from( + participant.audioTrackPublications.values() + ); + for (const publication of audioTracks) { + if (publication.track && publication.isSubscribed) { + console.log(`Found existing audio track for ${identity}`); + await this.network.livekitAdapter.handleTrackSubscribed( + publication.track, + publication, + participant + ); + } + } - for (const session of this.state.channel.rtcSessions) { - if (session.eq(this.selfSession)) { - continue; - } - // Check if session has livekit tracks that need to be rebound - if (session.livekitTracks && session.livekitTracks.size > 0) { - for (const [type, track] of session.livekitTracks.entries()) { - console.log( - `Rebinding existing track for session ${session.id}, type ${type}, track ${track}` - ); - this.store.env.bus.trigger("LIVEKIT:TRACK:REBIND", { - sessionId: session.id, - type: type, - identity: `partner:${session.partnerId}`, - }); + // Process video tracks + const videoTracks = Array.from( + participant.videoTrackPublications.values() + ); + for (const publication of videoTracks) { + if (publication.track && publication.isSubscribed) { + console.log(`Found existing video track for ${identity}`); + await this.network.livekitAdapter.handleTrackSubscribed( + publication.track, + publication, + participant + ); + } } } } @@ -219,7 +236,7 @@ patch(Rtc.prototype, { ); this.selfSession.connectionState = "connected"; - this._triggerRebind(this.state.channel); + this._triggerRebind(); } catch (error) { console.error("Failed to connect to LiveKit server:", error); this.selfSession.connectionState = "failed"; From 03c526fd67fcac56f0c9a512e3a17f72b04892da Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Wed, 21 Jan 2026 09:55:04 +0000 Subject: [PATCH 24/33] move rebind to livekit service --- .../static/src/discuss/livekit_service.js | 44 +++++++++++++++++++ .../static/src/discuss/rtc_livekit_patch.js | 42 ------------------ 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index f4bfd902..931762ed 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -143,6 +143,46 @@ class LivekitService { } } + // Add this method to the LivekitService class + async rebindExistingTracks() { + if (!this.room || !this.connected) { + log("Cannot rebind - not connected to room"); + return; + } + + log("Rebinding existing participant tracks"); + + for (const [identity, participant] of this.room.remoteParticipants.entries()) { + log(`Processing existing participant: ${identity}`); + + // Process audio tracks + const audioTracks = Array.from(participant.audioTrackPublications.values()); + for (const publication of audioTracks) { + if (publication.track && publication.isSubscribed) { + log(`Rebinding existing audio track for ${identity}`); + this.handleTrackSubscribed( + publication.track, + publication, + participant + ); + } + } + + // Process video tracks + const videoTracks = Array.from(participant.videoTrackPublications.values()); + for (const publication of videoTracks) { + if (publication.track && publication.isSubscribed) { + log(`Rebinding existing video track for ${identity}`); + this.handleTrackSubscribed( + publication.track, + publication, + participant + ); + } + } + } + } + async connect(url, token) { if (this.initiated) { log("Already connected or connecting to LiveKit"); @@ -201,6 +241,10 @@ class LivekitService { if (!this.room?.canPlaybackAudio) { log("Issue with audio playback: requires UI interaction"); } + }) + .on(RoomEvent.Connected, () => { + log("Room connected - rebinding existing tracks"); + setTimeout(() => this.rebindExistingTracks(), 100); }); try { diff --git a/mail_livekit/static/src/discuss/rtc_livekit_patch.js b/mail_livekit/static/src/discuss/rtc_livekit_patch.js index 5db6cdc0..c2c17f02 100644 --- a/mail_livekit/static/src/discuss/rtc_livekit_patch.js +++ b/mail_livekit/static/src/discuss/rtc_livekit_patch.js @@ -184,46 +184,6 @@ patch(Rtc.prototype, { } }, - async _triggerRebind() { - if (this.state.channel && this.network.livekitService?.room) { - const room = this.network.livekitService.room; - - for (const [identity, participant] of room.remoteParticipants.entries()) { - console.log(`Processing existing participant: ${identity}`); - - // Process audio tracks - const audioTracks = Array.from( - participant.audioTrackPublications.values() - ); - for (const publication of audioTracks) { - if (publication.track && publication.isSubscribed) { - console.log(`Found existing audio track for ${identity}`); - await this.network.livekitAdapter.handleTrackSubscribed( - publication.track, - publication, - participant - ); - } - } - - // Process video tracks - const videoTracks = Array.from( - participant.videoTrackPublications.values() - ); - for (const publication of videoTracks) { - if (publication.track && publication.isSubscribed) { - console.log(`Found existing video track for ${identity}`); - await this.network.livekitAdapter.handleTrackSubscribed( - publication.track, - publication, - participant - ); - } - } - } - } - }, - async call() { if (!this.network || this.network.isConnected()) { return; @@ -235,8 +195,6 @@ patch(Rtc.prototype, { this.selfSession.livekit_token ); this.selfSession.connectionState = "connected"; - - this._triggerRebind(); } catch (error) { console.error("Failed to connect to LiveKit server:", error); this.selfSession.connectionState = "failed"; From 8254fd5d1b941b789e148c61be395a36d661870e Mon Sep 17 00:00:00 2001 From: "Daniel Phillip @ Solvti" Date: Wed, 21 Jan 2026 11:53:13 +0100 Subject: [PATCH 25/33] Delete odoo.conf --- odoo.conf | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 odoo.conf diff --git a/odoo.conf b/odoo.conf deleted file mode 100644 index 5e4fdbca..00000000 --- a/odoo.conf +++ /dev/null @@ -1,25 +0,0 @@ -[options] -admin_passwd = odoo -db_host = postgres -db_port = 5432 -db_user = odoo -db_password = odoo -db_name = lkint -http_port = 8069 -gevent_port = 8072 -data_dir = /code/data -addons_path = - /code/odoo/addons, - /code/enterprise, - /code/design-themes, - /code/repos/nitrokey-odoo-modules, -list_db = False -limit_time_real = 2000 -limit_time_cpu = 2000 -#dev_mode = True -#server_wide_modules = web,queue_job -# workers = 2 -# proxy_mode = True - -# [queue_job] -# channels = root:2 From 3a0f3b47172edc655d29aab3a7df1ed76026cdce Mon Sep 17 00:00:00 2001 From: "Daniel Phillip @ Solvti" Date: Wed, 21 Jan 2026 11:57:58 +0100 Subject: [PATCH 26/33] Delete mail_livekit/streamIssue.md --- mail_livekit/streamIssue.md | 38 ------------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 mail_livekit/streamIssue.md diff --git a/mail_livekit/streamIssue.md b/mail_livekit/streamIssue.md deleted file mode 100644 index 6be13007..00000000 --- a/mail_livekit/streamIssue.md +++ /dev/null @@ -1,38 +0,0 @@ -Problem Summary: "Skipping incoming track as it already ended" The Error Receiver side -error: "skipping incoming track as it already ended" - -Occurs when sender toggles camera on Appears in receiver's console, not sender's Video -feed breaks for receivers Root Cause Identified Odoo's behavior when toggling camera: - -Camera OFF: Odoo calls updateUpload("camera", undefined) → triggers unpublish Camera ON: -Odoo calls updateUpload("camera", newTrack) → triggers publish with brand new -MediaStreamTrack (different ID) Odoo immediately stops the old track after creating the -new one (via setVideo() or closeStream()) The race condition: - -LiveKit unpublishes old track → publishes new track (async operations) Meanwhile, Odoo -stops the MediaStreamTrack we're trying to publish Track ends before/during LiveKit's -publish operation Receivers attempt to subscribe to an already-ended track What We've -Tried (All Failed) Track cloning - Clone tracks immediately to prevent Odoo from -stopping them - -Result: Clones still end somehow Delayed unpublish - Wait 500ms before unpublishing to -give receivers time - -Result: Error persists Keep old clones alive - Don't stop old clones, accumulate them - -Result: Error persists Use replaceTrack() - Avoid unpublish/publish cycle, keep same -publication - -Current approach: Uses LiveKit's LocalTrack.replaceTrack() to swap underlying -MediaStreamTrack Result: Unknown (just implemented) Key Observations from Logs This -suggests: The track is alive when published on sender side, but ends between publish and -receiver subscription. - -The Critical Question Why does the track end after successful publish? - -Is Odoo stopping it even after we clone it? Is the clone somehow linked to the -original's lifecycle? Is LiveKit stopping it during internal operations? Is there a -timing issue with the WebRTC negotiation? Expected Behavior When sender toggles camera: - -Old video publication should be replaced seamlessly Receivers should receive a live -track Video should continue without interruption From 621cd62d5b83e68c3624fafe5e96ca82a194314e Mon Sep 17 00:00:00 2001 From: "Dmytro Kashuba @ Solvti" Date: Fri, 30 Jan 2026 13:11:27 +0100 Subject: [PATCH 27/33] Rename JS file to avoid liner errors --- mail_livekit/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mail_livekit/__manifest__.py b/mail_livekit/__manifest__.py index 129dee4e..8e8e56b0 100644 --- a/mail_livekit/__manifest__.py +++ b/mail_livekit/__manifest__.py @@ -13,7 +13,7 @@ ], "assets": { "mail_livekit.assets_livekit": [ - "mail_livekit/static/lib/livekit/livekit-client.umd.js", + "mail_livekit/static/lib/livekit/livekit-client.umd.min.js", "mail_livekit/static/src/discuss/livekit_service.js", "mail_livekit/static/src/discuss/livekit_adapter.js", "mail_livekit/static/src/discuss/rtc_livekit_patch.js", From 8463ac86128d85b4a98bc2ec336f27e5409c23e2 Mon Sep 17 00:00:00 2001 From: "Dmytro Kashuba @ Solvti" Date: Fri, 30 Jan 2026 13:11:57 +0100 Subject: [PATCH 28/33] Rename JS file to avoid linter errors --- .../livekit/{livekit-client.umd.js => livekit-client.umd.min.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename mail_livekit/static/lib/livekit/{livekit-client.umd.js => livekit-client.umd.min.js} (100%) diff --git a/mail_livekit/static/lib/livekit/livekit-client.umd.js b/mail_livekit/static/lib/livekit/livekit-client.umd.min.js similarity index 100% rename from mail_livekit/static/lib/livekit/livekit-client.umd.js rename to mail_livekit/static/lib/livekit/livekit-client.umd.min.js From 4e6a49ed43b2ab801776dd963597ef34cfa53c73 Mon Sep 17 00:00:00 2001 From: jans23 Date: Fri, 30 Jan 2026 13:51:02 +0100 Subject: [PATCH 29/33] Update author information in manifest --- mail_livekit/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mail_livekit/__manifest__.py b/mail_livekit/__manifest__.py index 8e8e56b0..d7e0157f 100644 --- a/mail_livekit/__manifest__.py +++ b/mail_livekit/__manifest__.py @@ -2,7 +2,7 @@ "name": "Discuss - Livekit Integration", "summary": "Integrate LiveKit video conferencing with Odoo Discuss", "version": "18.0.1.0.1", - "author": "Odoo Community Association (OCA), Solvti Sp. z o.o.", + "author": "Nitrokey GmbH, Solvti Sp. z o.o.", "license": "LGPL-3", "category": "Discuss", "depends": ["mail"], From 397dd52769d3fc5b50281a055f605be60df11b6c Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Thu, 19 Feb 2026 13:34:17 +0000 Subject: [PATCH 30/33] additional cleanup on disconnect --- mail_livekit/static/src/discuss/livekit_service.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index 931762ed..e5f618a6 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -124,6 +124,14 @@ class LivekitService { this.connected = false; } + handleParticpantDisconnected(participant) { + log("Participant disconnected", participant.identity); + + const audioElementId = this._formAudioElementId(participant.identity); + const audioElement = document.getElementById(audioElementId); + audioElement?.remove(); + } + // Requires functions that accept info as parameter subscribeToInfoChange(name, listener) { log("Subscribing to info change:", name); @@ -245,6 +253,9 @@ class LivekitService { .on(RoomEvent.Connected, () => { log("Room connected - rebinding existing tracks"); setTimeout(() => this.rebindExistingTracks(), 100); + }) + .on(RoomEvent.ParticipantDisconnected, (remoteParticipant) => { + this.handleParticpantDisconnected(remoteParticipant); }); try { From 4ede470bd609e6ce8da9b56c73ec482e062d56db Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Thu, 12 Mar 2026 13:39:27 +0000 Subject: [PATCH 31/33] fix bad return on create, throw loud error for missing credentials --- mail_livekit/models/mail_rtc_session.py | 13 +++++++++++-- .../src/discuss/call_participant_video_patch.js | 4 ++-- .../static/src/discuss/livekit_adapter.js | 8 ++++---- .../static/src/discuss/livekit_service.js | 2 -- .../static/src/discuss/rtc_livekit_patch.js | 16 ++++++++-------- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/mail_livekit/models/mail_rtc_session.py b/mail_livekit/models/mail_rtc_session.py index fdd553fd..3cda2704 100644 --- a/mail_livekit/models/mail_rtc_session.py +++ b/mail_livekit/models/mail_rtc_session.py @@ -1,6 +1,7 @@ from livekit.api import AccessToken, VideoGrants -from odoo import api, fields, models +from odoo import _, api, fields, models +from odoo.exceptions import UserError from odoo.tools.misc import str2bool from odoo.addons.mail.tools.discuss import Store @@ -20,7 +21,7 @@ def create(self, vals_list): result = super().create(vals_list) if not livekit_params.get("valid"): - return + return result for session in result: session._generate_livekit_token(livekit_params) @@ -47,6 +48,14 @@ def _get_livekit_config_params(self): and api_secret.strip() ) + if livekit_enabled and not valid: + raise UserError( + _( + "LiveKit integration is enabled but not properly configured." + " Please check the LiveKit settings." + ) + ) + return { "valid": valid, "enabled": livekit_enabled, diff --git a/mail_livekit/static/src/discuss/call_participant_video_patch.js b/mail_livekit/static/src/discuss/call_participant_video_patch.js index 46c6b828..50890275 100644 --- a/mail_livekit/static/src/discuss/call_participant_video_patch.js +++ b/mail_livekit/static/src/discuss/call_participant_video_patch.js @@ -30,7 +30,7 @@ patch(CallParticipantVideo.prototype, { useExternalListener(this.env.bus, "LIVEKIT:TRACK:REBIND", (event) => { const {sessionId, identity, type} = event.detail; if (this.props.identity == identity && this.props.type === type) { - console.log( + console.debug( `LIVEKIT:TRACK:REBIND for identity ${identity}, type ${type}` ); if (sessionId && this.props.session.id !== sessionId) { @@ -64,7 +64,7 @@ patch(CallParticipantVideo.prototype, { const livekitTrack = rtcSession.livekitTracks?.get(type); if (livekitTrack) { - console.log( + console.debug( `Attaching LiveKit track for session ${rtcSession.id}, type ${type}` ); diff --git a/mail_livekit/static/src/discuss/livekit_adapter.js b/mail_livekit/static/src/discuss/livekit_adapter.js index 490f3287..f0d5575b 100644 --- a/mail_livekit/static/src/discuss/livekit_adapter.js +++ b/mail_livekit/static/src/discuss/livekit_adapter.js @@ -62,7 +62,7 @@ export class LiveKitAdapter { } handleTrackMuted(participantId, source, track, muted) { - console.log("Track muted event:", participantId, source, track, muted); + console.debug("Track muted event:", participantId, source, track, muted); const type = source === Source.MICROPHONE ? "audio" @@ -82,13 +82,13 @@ export class LiveKitAdapter { addLivekitListeners() { livekitService.subscribeToInfoChange("adapter", (info) => { - console.log("received Info change event:", info); + console.debug("received Info change event:", info); this._emit("info_change", info); }); livekitService.subscribeToTrackSubscribed( "adapter", (participantId, source, track) => { - console.log( + console.debug( "received Track subscribed event:", participantId, source, @@ -100,7 +100,7 @@ export class LiveKitAdapter { livekitService.subscribeToTrackMuted( "adapter", (participantId, source, track, muted) => { - console.log( + console.debug( "received Track muted event:", participantId, source, diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index e5f618a6..481b2445 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -8,8 +8,6 @@ const Source = { SCREEN: window.LivekitClient.Track.Source.ScreenShare, }; -console.log("Livekit Source constants:", Source); - Object.freeze(Source); let debug = false; diff --git a/mail_livekit/static/src/discuss/rtc_livekit_patch.js b/mail_livekit/static/src/discuss/rtc_livekit_patch.js index c2c17f02..317f8731 100644 --- a/mail_livekit/static/src/discuss/rtc_livekit_patch.js +++ b/mail_livekit/static/src/discuss/rtc_livekit_patch.js @@ -22,11 +22,11 @@ patch(RtcSession.prototype, { patch(PeerToPeer.prototype, { async handleNotification() { - console.log("message intercepted"); + console.debug("message intercepted"); }, _dataChannelupdateInBroadcast() { - console.log("message intercepted"); + console.debug("message intercepted"); }, }); @@ -89,7 +89,7 @@ patch(Rtc.prototype, { }, async _handleNetworkUpdates(eventdata) { - console.log("LIVEKIT: Network update received", eventdata); + console.debug("LIVEKIT: Network update received", eventdata); this.fixEventIds(eventdata); return super._handleNetworkUpdates(eventdata); }, @@ -107,7 +107,7 @@ patch(Rtc.prototype, { }, async handleSetAudioVolume(eventdata) { - console.log("LIVEKIT: Set audio volume event received", eventdata); + console.debug("LIVEKIT: Set audio volume event received", eventdata); this.fixEventIds(eventdata); return this.setAudioVolume( eventdata.detail.payload.sessionId, @@ -116,13 +116,13 @@ patch(Rtc.prototype, { }, async handleTrackSubscribed(eventdata) { - console.log("LIVEKIT: Track subscribed event received", eventdata); + console.debug("LIVEKIT: Track subscribed event received", eventdata); this.fixEventIds(eventdata); if (eventdata.detail.name === "trackSubscribed") { const {identity, type, track} = eventdata.detail.payload; const sessionId = this.identityToSessionId(identity); - console.log( + console.debug( `Track subscribed for session ${sessionId}, type ${type}. Triggering rebind.` ); @@ -164,7 +164,7 @@ patch(Rtc.prototype, { }, async updateUpload() { - console.log("Updating uploads for tracks..."); + console.debug("Updating uploads for tracks..."); await this.network?.updateUpload(Source.MICROPHONE, this.state.audioTrack); await this.network?.updateUpload( Source.CAMERA, @@ -189,7 +189,7 @@ patch(Rtc.prototype, { return; } try { - console.log("Connecting to LiveKit server..."); + console.debug("Connecting to LiveKit server..."); await this.network.connect( this.selfSession.livekit_url, this.selfSession.livekit_token From 26f70b4c47b8aa8861ad45bb9ecfa84243115b32 Mon Sep 17 00:00:00 2001 From: "daniel.phillip" Date: Thu, 12 Mar 2026 14:04:26 +0000 Subject: [PATCH 32/33] remove disconnect on page leave behaviour --- mail_livekit/static/src/discuss/livekit_service.js | 1 + 1 file changed, 1 insertion(+) diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index 481b2445..05704c98 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -215,6 +215,7 @@ class LivekitService { videoCaptureDefaults: { resolution: VideoPresets.h720.resolution, }, + disconnectOnPageLeave: false, }); await this.room.prepareConnection(url, token); From 2b102b58b41505abdc5f06b397fd867c93d45342 Mon Sep 17 00:00:00 2001 From: "Daniel Phillip @ Solvti" Date: Thu, 12 Mar 2026 15:22:11 +0100 Subject: [PATCH 33/33] Refactor track publishing logic into a separate method --- .../static/src/discuss/livekit_service.js | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/mail_livekit/static/src/discuss/livekit_service.js b/mail_livekit/static/src/discuss/livekit_service.js index 05704c98..243cb2dc 100644 --- a/mail_livekit/static/src/discuss/livekit_service.js +++ b/mail_livekit/static/src/discuss/livekit_service.js @@ -334,28 +334,32 @@ class LivekitService { const publication = this.room?.localParticipant.getTrackPublication(source); if (mediaStreamTrack && enabled) { - if (!publication) { - log("Publishing new track for source:", source); - await this.room?.localParticipant.publishTrack(mediaStreamTrack, { - source, - simulcast: source !== Source.Microphone, - }); - } else if (publication.track) { - log("Replacing track for source:", source); - await publication.track.replaceTrack(mediaStreamTrack); - if ( - publication.track.source !== Source.Microphone || - mediaStreamTrack?.enabled - ) { - publication?.track?.unmute(); - } - } + await this._publishOrReplaceTrack(source, publication, mediaStreamTrack); } else if (!enabled && publication?.track) { log("Muting/unmuting existing track for source:", source); await publication.track.mute(); } } + async _publishOrReplaceTrack(source, publication, mediaStreamTrack) { + if (!publication) { + log("Publishing new track for source:", source); + await this.room?.localParticipant.publishTrack(mediaStreamTrack, { + source, + simulcast: source !== Source.Microphone, + }); + } else if (publication.track) { + log("Replacing track for source:", source); + await publication.track.replaceTrack(mediaStreamTrack); + if ( + publication.track.source !== Source.Microphone || + mediaStreamTrack?.enabled + ) { + publication?.track?.unmute(); + } + } + } + getTrack(participantId, source) { const participant = this.room?.remoteParticipants.get(participantId); if (participant) {