@sanseng/livekit-ws-sdk 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,3 @@
1
- # 🤖 Real-time Audio-Video Interaction SDK User Guide (v0.1.0)
1
+ # 🤖 Real-time Audio-Video Interaction SDK User Guide
2
2
 
3
3
  This SDK provides an integrated communication solution combining **LiveKit (RTC)** and **WebSocket (command stream)**, specifically designed for digital human conversations, real-time voice interactions, and similar scenarios. It handles complex underlying logic such as media track synchronization, audio capture, streaming text parsing, and automatic reconnection.
package/dist/index.cjs.js CHANGED
@@ -1 +1,110 @@
1
- "use strict";class e extends Error{constructor(t,s="SDK_ERROR",i){super(t),this.name="SDKError",this.code=s,this.cause=i,Object.setPrototypeOf(this,e.prototype)}static fromError(t,s){return t instanceof e?t:t instanceof Error?new e(t.message,s||"SDK_ERROR",t):"string"==typeof t?new e(t,s||"SDK_ERROR"):new e("Unknown error",s||"SDK_ERROR",t)}}class t{constructor(){this._disposed=!1}get isDisposed(){return this._disposed}dispose(){this._disposed||(this.onDispose(),this._disposed=!0)}ensureNotDisposed(){if(this._disposed)throw new e("Object has been disposed")}}var s,i,n;exports.LogLevel=void 0,(s=exports.LogLevel||(exports.LogLevel={}))[s.DEBUG=0]="DEBUG",s[s.INFO=1]="INFO",s[s.WARN=2]="WARN",s[s.ERROR=3]="ERROR",s[s.NONE=4]="NONE";class r{static setLevel(e){this._level=e}static setPrefix(e){this._prefix=e}static debug(e,...t){this._level<=exports.LogLevel.DEBUG&&console.debug(`${this._prefix} [DEBUG]`,e,...t)}static info(e,...t){this._level<=exports.LogLevel.INFO&&console.info(`${this._prefix} [INFO]`,e,...t)}static warn(e,...t){this._level<=exports.LogLevel.WARN&&console.warn(`${this._prefix} [WARN]`,e,...t)}static error(e,...t){this._level<=exports.LogLevel.ERROR&&console.error(`${this._prefix} [ERROR]`,e,...t)}}r._level=exports.LogLevel.ERROR,r._prefix="[SDK]";class o extends t{constructor(){super(...arguments),this._listeners=new Map}on(e,t){this.ensureNotDisposed(),this._listeners.has(e)||this._listeners.set(e,new Set);const s=this._listeners.get(e);return s.add(t),r.debug(`Event listener added for: ${String(e)}`),()=>{s.delete(t),r.debug(`Event listener removed for: ${String(e)}`)}}once(e,t){this.ensureNotDisposed();const s=i=>{t(i),this.off(e,s)};return this.on(e,s)}off(e,t){this.ensureNotDisposed();const s=this._listeners.get(e);s&&s.delete(t)}emit(e,t){this.ensureNotDisposed();const s=this._listeners.get(e);s&&s.size>0&&(r.debug(`Emitting event: ${String(e)}`,t),s.forEach(s=>{try{s(t)}catch(t){r.error(`Error in event listener for ${String(e)}:`,t)}}))}removeAllListeners(){this._listeners.clear(),r.debug("All event listeners removed")}listenerCount(e){const t=this._listeners.get(e);return t?t.size:0}onDispose(){this.removeAllListeners()}}class a{constructor(){this.currentTrackId=null,this.currentParticipantId=null,this.renderMode="raw",this.isRendering=!1}reset(){this.currentTrackId=null,this.currentParticipantId=null,this.renderMode="raw",this.isRendering=!1}}class h{constructor(){this.isCapturing=!1,this.sampleRate=48e3,this.channels=1,this.vadEnabled=!1,this.threeAEnabled=!1,this.isPlaying=!1,this.currentOutputTrackId=null,this.volume=1,this.isMuted=!1}reset(){this.isCapturing=!1,this.sampleRate=48e3,this.channels=1,this.vadEnabled=!1,this.threeAEnabled=!1,this.isPlaying=!1,this.currentOutputTrackId=null,this.volume=1,this.isMuted=!1}}exports.ConversationStateType=void 0,(i=exports.ConversationStateType||(exports.ConversationStateType={})).IDLE="idle",i.WAITING="waiting",i.STREAMING="streaming",i.COMPLETED="completed",i.ERROR="error";class c{constructor(){this.state=exports.ConversationStateType.IDLE,this.currentSessionId=null,this.currentQuestionId=null,this.currentAnswer="",this.isWaiting=!1,this.isStreaming=!1,this.lastError=null}reset(){this.state=exports.ConversationStateType.IDLE,this.currentSessionId=null,this.currentQuestionId=null,this.currentAnswer="",this.isWaiting=!1,this.isStreaming=!1,this.lastError=null}}exports.SessionStatus=void 0,(n=exports.SessionStatus||(exports.SessionStatus={})).DISCONNECTED="disconnected",n.CONNECTING="connecting",n.CONNECTED="connected",n.RECONNECTING="reconnecting",n.ERROR="error";class d{constructor(){this.status=exports.SessionStatus.DISCONNECTED,this.isConnected=!1,this.isReconnecting=!1,this.reconnectAttempts=0,this.lastError=null,this.connectedAt=null}reset(){this.status=exports.SessionStatus.DISCONNECTED,this.isConnected=!1,this.isReconnecting=!1,this.reconnectAttempts=0,this.lastError=null,this.connectedAt=null}}class l{constructor(e){this.options=e,this._livekitUrl="",this._token="",this._wsUrl="",this.eventBus=new o,this.videoState=new a,this.audioState=new h,this.conversationState=new c,this.sessionState=new d,e.debug&&r.setLevel(0),r.info("SDK Context initialized")}setLivekitConfig(e,t,s){this._livekitUrl=e,this._token=t,this._roomId=s}emitError(t,s){const i=e.fromError(t,s);return this.eventBus.emit("error",{error:i}),i}setWsUrl(e){this._wsUrl=e}get wsUrl(){return this._wsUrl}get livekitUrl(){return this._livekitUrl}get token(){return this._token}get roomId(){return this._roomId}getLivekitConfig(){return{livekitUrl:this._livekitUrl,token:this._token}}dispose(){this.eventBus.dispose(),this.videoState.reset(),this.audioState.reset(),this.conversationState.reset(),this.sessionState.reset(),r.info("SDK Context disposed")}}class u extends t{constructor(){super(...arguments),this._trackId=null,this._participantId=null,this._track=null}get trackId(){return this._trackId}get participantId(){return this._participantId}get track(){return this._track}setTrack(e,t,s){this.ensureNotDisposed(),this._track&&this._track.stop(),this._track=e,this._trackId=t,this._participantId=s,r.info("Video track ready")}clearTrack(){this._track&&(this._track.stop(),this._track=null),this._trackId=null,this._participantId=null,r.info("Video track cleared")}get hasTrack(){return null!==this._track&&"live"===this._track.readyState}onDispose(){this.clearTrack()}}class p extends t{constructor(){super(...arguments),this._renderer=null}getRenderer(){return this._renderer}setRenderer(e){this._renderer&&this._renderer.dispose(),this._renderer=e,r.debug("Raw render strategy renderer set")}getProcessor(){return null}setProcessor(e){r.warn("Raw render strategy does not support processors")}onDispose(){this._renderer&&(this._renderer.dispose(),this._renderer=null),r.info("Raw Render Strategy disposed")}}class _{create(){return new p}}class m extends t{constructor(e,t){if(super(),this._canvas=null,this._ctx=null,this._videoElement=null,this._parentElement=null,this._resizeObserver=null,this._animationFrameId=null,this._isRendering=!1,this._renderLoop=()=>{if(this._isRendering&&this._videoElement&&this._canvas&&this._ctx){try{this._syncCanvasSize(),this._ctx.drawImage(this._videoElement,0,0,this._canvas.width,this._canvas.height)}catch(e){r.error("Error rendering from video to canvas:",e)}this._animationFrameId=requestAnimationFrame(this._renderLoop)}},e){if(this._canvas=e,this._ctx=e.getContext("2d"),!this._ctx)throw new Error("Failed to get 2D context from canvas")}else{if(!t)throw new Error("CanvasRenderer requires either canvas or videoElement");this._videoElement=t,this._createCanvasFromVideo()}r.info("Canvas Renderer created")}_createCanvasFromVideo(){if(!this._videoElement)return;if(this._parentElement=this._videoElement.parentElement,!this._parentElement)throw new Error("Video element must have a parent element");if("static"===window.getComputedStyle(this._parentElement).position&&(this._parentElement.style.position="relative"),this._canvas=document.createElement("canvas"),this._ctx=this._canvas.getContext("2d"),!this._ctx)throw new Error("Failed to get 2D context from canvas");this._canvas.style.position="absolute",this._canvas.style.top="0",this._canvas.style.left="0",this._canvas.style.width="100%",this._canvas.style.height="100%",this._canvas.style.pointerEvents="none",this._parentElement.appendChild(this._canvas),this._syncCanvasSize(),this._setupResizeObserver()}_syncCanvasSize(){if(!this._canvas||!this._videoElement||!this._ctx)return;const e=this._videoElement.videoWidth,t=this._videoElement.videoHeight,s=this._videoElement.clientWidth,i=this._videoElement.clientHeight;if(e>0&&t>0&&s>0&&i>0){const n=e/t;let r,o;n>s/i?(r=s,o=s/n):(r=i*n,o=i),this._canvas.style.width=`${r}px`,this._canvas.style.height=`${o}px`;const a=(s-r)/2,h=(i-o)/2;this._canvas.style.left=`${a}px`,this._canvas.style.top=`${h}px`,this._canvas.width=e,this._canvas.height=t}}_setupResizeObserver(){this._videoElement&&"undefined"!=typeof ResizeObserver&&(this._resizeObserver=new ResizeObserver(()=>{this._syncCanvasSize()}),this._resizeObserver.observe(this._videoElement))}startRenderingFromVideo(){!this._isRendering&&this._videoElement&&this._canvas&&this._ctx&&(this._isRendering=!0,this._renderLoop())}stopRenderingFromVideo(){this._isRendering=!1,null!==this._animationFrameId&&(cancelAnimationFrame(this._animationFrameId),this._animationFrameId=null)}render(e){if(this.ensureNotDisposed(),this._ctx&&this._canvas)try{const t=e.displayWidth,s=e.displayHeight;this._videoElement?this._syncCanvasSize():this._canvas.width===t&&this._canvas.height===s||(this._canvas.width=t,this._canvas.height=s),this._ctx.drawImage(e,0,0,this._canvas.width,this._canvas.height)}catch(e){r.error("Error rendering video frame to canvas:",e)}}getCanvas(){return this._canvas}getContext(){return this._ctx}onDispose(){this.stopRenderingFromVideo(),this._resizeObserver&&(this._resizeObserver.disconnect(),this._resizeObserver=null),this._canvas&&this._parentElement&&this._canvas.parentElement===this._parentElement&&this._parentElement.removeChild(this._canvas),this._canvas=null,this._ctx=null,this._videoElement=null,this._parentElement=null,r.info("Canvas Renderer disposed")}}class g extends t{constructor(e){super(),this._element=null,this._stream=null,this._track=null,this._element=e,r.info("Video Element Renderer created")}setTrack(e){this.ensureNotDisposed(),this._track&&this._track!==e&&this._track.stop(),this._track=e,this._element&&(this._stream&&(this._stream.getTracks().forEach(e=>e.stop()),this._stream=null),this._stream=new MediaStream([e]),this._element.srcObject=this._stream,this._element.play().catch(e=>{r.error("Error playing video:",e)}),r.debug("Video track set to element"))}setOpacity(e){this._element&&(this._element.style.opacity=String(e))}getElement(){return this._element}render(e){r.debug("Render called in direct mode (no-op)")}onDispose(){this._element&&(this._element.srcObject=null),this._stream&&(this._stream.getTracks().forEach(e=>e.stop()),this._stream=null),this._track&&(this._track.stop(),this._track=null),r.info("Video Element Renderer disposed")}}class v extends t{onDispose(){}}class f extends v{constructor(e){super(),this._canvas=null,this._ctx=null,this._alphaCanvas=null,this._alphaCtx=null,this._width=0,this._height=0,this._copyCanvas=null,this._copyCtx=null,this._lastProcessedTimestamp=null,this._options=e,r.info("Green Screen Processor created")}clearCanvases(){const e=(e,t,s)=>{e&&e.clearRect(0,0,t,s)};this._ctx&&this._canvas&&e(this._ctx,this._canvas.width,this._canvas.height),this._alphaCtx&&this._alphaCanvas&&e(this._alphaCtx,this._alphaCanvas.width,this._alphaCanvas.height),this._copyCtx&&this._copyCanvas&&e(this._copyCtx,this._copyCanvas.width,this._copyCanvas.height)}process(e){this.ensureNotDisposed();const t=e.timestamp??performance.now();if(t===this._lastProcessedTimestamp)return this.clearCanvases(),e;if(this._lastProcessedTimestamp=t,!this._options.enabled){try{e.close()}catch(e){r.warn("Error closing original frame when green screen disabled:",e)}return this.clearCanvases(),e}try{const t=e.displayWidth,s=e.displayHeight;if(!(this._canvas&&this._width===t&&this._height===s||(this._width=t,this._height=s,this._canvas=document.createElement("canvas"),this._canvas.width=t,this._canvas.height=s,this._ctx=this._canvas.getContext("2d",{willReadFrequently:!0}),this._alphaCanvas=document.createElement("canvas"),this._alphaCanvas.width=t,this._alphaCanvas.height=s,this._alphaCtx=this._alphaCanvas.getContext("2d",{willReadFrequently:!0}),this._copyCanvas=document.createElement("canvas"),this._copyCanvas.width=t,this._copyCanvas.height=s,this._copyCtx=this._copyCanvas.getContext("2d"),this._ctx&&this._alphaCtx&&this._copyCtx)))return r.error("Failed to get required contexts for green screen processing"),this.clearCanvases(),e;if(!this._ctx||!this._alphaCtx||!this._copyCtx)return r.error("Contexts missing for green screen processing"),this.clearCanvases(),e;if(this.clearCanvases(),this._copyCtx)try{this._copyCtx.clearRect(0,0,t,s),this._copyCtx.drawImage(e,0,0,t,s)}catch(e){r.warn("Error drawing frame to copy canvas:",e)}const i=this._sampleBackgroundColor(t,s);if(this._ctx&&this._copyCtx){const e=this._copyCtx.getImageData(0,0,t,s),n=e.data,o=this._generateAlphaMaskWithDespill(n,t,s,i);if(this._applyAlphaMask(n,o,t,s),this._ctx.putImageData(e,0,0),this._alphaCtx&&this._alphaCanvas)try{this._alphaCtx.clearRect(0,0,this._alphaCanvas.width,this._alphaCanvas.height),this._alphaCtx.drawImage(this._canvas,0,0)}catch(e){r.warn("Error synchronizing alpha canvas:",e)}}try{if(this._canvas)try{const t=new VideoFrame(this._canvas,{timestamp:e.timestamp,duration:e.duration??void 0});try{e.close()}catch(e){r.warn("Error closing original frame after processing:",e)}return t}catch(t){return r.debug("Cannot create VideoFrame from Canvas synchronously, returning original frame",t),e}return e}catch(t){return r.error("Error creating VideoFrame from processed canvas:",t),e}}catch(t){this.clearCanvases();try{e.close()}catch(e){r.warn("Error closing original frame on processing failure:",e)}return r.error("Error processing green screen:",t),e}}_generateAlphaMaskWithDespill(e,t,s,i){const n=new Uint8Array(t*s),r=this._options.similarity??.4,o=this._options.smoothness??.1,a=this._options.despillStrength??.5,h=(e,t,s)=>{const n=e-i[0],r=1.2*(t-i[1]),o=s-i[2];return Math.sqrt(n*n+r*r+o*o)},c=(e,t,s)=>{const i=.299*e+.587*t+.114*s;let n=1;i<30&&(n=i/30);const r=Math.max(e,t,s),o=Math.min(e,t,s),a=r>0?(r-o)/r:0,h=1-.5*Math.abs((i-128)/128),c=Math.max(0,Math.min(1,h)),d=Math.min(1,1.05*a)*c*n;return Math.max(0,Math.min(1,d))};for(let d=0;d<s;d++)for(let s=0;s<t;s++){const l=4*(d*t+s),u=e[l],p=e[l+1],_=e[l+2],m=c(u,p,_),g=h(u,p,_),v=255*Math.sqrt(3)*1.2,f=Math.min(1,g/v),C=f;let S=1;if(f<r){const e=Math.max(o,.05),t=Math.max(0,r-e);if(f<t)S=0;else{const s=(f-t)/e;S=s*s*(3-2*s)}}let E=S;const w=.45;if(m<w)E=1;else{if(C>r+.1)E=1;else if(C>r){const e=.65;E=Math.max(e,S)}}if(E>0&&E<1&&C<=r+.1&&m>=w){const t=(1-E)*a,s=i[1]>0?p/i[1]:0,n=i[0]>0?u/i[0]:0,r=Math.max(0,s-n)*i[1];if(r>5){const s=t*r*.5;e[l+1]=Math.max(0,Math.min(255,p-s));const i=.25*s;e[l]=Math.max(0,Math.min(255,u+i)),e[l+2]=Math.max(0,Math.min(255,_+i))}}const y=Math.round(255*E);n[d*t+s]=y}return this._applySpatialContinuity(n,t,s),n}_applySpatialContinuity(e,t,s){const i=new Uint8Array(e);for(let n=1;n<s-1;n++)for(let s=1;s<t-1;s++){const r=n*t+s,o=i[r];if(o<200&&o>0){let a=0,h=0;for(let e=-1;e<=1;e++)for(let r=-1;r<=1;r++){if(0===r&&0===e)continue;h++,i[(n+e)*t+(s+r)]>=240&&a++}if(a/h>=.625){let a=0,h=0;for(let e=-1;e<=1;e++)for(let r=-1;r<=1;r++){if(0===r&&0===e)continue;const o=i[(n+e)*t+(s+r)];o>=240&&(a+=o,h++)}if(h>0){const t=Math.min(255,Math.round(a/h)),s=1-o/200,i=Math.round(o+(t-o)*s*.8);e[r]=Math.max(o,Math.min(255,i))}}}}}_sampleBackgroundColor(e,t){try{const s=this._copyCtx;if(!s)return this._options.chromaKey||[0,255,0];const i=Math.max(4,Math.floor(.05*Math.min(e,t))),n=[],r=s.getImageData(0,0,e,i).data;for(let t=0;t<r.length;t+=4*Math.max(1,Math.floor(e/64)))n.push([r[t],r[t+1],r[t+2]]);const o=s.getImageData(0,t-i,e,i).data;for(let t=0;t<o.length;t+=4*Math.max(1,Math.floor(e/64)))n.push([o[t],o[t+1],o[t+2]]);const a=s.getImageData(0,0,i,t).data;for(let e=0;e<a.length;e+=4*Math.max(1,Math.floor(t/64)))n.push([a[e],a[e+1],a[e+2]]);const h=s.getImageData(e-i,0,i,t).data;for(let e=0;e<h.length;e+=4*Math.max(1,Math.floor(t/64)))n.push([h[e],h[e+1],h[e+2]]);if(0===n.length)return this._options.chromaKey||[0,255,0];let c=0,d=0,l=0,u=0;for(const e of n){(e[0]+e[1]+e[2])/3>16&&(c+=e[0],d+=e[1],l+=e[2],u++)}return 0===u?this._options.chromaKey||[0,255,0]:[Math.round(c/u),Math.round(d/u),Math.round(l/u)]}catch(e){return r.warn("Error sampling background color for chroma key:",e),this._options.chromaKey||[0,255,0]}}_applyAlphaMask(e,t,s,i){for(let n=0;n<i;n++)for(let i=0;i<s;i++){e[4*(n*s+i)+3]=t[n*s+i]}}updateOptions(e){this._options={...this._options,...e}}getCanvas(){return this._canvas}getImageData(){if(this._alphaCtx&&this._alphaCanvas)try{return this._alphaCtx.getImageData(0,0,this._alphaCanvas.width,this._alphaCanvas.height)}catch(e){return r.warn("Error getting ImageData from alpha canvas:",e),null}if(this._ctx&&this._canvas)try{return this._ctx.getImageData(0,0,this._canvas.width,this._canvas.height)}catch(e){return r.warn("Error getting ImageData from canvas:",e),null}return null}onDispose(){this._canvas=null,this._ctx=null,this._alphaCanvas=null,this._alphaCtx=null,r.info("Green Screen Processor disposed")}}class C extends t{constructor(){super(...arguments),this._renderer=null,this._processor=null,this._videoElementRenderer=null,this._canvasRenderer=null,this._videoFrameCallbackId=null,this._isProcessing=!1,this._processVideoFrame=()=>{if(!(this._isProcessing&&this._videoElementRenderer&&this._processor&&this._canvasRenderer))return;const e=this._videoElementRenderer.getElement();if(!e||e.readyState<2)this._isProcessing&&e&&(this._videoFrameCallbackId=e.requestVideoFrameCallback(this._processVideoFrame));else{try{const t=new VideoFrame(e,{timestamp:1e3*performance.now()}),s=this._processor.process(t);if(s&&s!==t)this._canvasRenderer.render(s),s.close();else if(null===s&&this._processor instanceof f){const e=this._processor,t=e.getCanvas(),s=e.getImageData();if(t&&s&&this._canvasRenderer.getContext()){const e=this._canvasRenderer.getContext();if(e){const i=this._canvasRenderer.getCanvas();if(i){const n=this._videoElementRenderer?.getElement();if(n){const e=n.videoWidth,t=n.videoHeight;e>0&&t>0&&(i.width===e&&i.height===t||(i.width=e,i.height=t))}else i.width===t.width&&i.height===t.height||(i.width=t.width,i.height=t.height);e.putImageData(s,0,0)}}}}else s===t&&this._canvasRenderer.render(t);t.close()}catch(e){r.error("Error processing video frame:",e)}this._isProcessing&&e&&(this._videoFrameCallbackId=e.requestVideoFrameCallback(this._processVideoFrame))}},this._processVideoFrameFallback=()=>{if(!(this._isProcessing&&this._videoElementRenderer&&this._processor&&this._canvasRenderer))return;const e=this._videoElementRenderer.getElement();if(!e||e.readyState<2)this._isProcessing&&requestAnimationFrame(this._processVideoFrameFallback);else{try{const t=new VideoFrame(e,{timestamp:1e3*performance.now()}),s=this._processor.process(t);if(s&&s!==t)this._canvasRenderer.render(s),s.close();else if(null===s&&this._processor instanceof f){const e=this._processor,t=e.getCanvas(),s=e.getImageData();if(t&&s&&this._canvasRenderer.getContext()){const e=this._canvasRenderer.getContext();if(e){const i=this._canvasRenderer.getCanvas();if(i){const n=this._videoElementRenderer?.getElement();if(n){const e=n.videoWidth,t=n.videoHeight;e>0&&t>0&&(i.width===e&&i.height===t||(i.width=e,i.height=t))}else i.width===t.width&&i.height===t.height||(i.width=t.width,i.height=t.height);e.putImageData(s,0,0)}}}}else s===t&&this._canvasRenderer.render(t);t.close()}catch(e){r.error("Error processing video frame:",e)}this._isProcessing&&requestAnimationFrame(this._processVideoFrameFallback)}}}getRenderer(){return this._renderer}setRenderer(e){this._renderer&&this._renderer.dispose(),this._renderer=e,e instanceof g?(this._videoElementRenderer=e,this._processor&&this._setupGreenScreenProcessing()):(this._videoElementRenderer=null,this._stopGreenScreenProcessing()),r.debug("Processed render strategy renderer set")}getProcessor(){return this._processor}setProcessor(e){this._processor&&this._processor.dispose(),this._processor=e,e&&this._videoElementRenderer?this._setupGreenScreenProcessing():this._stopGreenScreenProcessing(),r.debug("Processed render strategy processor set")}_setupGreenScreenProcessing(){if(!this._videoElementRenderer||!this._processor)return;const e=this._videoElementRenderer.getElement();if(e){if(e.readyState<2){const t=()=>{e.removeEventListener("loadedmetadata",t),this._setupGreenScreenProcessing()};return void e.addEventListener("loadedmetadata",t)}if(this._videoElementRenderer.setOpacity(0),!this._canvasRenderer)try{this._canvasRenderer=new m(void 0,e),this._renderer=this._canvasRenderer}catch(e){return void r.error("Failed to create CanvasRenderer for green screen:",e)}this._startProcessingLoop(),r.info("Green screen processing setup completed")}else r.warn("Video element not available for green screen processing")}_stopGreenScreenProcessing(){this._stopProcessingLoop(),this._videoElementRenderer&&this._videoElementRenderer.setOpacity(1),this._canvasRenderer&&(this._canvasRenderer.dispose(),this._canvasRenderer=null),this._videoElementRenderer&&(this._renderer=this._videoElementRenderer)}_startProcessingLoop(){if(this._isProcessing||!this._videoElementRenderer||!this._processor||!this._canvasRenderer)return;this._videoElementRenderer.getElement()&&(this._isProcessing=!0,"requestVideoFrameCallback"in HTMLVideoElement.prototype?this._processVideoFrame():this._processVideoFrameFallback())}_stopProcessingLoop(){this._isProcessing=!1,null!==this._videoFrameCallbackId&&(this._videoFrameCallbackId=null)}onDispose(){this._stopGreenScreenProcessing(),this._renderer&&(this._renderer.dispose(),this._renderer=null),this._processor&&(this._processor.dispose(),this._processor=null),this._videoElementRenderer=null,this._canvasRenderer=null,r.info("Processed Render Strategy disposed")}}class S{create(){return new C}}class E{static getFactory(e){return"processed"===e?new S:new _}}class w extends t{constructor(e,t){super(),this._source=e;const s=t?.renderMode||"raw";if(this._strategyFactory=E.getFactory(s),this._strategy=this._strategyFactory.create(),t?.element&&t.element instanceof HTMLVideoElement){const e=new g(t.element);this._strategy.setRenderer(e),r.info("Video element renderer set from options")}r.info("Video Pipeline created")}setRenderMode(e){this.ensureNotDisposed();const t=E.getFactory(e);if(this._strategyFactory.constructor===t.constructor)return;const s=this._strategy.getRenderer(),i=this._strategy.getProcessor();this._strategy.dispose(),this._strategyFactory=t,this._strategy=this._strategyFactory.create(),s&&this._strategy.setRenderer(s),i&&this._strategy.setProcessor(i),r.info(`Video render mode changed to: ${e}`)}setProcessor(e){this.ensureNotDisposed(),this._strategy.setProcessor(e)}setRenderer(e){this.ensureNotDisposed(),this._strategy.setRenderer(e)}get strategy(){return this._strategy}onDispose(){this._strategy.dispose(),r.info("Video Pipeline disposed")}}class y extends t{constructor(e,t){if(super(),this._context=e,this._source=new u,this._pipeline=new w(this._source,t),t?.greenScreen?.enabled){"processed"!==t?.renderMode&&this._pipeline.setRenderMode("processed");const e=new f(t.greenScreen);this._pipeline.setProcessor(e),r.info("Green screen processor enabled")}r.info("Video Controller created")}setTrack(e,t,s){this.ensureNotDisposed(),this._source.setTrack(e,t,s),this._context.videoState.currentTrackId=t,this._context.videoState.currentParticipantId=s;const i=this._pipeline.strategy.getRenderer();i&&"setTrack"in i&&"function"==typeof i.setTrack&&i.setTrack(e),this._context.eventBus.emit("videoTrackAdded",{trackId:t,participantId:s})}removeTrack(e){if(this.ensureNotDisposed(),this._source.trackId===e){const t=this._source.participantId;this._source.clearTrack(),this._context.videoState.reset(),t&&this._context.eventBus.emit("videoTrackRemoved",{trackId:e,participantId:t})}}setRenderMode(e){this.ensureNotDisposed(),this._pipeline.setRenderMode(e),this._context.videoState.renderMode=e,this._context.eventBus.emit("videoRenderModeChanged",{mode:e})}onDispose(){this._source.dispose(),this._pipeline.dispose(),r.info("Video Controller disposed")}}class x extends t{process(e,t){return this.ensureNotDisposed(),e}onDispose(){}}class T extends t{set onProcessedAudio(e){this._onProcessedAudio=e}constructor(e){super(),this._processors=[],this._processingStrategy=new x,r.info("Input Audio Pipeline created")}setProcessingStrategy(e){this.ensureNotDisposed(),this._processingStrategy&&this._processingStrategy.dispose(),this._processingStrategy=e,r.debug("Audio processing strategy set")}get processingStrategy(){return this._processingStrategy}addProcessor(e){this.ensureNotDisposed(),this._processors.push(e),r.debug(`Audio processor added. Total: ${this._processors.length}`)}removeProcessor(e){this.ensureNotDisposed();const t=this._processors.indexOf(e);t>=0&&(this._processors.splice(t,1),r.debug(`Audio processor removed. Total: ${this._processors.length}`))}process(e,t){this.ensureNotDisposed();let s=e;try{s=this._processingStrategy.process(s,t)}catch(e){r.error("Error in audio processing strategy:",e)}for(const e of this._processors)try{s=e.process(s,t)}catch(e){r.error("Error in audio processor:",e);continue}this._onProcessedAudio&&this._onProcessedAudio(s,t)}onDispose(){if(this._processingStrategy)try{this._processingStrategy.dispose()}catch(e){r.error("Error disposing audio processing strategy:",e)}this._processors.forEach(e=>{try{e.dispose()}catch(e){r.error("Error disposing audio processor:",e)}}),this._processors.length=0,this._onProcessedAudio=void 0,r.info("Input Audio Pipeline disposed")}}class I extends t{constructor(){super(),this._audioElement=null,this._stream=null,this._track=null,this._volume=1,this._isMuted=!1,this._audioElement=document.createElement("audio"),this._audioElement.autoplay=!0,this._audioElement.volume=this._volume,this._audioElement.muted=this._isMuted,r.info("Output Audio Pipeline created")}setTrack(e){this.ensureNotDisposed(),this._track&&this._track!==e&&this._track.stop(),this._track=e,this._audioElement&&(this._stream&&(this._stream.getTracks().forEach(e=>e.stop()),this._stream=null),this._stream=new MediaStream([e]),this._audioElement.srcObject=this._stream,this._audioElement.volume=this._volume,this._audioElement.muted=this._isMuted,this._audioElement.play().catch(e=>{r.error("Error playing audio:",e)}),r.debug("Audio track set to output pipeline"))}removeTrack(){this.ensureNotDisposed(),this._audioElement&&(this._audioElement.srcObject=null),this._stream&&(this._stream.getTracks().forEach(e=>e.stop()),this._stream=null),this._track&&(this._track.stop(),this._track=null),r.debug("Audio track removed from output pipeline")}setVolume(e){this.ensureNotDisposed(),this._volume=Math.max(0,Math.min(1,e)),this._audioElement&&(this._audioElement.volume=this._volume),r.debug(`Audio output volume set to: ${this._volume}`)}getVolume(){return this._volume}mute(){this.ensureNotDisposed(),this._isMuted=!0,this._audioElement&&(this._audioElement.muted=!0),r.debug("Audio output muted")}unmute(){this.ensureNotDisposed(),this._isMuted=!1,this._audioElement&&(this._audioElement.muted=!1),r.debug("Audio output unmuted")}isMuted(){return this._isMuted}onDispose(){this.removeTrack(),this._audioElement&&(this._audioElement=null),r.info("Output Audio Pipeline disposed")}}const R={0:0,1:1,2:2};function k(t){!function(t){if(0!==t&&1!==t&&2!==t)throw new e(`Invalid sample rate encoding: ${t}. Must be 0 (16kHz), 1 (24kHz), or 2 (48kHz)`,"INVALID_SAMPLE_RATE")}(t.sampleRate);const s=(i=t.sequenceNumber)<0?0:i>4095?4095:Math.floor(i);var i;const n=function(e){if(e<0)return 0;const t=1048575;return e>t?e&t:Math.floor(e)}(t.timestamp),r=function(e){return e<0?0:e>4095?4095:Math.floor(e)}(t.frameSize),o=function(e){return e<0?0:e>65535?65535:Math.floor(e)}(t.payloadLength);if(0!==t.channel&&1!==t.channel)throw new e(`Invalid channel value: ${t.channel}. Must be 0 (mono) or 1 (stereo)`,"INVALID_CHANNEL");const a=new Uint8Array(9);let h=64;h|=t.channel<<5,h|=(t.keyFrame?1:0)<<4,h|=s>>8&15,a[0]=h,a[1]=255&s,a[2]=n>>12&255,a[3]=n>>4&255;let c=(15&n)<<4;c|=R[t.sampleRate]<<2,c|=r>>10&3,a[4]=c,a[5]=r>>2&255;let d=(3&r)<<6;return d|=0,a[6]=d,a[7]=o>>8&255,a[8]=255&o,a}class b{constructor(e){this.transport=e}sendBinary(e){this.transport.sendBinary(e)}isConnected(){return this.transport.isConnected}}class D extends t{constructor(e,t){super(),this._wsSender=null,this._sequenceNumber=0,this._isKeyFrame=!0,this._audioStartTime=0,this._isSending=!1,this._audioFrameListener=null,this._audioBuffer=[],this._bufferedSampleCount=0,this._targetSampleRate=24e3,this._bitDepth=16,this._minSamplesToSend=0,this._context=e,this._options=t;const s=t?.input;this._targetSampleRate=s?.sampleRate||24e3,this._bitDepth=s?.bitDepth||16,this._minSamplesToSend=Math.floor(this._targetSampleRate/10),r.info(`Audio Frame Sender created: sampleRate=${this._targetSampleRate}Hz, bitDepth=${this._bitDepth}bit, minSamples=${this._minSamplesToSend}`)}setWebSocketSender(e){this._wsSender=e}setConversationTransport(e){this._wsSender=new b(e)}start(){this.ensureNotDisposed(),this._isSending?r.warn("Audio frame sending already started"):(this._sequenceNumber=0,this._isKeyFrame=!0,this._audioStartTime=Date.now(),this._audioFrameListener=e=>{this._handleAudioFrame(e.data,e.sampleRate)},this._context.eventBus.on("audioFrame",this._audioFrameListener),this._isSending=!0,r.info("Audio frame sending started"))}stop(){this.ensureNotDisposed(),this._isSending&&(this._flushBuffer(),this._audioFrameListener&&(this._context.eventBus.off("audioFrame",this._audioFrameListener),this._audioFrameListener=null),this._isSending=!1,r.info("Audio frame sending stopped"))}_handleAudioFrame(e,t){if(this._isSending)try{Math.abs(t-this._targetSampleRate)>1&&r.warn(`Sample rate mismatch: expected ${this._targetSampleRate}Hz, got ${t}Hz`),this._audioBuffer.push(new Float32Array(e)),this._bufferedSampleCount+=e.length,this._bufferedSampleCount>=this._minSamplesToSend&&this._flushBuffer()}catch(e){r.error("Error handling audio frame:",e)}}_flushBuffer(){if(0!==this._audioBuffer.length&&0!==this._bufferedSampleCount)try{const e=this._bufferedSampleCount,t=new Float32Array(e);let s=0;for(const e of this._audioBuffer)t.set(e,s),s+=e.length;this._audioBuffer=[],this._bufferedSampleCount=0;const i=this._convertToPCM(t,this._bitDepth),n=Math.ceil(this._bitDepth/8),o=i.length*n,a=this._getSampleRateEncoding(this._targetSampleRate),h=Math.floor(Date.now()-this._audioStartTime),c={channel:1===(this._options?.input?.channels||1)?0:1,keyFrame:!!this._isKeyFrame,sequenceNumber:this._sequenceNumber,timestamp:h,sampleRate:a,frameSize:t.length,payloadLength:o},d=this._pcmToUint8Array(i,this._bitDepth);if(setTimeout(()=>{try{this._context.eventBus.emit("audioPayload",{payload:d,sampleRate:this._targetSampleRate,channels:this._options?.input?.channels||1,sequenceNumber:c.sequenceNumber,timestamp:c.timestamp,keyFrame:c.keyFrame,frameSize:c.frameSize})}catch(e){r.error("Error emitting audioPayload event:",e)}},0),this._wsSender&&this._wsSender.isConnected())try{const e=k(c),s=new Uint8Array(e.length+d.length);s.set(e,0),s.set(d,e.length),this._wsSender.sendBinary(s),r.debug(`Audio frame sent via WS: seq=${c.sequenceNumber}, samples=${t.length}, size=${s.length} bytes`)}catch(e){r.error("Error sending audio frame via WebSocket:",e)}this._isKeyFrame=!1,this._sequenceNumber=(this._sequenceNumber+1)%4096}catch(e){r.error("Error flushing audio buffer:",e)}}_convertToPCM(e,t){if(16===t){const t=new Int16Array(e.length);for(let s=0;s<e.length;s++){const i=Math.max(-1,Math.min(1,e[s]));t[s]=i<0?32768*i:32767*i}return t}if(32===t){const t=new Int32Array(e.length);for(let s=0;s<e.length;s++){const i=Math.max(-1,Math.min(1,e[s]));t[s]=2147483647*i}return t}return r.warn(`Unsupported bit depth: ${t}, using 16-bit`),this._convertToPCM(e,16)}_pcmToUint8Array(e,t){const s=Math.ceil(t/8),i=new Uint8Array(e.length*s),n=new DataView(i.buffer);for(let s=0;s<e.length;s++)16===t?n.setInt16(2*s,e[s],!0):32===t&&n.setInt32(4*s,e[s],!0);return i}_getSampleRateEncoding(e){return 16e3===e?0:24e3===e?1:48e3===e?2:(r.warn(`Unsupported sample rate: ${e}, defaulting to 48kHz`),1)}onDispose(){this.stop(),r.info("Audio Frame Sender disposed")}}class A extends t{emitAudioData(e,t){if(this.onAudioData)try{this.onAudioData(e,t)}catch(e){r.error("Error in audio data callback:",e)}}}const N=24e3;class O extends A{constructor(e){super(),this.options=e,this._stream=null,this._audioContext=null,this._sourceNode=null,this._workletNode=null,this._targetSampleRate=N,this._bitDepth=16,this._channels=1;const t=e?.input;this._targetSampleRate=t?.sampleRate||N,this._bitDepth=t?.bitDepth||16,this._channels=t?.channels||1}async start(){this.ensureNotDisposed();try{const e=this.options?.input,t={audio:e?.constraints||{channelCount:this._channels}};this._stream=await navigator.mediaDevices.getUserMedia(t);const s=this._stream.getAudioTracks()[0],i=s.getSettings().sampleRate||44100;this._audioContext=new AudioContext({sampleRate:i});const n=function(){const e=new Blob(["\nclass AudioResamplerProcessor extends AudioWorkletProcessor {\n constructor(options) {\n super();\n this.targetSampleRate = options.processorOptions?.targetSampleRate || 24000;\n this.bitDepth = options.processorOptions?.bitDepth || 16;\n this.channels = options.processorOptions?.channels || 1;\n \n // Resampling related\n // sampleRate is a global in AudioWorkletProcessor representing the AudioContext's sample rate\n this.resampleRatio = this.targetSampleRate / sampleRate;\n \n // Timestamp tracking\n this.frameCount = 0;\n }\n\n process(inputs, outputs, parameters) {\n const input = inputs[0];\n if (!input || input.length === 0 || !input[0] || input[0].length === 0) {\n return true;\n }\n\n const inputData = input[0]; // mono input\n const inputLength = inputData.length;\n \n // Linear resampling\n const outputLength = Math.floor(inputLength * this.resampleRatio);\n const resampledData = new Float32Array(outputLength);\n \n for (let i = 0; i < outputLength; i++) {\n const srcIndex = i / this.resampleRatio;\n const srcIndexFloor = Math.floor(srcIndex);\n const srcIndexCeil = Math.min(srcIndexFloor + 1, inputLength - 1);\n const fraction = srcIndex - srcIndexFloor;\n \n // Linear interpolation\n resampledData[i] = inputData[srcIndexFloor] * (1 - fraction) + inputData[srcIndexCeil] * fraction;\n }\n \n // Post the resampled data\n this.port.postMessage({\n type: 'audioData',\n data: resampledData,\n sampleRate: this.targetSampleRate,\n bitDepth: this.bitDepth,\n frameCount: this.frameCount,\n });\n \n this.frameCount += outputLength;\n \n return true;\n }\n}\n\nregisterProcessor('audio-resampler', AudioResamplerProcessor);\n"],{type:"text/javascript"});return URL.createObjectURL(e)}();await this._audioContext.audioWorklet.addModule(n),this._sourceNode=this._audioContext.createMediaStreamSource(this._stream),this._workletNode=new AudioWorkletNode(this._audioContext,"audio-resampler",{processorOptions:{targetSampleRate:this._targetSampleRate,bitDepth:this._bitDepth,channels:this._channels},numberOfInputs:1,numberOfOutputs:0}),this._workletNode.port.onmessage=e=>{const{type:t,data:s,sampleRate:i}=e.data;"audioData"===t&&s&&this.emitAudioData(s,i)},this._sourceNode.connect(this._workletNode),r.info(`Audio capture started: input=${i}Hz -> output=${this._targetSampleRate}Hz, ${this._bitDepth}bit`)}catch(t){throw e.fromError(t,"AUDIO_CAPTURE_FAILED")}}stop(){this._stream&&(this._stream.getTracks().forEach(e=>e.stop()),this._stream=null),this._workletNode&&(this._workletNode.port.onmessage=null,this._workletNode.disconnect(),this._workletNode=null),this._sourceNode&&(this._sourceNode.disconnect(),this._sourceNode=null),this._audioContext&&(this._audioContext.close(),this._audioContext=null),r.info("Audio capture stopped")}onDispose(){this.stop()}}class M{create(e){return new O(e)}}class P extends t{constructor(e,t,s){super(),this._source=null,this._isCapturing=!1,this._currentOutputTrackId=null,this._context=e,this._inputPipeline=new T(t),this._outputPipeline=new I,this._frameSender=new D(e,t),this._sourceFactory=s||new M,this._inputPipeline.onProcessedAudio=(e,t)=>{this._context.eventBus.emit("audioFrame",{data:e,sampleRate:t})},r.info("Audio Controller created")}setWebSocketSender(e){this._frameSender.setWebSocketSender(e)}async startCapture(){if(this.ensureNotDisposed(),this._isCapturing)r.warn("Audio capture already started");else try{this._source||(this._source=this._sourceFactory.create(this._context.options.audio),this._source.onAudioData=(e,t)=>{this._inputPipeline.process(e,t)}),await this._source.start(),this._isCapturing=!0,this._context.audioState.isCapturing=!0,this._frameSender.start(),this._context.eventBus.emit("audioInputStarted",void 0),r.info("Audio capture started")}catch(e){throw this._context.emitError(e,"AUDIO_CAPTURE_START_FAILED")}}stopCapture(){this.ensureNotDisposed(),this._isCapturing&&(this._source&&this._source.stop(),this._frameSender.stop(),this._isCapturing=!1,this._context.audioState.isCapturing=!1,this._context.eventBus.emit("audioInputStopped",void 0),r.info("Audio capture stopped"))}get isCapturing(){return this._isCapturing}setOutputTrack(e,t,s){this.ensureNotDisposed(),this._outputPipeline.setTrack(e),this._currentOutputTrackId=t,this._context.audioState.isPlaying=!0,this._context.audioState.currentOutputTrackId=t,this._context.eventBus.emit("audioTrackAdded",{trackId:t,participantId:s}),r.info("Audio output track ready")}removeOutputTrack(e){this.ensureNotDisposed(),this._currentOutputTrackId===e&&(this._outputPipeline.removeTrack(),this._currentOutputTrackId=null,this._context.audioState.isPlaying=!1,this._context.audioState.currentOutputTrackId=null,this._context.eventBus.emit("audioTrackRemoved",{trackId:e}),r.info("Audio output track removed"))}setVolume(e){this.ensureNotDisposed(),this._outputPipeline.setVolume(e),this._context.audioState.volume=e,this._context.eventBus.emit("audioVolumeChanged",{volume:e}),r.debug(`Audio volume set to: ${e}`)}getVolume(){return this._outputPipeline.getVolume()}mute(){this.ensureNotDisposed(),this._outputPipeline.mute(),this._context.audioState.isMuted=!0,this._context.eventBus.emit("audioMuted",void 0),r.debug("Audio muted")}unmute(){this.ensureNotDisposed(),this._outputPipeline.unmute(),this._context.audioState.isMuted=!1,this._context.eventBus.emit("audioUnmuted",void 0),r.debug("Audio unmuted")}isMuted(){return this._outputPipeline.isMuted()}onDispose(){this.stopCapture(),this._source&&(this._source.dispose(),this._source=null),this._inputPipeline.dispose(),this._outputPipeline.dispose(),this._frameSender.dispose(),r.info("Audio Controller disposed")}}class L{constructor(){this._currentState=exports.ConversationStateType.IDLE}getCurrentState(){return this._currentState}transitionTo(t){const s=this._currentState;if(!this.canTransition(s,t)){const i=L.TRANSITION_MAP.get(s),n=i?Array.from(i).join(", "):"none";throw new e(`Invalid state transition: cannot transition from "${s}" to "${t}". Current state: "${s}". Allowed transitions: [${n}]`,"INVALID_STATE_TRANSITION")}this._currentState=t}canTransition(e,t){if(e===t)return!1;const s=L.TRANSITION_MAP.get(e);return!!s&&s.has(t)}reset(){this._currentState=exports.ConversationStateType.IDLE}}L.TRANSITION_TABLE=[{from:exports.ConversationStateType.IDLE,to:[exports.ConversationStateType.WAITING,exports.ConversationStateType.ERROR]},{from:exports.ConversationStateType.WAITING,to:[exports.ConversationStateType.STREAMING,exports.ConversationStateType.ERROR]},{from:exports.ConversationStateType.STREAMING,to:[exports.ConversationStateType.COMPLETED,exports.ConversationStateType.ERROR]},{from:exports.ConversationStateType.COMPLETED,to:[exports.ConversationStateType.IDLE,exports.ConversationStateType.WAITING,exports.ConversationStateType.ERROR]},{from:exports.ConversationStateType.ERROR,to:[exports.ConversationStateType.IDLE]}],L.TRANSITION_MAP=(()=>{const e=new Map;for(const t of L.TRANSITION_TABLE){const s=new Set(t.to);e.set(t.from,s)}return new Map(Array.from(e.entries()).map(([e,t])=>[e,new Set(t)]))})();class F extends t{constructor(e,t){super(),this._currentQuestion=null,this._currentAnswer=null,this._sessionId=e,this._stateMachine=new L,this._context=t,this._context.conversationState.currentSessionId=e,r.info(`Conversation session created: ${e}`)}get sessionId(){return this._sessionId}get state(){return this._stateMachine.getCurrentState()}_setQuestion(e){this._currentQuestion=e,this._stateMachine.transitionTo(exports.ConversationStateType.WAITING),this._syncContextState(),this._context.conversationState.currentQuestionId=e.id,this._context.conversationState.isWaiting=!0,this._context.conversationState.isStreaming=!1,this._context.conversationState.currentAnswer=""}get currentQuestion(){return this._currentQuestion}_startAnswer(e){this._currentAnswer={questionId:e,text:"",isComplete:!1,timestamp:Date.now()},this._stateMachine.transitionTo(exports.ConversationStateType.STREAMING),this._syncContextState(),this._context.conversationState.isWaiting=!1,this._context.conversationState.isStreaming=!0}_appendAnswerChunk(e){this._currentAnswer&&(this._currentAnswer.text+=e,this._context.conversationState.currentAnswer=this._currentAnswer.text)}_completeAnswer(){this._currentAnswer&&(this._currentAnswer.isComplete=!0,this._currentAnswer.completedAt=Date.now()),this._stateMachine.transitionTo(exports.ConversationStateType.COMPLETED),this._syncContextState(),this._context.conversationState.isWaiting=!1,this._context.conversationState.isStreaming=!1}get currentAnswer(){return this._currentAnswer}_setError(e){this._stateMachine.transitionTo(exports.ConversationStateType.ERROR),this._syncContextState(),this._context.conversationState.lastError=e,r.error(`Session ${this._sessionId} error: ${e}`)}_syncContextState(){this._context.conversationState.state=this._stateMachine.getCurrentState()}handleEvent(e){const t=this._stateMachine.getCurrentState();switch(e.type){case"QUESTION":if(t!==exports.ConversationStateType.IDLE&&t!==exports.ConversationStateType.COMPLETED)return void r.warn(`Ignoring QUESTION event in invalid state: ${t}`);this._setQuestion(e.payload);break;case"ANSWER_START":if(t!==exports.ConversationStateType.WAITING)return void r.warn(`Ignoring ANSWER_START event in invalid state: ${t}. Expected: WAITING`);this._startAnswer(e.payload);break;case"ANSWER_CHUNK":if(t!==exports.ConversationStateType.STREAMING)return void r.warn(`Ignoring ANSWER_CHUNK event in invalid state: ${t}. Expected: STREAMING`);this._appendAnswerChunk(e.payload&&e.payload.chunk||""),e.payload&&e.payload.isComplete&&this._completeAnswer();break;case"ANSWER_COMPLETE":if(t!==exports.ConversationStateType.STREAMING)return void r.warn(`Ignoring ANSWER_COMPLETE event in invalid state: ${t}. Expected: STREAMING`);this._completeAnswer();break;case"ERROR":this._setError(e.payload);break;default:r.warn(`Unknown event type: ${e.type}`)}}reset(){this._stateMachine.reset(),this._currentQuestion=null,this._currentAnswer=null}onDispose(){this.reset(),r.info(`Conversation session disposed: ${this._sessionId}`)}}class V extends t{constructor(){super(...arguments),this._buffers=new Map}appendChunk(e,t){this.ensureNotDisposed();const s=(this._buffers.get(e)||"")+t;return this._buffers.set(e,s),r.debug(`Message chunk appended for question ${e}, length: ${s.length}`),s}getMessage(e){return this._buffers.get(e)||null}complete(e){const t=this.getMessage(e)||"";return this._buffers.delete(e),r.debug(`Message assembly completed for question ${e}, length: ${t.length}`),t}clear(e){this._buffers.delete(e)}onDispose(){this._buffers.clear(),r.info("Message Assembler disposed")}}class $ extends t{dispose(){throw new Error("Method not implemented.")}set onTextInput(e){this._onTextInput=e}route(e){if(this.ensureNotDisposed(),"string"!=typeof e)return void r.warn("Text input strategy received non-string input");const t=e;if(t&&0!==t.trim().length)if(this._onTextInput)try{this._onTextInput(t),r.debug(`Text input routed: ${t.substring(0,50)}...`)}catch(e){r.error("Error routing text input:",e)}else r.warn("No text input handler registered");else r.warn("Empty text input ignored")}onDispose(){this._onTextInput=void 0,r.info("Text Input Routing Strategy disposed")}}class U extends t{dispose(){throw new Error("Method not implemented.")}set onVoiceInput(e){this._onVoiceInput=e}route(e){if(this.ensureNotDisposed(),!(e instanceof Float32Array))return void r.warn("Voice input strategy received non-Float32Array input");const t=e;if(t&&0!==t.length)if(this._onVoiceInput)try{this._onVoiceInput(t),r.debug(`Voice input routed: ${t.length} samples`)}catch(e){r.error("Error routing voice input:",e)}else r.warn("No voice input handler registered");else r.warn("Empty audio input ignored")}onDispose(){this._onVoiceInput=void 0,r.info("Voice Input Routing Strategy disposed")}}class W extends t{constructor(){super(),this._textStrategy=new $,this._voiceStrategy=new U,r.info("Input Router created")}set onTextInput(e){this._textStrategy.onTextInput=e}set onVoiceInput(e){this._voiceStrategy.onVoiceInput=e}routeText(e){this.ensureNotDisposed(),this._textStrategy.route(e)}routeVoice(e){this.ensureNotDisposed(),this._voiceStrategy.route(e)}onDispose(){this._textStrategy.dispose(),this._voiceStrategy.dispose(),r.info("Input Router disposed")}}class q{generateSessionId(){return`session_${Date.now()}_${Math.random().toString(36).substring(2,9)}`}generateQuestionId(){return Math.random().toString(36).substring(2,6)}}class z extends t{constructor(e,t){super(),this._transport=null,this._sessions=new Map,this._context=e,this._assembler=new V,this._router=new W,this._idService=new q,this._router.onTextInput=e=>{this.handleTextInput(e)},r.info("Conversation Manager created")}setTransport(e){this._transport=e}get inputRouter(){return this._router}async sendQuestion(e,t={speed:100,mood:0,vol:50}){this.ensureNotDisposed();const s=this._idService.generateQuestionId(),i={id:s,text:e,timestamp:Date.now(),inputMode:"text"},n=this._idService.generateSessionId(),o=new F(n,this._context);if(o.handleEvent({type:"QUESTION",payload:i}),this._sessions.set(s,o),this._transport)try{this._transport.sendText(s,e,200,t)}catch(e){throw r.error("Error sending question via transport:",e),o.handleEvent({type:"ERROR",payload:"Failed to send question"}),this._context.eventBus.emit("error",{error:e instanceof Error?e:new Error(String(e))}),e}else r.warn("Transport not set, question not sent");return this._context.eventBus.emit("questionSent",{questionId:s,text:e}),this._context.eventBus.emit("answerWaiting",{questionId:s}),r.info(`Question sent: ${s}`),s}handleServerPong(){this.ensureNotDisposed(),this._transport&&this._transport.handlePongReceived()}willDisconnect(){this.ensureNotDisposed(),this._transport?.willDisconnect()}handleTextInput(e){this.sendQuestion(e).catch(e=>{r.error("Error sending question:",e)})}handleAnswerChunk(e,t,s){this.ensureNotDisposed();const i=this._sessions.get(e);if(!i)return void r.warn(`No active session for answer chunk: ${e}`);if(i.state===exports.ConversationStateType.WAITING&&i.handleEvent({type:"ANSWER_START",payload:e}),s){i.handleEvent({type:"ANSWER_COMPLETE"});const t=this._assembler.complete(e);this._context.eventBus.emit("answerCompleted",{questionId:e,fullAnswer:t});try{i.dispose()}catch(e){r.error("Error disposing session:",e)}this._sessions.delete(e)}else i.handleEvent({type:"ANSWER_CHUNK",payload:{uid:e,chunk:t,isComplete:s}}),this._assembler.appendChunk(e,t),this._context.eventBus.emit("answerChunk",{questionId:e,chunk:t,isComplete:s})}handleServerInitiatedMessage(e,t){this.ensureNotDisposed(),this._context.eventBus.emit("serverMessage",{questionId:e,message:t,type:"text"})}handleAsrTextReceived(e,t){this.ensureNotDisposed();const s=this._idService.generateSessionId(),i=new F(s,this._context);i.handleEvent({type:"QUESTION",payload:{id:e,text:t,timestamp:Date.now(),inputMode:"voice"}}),this._sessions.set(e,i),this._context.eventBus.emit("asrReceived",{questionId:e,text:t})}onDispose(){for(const e of this._sessions.values())try{e.dispose()}catch(e){r.error("Error disposing session:",e)}this._sessions.clear(),this._assembler.dispose(),this._router.dispose(),r.info("Conversation Manager disposed")}}class K extends t{constructor(e,t){super(),this._manager=new z(e,t),r.info("Conversation Controller created")}get inputRouter(){return this._manager.inputRouter}get manager(){return this._manager}setTransport(e){this._manager.setTransport(e)}async sendQuestion(e,t){return this.ensureNotDisposed(),this._manager.sendQuestion(e,t)}onDispose(){this._manager.dispose(),r.info("Conversation Controller disposed")}}class B extends t{constructor(){super(...arguments),this._tracks=new Map,this._participants=new Map}register(e,t,s){this.ensureNotDisposed(),this._tracks.set(e,t),this._participants.has(s)||this._participants.set(s,new Set),this._participants.get(s).add(e),r.debug(`Track registered: ${e} from participant ${s}`)}unregister(e){const t=this._tracks.get(e);if(t){t.stop(),this._tracks.delete(e);for(const[t,s]of this._participants.entries())if(s.has(e)){s.delete(e),0===s.size&&this._participants.delete(t);break}r.debug(`Track unregistered: ${e}`)}}getTrack(e){return this._tracks.get(e)||null}getParticipantTracks(e){const t=this._participants.get(e);return t?Array.from(t):[]}getAllTrackIds(){return Array.from(this._tracks.keys())}clear(){for(const e of this._tracks.values())e.stop();this._tracks.clear(),this._participants.clear(),r.info("All tracks cleared")}onDispose(){this.clear()}}class H extends t{constructor(e,t){super(),this._videoController=null,this._context=e,this._trackRegistry=t,r.info("Video Track Handler created")}setVideoController(e){this._videoController=e}handleTrackSubscribed(e,t,s){this.ensureNotDisposed(),this._trackRegistry.register(t,e,s),this._videoController?this._videoController.setTrack(e,t,s):this._context.eventBus.emit("videoTrackAdded",{trackId:t,participantId:s}),r.debug(`Video track subscribed: ${t}`)}handleTrackUnsubscribed(e,t,s){this.ensureNotDisposed(),this._videoController?this._videoController.removeTrack(t):this._context.eventBus.emit("videoTrackRemoved",{trackId:t,participantId:s}),this._trackRegistry.unregister(t),r.debug(`Video track unsubscribed: ${t}`)}supports(e){return"video"===e.kind}onDispose(){r.info("Video Track Handler disposed")}}class G extends t{constructor(e,t){super(),this._audioController=null,this._context=e,this._trackRegistry=t,r.info("Audio Track Handler created")}setAudioController(e){this._audioController=e}handleTrackSubscribed(e,t,s){this.ensureNotDisposed(),this._trackRegistry.register(t,e,s),this._audioController?this._audioController.setOutputTrack(e,t,s):this._context.eventBus.emit("audioTrackAdded",{trackId:t,participantId:s}),r.debug(`Audio track subscribed: ${t}`)}handleTrackUnsubscribed(e,t,s){this.ensureNotDisposed(),this._audioController?this._audioController.removeOutputTrack(t):this._context.eventBus.emit("audioTrackRemoved",{trackId:t}),this._trackRegistry.unregister(t),r.debug(`Audio track unsubscribed: ${t}`)}supports(e){return"audio"===e.kind}onDispose(){r.info("Audio Track Handler disposed")}}class Q extends t{constructor(e,t){super(),this._context=e,this._trackRegistry=t,this._handlers=[new H(e,t),new G(e,t)],r.info("LiveKit Event Adapter created")}setVideoController(e){const t=this._handlers.find(e=>e instanceof H);t&&t.setVideoController(e)}setAudioController(e){const t=this._handlers.find(e=>e instanceof G);t&&t.setAudioController(e)}handleTrackSubscribed(e,t,s){this.ensureNotDisposed();const i=this._findHandler(e);i?i.handleTrackSubscribed(e,t,s):r.warn(`No handler found for track, trackId: ${t}`)}handleTrackUnsubscribed(e,t){this.ensureNotDisposed();const s=this._trackRegistry.getTrack(e);if(s){const i=this._findHandler(s);i?i.handleTrackUnsubscribed(s,e,t):(this._trackRegistry.unregister(e),r.warn(`No handler found for track, trackId: ${e}`))}}_findHandler(e){return this._handlers.find(t=>t.supports(e))||null}onDispose(){this._handlers.forEach(e=>{try{e.dispose()}catch(e){r.error("Error disposing track handler:",e)}}),this._handlers.length=0,r.info("LiveKit Event Adapter disposed")}}class j extends t{constructor(e){super(),this._room=null,this._context=e,this._trackRegistry=new B,this._eventAdapter=new Q(e,this._trackRegistry),r.info("LiveKit Service created")}async connect(t,s,i,n){if(this.ensureNotDisposed(),this._room&&this._room.isConnected())r.warn("Already connected to LiveKit room");else try{const{Room:e,RoomEvent:n}=await import("livekit-client");r.info(`Connecting to LiveKit room: ${i} at ${t}`);const o=new e;o.prepareConnection(t,s),o.on(n.TrackSubscribed,(e,t,s)=>{this._handleTrackSubscribed(e,t,s)}),o.on(n.TrackUnsubscribed,(e,t,s)=>{this._handleTrackUnsubscribed(e,t,s)}),o.on(n.Disconnected,()=>{r.info("LiveKit room disconnected"),this._room=null}),await o.connect(t,s,{autoSubscribe:!0,maxRetries:this._context.options.reconnect?.maxAttempts||3}),this._room=o,this._context.eventBus.emit("connected",{source:"livekit"}),r.info("Connected to LiveKit room")}catch(t){throw e.fromError(t,"LIVEKIT_CONNECT_FAILED")}}_handleTrackSubscribed(e,t,s){try{const i=e,n=t,o=s,a=i.mediaStreamTrack||i.track;if(!a)return void r.warn("Track does not have MediaStreamTrack");const h=n.trackSid,c=o.identity;this._eventAdapter.handleTrackSubscribed(a,h,c)}catch(e){r.error("Error handling track subscribed:",e)}}_handleTrackUnsubscribed(e,t,s){try{const e=s,i=t.trackSid,n=e.identity;this._eventAdapter.handleTrackUnsubscribed(i,n)}catch(e){r.error("Error handling track unsubscribed:",e)}}async disconnect(){if(this._room)try{await this._room.disconnect(),this._room=null,this._context.eventBus.emit("disconnected",{source:"livekit",reason:"Disconnected from LiveKit room"}),r.info("Disconnected from LiveKit room")}catch(e){r.error("Error disconnecting from LiveKit room:",e),this._room=null}}isConnected(){return null!==this._room&&this._room.isConnected()}getTrackRegistry(){return this._trackRegistry}get trackRegistry(){return this._trackRegistry}getEventAdapter(){return this._eventAdapter}onDispose(){this.disconnect(),this._trackRegistry.dispose(),this._eventAdapter.dispose(),r.info("LiveKit Service disposed")}}class J extends t{constructor(e){super(),this._conversationManager=null,this._context=e,r.info("WebSocket Dispatcher created")}setConversationManager(e){this._conversationManager=e,r.debug("Conversation manager set in dispatcher")}dispatch(e){this.ensureNotDisposed();try{if("ws"===e.type)return void this._handleWSServerMessage(e);if("text"===e.type)return void this._handleServerTextMessage(e)}catch(e){r.error("Error dispatching message:",e)}}_handleWSServerMessage(e){101===e.code?(this._conversationManager?.handleServerPong(),r.debug("Received pingpong response")):102===e.code&&(r.warn("Server will disconnect"),this._conversationManager?.willDisconnect())}_handleServerTextMessage(e){if(!this._conversationManager)return void r.warn("Conversation manager not set, text message ignored");const{uid:t,payload:s,code:i}=e;200===i?(this._conversationManager.handleAnswerChunk(t,s,!1),r.debug(`Answer received (code 401) for uid: ${t}`)):201===i?(this._conversationManager.handleAnswerChunk(t,"",!0),r.debug(`Answer completed (code 411) for uid: ${t}`)):300===i?(this._conversationManager.handleAsrTextReceived(t,s),r.debug(`ASR text chunk received (code 410) for uid: ${t}`)):400===i&&(this._conversationManager.handleServerInitiatedMessage(t,s),r.debug(`Server initiated message received (code 412) for uid: ${t}`))}onDispose(){r.info("WebSocket Dispatcher disposed")}}class Z extends t{constructor(e){super(),this._ws=null,this._dispatcher=null,this._isConnecting=!1,this._activeTimers=new Set,this._retryCount=0,this._maxRetries=3,this._pingTimer=void 0,this._pongTimer=void 0,this._isExplicitDisconnect=!1,this._context=e,this._dispatcher=new J(e)}setConversationManager(e){this._dispatcher&&this._dispatcher.setConversationManager(e)}async connect(){if(this.ensureNotDisposed(),this._stopHeartbeat(),!this._isConnecting&&!this.isConnected&&this._ws?.readyState!==WebSocket.OPEN){this._isConnecting=!0,this._isExplicitDisconnect=!1;try{return this._ws=new WebSocket(this._context.wsUrl),new Promise((t,s)=>{this._ws.onopen=()=>{this._isConnecting=!1,this._retryCount=0,this._context.sessionState.isConnected=!0,this._context.sessionState.status=exports.SessionStatus.CONNECTED,this.sendPing(),this._context.eventBus.emit("connected",{source:"ws"}),r.info("Conversation transport connected"),t()},this._ws.onerror=t=>{this._isConnecting=!1,r.error("Conversation transport error:",t),this._context.eventBus.emit("error",{error:new e("WebSocket connection error","WS_CONNECT_ERROR",t)}),s(new e("WebSocket connection error","WS_CONNECT_ERROR",t))},this._ws.onclose=()=>{this._handleDisconnect()},this._ws.onmessage=e=>{this._handleMessage(e.data)}})}catch(e){throw this._isConnecting=!1,this._context.emitError(e,"WS_CONNECT_FAILED")}}}disconnect(){this._isExplicitDisconnect=!0,this._stopHeartbeat(),this._ws&&(this._ws.close(),this._ws=null),this._context.sessionState.isConnected=!1,this._context.sessionState.status=exports.SessionStatus.DISCONNECTED,r.info("Conversation transport disconnected")}_handleDisconnect(){if(this._stopHeartbeat(),this._isConnecting=!1,!this._isExplicitDisconnect&&this._retryCount<this._maxRetries){this._retryCount++;const e=Math.min(1e3*Math.pow(2,this._retryCount-1),1e4);r.warn(`Connection lost. Retry ${this._retryCount} in ${e}ms`);const t=setTimeout(()=>{this._isExplicitDisconnect||this.isDisposed||this.connect().catch(()=>{})},e);this._registerTimer(t)}else this._context.sessionState.isConnected=!1,this._context.sessionState.status=exports.SessionStatus.DISCONNECTED,this._context.eventBus.emit("disconnected",{source:"ws",reason:"Closed"})}_registerTimer(e){return this._activeTimers.add(e),e}_clearTimer(e){e&&(clearTimeout(e),this._activeTimers.delete(e))}sendPing(){if(!this.isConnected)return;this._ws?.send(JSON.stringify({type:"ws",code:101,payload:"ping"})),clearTimeout(this._pongTimer),this._pongTimer=setTimeout(()=>{r.error("Pong timeout (30s). Reconnecting..."),this._ws?.close()},3e4)}handlePongReceived(){clearTimeout(this._pongTimer),this._clearTimer(this._pingTimer),this._pingTimer=setTimeout(()=>{this.sendPing()},3e3)}willDisconnect(){if(this.ensureNotDisposed(),this._ws&&this._ws.readyState===WebSocket.OPEN){const e={type:"ws",code:102,payload:"will disconnect"},t=JSON.stringify(e);this._ws.send(t),this._ws.close(),this._ws=null}}sendText(t,s,i=200,n){if(this.ensureNotDisposed(),!this._ws||this._ws.readyState!==WebSocket.OPEN)throw new e("WebSocket is not connected","WS_NOT_CONNECTED");try{const e={type:"text",code:i,uid:t,metadata:n,payload:s},o=JSON.stringify(e);this._ws.send(o),r.debug("Text message sent via transport:",t)}catch(e){throw this._context.emitError(e,"WS_SEND_FAILED")}}_handleMessage(e){try{if("string"!=typeof e)return;const t=JSON.parse(e);r.debug("Message received:",t.type),this._dispatcher?this._dispatcher.dispatch(t):r.warn("Dispatcher not set, message ignored")}catch(e){r.error("Error parsing message:",e),this._context.emitError(e,"WS_PARSE_ERROR")}}sendBinary(e){if(this.ensureNotDisposed(),this._ws&&this._ws.readyState===WebSocket.OPEN)try{this._ws.send(e),r.debug("Binary data sent via transport")}catch(e){r.error("Error sending binary data:",e)}else r.debug("WebSocket not connected, binary data dropped")}get isConnected(){return this._ws?.readyState===WebSocket.OPEN}_stopHeartbeat(){this._clearTimer(this._pingTimer),this._clearTimer(this._pongTimer)}isConnectedMethod(){return this.isConnected}onDispose(){this._stopHeartbeat(),this.disconnect(),this._dispatcher&&(this._dispatcher.dispose(),this._dispatcher=null),r.info("Conversation transport disposed")}}const Y=["sdk:connected","sdk:disconnected","sdk:error","media:video:trackAdded","media:audio:captureStarted","conversation:question:sent","conversation:answer:waiting","conversation:server:message","conversation:asr:received","conversation:answer:chunk","conversation:answer:completed"],X=/^[a-z]+:[a-z]+(:[a-zA-Z]+)?$/;class ee{constructor(e){this.inner=e,this.listeners=new Map,this.forwardedVideoTrackIds=new Set,this.wsConnected=!1,this.livekitConnected=!1,this.internalMap={error:{public:"sdk:error",sanitizer:e=>({message:e?.error?.message,code:e?.error?.code})},videoTrackAdded:{public:"media:video:trackAdded",sanitizer:e=>({available:!0})},audioInputStarted:{public:"media:audio:captureStarted"},questionSent:{public:"conversation:question:sent",sanitizer:e=>({questionId:e?.questionId,text:String(e?.text||"")})},answerWaiting:{public:"conversation:answer:waiting",sanitizer:e=>({questionId:e?.questionId})},serverMessage:{public:"conversation:server:message",sanitizer:e=>({questionId:e?.questionId,message:String(e?.message||""),type:String(e?.type||"")})},asrReceived:{public:"conversation:asr:received",sanitizer:e=>({questionId:e?.questionId,text:String(e?.text||"")})},answerChunk:{public:"conversation:answer:chunk",sanitizer:e=>({questionId:e?.questionId,chunk:String(e?.chunk||""),isComplete:!!e?.isComplete})},answerCompleted:{public:"conversation:answer:completed",sanitizer:e=>({questionId:e?.questionId,fullAnswer:String(e?.fullAnswer||"")})}},Object.keys(this.internalMap).forEach(e=>{this.inner.on(e,t=>this.handleInternalEvent(e,t))}),this.inner.on("connected",e=>this.handleConnected(e,!0)),this.inner.on("disconnected",e=>this.handleConnected(e,!1)),Y.forEach(e=>{this.inner.on(e,t=>this.handlePublicEvent(e,t))})}publicAPI(){return{on:this.on.bind(this),off:this.off.bind(this),once:this.once.bind(this)}}on(e,t){const s=String(e);return this.assertAllowed(s),this.listeners.has(s)||this.listeners.set(s,new Set),this.listeners.get(s).add(t),()=>this.off(e,t)}once(e,t){const s=String(e);this.assertAllowed(s);const i=s=>{try{t(s)}finally{this.off(e,i)}};return this.on(e,i)}off(e,t){const s=String(e);this.assertAllowed(s);const i=this.listeners.get(s);i&&(i.delete(t),0===i.size&&this.listeners.delete(s))}handleInternalEvent(e,t){const s=this.internalMap[e];if(!s)return;const i=s.public;if(-1===Y.indexOf(i))return;if("media:video:trackAdded"===i){const e=t?.trackId||t?.id;if("string"==typeof e){if(this.forwardedVideoTrackIds.has(e))return;this.forwardedVideoTrackIds.add(e)}}const n=s.sanitizer?s.sanitizer(t):t;if(!X.test(i))return;const r=this.listeners.get(i);r&&0!==r.size&&r.forEach(e=>{try{e(n)}catch(e){console.error("PublicEventEmitter listener error",e)}})}handlePublicEvent(e,t){if(-1===Y.indexOf(e))return;const s=Object.values(this.internalMap).find(t=>t.public===e),i=s&&s.sanitizer?s.sanitizer(t):t;if("media:video:trackAdded"===e){const e=t?.trackId||t?.id;if("string"==typeof e){if(this.forwardedVideoTrackIds.has(e))return;this.forwardedVideoTrackIds.add(e)}}const n=this.listeners.get(e);n&&0!==n.size&&n.forEach(e=>{try{e(i)}catch(e){console.error("PublicEventEmitter listener error",e)}})}handleConnected(e,t){"livekit"===e.source?this.livekitConnected=t:"ws"===e.source&&(this.wsConnected=t),this.maybeEmitSdkConnected()}maybeEmitSdkConnected(){const e={livekit:!!this.livekitConnected,ws:!!this.wsConnected,all:!(!this.livekitConnected||!this.wsConnected)},t=JSON.stringify(e);this.lastConnectedPayloadJson!==t&&(this.lastConnectedPayloadJson=t,this.inner.emit("sdk:connected",e))}assertAllowed(e){if(-1===Y.indexOf(e))throw new Error(`Event "${e}" is not allowed for public consumers`);if(!X.test(e))throw new Error(`Event name "${e}" does not follow namespace:domain[:action] naming`)}}class te extends t{constructor(e,t,s){super(),this._requestCounter=0,this._context=e,this._baseURL=t||"",this._defaultHeaders=s||{},r.info(`HTTP Service created with baseURL: ${this._baseURL||"none"}`)}setAuthToken(e){this._defaultHeaders.Authorization=`Bearer ${e}`}request(e){this.ensureNotDisposed();const t=e.requestId||`req_${Date.now()}_${++this._requestCounter}`,s=this._buildURL(e.url,e.params),i=this._mergeHeaders(e.headers),n={method:e.method||"GET",headers:i};void 0!==e.data&&"GET"!==(e.method||"GET")&&("string"==typeof e.data?n.body=e.data:(n.body=JSON.stringify(e.data),i["Content-Type"]||i["content-type"]||(i["Content-Type"]="application/json")));const o=e.timeout||3e4,a=new AbortController;return n.signal=a.signal,new Promise((i,h)=>{const c=setTimeout(()=>a.abort(),o);fetch(s,n).then(async n=>{clearTimeout(c);const o={};let a;n.headers.forEach((e,t)=>{o[t]=e});const h=n.headers.get("content-type");a=h&&h.includes("application/json")?await n.json():await n.text();const d={requestId:t,status:n.status,headers:o,data:a,config:e};r.debug(`HTTP request succeeded: ${e.method} ${s} [${t}]`),i(d)}).catch(i=>{clearTimeout(c);const n=i&&"AbortError"===i.name,o={requestId:t,status:i&&i.status||void 0,message:n?"Request aborted (timeout)":i&&i.message||"HTTP request failed",error:i,config:e};r.error(`HTTP request failed: ${e.method} ${s} [${t}]`,i),h(o)})})}get(e,t,s){return this.request({...s,url:e,method:"GET",params:t})}post(e,t,s){return this.request({...s,url:e,method:"POST",data:t})}put(e,t,s){return this.request({...s,url:e,method:"PUT",data:t})}delete(e,t){return this.request({...t,url:e,method:"DELETE"})}patch(e,t,s){return this.request({...s,url:e,method:"PATCH",data:t})}_buildURL(e,t){if(e.startsWith("http://")||e.startsWith("https://"))return this._appendParams(e,t);let s=this._baseURL;return!s||s.endsWith("/")||e.startsWith("/")?s&&s.endsWith("/")&&e.startsWith("/")&&(s=s.slice(0,-1)):s+="/",s+=e,this._appendParams(s,t)}_appendParams(e,t){if(!t||0===Object.keys(t).length)return e;const s=new URLSearchParams;for(const[e,i]of Object.entries(t))s.append(e,String(i));const i=e.includes("?")?"&":"?";return`${e}${i}${s.toString()}`}_mergeHeaders(e){const t={...this._defaultHeaders};return e&&Object.assign(t,e),t}onDispose(){r.info("HTTP Service disposed")}}class se extends t{constructor(e,t){super(),this._context=e,this._httpService=new te(e,t||"https://api.newportai.com/s2/aigc/api/vih_dispatcher")}getAuthToken(){return this.ensureNotDisposed(),this._httpService?.request({url:"/auth/login",method:"GET",data:{}}).then(e=>{0===e.data.code&&this._httpService?.setAuthToken(e.data.data.token)}).catch(e=>{throw this._context.emitError(e,"SDK_AUTH_TOKEN_FAILED")})}getLivekitConfig(){return this.ensureNotDisposed(),this._httpService?.request({url:"/stream/v1/start",method:"POST",data:{avatarName:this._context.options.avatarName}}).then(t=>{if(0===t.data.code){const e=t.data.data;return this._context.setLivekitConfig(e.livekitUrl,e.roomToken,e.roomId),this._context.setWsUrl(`${this._context.options.wsUrlPrefix||"wss://api.newportai.com/s2/aigc/api/ws_dispatch/render/v1/stream"}/${e.roomId}/${this._context.options.avatarName}`),!0}throw e.fromError(t.data.message,"SDK_GET_LIVEKIT_CONFIG_FAILED")}).catch(t=>{throw e.fromError(t,"SDK_GET_LIVEKIT_CONFIG_FAILED")})}switchVideo({onceActions:e,loopActions:t}){return this.ensureNotDisposed(),this._httpService?.request({url:"/avatar/v1/switch-video",method:"POST",data:{roomId:this._context.roomId,onceActions:e,loopActions:t}}).then(e=>{if(0===e.data.code)return"success";throw this._context.emitError(e.data.message,"SDK_SWITCH_VIDEO_FAILED")})}interruptConversation(){return this.ensureNotDisposed(),this._httpService?.request({url:"/stream/v1/interrupt",method:"POST",data:{roomId:this._context.roomId}}).then(e=>{if(0===e.data.code)return"success";throw this._context.emitError(e.data.message,"SDK_INTERRUPT_CONVERSATION_FAILED")})}disconnectConversation(){return this.ensureNotDisposed(),this._httpService?.request({url:"/stream/v1/stop",method:"POST",data:{roomId:this._context.roomId}}).then(e=>{if(0===e.data.code)return"success";throw this._context.emitError(e.data.message,"SDK_STOP_CONVERSATION_FAILED")})}onDispose(){this._httpService.dispose()}}class ie extends t{constructor(e){super(),this._videoController=null,this._audioController=null,this._conversationController=null,this._liveKitService=null,this._conversationTransport=null,this._isConnected=!1,this._httpController=null,this._preConnectPromise=null,this._context=new l(e),r.info("SDK Client created")}get events(){return this.ensureNotDisposed(),this._publicEventAPI||(this._publicEmitter=new ee(this._context.eventBus),this._publicEventAPI=this._publicEmitter.publicAPI()),this._publicEventAPI}pushActions({onceActions:e,loopActions:t}){return this.ensureNotDisposed(),this._ensureInitialized(),this._httpController?.switchVideo({onceActions:e,loopActions:t})}interruptConnection(){return this.ensureNotDisposed(),this._ensureInitialized(),this._httpController?.interruptConversation()}sendTextQuestion(t){if(this.ensureNotDisposed(),this._ensureInitialized(),this._conversationController)return this._conversationController.sendQuestion(t);throw new e("Conversation controller is not available","CONVERSATION_CONTROLLER_NOT_AVAILABLE")}async startAudioCapture(){if(this.ensureNotDisposed(),this._ensureInitialized(),!this._audioController)throw new e("Audio controller is not available","AUDIO_CONTROLLER_NOT_AVAILABLE");await this._audioController.startCapture()}async stopAudioCapture(){if(this.ensureNotDisposed(),this._ensureInitialized(),!this._audioController)throw new e("Audio controller is not available","AUDIO_CONTROLLER_NOT_AVAILABLE");await this._audioController.stopCapture()}setVolume(t){if(this.ensureNotDisposed(),this._ensureInitialized(),!this._audioController)throw new e("Audio controller is not available","AUDIO_CONTROLLER_NOT_AVAILABLE");this._audioController.setVolume(t)}getVolume(){if(this.ensureNotDisposed(),this._ensureInitialized(),!this._audioController)throw new e("Audio controller is not available","AUDIO_CONTROLLER_NOT_AVAILABLE");return this._audioController?.getVolume()||1}mute(){if(this.ensureNotDisposed(),this._ensureInitialized(),!this._audioController)throw new e("Audio controller is not available","AUDIO_CONTROLLER_NOT_AVAILABLE");this._audioController.mute()}get isAudioCapturing(){return this.ensureNotDisposed(),this._ensureInitialized(),!!this._audioController&&this._audioController.isCapturing}async preConnect(){return this.ensureNotDisposed(),this._preConnectPromise||(this._preConnectPromise=(async()=>{try{r.info("Creating HTTP controller..."),this._httpController=new se(this._context,this._context.options.http?.baseURL),r.info("Getting auth token..."),await this._httpController.getAuthToken(),r.info("Getting livekit config...");if(!!!await(this._httpController?.getLivekitConfig()))throw new Error("Config missing");return!0}catch(e){throw this._preConnectPromise=null,this._context.emitError(e,"SDK_PRECONNECT_FAILED")}})()),this._preConnectPromise}async connect(){if(this.ensureNotDisposed(),this._isConnected)r.warn("SDK already initialized");else{try{if(!await this.preConnect())throw new e("PreConnect failed without explicit error","SDK_INITIALIZATION_FAILED")}catch(e){throw this._context.emitError(e,"SDK_INITIALIZATION_FAILED")}try{if(r.info("Initializing SDK..."),this._context.sessionState.status=exports.SessionStatus.CONNECTING,this._videoController=new y(this._context,this._context.options.video),this._audioController=new P(this._context,this._context.options.audio),this._conversationController=new K(this._context),this._liveKitService=new j(this._context),this._conversationTransport=new Z(this._context),this._liveKitService&&this._videoController&&this._audioController){const e=this._liveKitService.getEventAdapter();e&&("function"==typeof e.setVideoController&&e.setVideoController(this._videoController),"function"==typeof e.setAudioController&&e.setAudioController(this._audioController))}this._audioController&&this._conversationTransport&&this._audioController.setWebSocketSender({sendBinary:e=>{this._conversationTransport.sendBinary(e)},isConnected:()=>this._conversationTransport.isConnected}),this._conversationTransport&&this._conversationController&&(this._conversationTransport.setConversationManager(this._conversationController.manager),this._conversationController.setTransport(this._conversationTransport)),await this._liveKitService.connect(this._context.livekitUrl,this._context.token,this._context.options.avatarName),this._conversationTransport&&await this._conversationTransport.connect(),this._isConnected=!0,r.info("SDK initialized and connected")}catch(e){throw await this._cleanup(),this._context.emitError(e,"SDK_INITIALIZATION_FAILED")}}}async disconnect(){if(this.ensureNotDisposed(),this._isConnected){r.info("Disconnecting SDK..."),this._context.sessionState.status=exports.SessionStatus.DISCONNECTED;try{this._conversationTransport&&this._conversationTransport.disconnect(),this._liveKitService&&await this._liveKitService.disconnect(),this._audioController&&this._audioController.stopCapture(),this._httpController&&this._httpController.disconnectConversation(),this._preConnectPromise=null,this._isConnected=!1,this._context.sessionState.isConnected=!1,r.info("SDK disconnected")}catch(e){throw r.error("Error during disconnect:",e),this._context.emitError(e,"SDK_DISCONNECT_FAILED")}}}async reconnect(){if(this.ensureNotDisposed(),this._isConnected)r.warn("SDK is already connected, skipping reconnect");else try{await this.preConnect(),this._conversationTransport&&this._conversationTransport.connect(),this._liveKitService&&await this._liveKitService.connect(this._context.livekitUrl,this._context.token,this._context.options.avatarName),this._audioController&&this._audioController.stopCapture(),this._isConnected=!0,this._context.sessionState.isConnected=!0,r.info("SDK reconnected")}catch(e){throw r.error("Error during disconnect:",e),this._context.emitError(e,"SDK_DISCONNECT_FAILED")}}async _cleanup(){if(this._conversationTransport&&this._conversationTransport.disconnect(),this._liveKitService)try{await this._liveKitService.disconnect()}catch(e){r.error("Error disconnecting LiveKit:",e)}this._audioController&&this._audioController.stopCapture()}get isConnected(){return this.ensureNotDisposed(),this._isConnected&&this._context.sessionState.isConnected}_ensureInitialized(){if(!this._isConnected)throw new e("SDK is not initialized. Call connect() first.","SDK_NOT_INITIALIZED")}onDispose(){this.disconnect().catch(e=>{r.error("Error during disconnect in dispose:",e)}),this._videoController&&(this._videoController.dispose(),this._videoController=null),this._audioController&&(this._audioController.dispose(),this._audioController=null),this._conversationController&&(this._conversationController.dispose(),this._conversationController=null),this._liveKitService&&(this._liveKitService.dispose(),this._liveKitService=null),this._conversationTransport&&(this._conversationTransport.dispose(),this._conversationTransport=null),this._httpController&&(this._httpController.dispose(),this._httpController=null),this._context.dispose(),this._isConnected=!1,r.info("SDK Client disposed")}}class ne extends t{constructor(e,t){super(),this._videoElement=null,this._videoUrl=null,this._isPlaying=!1,this._frameCallbackId=null,this._videoUrl=e,t?this._videoElement=t:(this._videoElement=document.createElement("video"),this._videoElement.style.opacity="0",this._videoElement.muted=!0,this._videoElement.playsInline=!0,this._videoElement.loop=!0,document.querySelector("#video-container")?.appendChild(this._videoElement)),r.info("Local Video Debug Source created")}get videoElement(){return this._videoElement}async load(){if(!this._videoElement)throw new Error("Video element or URL not set");return new Promise((e,t)=>{const s=this._videoElement,i=()=>{s.removeEventListener("loadedmetadata",i),s.removeEventListener("error",n),r.info(`Video loaded: ${s.videoWidth}x${s.videoHeight}`),e()},n=e=>{s.removeEventListener("loadedmetadata",i),s.removeEventListener("error",n),t(new Error(`Failed to load video: ${e}`))};s.addEventListener("loadedmetadata",i),s.addEventListener("error",n),s.src=this._videoUrl||"",s.load()})}async play(){if(!this._videoElement)throw new Error("Video element not set");if(!this._isPlaying)try{await this._videoElement.play(),this._videoElement.style.opacity="0",this._videoElement.setAttribute("loop","true"),this._isPlaying=!0,r.info("Video playback started")}catch(e){throw r.error("Failed to play video:",e),e}}pause(){this._videoElement&&this._isPlaying&&(this._videoElement.pause(),this._isPlaying=!1,r.info("Video playback paused"))}stop(){this._videoElement&&(this._videoElement.pause(),this._videoElement.currentTime=0,this._isPlaying=!1,r.info("Video playback stopped"))}get isPlaying(){return this._isPlaying&&null!==this._videoElement&&!this._videoElement.paused}get videoWidth(){return this._videoElement?.videoWidth||0}get videoHeight(){return this._videoElement?.videoHeight||0}async captureFrame(){if(!this._videoElement||this._videoElement.readyState<2)return null;try{if("VideoFrame"in window&&"function"==typeof window.VideoFrame)try{return new VideoFrame(this._videoElement,{timestamp:1e6*this._videoElement.currentTime})}catch(e){}const e=await createImageBitmap(this._videoElement),t=new VideoFrame(e,{timestamp:1e6*this._videoElement.currentTime});return e.close(),t}catch(e){return r.error("Failed to capture video frame:",e),null}}onFrame(e){if(!this._videoElement)return;this.offFrame();const t=this._videoElement;if("requestVideoFrameCallback"in t){const s=(i,n)=>{this._isPlaying&&this._videoElement&&this.captureFrame().then(i=>{i&&(e(i),i.close()),this._isPlaying&&this._videoElement&&(this._frameCallbackId=t.requestVideoFrameCallback(s))}).catch(e=>{r.error("Error in frame callback:",e)})};this._frameCallbackId=t.requestVideoFrameCallback(s)}else{const t=()=>{this._isPlaying&&this._videoElement&&this.captureFrame().then(s=>{s&&(e(s),s.close()),this._isPlaying&&this._videoElement&&(this._frameCallbackId=requestAnimationFrame(t))}).catch(e=>{r.error("Error in frame callback:",e)})};this._frameCallbackId=requestAnimationFrame(t)}}offFrame(){null!==this._frameCallbackId&&(this._videoElement&&"cancelVideoFrameCallback"in this._videoElement?this._videoElement.cancelVideoFrameCallback(this._frameCallbackId):cancelAnimationFrame(this._frameCallbackId),this._frameCallbackId=null)}onDispose(){this.stop(),this.offFrame(),this._videoElement&&this._videoElement.parentElement===document.body&&document.body.removeChild(this._videoElement),this._videoElement=null,this._videoUrl=null,r.info("Local Video Debug Source disposed")}}class re extends t{constructor(e,t,s){super(),this._outputCanvas=null,this._outputRenderer=null,this._source=new u;const i={...e,renderMode:"processed"};this._pipeline=new w(this._source,i),this._outputRenderer=new m(s,t),this._pipeline.setRenderer(this._outputRenderer),this._outputCanvas=this._outputRenderer.getCanvas(),r.info("Video Pipeline Runner created")}get outputCanvas(){return this._outputCanvas}get processor(){return this._pipeline.strategy.getProcessor()}setProcessor(e){this._pipeline.setProcessor(e),r.info("Processor set on pipeline")}async processFrame(e){if(this.ensureNotDisposed(),!this._outputRenderer)return r.error("Output renderer not available"),void e.close();try{const t=this._pipeline.strategy.getProcessor();let s=null;if(t){try{s=t.process(e)}catch(t){r.error("Error processing frame:",t),s=e}if(null===s&&"getImageData"in t){const s=t.getImageData();if(s&&this._outputCanvas&&this._outputRenderer.getContext()){const e=this._outputRenderer.getContext();e&&(this._outputCanvas.width===s.width&&this._outputCanvas.height===s.height||(this._outputCanvas.width=s.width,this._outputCanvas.height=s.height),e.putImageData(s,0,0))}return void e.close()}s&&s!==e?(this._outputRenderer.render(s),e.close()):s===e?this._outputRenderer.render(e):e.close()}else this._outputRenderer.render(e)}catch(t){r.error("Error in processFrame:",t),e.close()}}setOutputSize(e,t){this._outputCanvas&&(this._outputCanvas.width=e,this._outputCanvas.height=t,r.info(`Output canvas size set to ${e}x${t}`))}onDispose(){this._pipeline.dispose(),this._outputRenderer&&(this._outputRenderer.dispose(),this._outputRenderer=null),this._outputCanvas&&this._outputCanvas.parentElement===document.body&&document.body.removeChild(this._outputCanvas),this._outputCanvas=null,r.info("Video Pipeline Runner disposed")}}exports.AudioState=h,exports.ConversationState=c,exports.DEFAULT_AUDIO_BUFFER_SIZE=4096,exports.DEFAULT_AUDIO_CHANNELS=1,exports.DEFAULT_AUDIO_SAMPLE_RATE=N,exports.DEFAULT_RECONNECT_ATTEMPTS=3,exports.DEFAULT_RECONNECT_DELAY=1e3,exports.DEFAULT_WS_TIMEOUT=1e4,exports.Disposable=t,exports.EventBus=o,exports.Logger=r,exports.SDKClient=ie,exports.SDKError=e,exports.SessionState=d,exports.StandaloneVideoDebugger=class extends t{constructor(e,t,s,i){if(super(),this._isRunning=!1,this._videoSource=new ne(e,t),this._options={renderMode:"processed",element:t,...i},this._pipelineRunner=new re(this._options,t,s),this._options.greenScreen?.enabled){const e=new f(this._options.greenScreen);this._pipelineRunner.setProcessor(e),r.info("Green screen processor enabled in debugger")}r.info("Standalone Video Debugger created")}async switchSource(e,t){this.ensureNotDisposed();const s=this._videoSource,i=this._isRunning,n=new ne(e,t);try{await n.load(),i&&await n.play(),n.onFrame(e=>{this._pipelineRunner.processFrame(e).catch(e=>{r.error("Error processing frame:",e)})}),this._videoSource=n;try{s.offFrame(),s.stop(),s.dispose()}catch(e){console.warn("Error disposing old video source during switch:",e)}const e=this._videoSource.videoWidth,t=this._videoSource.videoHeight;e>0&&t>0&&this._pipelineRunner.setOutputSize(e,t)}catch(e){r.error("Failed to switch video source:",e);try{n.dispose()}catch(e){console.warn("Error disposing new video source after failed switch:",e)}throw e}}get outputCanvas(){return this._pipelineRunner.outputCanvas}get videoSource(){return this._videoSource}get processor(){return this._pipelineRunner.processor}setProcessor(e){this._pipelineRunner.setProcessor(e)}updateGreenScreenOptions(e){const t=this._pipelineRunner.processor;if(t&&"updateOptions"in t&&"function"==typeof t.updateOptions)t.updateOptions(e),r.info("Green screen options updated");else{const t=this._options.greenScreen||{enabled:!1},s={...t,...e,enabled:void 0!==e.enabled?e.enabled:t.enabled},i=new f(s);this._pipelineRunner.setProcessor(i),this._options.greenScreen=s,r.info("Green screen processor recreated with new options")}}async initialize(){this.ensureNotDisposed();try{await this._videoSource.load();const e=this._videoSource.videoWidth,t=this._videoSource.videoHeight;e>0&&t>0&&this._pipelineRunner.setOutputSize(e,t),r.info("Video debugger initialized")}catch(e){throw r.error("Failed to initialize video debugger:",e),e}}async start(){if(this.ensureNotDisposed(),this._isRunning)r.warn("Debugger is already running");else try{0===this._videoSource.videoWidth&&await this.initialize(),await this._videoSource.play(),this._videoSource.onFrame(e=>{this._pipelineRunner.processFrame(e).catch(e=>{r.error("Error processing frame:",e)})}),this._isRunning=!0,r.info("Video debugger started")}catch(e){throw r.error("Failed to start video debugger:",e),e}}stop(){this._isRunning&&(this._videoSource.stop(),this._videoSource.offFrame(),this._isRunning=!1,r.info("Video debugger stopped"))}pause(){this._isRunning&&(this._videoSource.pause(),r.info("Video debugger paused"))}async resume(){this._isRunning&&(await this._videoSource.play(),r.info("Video debugger resumed"))}get isRunning(){return this._isRunning}onDispose(){this.stop(),this._videoSource.dispose(),this._pipelineRunner.dispose(),r.info("Standalone Video Debugger disposed")}},exports.VideoState=a,exports.createClient=function(t){if(!t.avatarName)throw new e("avatarName is required","INVALID_CONFIG");return r.info("Creating SDK client with options:",{avatarName:t.avatarName}),new ie(t)};
1
+ "use strict";var f=require("livekit-client"),d;(function(o){o.SDK_AUTH_TOKEN_FAILED="SDK_AUTH_TOKEN_FAILED",o.SDK_GET_LIVEKIT_CONFIG_FAILED="SDK_GET_LIVEKIT_CONFIG_FAILED",o.SDK_RECONNECT_FAILED="SDK_RECONNECT_FAILED",o.SDK_DISCONNECT_FAILED="SDK_DISCONNECT_FAILED",o.SDK_NOT_CONNECTED="SDK_NOT_CONNECTED",o.SDK_CONNECT_FAILED="SDK_CONNECT_FAILED",o.SDK_SWITCH_VIDEO_FAILED="SDK_SWITCH_VIDEO_FAILED",o.SDK_ERROR="SDK_ERROR",o.SDK_PRECONNECT_FAILED="SDK_PRECONNECT_FAILED",o.SDK_INTERRUPT_CONVERSATION_FAILED="SDK_INTERRUPT_CONVERSATION_FAILED",o.SDK_INITIALIZATION_FAILED="SDK_INITIALIZATION_FAILED",o.SDK_INVALID_STATE_TRANSITION="SDK_INVALID_STATE_TRANSITION",o.NO_AVATARNAME="NO_AVATARNAME",o.AUDIO_CAPTURE_START_FAILED="AUDIO_CAPTURE_START_FAILED",o.AUDIO_CAPTURE_FAILED="AUDIO_CAPTURE_FAILED",o.AUDIO_INVALID_SAMPLE_RATE="AUDIO_INVALID_SAMPLE_RATE",o.AUDIO_INVALID_CHANNEL="AUDIO_INVALID_CHANNEL",o.AUDIO_INVALID_HEADER_LENGTH="AUDIO_INVALID_HEADER_LENGTH",o.AUDIO_INVALID_TYPE="AUDIO_INVALID_TYPE",o.AUDIO_INVALID_RESERVED="AUDIO_INVALID_RESERVED",o.AUDIO_CONTROLLER_NOT_AVAILABLE="AUDIO_CONTROLLER_NOT_AVAILABLE",o.WS_CONNECT_FAILED="WS_CONNECT_FAILED",o.WS_TEXT_SEND_FAILED="WS_TEXT_SEND_FAILED",o.WS_PARSE_ERROR="WS_PARSE_ERROR",o.WS_NOT_CONNECTED="WS_NOT_CONNECTED",o.WS_CONNECT_ERROR="WS_CONNECT_ERROR",o.LIVEKIT_CONNECT_FAILED="LIVEKIT_CONNECT_FAILED",o.CONVERSATION_CONTROLLER_NOT_AVAILABLE="CONVERSATION_CONTROLLER_NOT_AVAILABLE",o.STATE_MACHINE_INVALID_STATE_TRANSITION="STATE_MACHINE_INVALID_STATE_TRANSITION",o.OBJECT_DISPOSED="OBJECT_DISPOSED"})(d||(d={}));class u extends Error{constructor(e,t="SDK_ERROR",s){super(e),this.name="SDKError",this.code=t,this.cause=s,Object.setPrototypeOf(this,u.prototype)}static fromError(e,t){return e instanceof u?e:e instanceof Error?new u(e.message,t||d.SDK_ERROR,e):typeof e=="string"?new u(e,t||d.SDK_ERROR):new u("Unknown error",t||d.SDK_ERROR,e)}}class h{constructor(){this._disposed=!1}get isDisposed(){return this._disposed}dispose(){this._disposed||(this.onDispose(),this._disposed=!0)}ensureNotDisposed(){if(this._disposed)throw new u("Object has been disposed",d.OBJECT_DISPOSED)}}exports.LogLevel=void 0;(function(o){o[o.DEBUG=0]="DEBUG",o[o.INFO=1]="INFO",o[o.WARN=2]="WARN",o[o.ERROR=3]="ERROR",o[o.NONE=4]="NONE"})(exports.LogLevel||(exports.LogLevel={}));class i{static setLevel(e){this._level=e}static setPrefix(e){this._prefix=e}static debug(e,...t){this._level<=exports.LogLevel.DEBUG&&console.debug(`${this._prefix} [DEBUG]`,e,...t)}static info(e,...t){this._level<=exports.LogLevel.INFO&&console.info(`${this._prefix} [INFO]`,e,...t)}static warn(e,...t){this._level<=exports.LogLevel.WARN&&console.warn(`${this._prefix} [WARN]`,e,...t)}static error(e,...t){this._level<=exports.LogLevel.ERROR&&console.error(`${this._prefix} [ERROR]`,e,...t)}}i._level=exports.LogLevel.ERROR;i._prefix="[SDK]";class M extends h{constructor(){super(...arguments),this._listeners=new Map}on(e,t){this.ensureNotDisposed(),this._listeners.has(e)||this._listeners.set(e,new Set);const s=this._listeners.get(e);return s.add(t),i.debug(`Event listener added for: ${String(e)}`),()=>{s.delete(t),i.debug(`Event listener removed for: ${String(e)}`)}}once(e,t){this.ensureNotDisposed();const s=n=>{t(n),this.off(e,s)};return this.on(e,s)}off(e,t){this.ensureNotDisposed();const s=this._listeners.get(e);s&&s.delete(t)}emit(e,t){this.ensureNotDisposed();const s=this._listeners.get(e);s&&s.size>0&&(i.debug(`Emitting event: ${String(e)}`,t),s.forEach(n=>{try{n(t)}catch(r){i.error(`Error in event listener for ${String(e)}:`,r)}}))}removeAllListeners(){this._listeners.clear(),i.debug("All event listeners removed")}listenerCount(e){const t=this._listeners.get(e);return t?t.size:0}onDispose(){this.removeAllListeners()}}exports.SessionStatus=void 0;(function(o){o.IDLE="idle",o.CONNECTING="connecting",o.CONNECTED="connected",o.PARTIAL="partial",o.DISCONNECTED="disconnected",o.RECONNECTING="reconnecting",o.DISCONNECTING="disconnecting",o.ERROR="error",o.DISPOSED="disposed"})(exports.SessionStatus||(exports.SessionStatus={}));function Q(o){switch(o){case"idle":return exports.SessionStatus.IDLE;case"connecting":return exports.SessionStatus.CONNECTING;case"connected":return exports.SessionStatus.CONNECTED;case"partial":return exports.SessionStatus.PARTIAL;case"disconnecting":return exports.SessionStatus.DISCONNECTING;case"disconnected":case"error":return exports.SessionStatus.DISCONNECTED;case"reconnecting:auto":case"reconnecting:manual":return exports.SessionStatus.RECONNECTING;case"disposed":return exports.SessionStatus.DISPOSED;default:return exports.SessionStatus.DISCONNECTED}}class V{constructor(){this.status=exports.SessionStatus.DISCONNECTED,this.state=exports.SessionStatus.DISCONNECTED,this.isConnected=!1}reset(){this.status=exports.SessionStatus.DISCONNECTED,this.state=exports.SessionStatus.DISCONNECTED,this.isConnected=!1}}const S=3,Y=5e3,C=1e3,y=10,X=1e4,J=3e3,N=3e4,A=24e3,I=16,Z=1,ee=4096,T=0,te="https://api.newportai.com/s2/aigc/api/vih_dispatcher",se="wss://api.newportai.com/s2/livekit-lisbon",ie="wss://api.newportai.com/s2/aigc/api/ws_dispatch/render/v1/stream";var v;(function(o){o.NO_VIDEO_TRACK="NO_VIDEO_TRACK",o.TRACK_MUTED="TRACK_MUTED",o.TRACK_ENDED="TRACK_ENDED"})(v||(v={}));class ne{constructor(e){this.options=e,this._livekitUrl="",this._token="",this._wsUrl="",this.eventBus=new M,this.sessionState=new V,e.debug&&i.setLevel(0),i.info("SDK Context initialized")}setLivekitConfig(e,t,s){this._livekitUrl=e||se,this._token=t,this._roomId=s}emitError(e,t){const s=u.fromError(e,t);return this.eventBus.emit("inner:sdk:error",{error:s}),s}setVideoOptions(e){this.options.video=Object.assign({},e,this.options.video||{})}setWsUrl(e){this._wsUrl=e}get wsUrl(){return this._wsUrl}get livekitUrl(){return this._livekitUrl}get token(){return this._token}get roomId(){return this._roomId}getLivekitConfig(){return{livekitUrl:this._livekitUrl,token:this._token}}dispose(){this.eventBus.dispose(),this.sessionState.reset(),i.info("SDK Context disposed")}}function U(o){return{ws:{connected:!1},rtc:{connected:!1,hasVideoTrack:!1},overall:{state:o}}}function K(o){return Object.freeze({ws:Object.freeze({...o.ws}),rtc:Object.freeze({...o.rtc}),overall:Object.freeze({...o.overall})})}class W{constructor(){this._transitionMap=null}get transitionMap(){if(!this._transitionMap){const e=new Map;for(const t of this.transitionTable)e.set(t.from,new Set(t.to));this._transitionMap=e}return this._transitionMap}getCurrentState(){return this._currentState}transitionTo(e,t){const s=this._currentState;if(!this.canTransition(s,e)){const n=this.transitionMap.get(s),r=n?Array.from(n).join(", "):"none";throw t?.error??new u(`Invalid state transition: cannot transition from "${s}" to "${e}". Current state: "${s}". Allowed transitions: [${r}]`,d.STATE_MACHINE_INVALID_STATE_TRANSITION)}this._currentState=e}canTransition(e,t){return e===t?!1:this.transitionMap.get(e)?.has(t)??!1}reset(){throw new Error("Method not implemented.")}}class re extends W{constructor(){super(...arguments),this._currentState="idle",this.transitionTable=[{from:"idle",to:["connecting","disposed"]},{from:"connecting",to:["connected","partial","error","idle","disposed"]},{from:"connected",to:["disconnecting","partial","reconnecting:auto","reconnecting:manual","error","disposed"]},{from:"partial",to:["connected","disconnecting","reconnecting:auto","reconnecting:manual","error","disposed"]},{from:"reconnecting:auto",to:["connected","partial","error","idle","disposed"]},{from:"reconnecting:manual",to:["connected","partial","error","idle","disposed"]},{from:"disconnecting",to:["disconnected","error","disposed"]},{from:"disconnected",to:["reconnecting:manual","reconnecting:auto","idle","disposed"]},{from:"error",to:["reconnecting:manual","reconnecting:auto","idle","disposed"]},{from:"disposed",to:[]}]}reset(){this._currentState="idle"}}class oe extends h{constructor(e){super(),this._unsubscribes=[],this._context=e,this._fsm=new re,this._snapshot=U("idle")}start(){this.ensureNotDisposed();const e=this._context.eventBus,t=e.on("inner:rtc:connected",()=>{this._snapshot.rtc.connected=!0,this._context.eventBus.emit("inner:sdk:connected",{source:"livekit"}),this._onFactsChanged()}),s=e.on("inner:rtc:disconnected",l=>{this._snapshot.rtc.connected=!1,this._snapshot.rtc.hasVideoTrack=!1,this._context.eventBus.emit("inner:sdk:disconnected",{source:"livekit",reason:l?.reason}),this._onFactsChanged()}),n=e.on("inner:rtc:video:available",()=>{this._snapshot.rtc.hasVideoTrack=!0}),r=e.on("inner:rtc:video:unavailable",()=>{this._snapshot.rtc.hasVideoTrack=!1}),a=e.on("inner:ws:connected",()=>{this._snapshot.ws.connected=!0,this._context.eventBus.emit("inner:sdk:connected",{source:"ws"}),this._onFactsChanged()}),c=e.on("inner:ws:disconnected",l=>{this._snapshot.ws.connected=!1,this._context.eventBus.emit("inner:sdk:disconnected",{source:"ws",reason:l?.reason}),this._onFactsChanged()});this._unsubscribes=[t,s,n,r,a,c]}startConnecting(){this._transitionTo("connecting")}startDisconnecting(){this._transitionTo("disconnecting")}completeDisconnecting(){this._snapshot.ws.connected=!1,this._snapshot.rtc.connected=!1,this._snapshot.rtc.hasVideoTrack=!1,this._transitionTo("disconnected")}captureSnapshotAndStartReconnectingManual(){const e=this.getSnapshot();return this._transitionTo("reconnecting:manual"),e}transitionToIdle(){this._snapshot.ws.connected=!1,this._snapshot.rtc.connected=!1,this._snapshot.rtc.hasVideoTrack=!1,this._transitionTo("idle")}transitionToDisposed(){this._transitionTo("disposed")}getSnapshot(){return K(this._snapshot)}getState(){return this._fsm.getCurrentState()}canStartReconnectingManual(){const e=this._fsm.getCurrentState();return e==="connected"||e==="partial"||e==="disconnected"||e==="error"}_onFactsChanged(){const e=this._fsm.getCurrentState();if(e==="connecting"||e==="reconnecting:auto"||e==="reconnecting:manual"){const t=this._snapshot.rtc.connected&&this._snapshot.ws.connected,s=this._snapshot.rtc.connected||this._snapshot.ws.connected;if(t){this._transitionTo("connected");return}if(s){this._transitionTo("partial");return}}if(e==="connected"||e==="partial"){const t=this._snapshot.rtc.connected&&this._snapshot.ws.connected;if(!(this._snapshot.rtc.connected||this._snapshot.ws.connected)){this._transitionTo("disconnected");return}if(!t){this._transitionTo("partial");return}if(t&&e==="partial"){this._transitionTo("connected");return}}}_transitionTo(e){this._fsm.canTransition(this._fsm.getCurrentState(),e)&&(this._fsm.transitionTo(e),this._snapshot.overall.state=this._fsm.getCurrentState(),this._syncSessionState())}_syncSessionState(){const e=this._fsm.getCurrentState();this._context.sessionState.status=Q(e),this._context.sessionState.state=this._context.sessionState.status,this._context.sessionState.isConnected=e==="connected"}onDispose(){this._unsubscribes.forEach(e=>e()),this._unsubscribes=[]}}class B extends h{get trackId(){return this._trackId}get participantId(){return this._participantId}get track(){return this._track}constructor(){super(),this._trackId=null,this._participantId=null,this._track=null,this._stream=null,this._videoElement=document.createElement("video"),this._videoElement.autoplay=!0,this._videoElement.playsInline=!0,this._videoElement.muted=!0,this._videoElement.crossOrigin="anonymous",this._videoElement.style.display="none",i.info("Video Source initialized with internal video element")}getInternalElement(){return this._videoElement}setTrack(e,t,s){this.ensureNotDisposed(),this._track&&this._track.stop(),this._track=e,this._trackId=t,this._participantId=s,this._stream||(this._stream=new MediaStream);const n=this._stream.getTracks();for(const r of n)if(r!==e)try{this._stream.removeTrack(r)}catch(a){i.warn("Failed to remove track from stream",a)}if(!this._stream.getTracks().includes(e))try{this._stream.addTrack(e)}catch(r){i.error("Failed to add track to media stream:",r)}i.info("Video track ready")}clearTrack(){if(this._stream){const e=this._stream.getTracks();for(const t of e)try{this._stream.removeTrack(t)}catch(s){i.warn("Failed to remove track from stream",s)}}this._track&&(this._track.stop(),this._track=null),this._trackId=null,this._participantId=null,i.info("Video track cleared")}get hasTrack(){return this._track!==null&&this._track.readyState==="live"}onDispose(){this.clearTrack(),this._videoElement&&this._videoElement.parentElement&&this._videoElement.parentElement.removeChild(this._videoElement),this._stream&&(this._stream.getTracks().forEach(e=>e.stop()),this._stream=null),i.info("Video Source disposed")}}class ae extends h{constructor(){super(...arguments),this._renderer=null}getRenderer(){return this._renderer}setRenderer(e){this._renderer&&this._renderer.dispose(),this._renderer=e,i.debug("Raw render strategy renderer set")}getProcessors(){return[]}setProcessors(e){i.warn("Raw render strategy does not support processors")}attachToContainer(e){if(!this._renderer){i.warn("No renderer available to attach to container");return}if("getElement"in this._renderer&&typeof this._renderer.getElement=="function"){const t=this._renderer.getElement();t instanceof HTMLVideoElement&&(t.parentElement&&t.parentElement!==e&&t.parentElement.removeChild(t),t.parentElement!==e&&(e.appendChild(t),t.style.display="",i.debug("Video element attached to container in raw mode")))}}onDispose(){this._renderer&&(this._renderer.dispose(),this._renderer=null),i.info("Raw Render Strategy disposed")}}class ce{create(){return new ae}}class D extends h{constructor(e,t){if(super(),this._canvas=null,this._ctx=null,this._videoElement=null,this._parentElement=null,this._resizeObserver=null,this._animationFrameId=null,this._isRendering=!1,this._renderLoop=()=>{if(!(!this._isRendering||!this._videoElement||!this._canvas||!this._ctx)){try{this._syncCanvasSize(),this._ctx.drawImage(this._videoElement,0,0,this._canvas.width,this._canvas.height)}catch(s){i.error("Error rendering from video to canvas:",s)}this._animationFrameId=requestAnimationFrame(this._renderLoop)}},e){if(this._canvas=e,this._ctx=e.getContext("2d"),!this._ctx)throw new Error("Failed to get 2D context from canvas")}else if(t)this._videoElement=t,this._createCanvasFromVideo();else throw new Error("CanvasRenderer requires either canvas or videoElement");i.info("Canvas Renderer created")}_createCanvasFromVideo(){if(!this._videoElement)return;if(this._parentElement=this._videoElement.parentElement,!this._parentElement)throw new Error("Video element must have a parent element");if(window.getComputedStyle(this._parentElement).position==="static"&&(this._parentElement.style.position="relative"),this._canvas=document.createElement("canvas"),this._ctx=this._canvas.getContext("2d"),!this._ctx)throw new Error("Failed to get 2D context from canvas");this._canvas.style.position="absolute",this._canvas.style.top="0",this._canvas.style.left="0",this._canvas.style.width="100%",this._canvas.style.height="100%",this._canvas.style.pointerEvents="none",this._parentElement.appendChild(this._canvas),this._syncCanvasSize(),this._setupResizeObserver()}_syncCanvasSize(){if(!this._canvas||!this._videoElement||!this._ctx)return;const e=this._videoElement.videoWidth,t=this._videoElement.videoHeight,s=this._videoElement.clientWidth,n=this._videoElement.clientHeight;if(e>0&&t>0&&s>0&&n>0){const r=e/t,a=s/n;let c,l;r>a?(c=s,l=s/r):(c=n*r,l=n),this._canvas.style.width=`${c}px`,this._canvas.style.height=`${l}px`;const p=(s-c)/2,m=(n-l)/2;this._canvas.style.left=`${p}px`,this._canvas.style.top=`${m}px`,this._canvas.width=e,this._canvas.height=t}}_setupResizeObserver(){!this._videoElement||typeof ResizeObserver>"u"||(this._resizeObserver=new ResizeObserver(()=>{this._syncCanvasSize()}),this._resizeObserver.observe(this._videoElement))}startRenderingFromVideo(){this._isRendering||!this._videoElement||!this._canvas||!this._ctx||(this._isRendering=!0,this._renderLoop())}stopRenderingFromVideo(){this._isRendering=!1,this._animationFrameId!==null&&(cancelAnimationFrame(this._animationFrameId),this._animationFrameId=null)}setFitMode(e){this._canvas&&(this._canvas.style.width="100%",this._canvas.style.height="100%",this._canvas.style.objectFit=e)}render(e){if(this.ensureNotDisposed(),!(!this._ctx||!this._canvas))try{const t=e.displayWidth,s=e.displayHeight;this._videoElement?this._syncCanvasSize():(this._canvas.width!==t||this._canvas.height!==s)&&(this._canvas.width=t,this._canvas.height=s);const n=e instanceof VideoFrame?e.displayWidth:e.videoWidth,r=e instanceof VideoFrame?e.displayHeight:e.videoHeight;n>0&&r>0&&(this._canvas.width!==n||this._canvas.height!==r)&&(this._canvas.width=n,this._canvas.height=r),this._ctx.clearRect(0,0,this._canvas.width,this._canvas.height),this._ctx.drawImage(e,0,0,this._canvas.width,this._canvas.height)}catch(t){i.error("Error rendering video frame to canvas:",t)}}getCanvas(){return this._canvas}getContext(){return this._ctx}onDispose(){this.stopRenderingFromVideo(),this._resizeObserver&&(this._resizeObserver.disconnect(),this._resizeObserver=null),this._canvas&&this._parentElement&&this._canvas.parentElement===this._parentElement&&this._parentElement.removeChild(this._canvas),this._canvas=null,this._ctx=null,this._videoElement=null,this._parentElement=null,i.info("Canvas Renderer disposed")}}class $ extends h{constructor(e){super(),this._element=null,this._stream=null,this._track=null,this._element=e,i.info("Video Element Renderer created")}setTrack(e){if(this.ensureNotDisposed(),this._track=e,!this._element){i.warn("No video element available to set track");return}this._stream||(this._stream=new MediaStream,this._element.srcObject=this._stream);const t=this._stream.getTracks();for(const s of t)if(s!==e)try{this._stream.removeTrack(s)}catch(n){console.error(n)}if(!this._stream.getTracks().includes(e))try{this._stream.addTrack(e)}catch(s){i.error("Failed to add track to media stream:",s)}this._element.play().catch(s=>{i.error("Error playing video:",s)}),i.debug("Video track set to element (stream reused)")}setOpacity(e){this._element&&(this._element.style.opacity=String(e))}getElement(){return this._element}setFitMode(e){this._element&&(this._element.style.width="100%",this._element.style.height="100%",this._element.style.objectFit=e)}render(e){i.debug("Render called in direct mode (no-op)")}onDispose(){this._element&&(this._element.srcObject=null),this._stream&&(this._stream.getTracks().forEach(e=>e.stop()),this._stream=null),this._track&&(this._track.stop(),this._track=null),i.info("Video Element Renderer disposed")}clearTrack(){if(this._stream){const e=this._stream.getTracks();for(const t of e)try{this._stream.removeTrack(t)}catch(s){console.error(s)}}this._track=null}}class de extends h{constructor(){super(...arguments),this._renderer=null,this._processors=[],this._videoElementRenderer=null,this._canvasRenderer=null,this._videoFrameCallbackId=null,this._animationFrameId=null,this._isProcessing=!1,this._processVideoFrame=()=>{if(!this._isProcessing||!this._videoElementRenderer||!this._canvasRenderer)return;const e=this._videoElementRenderer.getElement();if(!e||e.readyState<2){this._isProcessing&&e&&(this._videoFrameCallbackId=e.requestVideoFrameCallback(this._processVideoFrame));return}try{let t=new VideoFrame(e,{timestamp:performance.now()*1e3});for(const s of this._processors){const n=s.process(t);n&&n!==t&&(t instanceof VideoFrame&&t.close(),t=n)}t instanceof ImageData?this._renderImageData(t):this._canvasRenderer.render(t),t instanceof VideoFrame&&t.close()}catch(t){i.error("Error processing video frame:",t)}this._isProcessing&&e&&(this._videoFrameCallbackId=e.requestVideoFrameCallback(this._processVideoFrame))},this._processVideoFrameFallback=()=>{if(!this._isProcessing||!this._canvasRenderer||!this._videoElementRenderer)return;const e=this._videoElementRenderer.getElement();if(!e||e.readyState<2||e.paused){const a=this._canvasRenderer.getContext(),c=this._canvasRenderer.getCanvas();a&&c&&a.clearRect(0,0,c.width,c.height),this._animationFrameId=requestAnimationFrame(this._processVideoFrameFallback);return}const t=e.videoWidth,s=e.videoHeight,n=this._canvasRenderer.getCanvas();t>0&&n&&(n.width!==t||n.height!==s)&&(n.width=t,n.height=s);let r=new VideoFrame(e);try{for(const a of this._processors){const c=a.process(r);c&&c!==r&&(r instanceof VideoFrame&&r.close(),r=c)}r instanceof ImageData?this._renderImageData(r):this._canvasRenderer.render(r)}finally{r instanceof VideoFrame&&r.close()}this._isProcessing&&(this._animationFrameId=requestAnimationFrame(this._processVideoFrameFallback))}}getRenderer(){return this._renderer}setRenderer(e){if(this._renderer&&this._renderer.dispose(),this._renderer=e,e instanceof $){if(this._videoElementRenderer=e,!this._canvasRenderer){const t=this._videoElementRenderer.getElement();if(t)try{t.parentElement&&(this._canvasRenderer=new D(void 0,t),this._renderer=this._canvasRenderer,i.debug("Canvas renderer created in setRenderer (processed mode)"))}catch(s){i.warn("Failed to create CanvasRenderer in setRenderer, will retry in attachToContainer:",s)}}this._setupProcessingPipeline()}else this._videoElementRenderer=null,this._stopProcessingPipeline();i.debug("Processed render strategy renderer set")}addProcessor(e,t){t!==void 0&&t>=0&&t<this._processors.length?this._processors.splice(t,0,e):this._processors.push(e),this._setupProcessingPipeline()}getProcessors(){return this._processors}setProcessors(e){this._processors.forEach(t=>t.dispose()),this._processors=e,this._setupProcessingPipeline(),i.debug("Processed render strategy processor set")}attachToContainer(e){if(this._canvasRenderer){const t=this._canvasRenderer.getCanvas();if(t&&(t.parentElement&&t.parentElement!==e&&t.parentElement.removeChild(t),t.parentElement!==e&&(e.appendChild(t),i.debug("Canvas element attached to container in processed mode"))),this._videoElementRenderer){const s=this._videoElementRenderer.getElement();s&&(s.parentElement&&s.parentElement.removeChild(s),s.style.display="none")}}else if(this._videoElementRenderer){const t=this._videoElementRenderer.getElement();if(t){const s=t.parentElement!==null;s||e.appendChild(t);try{this._canvasRenderer=new D(void 0,t),this._renderer=this._canvasRenderer,!s&&t.parentElement===e&&e.removeChild(t),t.style.display="none";const n=this._canvasRenderer.getCanvas();n&&n.parentElement!==e&&e.appendChild(n),this._startProcessingLoop(),i.debug("Canvas created and attached to container in processed mode")}catch(n){i.error("Failed to create CanvasRenderer in attachToContainer:",n),!s&&t.parentElement===e&&e.removeChild(t),t.parentElement!==e&&(e.appendChild(t),t.style.display="")}}}}_setupProcessingPipeline(){if(!this._videoElementRenderer)return;const e=this._videoElementRenderer.getElement();if(!e){i.warn("Video element not available for processing");return}if(e.parentElement&&e.parentElement.removeChild(e),e.style.display="none",e.readyState<2){const t=()=>{this._setupProcessingPipeline(),e.removeEventListener("loadedmetadata",t)};e.addEventListener("loadedmetadata",t);return}this._canvasRenderer&&(this._startProcessingLoop(),i.info("Processing pipeline setup completed"))}_stopProcessingPipeline(){this._stopProcessingLoop(),this._canvasRenderer&&(this._canvasRenderer.dispose(),this._canvasRenderer=null),this._videoElementRenderer&&(this._renderer=this._videoElementRenderer)}_startProcessingLoop(){this._isProcessing||!this._videoElementRenderer||!this._canvasRenderer||!this._videoElementRenderer.getElement()||(this._isProcessing=!0,"requestVideoFrameCallback"in HTMLVideoElement.prototype?this._processVideoFrame():this._processVideoFrameFallback())}_stopProcessingLoop(){this._isProcessing=!1;const e=this._videoElementRenderer?.getElement();this._videoFrameCallbackId!==null&&e&&"cancelVideoFrameCallback"in e&&(e.cancelVideoFrameCallback(this._videoFrameCallbackId),this._videoFrameCallbackId=null),this._animationFrameId!==null&&(cancelAnimationFrame(this._animationFrameId),this._animationFrameId=null)}_renderImageData(e){if(!this._canvasRenderer)return;const t=this._canvasRenderer.getContext(),s=this._canvasRenderer.getCanvas();t&&s&&((s.width!==e.width||s.height!==e.height)&&(s.width=e.width,s.height=e.height),t.clearRect(0,0,s.width,s.height),t.putImageData(e,0,0))}onDispose(){this._stopProcessingPipeline(),this._renderer&&(this._renderer.dispose(),this._renderer=null),this._processors.forEach(e=>e.dispose()),this._processors=[],this._videoElementRenderer=null,this._canvasRenderer=null,i.info("Processed Render Strategy disposed")}}class he{create(){return new de}}class k{static getFactory(e){return e==="processed"?new he:new ce}}class H extends h{constructor(e,t){super(),this._videoElementRenderer=null,this._containerElement=null,this._source=e;const s=t?.renderMode||"raw";this._containerElement=t?.containerElement||null,this._strategyFactory=k.getFactory(s),this._strategy=this._strategyFactory.create();const n=this._source.getInternalElement(),r=new $(n);this._videoElementRenderer=r,this._strategy.setRenderer(r),this._containerElement&&(this._strategy.attachToContainer(this._containerElement),i.info("Renderer elements attached to container via strategy")),i.info("Video Pipeline created")}setRenderMode(e){this.ensureNotDisposed();const t=k.getFactory(e);if(this._strategyFactory.constructor===t.constructor)return;const s=this._strategy.getRenderer(),n=this._strategy.getProcessors();this._strategy.dispose(),this._strategyFactory=t,this._strategy=this._strategyFactory.create(),s&&this._strategy.setRenderer(s),n.length>0&&this._strategy.setProcessors(n),this._containerElement&&this._strategy.attachToContainer(this._containerElement),i.info(`Video render mode changed to: ${e}`)}setRenderFitMode(e){this.ensureNotDisposed(),this._strategy.getRenderer()?.setFitMode(e),i.info(`Video render fit mode changed to: ${e}`)}setProcessor(e){this.ensureNotDisposed(),this._strategy.setProcessors(e?[e]:[])}setRenderer(e){this.ensureNotDisposed(),this._strategy.setRenderer(e)}get strategy(){return this._strategy}get videoElementRenderer(){return this._videoElementRenderer}onDispose(){if(this._strategy.dispose(),this._videoElementRenderer){const e=this._videoElementRenderer.getElement();e&&e.parentElement&&e.parentElement.removeChild(e),this._videoElementRenderer.dispose(),this._videoElementRenderer=null}i.info("Video Pipeline disposed")}}class le extends h{onDispose(){}}class w extends le{constructor(e){super(),this._program=null,this._texture=null,this._lastProcessedTimestamp=null,this._options=e,this._canvas=document.createElement("canvas");const t=this._canvas.getContext("webgl",{premultipliedAlpha:!1,preserveDrawingBuffer:!0});if(!t)throw new Error("WebGL not supported");this._gl=t,this._initGL(),i.info("WebGL Green Screen Processor initialized")}_initGL(){const e=this._gl,t=`
2
+ attribute vec2 aPosition;
3
+ attribute vec2 aTexCoord;
4
+ varying vec2 vTexCoord;
5
+ void main() {
6
+ gl_Position = vec4(aPosition, 0, 1);
7
+ vTexCoord = aTexCoord;
8
+ }`,s=`
9
+ precision mediump float;
10
+ varying vec2 vTexCoord;
11
+ uniform sampler2D uSampler;
12
+ uniform vec3 uChromaKey; // greenScreen target color: RGB
13
+ uniform float uSimilarity; // greenScreen similarity
14
+ uniform float uSmoothness; // greenScreen smoothness
15
+ uniform float uSpill; // greenScreen despill strength
16
+
17
+ // convert RGB to YCbCr space, separate luminance and chrominance
18
+ vec3 rgbToYcbcr(vec3 rgb) {
19
+ float y = 0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b;
20
+ float cb = 0.564 * (rgb.b - y) + 0.5;
21
+ float cr = 0.713 * (rgb.r - y) + 0.5;
22
+ return vec3(y, cb, cr);
23
+ }
24
+
25
+ void main() {
26
+ vec4 color = texture2D(uSampler, vTexCoord);
27
+ vec3 rgb = color.rgb;
28
+
29
+ vec3 ycbcr = rgbToYcbcr(rgb);
30
+ vec3 targetYcbcr = rgbToYcbcr(uChromaKey);
31
+
32
+ // \u6838\u5FC3\u6539\u8FDB\uFF1A\u53EA\u8BA1\u7B97 Cb \u548C Cr \u7684\u6B27\u5F0F\u8DDD\u79BB\uFF0C\u5FFD\u7565\u4EAE\u5EA6 Y
33
+ // \u8FD9\u80FD\u786E\u4FDD\u6DF1\u8272\u8936\u76B1\uFF08Y\u4F4E\uFF09\u56E0\u4E3A Cb/Cr \u4E0D\u53D8\u800C\u4E0D\u88AB\u6263\u9664
34
+ float dist = distance(ycbcr.yz, targetYcbcr.yz);
35
+
36
+ // \u4F7F\u7528 smoothstep \u751F\u6210\u4E1D\u6ED1\u8FB9\u7F18
37
+ float alpha = smoothstep(uSimilarity, uSimilarity + uSmoothness, dist);
38
+ alpha = pow(alpha, 1.2);
39
+
40
+ // \u589E\u5F3A\u578B Despill (\u53BB\u6EA2\u51FA)
41
+ float maxRB = max(rgb.r, rgb.b);
42
+ if (rgb.g > maxRB) {
43
+ float edgeFactor = 1.0 - alpha; // \u8FB9\u7F18\u50CF\u7D20\u66F4\u5F3A\u53BB\u7EFF
44
+ float diff = (rgb.g - maxRB) * uSpill * edgeFactor;
45
+ rgb.g -= diff;
46
+ rgb.rb += diff * 0.15;
47
+ }
48
+
49
+ // rgb = mix(vec3(dot(rgb, vec3(0.333))), rgb, alpha);
50
+ float luma = dot(rgb, vec3(0.299, 0.587, 0.114));
51
+ rgb = mix(vec3(luma), rgb, alpha);
52
+
53
+ gl_FragColor = vec4(rgb, alpha * color.a);
54
+ }
55
+ `;this._program=this._createProgram(t,s),this._texture=e.createTexture();const n=new Float32Array([-1,-1,0,1,1,-1,1,1,-1,1,0,0,1,1,1,0]),r=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,r),e.bufferData(e.ARRAY_BUFFER,n,e.STATIC_DRAW);const a=e.getAttribLocation(this._program,"aPosition"),c=e.getAttribLocation(this._program,"aTexCoord");e.enableVertexAttribArray(a),e.vertexAttribPointer(a,2,e.FLOAT,!1,16,0),e.enableVertexAttribArray(c),e.vertexAttribPointer(c,2,e.FLOAT,!1,16,8)}process(e){if(!this._options.enabled)return e;const{displayWidth:t,displayHeight:s,timestamp:n}=e;(this._canvas.width!==t||this._canvas.height!==s)&&(this._canvas.width=t,this._canvas.height=s,this._gl.viewport(0,0,t,s));const r=this._gl;r.useProgram(this._program),r.activeTexture(r.TEXTURE0),r.bindTexture(r.TEXTURE_2D,this._texture),r.texImage2D(r.TEXTURE_2D,0,r.RGBA,r.RGBA,r.UNSIGNED_BYTE,e),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_S,r.CLAMP_TO_EDGE),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_T,r.CLAMP_TO_EDGE),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MIN_FILTER,r.LINEAR);const a=this._options.chromaKey||[0,255,0];r.uniform3f(r.getUniformLocation(this._program,"uChromaKey"),a[0]/255,a[1]/255,a[2]/255),r.uniform1f(r.getUniformLocation(this._program,"uSimilarity"),this._options.similarity??.3),r.uniform1f(r.getUniformLocation(this._program,"uSmoothness"),this._options.smoothness??.25),r.uniform1f(r.getUniformLocation(this._program,"uSpill"),this._options.despillStrength??1.15),r.drawArrays(r.TRIANGLE_STRIP,0,4);const c=new VideoFrame(this._canvas,{timestamp:n,duration:e.duration??void 0});return e.close(),c}_createProgram(e,t){const s=this._gl,n=(a,c)=>{const l=s.createShader(a);return s.shaderSource(l,c),s.compileShader(l),l},r=s.createProgram();return s.attachShader(r,n(s.VERTEX_SHADER,e)),s.attachShader(r,n(s.FRAGMENT_SHADER,t)),s.linkProgram(r),r}onDispose(){const e=this._gl;this._texture&&e.deleteTexture(this._texture),this._program&&e.deleteProgram(this._program),i.info("WebGL Green Screen Processor disposed")}updateOptions(e){this._options={...this._options,...e}}}class ue extends h{constructor(e,t){if(super(),this._context=e,this._source=new B,this._pipeline=new H(this._source,t),t?.renderMode==="processed"&&t?.greenScreen?.enabled){const s=new w(t.greenScreen);this._pipeline.setProcessor(s),i.info("Green screen processor enabled")}this._pipeline.setRenderFitMode(t?.fitMode||"contain"),i.info("Video Controller created")}setTrack(e,t,s){this.ensureNotDisposed(),this._source.setTrack(e,t,s)}removeTrack(e){this.ensureNotDisposed(),this._source.trackId===e&&this._source.clearTrack()}setRenderMode(e){this.ensureNotDisposed(),this._pipeline.setRenderMode(e),this._context.eventBus.emit("inner:video:render:mode:changed",{mode:e})}setRenderFitMode(e){this.ensureNotDisposed(),this._pipeline.setRenderFitMode(e)}getSource(){return this.ensureNotDisposed(),this._source}onDispose(){this._source.dispose(),this._pipeline.dispose(),i.info("Video Controller disposed")}}class _e extends h{process(e,t){return this.ensureNotDisposed(),e}onDispose(){}}class pe extends h{set onProcessedAudio(e){this._onProcessedAudio=e}constructor(e){super(),this._processors=[],this._processingStrategy=new _e,i.info("Input Audio Pipeline created")}setProcessingStrategy(e){this.ensureNotDisposed(),this._processingStrategy&&this._processingStrategy.dispose(),this._processingStrategy=e,i.debug("Audio processing strategy set")}get processingStrategy(){return this._processingStrategy}addProcessor(e){this.ensureNotDisposed(),this._processors.push(e),i.debug(`Audio processor added. Total: ${this._processors.length}`)}removeProcessor(e){this.ensureNotDisposed();const t=this._processors.indexOf(e);t>=0&&(this._processors.splice(t,1),i.debug(`Audio processor removed. Total: ${this._processors.length}`))}process(e,t){this.ensureNotDisposed();let s=e;try{s=this._processingStrategy.process(s,t)}catch(n){i.error("Error in audio processing strategy:",n)}for(const n of this._processors)try{s=n.process(s,t)}catch(r){i.error("Error in audio processor:",r);continue}this._onProcessedAudio&&this._onProcessedAudio(s,t)}onDispose(){if(this._processingStrategy)try{this._processingStrategy.dispose()}catch(e){i.error("Error disposing audio processing strategy:",e)}this._processors.forEach(e=>{try{e.dispose()}catch(t){i.error("Error disposing audio processor:",t)}}),this._processors.length=0,this._onProcessedAudio=void 0,i.info("Input Audio Pipeline disposed")}}class me extends h{constructor(){super(),this._audioElement=null,this._stream=null,this._track=null,this._volume=1,this._isMuted=!1,this._audioElement=document.createElement("audio"),this._audioElement.autoplay=!0,this._audioElement.volume=this._volume,this._audioElement.muted=this._isMuted,i.info("Output Audio Pipeline created")}getAudioElement(){if(!this._audioElement)throw new u("Audio element not found");return this._audioElement}setTrack(e){this.ensureNotDisposed(),this._track&&this._track!==e&&this._track.stop(),this._track=e,this._audioElement&&(this._stream&&(this._stream.getTracks().forEach(t=>t.stop()),this._stream=null),this._stream=new MediaStream([e]),this._audioElement.volume=this._volume,this._audioElement.muted=this._isMuted,i.debug("Audio track set to output pipeline"))}removeTrack(){this.ensureNotDisposed(),this._stream&&(this._stream.getTracks().forEach(e=>e.stop()),this._stream=null),this._track&&(this._track.stop(),this._track=null),i.debug("Audio track removed from output pipeline")}setVolume(e){this.ensureNotDisposed(),this._volume=Math.max(0,Math.min(1,e)),this._audioElement&&(this._audioElement.volume=this._volume),i.debug(`Audio output volume set to: ${this._volume}`)}getVolume(){return this._volume}mute(){this.ensureNotDisposed(),this._isMuted=!0,this._audioElement&&(this._audioElement.muted=!0),i.debug("Audio output muted")}unmute(){this.ensureNotDisposed(),this._isMuted=!1,this._audioElement&&(this._audioElement.muted=!1),i.debug("Audio output unmuted")}isMuted(){return this._isMuted}onDispose(){this.removeTrack(),this._audioElement&&(this._audioElement=null),i.info("Output Audio Pipeline disposed")}}const fe=1,ge=0,ve={0:0,1:1,2:2};function Ee(o){return o<0?0:o>4095?4095:Math.floor(o)}function Te(o){if(o<0)return 0;const e=1048575;return o>e?o&e:Math.floor(o)}function Ce(o){return o<0?0:o>4095?4095:Math.floor(o)}function Se(o){return o<0?0:o>65535?65535:Math.floor(o)}function Re(o){if(o!==0&&o!==1&&o!==2)throw new u(`Invalid sample rate encoding: ${o}. Must be 0 (16kHz), 1 (24kHz), or 2 (48kHz)`,d.AUDIO_INVALID_SAMPLE_RATE)}function Ae(o){Re(o.sampleRate);const e=Ee(o.sequenceNumber),t=Te(o.timestamp),s=Ce(o.frameSize),n=Se(o.payloadLength);if(o.channel!==0&&o.channel!==1)throw new u(`Invalid channel value: ${o.channel}. Must be 0 (mono) or 1 (stereo)`,d.AUDIO_INVALID_CHANNEL);const r=new Uint8Array(9);let a=fe<<6;a|=o.channel<<5,a|=(o.keyFrame?1:0)<<4,a|=e>>8&15,r[0]=a,r[1]=e&255,r[2]=t>>12&255,r[3]=t>>4&255;const c=ve[o.sampleRate];let l=(t&15)<<4;l|=c<<2,l|=s>>10&3,r[4]=l,r[5]=s>>2&255;let p=(s&3)<<6;return p|=ge&63,r[6]=p,r[7]=n>>8&255,r[8]=n&255,r}class De{constructor(e){this.transport=e}sendBinary(e){this.transport.sendBinary(e)}isConnected(){return this.transport.isConnected}}class we extends h{constructor(e,t){super(),this._wsSender=null,this._sequenceNumber=0,this._isKeyFrame=!0,this._audioStartTime=0,this._isSending=!1,this._audioFrameListener=null,this._audioBuffer=[],this._bufferedSampleCount=0,this._targetSampleRate=24e3,this._bitDepth=16,this._minSamplesToSend=0,this._context=e,this._options=t;const s=t?.input;this._targetSampleRate=s?.sampleRate||24e3,this._bitDepth=s?.bitDepth||16,this._minSamplesToSend=Math.floor(this._targetSampleRate/10),i.info(`Audio Frame Sender created: sampleRate=${this._targetSampleRate}Hz, bitDepth=${this._bitDepth}bit, minSamples=${this._minSamplesToSend}`)}setWebSocketSender(e){this._wsSender=e}setConversationTransport(e){this._wsSender=new De(e)}start(){if(this.ensureNotDisposed(),this._isSending){i.warn("Audio frame sending already started");return}this._sequenceNumber=0,this._isKeyFrame=!0,this._audioStartTime=Date.now(),this._audioFrameListener=e=>{this._handleAudioFrame(e.data,e.sampleRate)},this._context.eventBus.on("inner:audio:frame:received",this._audioFrameListener),this._isSending=!0,i.info("Audio frame sending started")}stop(){this.ensureNotDisposed(),this._isSending&&(this._flushBuffer(),this._audioFrameListener&&(this._context.eventBus.off("inner:audio:frame:received",this._audioFrameListener),this._audioFrameListener=null),this._isSending=!1,i.info("Audio frame sending stopped"))}_handleAudioFrame(e,t){if(this._isSending)try{Math.abs(t-this._targetSampleRate)>1&&i.warn(`Sample rate mismatch: expected ${this._targetSampleRate}Hz, got ${t}Hz`),this._audioBuffer.push(new Float32Array(e)),this._bufferedSampleCount+=e.length,this._bufferedSampleCount>=this._minSamplesToSend&&this._flushBuffer()}catch(s){i.error("Error handling audio frame:",s)}}_flushBuffer(){if(!(this._audioBuffer.length===0||this._bufferedSampleCount===0))try{const e=this._bufferedSampleCount,t=new Float32Array(e);let s=0;for(const _ of this._audioBuffer)t.set(_,s),s+=_.length;this._audioBuffer=[],this._bufferedSampleCount=0;const n=this._convertToPCM(t,this._bitDepth),r=Math.ceil(this._bitDepth/8),a=n.length*r,c=this._getSampleRateEncoding(this._targetSampleRate),l=Math.floor(Date.now()-this._audioStartTime),p={channel:(this._options?.input?.channels||1)===1?0:1,keyFrame:!!this._isKeyFrame,sequenceNumber:this._sequenceNumber,timestamp:l,sampleRate:c,frameSize:t.length,payloadLength:a},m=this._pcmToUint8Array(n,this._bitDepth);if(setTimeout(()=>{try{this._context.eventBus.emit("inner:audio:payload:send",{payload:m,sampleRate:this._targetSampleRate,channels:this._options?.input?.channels||1,sequenceNumber:p.sequenceNumber,timestamp:p.timestamp,keyFrame:p.keyFrame,frameSize:p.frameSize})}catch(_){i.error("Error emitting inner:audio:payload:send event:",_)}},0),this._wsSender&&this._wsSender.isConnected())try{const _=Ae(p),g=new Uint8Array(_.length+m.length);g.set(_,0),g.set(m,_.length),this._wsSender.sendBinary(g),i.debug(`Audio frame sent via WS: seq=${p.sequenceNumber}, samples=${t.length}, size=${g.length} bytes`)}catch(_){i.error("Error sending audio frame via WebSocket:",_)}this._isKeyFrame=!1,this._sequenceNumber=(this._sequenceNumber+1)%4096}catch(e){i.error("Error flushing audio buffer:",e)}}_convertToPCM(e,t){if(t===16){const s=new Int16Array(e.length);for(let n=0;n<e.length;n++){const r=Math.max(-1,Math.min(1,e[n]));s[n]=r<0?r*32768:r*32767}return s}else if(t===32){const s=new Int32Array(e.length);for(let n=0;n<e.length;n++){const r=Math.max(-1,Math.min(1,e[n]));s[n]=r*2147483647}return s}else return i.warn(`Unsupported bit depth: ${t}, using 16-bit`),this._convertToPCM(e,16)}_pcmToUint8Array(e,t){const s=Math.ceil(t/8),n=new Uint8Array(e.length*s),r=new DataView(n.buffer);for(let a=0;a<e.length;a++)t===16?r.setInt16(a*2,e[a],!0):t===32&&r.setInt32(a*4,e[a],!0);return n}_getSampleRateEncoding(e){return e===16e3?0:e===24e3?1:e===48e3?2:(i.warn(`Unsupported sample rate: ${e}, defaulting to 48kHz`),1)}onDispose(){this.stop(),i.info("Audio Frame Sender disposed")}}class ye extends h{emitAudioData(e,t){if(this.onAudioData)try{this.onAudioData(e,t)}catch(s){i.error("Error in audio data callback:",s)}}}const be=`
56
+ class AudioResamplerProcessor extends AudioWorkletProcessor {
57
+ constructor(options) {
58
+ super();
59
+ this.targetSampleRate = options.processorOptions?.targetSampleRate || 24000;
60
+ this.bitDepth = options.processorOptions?.bitDepth || 16;
61
+ this.channels = options.processorOptions?.channels || 1;
62
+
63
+ // Resampling related
64
+ // sampleRate is a global in AudioWorkletProcessor representing the AudioContext's sample rate
65
+ this.resampleRatio = this.targetSampleRate / sampleRate;
66
+
67
+ // Timestamp tracking
68
+ this.frameCount = 0;
69
+ }
70
+
71
+ process(inputs, outputs, parameters) {
72
+ const input = inputs[0];
73
+ if (!input || input.length === 0 || !input[0] || input[0].length === 0) {
74
+ return true;
75
+ }
76
+
77
+ const inputData = input[0]; // mono input
78
+ const inputLength = inputData.length;
79
+
80
+ // Linear resampling
81
+ const outputLength = Math.floor(inputLength * this.resampleRatio);
82
+ const resampledData = new Float32Array(outputLength);
83
+
84
+ for (let i = 0; i < outputLength; i++) {
85
+ const srcIndex = i / this.resampleRatio;
86
+ const srcIndexFloor = Math.floor(srcIndex);
87
+ const srcIndexCeil = Math.min(srcIndexFloor + 1, inputLength - 1);
88
+ const fraction = srcIndex - srcIndexFloor;
89
+
90
+ // Linear interpolation
91
+ resampledData[i] = inputData[srcIndexFloor] * (1 - fraction) + inputData[srcIndexCeil] * fraction;
92
+ }
93
+
94
+ // Post the resampled data
95
+ this.port.postMessage({
96
+ type: 'audioData',
97
+ data: resampledData,
98
+ sampleRate: this.targetSampleRate,
99
+ bitDepth: this.bitDepth,
100
+ frameCount: this.frameCount,
101
+ });
102
+
103
+ this.frameCount += outputLength;
104
+
105
+ return true;
106
+ }
107
+ }
108
+
109
+ registerProcessor('audio-resampler', AudioResamplerProcessor);
110
+ `;function Ne(){const o=new Blob([be],{type:"text/javascript"});return URL.createObjectURL(o)}class Ie extends ye{constructor(e){super(),this.options=e,this._stream=null,this._audioContext=null,this._sourceNode=null,this._workletNode=null,this._targetSampleRate=A,this._bitDepth=I,this._channels=1;const t=e?.input;this._targetSampleRate=t?.sampleRate||A,this._bitDepth=t?.bitDepth||I,this._channels=t?.channels||1}async start(){this.ensureNotDisposed();try{const t={audio:this.options?.input?.constraints||{channelCount:this._channels}};this._stream=await navigator.mediaDevices.getUserMedia(t);const r=this._stream.getAudioTracks()[0].getSettings().sampleRate||44100;this._audioContext=new AudioContext({sampleRate:r});const a=Ne();await this._audioContext.audioWorklet.addModule(a),this._sourceNode=this._audioContext.createMediaStreamSource(this._stream),this._workletNode=new AudioWorkletNode(this._audioContext,"audio-resampler",{processorOptions:{targetSampleRate:this._targetSampleRate,bitDepth:this._bitDepth,channels:this._channels},numberOfInputs:1,numberOfOutputs:0}),this._workletNode.port.onmessage=c=>{const{type:l,data:p,sampleRate:m}=c.data;l==="audioData"&&p&&this.emitAudioData(p,m)},this._sourceNode.connect(this._workletNode),i.info(`Audio capture started: input=${r}Hz -> output=${this._targetSampleRate}Hz, ${this._bitDepth}bit`)}catch(e){throw u.fromError(e,d.AUDIO_CAPTURE_FAILED)}}stop(){this._stream&&(this._stream.getTracks().forEach(e=>e.stop()),this._stream=null),this._workletNode&&(this._workletNode.port.onmessage=null,this._workletNode.disconnect(),this._workletNode=null),this._sourceNode&&(this._sourceNode.disconnect(),this._sourceNode=null),this._audioContext&&(this._audioContext.close(),this._audioContext=null),i.info("Audio capture stopped")}onDispose(){this.stop()}}class ke{create(e){return new Ie(e)}}class Oe extends h{constructor(e,t,s){super(),this._source=null,this._isCapturing=!1,this._currentOutputTrackId=null,this._context=e,this._inputPipeline=new pe(t),this._outputPipeline=new me,this._frameSender=new we(e,t),this._sourceFactory=s||new ke,this._inputPipeline.onProcessedAudio=(n,r)=>{this._context.eventBus.emit("inner:audio:frame:received",{data:n,sampleRate:r})},i.info("Audio Controller created")}setWebSocketSender(e){this._frameSender.setWebSocketSender(e)}async startCapture(){if(this.ensureNotDisposed(),this._isCapturing){i.warn("Audio capture already started");return}try{this._source||(this._source=this._sourceFactory.create(this._context.options.audio),this._source.onAudioData=(e,t)=>{this._inputPipeline.process(e,t)}),await this._source.start(),this._isCapturing=!0,this._frameSender.start(),this._context.eventBus.emit("inner:audio:input:started",void 0),i.info("Audio capture started")}catch(e){throw this._context.emitError(e,d.AUDIO_CAPTURE_START_FAILED)}}stopCapture(){this.ensureNotDisposed(),this._isCapturing&&(this._source&&this._source.stop(),this._frameSender.stop(),this._isCapturing=!1,this._context.eventBus.emit("inner:audio:input:stopped",void 0),i.info("Audio capture stopped"))}get isCapturing(){return this._isCapturing}setOutputTrack(e,t,s){this.ensureNotDisposed(),this._outputPipeline.setTrack(e),this._currentOutputTrackId=t,this._context.eventBus.emit("inner:audio:track:added",{trackId:t,participantId:s}),i.info("Audio output track ready")}removeOutputTrack(e){this.ensureNotDisposed(),this._currentOutputTrackId===e&&(this._outputPipeline.removeTrack(),this._currentOutputTrackId=null,this._context.eventBus.emit("inner:audio:track:removed",{trackId:e}),i.info("Audio output track removed"))}setVolume(e){this.ensureNotDisposed(),this._outputPipeline.setVolume(e),this._context.eventBus.emit("inner:audio:volume:changed",{volume:e}),i.debug(`Audio volume set to: ${e}`)}getVolume(){return this._outputPipeline.getVolume()}mute(){this.ensureNotDisposed(),this._outputPipeline.mute(),this._context.eventBus.emit("inner:audio:muted",void 0),i.debug("Audio muted")}unmute(){this.ensureNotDisposed(),this._outputPipeline.unmute(),this._context.eventBus.emit("inner:audio:unmuted",void 0),i.debug("Audio unmuted")}getOutputElement(){return this._outputPipeline.getAudioElement()}isMuted(){return this._outputPipeline.isMuted()}onDispose(){this.stopCapture(),this._source&&(this._source.dispose(),this._source=null),this._inputPipeline.dispose(),this._outputPipeline.dispose(),this._frameSender.dispose(),i.info("Audio Controller disposed")}}exports.ConversationStateType=void 0;(function(o){o.IDLE="idle",o.WAITING="waiting",o.STREAMING="streaming",o.COMPLETED="completed",o.ERROR="error"})(exports.ConversationStateType||(exports.ConversationStateType={}));class xe extends W{constructor(){super(...arguments),this._currentState=exports.ConversationStateType.IDLE,this.transitionTable=[{from:exports.ConversationStateType.IDLE,to:[exports.ConversationStateType.WAITING,exports.ConversationStateType.ERROR]},{from:exports.ConversationStateType.WAITING,to:[exports.ConversationStateType.STREAMING,exports.ConversationStateType.ERROR]},{from:exports.ConversationStateType.STREAMING,to:[exports.ConversationStateType.COMPLETED,exports.ConversationStateType.ERROR]},{from:exports.ConversationStateType.COMPLETED,to:[exports.ConversationStateType.IDLE,exports.ConversationStateType.WAITING,exports.ConversationStateType.ERROR]},{from:exports.ConversationStateType.ERROR,to:[exports.ConversationStateType.IDLE]}]}reset(){this._currentState=exports.ConversationStateType.IDLE}}class O extends h{constructor(e,t){super(),this._currentQuestion=null,this._currentAnswer=null,this._sessionId=e,this._stateMachine=new xe,i.info(`Conversation session created: ${e}`)}get sessionId(){return this._sessionId}get state(){return this._stateMachine.getCurrentState()}_setQuestion(e){this._currentQuestion=e,this._stateMachine.transitionTo(exports.ConversationStateType.WAITING),this._syncContextState()}get currentQuestion(){return this._currentQuestion}_startAnswer(e){this._currentAnswer={questionId:e,text:"",isComplete:!1,timestamp:Date.now()},this._stateMachine.transitionTo(exports.ConversationStateType.STREAMING),this._syncContextState()}_appendAnswerChunk(e){this._currentAnswer&&(this._currentAnswer.text+=e)}_completeAnswer(){this._currentAnswer&&(this._currentAnswer.isComplete=!0,this._currentAnswer.completedAt=Date.now()),this._stateMachine.transitionTo(exports.ConversationStateType.COMPLETED),this._syncContextState()}get currentAnswer(){return this._currentAnswer}_setError(e){this._stateMachine.transitionTo(exports.ConversationStateType.ERROR),this._syncContextState()}_syncContextState(){}handleEvent(e){const t=this._stateMachine.getCurrentState();switch(e.type){case"QUESTION":if(t!==exports.ConversationStateType.IDLE&&t!==exports.ConversationStateType.COMPLETED){i.warn(`Ignoring QUESTION event in invalid state: ${t}`);return}this._setQuestion(e.payload);break;case"ANSWER_START":if(t!==exports.ConversationStateType.WAITING){i.warn(`Ignoring ANSWER_START event in invalid state: ${t}. Expected: WAITING`);return}this._startAnswer(e.payload);break;case"ANSWER_CHUNK":if(t!==exports.ConversationStateType.STREAMING){i.warn(`Ignoring ANSWER_CHUNK event in invalid state: ${t}. Expected: STREAMING`);return}this._appendAnswerChunk(e.payload&&e.payload.chunk||""),e.payload&&e.payload.isComplete&&this._completeAnswer();break;case"ANSWER_COMPLETE":if(t!==exports.ConversationStateType.STREAMING){i.warn(`Ignoring ANSWER_COMPLETE event in invalid state: ${t}. Expected: STREAMING`);return}this._completeAnswer();break;case"ERROR":this._setError(e.payload);break;default:i.warn(`Unknown event type: ${e.type}`);break}}reset(){this._stateMachine.reset(),this._currentQuestion=null,this._currentAnswer=null}onDispose(){this.reset(),i.info(`Conversation session disposed: ${this._sessionId}`)}}class Le extends h{constructor(){super(...arguments),this._buffers=new Map}appendChunk(e,t){this.ensureNotDisposed();const n=(this._buffers.get(e)||"")+t;return this._buffers.set(e,n),i.debug(`Message chunk appended for question ${e}, length: ${n.length}`),n}getMessage(e){return this._buffers.get(e)||null}complete(e){const t=this.getMessage(e)||"";return this._buffers.delete(e),i.debug(`Message assembly completed for question ${e}, length: ${t.length}`),t}clear(e){this._buffers.delete(e)}onDispose(){this._buffers.clear(),i.info("Message Assembler disposed")}}class Pe{generateSessionId(){return`session_${Date.now()}_${Math.random().toString(36).substring(2,9)}`}generateQuestionId(){return Math.random().toString(36).substring(2,6)}}class Fe extends h{constructor(e,t){super(),this._transport=null,this._sessions=new Map,this._context=e,this._assembler=new Le,this._idService=new Pe,i.info("Conversation Manager created")}setTransport(e){this._transport=e}async sendQuestion(e,t={speed:100,mood:0,vol:50}){this.ensureNotDisposed();const s=this._idService.generateQuestionId(),n={id:s,text:e,timestamp:Date.now(),inputMode:"text"},r=this._idService.generateSessionId(),a=new O(r,this._context);if(a.handleEvent({type:"QUESTION",payload:n}),this._sessions.set(s,a),this._transport)try{this._transport.sendText(s,e,200,t)}catch(c){throw i.error("Error sending question via transport:",c),a.handleEvent({type:"ERROR",payload:"Failed to send question"}),this._context.eventBus.emit("inner:sdk:error",{error:c instanceof Error?c:new Error(String(c))}),c}else i.warn("Transport not set, question not sent");return this._context.eventBus.emit("inner:conversation:question:sent",{questionId:s,text:e}),this._context.eventBus.emit("inner:conversation:answer:waiting",{questionId:s}),i.info(`Question sent: ${s}`),s}handleServerPong(){this.ensureNotDisposed(),this._transport&&this._transport.handlePongReceived()}willDisconnect(){this.ensureNotDisposed(),this._transport?.willDisconnect()}handleTextInput(e){this.sendQuestion(e).catch(t=>{i.error("Error sending question:",t)})}handleAnswerChunk(e,t,s){this.ensureNotDisposed();const n=this._sessions.get(e);if(!n){i.warn(`No active session for answer chunk: ${e}`);return}if(n.state===exports.ConversationStateType.WAITING&&n.handleEvent({type:"ANSWER_START",payload:e}),s){n.handleEvent({type:"ANSWER_COMPLETE"});const a=this._assembler.complete(e);this._context.eventBus.emit("inner:conversation:answer:completed",{questionId:e,fullAnswer:a});try{n.dispose()}catch(c){i.error("Error disposing session:",c)}this._sessions.delete(e)}else n.handleEvent({type:"ANSWER_CHUNK",payload:{uid:e,chunk:t,isComplete:s}}),this._assembler.appendChunk(e,t),this._context.eventBus.emit("inner:conversation:answer:chunk",{questionId:e,chunk:t,isComplete:s})}handleServerInitiatedMessage(e,t){this.ensureNotDisposed(),this._context.eventBus.emit("inner:conversation:server:message",{questionId:e,message:t,type:"text"})}handleAsrTextReceived(e,t){this.ensureNotDisposed();const s=this._idService.generateSessionId(),n=new O(s,this._context);n.handleEvent({type:"QUESTION",payload:{id:e,text:t,timestamp:Date.now(),inputMode:"voice"}}),this._sessions.set(e,n),this._context.eventBus.emit("inner:conversation:asr:received",{questionId:e,text:t})}onDispose(){for(const e of this._sessions.values())try{e.dispose()}catch(t){i.error("Error disposing session:",t)}this._sessions.clear(),this._assembler.dispose(),i.info("Conversation Manager disposed")}}class Me extends h{constructor(e,t){super(),this._manager=new Fe(e,t),i.info("Conversation Controller created")}get manager(){return this._manager}setTransport(e){this._manager.setTransport(e)}async sendQuestion(e,t){return this.ensureNotDisposed(),this._manager.sendQuestion(e,t)}onDispose(){this._manager.dispose(),i.info("Conversation Controller disposed")}}class Ve extends h{constructor(){super(...arguments),this._tracks=new Map,this._participants=new Map}register(e,t,s){this.ensureNotDisposed(),this._tracks.set(e,t),this._participants.has(s)||this._participants.set(s,new Set),this._participants.get(s).add(e),t.on("ended",()=>{i.debug(`Track ended: ${e}`),this.unregister(e)}),i.debug(`Track registered: ${e} from participant ${s}`)}unregister(e){const t=this._tracks.get(e);if(t){t.stop(),this._tracks.delete(e);for(const[s,n]of this._participants.entries())if(n.has(e)){n.delete(e),n.size===0&&this._participants.delete(s);break}i.debug(`Track unregistered: ${e}`)}}getTrack(e){return this._tracks.get(e)||null}getParticipantTracks(e){const t=this._participants.get(e);return t?Array.from(t):[]}getAllTrackIds(){return Array.from(this._tracks.keys())}getVideoAvailability(){let e=!1,t=!1,s=!1;for(const n of this._tracks.values()){const r=n.mediaStreamTrack;if(r.kind==="video"&&(e=!0,r.readyState==="live"&&(t=!0),r.enabled&&(s=!0),r.readyState==="live"&&r.enabled))return{available:!0}}return e?t?s?{available:!1,reason:v.NO_VIDEO_TRACK}:{available:!1,reason:v.TRACK_MUTED}:{available:!1,reason:v.TRACK_ENDED}:{available:!1,reason:v.NO_VIDEO_TRACK}}clear(){for(const e of this._tracks.values())e.stop();this._tracks.clear(),this._participants.clear(),i.info("All tracks cleared")}onDispose(){this.clear()}}class x extends h{constructor(e,t){super(),this._videoController=null,this._room=null,this._context=e,this._trackRegistry=t,this._loosTrackTimer=null,i.info("Video Track Handler created")}setRoom(e){this._room=e}setVideoController(e){this._videoController=e}handleTrackSubscribed(e,t,s){this.ensureNotDisposed(),this._loosTrackTimer&&clearTimeout(this._loosTrackTimer),this._trackRegistry.register(t,e,s),this._videoController&&e.attach(this._videoController.getSource().getInternalElement()),e.on("videoPlaybackStarted",()=>{i.info("inner:rtc:video:available"),this._context.eventBus.emit("inner:rtc:video:available",void 0)}),this._context.eventBus.emit("inner:video:track:added",{trackId:t,participantId:s}),i.debug(`Video track subscribed: ${t}`)}handleTrackUnsubscribed(e,t,s){this.ensureNotDisposed(),this._videoController&&e.detach(this._videoController.getSource().getInternalElement()),e.removeAllListeners(),this._context.eventBus.emit("inner:video:track:removed",{trackId:t,participantId:s}),this._loosTrackTimer&&clearTimeout(this._loosTrackTimer),this._loosTrackTimer=setTimeout(()=>{this._context.eventBus.emit("inner:rtc:video:unavailable",void 0)},Y),this._trackRegistry.unregister(t),i.debug(`Video track unsubscribed: ${t}`)}supports(e){return e.mediaStreamTrack.kind==="video"}onDispose(){this._loosTrackTimer&&(clearTimeout(this._loosTrackTimer),this._loosTrackTimer=null),i.info("Video Track Handler disposed")}}class L extends h{constructor(e,t){super(),this._audioController=null,this._room=null,this._context=e,this._trackRegistry=t,i.info("Audio Track Handler created")}setRoom(e){this._room=e}setAudioController(e){this._audioController=e}handleTrackSubscribed(e,t,s){this.ensureNotDisposed(),this._trackRegistry.register(t,e,s),this._audioController?e.attach(this._audioController.getOutputElement()):this._context.eventBus.emit("inner:audio:track:added",{trackId:t,participantId:s}),i.debug(`Audio track subscribed: ${t}`)}handleTrackUnsubscribed(e,t,s){this.ensureNotDisposed(),this._audioController?(this._audioController.removeOutputTrack(t),e.detach(this._audioController.getOutputElement())):this._context.eventBus.emit("inner:audio:track:removed",{trackId:t}),this._trackRegistry.unregister(t),i.debug(`Audio track unsubscribed: ${t}`)}supports(e){return e.mediaStreamTrack.kind==="audio"}onDispose(){i.info("Audio Track Handler disposed")}}class Ue extends h{constructor(e,t){super(),this._room=null,this._context=e,this._trackRegistry=t,this._handlers=[new x(e,t),new L(e,t)],i.info("LiveKit Event Adapter created")}setRoom(e){this._room=e,this._handlers.forEach(t=>{t.setRoom(e)}),console.log("LiveKit room set:",this._room)}setVideoController(e){const t=this._handlers.find(s=>s instanceof x);t&&t.setVideoController(e)}setAudioController(e){const t=this._handlers.find(s=>s instanceof L);t&&t.setAudioController(e)}handleTrackSubscribed(e,t,s){this.ensureNotDisposed();const n=this._findHandler(e);n?n.handleTrackSubscribed(e,t,s):i.warn(`No handler found for track, trackId: ${t}`)}handleTrackUnsubscribed(e,t){this.ensureNotDisposed();const s=this._trackRegistry.getTrack(e);if(s){const n=this._findHandler(s);n?n.handleTrackUnsubscribed(s,e,t):(this._trackRegistry.unregister(e),i.warn(`No handler found for track, trackId: ${e}`))}}_findHandler(e){return this._handlers.find(t=>t.supports(e))||null}onDispose(){this._handlers.forEach(e=>{try{e.dispose()}catch(t){i.error("Error disposing track handler:",t)}}),this._handlers.length=0,i.info("LiveKit Event Adapter disposed")}}class Ke extends h{constructor(e){super(),this._room=null,this._context=e,this._trackRegistry=new Ve,this._eventAdapter=new Ue(e,this._trackRegistry),this._maxAttempts=e.options.reconnect?.maxAttempts||S,this._maxDelay=(e.options.reconnect?.delay??y)*C,i.info("LiveKit Service created")}async connect(e,t,s,n){if(this.ensureNotDisposed(),this._room&&this._room.isConnected()){i.warn("Already connected to LiveKit room");return}try{i.info(`Connecting to LiveKit room: ${s} at ${e}`);const r=new f.Room({reconnectPolicy:{nextRetryDelayInMs:a=>a.elapsedMs<this._maxDelay?Math.min(C*Math.pow(2,a.retryCount),this._maxDelay):null}});r.prepareConnection(e,t),r.on(f.RoomEvent.TrackSubscribed,(a,c,l)=>{this._handleTrackSubscribed(a,c,l)}),r.on(f.RoomEvent.TrackUnsubscribed,(a,c,l)=>{this._handleTrackUnsubscribed(a,c,l)}),r.on(f.RoomEvent.TrackMuted,(a,c)=>{this._handleTrackMuted(a,c)}),r.on(f.RoomEvent.TrackUnmuted,(a,c)=>{this._handleTrackUnmuted(a,c)}),r.on(f.RoomEvent.Connected,()=>{i.info("Connected to LiveKit room"),this._context.eventBus.emit("inner:rtc:connected",void 0)}),r.on(f.RoomEvent.Disconnected,a=>{a?i.info(`LiveKit room disconnected: ${a}`):i.info("LiveKit room disconnected"),a!==f.DisconnectReason.CLIENT_INITIATED&&this._context.eventBus.emit("inner:rtc:disconnected",{reason:a?String(a):void 0}),this._room=null}),i.info("Connecting to LiveKit room..."),await r.connect(e,t,{autoSubscribe:!0,maxRetries:this._context.options.reconnect?.maxAttempts||S}),this._eventAdapter.setRoom(r),this._room=r}catch(r){throw u.fromError(r,d.LIVEKIT_CONNECT_FAILED)}}_handleTrackSubscribed(e,t,s){try{if(!e.mediaStreamTrack){i.warn("Track does not have MediaStreamTrack");return}e.kind==="audio"&&s.on(f.ParticipantEvent.IsSpeakingChanged,c=>{console.log("\u8F68\u9053 \u8BF4\u8BDD\u72B6\u6001:",c)});const r=t.trackSid,a=s.identity;this._eventAdapter.handleTrackSubscribed(e,r,a)}catch(n){i.error("Error handling track subscribed:",n)}}_handleTrackUnsubscribed(e,t,s){try{const n=t,r=s,a=n.trackSid,c=r.identity;this._trackRegistry.getTrack(a)?.kind==="video"&&this._context.eventBus.emit("inner:rtc:video:unavailable",void 0),this._eventAdapter.handleTrackUnsubscribed(a,c)}catch(n){i.error("Error handling track unsubscribed:",n)}}_handleTrackMuted(e,t){try{e.kind==="video"&&this._context.eventBus.emit("inner:rtc:video:unavailable",void 0)}catch(s){i.error("Error handling track muted:",s)}}_handleTrackUnmuted(e,t){try{e.kind==="video"&&this._context.eventBus.emit("inner:rtc:video:available",void 0)}catch(s){i.error("Error handling track unmuted:",s)}}async disconnect(){if(this._room)try{await this._room.disconnect(),this._room=null,this._context.eventBus.emit("inner:rtc:disconnected",{reason:"Disconnected from LiveKit room"}),i.info("Disconnected from LiveKit room")}catch(e){i.error("Error disconnecting from LiveKit room:",e),this._room=null}}isConnected(){return this._room?this._room.state===f.ConnectionState.Connected:!1}getTrackRegistry(){return this._trackRegistry}get trackRegistry(){return this._trackRegistry}getEventAdapter(){return this._eventAdapter}onDispose(){this.disconnect(),this._trackRegistry.dispose(),this._eventAdapter.dispose(),i.info("LiveKit Service disposed")}}class We extends h{constructor(e){super(),this._conversationManager=null,this._context=e,i.info("WebSocket Dispatcher created")}setConversationManager(e){this._conversationManager=e,i.debug("Conversation manager set in dispatcher")}dispatch(e){this.ensureNotDisposed();try{if(e.type==="ws"){this._handleWSServerMessage(e);return}if(e.type==="text"){this._handleServerTextMessage(e);return}}catch(t){i.error("Error dispatching message:",t)}}_handleWSServerMessage(e){e.code===101?(this._conversationManager?.handleServerPong(),i.debug("Received pingpong response")):e.code===102&&(i.warn("Server will disconnect"),this._conversationManager?.willDisconnect())}_handleServerTextMessage(e){if(!this._conversationManager){i.warn("Conversation manager not set, text message ignored");return}const{uid:t,payload:s,code:n}=e;n===200?(this._conversationManager.handleAnswerChunk(t,s,!1),i.debug(`Answer received (code 401) for uid: ${t}`)):n===201?(this._conversationManager.handleAnswerChunk(t,"",!0),i.debug(`Answer completed (code 411) for uid: ${t}`)):n===300?(this._conversationManager.handleAsrTextReceived(t,s),i.debug(`ASR text chunk received (code 410) for uid: ${t}`)):n===400&&(this._conversationManager.handleServerInitiatedMessage(t,s),i.debug(`Server initiated message received (code 412) for uid: ${t}`))}onDispose(){i.info("WebSocket Dispatcher disposed")}}class Be extends h{constructor(e){super(),this._ws=null,this._dispatcher=null,this._isConnecting=!1,this._activeTimers=new Set,this._retryCount=0,this._maxRetries=S,this._pingTimer=void 0,this._pongTimer=void 0,this._isExplicitDisconnect=!1,this._context=e,this._maxRetries=e.options.reconnect?.maxAttempts??S,this._maxDelay=(e.options.reconnect?.delay??y)*C,this._dispatcher=new We(e)}setConversationManager(e){this._dispatcher&&this._dispatcher.setConversationManager(e)}async connect(){if(this.ensureNotDisposed(),this._stopHeartbeat(),!(this._isConnecting||this.isConnected||this._ws?.readyState===WebSocket.OPEN)){this._isConnecting=!0,this._isExplicitDisconnect=!1;try{return this._ws=new WebSocket(this._context.wsUrl),new Promise((e,t)=>{this._ws.onopen=()=>{this._isConnecting=!1,this._retryCount=0,this.sendPing(),this._context.eventBus.emit("inner:ws:connected",void 0),i.info("Conversation transport connected"),e()},this._ws.onerror=s=>{this._isConnecting=!1,i.error("Conversation transport error:",s),this._context.eventBus.emit("inner:sdk:error",{error:new u("WebSocket connection error",d.WS_CONNECT_ERROR,s)}),t(new u("WebSocket connection error",d.WS_CONNECT_ERROR,s))},this._ws.onclose=()=>{this._handleDisconnect()},this._ws.onmessage=s=>{this._handleMessage(s.data)}})}catch(e){throw this._isConnecting=!1,this._context.emitError(e,d.WS_CONNECT_FAILED)}}}disconnect(){this._isExplicitDisconnect=!0,this._stopHeartbeat(),this._ws&&(this._ws.close(),this._ws=null),this._context.eventBus.emit("inner:ws:disconnected",{reason:"Client disconnect"}),i.info("Conversation transport disconnected")}_handleDisconnect(){if(this._stopHeartbeat(),this._isConnecting=!1,!this._isExplicitDisconnect&&this._retryCount<this._maxRetries){this._retryCount++;const e=Math.min(C*Math.pow(2,this._retryCount-1),this._maxDelay);i.warn(`Connection lost. Retry ${this._retryCount} in ${e}ms`);const t=setTimeout(()=>{!this._isExplicitDisconnect&&!this.isDisposed&&this.connect().catch(()=>{})},e);this._registerTimer(t)}else this._context.eventBus.emit("inner:ws:disconnected",{reason:"Closed"})}_registerTimer(e){return this._activeTimers.add(e),e}_clearTimer(e){e&&(clearTimeout(e),this._activeTimers.delete(e))}sendPing(){if(!this.isConnected)return;const e={type:"ws",code:101,payload:"ping"};this._ws?.send(JSON.stringify(e)),clearTimeout(this._pongTimer),this._pongTimer=setTimeout(()=>{i.error(`Pong timeout (${N/C}s). Reconnecting...`),this._ws?.close()},N)}handlePongReceived(){clearTimeout(this._pongTimer),this._clearTimer(this._pingTimer),this._pingTimer=setTimeout(()=>{this.sendPing()},J)}willDisconnect(){if(this.ensureNotDisposed(),this._ws&&this._ws.readyState===WebSocket.OPEN){const t=JSON.stringify({type:"ws",code:102,payload:"will disconnect"});this._ws.send(t),this._isExplicitDisconnect=!0,this._ws.close(),this._ws=null,this._context.eventBus.emit("inner:ws:disconnected",{reason:"Client responsive to server's disconnect message."})}}sendText(e,t,s=200,n){if(this.ensureNotDisposed(),!this._ws||this._ws.readyState!==WebSocket.OPEN)throw new u("WebSocket is not connected",d.WS_NOT_CONNECTED);try{const a=JSON.stringify({type:"text",code:s,uid:e,metadata:n,payload:t});this._ws.send(a),i.debug("Text message sent via transport:",e)}catch(r){throw this._context.emitError(r,d.WS_TEXT_SEND_FAILED)}}_handleMessage(e){try{if(typeof e!="string")return;const t=JSON.parse(e);i.debug("Message received:",t.type),this._dispatcher?this._dispatcher.dispatch(t):i.warn("Dispatcher not set, message ignored")}catch(t){i.error("Error parsing message:",t),this._context.emitError(t,d.WS_PARSE_ERROR)}}sendBinary(e){if(this.ensureNotDisposed(),!this._ws||this._ws.readyState!==WebSocket.OPEN){i.debug("WebSocket not connected, binary data dropped");return}try{this._ws.send(e),i.debug("Binary data sent via transport")}catch(t){i.error("Error sending binary data:",t)}}get isConnected(){return this._ws?.readyState===WebSocket.OPEN}_stopHeartbeat(){this._clearTimer(this._pingTimer),this._clearTimer(this._pongTimer)}onDispose(){this._stopHeartbeat(),this.disconnect(),this._dispatcher&&(this._dispatcher.dispose(),this._dispatcher=null),i.info("Conversation transport disposed")}}const R=["sdk:connected","sdk:disconnected","sdk:error","media:video:available","media:video:unavailable","media:video:trackAdded","media:video:trackRemoved","media:audio:trackAdded","media:audio:trackRemoved","media:audio:captureStarted","media:audio:captureStopped","media:audio:volumeChanged","media:audio:muted","media:audio:unmuted","conversation:question:sent","conversation:answer:waiting","conversation:server:message","conversation:asr:received","conversation:answer:chunk","conversation:answer:completed"],P=/^[a-z]+:[a-zA-z]+(:[a-zA-Z]+)?$/;class $e{constructor(e){this.inner=e,this.listeners=new Map,this.forwardedVideoTrackIds=new Set,this.wsConnected=!1,this.livekitConnected=!1,this.httpConnected=!1,this.internalMap={"inner:sdk:error":{public:"sdk:error",sanitizer:t=>({message:t?.error?.message,code:t?.error?.code})},"inner:rtc:video:available":{public:"media:video:available"},"inner:rtc:video:unavailable":{public:"media:video:unavailable"},"inner:video:track:added":{public:"media:video:trackAdded"},"inner:video:track:removed":{public:"media:video:trackRemoved"},"inner:audio:track:added":{public:"media:audio:trackAdded"},"inner:audio:track:removed":{public:"media:audio:trackRemoved"},"inner:audio:input:started":{public:"media:audio:captureStarted"},"inner:audio:input:stopped":{public:"media:audio:captureStopped"},"inner:audio:volume:changed":{public:"media:audio:volumeChanged",sanitizer:t=>({volume:t?.volume})},"inner:audio:muted":{public:"media:audio:muted"},"inner:audio:unmuted":{public:"media:audio:unmuted"},"inner:conversation:question:sent":{public:"conversation:question:sent",sanitizer:t=>({questionId:t?.questionId,text:String(t?.text||"")})},"inner:conversation:answer:waiting":{public:"conversation:answer:waiting",sanitizer:t=>({questionId:t?.questionId})},"inner:conversation:server:message":{public:"conversation:server:message",sanitizer:t=>({questionId:t?.questionId,message:String(t?.message||""),type:String(t?.type||"")})},"inner:conversation:asr:received":{public:"conversation:asr:received",sanitizer:t=>({questionId:t?.questionId,text:String(t?.text||"")})},"inner:conversation:answer:chunk":{public:"conversation:answer:chunk",sanitizer:t=>({questionId:t?.questionId,chunk:String(t?.chunk||"")})},"inner:conversation:answer:completed":{public:"conversation:answer:completed",sanitizer:t=>({questionId:t?.questionId,fullAnswer:String(t?.fullAnswer||"")})}},Object.keys(this.internalMap).forEach(t=>{this.inner.on(t,s=>this.handleInternalEvent(t,s))}),this.inner.on("inner:sdk:connected",t=>this.handleConnected(t,!0)),this.inner.on("inner:sdk:disconnected",t=>this.handleConnected(t,!1)),R.forEach(t=>{this.inner.on(t,s=>this.handlePublicEvent(t,s))})}publicAPI(){return{on:this.on.bind(this),off:this.off.bind(this),once:this.once.bind(this)}}on(e,t){const s=String(e);return this.assertAllowed(s),this.listeners.has(s)||this.listeners.set(s,new Set),this.listeners.get(s).add(t),()=>this.off(e,t)}once(e,t){const s=String(e);this.assertAllowed(s);const n=r=>{try{t(r)}finally{this.off(e,n)}};return this.on(e,n)}off(e,t){const s=String(e);this.assertAllowed(s);const n=this.listeners.get(s);n&&(n.delete(t),n.size===0&&this.listeners.delete(s))}handleInternalEvent(e,t){const s=this.internalMap[e];if(!s)return;const n=s.public;if(R.indexOf(n)===-1)return;if(n==="media:video:trackAdded"){const c=t?.trackId||t?.id;if(typeof c=="string"){if(this.forwardedVideoTrackIds.has(c))return;this.forwardedVideoTrackIds.add(c)}}const r=s.sanitizer?s.sanitizer(t):t;if(!P.test(n))return;const a=this.listeners.get(n);!a||a.size===0||a.forEach(c=>{try{c(r)}catch(l){console.error("PublicEventEmitter listener error",l)}})}handlePublicEvent(e,t){if(R.indexOf(e)===-1)return;const s=Object.values(this.internalMap).find(a=>a.public===e),n=s&&s.sanitizer?s.sanitizer(t):t;if(e==="media:video:trackAdded"){const a=t?.trackId||t?.id;if(typeof a=="string"){if(this.forwardedVideoTrackIds.has(a))return;this.forwardedVideoTrackIds.add(a)}}const r=this.listeners.get(e);!r||r.size===0||r.forEach(a=>{try{a(n)}catch(c){console.error("PublicEventEmitter listener error",c)}})}handleConnected(e,t){e.source==="livekit"?this.livekitConnected=t:e.source==="ws"?this.wsConnected=t:e.source==="http"&&(this.httpConnected=t),this.maybeEmitSdkConnected(t?"connected":"disconnected")}maybeEmitSdkConnected(e){const t=e==="connected",s=t?!!this.livekitConnected:!this.livekitConnected,n=t?!!this.wsConnected:!this.wsConnected,r=t?!!this.httpConnected:!this.httpConnected,a={livekit:s,ws:n,http:r,all:s&&n&&r},c=JSON.stringify(a);this.lastConnectedPayloadJson!==c&&(this.lastConnectedPayloadJson=c,this.inner.emit(`sdk:${e}`,a))}assertAllowed(e){if(R.indexOf(e)===-1)throw new Error(`Event "${e}" is not allowed for public consumers`);if(!P.test(e))throw new Error(`Event name "${e}" does not follow namespace:domain[:action] naming`)}}class He extends h{constructor(e,t,s){super(),this._requestCounter=0,this._context=e,this._baseURL=t||"",this._defaultHeaders=s||{},i.info(`HTTP Service created with baseURL: ${this._baseURL||"none"}`)}setAuthToken(e){this._defaultHeaders.Authorization=`Bearer ${e}`}request(e){this.ensureNotDisposed();const t=e.requestId||`req_${Date.now()}_${++this._requestCounter}`,s=this._buildURL(e.url,e.params),n=this._mergeHeaders(e.headers),r={method:e.method||"GET",headers:n};e.data!==void 0&&(e.method||"GET")!=="GET"&&(typeof e.data=="string"?r.body=e.data:(r.body=JSON.stringify(e.data),!n["Content-Type"]&&!n["content-type"]&&(n["Content-Type"]="application/json")));const a=e.timeout||3e4,c=new AbortController;return r.signal=c.signal,new Promise((l,p)=>{const m=setTimeout(()=>c.abort(),a);fetch(s,r).then(async _=>{clearTimeout(m);const g={};_.headers.forEach((G,j)=>{g[j]=G});let E;const b=_.headers.get("content-type");b&&b.includes("application/json")?E=await _.json():E=await _.text();const q={requestId:t,status:_.status,headers:g,data:E,config:e};i.debug(`HTTP request succeeded: ${e.method} ${s} [${t}]`),l(q)}).catch(_=>{clearTimeout(m);const g=_&&_.name==="AbortError",E={requestId:t,status:_&&_.status||void 0,message:g?"Request aborted (timeout)":_&&_.message||"HTTP request failed",error:_,config:e};i.error(`HTTP request failed: ${e.method} ${s} [${t}]`,_),p(E)})})}get(e,t,s){return this.request({...s,url:e,method:"GET",params:t})}post(e,t,s){return this.request({...s,url:e,method:"POST",data:t})}put(e,t,s){return this.request({...s,url:e,method:"PUT",data:t})}delete(e,t){return this.request({...t,url:e,method:"DELETE"})}patch(e,t,s){return this.request({...s,url:e,method:"PATCH",data:t})}_buildURL(e,t){if(e.startsWith("http://")||e.startsWith("https://"))return this._appendParams(e,t);let s=this._baseURL;return s&&!s.endsWith("/")&&!e.startsWith("/")?s+="/":s&&s.endsWith("/")&&e.startsWith("/")&&(s=s.slice(0,-1)),s+=e,this._appendParams(s,t)}_appendParams(e,t){if(!t||Object.keys(t).length===0)return e;const s=new URLSearchParams;for(const[r,a]of Object.entries(t))s.append(r,String(a));const n=e.includes("?")?"&":"?";return`${e}${n}${s.toString()}`}_mergeHeaders(e){const t={...this._defaultHeaders};return e&&Object.assign(t,e),t}onDispose(){i.info("HTTP Service disposed")}}class ze extends h{constructor(e,t){super(),this._context=e,this._httpService=new He(e,t||te)}getAuthToken(){return this.ensureNotDisposed(),this._httpService?.request({url:"/auth/login",method:"GET",data:{}}).then(e=>{e.data.code===T&&this._httpService?.setAuthToken(e.data.data.token)}).catch(e=>{throw this._context.emitError(e,d.SDK_AUTH_TOKEN_FAILED)})}getLivekitConfig(){return this.ensureNotDisposed(),this._httpService?.request({url:"/stream/v1/start",method:"POST",data:{avatarName:this._context.options.avatarName}}).then(e=>{if(e.data.code===T){const t=e.data.data;return this._context.setLivekitConfig(t.livekitUrl,t.roomToken,t.roomId),this._context.setWsUrl(`${this._context.options.wsUrlPrefix||ie}/${t.roomId}/${this._context.options.avatarName}`),this._context.setVideoOptions({renderMode:t.greenScreen.enabled?"processed":"raw",greenScreen:t.greenScreen||{}}),!0}else throw new u(e.data.msg,d.SDK_GET_LIVEKIT_CONFIG_FAILED)}).catch(e=>{throw this._context.eventBus.emit("inner:sdk:error",{error:new u(e.message,d.SDK_GET_LIVEKIT_CONFIG_FAILED)}),u.fromError(e,d.SDK_GET_LIVEKIT_CONFIG_FAILED)})}switchVideo({onceActions:e,loopActions:t}){return this.ensureNotDisposed(),this._httpService?.request({url:"/avatar/v1/switch-video",method:"POST",data:{roomId:this._context.roomId,onceActions:e,loopActions:t}}).then(s=>{if(s.data.code===T)return!0;throw this._context.emitError(s.data.message,d.SDK_SWITCH_VIDEO_FAILED)})}interruptConversation(){return this.ensureNotDisposed(),this._httpService?.request({url:"/stream/v1/interrupt",method:"POST",data:{roomId:this._context.roomId}}).then(e=>{if(e.data.code===T)return!0;throw this._context.emitError(e.data.message,d.SDK_INTERRUPT_CONVERSATION_FAILED)}).finally(()=>{this._context.eventBus.emit("inner:sdk:disconnected",{source:"http"})})}disconnectConversation(){return this.ensureNotDisposed(),this._httpService?.request({url:"/stream/v1/stop",method:"POST",data:{roomId:this._context.roomId}}).then(e=>e.data.code===T).finally(()=>{this._context.eventBus.emit("inner:sdk:disconnected",{source:"http"})})}onDispose(){this._httpService.dispose()}}class z extends h{constructor(e){super(),this._videoController=null,this._audioController=null,this._conversationController=null,this._liveKitService=null,this._conversationTransport=null,this._connectionCoordinator=null,this._httpController=null,this._preConnectPromise=null,this._context=new ne(e),i.info("SDK Client created")}get events(){return this.ensureNotDisposed(),this._publicEventAPI||(this._publicEmitter=new $e(this._context.eventBus),this._publicEventAPI=this._publicEmitter.publicAPI()),this._publicEventAPI}pushActions({onceActions:e,loopActions:t}){return this.ensureNotDisposed(),this._ensureConnected(),this._httpController?.switchVideo({onceActions:e,loopActions:t})}interruptConnection(){return this.ensureNotDisposed(),this._ensureConnected(),this._httpController?.interruptConversation()}sendTextQuestion(e){if(this.ensureNotDisposed(),this._ensureConnected(),this._conversationController)return this._conversationController.sendQuestion(e);throw new u("Conversation controller is not available",d.CONVERSATION_CONTROLLER_NOT_AVAILABLE)}setRenderFitMode(e){this.ensureNotDisposed(),this._ensureConnected(),this._videoController&&this._videoController.setRenderFitMode(e)}async startAudioCapture(){if(this.ensureNotDisposed(),this._ensureConnected(),!this._audioController)throw new u("Audio controller is not available",d.AUDIO_CONTROLLER_NOT_AVAILABLE);await this._audioController.startCapture()}async stopAudioCapture(){if(this.ensureNotDisposed(),this._ensureConnected(),!this._audioController)throw new u("Audio controller is not available",d.AUDIO_CONTROLLER_NOT_AVAILABLE);await this._audioController.stopCapture()}setVolume(e){if(this.ensureNotDisposed(),this._ensureConnected(),!this._audioController)throw new u("Audio controller is not available",d.AUDIO_CONTROLLER_NOT_AVAILABLE);this._audioController.setVolume(e)}getVolume(){if(this.ensureNotDisposed(),this._ensureConnected(),!this._audioController)throw new u("Audio controller is not available",d.AUDIO_CONTROLLER_NOT_AVAILABLE);return this._audioController?.getVolume()||1}mute(){if(this.ensureNotDisposed(),this._ensureConnected(),!this._audioController)throw new u("Audio controller is not available",d.AUDIO_CONTROLLER_NOT_AVAILABLE);this._audioController.mute()}unmute(){if(this.ensureNotDisposed(),this._ensureConnected(),!this._audioController)throw new u("Audio controller is not available",d.AUDIO_CONTROLLER_NOT_AVAILABLE);this._audioController.unmute()}get isMuted(){if(this.ensureNotDisposed(),this._ensureConnected(),!this._audioController)throw new u("Audio controller is not available",d.AUDIO_CONTROLLER_NOT_AVAILABLE);return this._audioController.isMuted()}get isAudioCapturing(){return this.ensureNotDisposed(),this._ensureConnected(),this._audioController?this._audioController.isCapturing:!1}async preConnect(){return this.ensureNotDisposed(),this._preConnectPromise?this._preConnectPromise:(this._preConnectPromise=(async()=>{try{if(i.info("Creating HTTP controller..."),this._httpController=this._httpController??new ze(this._context,this._context.options.http?.baseURL),i.info("Getting auth token..."),await this._httpController.getAuthToken(),i.info("Getting livekit config..."),!!!await this._httpController?.getLivekitConfig())throw new Error("Config missing");return!0}catch(e){throw this._preConnectPromise=null,this._context.emitError(e,d.SDK_PRECONNECT_FAILED)}})(),this._preConnectPromise)}async connect(){if(this.ensureNotDisposed(),this._connectionCoordinator&&this._context.sessionState.isConnected){i.warn("SDK already initialized");return}try{if(!await this.preConnect())throw new u("PreConnect failed without explicit error",d.SDK_CONNECT_FAILED)}catch(e){throw this._context.emitError(e,d.SDK_CONNECT_FAILED)}try{if(i.info("Initializing SDK..."),this._connectionCoordinator=new oe(this._context),this._connectionCoordinator.start(),this._connectionCoordinator.startConnecting(),this._videoController=new ue(this._context,this._context.options.video),this._audioController=new Oe(this._context,this._context.options.audio),this._conversationController=new Me(this._context),this._liveKitService=new Ke(this._context),this._conversationTransport=new Be(this._context),this._liveKitService&&this._videoController&&this._audioController){const e=this._liveKitService.getEventAdapter();e&&(typeof e.setVideoController=="function"&&e.setVideoController(this._videoController),typeof e.setAudioController=="function"&&e.setAudioController(this._audioController))}this._audioController&&this._conversationTransport&&this._audioController.setWebSocketSender({sendBinary:e=>{this._conversationTransport.sendBinary(e)},isConnected:()=>this._conversationTransport.isConnected}),this._conversationTransport&&this._conversationController&&(this._conversationTransport.setConversationManager(this._conversationController.manager),this._conversationController.setTransport(this._conversationTransport)),await this._liveKitService.connect(this._context.livekitUrl,this._context.token,this._context.options.avatarName),this._conversationTransport&&await this._conversationTransport.connect(),i.info("SDK initialized and connected")}catch(e){throw this._connectionCoordinator&&this._connectionCoordinator.transitionToIdle(),await this._cleanup(),this._context.emitError(e,d.SDK_INITIALIZATION_FAILED)}}async disconnect(){if(this.ensureNotDisposed(),!(!this._connectionCoordinator||this._connectionCoordinator.getState()==="idle"||this._connectionCoordinator.getState()==="disposed")){i.info("Disconnecting SDK..."),this._connectionCoordinator.startDisconnecting();try{this._conversationTransport&&this._conversationTransport.disconnect(),this._liveKitService&&await this._liveKitService.disconnect(),this._audioController&&this._audioController.stopCapture(),this._httpController&&await this._httpController.disconnectConversation(),this._preConnectPromise=null,this._connectionCoordinator.completeDisconnecting(),i.info("SDK disconnected")}catch(e){throw i.error("Error during disconnect:",e),this._context.emitError(e,d.SDK_DISCONNECT_FAILED)}}}async reconnect(){this.ensureNotDisposed();const e=this._connectionCoordinator;if(!e?.canStartReconnectingManual()){const s=e?e.getSnapshot():this.connectionSnapshot;return i.warn("SDK reconnect not allowed in current state, returning current snapshot"),s}const t=e.captureSnapshotAndStartReconnectingManual();try{return this._audioController&&this._audioController.stopCapture(),t.rtc.connected&&!t.rtc.hasVideoTrack&&(await this._liveKitService?.disconnect(),await this._conversationTransport?.disconnect()),this._conversationTransport&&!this._conversationTransport.isConnected&&(await this.preConnect(),await this._conversationTransport.connect()),this._liveKitService&&!this._liveKitService.isConnected()&&await this._liveKitService.connect(this._context.livekitUrl,this._context.token,this._context.options.avatarName),t}catch(s){throw i.error("Error during reconnect:",s),this._context.emitError(s,d.SDK_RECONNECT_FAILED)}}get connectionSnapshot(){return this.ensureNotDisposed(),this._connectionCoordinator?this._connectionCoordinator.getSnapshot():K(U("idle"))}async _cleanup(){if(this._conversationTransport&&this._conversationTransport.disconnect(),this._liveKitService)try{await this._liveKitService.disconnect()}catch(e){i.error("Error disconnecting LiveKit:",e)}this._audioController&&this._audioController.stopCapture()}get isConnected(){return this.ensureNotDisposed(),this._context.sessionState.isConnected}_ensureConnected(){if(!this._context.sessionState.isConnected)throw new u("SDK is not connected. Call connect() first.",d.SDK_NOT_CONNECTED)}onDispose(){this.disconnect().catch(e=>{i.error("Error during disconnect in dispose:",e)}),this._videoController&&(this._videoController.dispose(),this._videoController=null),this._audioController&&(this._audioController.dispose(),this._audioController=null),this._conversationController&&(this._conversationController.dispose(),this._conversationController=null),this._liveKitService&&(this._liveKitService.dispose(),this._liveKitService=null),this._conversationTransport&&(this._conversationTransport.dispose(),this._conversationTransport=null),this._httpController&&(this._httpController.dispose(),this._httpController=null),this._connectionCoordinator&&(this._connectionCoordinator.transitionToDisposed(),this._connectionCoordinator.dispose(),this._connectionCoordinator=null),this._context.dispose(),i.info("SDK Client disposed")}}function qe(o){if(!o.avatarName)throw new u("avatarName is required",d.NO_AVATARNAME);return i.info("Creating SDK client with options:",{avatarName:o.avatarName}),new z(o)}class F extends h{constructor(e,t){super(),this._videoElement=null,this._videoUrl=null,this._isPlaying=!1,this._frameCallbackId=null,this._videoUrl=e,t?this._videoElement=t:(this._videoElement=document.createElement("video"),this._videoElement.style.opacity="0",this._videoElement.muted=!0,this._videoElement.playsInline=!0,this._videoElement.loop=!0,document.querySelector("#video-container")?.appendChild(this._videoElement)),i.info("Local Video Debug Source created")}get videoElement(){return this._videoElement}async load(){if(!this._videoElement)throw new Error("Video element or URL not set");return new Promise((e,t)=>{const s=this._videoElement,n=()=>{s.removeEventListener("loadedmetadata",n),s.removeEventListener("error",r),i.info(`Video loaded: ${s.videoWidth}x${s.videoHeight}`),e()},r=a=>{s.removeEventListener("loadedmetadata",n),s.removeEventListener("error",r),t(new Error(`Failed to load video: ${a}`))};s.addEventListener("loadedmetadata",n),s.addEventListener("error",r),s.src=this._videoUrl||"",s.load()})}async play(){if(!this._videoElement)throw new Error("Video element not set");if(!this._isPlaying)try{await this._videoElement.play(),this._videoElement.style.opacity="0",this._videoElement.setAttribute("loop","true"),this._isPlaying=!0,i.info("Video playback started")}catch(e){throw i.error("Failed to play video:",e),e}}pause(){this._videoElement&&this._isPlaying&&(this._videoElement.pause(),this._isPlaying=!1,i.info("Video playback paused"))}stop(){this._videoElement&&(this._videoElement.pause(),this._videoElement.currentTime=0,this._isPlaying=!1,i.info("Video playback stopped"))}get isPlaying(){return this._isPlaying&&this._videoElement!==null&&!this._videoElement.paused}get videoWidth(){return this._videoElement?.videoWidth||0}get videoHeight(){return this._videoElement?.videoHeight||0}async captureFrame(){if(!this._videoElement||this._videoElement.readyState<2)return null;try{if("VideoFrame"in window&&typeof window.VideoFrame=="function")try{return new VideoFrame(this._videoElement,{timestamp:this._videoElement.currentTime*1e6})}catch{}const e=await createImageBitmap(this._videoElement),t=new VideoFrame(e,{timestamp:this._videoElement.currentTime*1e6});return e.close(),t}catch(e){return i.error("Failed to capture video frame:",e),null}}onFrame(e){if(!this._videoElement)return;this.offFrame();const t=this._videoElement;if("requestVideoFrameCallback"in t){const s=(n,r)=>{!this._isPlaying||!this._videoElement||this.captureFrame().then(a=>{a&&(e(a),a.close()),this._isPlaying&&this._videoElement&&(this._frameCallbackId=t.requestVideoFrameCallback(s))}).catch(a=>{i.error("Error in frame callback:",a)})};this._frameCallbackId=t.requestVideoFrameCallback(s)}else{const s=()=>{!this._isPlaying||!this._videoElement||this.captureFrame().then(n=>{n&&(e(n),n.close()),this._isPlaying&&this._videoElement&&(this._frameCallbackId=requestAnimationFrame(s))}).catch(n=>{i.error("Error in frame callback:",n)})};this._frameCallbackId=requestAnimationFrame(s)}}offFrame(){this._frameCallbackId!==null&&(this._videoElement&&"cancelVideoFrameCallback"in this._videoElement?this._videoElement.cancelVideoFrameCallback(this._frameCallbackId):cancelAnimationFrame(this._frameCallbackId),this._frameCallbackId=null)}onDispose(){this.stop(),this.offFrame(),this._videoElement&&this._videoElement.parentElement===document.body&&document.body.removeChild(this._videoElement),this._videoElement=null,this._videoUrl=null,i.info("Local Video Debug Source disposed")}}class Ge extends h{constructor(e,t,s){super(),this._outputCanvas=null,this._outputRenderer=null,this._source=new B;const n={...e,renderMode:"processed"};this._pipeline=new H(this._source,n),this._outputRenderer=new D(s,t),this._pipeline.setRenderer(this._outputRenderer),this._outputCanvas=this._outputRenderer.getCanvas(),i.info("Video Pipeline Runner created")}get outputCanvas(){return this._outputCanvas}get processor(){return this._pipeline.strategy.getProcessors()[0]||null}setProcessor(e){this._pipeline.setProcessor(e),i.info("Processor set on pipeline")}async processFrame(e){if(this.ensureNotDisposed(),!this._outputRenderer){i.error("Output renderer not available"),e.close();return}try{const t=this._pipeline.strategy.getProcessors()[0]||null;let s=null;if(t){try{s=t.process(e)}catch(n){i.error("Error processing frame:",n),s=e}if(s===null&&"getImageData"in t){const n=t.getImageData();if(n&&this._outputCanvas&&this._outputRenderer.getContext()){const r=this._outputRenderer.getContext();r&&((this._outputCanvas.width!==n.width||this._outputCanvas.height!==n.height)&&(this._outputCanvas.width=n.width,this._outputCanvas.height=n.height),r.putImageData(n,0,0))}e.close();return}s&&s!==e?(this._outputRenderer.render(s),e.close()):s===e?this._outputRenderer.render(e):e.close()}else this._outputRenderer.render(e)}catch(t){i.error("Error in processFrame:",t),e.close()}}setOutputSize(e,t){this._outputCanvas&&(this._outputCanvas.width=e,this._outputCanvas.height=t,i.info(`Output canvas size set to ${e}x${t}`))}onDispose(){this._pipeline.dispose(),this._outputRenderer&&(this._outputRenderer.dispose(),this._outputRenderer=null),this._outputCanvas&&this._outputCanvas.parentElement===document.body&&document.body.removeChild(this._outputCanvas),this._outputCanvas=null,i.info("Video Pipeline Runner disposed")}}class je extends h{constructor(e,t,s,n){if(super(),this._isRunning=!1,this._videoSource=new F(e,t),this._options={renderMode:"processed",containerElement:t,...n},this._pipelineRunner=new Ge(this._options,t,s),this._options.greenScreen?.enabled){const r=new w(this._options.greenScreen);this._pipelineRunner.setProcessor(r),i.info("Green screen processor enabled in debugger")}i.info("Standalone Video Debugger created")}async switchSource(e,t){this.ensureNotDisposed();const s=this._videoSource,n=this._isRunning,r=new F(e,t);try{await r.load(),n&&await r.play(),r.onFrame(l=>{this._pipelineRunner.processFrame(l).catch(p=>{i.error("Error processing frame:",p)})}),this._videoSource=r;try{s.offFrame(),s.stop(),s.dispose()}catch(l){console.warn("Error disposing old video source during switch:",l)}const a=this._videoSource.videoWidth,c=this._videoSource.videoHeight;a>0&&c>0&&this._pipelineRunner.setOutputSize(a,c)}catch(a){i.error("Failed to switch video source:",a);try{r.dispose()}catch(c){console.warn("Error disposing new video source after failed switch:",c)}throw a}}get outputCanvas(){return this._pipelineRunner.outputCanvas}get videoSource(){return this._videoSource}get processor(){return this._pipelineRunner.processor}setProcessor(e){this._pipelineRunner.setProcessor(e)}updateGreenScreenOptions(e){const t=this._pipelineRunner.processor;if(t&&"updateOptions"in t&&typeof t.updateOptions=="function")t.updateOptions(e),i.info("Green screen options updated");else{const s=this._options.greenScreen||{enabled:!1},n={...s,...e,enabled:e.enabled!==void 0?e.enabled:s.enabled},r=new w(n);this._pipelineRunner.setProcessor(r),this._options.greenScreen=n,i.info("Green screen processor recreated with new options")}}async initialize(){this.ensureNotDisposed();try{await this._videoSource.load();const e=this._videoSource.videoWidth,t=this._videoSource.videoHeight;e>0&&t>0&&this._pipelineRunner.setOutputSize(e,t),i.info("Video debugger initialized")}catch(e){throw i.error("Failed to initialize video debugger:",e),e}}async start(){if(this.ensureNotDisposed(),this._isRunning){i.warn("Debugger is already running");return}try{this._videoSource.videoWidth===0&&await this.initialize(),await this._videoSource.play(),this._videoSource.onFrame(e=>{this._pipelineRunner.processFrame(e).catch(t=>{i.error("Error processing frame:",t)})}),this._isRunning=!0,i.info("Video debugger started")}catch(e){throw i.error("Failed to start video debugger:",e),e}}stop(){this._isRunning&&(this._videoSource.stop(),this._videoSource.offFrame(),this._isRunning=!1,i.info("Video debugger stopped"))}pause(){this._isRunning&&(this._videoSource.pause(),i.info("Video debugger paused"))}async resume(){this._isRunning&&(await this._videoSource.play(),i.info("Video debugger resumed"))}get isRunning(){return this._isRunning}onDispose(){this.stop(),this._videoSource.dispose(),this._pipelineRunner.dispose(),i.info("Standalone Video Debugger disposed")}}exports.DEFAULT_AUDIO_BUFFER_SIZE=ee;exports.DEFAULT_AUDIO_CHANNELS=Z;exports.DEFAULT_AUDIO_SAMPLE_RATE=A;exports.DEFAULT_RECONNECT_ATTEMPTS=S;exports.DEFAULT_RECONNECT_DELAY=y;exports.DEFAULT_WS_TIMEOUT=X;exports.Disposable=h;exports.EventBus=M;exports.Logger=i;exports.SDKClient=z;exports.SDKError=u;exports.SessionState=V;exports.StandaloneVideoDebugger=je;exports.createClient=qe;