@vidtreo/recorder-wc 0.8.4 → 0.8.5

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.
@@ -7742,7 +7742,7 @@ class RecorderWorker {
7742
7742
  }
7743
7743
  }
7744
7744
  new RecorderWorker;
7745
- `],{type:`application/javascript`});return wo=URL.createObjectURL(e),wo}var Eo=class{constructor(){this.worker=null,this.chunks=[],this.totalSize=0,this.isActive=!1,this.videoTrackClone=null,this.audioTrackClone=null,this.isMuted=!1,this.currentVideoTrack=null,this.isPaused=!1,this.readyPromiseResolve=null,this.setupWorker()}setupWorker(){if(typeof Worker>`u`)throw b.error(`[WorkerProcessor] Web Workers are not supported`),Error(`Web Workers are not supported`);try{b.debug(`[WorkerProcessor] Setting up worker`);let e=To();b.debug(`[WorkerProcessor] Worker URL created`,{urlType:typeof e,isBlobUrl:e.startsWith(`blob:`)}),this.worker=new Worker(e,{type:`classic`}),b.debug(`[WorkerProcessor] Worker created successfully`),this.worker.onmessage=this.handleWorkerMessage.bind(this),this.worker.onerror=this.handleWorkerError.bind(this),b.debug(`[WorkerProcessor] Worker event handlers attached`)}catch(e){let t=e instanceof Error?e.message:String(e);throw b.error(`[WorkerProcessor] Failed to create worker:`,e),Error(`Failed to create worker: ${t}`)}}handleWorkerMessage(e){let t=e.data;switch(t.type){case`ready`:b.debug(`[WorkerProcessor] Worker ready`),this.readyPromiseResolve&&=(this.readyPromiseResolve(),null);break;case`error`:b.error(`[WorkerProcessor] Worker error:`,t.error),this.onError&&this.onError(Error(t.error));break;case`chunk`:this.chunks.push({data:t.data,position:t.position}),this.totalSize=Math.max(this.totalSize,t.position+t.data.length);break;case`bufferUpdate`:this.onBufferUpdate&&this.onBufferUpdate(t.size,t.formatted);break;case`stateChange`:b.debug(`[WorkerProcessor] State changed:`,t.state),this.isPaused=t.state===`paused`;break;default:b.warn(`[WorkerProcessor] Unknown response type:`,t)}}handleWorkerError(e){b.error(`[WorkerProcessor] Worker error event:`,{message:e.message,filename:e.filename,lineno:e.lineno,colno:e.colno,error:e.error}),this.onError&&this.onError(Error(e.message||`Unknown worker error`))}async startProcessing(e,t){if(!this.worker)throw Error(`Worker not initialized`);if(this.isActive)throw Error(`Processing already active`);this.isActive=!0,this.isMuted=!1,this.isPaused=!1,this.chunks=[],this.totalSize=0;let n=t.format||`mp4`,r=t.audioCodec||i(n),a=Co(e),o=a?15:t.fps;b.debug(`[WorkerProcessor] Starting processing`,{isScreenCapture:a,targetFps:o,originalFps:t.fps});let s={width:t.width,height:t.height,fps:o,bitrate:t.bitrate,audioCodec:r,audioBitrate:t.audioBitrate,codec:`avc`,keyFrameInterval:5,format:n},c=e.getVideoTracks(),l=e.getAudioTracks();b.debug(`[WorkerProcessor] Preparing to start processing`,{videoTracksCount:c.length,audioTracksCount:l.length,hasWorker:!!this.worker});let u=null,d=null;if(c.length>0){this.stopCurrentVideoTrack();let e=c[0];u=this.cloneVideoTrack(e),this.currentVideoTrack=u}if(l.length>0){let e=l[0];d=this.cloneAudioTrack(e)}b.debug(`[WorkerProcessor] Track details`,{hasVideoTrack:!!u,videoTrackId:u?.id,videoTrackKind:u?.kind,videoTrackReadyState:u?.readyState,hasAudioTrack:!!d,audioTrackId:d?.id,audioTrackKind:d?.kind,audioTrackReadyState:d?.readyState});let f=u===null?null:new MediaStreamTrackProcessor({track:u}).readable,p=d===null?null:new MediaStreamTrackProcessor({track:d}).readable,m={type:`start`,videoStream:f,audioStream:p,config:s},h=[];f&&h.push(f),p&&h.push(p),b.debug(`[WorkerProcessor] Posting message to worker`,{transferablesCount:h.length,messageType:m.type});let g=new Promise(e=>{this.readyPromiseResolve=e});try{this.worker.postMessage(m,h),b.debug(`[WorkerProcessor] Message posted successfully`),await g,b.debug(`[WorkerProcessor] Worker confirmed ready`)}catch(e){throw b.error(`[WorkerProcessor] Failed to post message:`,e),this.readyPromiseResolve=null,e}}pause(){this.worker&&this.isActive&&this.worker.postMessage({type:`pause`})}resume(){this.isWorkerActive()&&this.worker&&this.worker.postMessage({type:`resume`})}isWorkerActive(){return!!(this.worker&&this.isActive)}toggleMute(){this.isMuted=!this.isMuted,this.onMuteStateChange&&this.onMuteStateChange(this.isMuted),this.isWorkerActive()&&this.worker&&this.worker.postMessage({type:`toggleMute`})}switchVideoSource(e){if(!(this.isWorkerActive()&&this.worker))return b.debug(`[WorkerProcessor] Cannot switch source - worker not active`,{hasWorker:!!this.worker,isActive:this.isActive}),Promise.resolve();let t=e.getVideoTracks();if(b.debug(`[WorkerProcessor] Switching video source`,{videoTracksCount:t.length}),t.length===0)return b.warn(`[WorkerProcessor] No video tracks in new stream`),Promise.resolve();let n=Co(e),r=n?15:30;b.debug(`[WorkerProcessor] Source type detected`,{isScreenCapture:n,targetFps:r});let i={type:`updateFps`,fps:r};this.worker.postMessage(i);let a=t[0];this.stopCurrentVideoTrack();let o=this.cloneVideoTrack(a);b.debug(`[WorkerProcessor] New video track details`,{trackId:o.id,trackKind:o.kind,trackReadyState:o.readyState}),this.currentVideoTrack=o;let s={type:`switchSource`,videoStream:new MediaStreamTrackProcessor({track:o}).readable};try{b.debug(`[WorkerProcessor] Posting switch source message`);let e=[];return s.videoStream&&e.push(s.videoStream),this.worker.postMessage(s,e),b.debug(`[WorkerProcessor] Switch source message posted`),new Promise(e=>{setTimeout(()=>{e()},0)})}catch(e){throw b.error(`[WorkerProcessor] Failed to switch source:`,e),e}}finalize(){if(!this.isWorkerActive())throw Error(`Processing not active`);return new Promise((e,t)=>{let n=setTimeout(()=>{t(Error(`Finalize timeout`))},3e4),r=i=>{let a=i.data;a.type===`stateChange`&&a.state===`stopped`?(this.worker&&this.worker.removeEventListener(`message`,r),clearTimeout(n),this.isActive=!1,e(this.createBlobFromChunks())):a.type===`error`&&(this.worker&&this.worker.removeEventListener(`message`,r),clearTimeout(n),t(Error(a.error)))};this.worker&&(this.worker.addEventListener(`message`,r),this.worker.postMessage({type:`stop`}))})}createBlobFromChunks(){let e=[...this.chunks].sort((e,t)=>e.position-t.position),t=new ArrayBuffer(this.totalSize),n=new Uint8Array(t);for(let t of e)n.set(t.data,t.position);return{blob:new Blob([t],{type:`video/mp4`}),totalSize:this.totalSize}}cancel(){return this.worker&&this.isActive&&this.worker.postMessage({type:`stop`}),this.isActive=!1,this.isPaused=!1,this.chunks=[],this.totalSize=0,Promise.resolve()}getBufferSize(){return this.totalSize}getMutedState(){return this.isMuted}isPausedState(){return this.isPaused}getClonedAudioTrack(){return this.audioTrackClone}getAudioStreamForAnalysis(){return this.audioTrackClone?new MediaStream([this.audioTrackClone]):null}setOnBufferUpdate(e){this.onBufferUpdate=e}setOnError(e){this.onError=e}setOnMuteStateChange(e){this.onMuteStateChange=e}cloneVideoTrack(e){if(b.debug(`[WorkerProcessor] Original video track:`,{id:e.id,kind:e.kind,readyState:e.readyState,hasClone:typeof e.clone==`function`}),typeof e.clone==`function`)try{let t=e.clone();return this.videoTrackClone=t,b.debug(`[WorkerProcessor] Video track cloned successfully:`,{id:t.id,kind:t.kind,readyState:t.readyState}),t}catch(e){throw b.error(`[WorkerProcessor] Failed to clone video track:`,e),Error(`Failed to clone video track: ${e instanceof Error?e.message:String(e)}`)}return b.warn(`[WorkerProcessor] Video track clone() not available, using original`),this.videoTrackClone=e,e}cloneAudioTrack(e){if(b.debug(`[WorkerProcessor] Original audio track:`,{id:e.id,kind:e.kind,readyState:e.readyState,hasClone:typeof e.clone==`function`}),typeof e.clone==`function`)try{let t=e.clone();return this.audioTrackClone=t,b.debug(`[WorkerProcessor] Audio track cloned successfully:`,{id:t.id,kind:t.kind,readyState:t.readyState}),t}catch(e){throw b.error(`[WorkerProcessor] Failed to clone audio track:`,e),Error(`Failed to clone audio track: ${e instanceof Error?e.message:String(e)}`)}return b.warn(`[WorkerProcessor] Audio track clone() not available, using original`),this.audioTrackClone=e,e}stopCurrentVideoTrack(){this.currentVideoTrack&&this.currentVideoTrack.readyState===`live`&&this.currentVideoTrack.stop(),this.currentVideoTrack=null}cleanup(){this.worker&&=(this.worker.terminate(),null),wo&&=(URL.revokeObjectURL(wo),null),this.isActive=!1,this.isPaused=!1,this.chunks=[],this.totalSize=0}static isSupported(){return typeof Worker<`u`&&typeof MediaStreamTrackProcessor<`u`&&typeof VideoFrame<`u`&&typeof AudioData<`u`}},Do=class{constructor(){if(this.currentVideoStream=null,!Eo.isSupported())throw Error(`Web Workers are required for video processing. Please use a modern browser that supports Web Workers, MediaStreamTrackProcessor, VideoFrame, and AudioData APIs.`);try{this.workerProcessor=new Eo,b.debug(`[StreamProcessor] Using worker-based processing`)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`Failed to initialize worker: ${t}. Web Workers are required for video processing.`)}}async startProcessing(e,t){this.workerProcessor.setOnBufferUpdate((e,t)=>{b.debug(`[StreamProcessor] Buffer update:`,{size:e,formatted:t})}),this.workerProcessor.setOnError(e=>{b.error(`[StreamProcessor] Worker error:`,e)}),this.currentVideoStream=e,await this.workerProcessor.startProcessing(e,t)}pause(){this.workerProcessor.pause()}resume(){this.workerProcessor.resume()}isPausedState(){return this.workerProcessor.isPausedState()}async finalize(){return b.debug(`[StreamProcessor] finalize called`),await this.workerProcessor.finalize()}toggleMute(){this.workerProcessor.toggleMute()}isMutedState(){return this.workerProcessor.getMutedState()}getClonedAudioTrack(){return this.workerProcessor.getClonedAudioTrack()}getAudioStreamForAnalysis(){return this.workerProcessor.getAudioStreamForAnalysis()}async switchVideoSource(e){await this.workerProcessor.switchVideoSource(e),this.currentVideoStream=e,this.onSourceChange&&this.onSourceChange(e)}getCurrentVideoSource(){return this.currentVideoStream}getBufferSize(){return this.workerProcessor.getBufferSize()}setOnMuteStateChange(e){this.workerProcessor.setOnMuteStateChange(e)}setOnSourceChange(e){this.onSourceChange=e}async cancel(){await this.workerProcessor.cancel(),this.workerProcessor.cleanup(),this.currentVideoStream=null}};let Oo=1e3,ko=`recording`,Ao=`idle`;var jo=class{constructor(e,t){this.recordingState=Ao,this.countdownDuration=5e3,this.countdownRemaining=0,this.countdownTimeoutId=null,this.countdownIntervalId=null,this.countdownStartTime=null,this.isPaused=!1,this.maxRecordingTime=null,this.maxTimeTimer=null,this.recordingSeconds=0,this.recordingIntervalId=null,this.pauseStartTime=null,this.totalPausedTime=0,this.streamProcessor=null,this.originalCameraStream=null,this.streamManager=e,this.callbacks=t}setCountdownDuration(e){this.countdownDuration=e}setMaxRecordingTime(e){this.maxRecordingTime=e}getRecordingState(){return this.recordingState}isPausedState(){return this.isPaused}getRecordingSeconds(){return this.recordingSeconds}getStreamProcessor(){return this.streamProcessor}setOriginalCameraStream(e){this.originalCameraStream=e}getOriginalCameraStream(){return this.originalCameraStream}async startRecording(){try{this.callbacks.onClearUploadStatus(),this.countdownDuration>0?this.startCountdown():await this.doStartRecording()}catch(e){this.handleError(e),this.recordingState=Ao,this.cancelCountdown()}}startCountdown(){this.recordingState=`countdown`,this.countdownRemaining=Math.ceil(this.countdownDuration/Oo),this.countdownStartTime=Date.now(),this.callbacks.onCountdownUpdate(this.recordingState,this.countdownRemaining),this.countdownIntervalId=window.setInterval(()=>{if(!this.countdownStartTime)return;let e=Date.now()-this.countdownStartTime;this.countdownRemaining=Math.max(0,Math.ceil((this.countdownDuration-e)/Oo)),this.callbacks.onCountdownUpdate(this.recordingState,this.countdownRemaining)},100),this.countdownTimeoutId=window.setTimeout(async()=>{await this.doStartRecording().catch(()=>{})},this.countdownDuration)}async doStartRecording(){b.debug(`[RecordingManager] doStartRecording called`),this.cancelCountdown(),this.recordingState=ko,this.callbacks.onStateChange(this.recordingState),this.resetRecordingState();let e=this.streamManager.getStream();if(b.debug(`[RecordingManager] Current stream:`,{hasStream:!!e,audioTracks:e?.getAudioTracks().length||0,videoTracks:e?.getVideoTracks().length||0}),!e){b.warn(`[RecordingManager] No stream available`),this.handleError(Error(`No stream available for recording`)),this.recordingState=Ao,this.callbacks.onStateChange(this.recordingState);return}this.originalCameraStream=e,b.debug(`[RecordingManager] Creating new StreamProcessor`),this.streamProcessor=new Do,b.debug(`[RecordingManager] StreamProcessor created:`,!!this.streamProcessor);let t=await this.callbacks.onGetConfig().then(e=>({config:e,error:null})).catch(e=>({config:null,error:e}));if(t.error){this.handleError(t.error),this.recordingState=Ao,this.callbacks.onStateChange(this.recordingState);return}if(!t.config){this.handleError(Error(`Failed to get recording config`)),this.recordingState=Ao,this.callbacks.onStateChange(this.recordingState);return}b.debug(`[RecordingManager] Starting recording with stream manager`);let n=await this.streamManager.startRecording(this.streamProcessor,t.config).then(()=>(b.info(`[RecordingManager] Recording started successfully`),null)).catch(e=>(b.error(`[RecordingManager] Error starting recording:`,e),e));if(n){this.handleError(n),this.recordingState=Ao,this.callbacks.onStateChange(this.recordingState);return}this.startRecordingTimer(),this.maxRecordingTime&&this.maxRecordingTime>0&&(this.maxTimeTimer=window.setTimeout(async()=>{this.recordingState===ko&&await this.stopRecording()},this.maxRecordingTime))}async stopRecording(){b.debug(`[RecordingManager] stopRecording called`);try{this.cancelCountdown(),this.clearTimer(this.recordingIntervalId,clearInterval),this.recordingIntervalId=null,this.clearTimer(this.maxTimeTimer,clearTimeout),this.maxTimeTimer=null,this.resetPauseState(),this.callbacks.onStopAudioTracking(),b.debug(`[RecordingManager] Stopping recording in stream manager`);let e=await this.streamManager.stopRecording();return b.info(`[RecordingManager] Recording stopped, blob size:`,e.size),this.recordingState=Ao,this.callbacks.onStateChange(this.recordingState),this.recordingSeconds=0,this.streamProcessor=null,this.callbacks.onRecordingComplete(e),e}catch(e){throw this.handleError(e),this.recordingState=Ao,this.callbacks.onStateChange(this.recordingState),e}}pauseRecording(){this.recordingState!==ko||this.isPaused||(this.streamManager.pauseRecording(),this.isPaused=!0,this.clearTimer(this.recordingIntervalId,clearInterval),this.recordingIntervalId=null,this.pauseStartTime=Date.now())}resumeRecording(){this.recordingState!==ko||!this.isPaused||(this.streamManager.resumeRecording(),this.isPaused=!1,this.updatePausedDuration(),this.startRecordingTimer())}cancelCountdown(){this.clearTimer(this.countdownTimeoutId,clearTimeout),this.countdownTimeoutId=null,this.clearTimer(this.countdownIntervalId,clearInterval),this.countdownIntervalId=null,this.recordingState=Ao,this.countdownRemaining=0,this.countdownStartTime=null,this.callbacks.onCountdownUpdate(this.recordingState,this.countdownRemaining)}cleanup(){this.cancelCountdown(),this.clearTimer(this.recordingIntervalId,clearInterval),this.recordingIntervalId=null,this.clearTimer(this.maxTimeTimer,clearTimeout),this.maxTimeTimer=null}resetRecordingState(){this.isPaused=!1,this.recordingSeconds=0,this.totalPausedTime=0,this.pauseStartTime=null}resetPauseState(){this.isPaused=!1,this.pauseStartTime=null,this.totalPausedTime=0}updatePausedDuration(){if(this.pauseStartTime===null)throw Error(`Pause start time not set`);let e=Date.now()-this.pauseStartTime;this.totalPausedTime+=e,this.pauseStartTime=null}startRecordingTimer(){this.recordingIntervalId===null&&(this.recordingIntervalId=window.setInterval(()=>{this.recordingSeconds+=1,this.callbacks.onTimerUpdate(me(this.recordingSeconds))},1e3))}clearTimer(e,t){e!==null&&t(e)}handleError(e){let n=e instanceof Error?e:Error(t(e));this.callbacks.onError(n)}};let Mo=()=>{},No=()=>{},Po=()=>{},Fo=()=>{},Io=e=>{},Lo=(e,t)=>{},Ro=e=>{},zo=e=>{},Bo=e=>{},Vo=()=>{},Ho=e=>{};function Uo(){return{onProgress:Mo,onSuccess:No,onError:Po,onClearStatus:Fo}}var Wo=class{constructor(e={}){this.uploadService=null,this.uploadQueueManager=null,this.isInitialized=!1,this.callbacks=e,this.streamManager=new ye,this.configManager=new p,this.storageManager=new y,this.deviceManager=new m(this.streamManager,e.device),this.audioLevelAnalyzer=new n,this.uploadService=new xe,this.uploadCallbacks=e.upload?e.upload:Uo();let t=this.createRecordingCallbacks(e);this.recordingManager=new jo(this.streamManager,t);let r=this.createSourceSwitchCallbacks(e);this.sourceSwitchManager=new se(this.streamManager,r),e.stream&&(this.streamManager.on(`streamstart`,({stream:t})=>{b.debug(`[RecorderController] streamstart event received, calling callback`),e.stream?.onStreamStart&&e.stream.onStreamStart(t)}),this.streamManager.on(`streamstop`,()=>{b.debug(`[RecorderController] streamstop event received, calling callback`),e.stream?.onStreamStop&&e.stream.onStreamStop()}),this.streamManager.on(`error`,({error:t})=>{b.error(`[RecorderController] stream error event received, calling callback`,t),e.stream?.onError&&e.stream.onError(t)}))}async initialize(e){if(this.isInitialized)return;e.apiKey&&e.backendUrl&&await this.configManager.initialize(e.apiKey,e.backendUrl),e.countdownDuration!==void 0&&this.recordingManager.setCountdownDuration(e.countdownDuration),e.maxRecordingTime!==void 0&&this.recordingManager.setMaxRecordingTime(e.maxRecordingTime);let t=this.callbacks.onStorageCleanupError??Ho;await this.storageManager.initialize(t);let n=this.storageManager.getStorageService();n&&this.uploadService&&(this.uploadQueueManager=new be(n,this.uploadService),this.uploadQueueManager.setCallbacks({onUploadProgress:(e,t)=>{this.uploadCallbacks.onProgress(t)},onUploadComplete:(e,t)=>{this.uploadCallbacks.onSuccess(t)},onUploadError:(e,t)=>{this.uploadCallbacks.onError(t)}})),this.isInitialized=!0}async startStream(){b.debug(`[RecorderController] startStream called`),await this.streamManager.startStream(),b.debug(`[RecorderController] startStream completed`)}async stopStream(){await this.streamManager.stopStream()}switchVideoDevice(e){return this.streamManager.switchVideoDevice(e)}switchAudioDevice(e){return this.streamManager.switchAudioDevice(e)}async startRecording(){await this.recordingManager.startRecording()}async stopRecording(){let e=await this.recordingManager.stopRecording();return await this.sourceSwitchManager.handleRecordingStop().catch(()=>{throw Error(`Source switch cleanup failed`)}),e}pauseRecording(){this.recordingManager.pauseRecording()}resumeRecording(){this.recordingManager.resumeRecording()}async switchSource(e){await this.sourceSwitchManager.toggleSource()}setCameraDevice(e){this.deviceManager.setCameraDevice(e)}setMicDevice(e){this.deviceManager.setMicDevice(e)}getAvailableDevices(){return this.deviceManager.getAvailableDevices()}muteAudio(){this.streamManager.muteAudio()}unmuteAudio(){this.streamManager.unmuteAudio()}toggleMute(){this.streamManager.toggleMute()}getIsMuted(){return this.streamManager.isMuted()}startAudioLevelTracking(e,t){if(!t)throw Error(`Audio level callbacks are required`);return this.audioLevelAnalyzer.startTracking(e,t,()=>this.streamManager.isMuted()),Promise.resolve()}stopAudioLevelTracking(){this.audioLevelAnalyzer.stopTracking()}getAudioLevel(){return this.audioLevelAnalyzer.getAudioLevel()}async uploadVideo(e,t,n,r){if(!this.uploadQueueManager)throw Error(`Upload queue manager not initialized`);this.uploadCallbacks.onClearStatus();let i=await xo(e),a=Object.keys(r).length>0?r:void 0;await this.uploadQueueManager.queueUpload({blob:e,apiKey:t,backendUrl:n,filename:`recording-${Date.now()}.mp4`,duration:i,metadata:void 0,userMetadata:a})}getStream(){return this.streamManager.getStream()}getRecordingState(){return this.recordingManager.getRecordingState()}isPaused(){return this.recordingManager.isPausedState()}getCurrentSourceType(){return this.sourceSwitchManager.getCurrentSourceType()}getOriginalCameraStream(){return this.sourceSwitchManager.getOriginalCameraStream()}getStreamManager(){return this.streamManager}getAudioStreamForAnalysis(){return this.streamManager.getAudioStreamForAnalysis()}getDeviceManager(){return this.deviceManager}getConfig(){return this.configManager.getConfig()}getUploadService(){return this.uploadService}isRecording(){return this.streamManager.isRecording()}isActive(){return this.streamManager.isActive()}cleanup(){this.storageManager.destroy(),this.recordingManager.cleanup(),this.audioLevelAnalyzer.stopTracking(),this.sourceSwitchManager.cleanup()}createRecordingCallbacks(e){let t=e.recording;return{onStateChange:t?.onStateChange??Io,onCountdownUpdate:t?.onCountdownUpdate??Lo,onTimerUpdate:t?.onTimerUpdate??Ro,onError:t?.onError??zo,onRecordingComplete:t?.onRecordingComplete??Bo,onClearUploadStatus:t?.onClearUploadStatus??Vo,onStopAudioTracking:()=>{this.audioLevelAnalyzer.stopTracking()},onGetConfig:()=>this.configManager.getConfig()}}createSourceSwitchCallbacks(e){let t=e.sourceSwitch;return{onSourceChange:t?.onSourceChange,onPreviewUpdate:t?.onPreviewUpdate,onError:t?.onError,onTransitionStart:t?.onTransitionStart,onTransitionEnd:t?.onTransitionEnd,getSelectedCameraDeviceId:()=>this.deviceManager.getSelectedCameraDeviceId(),getSelectedMicDeviceId:()=>this.deviceManager.getSelectedMicDeviceId()}}};function Go(e){if(typeof e==`string`)return new Ir(e);if(e instanceof Blob)return new Pr(e);throw Error(`Invalid input type. Expected Blob, File, or file path string.`)}function Ko(e){switch(e){case`mp4`:return new Ba;case`webm`:case`mkv`:case`mov`:throw Error(`Format ${e} is not yet supported. Only MP4 is currently supported.`);default:throw Error(`Unsupported output format: ${e}`)}}function qo(e){switch(e){case`mp4`:return`video/mp4`;case`webm`:return`video/webm`;case`mkv`:return`video/x-matroska`;case`mov`:return`video/quicktime`;default:throw Error(`Unsupported output format: ${e}`)}}function Jo(e){let t=a(e.format,e.audioCodec);return{video:{width:e.width,height:e.height,fit:`contain`,frameRate:e.fps,bitrate:e.bitrate,forceTranscode:!0},audio:{codec:t,forceTranscode:!0}}}function Yo(e){if(!e.isValid){let t=e.discardedTracks.map(e=>e.reason).join(`, `);throw Error(`Conversion is invalid. Discarded tracks: ${t}`)}}async function Xo(e,t={},n){let r={...o,...t,format:t.format||o.format};r.audioCodec||=i(r.format);let a=Go(e),s=new Br({formats:[Ar],source:a}),c=new mo({format:Ko(r.format),target:new Na}),l=await vo.init({input:s,output:c,...Jo(r)});Yo(l),n&&(l.onProgress=n),await l.execute();let u=c.target.buffer;if(!u)throw Error(`Transcoding completed but no output buffer was generated`);let d=qo(r.format);return{buffer:u,blob:new Blob([u],{type:d})}}function Zo(e){if(e<.25){let t=e/.25;return`rgb(255, ${Math.round(165+50*t)}, 0)`}if(e<.5){let t=(e-.25)/.25;return`rgb(${Math.round(255- -205*t)}, ${Math.round(215+-10*t)}, ${Math.round(0+50*t)})`}if(e<.75){let t=(e-.5)/.25;return`rgb(${Math.round(50- -50*t)}, ${Math.round(205+-77*t)}, ${Math.round(50+78*t)})`}let t=(e-.75)/.25;return`rgb(0, ${Math.round(128- -28*t)}, ${Math.round(128+72*t)})`}function Qo(e,t){let n=e.querySelector(t);if(!n)throw Error(`Element not found: ${t}`);return n}async function $o(e,n,r){e.pause(),e.srcObject=null,e.load(),r===`screen`?e.classList.add(`screen-share`):e.classList.remove(`screen-share`),await new Promise(e=>{setTimeout(()=>e(),100)}),e.srcObject=n,await new Promise((n,r)=>{let i=setTimeout(()=>{a||(a=!0,o(),r(Error(`Timeout waiting for video to load`)))},1e4),a=!1,o=()=>{a||!e||(e.removeEventListener(`loadedmetadata`,f),e.removeEventListener(`loadeddata`,p),e.removeEventListener(`canplay`,m),e.removeEventListener(`playing`,h),e.removeEventListener(`error`,g))},s=()=>{a||(a=!0,clearTimeout(i),o(),n())},c=e=>{a||(a=!0,clearTimeout(i),o(),r(Error(`Failed to play preview video: ${e}`)))},l=async()=>{if(!(a||!e))try{await e.play(),s()}catch(e){c(`Failed to play preview video: ${t(e)}`)}},u=n=>{if(a||!e)return;let r=t(n);r.includes(`interrupted`)||r.includes(`abort`)?setTimeout(l,200):c(r)},d=async()=>{if(!(a||!e))try{await e.play(),s()}catch(e){u(e)}},f=()=>{a||!e||d()},p=()=>{a||!e||e.readyState>=2&&d()},m=()=>{a||!e||e.readyState>=3&&d()},h=()=>{a||!e||(a=!0,clearTimeout(i),o(),n())},g=e=>{if(a)return;a=!0,clearTimeout(i),o();let n=e instanceof ErrorEvent?e.error:Error(`Video element error`);r(Error(`Failed to load preview: ${t(n)}`))};if(e.readyState>=1){d();return}e.addEventListener(`loadedmetadata`,f,{once:!0}),e.addEventListener(`loadeddata`,p,{once:!0}),e.addEventListener(`canplay`,m,{once:!0}),e.addEventListener(`playing`,h,{once:!0}),e.addEventListener(`error`,g,{once:!0}),setTimeout(()=>{!a&&e&&e.readyState>=1&&d()},500)})}async function es(e,t){e.pause(),e.srcObject=t,await new Promise(t=>{let n=()=>{e.removeEventListener(`loadedmetadata`,n),t()};e.addEventListener(`loadedmetadata`,n),e.load(),setTimeout(()=>t(),500)});try{await e.play()}catch(e){let t=e instanceof Error?e.message:String(e);if(!(t.includes(`abort`)||t.includes(`interrupted`)))throw Error(`Failed to play preview after device switch: ${t}`)}}function ts(e){return{recording:{onStateChange:()=>{},onCountdownUpdate:(t,n)=>{e.getUIStateManager().updateCountdownOverlay(t,n)},onTimerUpdate:t=>{e.getUIStateManager().updateRecordingTimer(t)},onError:t=>{e.getUIStateManager().showError(t.message)},onRecordingComplete:e=>{},onClearUploadStatus:()=>{e.getUIStateManager().clearUploadStatus()},onStopAudioTracking:()=>{},onGetConfig:async()=>({format:`mp4`,fps:30,width:1280,height:720,bitrate:25e5,audioCodec:`aac`,preset:`medium`,packetCount:0,audioBitrate:128e3})},upload:{onProgress:t=>{e.getUIStateManager().showUploadProgress(),e.getUIStateManager().updateUploadProgress(t)},onSuccess:t=>{e.getUIStateManager().hideUploadProgress(),e.getUIStateManager().showUploadSuccess(t)},onError:t=>{e.getUIStateManager().hideUploadProgress(),e.getUIStateManager().showUploadError(t.message)},onClearStatus:()=>{e.getUIStateManager().clearUploadStatus()}},sourceSwitch:{onSourceChange:async t=>{e.getUIStateManager().updateSwitchButtonText(t);let n=e.getController();if(t===`camera`){let t=n.getStream();if(!t||t.getAudioTracks().length===0)return;n.stopAudioLevelTracking(),await n.startAudioLevelTracking(t,{onLevelUpdate:(t,n)=>{e.getAudioLevelVisualizer().updateBars(t,n)}}).catch(()=>{})}},onPreviewUpdate:async t=>{let n=e.getController(),r=n.getCurrentSourceType();if(r===`screen`){let t=n.getAudioStreamForAnalysis();if(!t||t.getAudioTracks().length===0)return;n.stopAudioLevelTracking(),await n.startAudioLevelTracking(t,{onLevelUpdate:(t,n)=>{e.getAudioLevelVisualizer().updateBars(t,n)}}).catch(()=>{})}else t.getAudioTracks().length>0&&(n.stopAudioLevelTracking(),await n.startAudioLevelTracking(t,{onLevelUpdate:(t,n)=>{e.getAudioLevelVisualizer().updateBars(t,n)}}));await $o(Qo(e.getShadowRoot(),`#videoPreview`),t,r)},onError:n=>{e.getUIStateManager().showError(t(n))},onTransitionStart:t=>{e.getUIStateManager().showSourceTransition(t)},onTransitionEnd:()=>{e.getUIStateManager().hideSourceTransition()}},storage:{onUploadProgress:()=>{},onUploadComplete:()=>{e.checkPendingUploads()},onUploadError:()=>{e.checkPendingUploads()}},onStorageCleanupError:t=>{e.getUIStateManager().showError(t)}}}function ns(e,t){let n=e.querySelector(`#previewSkeleton`),r=e.querySelector(`.skeleton-text`);if(!n)throw Error(`Preview skeleton element not found`);if(n.style.display=`flex`,!r)throw Error(`Skeleton text element not found`);r.textContent=t}function rs(e){let t=e.querySelector(`#previewSkeleton`);if(!t)throw Error(`Preview skeleton element not found`);t.style.display=`none`}async function is(e,n){let r=n===`default`?null:n;if(e.getController().setCameraDevice(r),e.getDeviceManager().setCameraDevice(r),!(!e.getController().isActive()||e.getController().isRecording())){ns(e.getShadowRoot(),e.getI18nManager().t(`switchingCamera`));try{let t=await e.getController().switchVideoDevice(r);await es(Qo(e.getShadowRoot(),`#videoPreview`),t),rs(e.getShadowRoot())}catch(n){rs(e.getShadowRoot()),e.showError(t(n));let r=e.getDeviceManager().getSelectedCameraDeviceId(),i=e.getShadowRoot().querySelector(`#cameraSelect`);if(!i)throw Error(`Camera select element not found`);if(!r)throw Error(`Camera device ID is required`);i.value=r}}}async function as(e,n){let r=n===`default`?null:n;if(e.getController().setMicDevice(r),e.getDeviceManager().setMicDevice(r),!(!e.getController().isActive()||e.getController().isRecording())){ns(e.getShadowRoot(),e.getI18nManager().t(`switchingMicrophone`));try{await e.getController().switchAudioDevice(r);let t=e.getController().getStream();if(!t)throw Error(`Stream is required`);e.getController().stopAudioLevelTracking(),await e.getController().startAudioLevelTracking(t,{onLevelUpdate:(t,n)=>{e.getAudioLevelVisualizer().updateBars(t,n)}}),setTimeout(()=>{rs(e.getShadowRoot())},200)}catch(n){rs(e.getShadowRoot()),e.showError(t(n));let r=e.getDeviceManager().getSelectedMicDeviceId(),i=e.getShadowRoot().querySelector(`#micSelect`);if(!i)throw Error(`Microphone select element not found`);if(!r)throw Error(`Microphone device ID is required`);i.value=r}}}function os(e){let t=e.getStreamManager();t.on(`statechange`,({state:t,previousState:n})=>{e.handleStateChange(t,n)}),t.on(`streamstart`,({stream:t})=>{e.handleStreamStart(t)}),t.on(`streamstop`,()=>{e.handleStreamStop()}),t.on(`recordingstart`,()=>{e.handleRecordingStart()}),t.on(`recordingstop`,({blob:t})=>{e.handleRecordingStop(t).catch(t=>{e.showError(e.extractErrorMessage(t))})}),t.on(`recordingtimeupdate`,({formatted:t})=>{e.updateRecordingTimer(t)}),t.on(`recordingbufferupdate`,()=>{}),t.on(`audiomutetoggle`,({muted:t})=>{e.updateMuteState(t)}),t.on(`videosourcechange`,({stream:t})=>{e.updateVideoPreview(t)}),t.on(`error`,({error:t})=>{e.showError(t.message)})}async function ss(e){if(e.getShowSettings()){e.setShowSettings(!1);let t=e.getShadowRoot().querySelector(`#settingsPanel`);if(!t)throw Error(`Settings panel element not found`);t.style.display=`none`}await e.getController().startRecording()}async function cs(e){let t=await e.getController().stopRecording();return e.setProcessedBlob(t),e.setRecordedBlob(t),e.getUIStateManager().updateRecordingControlsAfterStop(),await fs(e,t),t}function ls(e){e.getController().pauseRecording(),e.getUIStateManager().updatePauseState(e.getController().isPaused())}function us(e){e.getController().resumeRecording(),e.getUIStateManager().updatePauseState(e.getController().isPaused())}async function ds(e){let n=e.getRecordedBlob();if(!n)throw Error(`No recording available`);e.setIsProcessing(!0);let r=Qo(e.getShadowRoot(),`#processButton`);r.disabled=!0,e.getUIStateManager().hideError(),e.getUIStateManager().showProgress(),e.getUIStateManager().updateProgress(0,`Starting transcoding...`);try{let t=await Xo(n,await e.getController().getConfig(),t=>{e.getUIStateManager().updateProgress(t,`Transcoding... ${Math.round(t*100)}%`)});e.setProcessedBlob(t.blob),e.getUIStateManager().updateProgress(1,`Complete!`),setTimeout(()=>{e.getUIStateManager().hideProgress(),r.disabled=!1,e.setIsProcessing(!1)},500)}catch(n){e.getUIStateManager().hideProgress(),e.getUIStateManager().showError(t(n)),r.disabled=!1,e.setIsProcessing(!1)}}async function fs(e,t){let n=e.getAttribute(`api-key`),r=e.getNormalizedBackendUrl(e.getAttribute(`backend-url`));n&&await e.getController().uploadVideo(t,n,r,e.getUserMetadata())}function ps(e){let t=e.getShadowRoot(),n=t.querySelector(`#startCameraButton`),r=t.querySelector(`#startButton`),i=t.querySelector(`#stopButton`),a=t.querySelector(`#processButton`),o=t.querySelector(`#muteButton`),s=t.querySelector(`#switchSourceButton`),c=t.querySelector(`#settingsButton`),l=t.querySelector(`#pauseButton`),u=t.querySelector(`#resumeButton`),d=t.querySelector(`#cameraSelect`),f=t.querySelector(`#micSelect`);if(!(n&&r&&i&&a&&o&&s))throw Error(`Required UI elements not found`);n.addEventListener(`click`,()=>{e.startCamera().catch(t=>{e.showError(e.extractErrorMessage(t))})}),r.addEventListener(`click`,()=>{e.startRecording().catch(t=>{e.showError(e.extractErrorMessage(t))})}),i.addEventListener(`click`,()=>{e.stopRecording().catch(t=>{e.showError(e.extractErrorMessage(t))})}),a&&(a.style.display=`none`,a.addEventListener(`click`,()=>{e.processVideo().catch(t=>{e.showError(e.extractErrorMessage(t))})})),o.addEventListener(`click`,()=>{e.toggleMute()}),s.addEventListener(`click`,()=>{e.toggleSource().catch(t=>{e.showError(e.extractErrorMessage(t))})}),c&&c.addEventListener(`click`,()=>{e.toggleSettings()}),l&&l.addEventListener(`click`,()=>{e.pauseRecording()}),u&&u.addEventListener(`click`,()=>{e.resumeRecording()}),d&&d.addEventListener(`change`,t=>{let n=t.target;e.handleCameraChange(n.value).catch(t=>{e.showError(e.extractErrorMessage(t))})}),f&&f.addEventListener(`change`,t=>{let n=t.target;e.handleMicChange(n.value).catch(t=>{e.showError(e.extractErrorMessage(t))})})}let ms=/[:.]/g;function hs(e){let t=URL.createObjectURL(e),n=document.createElement(`a`),r=new Date().toISOString().replace(ms,`-`).slice(0,-5);n.href=t,n.download=`vidtreo-recording-${r}.mp4`,document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(t)}function gs(e){let t=URL.createObjectURL(e),n=window.open();if(!n)throw Error(`Failed to open video player window`);n.document.write(`
7745
+ `],{type:`application/javascript`});return wo=URL.createObjectURL(e),wo}var Eo=class{constructor(){this.worker=null,this.chunks=[],this.totalSize=0,this.isActive=!1,this.videoTrackClone=null,this.audioTrackClone=null,this.isMuted=!1,this.currentVideoTrack=null,this.isPaused=!1,this.readyPromiseResolve=null,this.setupWorker()}setupWorker(){if(typeof Worker>`u`)throw b.error(`[WorkerProcessor] Web Workers are not supported`),Error(`Web Workers are not supported`);try{b.debug(`[WorkerProcessor] Setting up worker`);let e=To();b.debug(`[WorkerProcessor] Worker URL created`,{urlType:typeof e,isBlobUrl:e.startsWith(`blob:`)}),this.worker=new Worker(e,{type:`classic`}),b.debug(`[WorkerProcessor] Worker created successfully`),this.worker.onmessage=this.handleWorkerMessage.bind(this),this.worker.onerror=this.handleWorkerError.bind(this),b.debug(`[WorkerProcessor] Worker event handlers attached`)}catch(e){let t=e instanceof Error?e.message:String(e);throw b.error(`[WorkerProcessor] Failed to create worker:`,e),Error(`Failed to create worker: ${t}`)}}handleWorkerMessage(e){let t=e.data;switch(t.type){case`ready`:b.debug(`[WorkerProcessor] Worker ready`),this.readyPromiseResolve&&=(this.readyPromiseResolve(),null);break;case`error`:b.error(`[WorkerProcessor] Worker error:`,t.error),this.onError&&this.onError(Error(t.error));break;case`chunk`:this.chunks.push({data:t.data,position:t.position}),this.totalSize=Math.max(this.totalSize,t.position+t.data.length);break;case`bufferUpdate`:this.onBufferUpdate&&this.onBufferUpdate(t.size,t.formatted);break;case`stateChange`:b.debug(`[WorkerProcessor] State changed:`,t.state),this.isPaused=t.state===`paused`;break;default:b.warn(`[WorkerProcessor] Unknown response type:`,t)}}handleWorkerError(e){b.error(`[WorkerProcessor] Worker error event:`,{message:e.message,filename:e.filename,lineno:e.lineno,colno:e.colno,error:e.error}),this.onError&&this.onError(Error(e.message||`Unknown worker error`))}async startProcessing(e,t){if(!this.worker)throw Error(`Worker not initialized`);if(this.isActive)throw Error(`Processing already active`);this.isActive=!0,this.isMuted=!1,this.isPaused=!1,this.chunks=[],this.totalSize=0;let n=t.format||`mp4`,r=t.audioCodec||i(n),a=Co(e),o=a?15:t.fps;b.debug(`[WorkerProcessor] Starting processing`,{isScreenCapture:a,targetFps:o,originalFps:t.fps});let s={width:t.width,height:t.height,fps:o,bitrate:t.bitrate,audioCodec:r,audioBitrate:t.audioBitrate,codec:`avc`,keyFrameInterval:5,format:n},c=e.getVideoTracks(),l=e.getAudioTracks();b.debug(`[WorkerProcessor] Preparing to start processing`,{videoTracksCount:c.length,audioTracksCount:l.length,hasWorker:!!this.worker});let u=null,d=null;if(c.length>0){this.stopCurrentVideoTrack();let e=c[0];u=this.cloneVideoTrack(e),this.currentVideoTrack=u}if(l.length>0){let e=l[0];d=this.cloneAudioTrack(e)}b.debug(`[WorkerProcessor] Track details`,{hasVideoTrack:!!u,videoTrackId:u?.id,videoTrackKind:u?.kind,videoTrackReadyState:u?.readyState,hasAudioTrack:!!d,audioTrackId:d?.id,audioTrackKind:d?.kind,audioTrackReadyState:d?.readyState});let f=u===null?null:new MediaStreamTrackProcessor({track:u}).readable,p=d===null?null:new MediaStreamTrackProcessor({track:d}).readable,m={type:`start`,videoStream:f,audioStream:p,config:s},h=[];f&&h.push(f),p&&h.push(p),b.debug(`[WorkerProcessor] Posting message to worker`,{transferablesCount:h.length,messageType:m.type});let g=new Promise(e=>{this.readyPromiseResolve=e});try{this.worker.postMessage(m,h),b.debug(`[WorkerProcessor] Message posted successfully`),await g,b.debug(`[WorkerProcessor] Worker confirmed ready`)}catch(e){throw b.error(`[WorkerProcessor] Failed to post message:`,e),this.readyPromiseResolve=null,e}}pause(){this.worker&&this.isActive&&this.worker.postMessage({type:`pause`})}resume(){this.isWorkerActive()&&this.worker&&this.worker.postMessage({type:`resume`})}isWorkerActive(){return!!(this.worker&&this.isActive)}toggleMute(){this.isMuted=!this.isMuted,this.onMuteStateChange&&this.onMuteStateChange(this.isMuted),this.isWorkerActive()&&this.worker&&this.worker.postMessage({type:`toggleMute`})}switchVideoSource(e){if(!(this.isWorkerActive()&&this.worker))return b.debug(`[WorkerProcessor] Cannot switch source - worker not active`,{hasWorker:!!this.worker,isActive:this.isActive}),Promise.resolve();let t=e.getVideoTracks();if(b.debug(`[WorkerProcessor] Switching video source`,{videoTracksCount:t.length}),t.length===0)return b.warn(`[WorkerProcessor] No video tracks in new stream`),Promise.resolve();let n=Co(e),r=n?15:30;b.debug(`[WorkerProcessor] Source type detected`,{isScreenCapture:n,targetFps:r});let i={type:`updateFps`,fps:r};this.worker.postMessage(i);let a=t[0];this.stopCurrentVideoTrack();let o=this.cloneVideoTrack(a);b.debug(`[WorkerProcessor] New video track details`,{trackId:o.id,trackKind:o.kind,trackReadyState:o.readyState}),this.currentVideoTrack=o;let s={type:`switchSource`,videoStream:new MediaStreamTrackProcessor({track:o}).readable};try{b.debug(`[WorkerProcessor] Posting switch source message`);let e=[];return s.videoStream&&e.push(s.videoStream),this.worker.postMessage(s,e),b.debug(`[WorkerProcessor] Switch source message posted`),new Promise(e=>{setTimeout(()=>{e()},0)})}catch(e){throw b.error(`[WorkerProcessor] Failed to switch source:`,e),e}}finalize(){if(!this.isWorkerActive())throw Error(`Processing not active`);return new Promise((e,t)=>{let n=setTimeout(()=>{t(Error(`Finalize timeout`))},3e4),r=i=>{let a=i.data;a.type===`stateChange`&&a.state===`stopped`?(this.worker&&this.worker.removeEventListener(`message`,r),clearTimeout(n),this.isActive=!1,e(this.createBlobFromChunks())):a.type===`error`&&(this.worker&&this.worker.removeEventListener(`message`,r),clearTimeout(n),t(Error(a.error)))};this.worker&&(this.worker.addEventListener(`message`,r),this.worker.postMessage({type:`stop`}))})}createBlobFromChunks(){let e=[...this.chunks].sort((e,t)=>e.position-t.position),t=new ArrayBuffer(this.totalSize),n=new Uint8Array(t);for(let t of e)n.set(t.data,t.position);return{blob:new Blob([t],{type:`video/mp4`}),totalSize:this.totalSize}}cancel(){return this.worker&&this.isActive&&this.worker.postMessage({type:`stop`}),this.isActive=!1,this.isPaused=!1,this.chunks=[],this.totalSize=0,Promise.resolve()}getBufferSize(){return this.totalSize}getMutedState(){return this.isMuted}isPausedState(){return this.isPaused}getClonedAudioTrack(){return this.audioTrackClone}getAudioStreamForAnalysis(){return this.audioTrackClone?new MediaStream([this.audioTrackClone]):null}setOnBufferUpdate(e){this.onBufferUpdate=e}setOnError(e){this.onError=e}setOnMuteStateChange(e){this.onMuteStateChange=e}cloneVideoTrack(e){if(b.debug(`[WorkerProcessor] Original video track:`,{id:e.id,kind:e.kind,readyState:e.readyState,hasClone:typeof e.clone==`function`}),typeof e.clone==`function`)try{let t=e.clone();return this.videoTrackClone=t,b.debug(`[WorkerProcessor] Video track cloned successfully:`,{id:t.id,kind:t.kind,readyState:t.readyState}),t}catch(e){throw b.error(`[WorkerProcessor] Failed to clone video track:`,e),Error(`Failed to clone video track: ${e instanceof Error?e.message:String(e)}`)}return b.warn(`[WorkerProcessor] Video track clone() not available, using original`),this.videoTrackClone=e,e}cloneAudioTrack(e){if(b.debug(`[WorkerProcessor] Original audio track:`,{id:e.id,kind:e.kind,readyState:e.readyState,hasClone:typeof e.clone==`function`}),typeof e.clone==`function`)try{let t=e.clone();return this.audioTrackClone=t,b.debug(`[WorkerProcessor] Audio track cloned successfully:`,{id:t.id,kind:t.kind,readyState:t.readyState}),t}catch(e){throw b.error(`[WorkerProcessor] Failed to clone audio track:`,e),Error(`Failed to clone audio track: ${e instanceof Error?e.message:String(e)}`)}return b.warn(`[WorkerProcessor] Audio track clone() not available, using original`),this.audioTrackClone=e,e}stopCurrentVideoTrack(){this.currentVideoTrack&&this.currentVideoTrack.readyState===`live`&&this.currentVideoTrack.stop(),this.currentVideoTrack=null}cleanup(){this.worker&&=(this.worker.terminate(),null),wo&&=(URL.revokeObjectURL(wo),null),this.isActive=!1,this.isPaused=!1,this.chunks=[],this.totalSize=0}static isSupported(){return typeof Worker<`u`&&typeof MediaStreamTrackProcessor<`u`&&typeof VideoFrame<`u`&&typeof AudioData<`u`}},Do=class{constructor(){if(this.currentVideoStream=null,!Eo.isSupported())throw Error(`Web Workers are required for video processing. Please use a modern browser that supports Web Workers, MediaStreamTrackProcessor, VideoFrame, and AudioData APIs.`);try{this.workerProcessor=new Eo,b.debug(`[StreamProcessor] Using worker-based processing`)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`Failed to initialize worker: ${t}. Web Workers are required for video processing.`)}}async startProcessing(e,t){this.workerProcessor.setOnBufferUpdate((e,t)=>{b.debug(`[StreamProcessor] Buffer update:`,{size:e,formatted:t})}),this.workerProcessor.setOnError(e=>{b.error(`[StreamProcessor] Worker error:`,e)}),this.currentVideoStream=e,await this.workerProcessor.startProcessing(e,t)}pause(){this.workerProcessor.pause()}resume(){this.workerProcessor.resume()}isPausedState(){return this.workerProcessor.isPausedState()}async finalize(){return b.debug(`[StreamProcessor] finalize called`),await this.workerProcessor.finalize()}toggleMute(){this.workerProcessor.toggleMute()}isMutedState(){return this.workerProcessor.getMutedState()}getClonedAudioTrack(){return this.workerProcessor.getClonedAudioTrack()}getAudioStreamForAnalysis(){return this.workerProcessor.getAudioStreamForAnalysis()}async switchVideoSource(e){await this.workerProcessor.switchVideoSource(e),this.currentVideoStream=e,this.onSourceChange&&this.onSourceChange(e)}getCurrentVideoSource(){return this.currentVideoStream}getBufferSize(){return this.workerProcessor.getBufferSize()}setOnMuteStateChange(e){this.workerProcessor.setOnMuteStateChange(e)}setOnSourceChange(e){this.onSourceChange=e}async cancel(){await this.workerProcessor.cancel(),this.workerProcessor.cleanup(),this.currentVideoStream=null}};let Oo=1e3,ko=`recording`,Ao=`idle`;var jo=class{constructor(e,t){this.recordingState=Ao,this.countdownDuration=5e3,this.countdownRemaining=0,this.countdownTimeoutId=null,this.countdownIntervalId=null,this.countdownStartTime=null,this.isPaused=!1,this.maxRecordingTime=null,this.maxTimeTimer=null,this.recordingSeconds=0,this.recordingIntervalId=null,this.pauseStartTime=null,this.totalPausedTime=0,this.streamProcessor=null,this.originalCameraStream=null,this.streamManager=e,this.callbacks=t}setCountdownDuration(e){this.countdownDuration=e}setMaxRecordingTime(e){this.maxRecordingTime=e}getRecordingState(){return this.recordingState}isPausedState(){return this.isPaused}getRecordingSeconds(){return this.recordingSeconds}getStreamProcessor(){return this.streamProcessor}setOriginalCameraStream(e){this.originalCameraStream=e}getOriginalCameraStream(){return this.originalCameraStream}async startRecording(){try{this.callbacks.onClearUploadStatus(),this.countdownDuration>0?this.startCountdown():await this.doStartRecording()}catch(e){this.handleError(e),this.recordingState=Ao,this.cancelCountdown()}}startCountdown(){this.recordingState=`countdown`,this.countdownRemaining=Math.ceil(this.countdownDuration/Oo),this.countdownStartTime=Date.now(),this.callbacks.onCountdownUpdate(this.recordingState,this.countdownRemaining),this.countdownIntervalId=window.setInterval(()=>{if(!this.countdownStartTime)return;let e=Date.now()-this.countdownStartTime;this.countdownRemaining=Math.max(0,Math.ceil((this.countdownDuration-e)/Oo)),this.callbacks.onCountdownUpdate(this.recordingState,this.countdownRemaining)},100),this.countdownTimeoutId=window.setTimeout(async()=>{await this.doStartRecording().catch(()=>{})},this.countdownDuration)}async doStartRecording(){b.debug(`[RecordingManager] doStartRecording called`),this.cancelCountdown(),this.recordingState=ko,this.callbacks.onStateChange(this.recordingState),this.resetRecordingState();let e=this.streamManager.getStream();if(b.debug(`[RecordingManager] Current stream:`,{hasStream:!!e,audioTracks:e?.getAudioTracks().length||0,videoTracks:e?.getVideoTracks().length||0}),!e){b.warn(`[RecordingManager] No stream available`),this.handleError(Error(`No stream available for recording`)),this.recordingState=Ao,this.callbacks.onStateChange(this.recordingState);return}this.originalCameraStream=e,b.debug(`[RecordingManager] Creating new StreamProcessor`),this.streamProcessor=new Do,b.debug(`[RecordingManager] StreamProcessor created:`,!!this.streamProcessor);let t=await this.callbacks.onGetConfig().then(e=>({config:e,error:null})).catch(e=>({config:null,error:e}));if(t.error){this.handleError(t.error),this.recordingState=Ao,this.callbacks.onStateChange(this.recordingState);return}if(!t.config){this.handleError(Error(`Failed to get recording config`)),this.recordingState=Ao,this.callbacks.onStateChange(this.recordingState);return}b.debug(`[RecordingManager] Starting recording with stream manager`);let n=await this.streamManager.startRecording(this.streamProcessor,t.config).then(()=>(b.info(`[RecordingManager] Recording started successfully`),null)).catch(e=>(b.error(`[RecordingManager] Error starting recording:`,e),e));if(n){this.handleError(n),this.recordingState=Ao,this.callbacks.onStateChange(this.recordingState);return}this.startRecordingTimer(),this.maxRecordingTime&&this.maxRecordingTime>0&&(this.maxTimeTimer=window.setTimeout(async()=>{this.recordingState===ko&&await this.stopRecording()},this.maxRecordingTime))}async stopRecording(){b.debug(`[RecordingManager] stopRecording called`);try{this.cancelCountdown(),this.clearTimer(this.recordingIntervalId,clearInterval),this.recordingIntervalId=null,this.clearTimer(this.maxTimeTimer,clearTimeout),this.maxTimeTimer=null,this.resetPauseState(),this.callbacks.onStopAudioTracking(),b.debug(`[RecordingManager] Stopping recording in stream manager`);let e=await this.streamManager.stopRecording();return b.info(`[RecordingManager] Recording stopped, blob size:`,e.size),this.recordingState=Ao,this.callbacks.onStateChange(this.recordingState),this.recordingSeconds=0,this.streamProcessor=null,this.callbacks.onRecordingComplete(e),e}catch(e){throw this.handleError(e),this.recordingState=Ao,this.callbacks.onStateChange(this.recordingState),e}}pauseRecording(){this.recordingState!==ko||this.isPaused||(this.streamManager.pauseRecording(),this.isPaused=!0,this.clearTimer(this.recordingIntervalId,clearInterval),this.recordingIntervalId=null,this.pauseStartTime=Date.now())}resumeRecording(){this.recordingState!==ko||!this.isPaused||(this.streamManager.resumeRecording(),this.isPaused=!1,this.updatePausedDuration(),this.startRecordingTimer())}cancelCountdown(){this.clearTimer(this.countdownTimeoutId,clearTimeout),this.countdownTimeoutId=null,this.clearTimer(this.countdownIntervalId,clearInterval),this.countdownIntervalId=null,this.recordingState=Ao,this.countdownRemaining=0,this.countdownStartTime=null,this.callbacks.onCountdownUpdate(this.recordingState,this.countdownRemaining)}cleanup(){this.cancelCountdown(),this.clearTimer(this.recordingIntervalId,clearInterval),this.recordingIntervalId=null,this.clearTimer(this.maxTimeTimer,clearTimeout),this.maxTimeTimer=null}resetRecordingState(){this.isPaused=!1,this.recordingSeconds=0,this.totalPausedTime=0,this.pauseStartTime=null}resetPauseState(){this.isPaused=!1,this.pauseStartTime=null,this.totalPausedTime=0}updatePausedDuration(){if(this.pauseStartTime===null)throw Error(`Pause start time not set`);let e=Date.now()-this.pauseStartTime;this.totalPausedTime+=e,this.pauseStartTime=null}startRecordingTimer(){this.recordingIntervalId===null&&(this.recordingIntervalId=window.setInterval(()=>{this.recordingSeconds+=1,this.callbacks.onTimerUpdate(me(this.recordingSeconds))},1e3))}clearTimer(e,t){e!==null&&t(e)}handleError(e){let n=e instanceof Error?e:Error(t(e));this.callbacks.onError(n)}};let Mo=()=>{},No=()=>{},Po=()=>{},Fo=()=>{},Io=e=>{},Lo=(e,t)=>{},Ro=e=>{},zo=e=>{},Bo=e=>{},Vo=()=>{},Ho=e=>{};function Uo(){return{onProgress:Mo,onSuccess:No,onError:Po,onClearStatus:Fo}}var Wo=class{constructor(e={}){this.uploadService=null,this.uploadQueueManager=null,this.isInitialized=!1,this.callbacks=e,this.streamManager=new ye,this.configManager=new p,this.storageManager=new y,this.deviceManager=new m(this.streamManager,e.device),this.audioLevelAnalyzer=new n,this.uploadService=new xe,this.uploadCallbacks=e.upload?e.upload:Uo();let t=this.createRecordingCallbacks(e);this.recordingManager=new jo(this.streamManager,t);let r=this.createSourceSwitchCallbacks(e);this.sourceSwitchManager=new se(this.streamManager,r),e.stream&&(this.streamManager.on(`streamstart`,({stream:t})=>{b.debug(`[RecorderController] streamstart event received, calling callback`),e.stream?.onStreamStart&&e.stream.onStreamStart(t)}),this.streamManager.on(`streamstop`,()=>{b.debug(`[RecorderController] streamstop event received, calling callback`),e.stream?.onStreamStop&&e.stream.onStreamStop()}),this.streamManager.on(`error`,({error:t})=>{b.error(`[RecorderController] stream error event received, calling callback`,t),e.stream?.onError&&e.stream.onError(t)}))}async initialize(e){if(this.isInitialized)return;e.apiKey&&e.backendUrl&&await this.configManager.initialize(e.apiKey,e.backendUrl),e.countdownDuration!==void 0&&this.recordingManager.setCountdownDuration(e.countdownDuration),e.maxRecordingTime!==void 0&&this.recordingManager.setMaxRecordingTime(e.maxRecordingTime);let t=this.callbacks.onStorageCleanupError??Ho;await this.storageManager.initialize(t);let n=this.storageManager.getStorageService();n&&this.uploadService&&(this.uploadQueueManager=new be(n,this.uploadService),this.uploadQueueManager.setCallbacks({onUploadProgress:(e,t)=>{this.uploadCallbacks.onProgress(t)},onUploadComplete:(e,t)=>{this.uploadCallbacks.onSuccess(t)},onUploadError:(e,t)=>{this.uploadCallbacks.onError(t)}})),this.isInitialized=!0}async startStream(){b.debug(`[RecorderController] startStream called`),await this.streamManager.startStream(),b.debug(`[RecorderController] startStream completed`)}async stopStream(){await this.streamManager.stopStream()}switchVideoDevice(e){return this.streamManager.switchVideoDevice(e)}switchAudioDevice(e){return this.streamManager.switchAudioDevice(e)}async startRecording(){await this.recordingManager.startRecording()}async stopRecording(){let e=await this.recordingManager.stopRecording();return await this.sourceSwitchManager.handleRecordingStop().catch(()=>{throw Error(`Source switch cleanup failed`)}),e}pauseRecording(){this.recordingManager.pauseRecording()}resumeRecording(){this.recordingManager.resumeRecording()}async switchSource(e){await this.sourceSwitchManager.toggleSource()}setCameraDevice(e){this.deviceManager.setCameraDevice(e)}setMicDevice(e){this.deviceManager.setMicDevice(e)}getAvailableDevices(){return this.deviceManager.getAvailableDevices()}muteAudio(){this.streamManager.muteAudio()}unmuteAudio(){this.streamManager.unmuteAudio()}toggleMute(){this.streamManager.toggleMute()}getIsMuted(){return this.streamManager.isMuted()}startAudioLevelTracking(e,t){if(!t)throw Error(`Audio level callbacks are required`);return this.audioLevelAnalyzer.startTracking(e,t,()=>this.streamManager.isMuted()),Promise.resolve()}stopAudioLevelTracking(){this.audioLevelAnalyzer.stopTracking()}getAudioLevel(){return this.audioLevelAnalyzer.getAudioLevel()}async uploadVideo(e,t,n,r){if(!this.uploadQueueManager)throw Error(`Upload queue manager not initialized`);this.uploadCallbacks.onClearStatus();let i=await xo(e),a=Object.keys(r).length>0?r:void 0;await this.uploadQueueManager.queueUpload({blob:e,apiKey:t,backendUrl:n,filename:`recording-${Date.now()}.mp4`,duration:i,metadata:void 0,userMetadata:a})}getStream(){return this.streamManager.getStream()}getRecordingState(){return this.recordingManager.getRecordingState()}isPaused(){return this.recordingManager.isPausedState()}getCurrentSourceType(){return this.sourceSwitchManager.getCurrentSourceType()}getOriginalCameraStream(){return this.sourceSwitchManager.getOriginalCameraStream()}getStreamManager(){return this.streamManager}getAudioStreamForAnalysis(){return this.streamManager.getAudioStreamForAnalysis()}getDeviceManager(){return this.deviceManager}getConfig(){return this.configManager.getConfig()}getUploadService(){return this.uploadService}isRecording(){return this.streamManager.isRecording()}isActive(){return this.streamManager.isActive()}cleanup(){this.storageManager.destroy(),this.recordingManager.cleanup(),this.audioLevelAnalyzer.stopTracking(),this.sourceSwitchManager.cleanup()}createRecordingCallbacks(e){let t=e.recording;return{onStateChange:t?.onStateChange??Io,onCountdownUpdate:t?.onCountdownUpdate??Lo,onTimerUpdate:t?.onTimerUpdate??Ro,onError:t?.onError??zo,onRecordingComplete:t?.onRecordingComplete??Bo,onClearUploadStatus:t?.onClearUploadStatus??Vo,onStopAudioTracking:()=>{this.audioLevelAnalyzer.stopTracking()},onGetConfig:()=>this.configManager.getConfig()}}createSourceSwitchCallbacks(e){let t=e.sourceSwitch;return{onSourceChange:t?.onSourceChange,onPreviewUpdate:t?.onPreviewUpdate,onError:t?.onError,onTransitionStart:t?.onTransitionStart,onTransitionEnd:t?.onTransitionEnd,getSelectedCameraDeviceId:()=>this.deviceManager.getSelectedCameraDeviceId(),getSelectedMicDeviceId:()=>this.deviceManager.getSelectedMicDeviceId()}}};function Go(e){if(typeof e==`string`)return new Ir(e);if(e instanceof Blob)return new Pr(e);throw Error(`Invalid input type. Expected Blob, File, or file path string.`)}function Ko(e){switch(e){case`mp4`:return new Ba;case`webm`:case`mkv`:case`mov`:throw Error(`Format ${e} is not yet supported. Only MP4 is currently supported.`);default:throw Error(`Unsupported output format: ${e}`)}}function qo(e){switch(e){case`mp4`:return`video/mp4`;case`webm`:return`video/webm`;case`mkv`:return`video/x-matroska`;case`mov`:return`video/quicktime`;default:throw Error(`Unsupported output format: ${e}`)}}function Jo(e){let t=a(e.format,e.audioCodec);return{video:{width:e.width,height:e.height,fit:`contain`,frameRate:e.fps,bitrate:e.bitrate,forceTranscode:!0},audio:{codec:t,forceTranscode:!0}}}function Yo(e){if(!e.isValid){let t=e.discardedTracks.map(e=>e.reason).join(`, `);throw Error(`Conversion is invalid. Discarded tracks: ${t}`)}}async function Xo(e,t={},n){let r={...o,...t,format:t.format||o.format};r.audioCodec||=i(r.format);let a=Go(e),s=new Br({formats:[Ar],source:a}),c=new mo({format:Ko(r.format),target:new Na}),l=await vo.init({input:s,output:c,...Jo(r)});Yo(l),n&&(l.onProgress=n),await l.execute();let u=c.target.buffer;if(!u)throw Error(`Transcoding completed but no output buffer was generated`);let d=qo(r.format);return{buffer:u,blob:new Blob([u],{type:d})}}function Zo(e){if(e<.25){let t=e/.25;return`rgb(255, ${Math.round(165+50*t)}, 0)`}if(e<.5){let t=(e-.25)/.25;return`rgb(${Math.round(255- -205*t)}, ${Math.round(215+-10*t)}, ${Math.round(0+50*t)})`}if(e<.75){let t=(e-.5)/.25;return`rgb(${Math.round(50- -50*t)}, ${Math.round(205+-77*t)}, ${Math.round(50+78*t)})`}let t=(e-.75)/.25;return`rgb(0, ${Math.round(128- -28*t)}, ${Math.round(128+72*t)})`}function Qo(e,t){let n=e.querySelector(t);if(!n)throw Error(`Element not found: ${t}`);return n}async function $o(e,n,r){e.pause(),e.srcObject=null,e.load(),r===`screen`?e.classList.add(`vidtreo-screen-share`):e.classList.remove(`vidtreo-screen-share`),await new Promise(e=>{setTimeout(()=>e(),100)}),e.srcObject=n,await new Promise((n,r)=>{let i=setTimeout(()=>{a||(a=!0,o(),r(Error(`Timeout waiting for video to load`)))},1e4),a=!1,o=()=>{a||!e||(e.removeEventListener(`loadedmetadata`,f),e.removeEventListener(`loadeddata`,p),e.removeEventListener(`canplay`,m),e.removeEventListener(`playing`,h),e.removeEventListener(`error`,g))},s=()=>{a||(a=!0,clearTimeout(i),o(),n())},c=e=>{a||(a=!0,clearTimeout(i),o(),r(Error(`Failed to play preview video: ${e}`)))},l=async()=>{if(!(a||!e))try{await e.play(),s()}catch(e){c(`Failed to play preview video: ${t(e)}`)}},u=n=>{if(a||!e)return;let r=t(n);r.includes(`interrupted`)||r.includes(`abort`)?setTimeout(l,200):c(r)},d=async()=>{if(!(a||!e))try{await e.play(),s()}catch(e){u(e)}},f=()=>{a||!e||d()},p=()=>{a||!e||e.readyState>=2&&d()},m=()=>{a||!e||e.readyState>=3&&d()},h=()=>{a||!e||(a=!0,clearTimeout(i),o(),n())},g=e=>{if(a)return;a=!0,clearTimeout(i),o();let n=e instanceof ErrorEvent?e.error:Error(`Video element error`);r(Error(`Failed to load preview: ${t(n)}`))};if(e.readyState>=1){d();return}e.addEventListener(`loadedmetadata`,f,{once:!0}),e.addEventListener(`loadeddata`,p,{once:!0}),e.addEventListener(`canplay`,m,{once:!0}),e.addEventListener(`playing`,h,{once:!0}),e.addEventListener(`error`,g,{once:!0}),setTimeout(()=>{!a&&e&&e.readyState>=1&&d()},500)})}async function es(e,t){e.pause(),e.srcObject=t,await new Promise(t=>{let n=()=>{e.removeEventListener(`loadedmetadata`,n),t()};e.addEventListener(`loadedmetadata`,n),e.load(),setTimeout(()=>t(),500)});try{await e.play()}catch(e){let t=e instanceof Error?e.message:String(e);if(!(t.includes(`abort`)||t.includes(`interrupted`)))throw Error(`Failed to play preview after device switch: ${t}`)}}function ts(e){return{recording:{onStateChange:()=>{},onCountdownUpdate:(t,n)=>{e.getUIStateManager().updateCountdownOverlay(t,n)},onTimerUpdate:t=>{e.getUIStateManager().updateRecordingTimer(t)},onError:t=>{e.getUIStateManager().showError(t.message)},onRecordingComplete:e=>{},onClearUploadStatus:()=>{e.getUIStateManager().clearUploadStatus()},onStopAudioTracking:()=>{},onGetConfig:async()=>({format:`mp4`,fps:30,width:1280,height:720,bitrate:25e5,audioCodec:`aac`,preset:`medium`,packetCount:0,audioBitrate:128e3})},upload:{onProgress:t=>{e.getUIStateManager().showUploadProgress(),e.getUIStateManager().updateUploadProgress(t)},onSuccess:t=>{e.getUIStateManager().hideUploadProgress(),e.getUIStateManager().showUploadSuccess(t)},onError:t=>{e.getUIStateManager().hideUploadProgress(),e.getUIStateManager().showUploadError(t.message)},onClearStatus:()=>{e.getUIStateManager().clearUploadStatus()}},sourceSwitch:{onSourceChange:async t=>{e.getUIStateManager().updateSwitchButtonText(t);let n=e.getController();if(t===`camera`){let t=n.getStream();if(!t||t.getAudioTracks().length===0)return;n.stopAudioLevelTracking(),await n.startAudioLevelTracking(t,{onLevelUpdate:(t,n)=>{e.getAudioLevelVisualizer().updateBars(t,n)}}).catch(()=>{})}},onPreviewUpdate:async t=>{let n=e.getController(),r=n.getCurrentSourceType();if(r===`screen`){let t=n.getAudioStreamForAnalysis();if(!t||t.getAudioTracks().length===0)return;n.stopAudioLevelTracking(),await n.startAudioLevelTracking(t,{onLevelUpdate:(t,n)=>{e.getAudioLevelVisualizer().updateBars(t,n)}}).catch(()=>{})}else t.getAudioTracks().length>0&&(n.stopAudioLevelTracking(),await n.startAudioLevelTracking(t,{onLevelUpdate:(t,n)=>{e.getAudioLevelVisualizer().updateBars(t,n)}}));await $o(Qo(e.getShadowRoot(),`#videoPreview`),t,r)},onError:n=>{e.getUIStateManager().showError(t(n))},onTransitionStart:t=>{e.getUIStateManager().showSourceTransition(t)},onTransitionEnd:()=>{e.getUIStateManager().hideSourceTransition()}},storage:{onUploadProgress:()=>{},onUploadComplete:()=>{e.checkPendingUploads()},onUploadError:()=>{e.checkPendingUploads()}},onStorageCleanupError:t=>{e.getUIStateManager().showError(t)}}}function ns(e,t){let n=e.querySelector(`#previewSkeleton`),r=e.querySelector(`.vidtreo-skeleton-text`);if(!n)throw Error(`Preview skeleton element not found`);if(n.style.display=`flex`,!r)throw Error(`Skeleton text element not found`);r.textContent=t}function rs(e){let t=e.querySelector(`#previewSkeleton`);if(!t)throw Error(`Preview skeleton element not found`);t.style.display=`none`}async function is(e,n){let r=n===`default`?null:n;if(e.getController().setCameraDevice(r),e.getDeviceManager().setCameraDevice(r),!(!e.getController().isActive()||e.getController().isRecording())){ns(e.getShadowRoot(),e.getI18nManager().t(`switchingCamera`));try{let t=await e.getController().switchVideoDevice(r);await es(Qo(e.getShadowRoot(),`#videoPreview`),t),rs(e.getShadowRoot())}catch(n){rs(e.getShadowRoot()),e.showError(t(n));let r=e.getDeviceManager().getSelectedCameraDeviceId(),i=e.getShadowRoot().querySelector(`#cameraSelect`);if(!i)throw Error(`Camera select element not found`);if(!r)throw Error(`Camera device ID is required`);i.value=r}}}async function as(e,n){let r=n===`default`?null:n;if(e.getController().setMicDevice(r),e.getDeviceManager().setMicDevice(r),!(!e.getController().isActive()||e.getController().isRecording())){ns(e.getShadowRoot(),e.getI18nManager().t(`switchingMicrophone`));try{await e.getController().switchAudioDevice(r);let t=e.getController().getStream();if(!t)throw Error(`Stream is required`);e.getController().stopAudioLevelTracking(),await e.getController().startAudioLevelTracking(t,{onLevelUpdate:(t,n)=>{e.getAudioLevelVisualizer().updateBars(t,n)}}),setTimeout(()=>{rs(e.getShadowRoot())},200)}catch(n){rs(e.getShadowRoot()),e.showError(t(n));let r=e.getDeviceManager().getSelectedMicDeviceId(),i=e.getShadowRoot().querySelector(`#micSelect`);if(!i)throw Error(`Microphone select element not found`);if(!r)throw Error(`Microphone device ID is required`);i.value=r}}}function os(e){let t=e.getStreamManager();t.on(`statechange`,({state:t,previousState:n})=>{e.handleStateChange(t,n)}),t.on(`streamstart`,({stream:t})=>{e.handleStreamStart(t)}),t.on(`streamstop`,()=>{e.handleStreamStop()}),t.on(`recordingstart`,()=>{e.handleRecordingStart()}),t.on(`recordingstop`,({blob:t})=>{e.handleRecordingStop(t).catch(t=>{e.showError(e.extractErrorMessage(t))})}),t.on(`recordingtimeupdate`,({formatted:t})=>{e.updateRecordingTimer(t)}),t.on(`recordingbufferupdate`,()=>{}),t.on(`audiomutetoggle`,({muted:t})=>{e.updateMuteState(t)}),t.on(`videosourcechange`,({stream:t})=>{e.updateVideoPreview(t)}),t.on(`error`,({error:t})=>{e.showError(t.message)})}async function ss(e){if(e.getShowSettings()){e.setShowSettings(!1);let t=e.getShadowRoot().querySelector(`#settingsPanel`);if(!t)throw Error(`Settings panel element not found`);t.style.display=`none`}await e.getController().startRecording()}async function cs(e){let t=await e.getController().stopRecording();return e.setProcessedBlob(t),e.setRecordedBlob(t),e.getUIStateManager().updateRecordingControlsAfterStop(),await fs(e,t),t}function ls(e){e.getController().pauseRecording(),e.getUIStateManager().updatePauseState(e.getController().isPaused())}function us(e){e.getController().resumeRecording(),e.getUIStateManager().updatePauseState(e.getController().isPaused())}async function ds(e){let n=e.getRecordedBlob();if(!n)throw Error(`No recording available`);e.setIsProcessing(!0);let r=Qo(e.getShadowRoot(),`#processButton`);r.disabled=!0,e.getUIStateManager().hideError(),e.getUIStateManager().showProgress(),e.getUIStateManager().updateProgress(0,`Starting transcoding...`);try{let t=await Xo(n,await e.getController().getConfig(),t=>{e.getUIStateManager().updateProgress(t,`Transcoding... ${Math.round(t*100)}%`)});e.setProcessedBlob(t.blob),e.getUIStateManager().updateProgress(1,`Complete!`),setTimeout(()=>{e.getUIStateManager().hideProgress(),r.disabled=!1,e.setIsProcessing(!1)},500)}catch(n){e.getUIStateManager().hideProgress(),e.getUIStateManager().showError(t(n)),r.disabled=!1,e.setIsProcessing(!1)}}async function fs(e,t){let n=e.getAttribute(`api-key`),r=e.getNormalizedBackendUrl(e.getAttribute(`backend-url`));n&&await e.getController().uploadVideo(t,n,r,e.getUserMetadata())}function ps(e){let t=e.getShadowRoot(),n=t.querySelector(`#startCameraButton`),r=t.querySelector(`#startButton`),i=t.querySelector(`#stopButton`),a=t.querySelector(`#processButton`),o=t.querySelector(`#muteButton`),s=t.querySelector(`#switchSourceButton`),c=t.querySelector(`#settingsButton`),l=t.querySelector(`#pauseButton`),u=t.querySelector(`#resumeButton`),d=t.querySelector(`#cameraSelect`),f=t.querySelector(`#micSelect`);if(!(n&&r&&i&&a&&o&&s))throw Error(`Required UI elements not found`);n.addEventListener(`click`,()=>{e.startCamera().catch(t=>{e.showError(e.extractErrorMessage(t))})}),r.addEventListener(`click`,()=>{e.startRecording().catch(t=>{e.showError(e.extractErrorMessage(t))})}),i.addEventListener(`click`,()=>{e.stopRecording().catch(t=>{e.showError(e.extractErrorMessage(t))})}),a&&(a.style.display=`none`,a.addEventListener(`click`,()=>{e.processVideo().catch(t=>{e.showError(e.extractErrorMessage(t))})})),o.addEventListener(`click`,()=>{e.toggleMute()}),s.addEventListener(`click`,()=>{e.toggleSource().catch(t=>{e.showError(e.extractErrorMessage(t))})}),c&&c.addEventListener(`click`,()=>{e.toggleSettings()}),l&&l.addEventListener(`click`,()=>{e.pauseRecording()}),u&&u.addEventListener(`click`,()=>{e.resumeRecording()}),d&&d.addEventListener(`change`,t=>{let n=t.target;e.handleCameraChange(n.value).catch(t=>{e.showError(e.extractErrorMessage(t))})}),f&&f.addEventListener(`change`,t=>{let n=t.target;e.handleMicChange(n.value).catch(t=>{e.showError(e.extractErrorMessage(t))})})}let ms=/[:.]/g;function hs(e){let t=URL.createObjectURL(e),n=document.createElement(`a`),r=new Date().toISOString().replace(ms,`-`).slice(0,-5);n.href=t,n.download=`vidtreo-recording-${r}.mp4`,document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(t)}function gs(e){let t=URL.createObjectURL(e),n=window.open();if(!n)throw Error(`Failed to open video player window`);n.document.write(`
7746
7746
  <html>
7747
7747
  <head><title>Recorded Video</title></head>
7748
7748
  <body style="margin:0;background:#000;display:flex;align-items:center;justify-content:center;min-height:100vh;">
@@ -7751,12 +7751,12 @@ new RecorderWorker;
7751
7751
  </video>
7752
7752
  </body>
7753
7753
  </html>
7754
- `)}let _s={en:{title:`Video Recorder`,subtitle:`Record video from your camera and transcode it to MP4 format`,initializingCamera:`Initializing camera...`,grantPermissions:`Grant camera and microphone permissions when prompted`,retryCamera:`Retry Camera`,switchingDevice:`Switching device...`,recordingStartsIn:`Recording starts in...`,switchingSource:`Switching source...`,rec:`REC`,settings:`Settings`,record:`Record`,stop:`Stop`,pause:`Pause`,resume:`Resume`,mute:`Mute`,unmute:`Unmute`,switchSource:`Switch Source`,camera:`Camera`,microphone:`Microphone`,processVideo:`Process Video`,processing:`Processing...`,uploading:`Uploading...`,switchingCamera:`Switching camera...`,switchingMicrophone:`Switching microphone...`,failedToStartCamera:`Failed to start camera`},es:{title:`Grabador de Video`,subtitle:`Graba video desde tu cámara y transcodifícalo a formato MP4`,initializingCamera:`Inicializando cámara...`,grantPermissions:`Otorga permisos de cámara y micrófono cuando se solicite`,retryCamera:`Reintentar Cámara`,switchingDevice:`Cambiando dispositivo...`,recordingStartsIn:`La grabación comienza en...`,switchingSource:`Cambiando fuente...`,rec:`GRAB`,settings:`Configuración`,record:`Grabar`,stop:`Detener`,pause:`Pausar`,resume:`Reanudar`,mute:`Silenciar`,unmute:`Activar sonido`,switchSource:`Cambiar Fuente`,camera:`Cámara`,microphone:`Micrófono`,processVideo:`Procesar Video`,processing:`Procesando...`,uploading:`Subiendo...`,switchingCamera:`Cambiando cámara...`,switchingMicrophone:`Cambiando micrófono...`,failedToStartCamera:`Error al iniciar la cámara`}};var vs=class{constructor(e=`en`,t={}){this.lang=e,this.customTexts=t}setLang(e){this.lang=e}setCustomTexts(e){this.customTexts=e}t(e){return this.customTexts[e]?this.customTexts[e]:(_s[this.lang]||_s.en)[e]}getAll(){return{..._s[this.lang]||_s.en,...this.customTexts}}};let ys=.7;var bs=class{constructor(){this.barsContainer=null}initializeBars(e){this.barsContainer=this.queryElement(e,`#audioLevelBars`),this.barsContainer.innerHTML=``;for(let e=0;e<15;e++){let e=this.createBar();this.barsContainer.appendChild(e)}}updateBars(e,t){if(!this.barsContainer)throw Error(`Bars container not initialized`);this.barsContainer.querySelectorAll(`.audio-level-bar`).forEach((n,r)=>{this.updateBar(n,r,e,t)})}queryElement(e,t){let n=e.querySelector(t);if(!n)throw Error(`Element not found: ${t}`);return n}createBar(){let e=document.createElement(`div`);return e.className=`audio-level-bar`,e.style.height=`15%`,e}updateBar(e,t,n,r){let i=n>=this.calculateThreshold(t)&&!r;this.setBarHeight(e,t,i),this.setBarStyle(e,t,i,r)}calculateThreshold(e){return(e+1)/15*100}setBarHeight(e,t,n){if(n){let n=30+t/15*70;e.style.height=`${n}%`}else e.style.height=`15%`}setBarStyle(e,t,n,r){if(r||!n)e.style.backgroundColor=``,e.style.opacity=`1`;else{let n=t/15,r=ys+t/15*(1-ys);e.style.backgroundColor=Zo(n),e.style.opacity=String(r)}}},xs=class extends m{updateDeviceSelects(e){let t=e.querySelector(`#cameraSelect`),n=e.querySelector(`#micSelect`),r=this.getAvailableDevicesList(),i=this.getSelectedCameraDeviceId(),a=this.getSelectedMicDeviceId();if(t){t.innerHTML=`<option value="default">Default Camera</option>`;for(let e of r.videoinput.filter(e=>e.deviceId&&e.deviceId.trim()!==``)){let n=document.createElement(`option`);n.value=e.deviceId,n.textContent=e.label||`Camera ${e.deviceId.slice(0,8)}`,e.deviceId===i&&(n.selected=!0),t.appendChild(n)}}if(n){n.innerHTML=`<option value="default">Default Microphone</option>`;for(let e of r.audioinput.filter(e=>e.deviceId&&e.deviceId.trim()!==``)){let t=document.createElement(`option`);t.value=e.deviceId,t.textContent=e.label||`Microphone ${e.deviceId.slice(0,8)}`,e.deviceId===a&&(t.selected=!0),n.appendChild(t)}}}},Ss=class{constructor(e){this.shadowRoot=e}setShadowRoot(e){this.shadowRoot=e}queryElement(e){let t=this.shadowRoot.querySelector(e);if(!t)throw Error(`Element not found: ${e}`);return t}setText(e,t){e.textContent=t}toggleClass(e,t,n){n?e.classList.add(t):e.classList.remove(t)}setStyle(e,t,n){e.style.setProperty(t,n)}setDisplay(e,t){this.setStyle(e,`display`,t)}setDisabled(e,t){e.disabled=t}showError(e){let t=this.queryElement(`#error`);this.setText(t,e),this.toggleClass(t,`active`,!0)}hideError(){let e=this.queryElement(`#error`);this.toggleClass(e,`active`,!1)}showProgress(){let e=this.queryElement(`#progress`);this.toggleClass(e,`active`,!0)}hideProgress(){let e=this.queryElement(`#progress`);this.toggleClass(e,`active`,!1)}updateProgress(e,t){let n=Math.round(e*100),r=this.queryElement(`#progressFill`),i=this.queryElement(`#progressText`);this.setStyle(r,`width`,`${n}%`),this.setText(i,t)}updateRecordingTimer(e){let t=this.queryElement(`#recordingTimer`);this.setText(t,e)}updateMuteState(e,t,n){let r=this.queryElement(`#muteButton`),i=this.shadowRoot.querySelector(`#muteIcon`);if(!i)throw Error(`Mute icon element not found`);e?(this.toggleClass(r,`muted`,!0),i.innerHTML=`<path d="M211,221.31,51,45.31A4,4,0,0,0,45,50.69L84,93.55V128a44,44,0,0,0,66,38.12l16.38,18A67.21,67.21,0,0,1,128,196a68.07,68.07,0,0,1-68-68,4,4,0,0,0-8,0,76.09,76.09,0,0,0,72,75.89V240a4,4,0,0,0,8,0V203.89a75.1,75.1,0,0,0,39.79-13.77L205,226.69a4,4,0,1,0,5.92-5.38ZM128,164a36,36,0,0,1-36-36V102.35L144.43,160A35.83,35.83,0,0,1,128,164Zm61.12-6.15A67.44,67.44,0,0,0,196,128a4,4,0,0,1,8,0,75.28,75.28,0,0,1-7.7,33.37,4,4,0,0,1-7.18-3.52ZM87.63,46.46A44,44,0,0,1,172,64v64a44.2,44.2,0,0,1-.24,4.61,4,4,0,0,1-4,3.58l-.42,0a4,4,0,0,1-3.57-4.39A36.67,36.67,0,0,0,164,128V64A36,36,0,0,0,95,49.66a4,4,0,0,1-7.34-3.2Z"></path>`):(this.toggleClass(r,`muted`,!1),i.innerHTML=`<path d="M128,172a44.05,44.05,0,0,0,44-44V64a44,44,0,0,0-88,0v64A44.05,44.05,0,0,0,128,172ZM92,64a36,36,0,0,1,72,0v64a36,36,0,0,1-72,0Zm40,139.89V240a4,4,0,0,1-8,0V203.89A76.09,76.09,0,0,1,52,128a4,4,0,0,1,8,0,68,68,0,0,0,136,0,4,4,0,0,1,8,0A76.09,76.09,0,0,1,132,203.89Z"></path>`),t(n,e)}updatePauseState(e){let t=this.queryElement(`#pauseButton`),n=this.queryElement(`#resumeButton`);this.setDisplay(t,e?`none`:`flex`),this.setDisplay(n,e?`flex`:`none`)}updateCountdownOverlay(e,t){let n=this.queryElement(`#countdownOverlay`),r=this.queryElement(`#countdownNumber`);e===`countdown`&&t>0?(this.setDisplay(n,`flex`),this.setText(r,t.toString())):this.setDisplay(n,`none`)}showSourceTransition(e){let t=this.queryElement(`#videoPreview`);this.toggleClass(t,`transitioning`,!0);let n=this.queryElement(`#sourceTransitionOverlay`);this.toggleClass(n,`active`,!0);let r=n.querySelector(`.transition-message`);if(!r)throw Error(`Transition message element not found`);this.setText(r,e)}hideSourceTransition(){let e=this.queryElement(`#videoPreview`);this.toggleClass(e,`transitioning`,!1);let t=this.queryElement(`#sourceTransitionOverlay`);this.toggleClass(t,`active`,!1)}handleStreamStart(e,t){let n=this.queryElement(`#startButton`),r=this.queryElement(`#stopButton`),i=this.queryElement(`#cameraArea`),a=this.queryElement(`#startCameraArea`),o=this.queryElement(`#audioLevelBars`);if(this.setDisabled(n,!1),this.setDisplay(n,`flex`),this.setDisabled(r,!0),this.setDisplay(r,`none`),this.toggleClass(i,`active`,!0),this.setDisplay(a,`none`),e===`idle`){let e=this.queryElement(`#settingsButton`),t=this.queryElement(`#muteButton`),n=this.queryElement(`#pauseButton`),r=this.queryElement(`#resumeButton`),i=this.queryElement(`#switchSourceButton`);this.setDisplay(e,`flex`),this.setDisplay(t,`none`),this.setDisplay(n,`none`),this.setDisplay(r,`none`),this.setDisplay(i,`none`)}t(),this.setDisplay(o,`flex`)}handleStreamStop(e){let t=this.queryElement(`#videoPreview`);t.srcObject=null;let n=this.queryElement(`#cameraArea`),r=this.queryElement(`#audioLevelBars`);this.toggleClass(n,`active`,!1),e(),this.setDisplay(r,`none`)}handleRecordingStart(e){let t=this.queryElement(`#startButton`),n=this.queryElement(`#stopButton`),r=this.queryElement(`#muteButton`),i=this.queryElement(`#switchSourceButton`),a=this.queryElement(`#settingsButton`),o=this.queryElement(`#pauseButton`),s=this.queryElement(`#resumeButton`),c=this.queryElement(`#recIndicatorTop`),l=this.queryElement(`#recordingTimerRow`);this.setDisplay(t,`none`),this.setDisplay(n,`flex`),this.setDisabled(n,!1),this.setDisplay(c,`flex`),this.setDisplay(l,`flex`),this.setDisplay(a,`none`),this.setDisabled(r,!1),this.setDisplay(r,`flex`),this.setDisabled(i,!1),this.setDisplay(i,`flex`),this.setDisplay(o,e?`none`:`flex`),this.setDisplay(s,e?`flex`:`none`),this.hideError()}updateRecordingControlsAfterStop(){let e=this.queryElement(`#startButton`),t=this.queryElement(`#stopButton`),n=this.queryElement(`#processButton`),r=this.queryElement(`#muteButton`),i=this.queryElement(`#switchSourceButton`),a=this.queryElement(`#settingsButton`),o=this.queryElement(`#pauseButton`),s=this.queryElement(`#resumeButton`),c=this.queryElement(`#recIndicatorTop`),l=this.queryElement(`#recordingTimerRow`);this.setDisplay(e,`flex`),this.setDisabled(e,!1),this.setDisplay(t,`none`),this.setDisabled(t,!0),this.setDisplay(c,`none`),this.setDisplay(l,`none`),this.setDisplay(n,`none`),this.setDisplay(r,`none`),this.setDisplay(i,`none`),this.setDisplay(a,`flex`),this.setDisplay(o,`none`),this.setDisplay(s,`none`)}updateSwitchButtonText(e){let t=this.queryElement(`#switchSourceButton`),n=this.shadowRoot.querySelector(`#switchSourceIcon`);if(!n)throw Error(`Switch source icon element not found`);e===`camera`?(n.innerHTML=`<rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/>`,t.title=`Switch to Screen`):(n.innerHTML=`<path d="M17 17H4a2 2 0 0 1-2-2V5c0-1.5 1-2 1-2"/><path d="M22 15V5a2 2 0 0 0-2-2H9"/><path d="M8 21h8"/><path d="M12 17v4"/><path d="m2 2 20 20"/>`,t.title=`Switch to Camera`)}toggleSettings(e){let t=this.queryElement(`#settingsPanel`),n=!e;return this.setDisplay(t,n?`block`:`none`),n}showUploadProgress(){let e=this.queryElement(`#uploadProgress`);this.toggleClass(e,`active`,!0),this.updateUploadProgress(0)}updateUploadProgress(e){let t=this.queryElement(`#uploadProgressFill`),n=this.queryElement(`#uploadProgressText`),r=Math.round(e*100);this.setStyle(t,`width`,`${r}%`),this.setText(n,`Uploading... ${r}%`)}hideUploadProgress(){let e=this.queryElement(`#uploadProgress`);this.toggleClass(e,`active`,!1)}showUploadSuccess(e){let t=this.queryElement(`#uploadStatus`),n=this.queryElement(`#uploadStatusText`);this.toggleClass(t,`active`,!0),this.toggleClass(t,`success`,!0),this.toggleClass(t,`error`,!1),this.setText(n,`✅ Video uploaded successfully! Video ID: ${e.videoId}`)}showUploadError(e){let t=this.queryElement(`#uploadStatus`),n=this.queryElement(`#uploadStatusText`);this.toggleClass(t,`active`,!0),this.toggleClass(t,`error`,!0),this.toggleClass(t,`success`,!1),this.setText(n,`❌ Upload failed: ${e}`)}clearUploadStatus(){let e=this.queryElement(`#uploadStatus`);this.toggleClass(e,`active`,!1),this.toggleClass(e,`success`,!1),this.toggleClass(e,`error`,!1),this.hideUploadProgress()}updateVideoPreview(e){let t=this.queryElement(`#videoPreview`);if(t.pause(),!e){t.srcObject=null;return}t.srcObject=e,t.play().catch(e=>{let t=e instanceof Error?e.message:String(e);t.includes(`abort`)||t.includes(`NotAllowedError`)||t.includes(`interrupted`)||this.showError(`Failed to play preview video: ${t}`)})}getShadowRoot(){return this.shadowRoot}};let Cs=`:host{--background:0 0% 100%;--foreground:0 0% 3.9%;--card:0 0% 100%;--card-foreground:0 0% 3.9%;--primary:0 0% 9%;--primary-foreground:0 0% 98%;--secondary:0 0% 96.1%;--secondary-foreground:0 0% 9%;--muted:0 0% 96.1%;--muted-foreground:0 0% 45.1%;--accent:0 0% 96.1%;--accent-foreground:0 0% 9%;--destructive:0 84.2% 60.2%;--destructive-foreground:0 0% 98%;--border:0 0% 89.8%;--input:0 0% 89.8%;--ring:0 0% 3.9%;--radius:.5rem;--preview-bg:0 0% 98%;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;display:block}.container{background:hsl(var(--background));border-radius:16px;width:100%;max-width:600px;padding:40px;box-shadow:0 20px 60px #0000004d}h1{color:#333;margin-bottom:10px;font-size:28px}.subtitle{color:#666;margin-bottom:30px;font-size:14px}.preview-container{aspect-ratio:9/16;border:1px solid hsl(var(--border));background:hsl(var(--preview-bg));border-radius:.5rem;justify-content:center;align-items:center;width:100%;display:flex;position:relative;overflow:hidden}@media (width>=768px){.preview-container{aspect-ratio:16/9}}.camera-area{background:#f8f9ff;border:2px solid #667eea;border-radius:12px;margin-bottom:20px;padding:20px;display:none;position:relative}.source-transition-overlay{z-index:10;backdrop-filter:blur(4px);background:#000000b3;border-radius:8px;flex-direction:column;justify-content:center;align-items:center;transition:opacity .3s;display:none;position:absolute;inset:20px}.source-transition-overlay.active{animation:.2s fadeIn;display:flex}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.transition-spinner{border:4px solid #ffffff4d;border-top-color:#667eea;border-radius:50%;width:40px;height:40px;margin-bottom:12px;animation:.8s linear infinite spin}@keyframes spin{to{transform:rotate(360deg)}}.transition-message{color:#fff;text-align:center;font-size:14px;font-weight:500}.camera-area.active{display:block}.preview-container{width:100%;height:100%;position:relative}.preview-skeleton{background:hsl(var(--background)/.95);z-index:10;border-radius:.5rem;flex-direction:column;justify-content:center;align-items:center;gap:1rem;display:flex;position:absolute;inset:0}.skeleton-spinner{border:4px solid hsl(var(--muted)/.3);border-top-color:hsl(var(--primary));border-radius:50%;width:40px;height:40px;animation:.8s linear infinite spin}.skeleton-text{color:hsl(var(--muted-foreground));font-size:.875rem;font-weight:500}.video-preview{object-fit:contain;background:#000;border-radius:.5rem;width:100%;height:100%;transition:opacity .3s,transform .3s;display:block;position:absolute;inset:0}.video-preview.screen-share{object-fit:cover}.video-preview.transitioning{opacity:.5;transform:scale(.98)}.countdown-overlay{background:hsl(var(--background)/.95);z-index:20;border-radius:.5rem;justify-content:center;align-items:center;display:none;position:absolute;inset:0}.countdown-overlay.active{display:flex}.countdown-number{color:hsl(var(--foreground));font-size:9rem;font-weight:700;animation:.3s zoomIn}@keyframes zoomIn{0%{opacity:0;transform:scale(.5)}to{opacity:1;transform:scale(1)}}.countdown-text{color:hsl(var(--muted-foreground));margin-top:1rem;font-size:.875rem;font-weight:500}.settings-panel{background:hsl(var(--background));border:1px solid hsl(var(--border));border-radius:.5rem;margin-top:1rem;padding:1.25rem;animation:.3s slideIn;display:none}.settings-panel.active{display:block}@keyframes slideIn{0%{opacity:0;transform:translateY(1rem)}to{opacity:1;transform:translateY(0)}}.settings-title{margin-bottom:1.25rem;font-size:.875rem;font-weight:600}.device-select-group{margin-bottom:1.25rem}.device-select-label{color:hsl(var(--muted-foreground));align-items:center;gap:.5rem;margin-bottom:.5rem;font-size:.75rem;font-weight:500;display:flex}.device-select{border:1px solid hsl(var(--input));background:hsl(var(--background));border-radius:.375rem;width:100%;height:2.25rem;padding:0 .75rem;font-size:.875rem}.audio-level-bars{z-index:10;align-items:center;gap:.125rem;height:1rem;display:flex;position:absolute;bottom:.75rem;right:.75rem}@media (width>=768px){.audio-level-bars{height:1.25rem}}.audio-level-bar{background:hsl(var(--border));border-radius:9999px;align-self:flex-end;width:.125rem;transition:all .1s}.recording-controls{justify-content:center;align-items:center;gap:12px;display:flex}.recording-indicator{color:#c33;align-items:center;gap:8px;font-weight:600;display:none}.recording-indicator.active{display:flex}.recording-dot{background:#c33;border-radius:50%;width:12px;height:12px;animation:1.5s ease-in-out infinite pulse}@keyframes pulse{0%,to{opacity:1}50%{opacity:.3}}.recording-timer{color:#333;font-family:monospace;font-size:18px}.start-camera-area{text-align:center;cursor:pointer;background:#f8f9ff;border:2px dashed #667eea;border-radius:12px;margin-bottom:20px;padding:40px;transition:all .3s}.start-camera-area:hover:not(.loading){background:#f0f2ff;border-color:#764ba2}.start-camera-area.loading{cursor:wait;opacity:.7}.start-camera-area.loading .camera-text{color:#999}.camera-icon{margin-bottom:16px;font-size:48px}.camera-text{color:#667eea;margin-bottom:8px;font-weight:600}.camera-hint{color:#999;font-size:12px}.recording-info{background:#f5f5f5;border-radius:8px;margin-top:20px;padding:16px;display:none}.recording-info.active{display:block}.recording-size{color:#666;font-size:14px}button{color:#fff;cursor:pointer;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);border:none;border-radius:8px;width:100%;margin-top:20px;padding:16px;font-size:16px;font-weight:600;transition:transform .2s,box-shadow .2s}button:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 20px #667eea66}button:disabled{opacity:.6;cursor:not-allowed}.recording-controls{padding:.75rem 1rem;position:absolute;bottom:0;left:0;right:0}.recording-controls-row{justify-content:center;align-items:center;gap:.5rem;display:flex}.recording-timer-row{justify-content:space-between;align-items:center;gap:.5rem;display:flex}.recording-timer-badge{background:hsl(var(--background)/.9);border:1px solid hsl(var(--border));z-index:10;border-radius:9999px;align-items:center;gap:.375rem;padding:.25rem .5rem;display:flex;position:absolute;top:.75rem;right:.75rem;box-shadow:0 1px 3px #0000001a,0 1px 2px -1px #0000001a}.recording-dot-small{background:hsl(var(--destructive));border-radius:50%;width:.375rem;height:.375rem;animation:1.5s ease-in-out infinite pulse}.recording-timer-text{color:hsl(var(--foreground));font-family:monospace;font-size:.75rem;font-weight:500}.control-buttons-row{justify-content:center;align-items:center;gap:.375rem;display:flex}.control-button{border:1px solid hsl(var(--border));background:hsl(var(--background)/.9);cursor:pointer;width:2rem;height:2rem;color:hsl(var(--foreground));border-radius:9999px;justify-content:center;align-items:center;transition:all .2s;display:flex}.control-button svg{color:inherit;fill:currentColor;flex-shrink:0;width:24px!important;height:24px!important}@media (width>=768px){.control-button svg{width:26px!important;height:26px!important}.control-button{width:2.25rem;height:2.25rem}}.control-button:hover:not(:disabled){background:hsl(var(--accent))}.control-button:disabled{opacity:.5;cursor:not-allowed}.control-button.muted{background:hsl(var(--muted));color:hsl(var(--foreground))}.record-button{background:hsl(var(--destructive));height:2rem;color:hsl(var(--destructive-foreground));border:none;border-radius:9999px;align-items:center;gap:.375rem;padding:0 .75rem;font-size:.75rem;font-weight:500;transition:all .2s;display:flex}@media (width>=768px){.record-button{height:2.25rem;font-size:.875rem}}.record-button:hover:not(:disabled){background:hsl(var(--destructive)/.9)}.rec-indicator-top{background:hsl(var(--background)/.9);border:1px solid hsl(var(--border));border-radius:9999px;align-items:center;gap:.375rem;padding:.25rem .5rem;display:flex;position:absolute;top:.75rem;left:.75rem;box-shadow:0 1px 3px #0000001a,0 1px 2px -1px #0000001a}.rec-indicator-top span{font-size:.75rem;font-weight:500}.progress{margin-top:20px;display:none}.progress.active{display:block}.progress-bar{background:#e0e0e0;border-radius:4px;width:100%;height:8px;margin-bottom:8px;overflow:hidden}.progress-fill{background:linear-gradient(90deg,#667eea 0%,#764ba2 100%);width:0%;height:100%;transition:width .3s}.progress-text{text-align:center;color:#666;font-size:14px}.result{background:#f0f9ff;border:2px solid #667eea;border-radius:8px;margin-top:20px;padding:20px;display:none}.result.active{display:block}.result-title{color:#333;margin-bottom:12px;font-weight:600}.result-info{color:#666;margin-bottom:12px;font-size:14px}.result-actions{gap:12px;display:flex}.result-actions button{flex:1;margin-top:0;padding:12px;font-size:14px}.error{color:#c33;background:#fee;border:2px solid #fcc;border-radius:8px;margin-top:20px;padding:16px;display:none}.error.active{display:block}.upload-progress{margin-top:20px;display:none}.upload-progress.active{display:block}.upload-status{border-radius:8px;margin-top:20px;padding:16px;display:none}.upload-status.active{display:block}.upload-status.success{color:#22543d;background:#f0f9ff;border:2px solid #48bb78}.upload-status.error{color:#c33;background:#fee;border:2px solid #fcc}.upload-status-text{font-size:14px;font-weight:500}`;var ws=`<div class="container">
7754
+ `)}let _s={en:{title:`Video Recorder`,subtitle:`Record video from your camera and transcode it to MP4 format`,initializingCamera:`Initializing camera...`,grantPermissions:`Grant camera and microphone permissions when prompted`,retryCamera:`Retry Camera`,switchingDevice:`Switching device...`,recordingStartsIn:`Recording starts in...`,switchingSource:`Switching source...`,rec:`REC`,settings:`Settings`,record:`Record`,stop:`Stop`,pause:`Pause`,resume:`Resume`,mute:`Mute`,unmute:`Unmute`,switchSource:`Switch Source`,camera:`Camera`,microphone:`Microphone`,processVideo:`Process Video`,processing:`Processing...`,uploading:`Uploading...`,switchingCamera:`Switching camera...`,switchingMicrophone:`Switching microphone...`,failedToStartCamera:`Failed to start camera`},es:{title:`Grabador de Video`,subtitle:`Graba video desde tu cámara y transcodifícalo a formato MP4`,initializingCamera:`Inicializando cámara...`,grantPermissions:`Otorga permisos de cámara y micrófono cuando se solicite`,retryCamera:`Reintentar Cámara`,switchingDevice:`Cambiando dispositivo...`,recordingStartsIn:`La grabación comienza en...`,switchingSource:`Cambiando fuente...`,rec:`GRAB`,settings:`Configuración`,record:`Grabar`,stop:`Detener`,pause:`Pausar`,resume:`Reanudar`,mute:`Silenciar`,unmute:`Activar sonido`,switchSource:`Cambiar Fuente`,camera:`Cámara`,microphone:`Micrófono`,processVideo:`Procesar Video`,processing:`Procesando...`,uploading:`Subiendo...`,switchingCamera:`Cambiando cámara...`,switchingMicrophone:`Cambiando micrófono...`,failedToStartCamera:`Error al iniciar la cámara`}};var vs=class{constructor(e=`en`,t={}){this.lang=e,this.customTexts=t}setLang(e){this.lang=e}setCustomTexts(e){this.customTexts=e}t(e){return this.customTexts[e]?this.customTexts[e]:(_s[this.lang]||_s.en)[e]}getAll(){return{..._s[this.lang]||_s.en,...this.customTexts}}};let ys=.7;var bs=class{constructor(){this.barsContainer=null}initializeBars(e){this.barsContainer=this.queryElement(e,`#audioLevelBars`),this.barsContainer.innerHTML=``;for(let e=0;e<15;e++){let e=this.createBar();this.barsContainer.appendChild(e)}}updateBars(e,t){if(!this.barsContainer)throw Error(`Bars container not initialized`);this.barsContainer.querySelectorAll(`.vidtreo-audio-level-bar`).forEach((n,r)=>{this.updateBar(n,r,e,t)})}queryElement(e,t){let n=e.querySelector(t);if(!n)throw Error(`Element not found: ${t}`);return n}createBar(){let e=document.createElement(`div`);return e.className=`vidtreo-audio-level-bar`,e.style.height=`15%`,e}updateBar(e,t,n,r){let i=n>=this.calculateThreshold(t)&&!r;this.setBarHeight(e,t,i),this.setBarStyle(e,t,i,r)}calculateThreshold(e){return(e+1)/15*100}setBarHeight(e,t,n){if(n){let n=30+t/15*70;e.style.height=`${n}%`}else e.style.height=`15%`}setBarStyle(e,t,n,r){if(r||!n)e.style.backgroundColor=``,e.style.opacity=`1`;else{let n=t/15,r=ys+t/15*(1-ys);e.style.backgroundColor=Zo(n),e.style.opacity=String(r)}}},xs=class extends m{updateDeviceSelects(e){let t=e.querySelector(`#cameraSelect`),n=e.querySelector(`#micSelect`),r=this.getAvailableDevicesList(),i=this.getSelectedCameraDeviceId(),a=this.getSelectedMicDeviceId();if(t){t.innerHTML=`<option value="default">Default Camera</option>`;for(let e of r.videoinput.filter(e=>e.deviceId&&e.deviceId.trim()!==``)){let n=document.createElement(`option`);n.value=e.deviceId,n.textContent=e.label||`Camera ${e.deviceId.slice(0,8)}`,e.deviceId===i&&(n.selected=!0),t.appendChild(n)}}if(n){n.innerHTML=`<option value="default">Default Microphone</option>`;for(let e of r.audioinput.filter(e=>e.deviceId&&e.deviceId.trim()!==``)){let t=document.createElement(`option`);t.value=e.deviceId,t.textContent=e.label||`Microphone ${e.deviceId.slice(0,8)}`,e.deviceId===a&&(t.selected=!0),n.appendChild(t)}}}},Ss=class{constructor(e){this.shadowRoot=e}setShadowRoot(e){this.shadowRoot=e}queryElement(e){let t=this.shadowRoot.querySelector(e);if(!t)throw Error(`Element not found: ${e}`);return t}setText(e,t){e.textContent=t}toggleClass(e,t,n){n?e.classList.add(t):e.classList.remove(t)}setStyle(e,t,n){e.style.setProperty(t,n)}setDisplay(e,t){this.setStyle(e,`display`,t)}setDisabled(e,t){e.disabled=t}showError(e){let t=this.queryElement(`#error`);this.setText(t,e),this.toggleClass(t,`vidtreo-active`,!0)}hideError(){let e=this.queryElement(`#error`);this.toggleClass(e,`vidtreo-active`,!1)}showProgress(){let e=this.queryElement(`#progress`);this.toggleClass(e,`vidtreo-active`,!0)}hideProgress(){let e=this.queryElement(`#progress`);this.toggleClass(e,`vidtreo-active`,!1)}updateProgress(e,t){let n=Math.round(e*100),r=this.queryElement(`#progressFill`),i=this.queryElement(`#progressText`);this.setStyle(r,`width`,`${n}%`),this.setText(i,t)}updateRecordingTimer(e){let t=this.queryElement(`#recordingTimer`);this.setText(t,e)}updateMuteState(e,t,n){let r=this.queryElement(`#muteButton`),i=this.shadowRoot.querySelector(`#muteIcon`);if(!i)throw Error(`Mute icon element not found`);e?(this.toggleClass(r,`vidtreo-muted`,!0),i.innerHTML=`<path d="M211,221.31,51,45.31A4,4,0,0,0,45,50.69L84,93.55V128a44,44,0,0,0,66,38.12l16.38,18A67.21,67.21,0,0,1,128,196a68.07,68.07,0,0,1-68-68,4,4,0,0,0-8,0,76.09,76.09,0,0,0,72,75.89V240a4,4,0,0,0,8,0V203.89a75.1,75.1,0,0,0,39.79-13.77L205,226.69a4,4,0,1,0,5.92-5.38ZM128,164a36,36,0,0,1-36-36V102.35L144.43,160A35.83,35.83,0,0,1,128,164Zm61.12-6.15A67.44,67.44,0,0,0,196,128a4,4,0,0,1,8,0,75.28,75.28,0,0,1-7.7,33.37,4,4,0,0,1-7.18-3.52ZM87.63,46.46A44,44,0,0,1,172,64v64a44.2,44.2,0,0,1-.24,4.61,4,4,0,0,1-4,3.58l-.42,0a4,4,0,0,1-3.57-4.39A36.67,36.67,0,0,0,164,128V64A36,36,0,0,0,95,49.66a4,4,0,0,1-7.34-3.2Z"></path>`):(this.toggleClass(r,`vidtreo-muted`,!1),i.innerHTML=`<path d="M128,172a44.05,44.05,0,0,0,44-44V64a44,44,0,0,0-88,0v64A44.05,44.05,0,0,0,128,172ZM92,64a36,36,0,0,1,72,0v64a36,36,0,0,1-72,0Zm40,139.89V240a4,4,0,0,1-8,0V203.89A76.09,76.09,0,0,1,52,128a4,4,0,0,1,8,0,68,68,0,0,0,136,0,4,4,0,0,1,8,0A76.09,76.09,0,0,1,132,203.89Z"></path>`),t(n,e)}updatePauseState(e){let t=this.queryElement(`#pauseButton`),n=this.queryElement(`#resumeButton`);this.setDisplay(t,e?`none`:`flex`),this.setDisplay(n,e?`flex`:`none`)}updateCountdownOverlay(e,t){let n=this.queryElement(`#countdownOverlay`),r=this.queryElement(`#countdownNumber`);e===`countdown`&&t>0?(this.setDisplay(n,`flex`),this.setText(r,t.toString())):this.setDisplay(n,`none`)}showSourceTransition(e){let t=this.queryElement(`#videoPreview`);this.toggleClass(t,`vidtreo-transitioning`,!0);let n=this.queryElement(`#sourceTransitionOverlay`);this.toggleClass(n,`vidtreo-active`,!0);let r=n.querySelector(`.vidtreo-transition-message`);if(!r)throw Error(`Transition message element not found`);this.setText(r,e)}hideSourceTransition(){let e=this.queryElement(`#videoPreview`);this.toggleClass(e,`vidtreo-transitioning`,!1);let t=this.queryElement(`#sourceTransitionOverlay`);this.toggleClass(t,`vidtreo-active`,!1)}handleStreamStart(e,t){let n=this.queryElement(`#startButton`),r=this.queryElement(`#stopButton`),i=this.queryElement(`#cameraArea`),a=this.queryElement(`#startCameraArea`),o=this.queryElement(`#audioLevelBars`);if(this.setDisabled(n,!1),this.setDisplay(n,`flex`),this.setDisabled(r,!0),this.setDisplay(r,`none`),this.toggleClass(i,`vidtreo-active`,!0),this.setDisplay(a,`none`),e===`idle`){let e=this.queryElement(`#settingsButton`),t=this.queryElement(`#muteButton`),n=this.queryElement(`#pauseButton`),r=this.queryElement(`#resumeButton`),i=this.queryElement(`#switchSourceButton`);this.setDisplay(e,`flex`),this.setDisplay(t,`none`),this.setDisplay(n,`none`),this.setDisplay(r,`none`),this.setDisplay(i,`none`)}t(),this.setDisplay(o,`flex`)}handleStreamStop(e){let t=this.queryElement(`#videoPreview`);t.srcObject=null;let n=this.queryElement(`#cameraArea`),r=this.queryElement(`#audioLevelBars`);this.toggleClass(n,`vidtreo-active`,!1),e(),this.setDisplay(r,`none`)}handleRecordingStart(e){let t=this.queryElement(`#startButton`),n=this.queryElement(`#stopButton`),r=this.queryElement(`#muteButton`),i=this.queryElement(`#switchSourceButton`),a=this.queryElement(`#settingsButton`),o=this.queryElement(`#pauseButton`),s=this.queryElement(`#resumeButton`),c=this.queryElement(`#recIndicatorTop`),l=this.queryElement(`#recordingTimerRow`);this.setDisplay(t,`none`),this.setDisplay(n,`flex`),this.setDisabled(n,!1),this.setDisplay(c,`flex`),this.setDisplay(l,`flex`),this.setDisplay(a,`none`),this.setDisabled(r,!1),this.setDisplay(r,`flex`),this.setDisabled(i,!1),this.setDisplay(i,`flex`),this.setDisplay(o,e?`none`:`flex`),this.setDisplay(s,e?`flex`:`none`),this.hideError()}updateRecordingControlsAfterStop(){let e=this.queryElement(`#startButton`),t=this.queryElement(`#stopButton`),n=this.queryElement(`#processButton`),r=this.queryElement(`#muteButton`),i=this.queryElement(`#switchSourceButton`),a=this.queryElement(`#settingsButton`),o=this.queryElement(`#pauseButton`),s=this.queryElement(`#resumeButton`),c=this.queryElement(`#recIndicatorTop`),l=this.queryElement(`#recordingTimerRow`);this.setDisplay(e,`flex`),this.setDisabled(e,!1),this.setDisplay(t,`none`),this.setDisabled(t,!0),this.setDisplay(c,`none`),this.setDisplay(l,`none`),this.setDisplay(n,`none`),this.setDisplay(r,`none`),this.setDisplay(i,`none`),this.setDisplay(a,`flex`),this.setDisplay(o,`none`),this.setDisplay(s,`none`)}updateSwitchButtonText(e){let t=this.queryElement(`#switchSourceButton`),n=this.shadowRoot.querySelector(`#switchSourceIcon`);if(!n)throw Error(`Switch source icon element not found`);e===`camera`?(n.innerHTML=`<rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/>`,t.title=`Switch to Screen`):(n.innerHTML=`<path d="M17 17H4a2 2 0 0 1-2-2V5c0-1.5 1-2 1-2"/><path d="M22 15V5a2 2 0 0 0-2-2H9"/><path d="M8 21h8"/><path d="M12 17v4"/><path d="m2 2 20 20"/>`,t.title=`Switch to Camera`)}toggleSettings(e){let t=this.queryElement(`#settingsPanel`),n=!e;return this.setDisplay(t,n?`block`:`none`),n}showUploadProgress(){let e=this.queryElement(`#uploadProgress`);this.toggleClass(e,`vidtreo-active`,!0),this.updateUploadProgress(0)}updateUploadProgress(e){let t=this.queryElement(`#uploadProgressFill`),n=this.queryElement(`#uploadProgressText`),r=Math.round(e*100);this.setStyle(t,`width`,`${r}%`),this.setText(n,`Uploading... ${r}%`)}hideUploadProgress(){let e=this.queryElement(`#uploadProgress`);this.toggleClass(e,`vidtreo-active`,!1)}showUploadSuccess(e){let t=this.queryElement(`#uploadStatus`),n=this.queryElement(`#uploadStatusText`);this.toggleClass(t,`vidtreo-active`,!0),this.toggleClass(t,`vidtreo-success`,!0),this.toggleClass(t,`vidtreo-error`,!1),this.setText(n,`✅ Video uploaded successfully! Video ID: ${e.videoId}`)}showUploadError(e){let t=this.queryElement(`#uploadStatus`),n=this.queryElement(`#uploadStatusText`);this.toggleClass(t,`vidtreo-active`,!0),this.toggleClass(t,`vidtreo-error`,!0),this.toggleClass(t,`vidtreo-success`,!1),this.setText(n,`❌ Upload failed: ${e}`)}clearUploadStatus(){let e=this.queryElement(`#uploadStatus`);this.toggleClass(e,`vidtreo-active`,!1),this.toggleClass(e,`vidtreo-success`,!1),this.toggleClass(e,`vidtreo-error`,!1),this.hideUploadProgress()}updateVideoPreview(e){let t=this.queryElement(`#videoPreview`);if(t.pause(),!e){t.srcObject=null;return}t.srcObject=e,t.play().catch(e=>{let t=e instanceof Error?e.message:String(e);t.includes(`abort`)||t.includes(`NotAllowedError`)||t.includes(`interrupted`)||this.showError(`Failed to play preview video: ${t}`)})}getShadowRoot(){return this.shadowRoot}};let Cs=`:host{--vidtreo-background:0 0% 100%;--vidtreo-foreground:0 0% 3.9%;--vidtreo-card:0 0% 100%;--vidtreo-card-foreground:0 0% 3.9%;--vidtreo-primary:0 0% 9%;--vidtreo-primary-foreground:0 0% 98%;--vidtreo-secondary:0 0% 96.1%;--vidtreo-secondary-foreground:0 0% 9%;--vidtreo-muted:0 0% 96.1%;--vidtreo-muted-foreground:0 0% 45.1%;--vidtreo-accent:0 0% 96.1%;--vidtreo-accent-foreground:0 0% 9%;--vidtreo-destructive:0 84.2% 60.2%;--vidtreo-destructive-foreground:0 0% 98%;--vidtreo-border:0 0% 89.8%;--vidtreo-input:0 0% 89.8%;--vidtreo-ring:0 0% 3.9%;--vidtreo-radius:.5rem;--vidtreo-preview-bg:0 0% 98%;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;display:block}.vidtreo-container{background:hsl(var(--vidtreo-background));border-radius:16px;width:100%;max-width:600px;padding:40px;box-shadow:0 20px 60px #0000004d}.vidtreo-preview-container{aspect-ratio:9/16;border:1px solid hsl(var(--vidtreo-border));background:hsl(var(--vidtreo-preview-bg));border-radius:.5rem;justify-content:center;align-items:center;width:100%;display:flex;position:relative;overflow:hidden}@media (width>=768px){.vidtreo-preview-container{aspect-ratio:16/9}}.vidtreo-camera-area{background:#f8f9ff;border:2px solid #667eea;border-radius:12px;margin-bottom:20px;padding:20px;display:none;position:relative}.vidtreo-source-transition-overlay{z-index:10;backdrop-filter:blur(4px);background:#000000b3;border-radius:8px;flex-direction:column;justify-content:center;align-items:center;transition:opacity .3s;display:none;position:absolute;inset:20px}.vidtreo-source-transition-overlay.vidtreo-active{animation:.2s vidtreo-fadeIn;display:flex}@keyframes vidtreo-fadeIn{0%{opacity:0}to{opacity:1}}.vidtreo-transition-spinner{border:4px solid #ffffff4d;border-top-color:#667eea;border-radius:50%;width:40px;height:40px;margin-bottom:12px;animation:.8s linear infinite vidtreo-spin}@keyframes vidtreo-spin{to{transform:rotate(360deg)}}.vidtreo-transition-message{color:#fff;text-align:center;font-size:14px;font-weight:500}.vidtreo-camera-area.vidtreo-active{display:block}.vidtreo-preview-skeleton{background:hsl(var(--vidtreo-background)/.95);z-index:10;border-radius:.5rem;flex-direction:column;justify-content:center;align-items:center;gap:1rem;display:flex;position:absolute;inset:0}.vidtreo-skeleton-spinner{border:4px solid hsl(var(--vidtreo-muted)/.3);border-top-color:hsl(var(--vidtreo-primary));border-radius:50%;width:40px;height:40px;animation:.8s linear infinite vidtreo-spin}.vidtreo-skeleton-text{color:hsl(var(--vidtreo-muted-foreground));font-size:.875rem;font-weight:500}.vidtreo-video-preview{object-fit:contain;background:#000;border-radius:.5rem;width:100%;height:100%;transition:opacity .3s,transform .3s;display:block;position:absolute;inset:0}.vidtreo-video-preview.vidtreo-screen-share{object-fit:cover}.vidtreo-video-preview.vidtreo-transitioning{opacity:.5;transform:scale(.98)}.vidtreo-countdown-overlay{background:hsl(var(--vidtreo-background)/.95);z-index:20;border-radius:.5rem;justify-content:center;align-items:center;display:none;position:absolute;inset:0}.vidtreo-countdown-overlay.vidtreo-active{display:flex}.vidtreo-countdown-number{color:hsl(var(--vidtreo-foreground));font-size:9rem;font-weight:700;animation:.3s vidtreo-zoomIn}@keyframes vidtreo-zoomIn{0%{opacity:0;transform:scale(.5)}to{opacity:1;transform:scale(1)}}.vidtreo-countdown-text{color:hsl(var(--vidtreo-muted-foreground));margin-top:1rem;font-size:.875rem;font-weight:500}.vidtreo-settings-panel{background:hsl(var(--vidtreo-background));border:1px solid hsl(var(--vidtreo-border));border-radius:.5rem;margin-top:1rem;padding:1.25rem;animation:.3s vidtreo-slideIn;display:none}.vidtreo-settings-panel.vidtreo-active{display:block}@keyframes vidtreo-slideIn{0%{opacity:0;transform:translateY(1rem)}to{opacity:1;transform:translateY(0)}}.vidtreo-settings-title{margin-bottom:1.25rem;font-size:.875rem;font-weight:600}.vidtreo-device-select-group{margin-bottom:1.25rem}.vidtreo-device-select-label{color:hsl(var(--vidtreo-muted-foreground));align-items:center;gap:.5rem;margin-bottom:.5rem;font-size:.75rem;font-weight:500;display:flex}.vidtreo-device-select{border:1px solid hsl(var(--vidtreo-input));background:hsl(var(--vidtreo-background));border-radius:.375rem;width:100%;height:2.25rem;padding:0 .75rem;font-size:.875rem}.vidtreo-audio-level-bars{z-index:10;align-items:center;gap:.125rem;height:1rem;display:flex;position:absolute;bottom:.75rem;right:.75rem}@media (width>=768px){.vidtreo-audio-level-bars{height:1.25rem}}.vidtreo-audio-level-bar{background:hsl(var(--vidtreo-border));border-radius:9999px;align-self:flex-end;width:.125rem;transition:all .1s}.vidtreo-recording-controls{padding:.75rem 1rem;position:absolute;bottom:0;left:0;right:0}.vidtreo-recording-controls-row{justify-content:center;align-items:center;gap:.5rem;display:flex}.vidtreo-recording-timer-row{justify-content:space-between;align-items:center;gap:.5rem;display:flex}.vidtreo-recording-timer-badge{background:hsl(var(--vidtreo-background)/.9);border:1px solid hsl(var(--vidtreo-border));z-index:10;border-radius:9999px;align-items:center;gap:.375rem;padding:.25rem .5rem;display:flex;position:absolute;top:.75rem;right:.75rem;box-shadow:0 1px 3px #0000001a,0 1px 2px -1px #0000001a}.vidtreo-recording-dot-small{background:hsl(var(--vidtreo-destructive));border-radius:50%;width:.375rem;height:.375rem;animation:1.5s ease-in-out infinite vidtreo-pulse}.vidtreo-recording-timer-text{color:hsl(var(--vidtreo-foreground));font-family:monospace;font-size:.75rem;font-weight:500}.vidtreo-control-buttons-row{justify-content:center;align-items:center;gap:.375rem;display:flex}.vidtreo-control-button{border:1px solid hsl(var(--vidtreo-border));background:hsl(var(--vidtreo-background)/.9);cursor:pointer;width:2rem;height:2rem;color:hsl(var(--vidtreo-foreground));border-radius:9999px;justify-content:center;align-items:center;transition:all .2s;display:flex}.vidtreo-control-button svg{color:inherit;fill:currentColor;flex-shrink:0;width:24px!important;height:24px!important}@media (width>=768px){.vidtreo-control-button svg{width:26px!important;height:26px!important}.vidtreo-control-button{width:2.25rem;height:2.25rem}}.vidtreo-control-button:hover:not(:disabled){background:hsl(var(--vidtreo-accent))}.vidtreo-control-button:disabled{opacity:.5;cursor:not-allowed}.vidtreo-control-button.vidtreo-muted{background:hsl(var(--vidtreo-muted));color:hsl(var(--vidtreo-foreground))}.vidtreo-record-button{background:hsl(var(--vidtreo-destructive));height:2rem;color:hsl(var(--vidtreo-destructive-foreground));border:none;border-radius:9999px;align-items:center;gap:.375rem;padding:0 .75rem;font-size:.75rem;font-weight:500;transition:all .2s;display:flex}@media (width>=768px){.vidtreo-record-button{height:2.25rem;font-size:.875rem}}.vidtreo-record-button:hover:not(:disabled){background:hsl(var(--vidtreo-destructive)/.9)}.vidtreo-rec-indicator-top{background:hsl(var(--vidtreo-background)/.9);border:1px solid hsl(var(--vidtreo-border));border-radius:9999px;align-items:center;gap:.375rem;padding:.25rem .5rem;display:flex;position:absolute;top:.75rem;left:.75rem;box-shadow:0 1px 3px #0000001a,0 1px 2px -1px #0000001a}.vidtreo-rec-indicator-top span{font-size:.75rem;font-weight:500}.vidtreo-start-camera-area{text-align:center;cursor:pointer;background:#f8f9ff;border:2px dashed #667eea;border-radius:12px;margin-bottom:20px;padding:40px;transition:all .3s}.vidtreo-start-camera-area:hover:not(.vidtreo-loading){background:#f0f2ff;border-color:#764ba2}.vidtreo-start-camera-area.vidtreo-loading{cursor:wait;opacity:.7}.vidtreo-start-camera-area.vidtreo-loading .vidtreo-camera-text{color:#999}.vidtreo-camera-icon{margin-bottom:16px;font-size:48px}.vidtreo-camera-text{color:#667eea;margin-bottom:8px;font-weight:600}.vidtreo-camera-hint{color:#999;font-size:12px}@keyframes vidtreo-pulse{0%,to{opacity:1}50%{opacity:.3}}.vidtreo-progress{margin-top:20px;display:none}.vidtreo-progress.vidtreo-active{display:block}.vidtreo-progress-bar{background:#e0e0e0;border-radius:4px;width:100%;height:8px;margin-bottom:8px;overflow:hidden}.vidtreo-progress-fill{background:linear-gradient(90deg,#667eea 0%,#764ba2 100%);width:0%;height:100%;transition:width .3s}.vidtreo-progress-text{text-align:center;color:#666;font-size:14px}.vidtreo-error{color:#c33;background:#fee;border:2px solid #fcc;border-radius:8px;margin-top:20px;padding:16px;display:none}.vidtreo-error.vidtreo-active{display:block}.vidtreo-upload-progress{margin-top:20px;display:none}.vidtreo-upload-progress.vidtreo-active{display:block}.vidtreo-upload-status{border-radius:8px;margin-top:20px;padding:16px;display:none}.vidtreo-upload-status.vidtreo-active{display:block}.vidtreo-upload-status.vidtreo-success{color:#22543d;background:#f0f9ff;border:2px solid #48bb78}.vidtreo-upload-status.vidtreo-error{color:#c33;background:#fee;border:2px solid #fcc}.vidtreo-upload-status-text{font-size:14px;font-weight:500}`;var ws=`<div class="vidtreo-container">
7755
7755
  <h1>{{TITLE}}</h1>
7756
- <p class="subtitle">{{SUBTITLE}}</p>
7756
+ <p class="vidtreo-subtitle">{{SUBTITLE}}</p>
7757
7757
 
7758
- <div class="start-camera-area" id="startCameraArea">
7759
- <div class="camera-icon">
7758
+ <div class="vidtreo-start-camera-area" id="startCameraArea">
7759
+ <div class="vidtreo-camera-icon">
7760
7760
  <svg
7761
7761
  width="48"
7762
7762
  height="48"
@@ -7774,63 +7774,72 @@ new RecorderWorker;
7774
7774
  <circle cx="128" cy="132" r="36" fill="none"/>
7775
7775
  </svg>
7776
7776
  </div>
7777
- <div class="camera-text">{{INITIALIZING_CAMERA}}</div>
7778
- <div class="camera-hint">{{GRANT_PERMISSIONS}}</div>
7777
+ <div class="vidtreo-camera-text">{{INITIALIZING_CAMERA}}</div>
7778
+ <div class="vidtreo-camera-hint">{{GRANT_PERMISSIONS}}</div>
7779
7779
  <button id="startCameraButton" style="display: none;">
7780
7780
  {{RETRY_CAMERA}}
7781
7781
  </button>
7782
7782
  </div>
7783
7783
 
7784
- <div class="camera-area" id="cameraArea">
7785
- <div class="preview-container">
7786
- <div class="preview-skeleton" id="previewSkeleton" style="display: none;">
7787
- <div class="skeleton-spinner"></div>
7788
- <div class="skeleton-text">{{SWITCHING_DEVICE}}</div>
7784
+ <div class="vidtreo-camera-area" id="cameraArea">
7785
+ <div class="vidtreo-preview-container">
7786
+ <div
7787
+ class="vidtreo-preview-skeleton"
7788
+ id="previewSkeleton"
7789
+ style="display: none;"
7790
+ >
7791
+ <div class="vidtreo-skeleton-spinner"></div>
7792
+ <div class="vidtreo-skeleton-text">{{SWITCHING_DEVICE}}</div>
7789
7793
  </div>
7790
7794
  <video
7791
7795
  id="videoPreview"
7792
- class="video-preview"
7796
+ class="vidtreo-video-preview"
7793
7797
  autoplay
7794
7798
  muted
7795
7799
  playsinline
7796
7800
  ></video>
7797
- <div class="countdown-overlay" id="countdownOverlay">
7798
- <div class="countdown-content">
7799
- <div class="countdown-number" id="countdownNumber">5</div>
7800
- <p class="countdown-text">{{RECORDING_STARTS_IN}}</p>
7801
+ <div class="vidtreo-countdown-overlay" id="countdownOverlay">
7802
+ <div class="vidtreo-countdown-content">
7803
+ <div class="vidtreo-countdown-number" id="countdownNumber">5</div>
7804
+ <p class="vidtreo-countdown-text">{{RECORDING_STARTS_IN}}</p>
7801
7805
  </div>
7802
7806
  </div>
7803
- <div class="source-transition-overlay" id="sourceTransitionOverlay">
7804
- <div class="transition-spinner"></div>
7805
- <div class="transition-message">{{SWITCHING_SOURCE}}</div>
7807
+ <div
7808
+ class="vidtreo-source-transition-overlay"
7809
+ id="sourceTransitionOverlay"
7810
+ >
7811
+ <div class="vidtreo-transition-spinner"></div>
7812
+ <div class="vidtreo-transition-message">{{SWITCHING_SOURCE}}</div>
7806
7813
  </div>
7807
7814
  <div
7808
- class="rec-indicator-top"
7815
+ class="vidtreo-rec-indicator-top"
7809
7816
  id="recIndicatorTop"
7810
7817
  style="display: none;"
7811
7818
  >
7812
- <div class="recording-dot-small"></div>
7819
+ <div class="vidtreo-recording-dot-small"></div>
7813
7820
  <span>{{REC}}</span>
7814
7821
  </div>
7815
7822
  <div
7816
- class="recording-timer-badge"
7823
+ class="vidtreo-recording-timer-badge"
7817
7824
  id="recordingTimerRow"
7818
7825
  style="display: none;"
7819
7826
  >
7820
- <div class="recording-dot-small"></div>
7821
- <span class="recording-timer-text" id="recordingTimer">00:00</span>
7827
+ <div class="vidtreo-recording-dot-small"></div>
7828
+ <span class="vidtreo-recording-timer-text" id="recordingTimer"
7829
+ >00:00</span
7830
+ >
7822
7831
  </div>
7823
7832
  <div
7824
- class="audio-level-bars"
7833
+ class="vidtreo-audio-level-bars"
7825
7834
  id="audioLevelBars"
7826
7835
  style="display: none;"
7827
7836
  ></div>
7828
- <div class="recording-controls">
7829
- <div class="recording-controls-row">
7830
- <div class="control-buttons-row">
7837
+ <div class="vidtreo-recording-controls">
7838
+ <div class="vidtreo-recording-controls-row">
7839
+ <div class="vidtreo-control-buttons-row">
7831
7840
  <!-- When not recording: settings - record - mute -->
7832
7841
  <button
7833
- class="control-button"
7842
+ class="vidtreo-control-button"
7834
7843
  id="settingsButton"
7835
7844
  style="display: none;"
7836
7845
  title="{{SETTINGS}}"
@@ -7847,7 +7856,7 @@ new RecorderWorker;
7847
7856
  ></path>
7848
7857
  </svg>
7849
7858
  </button>
7850
- <button class="record-button" id="startButton" disabled>
7859
+ <button class="vidtreo-record-button" id="startButton" disabled>
7851
7860
  <svg
7852
7861
  width="24"
7853
7862
  height="24"
@@ -7868,7 +7877,7 @@ new RecorderWorker;
7868
7877
  {{RECORD}}
7869
7878
  </button>
7870
7879
  <button
7871
- class="control-button"
7880
+ class="vidtreo-control-button"
7872
7881
  id="muteButton"
7873
7882
  disabled
7874
7883
  style="display: none;"
@@ -7886,7 +7895,7 @@ new RecorderWorker;
7886
7895
  </button>
7887
7896
  <!-- When recording: pause/resume - stop - mute - share screen -->
7888
7897
  <button
7889
- class="control-button"
7898
+ class="vidtreo-control-button"
7890
7899
  id="pauseButton"
7891
7900
  style="display: none;"
7892
7901
  title="{{PAUSE}}"
@@ -7916,7 +7925,7 @@ new RecorderWorker;
7916
7925
  </svg>
7917
7926
  </button>
7918
7927
  <button
7919
- class="control-button"
7928
+ class="vidtreo-control-button"
7920
7929
  id="resumeButton"
7921
7930
  style="display: none;"
7922
7931
  title="{{RESUME}}"
@@ -7938,7 +7947,7 @@ new RecorderWorker;
7938
7947
  </svg>
7939
7948
  </button>
7940
7949
  <button
7941
- class="record-button"
7950
+ class="vidtreo-record-button"
7942
7951
  id="stopButton"
7943
7952
  disabled
7944
7953
  style="display: none;"
@@ -7962,7 +7971,7 @@ new RecorderWorker;
7962
7971
  {{STOP}}
7963
7972
  </button>
7964
7973
  <button
7965
- class="control-button"
7974
+ class="vidtreo-control-button"
7966
7975
  id="switchSourceButton"
7967
7976
  disabled
7968
7977
  style="display: none;"
@@ -7986,10 +7995,10 @@ new RecorderWorker;
7986
7995
  </div>
7987
7996
  </div>
7988
7997
  </div>
7989
- <div class="settings-panel" id="settingsPanel">
7990
- <h3 class="settings-title">{{SETTINGS}}</h3>
7991
- <div class="device-select-group">
7992
- <div class="device-select-label">
7998
+ <div class="vidtreo-settings-panel" id="settingsPanel">
7999
+ <h3 class="vidtreo-settings-title">{{SETTINGS}}</h3>
8000
+ <div class="vidtreo-device-select-group">
8001
+ <div class="vidtreo-device-select-label">
7993
8002
  <svg
7994
8003
  xmlns="http://www.w3.org/2000/svg"
7995
8004
  width="20"
@@ -8003,12 +8012,12 @@ new RecorderWorker;
8003
8012
  </svg>
8004
8013
  <span>{{CAMERA}}</span>
8005
8014
  </div>
8006
- <select class="device-select" id="cameraSelect">
8015
+ <select class="vidtreo-device-select" id="cameraSelect">
8007
8016
  <option value="default">Default Camera</option>
8008
8017
  </select>
8009
8018
  </div>
8010
- <div class="device-select-group">
8011
- <div class="device-select-label">
8019
+ <div class="vidtreo-device-select-group">
8020
+ <div class="vidtreo-device-select-label">
8012
8021
  <svg
8013
8022
  xmlns="http://www.w3.org/2000/svg"
8014
8023
  width="20"
@@ -8022,7 +8031,7 @@ new RecorderWorker;
8022
8031
  </svg>
8023
8032
  <span>{{MICROPHONE}}</span>
8024
8033
  </div>
8025
- <select class="device-select" id="micSelect">
8034
+ <select class="vidtreo-device-select" id="micSelect">
8026
8035
  <option value="default">Default Microphone</option>
8027
8036
  </select>
8028
8037
  </div>
@@ -8031,24 +8040,26 @@ new RecorderWorker;
8031
8040
 
8032
8041
  <button id="processButton" disabled>{{PROCESS_VIDEO}}</button>
8033
8042
 
8034
- <div class="progress" id="progress">
8035
- <div class="progress-bar">
8036
- <div class="progress-fill" id="progressFill"></div>
8043
+ <div class="vidtreo-progress" id="progress">
8044
+ <div class="vidtreo-progress-bar">
8045
+ <div class="vidtreo-progress-fill" id="progressFill"></div>
8037
8046
  </div>
8038
- <div class="progress-text" id="progressText">{{PROCESSING}}</div>
8047
+ <div class="vidtreo-progress-text" id="progressText">{{PROCESSING}}</div>
8039
8048
  </div>
8040
8049
 
8041
- <div class="error" id="error"></div>
8050
+ <div class="vidtreo-error" id="error"></div>
8042
8051
 
8043
- <div class="upload-progress" id="uploadProgress">
8044
- <div class="progress-bar">
8045
- <div class="progress-fill" id="uploadProgressFill"></div>
8052
+ <div class="vidtreo-upload-progress" id="uploadProgress">
8053
+ <div class="vidtreo-progress-bar">
8054
+ <div class="vidtreo-progress-fill" id="uploadProgressFill"></div>
8055
+ </div>
8056
+ <div class="vidtreo-progress-text" id="uploadProgressText">
8057
+ {{UPLOADING}}0%
8046
8058
  </div>
8047
- <div class="progress-text" id="uploadProgressText">{{UPLOADING}}0%</div>
8048
8059
  </div>
8049
8060
 
8050
- <div class="upload-status" id="uploadStatus">
8051
- <div class="upload-status-text" id="uploadStatusText"></div>
8061
+ <div class="vidtreo-upload-status" id="uploadStatus">
8062
+ <div class="vidtreo-upload-status-text" id="uploadStatusText"></div>
8052
8063
  </div>
8053
8064
  </div>
8054
- `;function Ts(e,t){return t.reduce((e,[t,n])=>e.split(t).join(n),e)}function Es(e,t,n=`camera`){return Ts(ws,[[`{{MUTE_ICON_PLACEHOLDER}}`,e?`<path d="M211,221.31,51,45.31A4,4,0,0,0,45,50.69L84,93.55V128a44,44,0,0,0,66,38.12l16.38,18A67.21,67.21,0,0,1,128,196a68.07,68.07,0,0,1-68-68,4,4,0,0,0-8,0,76.09,76.09,0,0,0,72,75.89V240a4,4,0,0,0,8,0V203.89a75.1,75.1,0,0,0,39.79-13.77L205,226.69a4,4,0,1,0,5.92-5.38ZM128,164a36,36,0,0,1-36-36V102.35L144.43,160A35.83,35.83,0,0,1,128,164Zm61.12-6.15A67.44,67.44,0,0,0,196,128a4,4,0,0,1,8,0,75.28,75.28,0,0,1-7.7,33.37,4,4,0,0,1-7.18-3.52ZM87.63,46.46A44,44,0,0,1,172,64v64a44.2,44.2,0,0,1-.24,4.61,4,4,0,0,1-4,3.58l-.42,0a4,4,0,0,1-3.57-4.39A36.67,36.67,0,0,0,164,128V64A36,36,0,0,0,95,49.66a4,4,0,0,1-7.34-3.2Z"></path>`:`<path d="M128,172a44.05,44.05,0,0,0,44-44V64a44,44,0,0,0-88,0v64A44.05,44.05,0,0,0,128,172ZM92,64a36,36,0,0,1,72,0v64a36,36,0,0,1-72,0Zm40,139.89V240a4,4,0,0,1-8,0V203.89A76.09,76.09,0,0,1,52,128a4,4,0,0,1,8,0,68,68,0,0,0,136,0,4,4,0,0,1,8,0A76.09,76.09,0,0,1,132,203.89Z"></path>`],[`{{SWITCH_SOURCE_ICON_PLACEHOLDER}}`,n===`camera`?`<rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/>`:`<path d="M17 17H4a2 2 0 0 1-2-2V5c0-1.5 1-2 1-2"/><path d="M22 15V5a2 2 0 0 0-2-2H9"/><path d="M8 21h8"/><path d="M12 17v4"/><path d="m2 2 20 20"/>`],[`{{TITLE}}`,t.title],[`{{SUBTITLE}}`,t.subtitle],[`{{INITIALIZING_CAMERA}}`,t.initializingCamera],[`{{GRANT_PERMISSIONS}}`,t.grantPermissions],[`{{RETRY_CAMERA}}`,t.retryCamera],[`{{SWITCHING_DEVICE}}`,t.switchingDevice],[`{{RECORDING_STARTS_IN}}`,t.recordingStartsIn],[`{{SWITCHING_SOURCE}}`,t.switchingSource],[`{{REC}}`,t.rec],[`{{SETTINGS}}`,t.settings],[`{{RECORD}}`,t.record],[`{{STOP}}`,t.stop],[`{{PAUSE}}`,t.pause],[`{{RESUME}}`,t.resume],[`{{CAMERA}}`,t.camera],[`{{MICROPHONE}}`,t.microphone],[`{{PROCESS_VIDEO}}`,t.processVideo],[`{{PROCESSING}}`,t.processing],[`{{UPLOADING}}`,t.uploading]])}let Ds=/^https?:\/\//i;function Os(e){return e?Ds.test(e)?e:`https://${e}`:`https://api.vidtreo.com`}function ks(e,n){let r={apiKey:e.getAttribute(`api-key`),backendUrl:Os(e.getAttribute(`backend-url`))},i=e.getAttribute(`countdown-duration`);if(i){let e=Number.parseInt(i,10);Number.isNaN(e)||(r.countdownDuration=e)}let a=e.getAttribute(`max-recording-time`);if(a){let e=Number.parseInt(a,10);Number.isNaN(e)||(r.maxRecordingTime=e)}let o=e.getAttribute(`user-metadata`);if(o)try{let e=JSON.parse(o);Object.assign(n,e),r.userMetadata=n}catch(e){throw Error(`Invalid user-metadata JSON: ${t(e)}`)}let s=e.getAttribute(`enable-source-switching`);r.enableSourceSwitching=s===null||s!==`false`;let c=e.getAttribute(`enable-mute`);r.enableMute=c===null||c!==`false`;let l=e.getAttribute(`enable-pause`);r.enablePause=l===null||l!==`false`;let u=e.getAttribute(`enable-device-change`);return r.enableDeviceChange=u===null||u!==`false`,r}var As=class extends HTMLElement{static{this.observedAttributes=[`api-key`,`backend-url`,`countdown-duration`,`max-recording-time`,`user-metadata`,`enable-source-switching`,`enable-mute`,`enable-pause`,`enable-device-change`,`lang`,`texts`]}constructor(){if(super(),this.recordedBlob=null,this.processedBlob=null,this.isProcessing=!1,this.isMuted=!1,this.showSettings=!1,this.userMetadata={},this.enableSourceSwitching=!0,this.enableMute=!0,this.enablePause=!0,this.enableDeviceChange=!0,this.attachShadow({mode:`open`}),!this.shadowRoot)throw Error(`Shadow root not initialized`);let e=this.getAttribute(`lang`)||`en`,t=this.getAttribute(`texts`);if(this.i18nManager=new vs(e,t?JSON.parse(t):{}),this.uiStateManager=new Ss(this.shadowRoot),this.audioLevelVisualizer=new bs,this.controller=new Wo(ts(this)),this.deviceManager=new xs(this.controller.getStreamManager(),void 0),os(this),!this.shadowRoot)throw Error(`Shadow root not initialized`);let n=Es(this.isMuted,this.i18nManager.getAll(),`camera`);this.shadowRoot.innerHTML=`<style>${Cs}</style>${n}`,ps(this)}async connectedCallback(){try{this.updateFeatureFlags();let e=ks(this,this.userMetadata);await this.controller.initialize(e),await this.checkPendingUploads(),this.initializeUIState(),this.startCamera().catch(e=>{this.uiStateManager.showError(t(e))})}catch(e){this.uiStateManager.showError(t(e))}}attributeChangedCallback(e,n,r){if(n===r)return;if(e===`lang`){this.i18nManager.setLang(r||`en`),this.updateTemplate();return}if(e===`texts`){let e=r?JSON.parse(r):{};this.i18nManager.setCustomTexts(e),this.updateTemplate();return}if(e===`enable-source-switching`||e===`enable-mute`||e===`enable-pause`||e===`enable-device-change`){this.updateFeatureFlags(),this.updateUIForFeatureFlags();return}let i=ks(this,this.userMetadata);this.controller.initialize(i).catch(e=>{this.uiStateManager.showError(t(e))})}disconnectedCallback(){this.controller.cleanup(),this.controller.getStreamManager().destroy()}get shadow(){if(!this.shadowRoot)throw Error(`Shadow root not initialized`);return this.shadowRoot}checkPendingUploads(){return Promise.resolve()}async startCamera(){let e=Qo(this.shadow,`#startCameraArea`);e.classList.add(`loading`);try{let t=this.controller.getDeviceManager(),n=t.getSelectedCameraDeviceId(),r=t.getSelectedMicDeviceId();if(this.deviceManager.setCameraDevice(n),this.deviceManager.setMicDevice(r),await this.controller.startStream(),!this.controller.getStream())throw Error(`Stream was not created after startStream()`);await this.deviceManager.getAvailableDevices(),this.deviceManager.updateDeviceSelects(this.shadow),e.classList.remove(`loading`)}catch(e){let n=Qo(this.shadow,`#startCameraArea`),r=Qo(this.shadow,`#startCameraButton`),i=n.querySelector(`.camera-text`);if(!i)throw Error(`Camera text element not found`);n.classList.remove(`loading`),n.style.display=`block`,r.style.display=`block`;let a=t(e);i.textContent=`${this.i18nManager.t(`failedToStartCamera`)}: ${a}`}}async startRecording(){await ss(this)}async stopRecording(){await cs(this)}pauseRecording(){this.enablePause&&ls(this)}resumeRecording(){this.enablePause&&us(this)}async processVideo(){await ds(this)}downloadVideo(){if(!this.processedBlob)throw Error(`No processed video available`);hs(this.processedBlob)}playVideo(){if(!this.processedBlob)throw Error(`No processed video available`);gs(this.processedBlob)}toggleMute(){this.enableMute&&(this.isMuted?(this.controller.unmuteAudio(),this.isMuted=!1):(this.controller.muteAudio(),this.isMuted=!0),this.uiStateManager.updateMuteState(this.isMuted,(e,t)=>this.audioLevelVisualizer.updateBars(e,t),this.controller.getAudioLevel()))}async toggleSource(){this.enableSourceSwitching&&await this.controller.switchSource(this.controller.getCurrentSourceType()===`camera`?`screen`:`camera`)}toggleSettings(){if(!this.enableDeviceChange)return;this.showSettings=!this.showSettings;let e=this.shadow.querySelector(`#settingsPanel`);if(!e)throw Error(`Settings panel element not found`);e.style.display=this.showSettings?`block`:`none`}async handleCameraChange(e){this.enableDeviceChange&&await is(this,e)}async handleMicChange(e){this.enableDeviceChange&&await as(this,e)}handleStateChange(e,t){e===`active`&&t===`starting`&&this.uiStateManager.hideError()}startAudioLevelTrackingForStream(e){try{this.controller.stopAudioLevelTracking(),this.audioLevelVisualizer.initializeBars(this.shadow),this.controller.startAudioLevelTracking(e,{onLevelUpdate:(e,t)=>{this.audioLevelVisualizer.updateBars(e,t)}}),this.uiStateManager.updateMuteState(this.isMuted,(e,t)=>{this.audioLevelVisualizer.updateBars(e,t)},this.controller.getAudioLevel())}catch(e){this.uiStateManager.showError(t(e))}}handleStreamStart(e){try{this.uiStateManager.updateVideoPreview(e),this.uiStateManager.handleStreamStart(this.controller.getRecordingState(),()=>{this.audioLevelVisualizer.initializeBars(this.shadow)}),this.updateUIForFeatureFlags();try{this.startAudioLevelTrackingForStream(e)}catch{}}catch(e){this.uiStateManager.showError(t(e))}}handleStreamStop(){this.uiStateManager.handleStreamStop(()=>this.controller.stopAudioLevelTracking())}handleRecordingStart(){if(this.showSettings){this.showSettings=!1;let e=this.shadow.querySelector(`#settingsPanel`);if(!e)throw Error(`Settings panel element not found`);e.style.display=`none`}this.uiStateManager.handleRecordingStart(this.controller.isPaused()),this.updateUIForFeatureFlags();let e=this.controller.getAudioStreamForAnalysis();e&&this.startAudioLevelTrackingForStream(e)}handleRecordingStop(e){return this.recordedBlob=e,this.uiStateManager.updateRecordingControlsAfterStop(),this.updateUIForFeatureFlags(),Promise.resolve()}updateRecordingTimer(e){this.uiStateManager.updateRecordingTimer(e)}updateMuteState(e){this.isMuted=e,this.uiStateManager.updateMuteState(e,(e,t)=>this.audioLevelVisualizer.updateBars(e,t),this.controller.getAudioLevel())}updateVideoPreview(e){this.uiStateManager.updateVideoPreview(e)}showError(e){this.uiStateManager.showError(e)}extractErrorMessage(e){return t(e)}getStreamManager(){return this.controller.getStreamManager()}getShadowRoot(){return this.shadow}getController(){return this.controller}getUIStateManager(){return this.uiStateManager}getDeviceManager(){return this.deviceManager}getAudioLevelVisualizer(){return this.audioLevelVisualizer}getRecordedBlob(){return this.recordedBlob}setRecordedBlob(e){this.recordedBlob=e}getProcessedBlob(){return this.processedBlob}setProcessedBlob(e){this.processedBlob=e}getIsProcessing(){return this.isProcessing}setIsProcessing(e){this.isProcessing=e}getIsMuted(){return this.isMuted}setIsMuted(e){this.isMuted=e}getShowSettings(){return this.showSettings}setShowSettings(e){this.showSettings=e}getUserMetadata(){return this.userMetadata}getNormalizedBackendUrl(e){return Os(e)}updateFeatureFlags(){let e=this.getAttribute(`enable-source-switching`);this.enableSourceSwitching=e===null||e!==`false`;let t=this.getAttribute(`enable-mute`);this.enableMute=t===null||t!==`false`;let n=this.getAttribute(`enable-pause`);this.enablePause=n===null||n!==`false`;let r=this.getAttribute(`enable-device-change`);this.enableDeviceChange=r===null||r!==`false`}initializeUIState(){let e=this.shadow.querySelector(`#muteButton`),t=this.shadow.querySelector(`#pauseButton`),n=this.shadow.querySelector(`#resumeButton`),r=this.shadow.querySelector(`#switchSourceButton`),i=this.shadow.querySelector(`#stopButton`),a=this.shadow.querySelector(`#settingsButton`);e&&(e.style.display=`none`),t&&(t.style.display=`none`),n&&(n.style.display=`none`),r&&(r.style.display=`none`),i&&(i.style.display=`none`),a&&(a.style.display=this.enableDeviceChange?`flex`:`none`)}updateUIForFeatureFlags(){let e=this.controller.getRecordingState()===`recording`,t=this.controller.isPaused();this.updateButtonVisibility(`#switchSourceButton`,e&&this.enableSourceSwitching),this.updateButtonVisibility(`#muteButton`,e&&this.enableMute),this.updateButtonVisibility(`#pauseButton`,e&&this.enablePause&&!t),this.updateButtonVisibility(`#resumeButton`,e&&this.enablePause&&t),this.updateButtonVisibility(`#settingsButton`,!e&&this.enableDeviceChange)}updateButtonVisibility(e,t){let n=this.shadow.querySelector(e);n&&(n.style.display=t?`flex`:`none`)}getEnableSourceSwitching(){return this.enableSourceSwitching}getEnableMute(){return this.enableMute}getEnablePause(){return this.enablePause}getEnableDeviceChange(){return this.enableDeviceChange}getI18nManager(){return this.i18nManager}updateTemplate(){if(!this.shadowRoot)return;let e=Es(this.isMuted,this.i18nManager.getAll(),this.controller.getCurrentSourceType());this.shadowRoot.innerHTML=`<style>${Cs}</style>${e}`,ps(this),this.uiStateManager.setShadowRoot(this.shadowRoot),this.initializeUIState(),this.controller.getStreamManager().getStream()&&this.uiStateManager.updateVideoPreview(this.controller.getStreamManager().getStream())}};return customElements.get(`vidtreo-recorder`)||customElements.define(`vidtreo-recorder`,As),e.VidtreoRecorder=As,e})({});
8065
+ `;function Ts(e,t){return t.reduce((e,[t,n])=>e.split(t).join(n),e)}function Es(e,t,n=`camera`){return Ts(ws,[[`{{MUTE_ICON_PLACEHOLDER}}`,e?`<path d="M211,221.31,51,45.31A4,4,0,0,0,45,50.69L84,93.55V128a44,44,0,0,0,66,38.12l16.38,18A67.21,67.21,0,0,1,128,196a68.07,68.07,0,0,1-68-68,4,4,0,0,0-8,0,76.09,76.09,0,0,0,72,75.89V240a4,4,0,0,0,8,0V203.89a75.1,75.1,0,0,0,39.79-13.77L205,226.69a4,4,0,1,0,5.92-5.38ZM128,164a36,36,0,0,1-36-36V102.35L144.43,160A35.83,35.83,0,0,1,128,164Zm61.12-6.15A67.44,67.44,0,0,0,196,128a4,4,0,0,1,8,0,75.28,75.28,0,0,1-7.7,33.37,4,4,0,0,1-7.18-3.52ZM87.63,46.46A44,44,0,0,1,172,64v64a44.2,44.2,0,0,1-.24,4.61,4,4,0,0,1-4,3.58l-.42,0a4,4,0,0,1-3.57-4.39A36.67,36.67,0,0,0,164,128V64A36,36,0,0,0,95,49.66a4,4,0,0,1-7.34-3.2Z"></path>`:`<path d="M128,172a44.05,44.05,0,0,0,44-44V64a44,44,0,0,0-88,0v64A44.05,44.05,0,0,0,128,172ZM92,64a36,36,0,0,1,72,0v64a36,36,0,0,1-72,0Zm40,139.89V240a4,4,0,0,1-8,0V203.89A76.09,76.09,0,0,1,52,128a4,4,0,0,1,8,0,68,68,0,0,0,136,0,4,4,0,0,1,8,0A76.09,76.09,0,0,1,132,203.89Z"></path>`],[`{{SWITCH_SOURCE_ICON_PLACEHOLDER}}`,n===`camera`?`<rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/>`:`<path d="M17 17H4a2 2 0 0 1-2-2V5c0-1.5 1-2 1-2"/><path d="M22 15V5a2 2 0 0 0-2-2H9"/><path d="M8 21h8"/><path d="M12 17v4"/><path d="m2 2 20 20"/>`],[`{{TITLE}}`,t.title],[`{{SUBTITLE}}`,t.subtitle],[`{{INITIALIZING_CAMERA}}`,t.initializingCamera],[`{{GRANT_PERMISSIONS}}`,t.grantPermissions],[`{{RETRY_CAMERA}}`,t.retryCamera],[`{{SWITCHING_DEVICE}}`,t.switchingDevice],[`{{RECORDING_STARTS_IN}}`,t.recordingStartsIn],[`{{SWITCHING_SOURCE}}`,t.switchingSource],[`{{REC}}`,t.rec],[`{{SETTINGS}}`,t.settings],[`{{RECORD}}`,t.record],[`{{STOP}}`,t.stop],[`{{PAUSE}}`,t.pause],[`{{RESUME}}`,t.resume],[`{{CAMERA}}`,t.camera],[`{{MICROPHONE}}`,t.microphone],[`{{PROCESS_VIDEO}}`,t.processVideo],[`{{PROCESSING}}`,t.processing],[`{{UPLOADING}}`,t.uploading]])}let Ds=/^https?:\/\//i;function Os(e){return e?Ds.test(e)?e:`https://${e}`:`https://api.vidtreo.com`}function ks(e,n){let r={apiKey:e.getAttribute(`api-key`),backendUrl:Os(e.getAttribute(`backend-url`))},i=e.getAttribute(`countdown-duration`);if(i){let e=Number.parseInt(i,10);Number.isNaN(e)||(r.countdownDuration=e)}let a=e.getAttribute(`max-recording-time`);if(a){let e=Number.parseInt(a,10);Number.isNaN(e)||(r.maxRecordingTime=e)}let o=e.getAttribute(`user-metadata`);if(o)try{let e=JSON.parse(o);Object.assign(n,e),r.userMetadata=n}catch(e){throw Error(`Invalid user-metadata JSON: ${t(e)}`)}let s=e.getAttribute(`enable-source-switching`);r.enableSourceSwitching=s===null||s!==`false`;let c=e.getAttribute(`enable-mute`);r.enableMute=c===null||c!==`false`;let l=e.getAttribute(`enable-pause`);r.enablePause=l===null||l!==`false`;let u=e.getAttribute(`enable-device-change`);return r.enableDeviceChange=u===null||u!==`false`,r}var As=class extends HTMLElement{static{this.observedAttributes=[`api-key`,`backend-url`,`countdown-duration`,`max-recording-time`,`user-metadata`,`enable-source-switching`,`enable-mute`,`enable-pause`,`enable-device-change`,`lang`,`texts`]}constructor(){if(super(),this.recordedBlob=null,this.processedBlob=null,this.isProcessing=!1,this.isMuted=!1,this.showSettings=!1,this.userMetadata={},this.enableSourceSwitching=!0,this.enableMute=!0,this.enablePause=!0,this.enableDeviceChange=!0,this.attachShadow({mode:`open`}),!this.shadowRoot)throw Error(`Shadow root not initialized`);let e=this.getAttribute(`lang`)||`en`,t=this.getAttribute(`texts`);if(this.i18nManager=new vs(e,t?JSON.parse(t):{}),this.uiStateManager=new Ss(this.shadowRoot),this.audioLevelVisualizer=new bs,this.controller=new Wo(ts(this)),this.deviceManager=new xs(this.controller.getStreamManager(),void 0),os(this),!this.shadowRoot)throw Error(`Shadow root not initialized`);let n=Es(this.isMuted,this.i18nManager.getAll(),`camera`);this.shadowRoot.innerHTML=`<style>${Cs}</style>${n}`,ps(this)}async connectedCallback(){try{this.updateFeatureFlags();let e=ks(this,this.userMetadata);await this.controller.initialize(e),await this.checkPendingUploads(),this.initializeUIState(),this.startCamera().catch(e=>{this.uiStateManager.showError(t(e))})}catch(e){this.uiStateManager.showError(t(e))}}attributeChangedCallback(e,n,r){if(n===r)return;if(e===`lang`){this.i18nManager.setLang(r||`en`),this.updateTemplate();return}if(e===`texts`){let e=r?JSON.parse(r):{};this.i18nManager.setCustomTexts(e),this.updateTemplate();return}if(e===`enable-source-switching`||e===`enable-mute`||e===`enable-pause`||e===`enable-device-change`){this.updateFeatureFlags(),this.updateUIForFeatureFlags();return}let i=ks(this,this.userMetadata);this.controller.initialize(i).catch(e=>{this.uiStateManager.showError(t(e))})}disconnectedCallback(){this.controller.cleanup(),this.controller.getStreamManager().destroy()}get shadow(){if(!this.shadowRoot)throw Error(`Shadow root not initialized`);return this.shadowRoot}checkPendingUploads(){return Promise.resolve()}async startCamera(){let e=Qo(this.shadow,`#startCameraArea`);e.classList.add(`vidtreo-loading`);try{let t=this.controller.getDeviceManager(),n=t.getSelectedCameraDeviceId(),r=t.getSelectedMicDeviceId();if(this.deviceManager.setCameraDevice(n),this.deviceManager.setMicDevice(r),await this.controller.startStream(),!this.controller.getStream())throw Error(`Stream was not created after startStream()`);await this.deviceManager.getAvailableDevices(),this.deviceManager.updateDeviceSelects(this.shadow),e.classList.remove(`vidtreo-loading`)}catch(e){let n=Qo(this.shadow,`#startCameraArea`),r=Qo(this.shadow,`#startCameraButton`),i=n.querySelector(`.vidtreo-camera-text`);if(!i)throw Error(`Camera text element not found`);n.classList.remove(`vidtreo-loading`),n.style.display=`block`,r.style.display=`block`;let a=t(e);i.textContent=`${this.i18nManager.t(`failedToStartCamera`)}: ${a}`}}async startRecording(){await ss(this)}async stopRecording(){await cs(this)}pauseRecording(){this.enablePause&&ls(this)}resumeRecording(){this.enablePause&&us(this)}async processVideo(){await ds(this)}downloadVideo(){if(!this.processedBlob)throw Error(`No processed video available`);hs(this.processedBlob)}playVideo(){if(!this.processedBlob)throw Error(`No processed video available`);gs(this.processedBlob)}toggleMute(){this.enableMute&&(this.isMuted?(this.controller.unmuteAudio(),this.isMuted=!1):(this.controller.muteAudio(),this.isMuted=!0),this.uiStateManager.updateMuteState(this.isMuted,(e,t)=>this.audioLevelVisualizer.updateBars(e,t),this.controller.getAudioLevel()))}async toggleSource(){this.enableSourceSwitching&&await this.controller.switchSource(this.controller.getCurrentSourceType()===`camera`?`screen`:`camera`)}toggleSettings(){if(!this.enableDeviceChange)return;this.showSettings=!this.showSettings;let e=this.shadow.querySelector(`#settingsPanel`);if(!e)throw Error(`Settings panel element not found`);e.style.display=this.showSettings?`block`:`none`}async handleCameraChange(e){this.enableDeviceChange&&await is(this,e)}async handleMicChange(e){this.enableDeviceChange&&await as(this,e)}handleStateChange(e,t){e===`active`&&t===`starting`&&this.uiStateManager.hideError()}startAudioLevelTrackingForStream(e){try{this.controller.stopAudioLevelTracking(),this.audioLevelVisualizer.initializeBars(this.shadow),this.controller.startAudioLevelTracking(e,{onLevelUpdate:(e,t)=>{this.audioLevelVisualizer.updateBars(e,t)}}),this.uiStateManager.updateMuteState(this.isMuted,(e,t)=>{this.audioLevelVisualizer.updateBars(e,t)},this.controller.getAudioLevel())}catch(e){this.uiStateManager.showError(t(e))}}handleStreamStart(e){try{this.uiStateManager.updateVideoPreview(e),this.uiStateManager.handleStreamStart(this.controller.getRecordingState(),()=>{this.audioLevelVisualizer.initializeBars(this.shadow)}),this.updateUIForFeatureFlags();try{this.startAudioLevelTrackingForStream(e)}catch{}}catch(e){this.uiStateManager.showError(t(e))}}handleStreamStop(){this.uiStateManager.handleStreamStop(()=>this.controller.stopAudioLevelTracking())}handleRecordingStart(){if(this.showSettings){this.showSettings=!1;let e=this.shadow.querySelector(`#settingsPanel`);if(!e)throw Error(`Settings panel element not found`);e.style.display=`none`}this.uiStateManager.handleRecordingStart(this.controller.isPaused()),this.updateUIForFeatureFlags();let e=this.controller.getAudioStreamForAnalysis();e&&this.startAudioLevelTrackingForStream(e)}handleRecordingStop(e){return this.recordedBlob=e,this.uiStateManager.updateRecordingControlsAfterStop(),this.updateUIForFeatureFlags(),Promise.resolve()}updateRecordingTimer(e){this.uiStateManager.updateRecordingTimer(e)}updateMuteState(e){this.isMuted=e,this.uiStateManager.updateMuteState(e,(e,t)=>this.audioLevelVisualizer.updateBars(e,t),this.controller.getAudioLevel())}updateVideoPreview(e){this.uiStateManager.updateVideoPreview(e)}showError(e){this.uiStateManager.showError(e)}extractErrorMessage(e){return t(e)}getStreamManager(){return this.controller.getStreamManager()}getShadowRoot(){return this.shadow}getController(){return this.controller}getUIStateManager(){return this.uiStateManager}getDeviceManager(){return this.deviceManager}getAudioLevelVisualizer(){return this.audioLevelVisualizer}getRecordedBlob(){return this.recordedBlob}setRecordedBlob(e){this.recordedBlob=e}getProcessedBlob(){return this.processedBlob}setProcessedBlob(e){this.processedBlob=e}getIsProcessing(){return this.isProcessing}setIsProcessing(e){this.isProcessing=e}getIsMuted(){return this.isMuted}setIsMuted(e){this.isMuted=e}getShowSettings(){return this.showSettings}setShowSettings(e){this.showSettings=e}getUserMetadata(){return this.userMetadata}getNormalizedBackendUrl(e){return Os(e)}updateFeatureFlags(){let e=this.getAttribute(`enable-source-switching`);this.enableSourceSwitching=e===null||e!==`false`;let t=this.getAttribute(`enable-mute`);this.enableMute=t===null||t!==`false`;let n=this.getAttribute(`enable-pause`);this.enablePause=n===null||n!==`false`;let r=this.getAttribute(`enable-device-change`);this.enableDeviceChange=r===null||r!==`false`}initializeUIState(){let e=this.shadow.querySelector(`#muteButton`),t=this.shadow.querySelector(`#pauseButton`),n=this.shadow.querySelector(`#resumeButton`),r=this.shadow.querySelector(`#switchSourceButton`),i=this.shadow.querySelector(`#stopButton`),a=this.shadow.querySelector(`#settingsButton`);e&&(e.style.display=`none`),t&&(t.style.display=`none`),n&&(n.style.display=`none`),r&&(r.style.display=`none`),i&&(i.style.display=`none`),a&&(a.style.display=this.enableDeviceChange?`flex`:`none`)}updateUIForFeatureFlags(){let e=this.controller.getRecordingState()===`recording`,t=this.controller.isPaused();this.updateButtonVisibility(`#switchSourceButton`,e&&this.enableSourceSwitching),this.updateButtonVisibility(`#muteButton`,e&&this.enableMute),this.updateButtonVisibility(`#pauseButton`,e&&this.enablePause&&!t),this.updateButtonVisibility(`#resumeButton`,e&&this.enablePause&&t),this.updateButtonVisibility(`#settingsButton`,!e&&this.enableDeviceChange)}updateButtonVisibility(e,t){let n=this.shadow.querySelector(e);n&&(n.style.display=t?`flex`:`none`)}getEnableSourceSwitching(){return this.enableSourceSwitching}getEnableMute(){return this.enableMute}getEnablePause(){return this.enablePause}getEnableDeviceChange(){return this.enableDeviceChange}getI18nManager(){return this.i18nManager}updateTemplate(){if(!this.shadowRoot)return;let e=Es(this.isMuted,this.i18nManager.getAll(),this.controller.getCurrentSourceType());this.shadowRoot.innerHTML=`<style>${Cs}</style>${e}`,ps(this),this.uiStateManager.setShadowRoot(this.shadowRoot),this.initializeUIState(),this.controller.getStreamManager().getStream()&&this.uiStateManager.updateVideoPreview(this.controller.getStreamManager().getStream())}};return customElements.get(`vidtreo-recorder`)||customElements.define(`vidtreo-recorder`,As),e.VidtreoRecorder=As,e})({});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vidtreo/recorder-wc",
3
- "version": "0.8.4",
3
+ "version": "0.8.5",
4
4
  "type": "module",
5
5
  "description": "Web component for @vidtreo/recorder - video recording SDK",
6
6
  "main": "./dist/vidtreo-recorder.js",