@vidtreo/recorder-wc 1.2.0 → 1.2.1

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.
@@ -105,7 +105,7 @@ Tracks were discarded because your environment is not able to encode any of the
105
105
  The @mediabunny/mp3-encoder extension package provides support for encoding MP3.`)}else e.push(`
106
106
  Check the discardedTracks field for more info.`)}return e}async execute(){if(!this.isValid)throw Error(`Cannot execute this conversion because its output configuration is invalid. Make sure to always check the isValid field before executing a conversion.
107
107
  `+this._getInvalidityExplanation().join(``));if(this._executed)throw Error(`Conversion cannot be executed twice.`);if(this._executed=!0,this.onProgress){let e=this.utilizedTracks.map(e=>e.computeDuration()),t=Math.max(0,...await Promise.all(e));this._computeProgress=!0,this._totalDuration=Math.min(t-this._startTimestamp,this._endTimestamp-this._startTimestamp);for(let e of this.utilizedTracks)this._maxTimestamps.set(e.id,0);this.onProgress?.(0)}await this.output.start(),this._start();try{await Promise.all(this._trackPromises)}catch(e){throw this._canceled||this.cancel(),e}if(this._canceled)throw new qp;await this.output.finalize(),this._computeProgress&&this.onProgress?.(1)}async cancel(){if(!(this.output.state===`finalizing`||this.output.state===`finalized`)){if(this._canceled){console.warn(`Conversion already canceled.`);return}this._canceled=!0,await this.output.cancel()}}async _processVideoTrack(e,t){let n=e.codec;if(!n){this.discardedTracks.push({track:e,reason:`unknown_source_codec`});return}let r,i=Ht(e.rotation+(t.rotate??0)),a=this.output.format.supportsVideoRotationMetadata&&(t.allowRotationMetadata??!0),[o,s]=i%180==0?[e.codedWidth,e.codedHeight]:[e.codedHeight,e.codedWidth],c=t.crop;c&&ua(c,o,s);let[l,u]=c?[c.width,c.height]:[o,s],d=l,f=u,p=d/f,m=e=>Math.ceil(e/2)*2;t.width!==void 0&&t.height===void 0?(d=m(t.width),f=m(Math.round(d/p))):t.width===void 0&&t.height!==void 0?(f=m(t.height),d=m(Math.round(f*p))):t.width!==void 0&&t.height!==void 0&&(d=m(t.width),f=m(t.height));let h=await e.getFirstTimestamp(),g=!!t.forceTranscode||h<this._startTimestamp||!!t.frameRate||t.keyFrameInterval!==void 0||t.process!==void 0,_=d!==l||f!==u||i!==0&&(!a||t.process!==void 0)||!!c,ee=t.alpha??`discard`,v=this.output.format.getSupportedVideoCodecs();if(!g&&!t.bitrate&&!_&&v.includes(n)&&(!t.codec||t.codec===n)){let t=new gp(n);r=t,this._trackPromises.push((async()=>{await this._started;let n=new Da(e),r={decoderConfig:await e.getDecoderConfig()??void 0},i=Number.isFinite(this._endTimestamp)?await n.getPacket(this._endTimestamp,{metadataOnly:!0})??void 0:void 0;for await(let a of n.packets(void 0,i,{verifyKeyPackets:!0})){if(this._canceled)return;let n=a.clone({timestamp:a.timestamp-this._startTimestamp,sideData:ee===`discard`?{}:a.sideData});D(n.timestamp>=0),this._reportProgress(e.id,n.timestamp),await t.add(n,r),this._synchronizer.shouldWait(e.id,n.timestamp)&&await this._synchronizer.wait(n.timestamp)}t.close(),this._synchronizer.closeTrack(e.id)})())}else{if(!await e.canDecode()){this.discardedTracks.push({track:e,reason:`undecodable_source_codec`});return}t.codec&&(v=v.filter(e=>e===t.codec));let n=t.bitrate??ep,a=await up(v,{width:t.process&&t.processedWidth?t.processedWidth:d,height:t.process&&t.processedHeight?t.processedHeight:f,bitrate:n});if(!a){this.discardedTracks.push({track:e,reason:`no_encodable_target_codec`});return}let o={codec:a,bitrate:n,keyFrameInterval:t.keyFrameInterval,sizeChangeBehavior:t.fit??`passThrough`,alpha:ee,hardwareAcceleration:t.hardwareAcceleration},s=new yp(o);if(r=s,!_){let t=new Bp({format:new Nf,target:new Ud}),n=new yp(o);t.addVideoTrack(n),await t.start();let r=await new Na(e).getSample(h);if(r)try{await n.add(r),r.close(),await t.finalize()}catch(e){console.info(`Error when probing encoder support. Falling back to rerender path.`,e),_=!0,t.cancel()}else await t.cancel()}_?this._trackPromises.push((async()=>{await this._started;let n=new Pa(e,{width:d,height:f,fit:t.fit??`fill`,rotation:i,crop:t.crop,poolSize:1,alpha:ee===`keep`}).canvases(this._startTimestamp,this._endTimestamp),r=t.frameRate,a=null,o=null,c=null,l=async n=>{D(a),D(r!==void 0);let i=Math.round((n-o)*r);for(let n=1;n<i;n++){let i=new sa(a,{timestamp:o+n/r,duration:1/r});await this._registerVideoSample(e,t,s,i),i.close()}};for await(let{canvas:i,timestamp:u,duration:d}of n){if(this._canceled)return;let n=Math.max(u-this._startTimestamp,0);if(c=n+d,r!==void 0){let e=Math.floor(n*r)/r;if(a!==null)if(e<=o){a=i,o=e;continue}else await l(e);n=e}let f=new sa(i,{timestamp:n,duration:r===void 0?d:1/r});await this._registerVideoSample(e,t,s,f),f.close(),r!==void 0&&(a=i,o=n)}a&&(D(c!==null),D(r!==void 0),await l(Math.floor(c*r)/r)),s.close(),this._synchronizer.closeTrack(e.id)})()):this._trackPromises.push((async()=>{await this._started;let n=new Na(e),r=t.frameRate,i=null,a=null,o=null,c=async n=>{D(i),D(r!==void 0);let o=Math.round((n-a)*r);for(let n=1;n<o;n++)i.setTimestamp(a+n/r),i.setDuration(1/r),await this._registerVideoSample(e,t,s,i);i.close()};for await(let l of n.samples(this._startTimestamp,this._endTimestamp)){if(this._canceled){l.close(),i?.close();return}let n=Math.max(l.timestamp-this._startTimestamp,0);if(o=n+l.duration,r!==void 0){let e=Math.floor(n*r)/r;if(i!==null)if(e<=a){i.close(),i=l,a=e;continue}else await c(e);n=e,l.setDuration(1/r)}l.setTimestamp(n),await this._registerVideoSample(e,t,s,l),r===void 0?l.close():(i=l,a=n)}i&&(D(o!==null),D(r!==void 0),await c(Math.floor(o*r)/r)),s.close(),this._synchronizer.closeTrack(e.id)})())}this.output.addVideoTrack(r,{frameRate:t.frameRate,languageCode:Dn(e.languageCode)?e.languageCode:void 0,name:e.name??void 0,disposition:e.disposition,rotation:_?0:i}),this._addedCounts.video++,this._totalTrackCount++,this.utilizedTracks.push(e)}async _registerVideoSample(e,t,n,r){if(this._canceled)return;this._reportProgress(e.id,r.timestamp);let i;if(!t.process)i=[r];else{let e=t.process(r);e instanceof Promise&&(e=await e),Array.isArray(e)||(e=e===null?[]:[e]),i=e.map(e=>e instanceof sa?e:typeof VideoFrame<`u`&&e instanceof VideoFrame?new sa(e):new sa(e,{timestamp:r.timestamp,duration:r.duration}))}for(let t of i){if(this._canceled)break;await n.add(t),this._synchronizer.shouldWait(e.id,t.timestamp)&&await this._synchronizer.wait(t.timestamp)}for(let e of i)e!==r&&e.close()}async _processAudioTrack(e,t){let n=e.codec;if(!n){this.discardedTracks.push({track:e,reason:`unknown_source_codec`});return}let r,i=e.numberOfChannels,a=e.sampleRate,o=await e.getFirstTimestamp(),s=t.numberOfChannels??i,c=t.sampleRate??a,l=s!==i||c!==a||o<this._startTimestamp,u=this.output.format.getSupportedAudioCodecs();if(!t.forceTranscode&&!t.bitrate&&!l&&u.includes(n)&&(!t.codec||t.codec===n)&&!t.process){let t=new Cp(n);r=t,this._trackPromises.push((async()=>{await this._started;let n=new Da(e),r={decoderConfig:await e.getDecoderConfig()??void 0},i=Number.isFinite(this._endTimestamp)?await n.getPacket(this._endTimestamp,{metadataOnly:!0})??void 0:void 0;for await(let a of n.packets(void 0,i)){if(this._canceled)return;let n=a.clone({timestamp:a.timestamp-this._startTimestamp});D(n.timestamp>=0),this._reportProgress(e.id,n.timestamp),await t.add(n,r),this._synchronizer.shouldWait(e.id,n.timestamp)&&await this._synchronizer.wait(n.timestamp)}t.close(),this._synchronizer.closeTrack(e.id)})())}else{if(!await e.canDecode()){this.discardedTracks.push({track:e,reason:`undecodable_source_codec`});return}let n=null;t.codec&&(u=u.filter(e=>e===t.codec));let i=t.bitrate??ep,a=await cp(u,{numberOfChannels:t.process&&t.processedNumberOfChannels?t.processedNumberOfChannels:s,sampleRate:t.process&&t.processedSampleRate?t.processedSampleRate:c,bitrate:i});if(!a.some(e=>ar.includes(e))&&u.some(e=>ar.includes(e))&&(s!==Wp||c!==Gp)){let e=(await cp(u,{numberOfChannels:Wp,sampleRate:Gp,bitrate:i})).find(e=>ar.includes(e));e&&(l=!0,n=e,s=Wp,c=Gp)}else n=a[0]??null;if(n===null){this.discardedTracks.push({track:e,reason:`no_encodable_target_codec`});return}if(l)r=this._resampleAudio(e,t,n,s,c,i);else{let a=new Tp({codec:n,bitrate:i});r=a,this._trackPromises.push((async()=>{await this._started;let n=new La(e);for await(let r of n.samples(void 0,this._endTimestamp)){if(this._canceled){r.close();return}r.setTimestamp(r.timestamp-this._startTimestamp),await this._registerAudioSample(e,t,a,r),r.close()}a.close(),this._synchronizer.closeTrack(e.id)})())}}this.output.addAudioTrack(r,{languageCode:Dn(e.languageCode)?e.languageCode:void 0,name:e.name??void 0,disposition:e.disposition}),this._addedCounts.audio++,this._totalTrackCount++,this.utilizedTracks.push(e)}async _registerAudioSample(e,t,n,r){if(this._canceled)return;this._reportProgress(e.id,r.timestamp);let i;if(!t.process)i=[r];else{let e=t.process(r);if(e instanceof Promise&&(e=await e),Array.isArray(e)||(e=e===null?[]:[e]),!e.every(e=>e instanceof ga))throw TypeError(`The audio process function must return an AudioSample, null, or an array of AudioSamples.`);i=e}for(let t of i){if(this._canceled)break;await n.add(t),this._synchronizer.shouldWait(e.id,t.timestamp)&&await this._synchronizer.wait(t.timestamp)}for(let e of i)e!==r&&e.close()}_resampleAudio(e,t,n,r,i,a){let o=new Tp({codec:n,bitrate:a});return this._trackPromises.push((async()=>{await this._started;let n=new Xp({targetNumberOfChannels:r,targetSampleRate:i,startTime:this._startTimestamp,endTime:this._endTimestamp,onSample:async n=>{await this._registerAudioSample(e,t,o,n),n.close()}}),a=new La(e).samples(this._startTimestamp,this._endTimestamp);for await(let e of a){if(this._canceled){e.close();return}await n.add(e),e.close()}await n.finalize(),o.close(),this._synchronizer.closeTrack(e.id)})()),o}_reportProgress(e,t){if(!this._computeProgress)return;D(this._totalDuration!==null),this._maxTimestamps.set(e,Math.max(t,this._maxTimestamps.get(e)));let n=bn(Math.min(...this._maxTimestamps.values())/this._totalDuration,0,1);n!==this._lastProgress&&(this._lastProgress=n,this.onProgress?.(n))}},qp=class extends Error{constructor(e=`Conversion has been canceled.`){super(e),this.name=`ConversionCanceledError`}},Jp=5,Yp=class{constructor(){this.maxTimestamps=new Map,this.resolvers=[]}computeMinAndMaybeResolve(){let e=1/0;for(let[,t]of this.maxTimestamps)e=Math.min(e,t);for(let t=0;t<this.resolvers.length;t++){let n=this.resolvers[t];n.timestamp-e<Jp&&(n.resolve(),this.resolvers.splice(t,1),t--)}return e}shouldWait(e,t){return this.maxTimestamps.set(e,Math.max(t,this.maxTimestamps.get(e)??-1/0)),t-this.computeMinAndMaybeResolve()>=Jp}wait(e){let{promise:t,resolve:n}=F();return this.resolvers.push({timestamp:e,resolve:n}),t}closeTrack(e){this.maxTimestamps.delete(e),this.computeMinAndMaybeResolve()}},Xp=class{constructor(e){this.sourceSampleRate=null,this.sourceNumberOfChannels=null,this.targetSampleRate=e.targetSampleRate,this.targetNumberOfChannels=e.targetNumberOfChannels,this.startTime=e.startTime,this.endTime=e.endTime,this.onSample=e.onSample,this.bufferSizeInFrames=Math.floor(this.targetSampleRate*5),this.bufferSizeInSamples=this.bufferSizeInFrames*this.targetNumberOfChannels,this.outputBuffer=new Float32Array(this.bufferSizeInSamples),this.bufferStartFrame=0,this.maxWrittenFrame=-1}doChannelMixerSetup(){D(this.sourceNumberOfChannels!==null);let e=this.sourceNumberOfChannels,t=this.targetNumberOfChannels;e===1&&t===2?this.channelMixer=(t,n)=>t[n*e]:e===1&&t===4?this.channelMixer=(t,n,r)=>t[n*e]*+(r<2):e===1&&t===6?this.channelMixer=(t,n,r)=>t[n*e]*+(r===2):e===2&&t===1?this.channelMixer=(t,n)=>{let r=n*e;return .5*(t[r]+t[r+1])}:e===2&&t===4||e===2&&t===6?this.channelMixer=(t,n,r)=>t[n*e+r]*+(r<2):e===4&&t===1?this.channelMixer=(t,n)=>{let r=n*e;return .25*(t[r]+t[r+1]+t[r+2]+t[r+3])}:e===4&&t===2?this.channelMixer=(t,n,r)=>{let i=n*e;return .5*(t[i+r]+t[i+r+2])}:e===4&&t===6?this.channelMixer=(t,n,r)=>{let i=n*e;return r<2?t[i+r]:r===2||r===3?0:t[i+r-2]}:e===6&&t===1?this.channelMixer=(t,n)=>{let r=n*e;return Math.SQRT1_2*(t[r]+t[r+1])+t[r+2]+.5*(t[r+4]+t[r+5])}:e===6&&t===2?this.channelMixer=(t,n,r)=>{let i=n*e;return t[i+r]+Math.SQRT1_2*(t[i+2]+t[i+r+4])}:e===6&&t===4?this.channelMixer=(t,n,r)=>{let i=n*e;return r<2?t[i+r]+Math.SQRT1_2*t[i+2]:t[i+r+2]}:this.channelMixer=(t,n,r)=>r<e?t[n*e+r]:0}ensureTempBufferSize(e){let t=this.tempSourceBuffer.length;for(;t<e;)t*=2;if(t!==this.tempSourceBuffer.length){let e=new Float32Array(t);e.set(this.tempSourceBuffer),this.tempSourceBuffer=e}}async add(e){this.sourceSampleRate===null&&(this.sourceSampleRate=e.sampleRate,this.sourceNumberOfChannels=e.numberOfChannels,this.tempSourceBuffer=new Float32Array(this.sourceSampleRate*this.sourceNumberOfChannels),this.doChannelMixerSetup());let t=e.numberOfFrames*e.numberOfChannels;this.ensureTempBufferSize(t);let n=e.allocationSize({planeIndex:0,format:`f32`}),r=new Float32Array(this.tempSourceBuffer.buffer,0,n/4);e.copyTo(r,{planeIndex:0,format:`f32`});let i=e.timestamp-this.startTime,a=e.numberOfFrames/this.sourceSampleRate,o=Math.min(i+a,this.endTime-this.startTime),s=Math.floor(i*this.targetSampleRate),c=Math.ceil(o*this.targetSampleRate);for(let t=s;t<c;t++){if(t<this.bufferStartFrame)continue;for(;t>=this.bufferStartFrame+this.bufferSizeInFrames;)await this.finalizeCurrentBuffer(),this.bufferStartFrame+=this.bufferSizeInFrames;let n=t-this.bufferStartFrame;D(n<this.bufferSizeInFrames);let a=(t/this.targetSampleRate-i)*this.sourceSampleRate,o=Math.floor(a),s=Math.ceil(a),c=a-o;for(let t=0;t<this.targetNumberOfChannels;t++){let i=0,a=0;o>=0&&o<e.numberOfFrames&&(i=this.channelMixer(r,o,t)),s>=0&&s<e.numberOfFrames&&(a=this.channelMixer(r,s,t));let l=i+c*(a-i),u=n*this.targetNumberOfChannels+t;this.outputBuffer[u]+=l}this.maxWrittenFrame=Math.max(this.maxWrittenFrame,n)}}async finalizeCurrentBuffer(){if(this.maxWrittenFrame<0)return;let e=(this.maxWrittenFrame+1)*this.targetNumberOfChannels,t=new Float32Array(e);t.set(this.outputBuffer.subarray(0,e));let n=this.bufferStartFrame/this.targetSampleRate,r=new ga({format:`f32`,sampleRate:this.targetSampleRate,numberOfChannels:this.targetNumberOfChannels,timestamp:n,data:t});await this.onSample(r),this.outputBuffer.fill(0),this.maxWrittenFrame=-1}finalize(){return this.finalizeCurrentBuffer()}}})),Qp=r({ADTS:()=>Dc,ALL_FORMATS:()=>Ac,ALL_TRACK_TYPES:()=>Rp,AUDIO_CODECS:()=>or,AdtsInputFormat:()=>vc,AdtsOutputFormat:()=>Bf,AttachedFile:()=>Qn,AudioBufferSink:()=>Ra,AudioBufferSource:()=>Ep,AudioSample:()=>ga,AudioSampleSink:()=>La,AudioSampleSource:()=>Tp,AudioSource:()=>Sp,BaseMediaSampleSink:()=>ka,BlobSource:()=>Lc,BufferSource:()=>Ic,BufferTarget:()=>Bd,CanvasSink:()=>Pa,CanvasSource:()=>bp,Conversion:()=>Kp,ConversionCanceledError:()=>qp,CustomAudioDecoder:()=>zi,CustomAudioEncoder:()=>Vi,CustomVideoDecoder:()=>Ri,CustomVideoEncoder:()=>Bi,EncodedAudioPacketSource:()=>Cp,EncodedPacket:()=>B,EncodedPacketSink:()=>Da,EncodedVideoPacketSource:()=>gp,FLAC:()=>Oc,FilePathSource:()=>Vc,FilePathTarget:()=>Hd,FlacInputFormat:()=>_c,FlacOutputFormat:()=>Vf,Input:()=>qc,InputAudioTrack:()=>Ha,InputDisposedError:()=>Jc,InputFormat:()=>cc,InputTrack:()=>Ba,InputVideoTrack:()=>Va,IsobmffInputFormat:()=>lc,IsobmffOutputFormat:()=>Mf,MATROSKA:()=>Sc,MP3:()=>wc,MP4:()=>bc,MPEG_TS:()=>kc,MatroskaInputFormat:()=>fc,MediaSource:()=>mp,MediaStreamAudioTrackSource:()=>Dp,MediaStreamVideoTrackSource:()=>xp,MkvOutputFormat:()=>Ff,MovOutputFormat:()=>Pf,Mp3InputFormat:()=>mc,Mp3OutputFormat:()=>Lf,Mp4InputFormat:()=>uc,Mp4OutputFormat:()=>Nf,MpegTsInputFormat:()=>yc,MpegTsOutputFormat:()=>Hf,NON_PCM_AUDIO_CODECS:()=>ar,NullTarget:()=>Ud,OGG:()=>Ec,OggInputFormat:()=>gc,OggOutputFormat:()=>zf,Output:()=>Bp,OutputFormat:()=>jf,PCM_AUDIO_CODECS:()=>L,QTFF:()=>xc,QUALITY_HIGH:()=>ep,QUALITY_LOW:()=>Qf,QUALITY_MEDIUM:()=>$f,QUALITY_VERY_HIGH:()=>tp,QUALITY_VERY_LOW:()=>Zf,Quality:()=>Xf,QuickTimeInputFormat:()=>dc,ReadableStreamSource:()=>Uc,RichImageData:()=>Zn,SUBTITLE_CODECS:()=>sr,Source:()=>Fc,StreamSource:()=>Hc,StreamTarget:()=>Vd,SubtitleSource:()=>Fp,Target:()=>zd,TextSubtitleSource:()=>Ip,UrlSource:()=>Bc,VIDEO_CODECS:()=>ir,VIDEO_SAMPLE_PIXEL_FORMATS:()=>aa,VideoSample:()=>sa,VideoSampleColorSpace:()=>ca,VideoSampleSink:()=>Na,VideoSampleSource:()=>yp,VideoSource:()=>hp,WAVE:()=>Tc,WEBM:()=>Cc,WavOutputFormat:()=>Rf,WaveInputFormat:()=>hc,WebMInputFormat:()=>pc,WebMOutputFormat:()=>If,canEncode:()=>np,canEncodeAudio:()=>ip,canEncodeSubtitles:()=>ap,canEncodeVideo:()=>rp,getEncodableAudioCodecs:()=>cp,getEncodableCodecs:()=>op,getEncodableSubtitleCodecs:()=>lp,getEncodableVideoCodecs:()=>sp,getFirstEncodableAudioCodec:()=>dp,getFirstEncodableSubtitleCodec:()=>fp,getFirstEncodableVideoCodec:()=>up,registerDecoder:()=>Ki,registerEncoder:()=>qi}),$p,em=n((()=>{Vp(),Uf(),Lp(),R(),pp(),Wd(),Kc(),jc(),Yc(),Ua(),Xi(),Ca(),za(),Zp(),Ji(),rr(),$p=Symbol.for(`mediabunny loaded`),globalThis[$p]&&console.error(`[WARNING]
108
- Mediabunny was loaded twice. This will likely cause Mediabunny not to work correctly. Check if multiple dependencies are importing different versions of Mediabunny, or if something is being bundled incorrectly.`),globalThis[$p]=!0}));let tm=`hevc`,nm=`No supported audio codec found for recording`,rm=[`aac`,`opus`];async function im(e){return e?.loadMediabunny?await e.loadMediabunny():await Promise.resolve().then(()=>(em(),Qp))}function am(e,t,n){let r={};return e!==void 0&&(r={...r,width:e}),t!==void 0&&(r={...r,height:t}),n!==void 0&&(r={...r,bitrate:n}),r}function om(e){let t={};return e!==void 0&&(t={...t,bitrate:e}),t}function sm(e){return{kind:`result`,module:e}}function cm(e){return{kind:`error`,error:e}}function lm(e){return{kind:`result`,supported:e}}function um(e){return{kind:`error`,error:e}}function dm(e){return{kind:`result`,codec:e}}function fm(e){return{kind:`error`,error:e}}async function pm(e,t,n,r){let i=await im(r).then(e=>sm(e)).catch(e=>cm(e));if(i.kind===`error`)return`avc`;let{canEncodeVideo:a}=i.module;if(typeof a!=`function`)return`avc`;let o=await a(tm,am(e,t,n)).then(e=>lm(e)).catch(e=>um(e));return o.kind===`error`?`avc`:o.supported?tm:`avc`}async function mm(e,t){let n=await im(t).then(e=>sm(e)).catch(e=>cm(e));if(n.kind===`error`)return`aac`;let{getFirstEncodableAudioCodec:r}=n.module;if(typeof r!=`function`)return`aac`;let a=await r(rm,om(e)).then(e=>dm(e)).catch(e=>fm(e));if(a.kind===`error`){if(i(a.error)===nm)throw Error(nm);return`aac`}if(a.codec===null)throw Error(nm);return a.codec}function hm(){let e=new wt().getDevice();return e.type===`mobile`||e.type===`tablet`}async function gm(e){let{preset:t,outputFormat:n,watermark:r,isMobile:i}=e;if(!(t in Lt))throw Error(`Invalid preset: ${t}`);let{width:a,height:o}=((i===void 0?hm():i)?zt:Rt)[t],s=n||`mp4`,c=await mm(Nt),l={format:s,width:a,height:o,bitrate:Lt[t],audioCodec:c,audioBitrate:Nt};return r&&(l.watermark={url:r.url,opacity:r.opacity,position:r.position}),l}let _m=new Map;function vm(e,t){return`${e}:${t}`}var ym=class e{constructor(e){if(this.cachedConfig=null,this.cacheTimestamp=0,this.fetchPromise=null,this.lastFetchSucceeded=!1,this.options=e,e.cacheTimeout!==void 0){if(typeof e.cacheTimeout!=`number`||e.cacheTimeout<=0)throw Error(`cacheTimeout must be a positive number`);this.cacheTimeout=e.cacheTimeout}else this.cacheTimeout=3e5}static getInstance(t){let n=vm(t.backendUrl,t.apiKey),r=_m.get(n);return r||(r=new e(t),_m.set(n,r)),r}async fetchConfig(){let e=Date.now();if(this.cachedConfig&&e-this.cacheTimestamp<this.cacheTimeout)return this.lastFetchSucceeded=!0,this.cachedConfig;if(this.fetchPromise)return this.fetchPromise;this.fetchPromise=this.fetchConfigFromBackend();try{let t=await this.fetchPromise;return this.cachedConfig=t,this.cacheTimestamp=e,this.fetchPromise=null,this.lastFetchSucceeded=!0,t}catch{return this.fetchPromise=null,this.lastFetchSucceeded=!1,Bt}}isConfigReady(){return this.lastFetchSucceeded}clearCache(){let e=vm(this.options.backendUrl,this.options.apiKey);this.cachedConfig=null,this.cacheTimestamp=0,this.fetchPromise=null,_m.delete(e)}static clearAllInstances(){_m.clear()}getCurrentConfig(){if(!this.cachedConfig)throw Error(`No cached config available. Call fetchConfig() first.`);return this.cachedConfig}async fetchConfigFromBackend(){let e=`${this.options.backendUrl}/api/v1/videos/config`,t=await fetch(e,{method:`GET`,headers:{Authorization:`Bearer ${this.options.apiKey}`,"Content-Type":`application/json`}});if(!t.ok)throw Error(`Failed to fetch config: ${t.status} ${t.statusText}`);let n=(await t.json()).data;if(!n.presetEncoding)throw Error(`Invalid config response from backend: missing presetEncoding`);return await gm({preset:n.presetEncoding,outputFormat:n.outputFormat,watermark:n.watermark})}},bm=class{constructor(){this.configService=null,this.currentConfig=Bt,this.configFetched=!1,this.configReady=!1}async initialize(e,t){if(this.configService)return;if(!e)throw Error(`apiKey is required`);let n=t||`https://core.vidtreo.com`;this.configService=ym.getInstance({apiKey:e,backendUrl:n}),this.configService.fetchConfig().then(e=>{this.currentConfig=e,this.configReady=this.configService?.isConfigReady()??!1,this.configFetched=!0}).catch(()=>{this.configReady=!1,this.configFetched=!0})}async fetchConfig(){this.configService&&(this.currentConfig=await this.configService.fetchConfig(),this.configReady=this.configService.isConfigReady(),this.configFetched=!0)}async getConfig(){return this.configService&&!this.configFetched&&await this.fetchConfig(),this.currentConfig}isConfigReady(){return this.configReady}clearCache(){if(!this.configService)throw Error(`ConfigService is not initialized`);this.configService.clearCache()}},xm=class{constructor(e,t){this.availableDevices={audioinput:[],videoinput:[]},this.selectedCameraDeviceId=null,this.selectedMicDeviceId=null,this.streamManager=e,this.callbacks=t}async getAvailableDevices(){return this.availableDevices=await this.streamManager.getAvailableDevices(),this.callbacks?.onDevicesChanged&&this.callbacks.onDevicesChanged(this.availableDevices),this.availableDevices}setCameraDevice(e){this.selectedCameraDeviceId=e,this.streamManager.setVideoDevice(e),this.callbacks?.onDeviceSelected&&this.callbacks.onDeviceSelected(`camera`,e)}setMicDevice(e){this.selectedMicDeviceId=e,this.streamManager.setAudioDevice(e),this.callbacks?.onDeviceSelected&&this.callbacks.onDeviceSelected(`mic`,e)}getSelectedCameraDeviceId(){return this.selectedCameraDeviceId}getSelectedMicDeviceId(){return this.selectedMicDeviceId}getAvailableDevicesList(){return this.availableDevices}};em();async function Sm(e){try{let t=new Lc(e),n=new qc({formats:[bc],source:t});if(typeof n.computeDuration!=`function`)throw Error(`computeDuration method is not available`);let r=await n.computeDuration();if(!r)throw Error(`Duration is missing from computeDuration`);if(r<=0)throw Error(`Invalid duration: must be greater than 0`);return r}catch{return Cm(e)}}function Cm(e){return new Promise((t,n)=>{let r=document.createElement(`video`),i=URL.createObjectURL(e),a=()=>{URL.revokeObjectURL(i)};r.addEventListener(`loadedmetadata`,()=>{a();let e=r.duration;if(!Number.isFinite(e)||e<=0){n(Error(`Invalid video duration`));return}t(e)}),r.addEventListener(`error`,()=>{a(),n(Error(`Failed to load video metadata`))}),r.src=i,r.load()})}let wm=[`video/mp4`,`video/quicktime`,`video/webm`];async function Tm(e,t={}){let n=t.maxFileSize===void 0?524288e3:t.maxFileSize;if(e.size>n)return{valid:!1,error:`File too large. Maximum size is ${Math.round(n/1024/1024)}MB`};let r=t.allowedFormats===void 0?wm:t.allowedFormats;if(!r.includes(e.type))return{valid:!1,error:`Unsupported format. Please use: ${r.join(`, `)}`};let a=await Sm(e).then(e=>({success:!0,duration:e})).catch(e=>({success:!1,error:i(e)}));if(a.success===!1)return{valid:!1,error:`Failed to read video file: ${a.error}`};let o=a.duration;return t.maxRecordingTime!==null&&t.maxRecordingTime!==void 0&&o>t.maxRecordingTime?{valid:!1,error:`Video too long. Maximum duration is ${t.maxRecordingTime} seconds`}:{valid:!0}}em();function Em(e){switch(e){case`mp4`:return new Nf;case`webm`:return new If;case`mkv`:return new Ff;case`mov`:return new Pf;default:throw Error(`Unsupported output format: ${e}`)}}function Dm(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 Om(e){if(!e.isValid){let t=e.discardedTracks.map(e=>e.reason).join(`, `);throw Error(`Conversion is invalid. Discarded tracks: ${t}`)}}async function km(e,t={},n){let r={...Bt,...t,format:t.format||Bt.format};r.audioCodec||=await mm(r.audioBitrate);let i=new qc({formats:Ac,source:new Lc(e)}),a=new Bp({format:Em(r.format),target:new Bd}),o=await Kp.init({input:i,output:a,video:{codec:r.codec,width:r.width,height:r.height,frameRate:r.fps,bitrate:r.bitrate,fit:`contain`,allowRotationMetadata:!1},audio:{codec:r.audioCodec}});Om(o),n&&(o.onProgress=n),await o.execute();let s=a.target.buffer;if(!s)throw Error(`Transcoding completed but no output buffer was generated`);let c=Dm(r.format);return{buffer:s,blob:new Blob([s],{type:c})}}function Am(e,t=1e4){return new Promise((n,r)=>{let i=document.createElement(`video`);i.preload=`metadata`,i.muted=!0;let a=setTimeout(()=>{o(),r(Error(`Preview extraction timeout`))},t),o=()=>{clearTimeout(a),URL.revokeObjectURL(i.src)};i.addEventListener(`loadedmetadata`,()=>{i.currentTime=Math.max(0,i.duration-.1)}),i.addEventListener(`seeked`,()=>{let e=document.createElement(`canvas`);e.width=i.videoWidth,e.height=i.videoHeight;let t=e.getContext(`2d`);if(!t){o(),r(Error(`Canvas context unavailable`));return}if(i.videoWidth===0||i.videoHeight===0){o(),r(Error(`Invalid video dimensions`));return}if(!(Number.isFinite(i.videoWidth)&&Number.isFinite(i.videoHeight))){o(),r(Error(`Invalid video dimensions`));return}t.drawImage(i,0,0,e.width,e.height),e.toBlob(e=>{o(),e?n(e):r(Error(`Failed to create preview blob`))},`image/jpeg`,.8)}),i.addEventListener(`error`,()=>{o(),r(Error(`Failed to load video for preview extraction`))}),i.src=URL.createObjectURL(e)})}var jm=class{constructor(e,t,n){this.pendingFile=null,this.configService=null,this.config=e,this.configService=t,this.uploadService=n}async handleFileSelection(e){let t=await Tm(e,{maxFileSize:this.config.maxFileSize===void 0?2*1024*1024*1024:this.config.maxFileSize,maxRecordingTime:this.config.maxRecordingTime,allowedFormats:[`video/mp4`,`video/quicktime`,`video/webm`]});if(!t.valid)throw Error(t.error);let n=await Am(e),r=URL.createObjectURL(n),a=await Sm(e).then(e=>({success:!0,duration:e})).catch(e=>({success:!1,error:i(e)}));if(a.success===!1)throw Error(`Failed to extract video duration: ${a.error}`);let o=a.duration;return this.pendingFile=e,{file:e,previewUrl:r,duration:o,validated:!0}}async processAndUpload(e,t){if(!this.pendingFile)throw Error(`No file selected`);let n=this.configService?await this.configService.fetchConfig():Bt,r=await km(this.pendingFile,n,e);if(!(this.config.apiKey&&this.config.backendUrl))throw Error(`Upload requires API key and backend URL`);let i=await this.uploadService.uploadVideo(r.blob,{apiKey:this.config.apiKey,backendUrl:this.config.backendUrl,filename:`${Date.now()}.mp4`,userMetadata:this.config.userMetadata,onProgress:t});return this.pendingFile=null,{blob:r.blob,recordingId:i.id,uploadUrl:i.uploadUrl||``}}cancel(){this.pendingFile=null}async preloadConfig(){this.configService&&await this.configService.fetchConfig()}};function Mm(){return new Blob([`"use strict";
108
+ Mediabunny was loaded twice. This will likely cause Mediabunny not to work correctly. Check if multiple dependencies are importing different versions of Mediabunny, or if something is being bundled incorrectly.`),globalThis[$p]=!0}));let tm=`No supported audio codec found for recording`,nm=[`aac`,`opus`];async function rm(e){return e?.loadMediabunny?await e.loadMediabunny():await Promise.resolve().then(()=>(em(),Qp))}function im(e,t,n){let r={};return e!==void 0&&(r={...r,width:e}),t!==void 0&&(r={...r,height:t}),n!==void 0&&(r={...r,bitrate:n}),r}function am(e){let t={};return e!==void 0&&(t={...t,bitrate:e}),t}function om(e){return{kind:`result`,module:e}}function sm(e){return{kind:`error`,error:e}}function cm(e){return{kind:`result`,supported:e}}function lm(e){return{kind:`error`,error:e}}async function um(e,t,n){return await e(t,n).then(e=>cm(e)).catch(e=>lm(e))}function dm(e){return{kind:`result`,codec:e}}function fm(e){return{kind:`error`,error:e}}async function pm(e,t,n,r){let i=await rm(r).then(e=>om(e)).catch(e=>sm(e));if(i.kind===`error`)return`avc`;let{canEncodeVideo:a}=i.module;if(typeof a!=`function`)return`avc`;let o=await um(a,`av1`,im(e,t,n));return o.kind===`error`?`avc`:o.supported?`av1`:`avc`}async function mm(e,t,n,r){let i=await rm(r).then(e=>om(e)).catch(e=>sm(e));if(i.kind===`error`)return`vp9`;let{canEncodeVideo:a}=i.module;if(typeof a!=`function`)return`vp9`;let o=im(e,t,n),s=await um(a,`av1`,o);if(s.kind===`error`)return`vp9`;if(s.supported)return`av1`;let c=await um(a,`vp9`,o);return c.kind===`error`||c.supported,`vp9`}async function hm(e,t){let n=await rm(t).then(e=>om(e)).catch(e=>sm(e));if(n.kind===`error`)return`aac`;let{getFirstEncodableAudioCodec:r}=n.module;if(typeof r!=`function`)return`aac`;let a=await r(nm,am(e)).then(e=>dm(e)).catch(e=>fm(e));if(a.kind===`error`){if(i(a.error)===tm)throw Error(tm);return`aac`}if(a.codec===null)throw Error(tm);return a.codec}function gm(){let e=new wt().getDevice();return e.type===`mobile`||e.type===`tablet`}async function _m(e){let{preset:t,outputFormat:n,watermark:r,isMobile:i}=e;if(!(t in Lt))throw Error(`Invalid preset: ${t}`);let{width:a,height:o}=((i===void 0?gm():i)?zt:Rt)[t],s=n||`mp4`,c=await hm(Nt),l={format:s,width:a,height:o,bitrate:Lt[t],audioCodec:c,audioBitrate:Nt};return r&&(l.watermark={url:r.url,opacity:r.opacity,position:r.position}),l}let vm=new Map;function ym(e,t){return`${e}:${t}`}var bm=class e{constructor(e){if(this.cachedConfig=null,this.cacheTimestamp=0,this.fetchPromise=null,this.lastFetchSucceeded=!1,this.options=e,e.cacheTimeout!==void 0){if(typeof e.cacheTimeout!=`number`||e.cacheTimeout<=0)throw Error(`cacheTimeout must be a positive number`);this.cacheTimeout=e.cacheTimeout}else this.cacheTimeout=3e5}static getInstance(t){let n=ym(t.backendUrl,t.apiKey),r=vm.get(n);return r||(r=new e(t),vm.set(n,r)),r}async fetchConfig(){let e=Date.now();if(this.cachedConfig&&e-this.cacheTimestamp<this.cacheTimeout)return this.lastFetchSucceeded=!0,this.cachedConfig;if(this.fetchPromise)return this.fetchPromise;this.fetchPromise=this.fetchConfigFromBackend();try{let t=await this.fetchPromise;return this.cachedConfig=t,this.cacheTimestamp=e,this.fetchPromise=null,this.lastFetchSucceeded=!0,t}catch{return this.fetchPromise=null,this.lastFetchSucceeded=!1,Bt}}isConfigReady(){return this.lastFetchSucceeded}clearCache(){let e=ym(this.options.backendUrl,this.options.apiKey);this.cachedConfig=null,this.cacheTimestamp=0,this.fetchPromise=null,vm.delete(e)}static clearAllInstances(){vm.clear()}getCurrentConfig(){if(!this.cachedConfig)throw Error(`No cached config available. Call fetchConfig() first.`);return this.cachedConfig}async fetchConfigFromBackend(){let e=`${this.options.backendUrl}/api/v1/videos/config`,t=await fetch(e,{method:`GET`,headers:{Authorization:`Bearer ${this.options.apiKey}`,"Content-Type":`application/json`}});if(!t.ok)throw Error(`Failed to fetch config: ${t.status} ${t.statusText}`);let n=(await t.json()).data;if(!n.presetEncoding)throw Error(`Invalid config response from backend: missing presetEncoding`);return await _m({preset:n.presetEncoding,outputFormat:n.outputFormat,watermark:n.watermark})}},xm=class{constructor(){this.configService=null,this.currentConfig=Bt,this.configFetched=!1,this.configReady=!1}async initialize(e,t){if(this.configService)return;if(!e)throw Error(`apiKey is required`);let n=t||`https://core.vidtreo.com`;this.configService=bm.getInstance({apiKey:e,backendUrl:n}),this.configService.fetchConfig().then(e=>{this.currentConfig=e,this.configReady=this.configService?.isConfigReady()??!1,this.configFetched=!0}).catch(()=>{this.configReady=!1,this.configFetched=!0})}async fetchConfig(){this.configService&&(this.currentConfig=await this.configService.fetchConfig(),this.configReady=this.configService.isConfigReady(),this.configFetched=!0)}async getConfig(){return this.configService&&!this.configFetched&&await this.fetchConfig(),this.currentConfig}isConfigReady(){return this.configReady}clearCache(){if(!this.configService)throw Error(`ConfigService is not initialized`);this.configService.clearCache()}},Sm=class{constructor(e,t){this.availableDevices={audioinput:[],videoinput:[]},this.selectedCameraDeviceId=null,this.selectedMicDeviceId=null,this.streamManager=e,this.callbacks=t}async getAvailableDevices(){return this.availableDevices=await this.streamManager.getAvailableDevices(),this.callbacks?.onDevicesChanged&&this.callbacks.onDevicesChanged(this.availableDevices),this.availableDevices}setCameraDevice(e){this.selectedCameraDeviceId=e,this.streamManager.setVideoDevice(e),this.callbacks?.onDeviceSelected&&this.callbacks.onDeviceSelected(`camera`,e)}setMicDevice(e){this.selectedMicDeviceId=e,this.streamManager.setAudioDevice(e),this.callbacks?.onDeviceSelected&&this.callbacks.onDeviceSelected(`mic`,e)}getSelectedCameraDeviceId(){return this.selectedCameraDeviceId}getSelectedMicDeviceId(){return this.selectedMicDeviceId}getAvailableDevicesList(){return this.availableDevices}};em();async function Cm(e){try{let t=new Lc(e),n=new qc({formats:[bc],source:t});if(typeof n.computeDuration!=`function`)throw Error(`computeDuration method is not available`);let r=await n.computeDuration();if(!r)throw Error(`Duration is missing from computeDuration`);if(r<=0)throw Error(`Invalid duration: must be greater than 0`);return r}catch{return wm(e)}}function wm(e){return new Promise((t,n)=>{let r=document.createElement(`video`),i=URL.createObjectURL(e),a=()=>{URL.revokeObjectURL(i)};r.addEventListener(`loadedmetadata`,()=>{a();let e=r.duration;if(!Number.isFinite(e)||e<=0){n(Error(`Invalid video duration`));return}t(e)}),r.addEventListener(`error`,()=>{a(),n(Error(`Failed to load video metadata`))}),r.src=i,r.load()})}let Tm=[`video/mp4`,`video/quicktime`,`video/webm`];async function Em(e,t={}){let n=t.maxFileSize===void 0?524288e3:t.maxFileSize;if(e.size>n)return{valid:!1,error:`File too large. Maximum size is ${Math.round(n/1024/1024)}MB`};let r=t.allowedFormats===void 0?Tm:t.allowedFormats;if(!r.includes(e.type))return{valid:!1,error:`Unsupported format. Please use: ${r.join(`, `)}`};let a=await Cm(e).then(e=>({success:!0,duration:e})).catch(e=>({success:!1,error:i(e)}));if(a.success===!1)return{valid:!1,error:`Failed to read video file: ${a.error}`};let o=a.duration;return t.maxRecordingTime!==null&&t.maxRecordingTime!==void 0&&o>t.maxRecordingTime?{valid:!1,error:`Video too long. Maximum duration is ${t.maxRecordingTime} seconds`}:{valid:!0}}em();function Dm(e){switch(e){case`mp4`:return new Nf;case`webm`:return new If;case`mkv`:return new Ff;case`mov`:return new Pf;default:throw Error(`Unsupported output format: ${e}`)}}function Om(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}`)}}async function km(e){return e.format===`webm`?await mm(e.width,e.height,e.bitrate):await pm(e.width,e.height,e.bitrate)}function Am(e){if(!e.isValid){let t=e.discardedTracks.map(e=>e.reason).join(`, `);throw Error(`Conversion is invalid. Discarded tracks: ${t}`)}}async function jm(e,t={},n){let r={...Bt,...t,format:t.format||Bt.format};r.audioCodec||=await hm(r.audioBitrate),r.codec=await km(r);let i=new qc({formats:Ac,source:new Lc(e)}),a=new Bp({format:Dm(r.format),target:new Bd}),o=await Kp.init({input:i,output:a,video:{codec:r.codec,width:r.width,height:r.height,frameRate:r.fps,bitrate:r.bitrate,fit:`contain`,allowRotationMetadata:!1},audio:{codec:r.audioCodec}});Am(o),n&&(o.onProgress=n),await o.execute();let s=a.target.buffer;if(!s)throw Error(`Transcoding completed but no output buffer was generated`);let c=Om(r.format);return{buffer:s,blob:new Blob([s],{type:c})}}function Mm(e,t=1e4){return new Promise((n,r)=>{let i=document.createElement(`video`);i.preload=`metadata`,i.muted=!0;let a=setTimeout(()=>{o(),r(Error(`Preview extraction timeout`))},t),o=()=>{clearTimeout(a),URL.revokeObjectURL(i.src)};i.addEventListener(`loadedmetadata`,()=>{i.currentTime=Math.max(0,i.duration-.1)}),i.addEventListener(`seeked`,()=>{let e=document.createElement(`canvas`);e.width=i.videoWidth,e.height=i.videoHeight;let t=e.getContext(`2d`);if(!t){o(),r(Error(`Canvas context unavailable`));return}if(i.videoWidth===0||i.videoHeight===0){o(),r(Error(`Invalid video dimensions`));return}if(!(Number.isFinite(i.videoWidth)&&Number.isFinite(i.videoHeight))){o(),r(Error(`Invalid video dimensions`));return}t.drawImage(i,0,0,e.width,e.height),e.toBlob(e=>{o(),e?n(e):r(Error(`Failed to create preview blob`))},`image/jpeg`,.8)}),i.addEventListener(`error`,()=>{o(),r(Error(`Failed to load video for preview extraction`))}),i.src=URL.createObjectURL(e)})}var Nm=class{constructor(e,t,n){this.pendingFile=null,this.configService=null,this.config=e,this.configService=t,this.uploadService=n}async handleFileSelection(e){let t=await Em(e,{maxFileSize:this.config.maxFileSize===void 0?2*1024*1024*1024:this.config.maxFileSize,maxRecordingTime:this.config.maxRecordingTime,allowedFormats:[`video/mp4`,`video/quicktime`,`video/webm`]});if(!t.valid)throw Error(t.error);let n=await Mm(e),r=URL.createObjectURL(n),a=await Cm(e).then(e=>({success:!0,duration:e})).catch(e=>({success:!1,error:i(e)}));if(a.success===!1)throw Error(`Failed to extract video duration: ${a.error}`);let o=a.duration;return this.pendingFile=e,{file:e,previewUrl:r,duration:o,validated:!0}}async processAndUpload(e,t){if(!this.pendingFile)throw Error(`No file selected`);let n=this.configService?await this.configService.fetchConfig():Bt,r=await jm(this.pendingFile,n,e);if(!(this.config.apiKey&&this.config.backendUrl))throw Error(`Upload requires API key and backend URL`);let i=await this.uploadService.uploadVideo(r.blob,{apiKey:this.config.apiKey,backendUrl:this.config.backendUrl,filename:`${Date.now()}.mp4`,userMetadata:this.config.userMetadata,onProgress:t});return this.pendingFile=null,{blob:r.blob,recordingId:i.id,uploadUrl:i.uploadUrl||``}}cancel(){this.pendingFile=null}async preloadConfig(){this.configService&&await this.configService.fetchConfig()}};function Pm(){return new Blob([`"use strict";
109
109
  var PROBE_MESSAGE_TYPE="probe";
110
110
  var PROBE_RESULT_TYPE="probeResult";
111
111
  self.onmessage=function(e){
@@ -119,11 +119,11 @@ hasOffscreenCanvas:typeof OffscreenCanvas!=="undefined",
119
119
  hasCreateImageBitmap:typeof createImageBitmap!=="undefined",
120
120
  hasReadableStream:typeof ReadableStream!=="undefined"
121
121
  });
122
- };`],{type:`application/javascript`})}function Nm(){let e=Mm();return URL.createObjectURL(e)}function Pm(e){URL.revokeObjectURL(e)}let Fm=`probe`,Im=`probeResult`,Lm=`mediaStreamTrackProcessor`,Rm=`unavailable`,zm=`unavailable`;function Bm(e,t){return typeof e==`boolean`?e:t}function Vm(e){return e.probeResult.hasMediaStreamTrackProcessor?`worker-track`:e.hasMainThreadMediaStreamTrackProcessor?`main-thread-stream`:Rm}function Hm(e){return e.requiresAudio?e.hasMainThreadMediaStreamTrackProcessor&&e.probeResult.hasAudioData?`main-thread-audio-stream`:e.hasAudioContext&&e.hasAudioWorklet?`audio-worklet-chunks`:zm:`none-required`}function Um(e,t){return e.includes(t)?e:[...e,t]}function Wm(e,t){let n=e;return t.hasWorker||(n=Um(n,`worker`)),t.probeResult.hasVideoFrame||(n=Um(n,`videoFrame`)),t.probeResult.hasOffscreenCanvas||(n=Um(n,`offscreenCanvas`)),t.probeResult.hasReadableStream||(n=Um(n,`readableStream`)),n}function Gm(e,t){let n=e;return t.requiresWatermark&&!t.probeResult.hasCreateImageBitmap&&(n=Um(n,`createImageBitmap`)),n}function Km(e,t){let n=e;return t.videoPath===Rm&&(n=Um(n,Lm)),n}function qm(e,t){let n=e;return t.hasMainThreadMediaStreamTrackProcessor&&t.probeResult.hasAudioData?n:(t.hasMainThreadMediaStreamTrackProcessor||(n=Um(n,Lm)),t.hasMainThreadMediaStreamTrackProcessor&&!t.probeResult.hasAudioData&&(n=Um(n,`audioData`)),n)}function Jm(e,t){let n=e;return t.hasAudioContext&&t.hasAudioWorklet?n:(t.hasAudioContext||(n=Um(n,`audioContext`)),t.hasAudioWorklet||(n=Um(n,`audioWorklet`)),n)}function Ym(e,t){let n=e;return t.requiresAudio&&t.audioPath===zm?(n=qm(n,t),n=Jm(n,t),n):n}function Xm(e){let t=[];return t=Wm(t,e),t=Gm(t,e),t=Km(t,e),t=Ym(t,e),t}function Zm(e,t){return!(e===Rm||t===zm)}function Qm(e,t){return!(!e.hasVideoFrame||!e.hasOffscreenCanvas||!e.hasReadableStream||t&&!e.hasCreateImageBitmap)}async function $m(e={}){let t=Bm(e.requiresAudio,!0),n=Bm(e.requiresWatermark,!1),r=typeof Worker<`u`,i=a()!==null,o=typeof AudioWorkletNode<`u`,s=typeof MediaStreamTrackProcessor<`u`,c=await eh(r),l=Vm({probeResult:c,hasMainThreadMediaStreamTrackProcessor:s}),u=Hm({requiresAudio:t,hasAudioContext:i,hasAudioWorklet:o,hasMainThreadMediaStreamTrackProcessor:s,probeResult:c}),d=Xm({hasWorker:r,hasAudioContext:i,hasAudioWorklet:o,hasMainThreadMediaStreamTrackProcessor:s,probeResult:c,requiresAudio:t,requiresWatermark:n,videoPath:l,audioPath:u}),f=Zm(l,u),p=Qm(c,n);return{isSupported:r&&f&&p,missing:d,hasWorker:r,hasAudioContext:i,hasAudioWorklet:o,hasMediaStreamTrackProcessor:c.hasMediaStreamTrackProcessor,hasMainThreadMediaStreamTrackProcessor:s,hasVideoFrame:c.hasVideoFrame,hasAudioData:c.hasAudioData,hasOffscreenCanvas:c.hasOffscreenCanvas,hasCreateImageBitmap:c.hasCreateImageBitmap,hasReadableStream:c.hasReadableStream,requiresAudio:t,requiresWatermark:n,videoPath:l,audioPath:u}}async function eh(e){if(!e)return nh();let t=await th().catch(()=>null);return t?await new Promise(e=>{let n=!1,r=r=>{n||(n=!0,t.terminate(),e(r))},i=setTimeout(()=>{r(nh())},2e3);t.onmessage=e=>{let t=e.data;t.type===Im&&(clearTimeout(i),r({hasMediaStreamTrackProcessor:t.hasMediaStreamTrackProcessor===!0,hasVideoFrame:t.hasVideoFrame===!0,hasAudioData:t.hasAudioData===!0,hasOffscreenCanvas:t.hasOffscreenCanvas===!0,hasCreateImageBitmap:t.hasCreateImageBitmap===!0,hasReadableStream:t.hasReadableStream===!0}))},t.onerror=()=>{clearTimeout(i),r(nh())},Promise.resolve().then(()=>{t.postMessage({type:Fm})}).catch(()=>{clearTimeout(i),r(nh())})}):nh()}function th(){return Promise.resolve().then(()=>{let e=Nm();try{let t=new Worker(e,{type:`classic`});return Pm(e),t}catch(t){throw Pm(e),t}})}function nh(){return{hasMediaStreamTrackProcessor:!1,hasVideoFrame:!1,hasAudioData:!1,hasOffscreenCanvas:!1,hasCreateImageBitmap:!1,hasReadableStream:!1}}let rh=`pending-uploads`,ih=`status`,ah=`createdAt`;var oh=class{constructor(){this.db=null}init(){return this.db?Promise.resolve():new Promise((e,t)=>{let n=indexedDB.open(`vidtreo-recorder`,1);n.onerror=()=>{n.error?t(n.error):t(Error(`Failed to open database`))},n.onsuccess=()=>{if(!n.result){t(Error(`Database result is null`));return}this.db=n.result,e()},n.onupgradeneeded=e=>{let n=e.target.result;if(!n){t(Error(`Database upgrade result is null`));return}if(!n.objectStoreNames.contains(rh)){let e=n.createObjectStore(rh,{keyPath:`id`});e.createIndex(ih,ih,{unique:!1}),e.createIndex(ah,ah,{unique:!1})}}})}isInitialized(){return this.db!==null}savePendingUpload(e){let t=this.generateUploadId(),n={...e,id:t,status:`pending`,retryCount:0,createdAt:Date.now(),updatedAt:Date.now()};return this.executeTransaction(`readwrite`,e=>{let r=e.add(n);return new Promise((e,n)=>{r.onsuccess=()=>e(t),r.onerror=()=>{r.error?r.error.name===`QuotaExceededError`?n(Error(`Storage quota exceeded. Please free up space or delete old uploads.`)):n(r.error):n(Error(`Failed to save upload`))}})})}getPendingUploads(e){return this.executeTransaction(`readonly`,t=>{let n=e?t.index(ih).getAll(e):t.getAll();return new Promise((e,t)=>{n.onsuccess=()=>{if(n.result===void 0){t(Error(`Failed to get uploads: result is undefined`));return}e(n.result)},n.onerror=()=>{n.error?t(n.error):t(Error(`Failed to get uploads`))}})})}updateUploadStatus(e,t){return this.executeTransaction(`readwrite`,n=>{let r=n.get(e);return new Promise((e,i)=>{r.onsuccess=()=>{let a=r.result;if(!a){i(Error(`Upload not found`));return}let o={...a,...t,updatedAt:Date.now()},s=n.put(o);s.onsuccess=()=>e(),s.onerror=()=>{s.error?i(s.error):i(Error(`Failed to update upload`))}},r.onerror=()=>{r.error?i(r.error):i(Error(`Failed to get upload`))}})})}deleteUpload(e){return this.executeTransaction(`readwrite`,t=>{let n=t.delete(e);return new Promise((e,t)=>{n.onsuccess=()=>e(),n.onerror=()=>{n.error?t(n.error):t(Error(`Failed to delete upload`))}})})}async cleanupPermanentlyFailedUploads(e){let t=e===void 0?24:e;if(typeof t!=`number`||t<0)throw Error(`retentionHours must be a non-negative number`);let n=Date.now()-t*36e5,r=(await this.getPendingUploads()).filter(e=>e.status===`failed`&&e.retryCount>=10&&e.updatedAt<n);for(let e of r)await this.deleteUpload(e.id);return r.length}async getTotalStorageSize(){return(await this.getPendingUploads()).reduce((e,t)=>e+t.blob.size,0)}generateUploadId(){return`upload-${Date.now()}-${Math.random().toString(36).substring(2,11)}`}executeTransaction(e,t){if(!this.db)throw Error(`Database not initialized`);return t(this.db.transaction([rh],e).objectStore(rh))}},sh=class{constructor(){this.storageService=null,this.cleanupIntervalId=null}async initialize(e){this.storageService||=new oh,this.storageService.isInitialized()||await this.storageService.init(),this.setupCleanupInterval(e)}setupCleanupInterval(e){this.cleanupIntervalId===null&&(this.cleanupIntervalId=window.setInterval(()=>{this.performCleanup().catch(t=>{e(i(t))})},36e5))}async performCleanup(){if(!this.storageService)throw Error(`StorageService not initialized`);await this.storageService.cleanupPermanentlyFailedUploads(24)}getStorageService(){return this.storageService}destroy(){this.cleanupIntervalId!==null&&(clearInterval(this.cleanupIntervalId),this.cleanupIntervalId=null)}};function ch(){let e=globalThis;if(e.__VIDTREO_DEBUG__===!0||e.__VIDTREO_DEV__===!0)return!0;let t=typeof process<`u`&&process?.env?`production`:void 0;return t===`development`||t===`test`||typeof localStorage<`u`&&localStorage.getItem(`VIDTREO_DEBUG`)===`true`}let lh=ch(),uh={reset:`\x1B[0m`,bright:`\x1B[1m`,dim:`\x1B[2m`,red:`\x1B[31m`,green:`\x1B[32m`,yellow:`\x1B[33m`,blue:`\x1B[34m`,magenta:`\x1B[35m`,cyan:`\x1B[36m`,white:`\x1B[37m`,gray:`\x1B[90m`};function dh(e,t,n){if(!lh)return``;let r=n?.prefix||`[${e.toUpperCase()}]`;return`${uh[n?.color||fh(e)]}${r}${uh.reset} ${t}`}function fh(e){switch(e){case`error`:return`red`;case`warn`:return`yellow`;case`info`:return`cyan`;case`debug`:return`gray`;default:return`white`}}function ph(e,t,...n){if(!lh)return;let r=dh(e,t);console[e](r,...n)}let $={log:(e,...t)=>{ph(`log`,e,...t)},info:(e,...t)=>{ph(`info`,e,...t)},warn:(e,...t)=>{ph(`warn`,e,...t)},error:(e,...t)=>{ph(`error`,e,...t)},debug:(e,...t)=>{ph(`debug`,e,...t)},group:(e,t=`cyan`)=>{if(!lh)return;let n=uh[t],r=uh.reset;console.group(`${n}${e}${r}`)},groupEnd:()=>{lh&&console.groupEnd()}};function mh(e,t){if(e==null)throw Error(t);return e}function hh(e,t=`StreamProcessor`){if(!e)throw Error(`${t} is required`);return e}function gh(){if(typeof navigator>`u`||!navigator.mediaDevices?.getUserMedia){let e=typeof window<`u`&&window.isSecureContext===!0?`Camera access is not supported in this browser`:`Camera access requires HTTPS. Please use a secure connection (https://) or localhost.`;throw Error(e)}return navigator.mediaDevices}function _h(e,t){let n={};if(t.originalCameraConstraints){let{deviceId:e,...r}=t.originalCameraConstraints;n={...n,...r}}e&&(n={...n,deviceId:{exact:e}});let r=t.getSelectedCameraDeviceId(),i=!1;return e&&(i=!0),n.deviceId&&(i=!0),!i&&r&&(n={...n,deviceId:{exact:r}}),n}function vh(e){return e?{deviceId:{exact:e}}:!0}let yh=`live`;function bh(e){for(let t of e)t.readyState===yh&&t.stop()}function xh(e){bh(e.getTracks())}function Sh(e){bh(e.getVideoTracks())}function Ch(e){return e?e.readyState===yh:!1}function wh(e,t){return Ch(e)&&Ch(t)}function Th(e,t,n){if(!Ch(e)){xh(n);let r=`undefined`;throw e&&(r=e.readyState),Error(`Failed to get live camera ${t} track. ReadyState: ${r}`)}}let Eh=`[SourceSwitchManager]`;var Dh=class{constructor(e){this.dependencies=e}async createCameraStreamWithOriginalAudio(e){let t=this.dependencies.getOriginalCameraStream(),n;if(t&&(n=t.getAudioTracks()[0]),this.dependencies.logger.debug(`${Eh} createCameraStreamWithOriginalAudio`,{hasOriginalCameraStream:!!t,originalCameraStreamId:t?.id,hasOriginalAudioTrack:!!n,originalAudioTrackId:n?.id,originalAudioTrackReadyState:n?.readyState,originalAudioTrackEnabled:n?.enabled,originalAudioTrackMuted:n?.muted,originalAudioTrackLabel:n?.label,isTrackLive:Ch(n),cameraDeviceId:e}),!Ch(n))return this.dependencies.logger.warn(`${Eh} Original audio track is not live, cannot reuse`,{originalAudioTrackId:n?.id,originalAudioTrackReadyState:n?.readyState}),null;let r=_h(e,{originalCameraConstraints:this.dependencies.getOriginalCameraConstraints(),getSelectedCameraDeviceId:this.dependencies.getSelectedCameraDeviceId}),i=Object.keys(r).length>0,a=!0;i&&(a=r);let o={video:a,audio:!1};this.dependencies.logger.debug(`${Eh} Requesting new video stream`,{constraints:o,cameraDeviceId:e});let s=await gh().getUserMedia(o),c=s.getVideoTracks()[0];Th(c,`video`,s),this.dependencies.logger.debug(`${Eh} New video stream obtained`,{newStreamId:s.id,videoTrackId:c.id,videoTrackReadyState:c.readyState,newStreamAudioTracksCount:s.getAudioTracks().length});let l=[c];n&&(l=[...l,n]),this.dependencies.logger.debug(`${Eh} Creating combined stream with original audio`,{videoTrackId:c.id,audioTrackId:n?.id,audioTrackReadyState:n?.readyState,audioTrackEnabled:n?.enabled,audioTrackMuted:n?.muted,combinedTracksCount:l.length});let u=new MediaStream(l);bh(s.getAudioTracks());let d=t?.id;return this.dependencies.setOriginalCameraStream(u),this.dependencies.logger.debug(`${Eh} Combined stream created and assigned`,{combinedStreamId:u.id,previousOriginalCameraStreamId:d,newOriginalCameraStreamId:u.id,combinedStreamVideoTracksCount:u.getVideoTracks().length,combinedStreamAudioTracksCount:u.getAudioTracks().length,combinedStreamAudioTrackId:u.getAudioTracks()[0]?.id,combinedStreamAudioTrackReadyState:u.getAudioTracks()[0]?.readyState,audioTrackStillSame:u.getAudioTracks()[0]===n}),u}async createCameraStreamWithNewAudio(e){let t=this.dependencies.getSelectedMicDeviceId(),n=_h(e,{originalCameraConstraints:this.dependencies.getOriginalCameraConstraints(),getSelectedCameraDeviceId:this.dependencies.getSelectedCameraDeviceId}),r=vh(t),i=Object.keys(n).length>0,a=!0;i&&(a=n);let o={video:a,audio:r},s=await gh().getUserMedia(o),c=s.getVideoTracks()[0],l=s.getAudioTracks()[0];return Th(c,`video`,s),Th(l,`audio`,s),this.dependencies.setOriginalCameraStream(s),s}async createNewCameraStreamForRecording(){let e=this.dependencies.getSelectedCameraDeviceId();return await this.createCameraStreamWithOriginalAudio(e)||this.createCameraStreamWithNewAudio(e)}async getCameraStream(e){let t=this.dependencies.streamManager.isRecording(),n=this.dependencies.getSelectedCameraDeviceId(),r=this.dependencies.getSelectedMicDeviceId();if(this.dependencies.streamManager.setVideoDevice(n),this.dependencies.streamManager.setAudioDevice(r),e.canReuseOriginalStream()){let e=this.dependencies.getOriginalCameraStream();if(!e)throw Error(`Original camera stream is null`);return e}if(e.canReuseManagerStream()){let e=this.dependencies.streamManager.getStream();if(!e)throw Error(`Manager stream is null`);return e}t||this.dependencies.getOriginalCameraStream()&&this.dependencies.setOriginalCameraStream(null);let i=this.dependencies.streamManager.getStream();if(!t&&i&&i!==this.dependencies.getOriginalCameraStream()&&(xh(i),this.dependencies.streamManager.setMediaStream(null)),t)return this.dependencies.streamManager.setVideoDevice(this.dependencies.getSelectedCameraDeviceId()),this.dependencies.streamManager.setAudioDevice(this.dependencies.getSelectedMicDeviceId()),this.createNewCameraStreamForRecording();let a=await this.dependencies.streamManager.startStream();return this.dependencies.setOriginalCameraStream(a),a}};let Oh=`screen`,kh=`No video track found in screen share stream`;async function Ah(e,t,n){n.setScreenShareStream(e);let r=e.getVideoTracks()[0];if(!r)throw n.stopStreamTracks(e),Error(kh);let i=n.combineScreenShareWithOriginalAudio(r),a=n.getOriginalCameraStream();t&&t!==a&&n.stopStreamVideoTracks(t);let o=e.getAudioTracks();for(let e of o)e.stop();return n.setCurrentSourceType(Oh),n.callbacks.onSourceChange&&await n.callbacks.onSourceChange(n.getCurrentSourceType()),jh(i,n),i}function jh(e,t){let n=e.getVideoTracks()[0];if(!n)throw Error(kh);let r=t.getScreenShareTrackEndHandler();if(r){let e=t.streamManager.getStream();if(e){let t=e.getVideoTracks()[0];t&&t.removeEventListener(`ended`,r)}}let i=()=>{t.getCurrentSourceType()===Oh&&t.switchToCamera().catch(e=>{t.handleSwitchError(e)})};t.setScreenShareTrackEndHandler(i),n.addEventListener(`ended`,i)}function Mh(e,t){let n=t.getScreenShareTrackEndHandler();if(!(n&&e))return;let r=e.getVideoTracks()[0];r&&r.removeEventListener(`ended`,n),t.setScreenShareTrackEndHandler(null)}function Nh(e,t){e.onTransitionStart&&e.onTransitionStart(t)}function Ph(e){e.onTransitionEnd&&e.onTransitionEnd()}function Fh(e){e.onScreenSelectionStart&&e.onScreenSelectionStart()}function Ih(e){e.onScreenSelectionEnd&&e.onScreenSelectionEnd()}function Lh(e){Ih(e),Ph(e)}let Rh=`Failed to get camera stream`;var zh=class{constructor(e,t={}){this.currentSourceType=`camera`,this.originalCameraStream=null,this.screenShareStream=null,this.screenShareTrackEndHandler=null,this.streamManager=e,this.callbacks=t;let n=null,r=()=>n;this.getOriginalCameraConstraints=r,this.setOriginalCameraConstraints=e=>{n=e},this.cameraStreamBuilder=new Dh({streamManager:this.streamManager,logger:{debug:(e,t)=>$.debug(e,t),warn:(e,t)=>$.warn(e,t)},getSelectedCameraDeviceId:()=>this.callbacks.getSelectedCameraDeviceId?this.callbacks.getSelectedCameraDeviceId():this.streamManager.getVideoDevice(),getSelectedMicDeviceId:()=>this.callbacks.getSelectedMicDeviceId?this.callbacks.getSelectedMicDeviceId():this.streamManager.getAudioDevice(),getOriginalCameraStream:()=>this.originalCameraStream,setOriginalCameraStream:e=>{this.originalCameraStream=e},getOriginalCameraConstraints:r})}getCurrentSourceType(){return this.currentSourceType}getOriginalCameraStream(){return this.originalCameraStream}storeOriginalCameraConstraints(e){let t=e.getVideoTracks()[0];if(!t)return;let n=t.getSettings(),r={width:n.width,height:n.height,aspectRatio:n.aspectRatio,frameRate:n.frameRate,deviceId:n.deviceId,facingMode:n.facingMode},i=this.getOriginalCameraConstraints();i&&i.width===r.width&&i.height===r.height&&i.aspectRatio===r.aspectRatio&&i.frameRate===r.frameRate&&i.deviceId===r.deviceId&&i.facingMode===r.facingMode||this.setOriginalCameraConstraints(r)}storeOriginalCameraStream(e){let t=e.getVideoTracks()[0],n=e.getAudioTracks()[0];wh(t,n)?this.originalCameraStream=new MediaStream([t,n]):this.originalCameraStream=e}createError(e){return e instanceof Error?e:Error(i(e))}waitForTracksToEnd(e){return new Promise(t=>{setTimeout(()=>{this.screenShareStream=null,t()},e)})}combineScreenShareWithOriginalAudio(e){let t;this.originalCameraStream&&(t=this.originalCameraStream.getAudioTracks()[0]),$.debug(`[SourceSwitchManager] combineScreenShareWithOriginalAudio`,{hasOriginalCameraStream:!!this.originalCameraStream,originalCameraStreamId:this.originalCameraStream?.id,hasOriginalAudioTrack:!!t,originalAudioTrackId:t?.id,originalAudioTrackReadyState:t?.readyState,originalAudioTrackEnabled:t?.enabled,originalAudioTrackMuted:t?.muted,originalAudioTrackLabel:t?.label,isTrackLive:Ch(t),screenVideoTrackId:e.id,screenVideoTrackReadyState:e.readyState});let n=[e];Ch(t)&&t?(n=[...n,t],$.debug(`[SourceSwitchManager] Added original audio track to combined stream`,{audioTrackId:t.id,combinedTracksCount:n.length})):$.warn(`[SourceSwitchManager] Original audio track is not live, not adding to combined stream`,{audioTrackId:t?.id,audioTrackReadyState:t?.readyState,combinedTracksCount:n.length});let r=new MediaStream(n);return $.debug(`[SourceSwitchManager] Combined stream created`,{combinedStreamId:r.id,combinedStreamVideoTracksCount:r.getVideoTracks().length,combinedStreamAudioTracksCount:r.getAudioTracks().length,combinedStreamAudioTrackId:r.getAudioTracks()[0]?.id,combinedStreamAudioTrackReadyState:r.getAudioTracks()[0]?.readyState}),r}isPermissionDeniedError(e){let t=i(e),n=!1;t.includes(`NotAllowedError`)&&(n=!0),t.includes(`AbortError`)&&(n=!0);let r=t.toLowerCase();return r.includes(`permission denied`)&&(n=!0),r.includes(`user denied`)&&(n=!0),n}switchToScreenCapture(){let e=this.streamManager.getStream();return e&&(this.storeOriginalCameraConstraints(e),this.storeOriginalCameraStream(e)),Nh(this.callbacks,`Select screen to share...`),Fh(this.callbacks),Promise.resolve().then(async()=>{let t=gh();if(typeof t.getDisplayMedia!=`function`)throw Error(`Screen sharing is not supported on this device`);return Ah(await t.getDisplayMedia({video:!0,audio:!0}),e,this.getScreenShareDependencies())}).catch(e=>{if(Lh(this.callbacks),this.isPermissionDeniedError(e))return null;throw e})}canReuseStream(e,t){if(!e||t&&e!==this.originalCameraStream)return!1;let n=e.getVideoTracks()[0],r=e.getAudioTracks()[0];return!(!wh(n,r)||this.callbacks.getSelectedCameraDeviceId&&this.callbacks.getSelectedCameraDeviceId()!==n.getSettings().deviceId)}canReuseOriginalStream(){return this.canReuseStream(this.originalCameraStream,!1)}canReuseManagerStream(){let e=this.streamManager.getStream();return e&&this.originalCameraStream?this.canReuseStream(e,!0):!1}getScreenShareDependencies(){return{callbacks:this.callbacks,streamManager:this.streamManager,combineScreenShareWithOriginalAudio:e=>this.combineScreenShareWithOriginalAudio(e),stopStreamTracks:e=>xh(e),stopStreamVideoTracks:e=>Sh(e),getCurrentSourceType:()=>this.currentSourceType,setCurrentSourceType:e=>{this.currentSourceType=e},getOriginalCameraStream:()=>this.originalCameraStream,getScreenShareStream:()=>this.screenShareStream,setScreenShareStream:e=>{this.screenShareStream=e},getScreenShareTrackEndHandler:()=>this.screenShareTrackEndHandler,setScreenShareTrackEndHandler:e=>{this.screenShareTrackEndHandler=e},switchToCamera:()=>this.switchToCamera(),handleSwitchError:e=>{this.callbacks.onError&&this.callbacks.onError(this.createError(e))}}}getCameraStream(){return this.cameraStreamBuilder.getCameraStream({canReuseOriginalStream:()=>this.canReuseOriginalStream(),canReuseManagerStream:()=>this.canReuseManagerStream()})}switchToCamera(){let e=this.streamManager.isRecording();return!e&&this.currentSourceType===`camera`?Promise.resolve():Promise.resolve().then(async()=>{Nh(this.callbacks,`Switching to camera...`),await this.handleScreenShareStop();let t=await this.getCameraStream();if(!t)throw Error(Rh);await this.applyCameraStream(t,e),Ph(this.callbacks)}).catch(e=>{throw Ph(this.callbacks),e})}stopScreenShareStreamTracks(e){let t=e.getVideoTracks(),n=e.getAudioTracks();$.debug(`[SourceSwitchManager] stopping screen share tracks`,{videoTracks:t.map(e=>({id:e.id,readyState:e.readyState,displaySurface:e.getSettings().displaySurface,constraints:e.getConstraints()})),audioTracks:n.map(e=>({id:e.id,readyState:e.readyState,constraints:e.getConstraints()}))});for(let e of t)e.stop();for(let e of n)e.stop()}stopDisplayTracks(e){if(e)for(let t of e.getVideoTracks())typeof t.getSettings().displaySurface==`string`&&Ch(t)&&($.debug(`[SourceSwitchManager] stopping display track`,{id:t.id,readyState:t.readyState,constraints:t.getConstraints(),settings:t.getSettings()}),t.stop())}async handleScreenShareStop(){if(this.currentSourceType!==`screen`)return;$.debug(`[SourceSwitchManager] handleScreenShareStop invoked`,{currentSourceType:this.currentSourceType,hasScreenShareStream:!!this.screenShareStream,screenShareStreamId:this.screenShareStream?.id,hasOriginalCameraStream:!!this.originalCameraStream,originalCameraStreamId:this.originalCameraStream?.id});let e=this.screenShareStream,t=this.streamManager.getStream();if($.debug(`[SourceSwitchManager] Current stream state before stop`,{currentStreamId:t?.id,currentStreamVideoTracksCount:t?.getVideoTracks().length,currentStreamAudioTracksCount:t?.getAudioTracks().length,currentStreamAudioTrackId:t?.getAudioTracks()[0]?.id,currentStreamAudioTrackReadyState:t?.getAudioTracks()[0]?.readyState,originalCameraStreamAudioTrackId:this.originalCameraStream?.getAudioTracks()[0]?.id,originalCameraStreamAudioTrackReadyState:this.originalCameraStream?.getAudioTracks()[0]?.readyState}),e){let t=e.getAudioTracks();$.debug(`[SourceSwitchManager] Screen share stream audio tracks before stop`,{screenShareStreamId:e.id,screenShareAudioTracksCount:t.length,screenShareAudioTrackIds:t.map(e=>({id:e.id,readyState:e.readyState,enabled:e.enabled}))}),Mh(e,this.getScreenShareDependencies()),this.stopScreenShareStreamTracks(e),this.stopDisplayTracks(e),this.screenShareStream=null,await this.waitForTracksToEnd(0),$.debug(`[SourceSwitchManager] Screen share stream stopped`,{screenShareAudioTracksAfterStop:t.map(e=>({id:e.id,readyState:e.readyState}))})}if(t){let e=t.getAudioTracks();$.debug(`[SourceSwitchManager] Current stream audio tracks before video stop`,{currentStreamId:t.id,currentStreamAudioTracksCount:e.length,currentStreamAudioTrackIds:e.map(e=>({id:e.id,readyState:e.readyState,enabled:e.enabled}))}),Sh(t),this.stopDisplayTracks(t),$.debug(`[SourceSwitchManager] Current stream audio tracks after video stop`,{currentStreamId:t.id,currentStreamAudioTracksCount:t.getAudioTracks().length,currentStreamAudioTrackIds:t.getAudioTracks().map(e=>({id:e.id,readyState:e.readyState,enabled:e.enabled}))})}$.debug(`[SourceSwitchManager] Original camera stream state before source change`,{hasOriginalCameraStream:!!this.originalCameraStream,originalCameraStreamId:this.originalCameraStream?.id,originalCameraStreamAudioTracksCount:this.originalCameraStream?.getAudioTracks().length,originalCameraStreamAudioTrackId:this.originalCameraStream?.getAudioTracks()[0]?.id,originalCameraStreamAudioTrackReadyState:this.originalCameraStream?.getAudioTracks()[0]?.readyState,originalCameraStreamAudioTrackEnabled:this.originalCameraStream?.getAudioTracks()[0]?.enabled}),this.currentSourceType=`camera`,this.callbacks.onSourceChange&&await this.callbacks.onSourceChange(this.currentSourceType),$.debug(`[SourceSwitchManager] handleScreenShareStop completed`,{hasScreenShareStream:!!this.screenShareStream,currentSourceType:this.currentSourceType,hasOriginalCameraStream:!!this.originalCameraStream,originalCameraStreamId:this.originalCameraStream?.id,originalCameraStreamAudioTracksCount:this.originalCameraStream?.getAudioTracks().length,originalCameraStreamAudioTrackId:this.originalCameraStream?.getAudioTracks()[0]?.id,originalCameraStreamAudioTrackReadyState:this.originalCameraStream?.getAudioTracks()[0]?.readyState})}async applyCameraStream(e,t){this.streamManager.setMediaStream(e);let n=this.currentSourceType!==`camera`;this.currentSourceType=`camera`,n&&this.callbacks.onSourceChange&&await this.callbacks.onSourceChange(this.currentSourceType),t&&await this.streamManager.switchVideoSource(e),this.callbacks.onPreviewUpdate&&await this.callbacks.onPreviewUpdate(e)}async toggleSource(){if(!this.streamManager.isRecording())return;let e;e=this.currentSourceType===`camera`?this.switchToScreen():this.switchToCamera(),await e.catch(e=>{this.handleToggleError(e)})}async switchToScreen(){let e=await this.switchToScreenCapture();if(!e){Ph(this.callbacks);return}Nh(this.callbacks,`Switching to screen...`),await this.streamManager.switchVideoSource(e),this.callbacks.onPreviewUpdate&&await this.callbacks.onPreviewUpdate(e),Ph(this.callbacks)}handleToggleError(e){Ph(this.callbacks);let t=i(e),n=!1;t.includes(`NotAllowedError`)&&(n=!0),t.includes(`AbortError`)&&(n=!0),n&&this.currentSourceType===`screen`&&this.switchToCamera().catch(e=>{this.callbacks.onError&&this.callbacks.onError(this.createError(e))}),!n&&this.callbacks.onError&&this.callbacks.onError(this.createError(e))}async handleRecordingStop(){if(this.currentSourceType!==`screen`){this.cleanup();return}await Promise.resolve().then(async()=>{let e=this.streamManager.getStream();e&&(Mh(e,this.getScreenShareDependencies()),Sh(e));let t=await this.getCameraStream();if(!t)throw Error(Rh);this.streamManager.setMediaStream(t),this.currentSourceType=`camera`,this.callbacks.onSourceChange&&await this.callbacks.onSourceChange(this.currentSourceType),this.callbacks.onPreviewUpdate&&await this.callbacks.onPreviewUpdate(t)}).catch(e=>{throw this.callbacks.onError&&this.callbacks.onError(this.createError(e)),e}),this.cleanup()}cleanup(){this.screenShareStream&&=(Mh(this.screenShareStream,this.getScreenShareDependencies()),this.stopScreenShareStreamTracks(this.screenShareStream),null);let e=this.streamManager.getStream();e&&Mh(e,this.getScreenShareDependencies()),this.screenShareTrackEndHandler=null,this.originalCameraStream=null,this.setOriginalCameraConstraints(null)}setCallbacks(e){this.callbacks={...this.callbacks,...e}}};let Bh=Object.freeze({width:{ideal:Bt.width||1920},height:{ideal:Bt.height||1080},frameRate:{ideal:Bt.fps||30}}),Vh=Object.freeze({video:Bh,audio:!0});Object.freeze({mimeType:`video/webm;codecs=vp9,opus`});var Hh=class{constructor(e={}){this.mediaStream=null,this.state=`idle`,this.eventListeners=new Map,this.selectedAudioDeviceId=null,this.selectedVideoDeviceId=null,this.streamConfig={...Vh,...e}}getState(){return this.state}getStream(){return this.mediaStream}getAudioStreamForAnalysis(){return this.mediaStream&&this.mediaStream.getAudioTracks().length>0?this.mediaStream:null}isActive(){return this.state===`active`||this.state===`recording`}on(e,t){this.eventListeners.has(e)||this.eventListeners.set(e,new Set);let n=this.eventListeners.get(e);return n&&n.add(t),()=>{this.off(e,t)}}off(e,t){let n=this.eventListeners.get(e);n&&n.delete(t)}once(e,t){let n=(r=>{t(r),this.off(e,n)});return this.on(e,n)}emit(e,t){let n=this.eventListeners.get(e);if(n)for(let e of n)try{e(t)}catch{}}setState(e){if(this.state===e)return;let t=this.state;this.state=e,this.emit(`statechange`,{state:e,previousState:t})}setAudioDevice(e){this.selectedAudioDeviceId=e}setVideoDevice(e){this.selectedVideoDeviceId=e}getAudioDevice(){return this.selectedAudioDeviceId}getVideoDevice(){return this.selectedVideoDeviceId}async getAvailableDevices(){try{let e=await navigator.mediaDevices.enumerateDevices();return{audioinput:e.filter(e=>e.kind===`audioinput`),videoinput:e.filter(e=>e.kind===`videoinput`)}}catch(e){throw Error(`Failed to enumerate devices: ${i(e)}`)}}buildDeviceConstraints(e,t){return e?typeof t==`object`?{...t,deviceId:{exact:e}}:{deviceId:{exact:e}}:t}buildVideoConstraints(e){return this.buildDeviceConstraints(e,this.streamConfig.video)}buildAudioConstraints(e){return this.buildDeviceConstraints(e,this.streamConfig.audio)}async startStream(){if($.debug(`[StreamManager] startStream called`,{hasExistingStream:!!this.mediaStream,selectedVideoDeviceId:this.selectedVideoDeviceId,selectedAudioDeviceId:this.selectedAudioDeviceId}),this.mediaStream){let e=this.mediaStream.getVideoTracks()[0];if(this.selectedVideoDeviceId===null)if(e?.getSettings?.()?.deviceId)$.debug(`[StreamManager] Stopping existing stream to recreate`),this.stopStream();else return $.debug(`[StreamManager] Reusing existing stream`),this.mediaStream;if(e?.getSettings&&e.getSettings().deviceId===this.selectedVideoDeviceId)return $.debug(`[StreamManager] Existing stream matches device, reusing`),this.mediaStream;$.debug(`[StreamManager] Device changed, stopping existing stream`),this.stopStream()}this.setState(`starting`),$.debug(`[StreamManager] State set to 'starting'`);try{$.debug(`[StreamManager] Building constraints`,{selectedVideoDeviceId:this.selectedVideoDeviceId,selectedAudioDeviceId:this.selectedAudioDeviceId});let e={video:this.buildVideoConstraints(this.selectedVideoDeviceId),audio:this.buildAudioConstraints(this.selectedAudioDeviceId)};return $.debug(`[StreamManager] Requesting media stream with constraints`,{hasVideo:!!e.video,hasAudio:!!e.audio}),this.mediaStream=await gh().getUserMedia(e),$.info(`[StreamManager] Media stream obtained`,{streamId:this.mediaStream.id,videoTracks:this.mediaStream.getVideoTracks().length,audioTracks:this.mediaStream.getAudioTracks().length}),this.setState(`active`),$.debug(`[StreamManager] State set to 'active'`),$.debug(`[StreamManager] Emitting streamstart event`),this.emit(`streamstart`,{stream:this.mediaStream}),this.mediaStream}catch(e){let t=e instanceof Error?e:Error(i(e));throw $.error(`[StreamManager] Failed to start stream`,t),this.setState(`error`),this.emit(`error`,{error:t}),t}}stopStream(){if(this.mediaStream){for(let e of this.mediaStream.getTracks())e.stop();this.mediaStream=null}this.state!==`idle`&&(this.setState(`idle`),this.emit(`streamstop`,void 0))}stopStreamTracks(e){for(let t of e.getTracks())t.stop()}isTrackLive(e){return e!==void 0&&e.readyState===`live`}async tryReplaceTrack(e,t,n){let r=e.replaceTrack;if(typeof r!=`function`)return!1;try{await r.call(e,t),e.stop();for(let e of n.getTracks())e!==t&&e.stop();return t.stop(),!0}catch{return!1}}recreateStreamWithNewTrack(e,t,n){for(let t of n.getTracks())t!==e&&t.stop();let r=[e];this.isTrackLive(t)&&t&&r.push(t);let i=new MediaStream(r);if(this.mediaStream)for(let e of this.mediaStream.getTracks())e!==t&&e.stop();return i}async switchDeviceTrack(e,t,n){if(!this.mediaStream)throw Error(`No active stream to switch device`);let r=t===`video`?this.mediaStream.getVideoTracks()[0]:this.mediaStream.getAudioTracks()[0],i=t===`video`?this.mediaStream.getAudioTracks()[0]:this.mediaStream.getVideoTracks()[0];if(!r){let e=t===`video`?`video`:`audio`;throw Error(`No ${e} track in current stream`)}let a={[t]:this.buildDeviceConstraints(e,n)},o=await gh().getUserMedia(a),s=t===`video`?o.getVideoTracks()[0]:o.getAudioTracks()[0];if(!s){this.stopStreamTracks(o);let e=t===`video`?`video`:`audio`;throw Error(`Failed to get new ${e} track`)}return await this.tryReplaceTrack(r,s,o)||(r.stop(),this.mediaStream=this.recreateStreamWithNewTrack(s,i,o)),t===`video`?(this.selectedVideoDeviceId=e,this.emit(`videosourcechange`,{stream:this.mediaStream})):this.selectedAudioDeviceId=e,this.mediaStream}switchVideoDevice(e){return this.switchDeviceTrack(e,`video`,this.streamConfig.video)}switchAudioDevice(e){return this.switchDeviceTrack(e,`audio`,this.streamConfig.audio)}setMediaStream(e){this.mediaStream=e}setAudioTracksEnabled(e){if(!this.mediaStream)return;let t=this.mediaStream.getAudioTracks();for(let n of t)n.enabled=e}destroy(){this.stopStream(),this.eventListeners.clear(),this.setState(`idle`)}};let Uh=[`Bytes`,`KB`,`MB`,`GB`],Wh=1024;function Gh(e){if(e===0)return`0 Bytes`;let t=Math.floor(Math.log(e)/Math.log(Wh));return`${Math.round(e/Wh**t*100)/100} ${Uh[t]}`}function Kh(e){let t=Math.floor(e/3600),n=Math.floor(e%3600/60),r=e%60;return t>0?`${t.toString().padStart(2,`0`)}:${n.toString().padStart(2,`0`)}:${r.toString().padStart(2,`0`)}`:`${n.toString().padStart(2,`0`)}:${r.toString().padStart(2,`0`)}`}var qh=class{constructor(){this.recordingStartTime=0,this.totalPausedTime=0,this.pauseStartTime=null,this.intervals=[],this.currentIntervalStart=null,this.isTracking=!1,this.visibilityChangeHandler=this.handleVisibilityChange.bind(this),this.blurHandler=this.handleBlur.bind(this),this.focusHandler=this.handleFocus.bind(this)}start(e){this.isTracking||(this.recordingStartTime=e,this.totalPausedTime=0,this.pauseStartTime=null,this.intervals=[],this.currentIntervalStart=null,this.isTracking=!0,typeof document<`u`&&document.addEventListener(`visibilitychange`,this.visibilityChangeHandler),typeof window<`u`&&(window.addEventListener(`blur`,this.blurHandler),window.addEventListener(`focus`,this.focusHandler)),this.checkInitialState())}pause(){!this.isTracking||this.pauseStartTime!==null||(this.pauseStartTime=Date.now(),this.endCurrentIntervalIfActive())}resume(){if(!this.isTracking||this.pauseStartTime===null)return;let e=Date.now()-this.pauseStartTime;this.totalPausedTime+=e,this.pauseStartTime=null}getIntervals(){return this.endCurrentIntervalIfActive(),this.intervals.map(e=>({start:this.normalizeTimestamp(e.start),end:this.normalizeTimestamp(e.end)}))}reset(){this.intervals=[],this.currentIntervalStart=null,this.totalPausedTime=0,this.pauseStartTime=null}cleanup(){this.isTracking=!1,this.endCurrentIntervalIfActive(),typeof document<`u`&&document.removeEventListener(`visibilitychange`,this.visibilityChangeHandler),typeof window<`u`&&(window.removeEventListener(`blur`,this.blurHandler),window.removeEventListener(`focus`,this.focusHandler)),this.reset()}checkInitialState(){typeof document>`u`||document.visibilityState===`hidden`&&this.startInterval()}handleVisibilityChange(){typeof document>`u`||(document.visibilityState===`hidden`?this.startInterval():this.endCurrentIntervalIfActive())}handleBlur(){this.startInterval()}handleFocus(){this.endCurrentIntervalIfActive()}startInterval(){this.currentIntervalStart!==null||!this.isTracking||this.pauseStartTime===null&&(this.currentIntervalStart=Date.now())}endCurrentIntervalIfActive(){if(this.currentIntervalStart===null)return;let e=Date.now(),t=this.currentIntervalStart;e>t&&this.intervals.push({start:t,end:e}),this.currentIntervalStart=null}normalizeTimestamp(e){let t=(e-this.recordingStartTime-this.totalPausedTime)/1e3;return Math.max(0,t)}};let Jh=1e3;var Yh=class{constructor(e){this.recordingStartTime=0,this.recordingTimer=null,this.pauseStartTime=null,this.totalPausedTime=0,this.streamProcessor=null,this.bufferSizeUpdateInterval=null,this.tabVisibilityTracker=null,this.visibilityChangeHandler=null,this.blurHandler=null,this.focusHandler=null,this.streamManager=e}isRecording(){return this.streamManager.getState()===`recording`}getStreamProcessor(){return this.streamProcessor}getAudioStreamForAnalysis(){if(this.streamProcessor){let e=this.streamProcessor.getAudioStreamForAnalysis();if(e)return e}return this.streamManager.getAudioStreamForAnalysis()}async startRecording(e,t,n,r){let i=this.streamManager.getStream();if($.debug(`[StreamRecordingState] startRecording called`,{hasMediaStream:!!i,isRecording:this.isRecording(),hasProcessor:!!e,audioTracks:i?.getAudioTracks().length||0}),!i)throw Error(`Stream must be started before recording`);if(this.isRecording())return $.debug(`[StreamRecordingState] Already recording, returning`),Promise.resolve();let a=await $m({requiresAudio:i.getAudioTracks().length>0,requiresWatermark:t.watermark!==void 0});if(!a.isSupported)throw kt({missingCapabilities:a.missing,resolutionStage:`feature-preflight`});this.streamProcessor=e,$.debug(`[StreamRecordingState] StreamProcessor assigned, setting callbacks`),e.setOnMuteStateChange(e=>{this.streamManager.emit(`audiomutetoggle`,{muted:e})}),e.setOnSourceChange(e=>{this.streamManager.emit(`videosourcechange`,{stream:e})}),this.bufferSizeUpdateInterval=window.setInterval(()=>{if(!this.streamProcessor)return;let e=this.streamProcessor.getBufferSize(),t=Gh(e);this.streamManager.emit(`recordingbufferupdate`,{size:e,formatted:t})},Jh),this.resetRecordingState();let o=n&&r?{enabled:!0,text:r,recordingStartTime:this.recordingStartTime}:void 0;$.debug(`[StreamRecordingState] Overlay config`,{enableTabVisibilityOverlay:n,hasOverlayText:!!r,overlayText:r,overlayConfig:o}),$.debug(`[StreamRecordingState] Starting processing`),await e.startProcessing(i,t,o),$.info(`[StreamRecordingState] Processing started and worker ready`),n&&($.debug(`[StreamRecordingState] Setting up tab visibility tracking`,{recordingStartTime:this.recordingStartTime}),this.tabVisibilityTracker=new qh,this.tabVisibilityTracker.start(this.recordingStartTime),this.setupVisibilityUpdates(e)),this.streamManager.setState(`recording`),this.streamManager.emit(`recordingstart`,{recorder:null}),this.startRecordingTimer()}async stopRecording(){if($.debug(`[StreamRecordingState] stopRecording called`,{hasStreamProcessor:!!this.streamProcessor,isRecording:this.isRecording()}),!(this.streamProcessor&&this.isRecording()))throw Error(`Not currently recording`);this.streamManager.setState(`stopping`),this.clearRecordingTimer(),this.clearBufferSizeInterval(),this.resetPauseState(),this.cleanupVisibilityUpdates();let e=[];this.tabVisibilityTracker?(e=this.tabVisibilityTracker.getIntervals(),$.debug(`[StreamRecordingState] Tab visibility intervals collected`,{intervalsCount:e.length,intervals:e}),this.tabVisibilityTracker.cleanup(),this.tabVisibilityTracker=null):$.debug(`[StreamRecordingState] No tab visibility tracker was active`),$.debug(`[StreamRecordingState] Finalizing stream processor`);let t=await this.streamProcessor.finalize();return $.info(`[StreamRecordingState] Stream processor finalized`,{blobSize:t.blob.size,hasBlob:!!t.blob}),this.streamManager.setState(`active`),this.streamManager.emit(`recordingstop`,{blob:t.blob,mimeType:`video/mp4`}),this.streamProcessor=null,$.debug(`[StreamRecordingState] StreamProcessor cleared`),{blob:t.blob,tabVisibilityIntervals:e}}pauseRecording(){this.clearRecordingTimer(),this.pauseStartTime===null&&(this.pauseStartTime=Date.now()),this.tabVisibilityTracker&&this.tabVisibilityTracker.pause(),this.streamProcessor&&this.isRecording()&&this.streamProcessor.pause()}resumeRecording(){if(this.pauseStartTime!==null){let e=Date.now()-this.pauseStartTime;this.totalPausedTime+=e,this.pauseStartTime=null}this.tabVisibilityTracker&&this.tabVisibilityTracker.resume(),this.startRecordingTimer(),this.streamProcessor&&this.isRecording()&&this.streamProcessor.resume()}toggleMute(){hh(this.streamProcessor,`StreamProcessor`).toggleMute()}muteAudio(){this.streamProcessor?(this.streamProcessor.isMutedState()||this.streamProcessor.toggleMute(),this.streamManager.setAudioTracksEnabled(!1)):this.streamManager.getStream()&&(this.streamManager.setAudioTracksEnabled(!1),this.streamManager.emit(`audiomutetoggle`,{muted:!0}))}unmuteAudio(){this.streamProcessor?(this.streamProcessor.isMutedState()&&this.streamProcessor.toggleMute(),this.streamManager.setAudioTracksEnabled(!0)):this.streamManager.getStream()&&(this.streamManager.setAudioTracksEnabled(!0),this.streamManager.emit(`audiomutetoggle`,{muted:!1}))}isMuted(){if(this.streamProcessor)return this.streamProcessor.isMutedState();let e=this.streamManager.getStream();if(e){let t=e.getAudioTracks();return t.length>0&&t.every(e=>!e.enabled)}return!1}async switchVideoSource(e){await hh(this.streamProcessor,`StreamProcessor`).switchVideoSource(e)}getCurrentVideoSource(){return mh(hh(this.streamProcessor,`StreamProcessor`).getCurrentVideoSource(),`Current video source is not available`)}formatTimeElapsed(e){let t=Math.floor(e/60),n=Math.floor(e%60);return`${t.toString().padStart(2,`0`)}:${n.toString().padStart(2,`0`)}`}startRecordingTimer(){this.recordingTimer=window.setInterval(()=>{let e=(Date.now()-this.recordingStartTime-this.totalPausedTime)/1e3,t=this.formatTimeElapsed(e);this.streamManager.emit(`recordingtimeupdate`,{elapsed:e,formatted:t})},Jh)}clearRecordingTimer(){this.recordingTimer!==null&&(clearInterval(this.recordingTimer),this.recordingTimer=null)}clearBufferSizeInterval(){this.bufferSizeUpdateInterval!==null&&(clearInterval(this.bufferSizeUpdateInterval),this.bufferSizeUpdateInterval=null)}resetRecordingState(){this.recordingStartTime=performance.now(),this.totalPausedTime=0,this.pauseStartTime=null}resetPauseState(){this.totalPausedTime=0,this.pauseStartTime=null}setupVisibilityUpdates(e){if(typeof document>`u`||typeof window>`u`){$.warn(`[StreamRecordingState] Cannot setup visibility updates - document/window not available`);return}if(this.visibilityChangeHandler=()=>{if(typeof document>`u`)return;let t=document.visibilityState===`hidden`,n=performance.now();$.debug(`[StreamRecordingState] Visibility change`,{isHidden:t,timestamp:n,visibilityState:document.visibilityState}),e.updateTabVisibility(t,n)},this.blurHandler=()=>{let t=performance.now();$.debug(`[StreamRecordingState] Window blur`,{timestamp:t}),e.updateTabVisibility(!0,t)},this.focusHandler=()=>{let t=performance.now();$.debug(`[StreamRecordingState] Window focus`,{timestamp:t}),e.updateTabVisibility(!1,t)},document.addEventListener(`visibilitychange`,this.visibilityChangeHandler),window.addEventListener(`blur`,this.blurHandler),window.addEventListener(`focus`,this.focusHandler),document.visibilityState===`hidden`){let t=performance.now();$.debug(`[StreamRecordingState] Initial state is hidden`,{timestamp:t}),e.updateTabVisibility(!0,t)}else $.debug(`[StreamRecordingState] Initial state is visible`)}cleanupVisibilityUpdates(){this.visibilityChangeHandler&&typeof document<`u`&&(document.removeEventListener(`visibilitychange`,this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.blurHandler&&typeof window<`u`&&(window.removeEventListener(`blur`,this.blurHandler),this.blurHandler=null),this.focusHandler&&typeof window<`u`&&(window.removeEventListener(`focus`,this.focusHandler),this.focusHandler=null)}destroy(){this.streamProcessor&&=(this.streamProcessor.cancel().catch(()=>{}),null),this.cleanupVisibilityUpdates(),this.tabVisibilityTracker&&=(this.tabVisibilityTracker.cleanup(),null),this.clearRecordingTimer(),this.clearBufferSizeInterval()}},Xh=class{constructor(e={}){this.streamManager=new Hh(e),this.recordingState=new Yh(this.streamManager)}getState(){return this.streamManager.getState()}getStream(){return this.streamManager.getStream()}getAudioStreamForAnalysis(){return this.recordingState.getAudioStreamForAnalysis()}isRecording(){return this.recordingState.isRecording()}isActive(){return this.streamManager.isActive()}on(e,t){return this.streamManager.on(e,t)}off(e,t){this.streamManager.off(e,t)}once(e,t){return this.streamManager.once(e,t)}setAudioDevice(e){this.streamManager.setAudioDevice(e)}setVideoDevice(e){this.streamManager.setVideoDevice(e)}getAudioDevice(){return this.streamManager.getAudioDevice()}getVideoDevice(){return this.streamManager.getVideoDevice()}async getAvailableDevices(){return await this.streamManager.getAvailableDevices()}async startStream(){return await this.streamManager.startStream()}stopStream(){this.streamManager.stopStream()}switchVideoDevice(e){return this.streamManager.switchVideoDevice(e)}switchAudioDevice(e){return this.streamManager.switchAudioDevice(e)}async startRecording(e,t,n,r){return await this.recordingState.startRecording(e,t,n,r)}async stopRecording(){return await this.recordingState.stopRecording()}pauseRecording(){this.recordingState.pauseRecording()}resumeRecording(){this.recordingState.resumeRecording()}toggleMute(){this.recordingState.toggleMute()}muteAudio(){this.recordingState.muteAudio()}unmuteAudio(){this.recordingState.unmuteAudio()}isMuted(){return this.recordingState.isMuted()}async switchVideoSource(e){return await this.recordingState.switchVideoSource(e)}setMediaStream(e){this.streamManager.setMediaStream(e)}getCurrentVideoSource(){return this.recordingState.getCurrentVideoSource()}destroy(){this.recordingState.destroy(),this.streamManager.destroy()}};let Zh=`VIDTREO_INSTALLATION_ID`,Qh=`unknown`,$h=new Map;function eg(e){let t=e.storageProvider,n=t?.getItem(Zh);if(n)return $.debug(`Using existing installation ID from storage`,{installationId:n}),n;let r=tg(e);return t?.setItem(Zh,r),$.debug(`Created new installation ID`,{installationId:r}),r}function tg(e){let t=e.cryptoProvider;if(t?.getRandomValues){let e=new Uint8Array(16);return t.getRandomValues(e),Array.from(e).map(e=>e.toString(16).padStart(2,`0`)).join(``)}let n=e.nowProvider().toString(16),r=e.randomProvider();return`${n}-${Math.floor(r*1e9).toString(16)}`}let ng=[`sdk.init.started`,`sdk.init.succeeded`,`sdk.init.failed`],rg=[`stream.error`],ig={"sdk.init.started":`lifecycle`,"sdk.init.succeeded":`lifecycle`,"sdk.init.failed":`error`,"preview.start.succeeded":`interaction`,"preview.start.failed":`error`,"recording.start.requested":`interaction`,"recording.start.succeeded":`interaction`,"recording.start.failed":`error`,"recording.stop.requested":`interaction`,"recording.stop.succeeded":`interaction`,"recording.stop.failed":`error`,"upload.started":`performance`,"upload.succeeded":`performance`,"upload.failed":`error`,"source.switch.requested":`interaction`,"source.switch.succeeded":`interaction`,"source.switch.failed":`error`,"stream.error":`error`};var ag=class{constructor(e,t){this.pendingEvents=[],this.flushTimeoutId=null,this.throttledEventTimestamps=new Map,this.config=e,this.dependencies=t,this.installationId=eg(this.dependencies),$.debug(`TelemetryClient initialized`,{installationId:this.installationId,backendUrl:e.backendUrl})}triggerTelemetryEvent(e){try{let t=this.dependencies.nowProvider();if(this.shouldSkipEvent(e.name,t))return;let n=ig[e.name],r=this.buildError(e.error),i=this.buildFingerprint(),a=this.buildContext(),o=this.mergeProperties(this.buildBaseProperties(i),e),s={event:e.name,category:n,timestamp:t,installationId:this.installationId,fingerprint:i,sdkVersion:`1.2.0`,context:a,properties:o,error:r};this.markEventTracking(e.name,t),this.enqueueEvent(s)}catch(t){$.error(`Telemetry event failed`,{eventName:e.name,error:i(t)})}}enqueueEvent(e){try{if(this.pendingEvents=[...this.pendingEvents,e],this.pendingEvents.length>=10){this.flushQueue();return}this.scheduleFlush()}catch(e){$.error(`Failed to enqueue telemetry event`,{error:i(e)})}}scheduleFlush(){this.flushTimeoutId||=this.dependencies.setTimeoutFunction(()=>{this.flushQueue()},1e3)}flushQueue(){try{if(this.pendingEvents.length===0){this.clearFlushTimer();return}let e=this.pendingEvents;this.pendingEvents=[],this.clearFlushTimer();let t=this.buildRequestPayload(e);$.debug(`Telemetry batch flush`,{eventsCount:t.events.length}),this.sendPayload(t).catch(()=>null)}catch(e){$.error(`Failed to flush telemetry queue`,{error:i(e)})}}clearFlushTimer(){this.flushTimeoutId&&=(this.dependencies.clearTimeoutFunction(this.flushTimeoutId),null)}buildRequestPayload(e){return{events:[...e]}}shouldSkipEvent(e,t){if(this.isOneTimeEvent(e)){let t=this.getOneTimeCacheKey(e);if($h.get(t))return $.debug(`Telemetry event skipped (dedupe)`,{event:e}),!0}if(this.isThrottledEvent(e)){let n=this.throttledEventTimestamps.get(e);if(n!==void 0&&t-n<5e3)return $.debug(`Telemetry event skipped (throttle)`,{event:e,lastSent:n}),!0}return!1}markEventTracking(e,t){if(this.isOneTimeEvent(e)){let t=this.getOneTimeCacheKey(e);$h.set(t,!0)}this.isThrottledEvent(e)&&(this.throttledEventTimestamps=this.updateNumberMap(this.throttledEventTimestamps,e,t))}updateNumberMap(e,t,n){let r=new Map(e);return r.set(t,n),r}getOneTimeCacheKey(e){return`${this.installationId}:${e}`}isOneTimeEvent(e){return ng.includes(e)}isThrottledEvent(e){return rg.includes(e)}buildBaseProperties(e){let t={},n=e.userAgent,r=this.getBrowserName(n);return r&&(t={...t,browserName:r}),t}mergeProperties(e,t){let n=t.properties;if(!(Object.keys(e).length===0&&!n)){if(Object.keys(e).length>0&&n)return{...e,...n};if(Object.keys(e).length>0)return{...e};if(n)return{...n}}}buildFingerprint(){let e=this.dependencies.navigatorProvider;if(!e)return{};let t={userAgent:e.userAgent,language:e.language,platform:e.platform};e.hardwareConcurrency&&(t={...t,hardwareConcurrency:e.hardwareConcurrency});let n=this.getDeviceMemory(e);return n!==null&&(t={...t,deviceMemory:n}),t}buildContext(){let e=this.config.pageUrl,t=this.config.referrerUrl;if(!e){let t=this.dependencies.locationProvider;t&&(e=t.href)}if(!t){let e=this.dependencies.documentProvider;if(e){let n=e.referrer;n&&(t=n)}}return{sessionId:this.config.sessionId,userId:this.config.userId,environmentId:this.config.environmentId,appVersion:this.config.appVersion,release:this.config.release,pageUrl:e,referrerUrl:t,sdkLocation:this.config.sdkLocation,clientLocation:this.config.clientLocation}}buildError(e){if(!e)return;let t={message:i(e)};return e instanceof Error&&(e.name&&(t.code=e.name),e.stack&&(t.stack=e.stack)),t}getBrowserName(e){return e?e.includes(`Edg`)?`edge`:e.includes(`Chrome`)?`chrome`:e.includes(`Firefox`)?`firefox`:e.includes(`Safari`)?`safari`:Qh:Qh}getDeviceMemory(e){let t=e;return t.deviceMemory?t.deviceMemory:null}async sendPayload(e){let t=this.buildTelemetryEndpoint(),n={method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${this.config.apiKey}`},body:JSON.stringify(e)};$.debug(`Sending telemetry to endpoint`,{endpoint:t,payloadSize:JSON.stringify(e).length,hasApiKey:!!this.config.apiKey}),await this.dependencies.fetchFunction(t,n).catch(e=>($.error(`Failed to send telemetry`,{endpoint:t,error:i(e)}),null))}buildTelemetryEndpoint(){return this.config.endpoint?this.config.endpoint:`${this.config.backendUrl}/api/v1/telemetry`}};function og(){let e=typeof window<`u`,t=typeof document<`u`,n=fetch,r=null,i=null,a=null,o=null,s=null,c=setTimeout,l=clearTimeout;return e&&(n=window.fetch.bind(window),r=window.crypto,i=window.localStorage,a=window.navigator,o=window.location,c=window.setTimeout.bind(window),l=window.clearTimeout.bind(window)),t&&(s=document),{fetchFunction:n,cryptoProvider:r,storageProvider:i,navigatorProvider:a,locationProvider:o,documentProvider:s,nowProvider:()=>Date.now(),randomProvider:()=>Math.random(),setTimeoutFunction:c,clearTimeoutFunction:l}}function sg(e,t,n){return new ag({apiKey:e,backendUrl:t,endpoint:n?.endpoint,sessionId:n?.sessionId,userId:n?.userId,environmentId:n?.environmentId,appVersion:n?.appVersion,release:n?.release,pageUrl:n?.pageUrl,referrerUrl:n?.referrerUrl,sdkLocation:n?.sdkLocation,clientLocation:n?.clientLocation},og())}var cg=class{constructor(e,t){this.isProcessing=!1,this.retryTimeoutId=null,this.callbacks={},this.storageService=e,this.uploadService=t,this.networkOnlineHandler=()=>{this.processQueue().catch(e=>{let t=i(e);this.callbacks.onUploadError?.(`network-recovery`,Error(t))})},window.addEventListener(`online`,this.networkOnlineHandler),this.processingIntervalId=window.setInterval(()=>{this.processQueue().catch(e=>{let t=i(e);this.callbacks.onUploadError?.(`processing-loop`,Error(t))})},5e3)}destroy(){this.clearTimer(this.processingIntervalId,clearInterval),this.clearTimer(this.retryTimeoutId,clearTimeout),window.removeEventListener(`online`,this.networkOnlineHandler)}setCallbacks(e){this.callbacks=e}async queueUpload(e){let t=await this.storageService.savePendingUpload(e);return this.processQueue(),t}async processQueue(){if(!this.isProcessing){this.isProcessing=!0;try{if(!this.storageService.isInitialized())throw Error(`Database not initialized`);let e=await this.storageService.getPendingUploads(`pending`);if(e.length>0){let t=this.getOldestUpload(e);await this.processUpload(t),this.isProcessing=!1;return}let t=(await this.storageService.getPendingUploads(`failed`)).filter(e=>e.retryCount<10);if(t.length>0){let e=this.getOldestFailedUpload(t),n=this.calculateRetryDelay(e.retryCount),r=Date.now()-e.updatedAt;if(r>=n)await this.storageService.updateUploadStatus(e.id,{status:`pending`,retryCount:e.retryCount}),await this.processUpload(e);else{let e=n-r;this.scheduleRetry(e)}}this.isProcessing=!1}catch(e){throw this.isProcessing=!1,Error(`Error processing upload queue: ${i(e)}`)}}}getPendingUploads(){return this.storageService.getPendingUploads()}async getStats(){let e=await this.storageService.getPendingUploads(),t={pending:0,uploading:0,failed:0,total:e.length};for(let n of e)n.status===`pending`?t.pending+=1:n.status===`uploading`?t.uploading+=1:n.status===`failed`&&(t.failed+=1);return t}getOldestUpload(e){if(e.length===0)throw Error(`Cannot get oldest upload from empty array`);return e.sort((e,t)=>e.createdAt-t.createdAt)[0]}getOldestFailedUpload(e){if(e.length===0)throw Error(`Cannot get oldest failed upload from empty array`);return e.sort((e,t)=>e.updatedAt-t.updatedAt)[0]}async processUpload(e){try{await this.storageService.updateUploadStatus(e.id,{status:`uploading`});let t=await this.uploadService.uploadVideo(e.blob,{apiKey:e.apiKey,backendUrl:e.backendUrl,filename:e.filename,metadata:e.metadata,userMetadata:e.userMetadata,onProgress:t=>{this.callbacks.onUploadProgress?.(e.id,t)}});await this.storageService.deleteUpload(e.id),this.callbacks.onUploadComplete?.(e.id,t)}catch(t){let n=i(t),r=e.retryCount+1;if(await this.storageService.updateUploadStatus(e.id,{status:`failed`,retryCount:r,lastError:n}),r>=10)this.callbacks.onUploadError?.(e.id,Error(`Upload failed after 10 attempts: ${n}`));else{let e=this.calculateRetryDelay(r);this.scheduleRetry(e)}}}calculateRetryDelay(e){let t=2e3*1.5**(e-1);return Math.min(t,3e5)}scheduleRetry(e){this.clearTimer(this.retryTimeoutId,clearTimeout),this.retryTimeoutId=window.setTimeout(()=>{this.retryTimeoutId=null,this.processQueue()},e)}clearTimer(e,t){e!==null&&t(e)}},lg=class{uploadVideo(e,t){if(!t.filename)throw Error(`Filename is required`);if(!e.type||e.type.trim()===``)throw Error(`Blob type is required`);return this.uploadVideoFile(e,t)}uploadVideoFile(e,t){return new Promise((n,r)=>{let i=new XMLHttpRequest;if(t.onProgress){let e=t.onProgress;i.upload.addEventListener(`progress`,t=>{t.lengthComputable&&e(t.loaded/t.total)})}i.addEventListener(`load`,()=>{if(i.status>=200&&i.status<=299){this.parseSuccessResponse(i,n,r);return}this.parseErrorResponse(i,r)}),i.addEventListener(`error`,()=>{r(Error(`Network error during upload`))}),i.addEventListener(`abort`,()=>{r(Error(`Upload was aborted`))});let a=`${t.backendUrl}/api/v1/videos/upload`;i.open(`POST`,a),i.setRequestHeader(`Authorization`,`Bearer ${t.apiKey}`);let o=new FormData;o.append(`file`,e,t.filename);let s={filename:t.filename,mimeType:e.type};t.userMetadata&&(s.userMetadata=t.userMetadata),o.append(`metadata`,JSON.stringify(s)),i.send(o)})}parseSuccessResponse(e,t,n){let r=this.safeParseJsonFromXhr(e);if(!r){n(Error(`Failed to parse upload response: invalid JSON`));return}let i=r.data;if(!i){n(Error(`Failed to parse upload response: missing data`));return}t({id:i.id,publicId:i.publicId,filename:i.filename,fileSize:i.fileSize,mimeType:i.mimeType,duration:i.duration,status:i.status,uploadUrl:i.uploadUrl,createdAt:i.createdAt})}parseErrorResponse(e,t){let n=this.safeParseJsonFromXhr(e);if(n&&typeof n==`object`&&`error`in n&&typeof n.error==`string`){t(Error(n.error));return}t(Error(`Upload failed: ${e.status} ${e.statusText}`))}safeParseJsonFromXhr(e){if(!e.responseText||e.responseText.trim()===``)return null;let t=e.responseText.trim();if(!(t.startsWith(`{`)&&t.endsWith(`}`))||t.length<2)return null;let n=JSON.parse(e.responseText);return typeof n==`object`&&n?n:null}};let ug=e=>{},dg=e=>{},fg=e=>{},pg=()=>{},mg=e=>{},hg=(e,t)=>{},gg=e=>{},_g=e=>{},vg=e=>{},yg=()=>{},bg=e=>{};function xg(e){let t={onProgress:ug,onSuccess:dg,onError:fg,onClearStatus:pg};return e.upload&&(t=e.upload),t}function Sg(e){let t=bg;return e.onStorageCleanupError&&(t=e.onStorageCleanupError),t}function Cg(e,t){let n=e.recording,r=mg;n?.onStateChange&&(r=n.onStateChange);let i=hg;n?.onCountdownUpdate&&(i=n.onCountdownUpdate);let a=gg;n?.onTimerUpdate&&(a=n.onTimerUpdate);let o=_g;n?.onError&&(o=n.onError);let s=vg;n?.onRecordingComplete&&(s=n.onRecordingComplete);let c=yg;return n?.onClearUploadStatus&&(c=n.onClearUploadStatus),{onStateChange:r,onCountdownUpdate:i,onTimerUpdate:a,onError:o,onRecordingComplete:s,onClearUploadStatus:c,onStopAudioTracking:t.stopAudioTracking,onGetConfig:t.getConfig}}function wg(e,t){let n=e.sourceSwitch;return{onSourceChange:n?.onSourceChange,onPreviewUpdate:n?.onPreviewUpdate,onError:n?.onError,onTransitionStart:n?.onTransitionStart,onTransitionEnd:n?.onTransitionEnd,onScreenSelectionStart:()=>{t.isRecording()&&t.updateSourceType(!0)},onScreenSelectionEnd:()=>{t.isRecording()&&t.updateSourceType(!1)},getSelectedCameraDeviceId:t.getSelectedCameraDeviceId,getSelectedMicDeviceId:t.getSelectedMicDeviceId}}function Tg(e){let t=e.getVideoTracks();if(t.length===0)return!1;let n=t[0];return`displaySurface`in n.getSettings()||n.label.toLowerCase().includes(`screen`)||n.label.toLowerCase().includes(`display`)}em();function Eg(e){if(e!==void 0)return typeof e==`number`?e:e===Qf?`low`:e===$f?`medium`:e===ep?`high`:e===tp?`very-high`:`high`}function Dg(e){let t=null,n=0;function r(){if(!t){let n=e.createBlob();t=e.createObjectUrl(n)}return n+=1,t}function i(){n!==0&&(--n,n===0&&(t&&=(e.revokeObjectUrl(t),null)))}return{acquire:r,release:i}}let Og=`vidtreo-audio-worklet`,kg=`audioChunk`,Ag=`setMuted`,jg=`setPaused`,Mg=`shutdown`,Ng=`
123
- const AUDIO_WORKLET_MESSAGE_TYPE_AUDIO_CHUNK = "${kg}";
124
- const AUDIO_WORKLET_MESSAGE_TYPE_SET_MUTED = "${Ag}";
125
- const AUDIO_WORKLET_MESSAGE_TYPE_SET_PAUSED = "${jg}";
126
- const AUDIO_WORKLET_MESSAGE_TYPE_SHUTDOWN = "${Mg}";
122
+ };`],{type:`application/javascript`})}function Fm(){let e=Pm();return URL.createObjectURL(e)}function Im(e){URL.revokeObjectURL(e)}let Lm=`probe`,Rm=`probeResult`,zm=`mediaStreamTrackProcessor`,Bm=`unavailable`,Vm=`unavailable`;function Hm(e,t){return typeof e==`boolean`?e:t}function Um(e){return e.probeResult.hasMediaStreamTrackProcessor?`worker-track`:e.hasMainThreadMediaStreamTrackProcessor?`main-thread-stream`:Bm}function Wm(e){return e.requiresAudio?e.hasMainThreadMediaStreamTrackProcessor&&e.probeResult.hasAudioData?`main-thread-audio-stream`:e.hasAudioContext&&e.hasAudioWorklet?`audio-worklet-chunks`:Vm:`none-required`}function Gm(e,t){return e.includes(t)?e:[...e,t]}function Km(e,t){let n=e;return t.hasWorker||(n=Gm(n,`worker`)),t.probeResult.hasVideoFrame||(n=Gm(n,`videoFrame`)),t.probeResult.hasOffscreenCanvas||(n=Gm(n,`offscreenCanvas`)),t.probeResult.hasReadableStream||(n=Gm(n,`readableStream`)),n}function qm(e,t){let n=e;return t.requiresWatermark&&!t.probeResult.hasCreateImageBitmap&&(n=Gm(n,`createImageBitmap`)),n}function Jm(e,t){let n=e;return t.videoPath===Bm&&(n=Gm(n,zm)),n}function Ym(e,t){let n=e;return t.hasMainThreadMediaStreamTrackProcessor&&t.probeResult.hasAudioData?n:(t.hasMainThreadMediaStreamTrackProcessor||(n=Gm(n,zm)),t.hasMainThreadMediaStreamTrackProcessor&&!t.probeResult.hasAudioData&&(n=Gm(n,`audioData`)),n)}function Xm(e,t){let n=e;return t.hasAudioContext&&t.hasAudioWorklet?n:(t.hasAudioContext||(n=Gm(n,`audioContext`)),t.hasAudioWorklet||(n=Gm(n,`audioWorklet`)),n)}function Zm(e,t){let n=e;return t.requiresAudio&&t.audioPath===Vm?(n=Ym(n,t),n=Xm(n,t),n):n}function Qm(e){let t=[];return t=Km(t,e),t=qm(t,e),t=Jm(t,e),t=Zm(t,e),t}function $m(e,t){return!(e===Bm||t===Vm)}function eh(e,t){return!(!e.hasVideoFrame||!e.hasOffscreenCanvas||!e.hasReadableStream||t&&!e.hasCreateImageBitmap)}async function th(e={}){let t=Hm(e.requiresAudio,!0),n=Hm(e.requiresWatermark,!1),r=typeof Worker<`u`,i=a()!==null,o=typeof AudioWorkletNode<`u`,s=typeof MediaStreamTrackProcessor<`u`,c=await nh(r),l=Um({probeResult:c,hasMainThreadMediaStreamTrackProcessor:s}),u=Wm({requiresAudio:t,hasAudioContext:i,hasAudioWorklet:o,hasMainThreadMediaStreamTrackProcessor:s,probeResult:c}),d=Qm({hasWorker:r,hasAudioContext:i,hasAudioWorklet:o,hasMainThreadMediaStreamTrackProcessor:s,probeResult:c,requiresAudio:t,requiresWatermark:n,videoPath:l,audioPath:u}),f=$m(l,u),p=eh(c,n);return{isSupported:r&&f&&p,missing:d,hasWorker:r,hasAudioContext:i,hasAudioWorklet:o,hasMediaStreamTrackProcessor:c.hasMediaStreamTrackProcessor,hasMainThreadMediaStreamTrackProcessor:s,hasVideoFrame:c.hasVideoFrame,hasAudioData:c.hasAudioData,hasOffscreenCanvas:c.hasOffscreenCanvas,hasCreateImageBitmap:c.hasCreateImageBitmap,hasReadableStream:c.hasReadableStream,requiresAudio:t,requiresWatermark:n,videoPath:l,audioPath:u}}async function nh(e){if(!e)return ih();let t=await rh().catch(()=>null);return t?await new Promise(e=>{let n=!1,r=r=>{n||(n=!0,t.terminate(),e(r))},i=setTimeout(()=>{r(ih())},2e3);t.onmessage=e=>{let t=e.data;t.type===Rm&&(clearTimeout(i),r({hasMediaStreamTrackProcessor:t.hasMediaStreamTrackProcessor===!0,hasVideoFrame:t.hasVideoFrame===!0,hasAudioData:t.hasAudioData===!0,hasOffscreenCanvas:t.hasOffscreenCanvas===!0,hasCreateImageBitmap:t.hasCreateImageBitmap===!0,hasReadableStream:t.hasReadableStream===!0}))},t.onerror=()=>{clearTimeout(i),r(ih())},Promise.resolve().then(()=>{t.postMessage({type:Lm})}).catch(()=>{clearTimeout(i),r(ih())})}):ih()}function rh(){return Promise.resolve().then(()=>{let e=Fm();try{let t=new Worker(e,{type:`classic`});return Im(e),t}catch(t){throw Im(e),t}})}function ih(){return{hasMediaStreamTrackProcessor:!1,hasVideoFrame:!1,hasAudioData:!1,hasOffscreenCanvas:!1,hasCreateImageBitmap:!1,hasReadableStream:!1}}let ah=`vidtreo-recorder`,oh=`pending-uploads`,sh=`status`,ch=`createdAt`;var lh=class{constructor(e){if(this.db=null,e){this.databaseFactory=e;return}this.databaseFactory=indexedDB}init(){return this.db?Promise.resolve():this.openDatabase(2,!0)}openDatabase(e,t){return new Promise((n,r)=>{let i=this.createOpenRequest(e);i.onerror=()=>{let e=i.error;if(t&&e&&e.name===`VersionError`){this.openDatabase(void 0,!1).then(n).catch(r);return}if(e){r(e);return}r(Error(`Failed to open database`))},i.onsuccess=()=>{if(!i.result){r(Error(`Database result is null`));return}let e=i.result,t=this.validateRequiredSchema(e);if(t){e.close(),r(t);return}this.db=e,n()},i.onupgradeneeded=e=>{let t=e.target.result;if(!t){r(Error(`Database upgrade result is null`));return}this.initializeStoreSchema(t)}})}createOpenRequest(e){return e===void 0?this.databaseFactory.open(ah):this.databaseFactory.open(ah,e)}initializeStoreSchema(e){if(e.objectStoreNames.contains(oh))return;let t=e.createObjectStore(oh,{keyPath:`id`});t.createIndex(sh,sh,{unique:!1}),t.createIndex(ch,ch,{unique:!1})}validateRequiredSchema(e){if(!e.objectStoreNames.contains(oh))return Error(`Database schema is missing required object store: pending-uploads`);let t=e.transaction([oh],`readonly`).objectStore(oh);return t.indexNames.contains(sh)?t.indexNames.contains(ch)?null:Error(`Database schema is missing required index: createdAt`):Error(`Database schema is missing required index: status`)}isInitialized(){return this.db!==null}savePendingUpload(e){let t=this.generateUploadId(),n={...e,id:t,status:`pending`,retryCount:0,createdAt:Date.now(),updatedAt:Date.now()};return this.executeTransaction(`readwrite`,e=>{let r=e.add(n);return new Promise((e,n)=>{r.onsuccess=()=>e(t),r.onerror=()=>{r.error?r.error.name===`QuotaExceededError`?n(Error(`Storage quota exceeded. Please free up space or delete old uploads.`)):n(r.error):n(Error(`Failed to save upload`))}})})}getPendingUploads(e){return this.executeTransaction(`readonly`,t=>{let n=e?t.index(sh).getAll(e):t.getAll();return new Promise((e,t)=>{n.onsuccess=()=>{if(n.result===void 0){t(Error(`Failed to get uploads: result is undefined`));return}e(n.result)},n.onerror=()=>{n.error?t(n.error):t(Error(`Failed to get uploads`))}})})}updateUploadStatus(e,t){return this.executeTransaction(`readwrite`,n=>{let r=n.get(e);return new Promise((e,i)=>{r.onsuccess=()=>{let a=r.result;if(!a){i(Error(`Upload not found`));return}let o={...a,...t,updatedAt:Date.now()},s=n.put(o);s.onsuccess=()=>e(),s.onerror=()=>{s.error?i(s.error):i(Error(`Failed to update upload`))}},r.onerror=()=>{r.error?i(r.error):i(Error(`Failed to get upload`))}})})}deleteUpload(e){return this.executeTransaction(`readwrite`,t=>{let n=t.delete(e);return new Promise((e,t)=>{n.onsuccess=()=>e(),n.onerror=()=>{n.error?t(n.error):t(Error(`Failed to delete upload`))}})})}async cleanupPermanentlyFailedUploads(e){let t=e===void 0?24:e;if(typeof t!=`number`||t<0)throw Error(`retentionHours must be a non-negative number`);let n=Date.now()-t*36e5,r=(await this.getPendingUploads()).filter(e=>e.status===`failed`&&e.retryCount>=10&&e.updatedAt<n);for(let e of r)await this.deleteUpload(e.id);return r.length}async getTotalStorageSize(){return(await this.getPendingUploads()).reduce((e,t)=>e+t.blob.size,0)}generateUploadId(){return`upload-${Date.now()}-${Math.random().toString(36).substring(2,11)}`}executeTransaction(e,t){if(!this.db)throw Error(`Database not initialized`);return t(this.db.transaction([oh],e).objectStore(oh))}},uh=class{constructor(){this.storageService=null,this.cleanupIntervalId=null}async initialize(e){this.storageService||=new lh,this.storageService.isInitialized()||await this.storageService.init(),this.setupCleanupInterval(e)}setupCleanupInterval(e){this.cleanupIntervalId===null&&(this.cleanupIntervalId=window.setInterval(()=>{this.performCleanup().catch(t=>{e(i(t))})},36e5))}async performCleanup(){if(!this.storageService)throw Error(`StorageService not initialized`);await this.storageService.cleanupPermanentlyFailedUploads(24)}getStorageService(){return this.storageService}destroy(){this.cleanupIntervalId!==null&&(clearInterval(this.cleanupIntervalId),this.cleanupIntervalId=null)}};function dh(){let e=globalThis;if(e.__VIDTREO_DEBUG__===!0||e.__VIDTREO_DEV__===!0)return!0;let t=typeof process<`u`&&process?.env?`production`:void 0;return t===`development`||t===`test`||typeof localStorage<`u`&&localStorage.getItem(`VIDTREO_DEBUG`)===`true`}let fh=dh(),ph={reset:`\x1B[0m`,bright:`\x1B[1m`,dim:`\x1B[2m`,red:`\x1B[31m`,green:`\x1B[32m`,yellow:`\x1B[33m`,blue:`\x1B[34m`,magenta:`\x1B[35m`,cyan:`\x1B[36m`,white:`\x1B[37m`,gray:`\x1B[90m`};function mh(e,t,n){if(!fh)return``;let r=n?.prefix||`[${e.toUpperCase()}]`;return`${ph[n?.color||hh(e)]}${r}${ph.reset} ${t}`}function hh(e){switch(e){case`error`:return`red`;case`warn`:return`yellow`;case`info`:return`cyan`;case`debug`:return`gray`;default:return`white`}}function gh(e,t,...n){if(!fh)return;let r=mh(e,t);console[e](r,...n)}let $={log:(e,...t)=>{gh(`log`,e,...t)},info:(e,...t)=>{gh(`info`,e,...t)},warn:(e,...t)=>{gh(`warn`,e,...t)},error:(e,...t)=>{gh(`error`,e,...t)},debug:(e,...t)=>{gh(`debug`,e,...t)},group:(e,t=`cyan`)=>{if(!fh)return;let n=ph[t],r=ph.reset;console.group(`${n}${e}${r}`)},groupEnd:()=>{fh&&console.groupEnd()}};function _h(e,t){if(e==null)throw Error(t);return e}function vh(e,t=`StreamProcessor`){if(!e)throw Error(`${t} is required`);return e}function yh(){if(typeof navigator>`u`||!navigator.mediaDevices?.getUserMedia){let e=typeof window<`u`&&window.isSecureContext===!0?`Camera access is not supported in this browser`:`Camera access requires HTTPS. Please use a secure connection (https://) or localhost.`;throw Error(e)}return navigator.mediaDevices}function bh(e,t){let n={};if(t.originalCameraConstraints){let{deviceId:e,...r}=t.originalCameraConstraints;n={...n,...r}}e&&(n={...n,deviceId:{exact:e}});let r=t.getSelectedCameraDeviceId(),i=!1;return e&&(i=!0),n.deviceId&&(i=!0),!i&&r&&(n={...n,deviceId:{exact:r}}),n}function xh(e){return e?{deviceId:{exact:e}}:!0}let Sh=`live`;function Ch(e){for(let t of e)t.readyState===Sh&&t.stop()}function wh(e){Ch(e.getTracks())}function Th(e){Ch(e.getVideoTracks())}function Eh(e){return e?e.readyState===Sh:!1}function Dh(e,t){return Eh(e)&&Eh(t)}function Oh(e,t,n){if(!Eh(e)){wh(n);let r=`undefined`;throw e&&(r=e.readyState),Error(`Failed to get live camera ${t} track. ReadyState: ${r}`)}}let kh=`[SourceSwitchManager]`;var Ah=class{constructor(e){this.dependencies=e}async createCameraStreamWithOriginalAudio(e){let t=this.dependencies.getOriginalCameraStream(),n;if(t&&(n=t.getAudioTracks()[0]),this.dependencies.logger.debug(`${kh} createCameraStreamWithOriginalAudio`,{hasOriginalCameraStream:!!t,originalCameraStreamId:t?.id,hasOriginalAudioTrack:!!n,originalAudioTrackId:n?.id,originalAudioTrackReadyState:n?.readyState,originalAudioTrackEnabled:n?.enabled,originalAudioTrackMuted:n?.muted,originalAudioTrackLabel:n?.label,isTrackLive:Eh(n),cameraDeviceId:e}),!Eh(n))return this.dependencies.logger.warn(`${kh} Original audio track is not live, cannot reuse`,{originalAudioTrackId:n?.id,originalAudioTrackReadyState:n?.readyState}),null;let r=bh(e,{originalCameraConstraints:this.dependencies.getOriginalCameraConstraints(),getSelectedCameraDeviceId:this.dependencies.getSelectedCameraDeviceId}),i=Object.keys(r).length>0,a=!0;i&&(a=r);let o={video:a,audio:!1};this.dependencies.logger.debug(`${kh} Requesting new video stream`,{constraints:o,cameraDeviceId:e});let s=await yh().getUserMedia(o),c=s.getVideoTracks()[0];Oh(c,`video`,s),this.dependencies.logger.debug(`${kh} New video stream obtained`,{newStreamId:s.id,videoTrackId:c.id,videoTrackReadyState:c.readyState,newStreamAudioTracksCount:s.getAudioTracks().length});let l=[c];n&&(l=[...l,n]),this.dependencies.logger.debug(`${kh} Creating combined stream with original audio`,{videoTrackId:c.id,audioTrackId:n?.id,audioTrackReadyState:n?.readyState,audioTrackEnabled:n?.enabled,audioTrackMuted:n?.muted,combinedTracksCount:l.length});let u=new MediaStream(l);Ch(s.getAudioTracks());let d=t?.id;return this.dependencies.setOriginalCameraStream(u),this.dependencies.logger.debug(`${kh} Combined stream created and assigned`,{combinedStreamId:u.id,previousOriginalCameraStreamId:d,newOriginalCameraStreamId:u.id,combinedStreamVideoTracksCount:u.getVideoTracks().length,combinedStreamAudioTracksCount:u.getAudioTracks().length,combinedStreamAudioTrackId:u.getAudioTracks()[0]?.id,combinedStreamAudioTrackReadyState:u.getAudioTracks()[0]?.readyState,audioTrackStillSame:u.getAudioTracks()[0]===n}),u}async createCameraStreamWithNewAudio(e){let t=this.dependencies.getSelectedMicDeviceId(),n=bh(e,{originalCameraConstraints:this.dependencies.getOriginalCameraConstraints(),getSelectedCameraDeviceId:this.dependencies.getSelectedCameraDeviceId}),r=xh(t),i=Object.keys(n).length>0,a=!0;i&&(a=n);let o={video:a,audio:r},s=await yh().getUserMedia(o),c=s.getVideoTracks()[0],l=s.getAudioTracks()[0];return Oh(c,`video`,s),Oh(l,`audio`,s),this.dependencies.setOriginalCameraStream(s),s}async createNewCameraStreamForRecording(){let e=this.dependencies.getSelectedCameraDeviceId();return await this.createCameraStreamWithOriginalAudio(e)||this.createCameraStreamWithNewAudio(e)}async getCameraStream(e){let t=this.dependencies.streamManager.isRecording(),n=this.dependencies.getSelectedCameraDeviceId(),r=this.dependencies.getSelectedMicDeviceId();if(this.dependencies.streamManager.setVideoDevice(n),this.dependencies.streamManager.setAudioDevice(r),e.canReuseOriginalStream()){let e=this.dependencies.getOriginalCameraStream();if(!e)throw Error(`Original camera stream is null`);return e}if(e.canReuseManagerStream()){let e=this.dependencies.streamManager.getStream();if(!e)throw Error(`Manager stream is null`);return e}t||this.dependencies.getOriginalCameraStream()&&this.dependencies.setOriginalCameraStream(null);let i=this.dependencies.streamManager.getStream();if(!t&&i&&i!==this.dependencies.getOriginalCameraStream()&&(wh(i),this.dependencies.streamManager.setMediaStream(null)),t)return this.dependencies.streamManager.setVideoDevice(this.dependencies.getSelectedCameraDeviceId()),this.dependencies.streamManager.setAudioDevice(this.dependencies.getSelectedMicDeviceId()),this.createNewCameraStreamForRecording();let a=await this.dependencies.streamManager.startStream();return this.dependencies.setOriginalCameraStream(a),a}};let jh=`screen`,Mh=`No video track found in screen share stream`;async function Nh(e,t,n){n.setScreenShareStream(e);let r=e.getVideoTracks()[0];if(!r)throw n.stopStreamTracks(e),Error(Mh);let i=n.combineScreenShareWithOriginalAudio(r),a=n.getOriginalCameraStream();t&&t!==a&&n.stopStreamVideoTracks(t);let o=e.getAudioTracks();for(let e of o)e.stop();return n.setCurrentSourceType(jh),n.callbacks.onSourceChange&&await n.callbacks.onSourceChange(n.getCurrentSourceType()),Ph(i,n),i}function Ph(e,t){let n=e.getVideoTracks()[0];if(!n)throw Error(Mh);let r=t.getScreenShareTrackEndHandler();if(r){let e=t.streamManager.getStream();if(e){let t=e.getVideoTracks()[0];t&&t.removeEventListener(`ended`,r)}}let i=()=>{t.getCurrentSourceType()===jh&&t.switchToCamera().catch(e=>{t.handleSwitchError(e)})};t.setScreenShareTrackEndHandler(i),n.addEventListener(`ended`,i)}function Fh(e,t){let n=t.getScreenShareTrackEndHandler();if(!(n&&e))return;let r=e.getVideoTracks()[0];r&&r.removeEventListener(`ended`,n),t.setScreenShareTrackEndHandler(null)}function Ih(e,t){e.onTransitionStart&&e.onTransitionStart(t)}function Lh(e){e.onTransitionEnd&&e.onTransitionEnd()}function Rh(e){e.onScreenSelectionStart&&e.onScreenSelectionStart()}function zh(e){e.onScreenSelectionEnd&&e.onScreenSelectionEnd()}function Bh(e){zh(e),Lh(e)}let Vh=`Failed to get camera stream`;var Hh=class{constructor(e,t={}){this.currentSourceType=`camera`,this.originalCameraStream=null,this.screenShareStream=null,this.screenShareTrackEndHandler=null,this.streamManager=e,this.callbacks=t;let n=null,r=()=>n;this.getOriginalCameraConstraints=r,this.setOriginalCameraConstraints=e=>{n=e},this.cameraStreamBuilder=new Ah({streamManager:this.streamManager,logger:{debug:(e,t)=>$.debug(e,t),warn:(e,t)=>$.warn(e,t)},getSelectedCameraDeviceId:()=>this.callbacks.getSelectedCameraDeviceId?this.callbacks.getSelectedCameraDeviceId():this.streamManager.getVideoDevice(),getSelectedMicDeviceId:()=>this.callbacks.getSelectedMicDeviceId?this.callbacks.getSelectedMicDeviceId():this.streamManager.getAudioDevice(),getOriginalCameraStream:()=>this.originalCameraStream,setOriginalCameraStream:e=>{this.originalCameraStream=e},getOriginalCameraConstraints:r})}getCurrentSourceType(){return this.currentSourceType}getOriginalCameraStream(){return this.originalCameraStream}storeOriginalCameraConstraints(e){let t=e.getVideoTracks()[0];if(!t)return;let n=t.getSettings(),r={width:n.width,height:n.height,aspectRatio:n.aspectRatio,frameRate:n.frameRate,deviceId:n.deviceId,facingMode:n.facingMode},i=this.getOriginalCameraConstraints();i&&i.width===r.width&&i.height===r.height&&i.aspectRatio===r.aspectRatio&&i.frameRate===r.frameRate&&i.deviceId===r.deviceId&&i.facingMode===r.facingMode||this.setOriginalCameraConstraints(r)}storeOriginalCameraStream(e){let t=e.getVideoTracks()[0],n=e.getAudioTracks()[0];Dh(t,n)?this.originalCameraStream=new MediaStream([t,n]):this.originalCameraStream=e}createError(e){return e instanceof Error?e:Error(i(e))}waitForTracksToEnd(e){return new Promise(t=>{setTimeout(()=>{this.screenShareStream=null,t()},e)})}combineScreenShareWithOriginalAudio(e){let t;this.originalCameraStream&&(t=this.originalCameraStream.getAudioTracks()[0]),$.debug(`[SourceSwitchManager] combineScreenShareWithOriginalAudio`,{hasOriginalCameraStream:!!this.originalCameraStream,originalCameraStreamId:this.originalCameraStream?.id,hasOriginalAudioTrack:!!t,originalAudioTrackId:t?.id,originalAudioTrackReadyState:t?.readyState,originalAudioTrackEnabled:t?.enabled,originalAudioTrackMuted:t?.muted,originalAudioTrackLabel:t?.label,isTrackLive:Eh(t),screenVideoTrackId:e.id,screenVideoTrackReadyState:e.readyState});let n=[e];Eh(t)&&t?(n=[...n,t],$.debug(`[SourceSwitchManager] Added original audio track to combined stream`,{audioTrackId:t.id,combinedTracksCount:n.length})):$.warn(`[SourceSwitchManager] Original audio track is not live, not adding to combined stream`,{audioTrackId:t?.id,audioTrackReadyState:t?.readyState,combinedTracksCount:n.length});let r=new MediaStream(n);return $.debug(`[SourceSwitchManager] Combined stream created`,{combinedStreamId:r.id,combinedStreamVideoTracksCount:r.getVideoTracks().length,combinedStreamAudioTracksCount:r.getAudioTracks().length,combinedStreamAudioTrackId:r.getAudioTracks()[0]?.id,combinedStreamAudioTrackReadyState:r.getAudioTracks()[0]?.readyState}),r}isPermissionDeniedError(e){let t=i(e),n=!1;t.includes(`NotAllowedError`)&&(n=!0),t.includes(`AbortError`)&&(n=!0);let r=t.toLowerCase();return r.includes(`permission denied`)&&(n=!0),r.includes(`user denied`)&&(n=!0),n}switchToScreenCapture(){let e=this.streamManager.getStream();return e&&(this.storeOriginalCameraConstraints(e),this.storeOriginalCameraStream(e)),Ih(this.callbacks,`Select screen to share...`),Rh(this.callbacks),Promise.resolve().then(async()=>{let t=yh();if(typeof t.getDisplayMedia!=`function`)throw Error(`Screen sharing is not supported on this device`);return Nh(await t.getDisplayMedia({video:!0,audio:!0}),e,this.getScreenShareDependencies())}).catch(e=>{if(Bh(this.callbacks),this.isPermissionDeniedError(e))return null;throw e})}canReuseStream(e,t){if(!e||t&&e!==this.originalCameraStream)return!1;let n=e.getVideoTracks()[0],r=e.getAudioTracks()[0];return!(!Dh(n,r)||this.callbacks.getSelectedCameraDeviceId&&this.callbacks.getSelectedCameraDeviceId()!==n.getSettings().deviceId)}canReuseOriginalStream(){return this.canReuseStream(this.originalCameraStream,!1)}canReuseManagerStream(){let e=this.streamManager.getStream();return e&&this.originalCameraStream?this.canReuseStream(e,!0):!1}getScreenShareDependencies(){return{callbacks:this.callbacks,streamManager:this.streamManager,combineScreenShareWithOriginalAudio:e=>this.combineScreenShareWithOriginalAudio(e),stopStreamTracks:e=>wh(e),stopStreamVideoTracks:e=>Th(e),getCurrentSourceType:()=>this.currentSourceType,setCurrentSourceType:e=>{this.currentSourceType=e},getOriginalCameraStream:()=>this.originalCameraStream,getScreenShareStream:()=>this.screenShareStream,setScreenShareStream:e=>{this.screenShareStream=e},getScreenShareTrackEndHandler:()=>this.screenShareTrackEndHandler,setScreenShareTrackEndHandler:e=>{this.screenShareTrackEndHandler=e},switchToCamera:()=>this.switchToCamera(),handleSwitchError:e=>{this.callbacks.onError&&this.callbacks.onError(this.createError(e))}}}getCameraStream(){return this.cameraStreamBuilder.getCameraStream({canReuseOriginalStream:()=>this.canReuseOriginalStream(),canReuseManagerStream:()=>this.canReuseManagerStream()})}switchToCamera(){let e=this.streamManager.isRecording();return!e&&this.currentSourceType===`camera`?Promise.resolve():Promise.resolve().then(async()=>{Ih(this.callbacks,`Switching to camera...`),await this.handleScreenShareStop();let t=await this.getCameraStream();if(!t)throw Error(Vh);await this.applyCameraStream(t,e),Lh(this.callbacks)}).catch(e=>{throw Lh(this.callbacks),e})}stopScreenShareStreamTracks(e){let t=e.getVideoTracks(),n=e.getAudioTracks();$.debug(`[SourceSwitchManager] stopping screen share tracks`,{videoTracks:t.map(e=>({id:e.id,readyState:e.readyState,displaySurface:e.getSettings().displaySurface,constraints:e.getConstraints()})),audioTracks:n.map(e=>({id:e.id,readyState:e.readyState,constraints:e.getConstraints()}))});for(let e of t)e.stop();for(let e of n)e.stop()}stopDisplayTracks(e){if(e)for(let t of e.getVideoTracks())typeof t.getSettings().displaySurface==`string`&&Eh(t)&&($.debug(`[SourceSwitchManager] stopping display track`,{id:t.id,readyState:t.readyState,constraints:t.getConstraints(),settings:t.getSettings()}),t.stop())}async handleScreenShareStop(){if(this.currentSourceType!==`screen`)return;$.debug(`[SourceSwitchManager] handleScreenShareStop invoked`,{currentSourceType:this.currentSourceType,hasScreenShareStream:!!this.screenShareStream,screenShareStreamId:this.screenShareStream?.id,hasOriginalCameraStream:!!this.originalCameraStream,originalCameraStreamId:this.originalCameraStream?.id});let e=this.screenShareStream,t=this.streamManager.getStream();if($.debug(`[SourceSwitchManager] Current stream state before stop`,{currentStreamId:t?.id,currentStreamVideoTracksCount:t?.getVideoTracks().length,currentStreamAudioTracksCount:t?.getAudioTracks().length,currentStreamAudioTrackId:t?.getAudioTracks()[0]?.id,currentStreamAudioTrackReadyState:t?.getAudioTracks()[0]?.readyState,originalCameraStreamAudioTrackId:this.originalCameraStream?.getAudioTracks()[0]?.id,originalCameraStreamAudioTrackReadyState:this.originalCameraStream?.getAudioTracks()[0]?.readyState}),e){let t=e.getAudioTracks();$.debug(`[SourceSwitchManager] Screen share stream audio tracks before stop`,{screenShareStreamId:e.id,screenShareAudioTracksCount:t.length,screenShareAudioTrackIds:t.map(e=>({id:e.id,readyState:e.readyState,enabled:e.enabled}))}),Fh(e,this.getScreenShareDependencies()),this.stopScreenShareStreamTracks(e),this.stopDisplayTracks(e),this.screenShareStream=null,await this.waitForTracksToEnd(0),$.debug(`[SourceSwitchManager] Screen share stream stopped`,{screenShareAudioTracksAfterStop:t.map(e=>({id:e.id,readyState:e.readyState}))})}if(t){let e=t.getAudioTracks();$.debug(`[SourceSwitchManager] Current stream audio tracks before video stop`,{currentStreamId:t.id,currentStreamAudioTracksCount:e.length,currentStreamAudioTrackIds:e.map(e=>({id:e.id,readyState:e.readyState,enabled:e.enabled}))}),Th(t),this.stopDisplayTracks(t),$.debug(`[SourceSwitchManager] Current stream audio tracks after video stop`,{currentStreamId:t.id,currentStreamAudioTracksCount:t.getAudioTracks().length,currentStreamAudioTrackIds:t.getAudioTracks().map(e=>({id:e.id,readyState:e.readyState,enabled:e.enabled}))})}$.debug(`[SourceSwitchManager] Original camera stream state before source change`,{hasOriginalCameraStream:!!this.originalCameraStream,originalCameraStreamId:this.originalCameraStream?.id,originalCameraStreamAudioTracksCount:this.originalCameraStream?.getAudioTracks().length,originalCameraStreamAudioTrackId:this.originalCameraStream?.getAudioTracks()[0]?.id,originalCameraStreamAudioTrackReadyState:this.originalCameraStream?.getAudioTracks()[0]?.readyState,originalCameraStreamAudioTrackEnabled:this.originalCameraStream?.getAudioTracks()[0]?.enabled}),this.currentSourceType=`camera`,this.callbacks.onSourceChange&&await this.callbacks.onSourceChange(this.currentSourceType),$.debug(`[SourceSwitchManager] handleScreenShareStop completed`,{hasScreenShareStream:!!this.screenShareStream,currentSourceType:this.currentSourceType,hasOriginalCameraStream:!!this.originalCameraStream,originalCameraStreamId:this.originalCameraStream?.id,originalCameraStreamAudioTracksCount:this.originalCameraStream?.getAudioTracks().length,originalCameraStreamAudioTrackId:this.originalCameraStream?.getAudioTracks()[0]?.id,originalCameraStreamAudioTrackReadyState:this.originalCameraStream?.getAudioTracks()[0]?.readyState})}async applyCameraStream(e,t){this.streamManager.setMediaStream(e);let n=this.currentSourceType!==`camera`;this.currentSourceType=`camera`,n&&this.callbacks.onSourceChange&&await this.callbacks.onSourceChange(this.currentSourceType),t&&await this.streamManager.switchVideoSource(e),this.callbacks.onPreviewUpdate&&await this.callbacks.onPreviewUpdate(e)}async toggleSource(){if(!this.streamManager.isRecording())return;let e;e=this.currentSourceType===`camera`?this.switchToScreen():this.switchToCamera(),await e.catch(e=>{this.handleToggleError(e)})}async switchToScreen(){let e=await this.switchToScreenCapture();if(!e){Lh(this.callbacks);return}Ih(this.callbacks,`Switching to screen...`),await this.streamManager.switchVideoSource(e),this.callbacks.onPreviewUpdate&&await this.callbacks.onPreviewUpdate(e),Lh(this.callbacks)}handleToggleError(e){Lh(this.callbacks);let t=i(e),n=!1;t.includes(`NotAllowedError`)&&(n=!0),t.includes(`AbortError`)&&(n=!0),n&&this.currentSourceType===`screen`&&this.switchToCamera().catch(e=>{this.callbacks.onError&&this.callbacks.onError(this.createError(e))}),!n&&this.callbacks.onError&&this.callbacks.onError(this.createError(e))}async handleRecordingStop(){if(this.currentSourceType!==`screen`){this.cleanup();return}await Promise.resolve().then(async()=>{let e=this.streamManager.getStream();e&&(Fh(e,this.getScreenShareDependencies()),Th(e));let t=await this.getCameraStream();if(!t)throw Error(Vh);this.streamManager.setMediaStream(t),this.currentSourceType=`camera`,this.callbacks.onSourceChange&&await this.callbacks.onSourceChange(this.currentSourceType),this.callbacks.onPreviewUpdate&&await this.callbacks.onPreviewUpdate(t)}).catch(e=>{throw this.callbacks.onError&&this.callbacks.onError(this.createError(e)),e}),this.cleanup()}cleanup(){this.screenShareStream&&=(Fh(this.screenShareStream,this.getScreenShareDependencies()),this.stopScreenShareStreamTracks(this.screenShareStream),null);let e=this.streamManager.getStream();e&&Fh(e,this.getScreenShareDependencies()),this.screenShareTrackEndHandler=null,this.originalCameraStream=null,this.setOriginalCameraConstraints(null)}setCallbacks(e){this.callbacks={...this.callbacks,...e}}};let Uh=Object.freeze({width:{ideal:Bt.width||1920},height:{ideal:Bt.height||1080},frameRate:{ideal:Bt.fps||30}}),Wh=Object.freeze({video:Uh,audio:!0});Object.freeze({mimeType:`video/webm;codecs=vp9,opus`});var Gh=class{constructor(e={}){this.mediaStream=null,this.state=`idle`,this.eventListeners=new Map,this.selectedAudioDeviceId=null,this.selectedVideoDeviceId=null,this.streamConfig={...Wh,...e}}getState(){return this.state}getStream(){return this.mediaStream}getAudioStreamForAnalysis(){return this.mediaStream&&this.mediaStream.getAudioTracks().length>0?this.mediaStream:null}isActive(){return this.state===`active`||this.state===`recording`}on(e,t){this.eventListeners.has(e)||this.eventListeners.set(e,new Set);let n=this.eventListeners.get(e);return n&&n.add(t),()=>{this.off(e,t)}}off(e,t){let n=this.eventListeners.get(e);n&&n.delete(t)}once(e,t){let n=(r=>{t(r),this.off(e,n)});return this.on(e,n)}emit(e,t){let n=this.eventListeners.get(e);if(n)for(let e of n)try{e(t)}catch{}}setState(e){if(this.state===e)return;let t=this.state;this.state=e,this.emit(`statechange`,{state:e,previousState:t})}setAudioDevice(e){this.selectedAudioDeviceId=e}setVideoDevice(e){this.selectedVideoDeviceId=e}getAudioDevice(){return this.selectedAudioDeviceId}getVideoDevice(){return this.selectedVideoDeviceId}async getAvailableDevices(){try{let e=await navigator.mediaDevices.enumerateDevices();return{audioinput:e.filter(e=>e.kind===`audioinput`),videoinput:e.filter(e=>e.kind===`videoinput`)}}catch(e){throw Error(`Failed to enumerate devices: ${i(e)}`)}}buildDeviceConstraints(e,t){return e?typeof t==`object`?{...t,deviceId:{exact:e}}:{deviceId:{exact:e}}:t}buildVideoConstraints(e){return this.buildDeviceConstraints(e,this.streamConfig.video)}buildAudioConstraints(e){return this.buildDeviceConstraints(e,this.streamConfig.audio)}async startStream(){if($.debug(`[StreamManager] startStream called`,{hasExistingStream:!!this.mediaStream,selectedVideoDeviceId:this.selectedVideoDeviceId,selectedAudioDeviceId:this.selectedAudioDeviceId}),this.mediaStream){let e=this.mediaStream.getVideoTracks()[0];if(this.selectedVideoDeviceId===null)if(e?.getSettings?.()?.deviceId)$.debug(`[StreamManager] Stopping existing stream to recreate`),this.stopStream();else return $.debug(`[StreamManager] Reusing existing stream`),this.mediaStream;if(e?.getSettings&&e.getSettings().deviceId===this.selectedVideoDeviceId)return $.debug(`[StreamManager] Existing stream matches device, reusing`),this.mediaStream;$.debug(`[StreamManager] Device changed, stopping existing stream`),this.stopStream()}this.setState(`starting`),$.debug(`[StreamManager] State set to 'starting'`);try{$.debug(`[StreamManager] Building constraints`,{selectedVideoDeviceId:this.selectedVideoDeviceId,selectedAudioDeviceId:this.selectedAudioDeviceId});let e={video:this.buildVideoConstraints(this.selectedVideoDeviceId),audio:this.buildAudioConstraints(this.selectedAudioDeviceId)};return $.debug(`[StreamManager] Requesting media stream with constraints`,{hasVideo:!!e.video,hasAudio:!!e.audio}),this.mediaStream=await yh().getUserMedia(e),$.info(`[StreamManager] Media stream obtained`,{streamId:this.mediaStream.id,videoTracks:this.mediaStream.getVideoTracks().length,audioTracks:this.mediaStream.getAudioTracks().length}),this.setState(`active`),$.debug(`[StreamManager] State set to 'active'`),$.debug(`[StreamManager] Emitting streamstart event`),this.emit(`streamstart`,{stream:this.mediaStream}),this.mediaStream}catch(e){let t=e instanceof Error?e:Error(i(e));throw $.error(`[StreamManager] Failed to start stream`,t),this.setState(`error`),this.emit(`error`,{error:t}),t}}stopStream(){if(this.mediaStream){for(let e of this.mediaStream.getTracks())e.stop();this.mediaStream=null}this.state!==`idle`&&(this.setState(`idle`),this.emit(`streamstop`,void 0))}stopStreamTracks(e){for(let t of e.getTracks())t.stop()}isTrackLive(e){return e!==void 0&&e.readyState===`live`}async tryReplaceTrack(e,t,n){let r=e.replaceTrack;if(typeof r!=`function`)return!1;try{await r.call(e,t),e.stop();for(let e of n.getTracks())e!==t&&e.stop();return t.stop(),!0}catch{return!1}}recreateStreamWithNewTrack(e,t,n){for(let t of n.getTracks())t!==e&&t.stop();let r=[e];this.isTrackLive(t)&&t&&r.push(t);let i=new MediaStream(r);if(this.mediaStream)for(let e of this.mediaStream.getTracks())e!==t&&e.stop();return i}async switchDeviceTrack(e,t,n){if(!this.mediaStream)throw Error(`No active stream to switch device`);let r=t===`video`?this.mediaStream.getVideoTracks()[0]:this.mediaStream.getAudioTracks()[0],i=t===`video`?this.mediaStream.getAudioTracks()[0]:this.mediaStream.getVideoTracks()[0];if(!r){let e=t===`video`?`video`:`audio`;throw Error(`No ${e} track in current stream`)}let a={[t]:this.buildDeviceConstraints(e,n)},o=await yh().getUserMedia(a),s=t===`video`?o.getVideoTracks()[0]:o.getAudioTracks()[0];if(!s){this.stopStreamTracks(o);let e=t===`video`?`video`:`audio`;throw Error(`Failed to get new ${e} track`)}return await this.tryReplaceTrack(r,s,o)||(r.stop(),this.mediaStream=this.recreateStreamWithNewTrack(s,i,o)),t===`video`?(this.selectedVideoDeviceId=e,this.emit(`videosourcechange`,{stream:this.mediaStream})):this.selectedAudioDeviceId=e,this.mediaStream}switchVideoDevice(e){return this.switchDeviceTrack(e,`video`,this.streamConfig.video)}switchAudioDevice(e){return this.switchDeviceTrack(e,`audio`,this.streamConfig.audio)}setMediaStream(e){this.mediaStream=e}setAudioTracksEnabled(e){if(!this.mediaStream)return;let t=this.mediaStream.getAudioTracks();for(let n of t)n.enabled=e}destroy(){this.stopStream(),this.eventListeners.clear(),this.setState(`idle`)}};let Kh=[`Bytes`,`KB`,`MB`,`GB`],qh=1024;function Jh(e){if(e===0)return`0 Bytes`;let t=Math.floor(Math.log(e)/Math.log(qh));return`${Math.round(e/qh**t*100)/100} ${Kh[t]}`}function Yh(e){let t=Math.floor(e/3600),n=Math.floor(e%3600/60),r=e%60;return t>0?`${t.toString().padStart(2,`0`)}:${n.toString().padStart(2,`0`)}:${r.toString().padStart(2,`0`)}`:`${n.toString().padStart(2,`0`)}:${r.toString().padStart(2,`0`)}`}var Xh=class{constructor(){this.recordingStartTime=0,this.totalPausedTime=0,this.pauseStartTime=null,this.intervals=[],this.currentIntervalStart=null,this.isTracking=!1,this.visibilityChangeHandler=this.handleVisibilityChange.bind(this),this.blurHandler=this.handleBlur.bind(this),this.focusHandler=this.handleFocus.bind(this)}start(e){this.isTracking||(this.recordingStartTime=e,this.totalPausedTime=0,this.pauseStartTime=null,this.intervals=[],this.currentIntervalStart=null,this.isTracking=!0,typeof document<`u`&&document.addEventListener(`visibilitychange`,this.visibilityChangeHandler),typeof window<`u`&&(window.addEventListener(`blur`,this.blurHandler),window.addEventListener(`focus`,this.focusHandler)),this.checkInitialState())}pause(){!this.isTracking||this.pauseStartTime!==null||(this.pauseStartTime=Date.now(),this.endCurrentIntervalIfActive())}resume(){if(!this.isTracking||this.pauseStartTime===null)return;let e=Date.now()-this.pauseStartTime;this.totalPausedTime+=e,this.pauseStartTime=null}getIntervals(){return this.endCurrentIntervalIfActive(),this.intervals.map(e=>({start:this.normalizeTimestamp(e.start),end:this.normalizeTimestamp(e.end)}))}reset(){this.intervals=[],this.currentIntervalStart=null,this.totalPausedTime=0,this.pauseStartTime=null}cleanup(){this.isTracking=!1,this.endCurrentIntervalIfActive(),typeof document<`u`&&document.removeEventListener(`visibilitychange`,this.visibilityChangeHandler),typeof window<`u`&&(window.removeEventListener(`blur`,this.blurHandler),window.removeEventListener(`focus`,this.focusHandler)),this.reset()}checkInitialState(){typeof document>`u`||document.visibilityState===`hidden`&&this.startInterval()}handleVisibilityChange(){typeof document>`u`||(document.visibilityState===`hidden`?this.startInterval():this.endCurrentIntervalIfActive())}handleBlur(){this.startInterval()}handleFocus(){this.endCurrentIntervalIfActive()}startInterval(){this.currentIntervalStart!==null||!this.isTracking||this.pauseStartTime===null&&(this.currentIntervalStart=Date.now())}endCurrentIntervalIfActive(){if(this.currentIntervalStart===null)return;let e=Date.now(),t=this.currentIntervalStart;e>t&&this.intervals.push({start:t,end:e}),this.currentIntervalStart=null}normalizeTimestamp(e){let t=(e-this.recordingStartTime-this.totalPausedTime)/1e3;return Math.max(0,t)}};let Zh=1e3,Qh=1e3;var $h=class{constructor(e){this.recordingStartTime=0,this.recordingTimer=null,this.pauseStartTime=null,this.totalPausedTime=0,this.streamProcessor=null,this.bufferSizeUpdateInterval=null,this.tabVisibilityTracker=null,this.visibilityChangeHandler=null,this.blurHandler=null,this.focusHandler=null,this.streamManager=e}isRecording(){return this.streamManager.getState()===`recording`}getStreamProcessor(){return this.streamProcessor}getAudioStreamForAnalysis(){if(this.streamProcessor){let e=this.streamProcessor.getAudioStreamForAnalysis();if(e)return e}return this.streamManager.getAudioStreamForAnalysis()}async startRecording(e,t,n,r){let i=this.streamManager.getStream();if($.debug(`[StreamRecordingState] startRecording called`,{hasMediaStream:!!i,isRecording:this.isRecording(),hasProcessor:!!e,audioTracks:i?.getAudioTracks().length||0}),!i)throw Error(`Stream must be started before recording`);if(this.isRecording())return $.debug(`[StreamRecordingState] Already recording, returning`),Promise.resolve();let a=await th({requiresAudio:i.getAudioTracks().length>0,requiresWatermark:t.watermark!==void 0});if(!a.isSupported)throw kt({missingCapabilities:a.missing,resolutionStage:`feature-preflight`});this.streamProcessor=e,$.debug(`[StreamRecordingState] StreamProcessor assigned, setting callbacks`),e.setOnMuteStateChange(e=>{this.streamManager.emit(`audiomutetoggle`,{muted:e})}),e.setOnSourceChange(e=>{this.streamManager.emit(`videosourcechange`,{stream:e})}),this.bufferSizeUpdateInterval=window.setInterval(()=>{if(!this.streamProcessor)return;let e=this.streamProcessor.getBufferSize(),t=Jh(e);this.streamManager.emit(`recordingbufferupdate`,{size:e,formatted:t})},Zh),this.resetRecordingState();let o=n&&r?{enabled:!0,text:r,recordingStartTime:this.recordingStartTime}:void 0;$.debug(`[StreamRecordingState] Overlay config`,{enableTabVisibilityOverlay:n,hasOverlayText:!!r,overlayText:r,overlayConfig:o}),$.debug(`[StreamRecordingState] Starting processing`),await e.startProcessing(i,t,o),$.info(`[StreamRecordingState] Processing started and worker ready`),n&&($.debug(`[StreamRecordingState] Setting up tab visibility tracking`,{recordingStartTime:this.recordingStartTime}),this.tabVisibilityTracker=new Xh,this.tabVisibilityTracker.start(this.recordingStartTime),this.setupVisibilityUpdates(e)),this.streamManager.setState(`recording`),this.streamManager.emit(`recordingstart`,{recorder:null}),this.startRecordingTimer()}async stopRecording(){let e=(performance.now()-this.recordingStartTime-this.totalPausedTime)/Qh;if($.debug(`[StreamRecordingState] stopRecording called`,{hasStreamProcessor:!!this.streamProcessor,isRecording:this.isRecording(),recordingElapsedSeconds:e}),!(this.streamProcessor&&this.isRecording()))throw Error(`Not currently recording`);this.streamManager.setState(`stopping`),this.clearRecordingTimer(),this.clearBufferSizeInterval(),this.resetPauseState(),this.cleanupVisibilityUpdates();let t=[];this.tabVisibilityTracker?(t=this.tabVisibilityTracker.getIntervals(),$.debug(`[StreamRecordingState] Tab visibility intervals collected`,{intervalsCount:t.length,intervals:t}),this.tabVisibilityTracker.cleanup(),this.tabVisibilityTracker=null):$.debug(`[StreamRecordingState] No tab visibility tracker was active`),$.debug(`[StreamRecordingState] Finalizing stream processor`);let n=await this.streamProcessor.finalize();return $.info(`[StreamRecordingState] Stream processor finalized`,{blobSize:n.blob.size,hasBlob:!!n.blob}),this.streamManager.setState(`active`),this.streamManager.emit(`recordingstop`,{blob:n.blob,mimeType:`video/mp4`}),this.streamProcessor=null,$.debug(`[StreamRecordingState] StreamProcessor cleared`),{blob:n.blob,tabVisibilityIntervals:t}}pauseRecording(){this.clearRecordingTimer(),this.pauseStartTime===null&&(this.pauseStartTime=Date.now()),this.tabVisibilityTracker&&this.tabVisibilityTracker.pause(),this.streamProcessor&&this.isRecording()&&this.streamProcessor.pause()}resumeRecording(){if(this.pauseStartTime!==null){let e=Date.now()-this.pauseStartTime;this.totalPausedTime+=e,this.pauseStartTime=null}this.tabVisibilityTracker&&this.tabVisibilityTracker.resume(),this.startRecordingTimer(),this.streamProcessor&&this.isRecording()&&this.streamProcessor.resume()}toggleMute(){vh(this.streamProcessor,`StreamProcessor`).toggleMute()}muteAudio(){this.streamProcessor?(this.streamProcessor.isMutedState()||this.streamProcessor.toggleMute(),this.streamManager.setAudioTracksEnabled(!1)):this.streamManager.getStream()&&(this.streamManager.setAudioTracksEnabled(!1),this.streamManager.emit(`audiomutetoggle`,{muted:!0}))}unmuteAudio(){this.streamProcessor?(this.streamProcessor.isMutedState()&&this.streamProcessor.toggleMute(),this.streamManager.setAudioTracksEnabled(!0)):this.streamManager.getStream()&&(this.streamManager.setAudioTracksEnabled(!0),this.streamManager.emit(`audiomutetoggle`,{muted:!1}))}isMuted(){if(this.streamProcessor)return this.streamProcessor.isMutedState();let e=this.streamManager.getStream();if(e){let t=e.getAudioTracks();return t.length>0&&t.every(e=>!e.enabled)}return!1}async switchVideoSource(e){await vh(this.streamProcessor,`StreamProcessor`).switchVideoSource(e)}getCurrentVideoSource(){return _h(vh(this.streamProcessor,`StreamProcessor`).getCurrentVideoSource(),`Current video source is not available`)}formatTimeElapsed(e){let t=Math.floor(e/60),n=Math.floor(e%60);return`${t.toString().padStart(2,`0`)}:${n.toString().padStart(2,`0`)}`}startRecordingTimer(){this.recordingTimer=window.setInterval(()=>{let e=(Date.now()-this.recordingStartTime-this.totalPausedTime)/Qh,t=this.formatTimeElapsed(e);this.streamManager.emit(`recordingtimeupdate`,{elapsed:e,formatted:t})},Zh)}clearRecordingTimer(){this.recordingTimer!==null&&(clearInterval(this.recordingTimer),this.recordingTimer=null)}clearBufferSizeInterval(){this.bufferSizeUpdateInterval!==null&&(clearInterval(this.bufferSizeUpdateInterval),this.bufferSizeUpdateInterval=null)}resetRecordingState(){this.recordingStartTime=performance.now(),this.totalPausedTime=0,this.pauseStartTime=null}resetPauseState(){this.totalPausedTime=0,this.pauseStartTime=null}setupVisibilityUpdates(e){if(typeof document>`u`||typeof window>`u`){$.warn(`[StreamRecordingState] Cannot setup visibility updates - document/window not available`);return}if(this.visibilityChangeHandler=()=>{if(typeof document>`u`)return;let t=document.visibilityState===`hidden`,n=performance.now();$.debug(`[StreamRecordingState] Visibility change`,{isHidden:t,timestamp:n,visibilityState:document.visibilityState}),e.updateTabVisibility(t,n)},this.blurHandler=()=>{let t=performance.now();$.debug(`[StreamRecordingState] Window blur`,{timestamp:t}),e.updateTabVisibility(!0,t)},this.focusHandler=()=>{let t=performance.now();$.debug(`[StreamRecordingState] Window focus`,{timestamp:t}),e.updateTabVisibility(!1,t)},document.addEventListener(`visibilitychange`,this.visibilityChangeHandler),window.addEventListener(`blur`,this.blurHandler),window.addEventListener(`focus`,this.focusHandler),document.visibilityState===`hidden`){let t=performance.now();$.debug(`[StreamRecordingState] Initial state is hidden`,{timestamp:t}),e.updateTabVisibility(!0,t)}else $.debug(`[StreamRecordingState] Initial state is visible`)}cleanupVisibilityUpdates(){this.visibilityChangeHandler&&typeof document<`u`&&(document.removeEventListener(`visibilitychange`,this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.blurHandler&&typeof window<`u`&&(window.removeEventListener(`blur`,this.blurHandler),this.blurHandler=null),this.focusHandler&&typeof window<`u`&&(window.removeEventListener(`focus`,this.focusHandler),this.focusHandler=null)}destroy(){this.streamProcessor&&=(this.streamProcessor.cancel().catch(()=>{}),null),this.cleanupVisibilityUpdates(),this.tabVisibilityTracker&&=(this.tabVisibilityTracker.cleanup(),null),this.clearRecordingTimer(),this.clearBufferSizeInterval()}},eg=class{constructor(e={}){this.streamManager=new Gh(e),this.recordingState=new $h(this.streamManager)}getState(){return this.streamManager.getState()}getStream(){return this.streamManager.getStream()}getAudioStreamForAnalysis(){return this.recordingState.getAudioStreamForAnalysis()}isRecording(){return this.recordingState.isRecording()}isActive(){return this.streamManager.isActive()}on(e,t){return this.streamManager.on(e,t)}off(e,t){this.streamManager.off(e,t)}once(e,t){return this.streamManager.once(e,t)}setAudioDevice(e){this.streamManager.setAudioDevice(e)}setVideoDevice(e){this.streamManager.setVideoDevice(e)}getAudioDevice(){return this.streamManager.getAudioDevice()}getVideoDevice(){return this.streamManager.getVideoDevice()}async getAvailableDevices(){return await this.streamManager.getAvailableDevices()}async startStream(){return await this.streamManager.startStream()}stopStream(){this.streamManager.stopStream()}switchVideoDevice(e){return this.streamManager.switchVideoDevice(e)}switchAudioDevice(e){return this.streamManager.switchAudioDevice(e)}async startRecording(e,t,n,r){return await this.recordingState.startRecording(e,t,n,r)}async stopRecording(){return await this.recordingState.stopRecording()}pauseRecording(){this.recordingState.pauseRecording()}resumeRecording(){this.recordingState.resumeRecording()}toggleMute(){this.recordingState.toggleMute()}muteAudio(){this.recordingState.muteAudio()}unmuteAudio(){this.recordingState.unmuteAudio()}isMuted(){return this.recordingState.isMuted()}async switchVideoSource(e){return await this.recordingState.switchVideoSource(e)}setMediaStream(e){this.streamManager.setMediaStream(e)}getCurrentVideoSource(){return this.recordingState.getCurrentVideoSource()}destroy(){this.recordingState.destroy(),this.streamManager.destroy()}};let tg=`VIDTREO_INSTALLATION_ID`,ng=`unknown`,rg=new Map;function ig(e){let t=e.storageProvider,n=t?.getItem(tg);if(n)return $.debug(`Using existing installation ID from storage`,{installationId:n}),n;let r=ag(e);return t?.setItem(tg,r),$.debug(`Created new installation ID`,{installationId:r}),r}function ag(e){let t=e.cryptoProvider;if(t?.getRandomValues){let e=new Uint8Array(16);return t.getRandomValues(e),Array.from(e).map(e=>e.toString(16).padStart(2,`0`)).join(``)}let n=e.nowProvider().toString(16),r=e.randomProvider();return`${n}-${Math.floor(r*1e9).toString(16)}`}let og=[`sdk.init.started`,`sdk.init.succeeded`,`sdk.init.failed`],sg=[`stream.error`],cg={"sdk.init.started":`lifecycle`,"sdk.init.succeeded":`lifecycle`,"sdk.init.failed":`error`,"preview.start.succeeded":`interaction`,"preview.start.failed":`error`,"recording.start.requested":`interaction`,"recording.start.succeeded":`interaction`,"recording.start.failed":`error`,"recording.stop.requested":`interaction`,"recording.stop.succeeded":`interaction`,"recording.stop.failed":`error`,"upload.started":`performance`,"upload.succeeded":`performance`,"upload.failed":`error`,"source.switch.requested":`interaction`,"source.switch.succeeded":`interaction`,"source.switch.failed":`error`,"stream.error":`error`};var lg=class{constructor(e,t){this.pendingEvents=[],this.flushTimeoutId=null,this.throttledEventTimestamps=new Map,this.config=e,this.dependencies=t,this.installationId=ig(this.dependencies),$.debug(`TelemetryClient initialized`,{installationId:this.installationId,backendUrl:e.backendUrl})}triggerTelemetryEvent(e){try{let t=this.dependencies.nowProvider();if(this.shouldSkipEvent(e.name,t))return;let n=cg[e.name],r=this.buildError(e.error),i=this.buildFingerprint(),a=this.buildContext(),o=this.mergeProperties(this.buildBaseProperties(i),e),s={event:e.name,category:n,timestamp:t,installationId:this.installationId,fingerprint:i,sdkVersion:`1.2.1`,context:a,properties:o,error:r};this.markEventTracking(e.name,t),this.enqueueEvent(s)}catch(t){$.error(`Telemetry event failed`,{eventName:e.name,error:i(t)})}}enqueueEvent(e){try{if(this.pendingEvents=[...this.pendingEvents,e],this.pendingEvents.length>=10){this.flushQueue();return}this.scheduleFlush()}catch(e){$.error(`Failed to enqueue telemetry event`,{error:i(e)})}}scheduleFlush(){this.flushTimeoutId||=this.dependencies.setTimeoutFunction(()=>{this.flushQueue()},1e3)}flushQueue(){try{if(this.pendingEvents.length===0){this.clearFlushTimer();return}let e=this.pendingEvents;this.pendingEvents=[],this.clearFlushTimer();let t=this.buildRequestPayload(e);$.debug(`Telemetry batch flush`,{eventsCount:t.events.length}),this.sendPayload(t).catch(()=>null)}catch(e){$.error(`Failed to flush telemetry queue`,{error:i(e)})}}clearFlushTimer(){this.flushTimeoutId&&=(this.dependencies.clearTimeoutFunction(this.flushTimeoutId),null)}buildRequestPayload(e){return{events:[...e]}}shouldSkipEvent(e,t){if(this.isOneTimeEvent(e)){let t=this.getOneTimeCacheKey(e);if(rg.get(t))return $.debug(`Telemetry event skipped (dedupe)`,{event:e}),!0}if(this.isThrottledEvent(e)){let n=this.throttledEventTimestamps.get(e);if(n!==void 0&&t-n<5e3)return $.debug(`Telemetry event skipped (throttle)`,{event:e,lastSent:n}),!0}return!1}markEventTracking(e,t){if(this.isOneTimeEvent(e)){let t=this.getOneTimeCacheKey(e);rg.set(t,!0)}this.isThrottledEvent(e)&&(this.throttledEventTimestamps=this.updateNumberMap(this.throttledEventTimestamps,e,t))}updateNumberMap(e,t,n){let r=new Map(e);return r.set(t,n),r}getOneTimeCacheKey(e){return`${this.installationId}:${e}`}isOneTimeEvent(e){return og.includes(e)}isThrottledEvent(e){return sg.includes(e)}buildBaseProperties(e){let t={},n=e.userAgent,r=this.getBrowserName(n);return r&&(t={...t,browserName:r}),t}mergeProperties(e,t){let n=t.properties;if(!(Object.keys(e).length===0&&!n)){if(Object.keys(e).length>0&&n)return{...e,...n};if(Object.keys(e).length>0)return{...e};if(n)return{...n}}}buildFingerprint(){let e=this.dependencies.navigatorProvider;if(!e)return{};let t={userAgent:e.userAgent,language:e.language,platform:e.platform};e.hardwareConcurrency&&(t={...t,hardwareConcurrency:e.hardwareConcurrency});let n=this.getDeviceMemory(e);return n!==null&&(t={...t,deviceMemory:n}),t}buildContext(){let e=this.config.pageUrl,t=this.config.referrerUrl;if(!e){let t=this.dependencies.locationProvider;t&&(e=t.href)}if(!t){let e=this.dependencies.documentProvider;if(e){let n=e.referrer;n&&(t=n)}}return{sessionId:this.config.sessionId,userId:this.config.userId,environmentId:this.config.environmentId,appVersion:this.config.appVersion,release:this.config.release,pageUrl:e,referrerUrl:t,sdkLocation:this.config.sdkLocation,clientLocation:this.config.clientLocation}}buildError(e){if(!e)return;let t={message:i(e)};return e instanceof Error&&(e.name&&(t.code=e.name),e.stack&&(t.stack=e.stack)),t}getBrowserName(e){return e?e.includes(`Edg`)?`edge`:e.includes(`Chrome`)?`chrome`:e.includes(`Firefox`)?`firefox`:e.includes(`Safari`)?`safari`:ng:ng}getDeviceMemory(e){let t=e;return t.deviceMemory?t.deviceMemory:null}async sendPayload(e){let t=this.buildTelemetryEndpoint(),n={method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${this.config.apiKey}`},body:JSON.stringify(e)};$.debug(`Sending telemetry to endpoint`,{endpoint:t,payloadSize:JSON.stringify(e).length,hasApiKey:!!this.config.apiKey}),await this.dependencies.fetchFunction(t,n).catch(e=>($.error(`Failed to send telemetry`,{endpoint:t,error:i(e)}),null))}buildTelemetryEndpoint(){return this.config.endpoint?this.config.endpoint:`${this.config.backendUrl}/api/v1/telemetry`}};function ug(){let e=typeof window<`u`,t=typeof document<`u`,n=fetch,r=null,i=null,a=null,o=null,s=null,c=setTimeout,l=clearTimeout;return e&&(n=window.fetch.bind(window),r=window.crypto,i=window.localStorage,a=window.navigator,o=window.location,c=window.setTimeout.bind(window),l=window.clearTimeout.bind(window)),t&&(s=document),{fetchFunction:n,cryptoProvider:r,storageProvider:i,navigatorProvider:a,locationProvider:o,documentProvider:s,nowProvider:()=>Date.now(),randomProvider:()=>Math.random(),setTimeoutFunction:c,clearTimeoutFunction:l}}function dg(e,t,n){return new lg({apiKey:e,backendUrl:t,endpoint:n?.endpoint,sessionId:n?.sessionId,userId:n?.userId,environmentId:n?.environmentId,appVersion:n?.appVersion,release:n?.release,pageUrl:n?.pageUrl,referrerUrl:n?.referrerUrl,sdkLocation:n?.sdkLocation,clientLocation:n?.clientLocation},ug())}var fg=class{constructor(e,t){this.isProcessing=!1,this.retryTimeoutId=null,this.callbacks={},this.storageService=e,this.uploadService=t,this.networkOnlineHandler=()=>{this.processQueue().catch(e=>{let t=i(e);this.callbacks.onUploadError?.(`network-recovery`,Error(t))})},window.addEventListener(`online`,this.networkOnlineHandler),this.processingIntervalId=window.setInterval(()=>{this.processQueue().catch(e=>{let t=i(e);this.callbacks.onUploadError?.(`processing-loop`,Error(t))})},5e3)}destroy(){this.clearTimer(this.processingIntervalId,clearInterval),this.clearTimer(this.retryTimeoutId,clearTimeout),window.removeEventListener(`online`,this.networkOnlineHandler)}setCallbacks(e){this.callbacks=e}async queueUpload(e){let t=await this.storageService.savePendingUpload(e);return this.processQueue(),t}async processQueue(){if(!this.isProcessing){this.isProcessing=!0;try{if(!this.storageService.isInitialized())throw Error(`Database not initialized`);let e=await this.storageService.getPendingUploads(`pending`);if(e.length>0){let t=this.getOldestUpload(e);await this.processUpload(t),this.isProcessing=!1;return}let t=(await this.storageService.getPendingUploads(`failed`)).filter(e=>e.retryCount<10);if(t.length>0){let e=this.getOldestFailedUpload(t),n=this.calculateRetryDelay(e.retryCount),r=Date.now()-e.updatedAt;if(r>=n)await this.storageService.updateUploadStatus(e.id,{status:`pending`,retryCount:e.retryCount}),await this.processUpload(e);else{let e=n-r;this.scheduleRetry(e)}}this.isProcessing=!1}catch(e){throw this.isProcessing=!1,Error(`Error processing upload queue: ${i(e)}`)}}}getPendingUploads(){return this.storageService.getPendingUploads()}async getStats(){let e=await this.storageService.getPendingUploads(),t={pending:0,uploading:0,failed:0,total:e.length};for(let n of e)n.status===`pending`?t.pending+=1:n.status===`uploading`?t.uploading+=1:n.status===`failed`&&(t.failed+=1);return t}getOldestUpload(e){if(e.length===0)throw Error(`Cannot get oldest upload from empty array`);return e.sort((e,t)=>e.createdAt-t.createdAt)[0]}getOldestFailedUpload(e){if(e.length===0)throw Error(`Cannot get oldest failed upload from empty array`);return e.sort((e,t)=>e.updatedAt-t.updatedAt)[0]}async processUpload(e){try{await this.storageService.updateUploadStatus(e.id,{status:`uploading`});let t=await this.uploadService.uploadVideo(e.blob,{apiKey:e.apiKey,backendUrl:e.backendUrl,filename:e.filename,metadata:e.metadata,userMetadata:e.userMetadata,onProgress:t=>{this.callbacks.onUploadProgress?.(e.id,t)}});await this.storageService.deleteUpload(e.id),this.callbacks.onUploadComplete?.(e.id,t)}catch(t){let n=i(t),r=e.retryCount+1;if(await this.storageService.updateUploadStatus(e.id,{status:`failed`,retryCount:r,lastError:n}),r>=10)this.callbacks.onUploadError?.(e.id,Error(`Upload failed after 10 attempts: ${n}`));else{let e=this.calculateRetryDelay(r);this.scheduleRetry(e)}}}calculateRetryDelay(e){let t=2e3*1.5**(e-1);return Math.min(t,3e5)}scheduleRetry(e){this.clearTimer(this.retryTimeoutId,clearTimeout),this.retryTimeoutId=window.setTimeout(()=>{this.retryTimeoutId=null,this.processQueue()},e)}clearTimer(e,t){e!==null&&t(e)}},pg=class{uploadVideo(e,t){if(!t.filename)throw Error(`Filename is required`);if(!e.type||e.type.trim()===``)throw Error(`Blob type is required`);return this.uploadVideoFile(e,t)}uploadVideoFile(e,t){return new Promise((n,r)=>{let i=new XMLHttpRequest;if(t.onProgress){let e=t.onProgress;i.upload.addEventListener(`progress`,t=>{t.lengthComputable&&e(t.loaded/t.total)})}i.addEventListener(`load`,()=>{if(i.status>=200&&i.status<=299){this.parseSuccessResponse(i,n,r);return}this.parseErrorResponse(i,r)}),i.addEventListener(`error`,()=>{r(Error(`Network error during upload`))}),i.addEventListener(`abort`,()=>{r(Error(`Upload was aborted`))});let a=`${t.backendUrl}/api/v1/videos/upload`;i.open(`POST`,a),i.setRequestHeader(`Authorization`,`Bearer ${t.apiKey}`);let o=new FormData;o.append(`file`,e,t.filename);let s={filename:t.filename,mimeType:e.type};t.userMetadata&&(s.userMetadata=t.userMetadata),o.append(`metadata`,JSON.stringify(s)),i.send(o)})}parseSuccessResponse(e,t,n){let r=this.safeParseJsonFromXhr(e);if(!r){n(Error(`Failed to parse upload response: invalid JSON`));return}let i=r.data;if(!i){n(Error(`Failed to parse upload response: missing data`));return}t({id:i.id,publicId:i.publicId,filename:i.filename,fileSize:i.fileSize,mimeType:i.mimeType,duration:i.duration,status:i.status,uploadUrl:i.uploadUrl,createdAt:i.createdAt})}parseErrorResponse(e,t){let n=this.safeParseJsonFromXhr(e);if(n&&typeof n==`object`&&`error`in n&&typeof n.error==`string`){t(Error(n.error));return}t(Error(`Upload failed: ${e.status} ${e.statusText}`))}safeParseJsonFromXhr(e){if(!e.responseText||e.responseText.trim()===``)return null;let t=e.responseText.trim();if(!(t.startsWith(`{`)&&t.endsWith(`}`))||t.length<2)return null;let n=JSON.parse(e.responseText);return typeof n==`object`&&n?n:null}};let mg=e=>{},hg=e=>{},gg=e=>{},_g=()=>{},vg=e=>{},yg=(e,t)=>{},bg=e=>{},xg=e=>{},Sg=e=>{},Cg=()=>{},wg=e=>{};function Tg(e){let t={onProgress:mg,onSuccess:hg,onError:gg,onClearStatus:_g};return e.upload&&(t=e.upload),t}function Eg(e){let t=wg;return e.onStorageCleanupError&&(t=e.onStorageCleanupError),t}function Dg(e,t){let n=e.recording,r=vg;n?.onStateChange&&(r=n.onStateChange);let i=yg;n?.onCountdownUpdate&&(i=n.onCountdownUpdate);let a=bg;n?.onTimerUpdate&&(a=n.onTimerUpdate);let o=xg;n?.onError&&(o=n.onError);let s=Sg;n?.onRecordingComplete&&(s=n.onRecordingComplete);let c=Cg;return n?.onClearUploadStatus&&(c=n.onClearUploadStatus),{onStateChange:r,onCountdownUpdate:i,onTimerUpdate:a,onError:o,onRecordingComplete:s,onClearUploadStatus:c,onStopAudioTracking:t.stopAudioTracking,onGetConfig:t.getConfig}}function Og(e,t){let n=e.sourceSwitch;return{onSourceChange:n?.onSourceChange,onPreviewUpdate:n?.onPreviewUpdate,onError:n?.onError,onTransitionStart:n?.onTransitionStart,onTransitionEnd:n?.onTransitionEnd,onScreenSelectionStart:()=>{t.isRecording()&&t.updateSourceType(!0)},onScreenSelectionEnd:()=>{t.isRecording()&&t.updateSourceType(!1)},getSelectedCameraDeviceId:t.getSelectedCameraDeviceId,getSelectedMicDeviceId:t.getSelectedMicDeviceId}}function kg(e){let t=e.getVideoTracks();if(t.length===0)return!1;let n=t[0];return`displaySurface`in n.getSettings()||n.label.toLowerCase().includes(`screen`)||n.label.toLowerCase().includes(`display`)}em();function Ag(e){if(e!==void 0)return typeof e==`number`?e:e===Qf?`low`:e===$f?`medium`:e===ep?`high`:e===tp?`very-high`:`high`}let jg=`recording.invalid-container-layout`;function Mg(e){let t=Error(jg);return t.code=jg,t.detectedBoxTypes=e,t}function Ng(e){return e instanceof Uint8Array?e:new Uint8Array(e)}function Pg(e,t){let n=e.getUint8(t),r=e.getUint8(t+1),i=e.getUint8(t+2),a=e.getUint8(t+3);return String.fromCharCode(n,r,i,a)}function Fg(e,t){let n=e.getUint32(t,!1),r=e.getUint32(t+4,!1);return n*4294967296+r}function Ig(e){let t=new Set;for(let n of e)t.add(n);return[...t]}function Lg(e){let t=Ng(e),n=t.byteLength,r=new DataView(t.buffer,t.byteOffset,t.byteLength),i=[],a=0;for(;a<n;){if(!(a+8<=n))throw Mg(i.map(e=>e.type));let e=r.getUint32(a,!1),t=Pg(r,a+4),o=e,s=8;if(e===1){let e=a+8;if(!(e+8<=n))throw Mg(i.map(e=>e.type));o=Fg(r,e),s=16}if(e===0&&(o=n-a),!(o>=s))throw Mg(i.map(e=>e.type));let c=a+o;if(!(c<=n))throw Mg(i.map(e=>e.type));i.push({type:t,size:o,startOffset:a,endOffset:c}),a=c}return i}function Rg(e){let t=Lg(e).filter(e=>e.type===`moof`||e.type===`mfra`).map(e=>e.type);if(t.length>0)throw Mg(Ig(t))}function zg(e){let t=null,n=0;function r(){if(!t){let n=e.createBlob();t=e.createObjectUrl(n)}return n+=1,t}function i(){n!==0&&(--n,n===0&&(t&&=(e.revokeObjectUrl(t),null)))}return{acquire:r,release:i}}let Bg=`vidtreo-audio-worklet`,Vg=`audioChunk`,Hg=`setMuted`,Ug=`setPaused`,Wg=`shutdown`,Gg=`
123
+ const AUDIO_WORKLET_MESSAGE_TYPE_AUDIO_CHUNK = "${Vg}";
124
+ const AUDIO_WORKLET_MESSAGE_TYPE_SET_MUTED = "${Hg}";
125
+ const AUDIO_WORKLET_MESSAGE_TYPE_SET_PAUSED = "${Ug}";
126
+ const AUDIO_WORKLET_MESSAGE_TYPE_SHUTDOWN = "${Wg}";
127
127
 
128
128
  class VidtreoAudioWorkletProcessor extends AudioWorkletProcessor {
129
129
  constructor() {
@@ -207,8 +207,8 @@ class VidtreoAudioWorkletProcessor extends AudioWorkletProcessor {
207
207
  }
208
208
  }
209
209
 
210
- registerProcessor("${Og}", VidtreoAudioWorkletProcessor);
211
- `;function Pg(){if(typeof Blob>`u`||typeof URL>`u`)throw Error(`Blob and URL APIs are required for audio worklet loading`);return new Blob([Ng],{type:`application/javascript`})}let Fg=Dg({createBlob:Pg,createObjectUrl:e=>URL.createObjectURL(e),revokeObjectUrl:e=>{URL.revokeObjectURL(e)}});var Ig=class{constructor(){this.audioContext=null,this.audioWorkletNode=null,this.audioSourceNode=null,this.audioDestinationNode=null,this.audioConfig=null,this.onAudioChunk=null,this.isMuted=!1,this.isPaused=!1,this.isProcessing=!1,this.hasAudioWorkletUrlLease=!1}async initialize(e,t){if(!e)throw Error(`Audio stream is required`);let n=e.getAudioTracks();if(n.length===0)throw Error(`Audio stream has no tracks`);let r=a();if(!r)throw Error(`AudioContext is not supported in this browser`);this.onAudioChunk=t;try{let t=Fg.acquire();this.hasAudioWorkletUrlLease=!0;let a=new r;this.audioContext=a,a.resume().catch(e=>{$.warn(`[AudioWorkletController] Failed to resume AudioContext`,i(e))}),await a.audioWorklet.addModule(t).catch(e=>{let t=i(e);throw Error(`Failed to load AudioWorklet module: ${t}`)});let o=this.getChannelCount(n[0]),s=new AudioWorkletNode(a,Og,{numberOfInputs:1,numberOfOutputs:1,outputChannelCount:[o]});s.port.onmessage=this.handleWorkletMessage.bind(this),this.audioWorkletNode=s,this.audioSourceNode=a.createMediaStreamSource(e),this.audioDestinationNode=a.createGain(),this.audioDestinationNode.gain.value=0;let c={sampleRate:a.sampleRate,numberOfChannels:o,format:`f32-planar`};return this.audioConfig=c,this.setMuted(this.isMuted),this.setPaused(this.isPaused),c}catch(e){throw await this.cleanupAfterInitializeFailure(),this.normalizeInitializationError(e)}}async startProcessing(){if(!this.isProcessing){if(!this.audioContext)throw Error(`AudioContext is not initialized`);if(!this.audioWorkletNode)throw Error(`AudioWorklet node is not initialized`);if(!this.audioSourceNode)throw Error(`Audio source node is not initialized`);if(!this.audioDestinationNode)throw Error(`AudioWorklet graph is not initialized`);this.audioSourceNode.connect(this.audioWorkletNode),this.audioWorkletNode.connect(this.audioDestinationNode),this.audioDestinationNode.connect(this.audioContext.destination),await this.audioContext.resume(),this.isProcessing=!0}}setMuted(e){this.isMuted=e,this.audioWorkletNode&&this.audioWorkletNode.port.postMessage({type:Ag,isMuted:e})}setPaused(e){this.isPaused=e,this.audioWorkletNode&&this.audioWorkletNode.port.postMessage({type:jg,isPaused:e})}close(){this.disconnectAudioNodes(!0),this.closeAudioContext(),this.audioConfig=null,this.onAudioChunk=null,this.isMuted=!1,this.isPaused=!1,this.isProcessing=!1,this.releaseAudioWorkletUrlLease()}getConfig(){return this.audioConfig}handleWorkletMessage(e){let t=e.data;if(!t||t.type!==kg)return;let n=this.parseAudioBuffer(t.data);if(!n||!this.onAudioChunk)return;let r={data:n,frames:t.frames,numberOfChannels:t.numberOfChannels,sampleRate:t.sampleRate,timestamp:t.timestamp};this.onAudioChunk(r)}parseAudioBuffer(e){return e instanceof Float32Array?e:e instanceof ArrayBuffer?new Float32Array(e):null}getChannelCount(e){let t=e.getSettings().channelCount;return typeof t==`number`&&t>0?t:1}async cleanupAfterInitializeFailure(){this.disconnectAudioNodes(!1),await this.closeAudioContext(),this.audioConfig=null,this.onAudioChunk=null,this.releaseAudioWorkletUrlLease()}normalizeInitializationError(e){if(e instanceof Error)return e;let t=i(e);return Error(t)}disconnectAudioNodes(e){this.audioWorkletNode&&=(e&&this.audioWorkletNode.port.postMessage({type:Mg}),this.audioWorkletNode.disconnect(),null),this.audioSourceNode&&=(this.audioSourceNode.disconnect(),null),this.audioDestinationNode&&=(this.audioDestinationNode.disconnect(),null)}closeAudioContext(){if(!this.audioContext)return Promise.resolve();let e=this.audioContext;return this.audioContext=null,e.close().catch(e=>{$.warn(`[AudioWorkletController] Failed to close AudioContext`,i(e))})}releaseAudioWorkletUrlLease(){this.hasAudioWorkletUrlLease&&=(Fg.release(),!1)}},Lg=class{constructor(e){this.audioWorkletController=null,this.audioWorkletConfig=null,this.onChunk=e.onChunk;let t=()=>new Ig;e.createController&&(t=e.createController),this.createController=t}async prepareAudioConfig(e){if(!e)return this.audioWorkletConfig=null,null;this.audioWorkletController||=this.createController();let t=new MediaStream([e]);return this.audioWorkletConfig=await this.audioWorkletController.initialize(t,e=>this.onChunk(e)).catch(e=>{throw this.stop(),e}),this.createWorkerAudioConfig(this.audioWorkletConfig)}async startProcessing(){this.audioWorkletController&&await this.audioWorkletController.startProcessing()}stop(){this.audioWorkletController&&=(this.audioWorkletController.close(),null),this.audioWorkletConfig=null}setMuted(e){this.audioWorkletController&&this.audioWorkletController.setMuted(e)}setPaused(e){this.audioWorkletController&&this.audioWorkletController.setPaused(e)}createWorkerAudioConfig(e){return e?{sampleRate:e.sampleRate,numberOfChannels:e.numberOfChannels,format:e.format}:null}};function Rg(e,t){if(e.length===0)return null;t.stopCurrentVideoTrack();let n=e[0],r=t.cloneVideoTrack(n);return t.setCurrentVideoTrack(r),r}function zg(e,t){if(e.length===0)return null;let n=e[0];return t.cloneAudioTrack(n)}function Bg(e,t,n){if(!e)return{videoTrack:null,videoStream:null};if(t.hasMediaStreamTrackProcessor)return{videoTrack:e,videoStream:null};if(n.canUseMainThreadVideoProcessor()){let t=n.createVideoStreamFromTrack(e);if(t)return{videoTrack:null,videoStream:t}}throw n.createBrowserUnsupportedError()}function Vg(e){if(!e||typeof e.getSettings!=`function`)return;let t=e.getSettings(),n={};typeof t.width==`number`&&(n.width=t.width),typeof t.height==`number`&&(n.height=t.height),typeof t.facingMode==`string`&&(n.facingMode=t.facingMode);let r=t;return typeof r.rotation==`number`&&(n.rotation=r.rotation),n}function Hg(e){return e.isMobileDevice()}function Ug(e,t,n,r){r.logger.debug(`[WorkerProcessor] Track details`,{hasVideoTrack:!!e,hasVideoStream:!!n,videoTrackId:e?.id,videoTrackKind:e?.kind,videoTrackReadyState:e?.readyState,hasAudioTrack:!!t,audioTrackId:t?.id,audioTrackKind:t?.kind,audioTrackReadyState:t?.readyState})}function Wg(e,t){if(!e||typeof e.getSettings!=`function`)return;let n=Kg(e.getSettings()),r;typeof e.getCapabilities==`function`&&(r=qg(e.getCapabilities())),t.logger.debug(`[WorkerProcessor] Video track settings`,n),r&&t.logger.debug(`[WorkerProcessor] Video track capabilities`,r)}function Gg(e){let t=e.getViewportMetadata();t&&e.logger.debug(`[WorkerProcessor] Viewport metadata`,t)}function Kg(e){let t=e;return{width:e.width,height:e.height,frameRate:e.frameRate,aspectRatio:e.aspectRatio,facingMode:e.facingMode,resizeMode:t.resizeMode,deviceId:e.deviceId,groupId:e.groupId,rotation:t.rotation}}function qg(e){let t=e;return{width:e.width,height:e.height,frameRate:e.frameRate,aspectRatio:e.aspectRatio,facingMode:e.facingMode,resizeMode:t.resizeMode}}function Jg(e){let{createWorker:t,workerUrl:n,onMessage:r,onError:i,logger:a}=e;a.debug(`[WorkerProcessor] Worker URL created`,{urlType:typeof n,isBlobUrl:n.startsWith(`blob:`)});let o=t(n);return a.debug(`[WorkerProcessor] Worker created successfully`),o.onmessage=r,o.onerror=i,a.debug(`[WorkerProcessor] Worker event handlers attached`),o}function Yg(e){let{videoTrack:t,videoStream:n,audioStream:r,isMobileDevice:i,videoSettings:a,viewportMetadata:o,audioConfig:s,workerConfig:c,overlayConfig:l}=e;return{type:`start`,videoTrack:t,videoStream:n,audioStream:r,isMobileDevice:i,videoSettings:a,viewportMetadata:o,audioConfig:s,config:c,overlayConfig:l}}function Xg(e,t){return{type:`switchSource`,videoTrack:e,videoStream:t}}function Zg(e,t,n=null){let r=[];return e&&(r=[...r,e]),t&&(r=[...r,t]),n&&(r=[...r,n]),r}var Qg=class{constructor(e){this.workerProbePromise=null,this.workerProbeResolve=null,this.workerProbeTimeoutId=null,this.workerProbeResult=null,this.dependencies=e}handleProbeResult(e){this.finalizeProbeResult(e)}async getProbeResult(e){if(this.workerProbeResult)return this.workerProbeResult;if(this.workerProbePromise)return await this.workerProbePromise;let t=new Promise(e=>{this.workerProbeResolve=e});return this.workerProbePromise=t,this.workerProbeTimeoutId=this.dependencies.setTimeout(()=>{let e=this.getEmptyProbeResult();this.finalizeProbeResult(e)},this.dependencies.timeoutMilliseconds),e.postMessage({type:Fm}),await t}finalizeProbeResult(e){this.workerProbeTimeoutId!==null&&(this.dependencies.clearTimeout(this.workerProbeTimeoutId),this.workerProbeTimeoutId=null),this.workerProbeResult=e,this.workerProbeResolve&&=(this.workerProbeResolve(e),null),this.workerProbePromise=null}getEmptyProbeResult(){return{type:Im,hasMediaStreamTrackProcessor:!1,hasVideoFrame:!1,hasAudioData:!1,hasOffscreenCanvas:!1,hasCreateImageBitmap:!1,hasReadableStream:!1}}};function $g(){if(typeof Blob>`u`||typeof URL>`u`)throw Error(`Blob and URL APIs are required for worker loading`);return new Blob([`// ../../node_modules/mediabunny/dist/modules/src/misc.js
210
+ registerProcessor("${Bg}", VidtreoAudioWorkletProcessor);
211
+ `;function Kg(){if(typeof Blob>`u`||typeof URL>`u`)throw Error(`Blob and URL APIs are required for audio worklet loading`);return new Blob([Gg],{type:`application/javascript`})}let qg=zg({createBlob:Kg,createObjectUrl:e=>URL.createObjectURL(e),revokeObjectUrl:e=>{URL.revokeObjectURL(e)}});var Jg=class{constructor(){this.audioContext=null,this.audioWorkletNode=null,this.audioSourceNode=null,this.audioDestinationNode=null,this.audioConfig=null,this.onAudioChunk=null,this.isMuted=!1,this.isPaused=!1,this.isProcessing=!1,this.hasAudioWorkletUrlLease=!1}async initialize(e,t){if(!e)throw Error(`Audio stream is required`);let n=e.getAudioTracks();if(n.length===0)throw Error(`Audio stream has no tracks`);let r=a();if(!r)throw Error(`AudioContext is not supported in this browser`);this.onAudioChunk=t;try{let t=qg.acquire();this.hasAudioWorkletUrlLease=!0;let a=new r;this.audioContext=a,a.resume().catch(e=>{$.warn(`[AudioWorkletController] Failed to resume AudioContext`,i(e))}),await a.audioWorklet.addModule(t).catch(e=>{let t=i(e);throw Error(`Failed to load AudioWorklet module: ${t}`)});let o=this.getChannelCount(n[0]),s=new AudioWorkletNode(a,Bg,{numberOfInputs:1,numberOfOutputs:1,outputChannelCount:[o]});s.port.onmessage=this.handleWorkletMessage.bind(this),this.audioWorkletNode=s,this.audioSourceNode=a.createMediaStreamSource(e),this.audioDestinationNode=a.createGain(),this.audioDestinationNode.gain.value=0;let c={sampleRate:a.sampleRate,numberOfChannels:o,format:`f32-planar`};return this.audioConfig=c,this.setMuted(this.isMuted),this.setPaused(this.isPaused),c}catch(e){throw await this.cleanupAfterInitializeFailure(),this.normalizeInitializationError(e)}}async startProcessing(){if(!this.isProcessing){if(!this.audioContext)throw Error(`AudioContext is not initialized`);if(!this.audioWorkletNode)throw Error(`AudioWorklet node is not initialized`);if(!this.audioSourceNode)throw Error(`Audio source node is not initialized`);if(!this.audioDestinationNode)throw Error(`AudioWorklet graph is not initialized`);this.audioSourceNode.connect(this.audioWorkletNode),this.audioWorkletNode.connect(this.audioDestinationNode),this.audioDestinationNode.connect(this.audioContext.destination),await this.audioContext.resume(),this.isProcessing=!0}}setMuted(e){this.isMuted=e,this.audioWorkletNode&&this.audioWorkletNode.port.postMessage({type:Hg,isMuted:e})}setPaused(e){this.isPaused=e,this.audioWorkletNode&&this.audioWorkletNode.port.postMessage({type:Ug,isPaused:e})}close(){this.disconnectAudioNodes(!0),this.closeAudioContext(),this.audioConfig=null,this.onAudioChunk=null,this.isMuted=!1,this.isPaused=!1,this.isProcessing=!1,this.releaseAudioWorkletUrlLease()}getConfig(){return this.audioConfig}handleWorkletMessage(e){let t=e.data;if(!t||t.type!==Vg)return;let n=this.parseAudioBuffer(t.data);if(!n||!this.onAudioChunk)return;let r={data:n,frames:t.frames,numberOfChannels:t.numberOfChannels,sampleRate:t.sampleRate,timestamp:t.timestamp};this.onAudioChunk(r)}parseAudioBuffer(e){return e instanceof Float32Array?e:e instanceof ArrayBuffer?new Float32Array(e):null}getChannelCount(e){let t=e.getSettings().channelCount;return typeof t==`number`&&t>0?t:1}async cleanupAfterInitializeFailure(){this.disconnectAudioNodes(!1),await this.closeAudioContext(),this.audioConfig=null,this.onAudioChunk=null,this.releaseAudioWorkletUrlLease()}normalizeInitializationError(e){if(e instanceof Error)return e;let t=i(e);return Error(t)}disconnectAudioNodes(e){this.audioWorkletNode&&=(e&&this.audioWorkletNode.port.postMessage({type:Wg}),this.audioWorkletNode.disconnect(),null),this.audioSourceNode&&=(this.audioSourceNode.disconnect(),null),this.audioDestinationNode&&=(this.audioDestinationNode.disconnect(),null)}closeAudioContext(){if(!this.audioContext)return Promise.resolve();let e=this.audioContext;return this.audioContext=null,e.close().catch(e=>{$.warn(`[AudioWorkletController] Failed to close AudioContext`,i(e))})}releaseAudioWorkletUrlLease(){this.hasAudioWorkletUrlLease&&=(qg.release(),!1)}},Yg=class{constructor(e){this.audioWorkletController=null,this.audioWorkletConfig=null,this.onChunk=e.onChunk;let t=()=>new Jg;e.createController&&(t=e.createController),this.createController=t}async prepareAudioConfig(e){if(!e)return this.audioWorkletConfig=null,null;this.audioWorkletController||=this.createController();let t=new MediaStream([e]);return this.audioWorkletConfig=await this.audioWorkletController.initialize(t,e=>this.onChunk(e)).catch(e=>{throw this.stop(),e}),this.createWorkerAudioConfig(this.audioWorkletConfig)}async startProcessing(){this.audioWorkletController&&await this.audioWorkletController.startProcessing()}stop(){this.audioWorkletController&&=(this.audioWorkletController.close(),null),this.audioWorkletConfig=null}setMuted(e){this.audioWorkletController&&this.audioWorkletController.setMuted(e)}setPaused(e){this.audioWorkletController&&this.audioWorkletController.setPaused(e)}createWorkerAudioConfig(e){return e?{sampleRate:e.sampleRate,numberOfChannels:e.numberOfChannels,format:e.format}:null}};function Xg(e,t){if(e.length===0)return null;t.stopCurrentVideoTrack();let n=e[0],r=t.cloneVideoTrack(n);return t.setCurrentVideoTrack(r),r}function Zg(e,t){if(e.length===0)return null;let n=e[0];return t.cloneAudioTrack(n)}function Qg(e,t,n){if(!e)return{videoTrack:null,videoStream:null};if(t.hasMediaStreamTrackProcessor)return{videoTrack:e,videoStream:null};if(n.canUseMainThreadVideoProcessor()){let t=n.createVideoStreamFromTrack(e);if(t)return{videoTrack:null,videoStream:t}}throw n.createBrowserUnsupportedError()}function $g(e){if(!e||typeof e.getSettings!=`function`)return;let t=e.getSettings(),n={};typeof t.width==`number`&&(n.width=t.width),typeof t.height==`number`&&(n.height=t.height),typeof t.facingMode==`string`&&(n.facingMode=t.facingMode);let r=t;return typeof r.rotation==`number`&&(n.rotation=r.rotation),n}function e_(e){return e.isMobileDevice()}function t_(e,t,n,r){r.logger.debug(`[WorkerProcessor] Track details`,{hasVideoTrack:!!e,hasVideoStream:!!n,videoTrackId:e?.id,videoTrackKind:e?.kind,videoTrackReadyState:e?.readyState,hasAudioTrack:!!t,audioTrackId:t?.id,audioTrackKind:t?.kind,audioTrackReadyState:t?.readyState})}function n_(e,t){if(!e||typeof e.getSettings!=`function`)return;let n=i_(e.getSettings()),r;typeof e.getCapabilities==`function`&&(r=a_(e.getCapabilities())),t.logger.debug(`[WorkerProcessor] Video track settings`,n),r&&t.logger.debug(`[WorkerProcessor] Video track capabilities`,r)}function r_(e){let t=e.getViewportMetadata();t&&e.logger.debug(`[WorkerProcessor] Viewport metadata`,t)}function i_(e){let t=e;return{width:e.width,height:e.height,frameRate:e.frameRate,aspectRatio:e.aspectRatio,facingMode:e.facingMode,resizeMode:t.resizeMode,deviceId:e.deviceId,groupId:e.groupId,rotation:t.rotation}}function a_(e){let t=e;return{width:e.width,height:e.height,frameRate:e.frameRate,aspectRatio:e.aspectRatio,facingMode:e.facingMode,resizeMode:t.resizeMode}}function o_(e){let{createWorker:t,workerUrl:n,onMessage:r,onError:i,logger:a}=e;a.debug(`[WorkerProcessor] Worker URL created`,{urlType:typeof n,isBlobUrl:n.startsWith(`blob:`)});let o=t(n);return a.debug(`[WorkerProcessor] Worker created successfully`),o.onmessage=r,o.onerror=i,a.debug(`[WorkerProcessor] Worker event handlers attached`),o}function s_(e){let{videoTrack:t,videoStream:n,audioStream:r,isMobileDevice:i,videoSettings:a,viewportMetadata:o,audioConfig:s,workerConfig:c,overlayConfig:l}=e;return{type:`start`,videoTrack:t,videoStream:n,audioStream:r,isMobileDevice:i,videoSettings:a,viewportMetadata:o,audioConfig:s,config:c,overlayConfig:l}}function c_(e,t){return{type:`switchSource`,videoTrack:e,videoStream:t}}function l_(e,t,n=null){let r=[];return e&&(r=[...r,e]),t&&(r=[...r,t]),n&&(r=[...r,n]),r}var u_=class{constructor(e){this.workerProbePromise=null,this.workerProbeResolve=null,this.workerProbeTimeoutId=null,this.workerProbeResult=null,this.dependencies=e}handleProbeResult(e){this.finalizeProbeResult(e)}async getProbeResult(e){if(this.workerProbeResult)return this.workerProbeResult;if(this.workerProbePromise)return await this.workerProbePromise;let t=new Promise(e=>{this.workerProbeResolve=e});return this.workerProbePromise=t,this.workerProbeTimeoutId=this.dependencies.setTimeout(()=>{let e=this.getEmptyProbeResult();this.finalizeProbeResult(e)},this.dependencies.timeoutMilliseconds),e.postMessage({type:Lm}),await t}finalizeProbeResult(e){this.workerProbeTimeoutId!==null&&(this.dependencies.clearTimeout(this.workerProbeTimeoutId),this.workerProbeTimeoutId=null),this.workerProbeResult=e,this.workerProbeResolve&&=(this.workerProbeResolve(e),null),this.workerProbePromise=null}getEmptyProbeResult(){return{type:Rm,hasMediaStreamTrackProcessor:!1,hasVideoFrame:!1,hasAudioData:!1,hasOffscreenCanvas:!1,hasCreateImageBitmap:!1,hasReadableStream:!1}}};function d_(){if(typeof Blob>`u`||typeof URL>`u`)throw Error(`Blob and URL APIs are required for worker loading`);return new Blob([`// ../../node_modules/mediabunny/dist/modules/src/misc.js
212
212
  /*!
213
213
  * Copyright (c) 2026-present, Vanilagy and contributors
214
214
  *
@@ -8567,6 +8567,54 @@ class FrameCompositor {
8567
8567
  }
8568
8568
  }
8569
8569
 
8570
+ // src/core/processor/worker/stop-finalization.ts
8571
+ var STOP_PENDING_WRITES_TIMEOUT_MILLISECONDS = 500;
8572
+ var STOP_PENDING_WRITES_POLL_INTERVAL_MILLISECONDS = 10;
8573
+ var ERROR_STOP_PENDING_WRITES_TIMEOUT = "stop.pending-writes-timeout";
8574
+ function createDefaultNowMilliseconds() {
8575
+ return () => performance.now();
8576
+ }
8577
+ function createDefaultWaitMilliseconds() {
8578
+ return (milliseconds) => new Promise((resolve) => {
8579
+ globalThis.setTimeout(resolve, milliseconds);
8580
+ });
8581
+ }
8582
+ async function waitForPendingWritesToDrain(dependencies) {
8583
+ let getNowMilliseconds = dependencies.getNowMilliseconds;
8584
+ if (!getNowMilliseconds) {
8585
+ getNowMilliseconds = createDefaultNowMilliseconds();
8586
+ }
8587
+ let waitMilliseconds = dependencies.waitMilliseconds;
8588
+ if (!waitMilliseconds) {
8589
+ waitMilliseconds = createDefaultWaitMilliseconds();
8590
+ }
8591
+ let timeoutMilliseconds = dependencies.timeoutMilliseconds;
8592
+ if (timeoutMilliseconds === undefined) {
8593
+ timeoutMilliseconds = STOP_PENDING_WRITES_TIMEOUT_MILLISECONDS;
8594
+ }
8595
+ const startedAtMilliseconds = getNowMilliseconds();
8596
+ let pendingWriteCount = dependencies.getPendingWriteCount();
8597
+ while (pendingWriteCount > 0) {
8598
+ const elapsedMilliseconds = getNowMilliseconds() - startedAtMilliseconds;
8599
+ if (elapsedMilliseconds >= timeoutMilliseconds) {
8600
+ throw new Error(ERROR_STOP_PENDING_WRITES_TIMEOUT);
8601
+ }
8602
+ await waitMilliseconds(STOP_PENDING_WRITES_POLL_INTERVAL_MILLISECONDS);
8603
+ pendingWriteCount = dependencies.getPendingWriteCount();
8604
+ }
8605
+ }
8606
+
8607
+ // src/core/processor/worker/stop-transition.ts
8608
+ async function runStopTransition(dependencies) {
8609
+ await dependencies.finalizeStopSequence().then(() => dependencies.completeStop()).catch((error) => {
8610
+ return dependencies.recoverStopFailure().then(() => {
8611
+ throw error;
8612
+ });
8613
+ }).finally(() => {
8614
+ dependencies.clearStoppingFlag();
8615
+ });
8616
+ }
8617
+
8570
8618
  // src/core/processor/worker/timestamp-manager.ts
8571
8619
  var DEFAULT_FRAME_RATE = 30;
8572
8620
  var DEFAULT_KEY_FRAME_INTERVAL_SECONDS = 5;
@@ -8777,7 +8825,6 @@ function clampValue(value, min, max) {
8777
8825
  var WORKER_MESSAGE_TYPE_PROBE = "probe";
8778
8826
  var WORKER_MESSAGE_TYPE_AUDIO_CHUNK = "audioChunk";
8779
8827
  var WORKER_RESPONSE_TYPE_PROBE_RESULT = "probeResult";
8780
- var WORKER_RESPONSE_TYPE_DEBUG_LOG = "debugLog";
8781
8828
  var WORKER_AUDIO_SAMPLE_FORMAT_F32_PLANAR = "f32-planar";
8782
8829
 
8783
8830
  // src/core/processor/worker/visibility-tracker.ts
@@ -8900,6 +8947,8 @@ var ERROR_AUDIO_CHANNELS_INVALID = "Audio channels must be greater than zero";
8900
8947
  var ERROR_AUDIO_FRAMES_INVALID = "Audio frames must be greater than zero";
8901
8948
  var STEREO_CHANNEL_COUNT = 2;
8902
8949
  var AUDIO_SAMPLE_AVERAGE_SCALE = 0.5;
8950
+ var STOP_PENDING_WRITES_TIMEOUT_MILLISECONDS2 = 500;
8951
+ var MP4_FAST_START_DISABLED = false;
8903
8952
 
8904
8953
  class RecorderWorker {
8905
8954
  output = null;
@@ -8922,6 +8971,7 @@ class RecorderWorker {
8922
8971
  totalSize = 0;
8923
8972
  expectedAudioChannels = null;
8924
8973
  expectedAudioSampleRate = null;
8974
+ pendingWriteCount = 0;
8925
8975
  constructor() {
8926
8976
  this.bufferTracker = new BufferTracker({
8927
8977
  getBufferSize: () => this.totalSize,
@@ -8952,14 +9002,6 @@ class RecorderWorker {
8952
9002
  },
8953
9003
  getNowMilliseconds: () => performance.now()
8954
9004
  });
8955
- const sendDebugLog = (message, payload) => {
8956
- const response = {
8957
- type: WORKER_RESPONSE_TYPE_DEBUG_LOG,
8958
- message,
8959
- payload
8960
- };
8961
- self.postMessage(response);
8962
- };
8963
9005
  this.frameCompositor = new FrameCompositor({
8964
9006
  logger: {
8965
9007
  debug: (message, data) => logger.debug(message, data),
@@ -8968,7 +9010,9 @@ class RecorderWorker {
8968
9010
  },
8969
9011
  fetchResource: (input, init) => fetch(input, init),
8970
9012
  createImageBitmap: (image) => createImageBitmap(image),
8971
- sendDebugLog
9013
+ sendDebugLog: (_message, _payload) => {
9014
+ return;
9015
+ }
8972
9016
  });
8973
9017
  self.addEventListener("message", this.handleMessage);
8974
9018
  }
@@ -9102,6 +9146,7 @@ class RecorderWorker {
9102
9146
  this.audioState.reset();
9103
9147
  this.expectedAudioChannels = null;
9104
9148
  this.expectedAudioSampleRate = null;
9149
+ this.pendingWriteCount = 0;
9105
9150
  this.videoProcessingActive = false;
9106
9151
  this.frameCompositor.reset();
9107
9152
  this.recordingStartTime = 0;
@@ -9132,13 +9177,11 @@ class RecorderWorker {
9132
9177
  }
9133
9178
  createOutput() {
9134
9179
  const writable = new WritableStream({
9135
- write: (chunk) => {
9136
- this.sendChunk(chunk.data, chunk.position);
9137
- }
9180
+ write: (chunk) => this.handleOutputChunkWrite(chunk)
9138
9181
  });
9139
9182
  this.output = new Output({
9140
9183
  format: new Mp4OutputFormat({
9141
- fastStart: "fragmented"
9184
+ fastStart: MP4_FAST_START_DISABLED
9142
9185
  }),
9143
9186
  target: new StreamTarget(writable, {
9144
9187
  chunked: true,
@@ -9146,6 +9189,24 @@ class RecorderWorker {
9146
9189
  })
9147
9190
  });
9148
9191
  }
9192
+ decrementPendingWriteCount() {
9193
+ this.pendingWriteCount -= 1;
9194
+ if (this.pendingWriteCount < 0) {
9195
+ this.pendingWriteCount = 0;
9196
+ }
9197
+ }
9198
+ handleOutputChunkWrite(chunk) {
9199
+ this.pendingWriteCount += 1;
9200
+ const writeOperation = Promise.resolve().then(() => {
9201
+ this.sendChunk(chunk.data, chunk.position);
9202
+ });
9203
+ return writeOperation.then(() => {
9204
+ this.decrementPendingWriteCount();
9205
+ }, (error) => {
9206
+ this.decrementPendingWriteCount();
9207
+ throw error;
9208
+ });
9209
+ }
9149
9210
  createVideoSource(config) {
9150
9211
  const fps = this.timestampManager.getFrameRate();
9151
9212
  const keyFrameIntervalSeconds = config.keyFrameInterval;
@@ -9635,19 +9696,42 @@ class RecorderWorker {
9635
9696
  }
9636
9697
  this.sendStateChange("recording");
9637
9698
  }
9638
- async handleStop() {
9699
+ handleStop() {
9639
9700
  if (this.isStopping) {
9640
9701
  logger.debug("[RecorderWorker] handleStop ignored (stopping/finalized)");
9641
- return;
9702
+ return Promise.resolve();
9642
9703
  }
9643
9704
  if (this.isFinalized) {
9644
9705
  logger.debug("[RecorderWorker] handleStop ignored (stopping/finalized)");
9645
- return;
9706
+ return Promise.resolve();
9646
9707
  }
9647
9708
  this.isStopping = true;
9648
9709
  this.isFinalized = true;
9649
9710
  this.videoProcessingActive = false;
9650
9711
  this.audioState.setProcessingActive(false);
9712
+ return runStopTransition({
9713
+ finalizeStopSequence: () => this.finalizeStopSequence(),
9714
+ completeStop: () => this.completeStop(),
9715
+ recoverStopFailure: () => {
9716
+ if (this.isFinalized) {
9717
+ this.resetStopStateAfterFailure();
9718
+ }
9719
+ return this.cleanup().catch((cleanupError) => {
9720
+ logger.error("[RecorderWorker] Stop failure cleanup failed", {
9721
+ error: extractErrorMessage(cleanupError)
9722
+ });
9723
+ });
9724
+ },
9725
+ clearStoppingFlag: () => {
9726
+ this.isStopping = false;
9727
+ }
9728
+ });
9729
+ }
9730
+ async completeStop() {
9731
+ await this.cleanup();
9732
+ this.sendStateChange("stopped");
9733
+ }
9734
+ async finalizeStopSequence() {
9651
9735
  if (this.videoProcessor) {
9652
9736
  await this.videoProcessor.cancel();
9653
9737
  this.videoProcessor = null;
@@ -9657,13 +9741,17 @@ class RecorderWorker {
9657
9741
  this.audioProcessor = null;
9658
9742
  }
9659
9743
  if (this.output) {
9660
- await this.output.finalize().catch((error) => {
9661
- logger.warn("[RecorderWorker] finalize failed (ignored, already finalized?)", error);
9662
- });
9744
+ await this.output.finalize();
9663
9745
  }
9664
- await this.cleanup();
9665
- this.sendStateChange("stopped");
9666
- this.isStopping = false;
9746
+ await waitForPendingWritesToDrain({
9747
+ getPendingWriteCount: () => this.pendingWriteCount,
9748
+ timeoutMilliseconds: STOP_PENDING_WRITES_TIMEOUT_MILLISECONDS2
9749
+ });
9750
+ }
9751
+ resetStopStateAfterFailure() {
9752
+ this.isFinalized = false;
9753
+ this.videoProcessingActive = false;
9754
+ this.audioState.setProcessingActive(false);
9667
9755
  }
9668
9756
  handleToggleMute() {
9669
9757
  this.audioState.toggleMuted();
@@ -9779,6 +9867,7 @@ class RecorderWorker {
9779
9867
  this.isScreenCapture = false;
9780
9868
  this.expectedAudioChannels = null;
9781
9869
  this.expectedAudioSampleRate = null;
9870
+ this.pendingWriteCount = 0;
9782
9871
  this.visibilityTracker.reset(this.recordingStartTime, this.isScreenCapture);
9783
9872
  }
9784
9873
  setExpectedAudioFormat(sampleRate, numberOfChannels) {
@@ -9868,8 +9957,8 @@ class RecorderWorker {
9868
9957
  }
9869
9958
  }
9870
9959
  new RecorderWorker;
9871
- `],{type:`application/javascript`})}let e_=Dg({createBlob:$g,createObjectUrl:e=>URL.createObjectURL(e),revokeObjectUrl:e=>{URL.revokeObjectURL(e)}});function t_(){return e_.acquire()}function n_(){e_.release()}var r_=class{constructor(e={}){this.worker=null,this.hasWorkerUrlLease=!1,this.chunks=[],this.totalSize=0,this.isActive=!1,this.audioTrackClone=null,this.isMuted=!1,this.currentVideoTrack=null,this.isPaused=!1,this.overlayConfig=null,this.readyPromiseResolve=null;let t=e=>new Worker(e,{type:`classic`});e.createWorker&&(t=e.createWorker);let n=()=>typeof MediaStreamTrackProcessor<`u`;e.canUseMainThreadVideoProcessor&&(n=e.canUseMainThreadVideoProcessor);let r=e=>typeof MediaStreamTrackProcessor>`u`?null:new MediaStreamTrackProcessor({track:e}).readable;e.createVideoStreamFromTrack&&(r=e.createVideoStreamFromTrack),this.canUseMainThreadVideoProcessorFn=n,this.createVideoStreamFromTrackFn=r;let i=!!e.createWorker;this.workerProbeManager=new Qg({setTimeout:window.setTimeout.bind(window),clearTimeout:window.clearTimeout.bind(window),timeoutMilliseconds:2e3}),this.audioWorkletManager=new Lg({onChunk:e=>{if(!(this.isWorkerActive()&&this.worker))return;let t={type:`audioChunk`,data:e.data,frames:e.frames,numberOfChannels:e.numberOfChannels,sampleRate:e.sampleRate,timestamp:e.timestamp},n=[];e.data.buffer instanceof ArrayBuffer&&n.push(e.data.buffer),this.worker.postMessage(t,n)}});let a=e=>{let t=e.data;switch(t.type){case`ready`:$.debug(`[WorkerProcessor] Worker ready`),this.readyPromiseResolve&&=(this.readyPromiseResolve(),null);break;case Im:this.workerProbeManager.handleProbeResult(t);break;case`debugLog`:t.payload?$.debug(t.message,t.payload):$.debug(t.message);break;case`error`:$.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`:$.debug(`[WorkerProcessor] State changed:`,t.state),this.isPaused=t.state===`paused`;break;default:$.warn(`[WorkerProcessor] Unknown response type:`,t)}},o=e=>{if($.error(`[WorkerProcessor] Worker error event:`,{message:e.message,filename:e.filename,lineno:e.lineno,colno:e.colno,error:e.error}),this.onError){let t=e.message;t||=`Unknown worker error`,this.onError(Error(t))}},s=typeof Worker<`u`,c=!1;if(s&&(c=!0),i&&(c=!0),!c)throw $.error(`[WorkerProcessor] Web Workers are not supported`),Error(`Web Workers are not supported`);let l=t_();this.hasWorkerUrlLease=!0;try{this.worker=Jg({createWorker:t,workerUrl:l,onMessage:a,onError:o,logger:$})}catch(e){throw this.releaseWorkerUrlLease(),e}}getWorkerProbeResult(){let e=this.getWorkerOrThrow();return this.workerProbeManager.getProbeResult(e)}async startProcessing(e,t,n){this.getWorkerOrThrow(),this.ensureProcessingInactive(),this.resetProcessingState(n),this.stopAudioWorklet();let r=this.resolveRecordingFormat(t),i=await this.resolveAudioCodec(t),a=await this.resolveVideoCodec(t),o=Tg(e);$.debug(`[WorkerProcessor] Starting processing`,{isScreenCapture:o,fps:t.fps,codec:a,bitrate:t.bitrate});let s=this.buildWorkerTranscodeConfig(t,i,a,r),c=e.getVideoTracks(),l=e.getAudioTracks();$.debug(`[WorkerProcessor] Preparing to start processing`,{videoTracksCount:c.length,audioTracksCount:l.length,hasWorker:!!this.worker});let u=this.getVideoInputSelectorDependencies(),d=Rg(c,u),f=zg(l,u),p=await this.getWorkerProbeResult(),m=Bg(d,p,u),h=Hg(u),g=Vg(d);Wg(d,u),Gg(u),Ug(d,f,m.videoStream,u);let _=u.getViewportMetadata(),ee;_&&(ee={orientationAngle:_.orientationAngle,windowOrientation:_.windowOrientation});let{audioConfig:v,audioStream:y,shouldStartAudioWorklet:b}=await this.prepareAudioPipeline(f,p),x=this.buildOverlayConfigToSend(),S=Yg({videoTrack:m.videoTrack,videoStream:m.videoStream,audioStream:y,isMobileDevice:h,videoSettings:g,viewportMetadata:ee,audioConfig:v,workerConfig:s,overlayConfig:x}),te=Zg(m.videoStream,y,m.videoTrack);$.debug(`[WorkerProcessor] Posting message to worker`,{transferablesCount:te.length,messageType:S.type}),await this.postStartMessage(S,te,b)}getWorkerOrThrow(){if(!this.worker)throw Error(`Worker not initialized`);return this.worker}ensureProcessingInactive(){if(this.isActive)throw Error(`Processing already active`)}resetProcessingState(e){this.isActive=!0,this.isMuted=!1,this.isPaused=!1,this.chunks=[],this.totalSize=0,e?this.overlayConfig=e:this.overlayConfig=null}resolveRecordingFormat(e){let t=e.format;return t||=`mp4`,t}async resolveAudioCodec(e){let t=e.audioCodec;return t||=await mm(e.audioBitrate),t}async resolveVideoCodec(e){let t=e.codec;return t||=await pm(e.width,e.height,e.bitrate),t}buildWorkerTranscodeConfig(e,t,n,r){return{width:e.width,height:e.height,fps:e.fps,bitrate:Eg(e.bitrate),audioCodec:t,audioBitrate:e.audioBitrate,codec:n,keyFrameInterval:5,format:r,watermark:e.watermark}}async prepareAudioPipeline(e,t){if(!e)return{audioConfig:null,audioStream:null,shouldStartAudioWorklet:!1};if(this.canUseMainThreadVideoProcessorFn()&&t.hasAudioData){let t=this.createAudioStreamFromTrack(e);if(t)return{audioConfig:null,audioStream:t,shouldStartAudioWorklet:!1}}let n=await this.prepareAudioConfig(e);if(n)return{audioConfig:n,audioStream:null,shouldStartAudioWorklet:!0};throw this.createBrowserUnsupportedError()}buildOverlayConfigToSend(){if(this.overlayConfig)return this.overlayConfig}async postStartMessage(e,t,n){let r=this.getWorkerOrThrow(),i=new Promise(e=>{this.readyPromiseResolve=e});try{r.postMessage(e,t),$.debug(`[WorkerProcessor] Message posted successfully`),await i,$.debug(`[WorkerProcessor] Worker confirmed ready`),n&&await this.startAudioWorkletProcessing()}catch(e){throw $.error(`[WorkerProcessor] Failed to post message:`,e),this.readyPromiseResolve=null,this.stopAudioWorklet(),this.worker&&this.isActive&&this.worker.postMessage({type:`stop`}),this.isActive=!1,e}}pause(){this.worker&&this.isActive&&(this.worker.postMessage({type:`pause`}),this.setAudioWorkletPaused(!0))}resume(){this.isWorkerActive()&&this.worker&&(this.worker.postMessage({type:`resume`}),this.setAudioWorkletPaused(!1))}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`}),this.setAudioWorkletMuted(this.isMuted)}async switchVideoSource(e){if(!(this.isWorkerActive()&&this.worker))return $.debug(`[WorkerProcessor] Cannot switch source - worker not active`,{hasWorker:!!this.worker,isActive:this.isActive}),Promise.resolve();let t=e.getVideoTracks();if($.debug(`[WorkerProcessor] Switching video source`,{videoTracksCount:t.length}),t.length===0)return $.warn(`[WorkerProcessor] No video tracks in new stream`),Promise.resolve();let n=Tg(e);$.debug(`[WorkerProcessor] Source type detected`,{isScreenCapture:n,targetFps:30}),this.worker.postMessage({type:`updateFps`,fps:30});let r={type:`updateSourceType`,isScreenCapture:n};this.worker.postMessage(r);let i=this.getVideoInputSelectorDependencies(),a=Rg(t,i);if(!a)return $.warn(`[WorkerProcessor] Unable to prepare video track`),Promise.resolve();$.debug(`[WorkerProcessor] New video track details`,{trackId:a.id,trackKind:a.kind,trackReadyState:a.readyState});let o=Bg(a,await this.getWorkerProbeResult(),i),s=Xg(o.videoTrack,o.videoStream),c=Zg(o.videoStream,null,o.videoTrack);try{return $.debug(`[WorkerProcessor] Posting switch source message`),this.worker.postMessage(s,c),$.debug(`[WorkerProcessor] Switch source message posted`),new Promise(e=>{setTimeout(()=>{e()},0)})}catch(e){throw $.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=()=>{this.worker&&this.worker.removeEventListener(`message`,i)},i=i=>{let a=i.data;if(a.type===`stateChange`&&a.state===`stopped`){r(),clearTimeout(n),this.isActive=!1,this.stopAudioWorklet(),e(this.createBlobFromChunks());return}a.type===`error`&&(r(),clearTimeout(n),this.stopAudioWorklet(),t(Error(a.error)))};this.worker&&(this.worker.addEventListener(`message`,i),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.stopAudioWorklet(),this.isActive=!1,this.isPaused=!1,this.chunks=[],this.totalSize=0,Promise.resolve()}getBufferSize(){return this.totalSize}getMutedState(){return this.isMuted}updateTabVisibility(e,t){if(!(this.isWorkerActive()&&this.worker)){$.warn(`[WorkerProcessor] Cannot update visibility - worker not active`,{isActive:this.isActive,hasWorker:!!this.worker});return}$.debug(`[WorkerProcessor] Sending visibility update to worker`,{isHidden:e,timestamp:t,timestampSeconds:t/1e3});let n={type:`updateVisibility`,isHidden:e,timestamp:t};this.worker.postMessage(n)}updateSourceType(e){if(!(this.isWorkerActive()&&this.worker)){$.warn(`[WorkerProcessor] Cannot update source type - worker not active`,{isActive:this.isActive,hasWorker:!!this.worker});return}$.debug(`[WorkerProcessor] Sending source type update to worker`,{isScreenCapture:e});let t={type:`updateSourceType`,isScreenCapture:e};this.worker.postMessage(t)}async startAudioWorkletProcessing(){await this.audioWorkletManager.startProcessing()}stopAudioWorklet(){this.audioWorkletManager.stop()}setAudioWorkletMuted(e){this.audioWorkletManager.setMuted(e)}setAudioWorkletPaused(e){this.audioWorkletManager.setPaused(e)}prepareAudioConfig(e){return this.audioWorkletManager.prepareAudioConfig(e)}createAudioStreamFromTrack(e){return!e||typeof MediaStreamTrackProcessor>`u`?null:new MediaStreamTrackProcessor({track:e}).readable}createBrowserUnsupportedError(){return kt({resolutionStage:`feature-preflight`})}getVideoInputSelectorDependencies(){return{stopCurrentVideoTrack:()=>this.stopCurrentVideoTrack(),cloneVideoTrack:e=>this.cloneVideoTrack(e),cloneAudioTrack:e=>this.cloneAudioTrack(e),setCurrentVideoTrack:e=>{this.currentVideoTrack=e},canUseMainThreadVideoProcessor:()=>this.canUseMainThreadVideoProcessorFn(),createVideoStreamFromTrack:e=>this.createVideoStreamFromTrackFn(e),createBrowserUnsupportedError:()=>this.createBrowserUnsupportedError(),getViewportMetadata:()=>{if(typeof window>`u`)return null;let e=window.screen,t,n,r,i;return e&&(i=e.orientation),i?.type&&(t=i.type),i&&typeof i.angle==`number`&&(n=i.angle),typeof window.orientation==`number`&&(r=window.orientation),{innerWidth:window.innerWidth,innerHeight:window.innerHeight,orientation:t,orientationAngle:n,windowOrientation:r}},logger:{debug:(e,t)=>$.debug(e,t),warn:(e,t)=>$.warn(e,t)},isMobileDevice:()=>hm()}}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($.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 $.debug(`[WorkerProcessor] Video track cloned successfully:`,{id:t.id,kind:t.kind,readyState:t.readyState}),t}catch(e){$.error(`[WorkerProcessor] Failed to clone video track:`,e);let t=i(e);throw Error(`Failed to clone video track: ${t}`)}return $.warn(`[WorkerProcessor] Video track clone() not available, using original`),e}cloneAudioTrack(e){if($.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,$.debug(`[WorkerProcessor] Audio track cloned successfully:`,{id:t.id,kind:t.kind,readyState:t.readyState}),t}catch(e){$.error(`[WorkerProcessor] Failed to clone audio track:`,e);let t=i(e);throw Error(`Failed to clone audio track: ${t}`)}return $.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),this.releaseWorkerUrlLease(),this.stopAudioWorklet(),this.isActive=!1,this.isPaused=!1,this.chunks=[],this.totalSize=0}releaseWorkerUrlLease(){this.hasWorkerUrlLease&&=(n_(),!1)}},i_=class{constructor(e={}){this.currentVideoStream=null;let t=()=>new r_;e.workerProcessorFactory&&(t=e.workerProcessorFactory);try{this.workerProcessor=t(),$.debug(`[StreamProcessor] Using worker-based processing`)}catch(e){let t=i(e);throw Error(`Failed to initialize worker: ${t}`)}}async startProcessing(e,t,n){this.workerProcessor.setOnBufferUpdate((e,t)=>{$.debug(`[StreamProcessor] Buffer update:`,{size:e,formatted:t}),this.onBufferUpdate&&this.onBufferUpdate(e,t)}),this.workerProcessor.setOnError(e=>{$.error(`[StreamProcessor] Worker error:`,e),this.onError&&this.onError(e)}),this.currentVideoStream=e,await this.workerProcessor.startProcessing(e,t,n)}updateTabVisibility(e,t){this.workerProcessor.updateTabVisibility(e,t)}updateSourceType(e){this.workerProcessor.updateSourceType(e)}pause(){this.workerProcessor.pause()}resume(){this.workerProcessor.resume()}isPausedState(){return this.workerProcessor.isPausedState()}async finalize(){return $.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}setOnBufferUpdate(e){this.onBufferUpdate=e}setOnError(e){this.onError=e}async cancel(){await this.workerProcessor.cancel(),this.workerProcessor.cleanup(),this.currentVideoStream=null}};let a_=1e3,o_=`recording`,s_=`idle`;var c_=class{constructor(e,t){this.recordingState=s_,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.recordingStartTime=null,this.maxTimeRemaining=null,this.recordingSeconds=0,this.recordingIntervalId=null,this.pauseStartTime=null,this.totalPausedTime=0,this.streamProcessor=null,this.originalCameraStream=null,this.enableTabVisibilityOverlay=!1,this.streamManager=e,this.callbacks=t}setCountdownDuration(e){this.countdownDuration=e}setMaxRecordingTime(e){this.maxRecordingTime=e}setTabVisibilityOverlayConfig(e,t){this.enableTabVisibilityOverlay=e,this.tabVisibilityOverlayText=t}getRecordingState(){return this.recordingState}isPausedState(){return this.isPaused}getRecordingSeconds(){return this.recordingSeconds}getStreamProcessor(){return this.streamProcessor}updateSourceType(e){this.recordingState!==o_||!this.streamProcessor||this.streamProcessor.updateSourceType(e)}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=s_,this.cancelCountdown()}}startCountdown(){this.recordingState=`countdown`,this.countdownRemaining=Math.ceil(this.countdownDuration/a_),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)/a_)),this.callbacks.onCountdownUpdate(this.recordingState,this.countdownRemaining)},100),this.countdownTimeoutId=window.setTimeout(async()=>{await this.doStartRecording().catch(()=>{})},this.countdownDuration)}async doStartRecording(){$.debug(`[RecordingManager] doStartRecording called`),this.cancelCountdown(),this.recordingState=o_,this.callbacks.onStateChange(this.recordingState),this.resetRecordingState();let e=this.streamManager.getStream();if($.debug(`[RecordingManager] Current stream:`,{hasStream:!!e,audioTracks:e?.getAudioTracks().length||0,videoTracks:e?.getVideoTracks().length||0}),!e){$.warn(`[RecordingManager] No stream available`),this.handleError(Error(`No stream available for recording`)),this.recordingState=s_,this.callbacks.onStateChange(this.recordingState);return}this.originalCameraStream=e,$.debug(`[RecordingManager] Creating stream processor`),this.streamProcessor=new i_,$.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=s_,this.callbacks.onStateChange(this.recordingState);return}if(!t.config){this.handleError(Error(`Failed to get recording config`)),this.recordingState=s_,this.callbacks.onStateChange(this.recordingState);return}$.debug(`[RecordingManager] Starting recording with stream manager`);let n=await this.streamManager.startRecording(this.streamProcessor,t.config,this.enableTabVisibilityOverlay,this.tabVisibilityOverlayText).then(()=>($.info(`[RecordingManager] Recording started successfully`),null)).catch(e=>($.error(`[RecordingManager] Error starting recording:`,e),e));if(n){this.handleError(n),this.recordingState=s_,this.callbacks.onStateChange(this.recordingState);return}this.startRecordingTimer(),this.recordingStartTime=Date.now(),this.maxRecordingTime&&this.maxRecordingTime>0&&(this.maxTimeRemaining=this.maxRecordingTime,this.startMaxTimeTimer())}async stopRecording(){$.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(),$.debug(`[RecordingManager] Stopping recording in stream manager`);let e=(await this.streamManager.stopRecording()).blob;return $.info(`[RecordingManager] Recording stopped, blob size:`,e.size),this.recordingState=s_,this.callbacks.onStateChange(this.recordingState),this.recordingSeconds=0,this.streamProcessor=null,this.callbacks.onRecordingComplete(e),e}catch(e){throw this.handleError(e),this.recordingState=s_,this.callbacks.onStateChange(this.recordingState),e}}pauseRecording(){if(!(this.recordingState!==o_||this.isPaused)&&(this.streamManager.pauseRecording(),this.isPaused=!0,this.clearTimer(this.recordingIntervalId,clearInterval),this.recordingIntervalId=null,this.pauseStartTime=Date.now(),this.maxTimeTimer!==null&&this.recordingStartTime!==null&&this.maxRecordingTime!==null)){let e=Date.now()-this.recordingStartTime-this.totalPausedTime;this.maxTimeRemaining=Math.max(0,this.maxRecordingTime-e),this.clearTimer(this.maxTimeTimer,clearTimeout),this.maxTimeTimer=null}}resumeRecording(){this.recordingState!==o_||!this.isPaused||(this.streamManager.resumeRecording(),this.isPaused=!1,this.updatePausedDuration(),this.startRecordingTimer(),this.maxTimeRemaining!==null&&this.maxTimeRemaining>0&&this.startMaxTimeTimer())}cancelCountdown(){this.clearTimer(this.countdownTimeoutId,clearTimeout),this.countdownTimeoutId=null,this.clearTimer(this.countdownIntervalId,clearInterval),this.countdownIntervalId=null,this.recordingState=s_,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,this.recordingStartTime=null,this.maxTimeRemaining=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(){if(this.recordingIntervalId!==null)return;let e=Kh(this.recordingSeconds);this.callbacks.onTimerUpdate(e),this.recordingIntervalId=window.setInterval(()=>{this.recordingSeconds+=1;let e=Kh(this.recordingSeconds);this.callbacks.onTimerUpdate(e)},1e3)}startMaxTimeTimer(){this.maxTimeRemaining===null||this.maxTimeRemaining<=0||(this.clearTimer(this.maxTimeTimer,clearTimeout),this.maxTimeTimer=window.setTimeout(async()=>{this.recordingState===o_&&!this.isPaused&&await this.stopRecording()},this.maxTimeRemaining))}clearTimer(e,t){e!==null&&t(e)}handleError(e){let t=e instanceof Error?e:Error(i(e));this.callbacks.onError(t)}},l_=class{constructor(e){this.client=null,this.createTelemetryClient=e.createTelemetryClient}initialize(e,t){typeof e==`string`&&e.length>0&&typeof t==`string`&&t.length>0&&(this.client=this.createTelemetryClient(e,t))}sendEvent(e,t,n){if(!this.client)return;let r={name:e};t&&(r={...r,properties:t}),n&&(r={...r,error:n}),this.client.triggerTelemetryEvent(r)}async executeAction(e){e.requestedEvent&&this.sendEvent(e.requestedEvent,e.properties);let t=null;if(await e.action().catch(e=>{t=e}),t)throw this.sendEvent(e.failedEvent,e.properties,t),t;this.sendEvent(e.succeededEvent,e.properties)}async executeActionWithResult(e){e.requestedEvent&&this.sendEvent(e.requestedEvent,e.properties);let t=null,n=null;if(await e.action().then(e=>{n=e}).catch(e=>{t=e}),t)throw this.sendEvent(e.failedEvent,e.properties,t),t;if(this.sendEvent(e.succeededEvent,e.properties),n===null)throw Error(`Telemetry action failed to return result`);return n}},u_=class{constructor(){this.metadataById=new Map}getMetadata(e){return this.metadataById.get(e)}setMetadata(e,t){let n=new Map(this.metadataById);n.set(e,t),this.metadataById=n}clearMetadata(e){let t=new Map(this.metadataById);t.delete(e),this.metadataById=t}};let d_=`[RecorderController]`;var f_=class{constructor(e={}){this.uploadService=null,this.uploadQueueManager=null,this.isInitialized=!1,this.isDemo=!1,this.enableTabVisibilityOverlay=!1,this.callbacks=e,this.streamManager=new Xh,this.configManager=new bm,this.storageManager=new sh,this.deviceManager=new xm(this.streamManager,e.device),this.audioLevelAnalyzer=new o,this.uploadService=new lg,this.uploadCallbacks=xg(e),this.telemetryManager=new l_({createTelemetryClient:sg}),this.uploadMetadataManager=new u_;let t=Cg(e,{stopAudioTracking:()=>this.audioLevelAnalyzer.stopTracking(),getConfig:()=>this.configManager.getConfig()});this.recordingManager=new c_(this.streamManager,t);let n=wg(e,{isRecording:()=>this.isRecording(),updateSourceType:e=>{this.recordingManager.updateSourceType(e)},getSelectedCameraDeviceId:()=>this.deviceManager.getSelectedCameraDeviceId(),getSelectedMicDeviceId:()=>this.deviceManager.getSelectedMicDeviceId()});this.sourceSwitchManager=new zh(this.streamManager,n);let r=e.stream;r&&(this.streamManager.on(`streamstart`,({stream:e})=>{$.debug(`${d_} streamstart event received, calling callback`),r.onStreamStart&&r.onStreamStart(e)}),this.streamManager.on(`streamstop`,()=>{$.debug(`${d_} streamstop event received, calling callback`),r.onStreamStop&&r.onStreamStop()}),this.streamManager.on(`error`,({error:e})=>{$.error(`${d_} stream error event received, calling callback`,e),this.telemetryManager.sendEvent(`stream.error`,{sourceType:this.getCurrentSourceType()},e),r.onError&&r.onError(e)}))}async initialize(e){if(this.isInitialized)return;await this.validateRecorderSupport();let t=!1;typeof e.demo==`boolean`&&(t=e.demo),this.isDemo=t;let n=null;typeof e.apiKey==`string`&&e.apiKey.length>0&&(n=e.apiKey);let r=null;typeof e.backendUrl==`string`&&e.backendUrl.length>0&&(r=e.backendUrl),this.telemetryManager.initialize(n,r),await this.telemetryManager.executeAction({requestedEvent:`sdk.init.started`,succeededEvent:`sdk.init.succeeded`,failedEvent:`sdk.init.failed`,action:async()=>{await this.initializeConfig(n,r),this.applyRecordingConfig(e),await this.initializeStorage(),this.isInitialized=!0}})}async startStream(){let e=this.getCurrentSourceType();await this.telemetryManager.executeAction({succeededEvent:`preview.start.succeeded`,failedEvent:`preview.start.failed`,action:async()=>{$.debug(`${d_} startStream called`),await this.streamManager.startStream(),$.debug(`${d_} startStream completed`)},properties:{sourceType:e}})}async stopStream(){await this.streamManager.stopStream()}switchVideoDevice(e){return this.streamManager.switchVideoDevice(e)}switchAudioDevice(e){return this.streamManager.switchAudioDevice(e)}async startRecording(){await this.ensureConfigReady();let e=this.getCurrentSourceType();await this.telemetryManager.executeAction({requestedEvent:`recording.start.requested`,succeededEvent:`recording.start.succeeded`,failedEvent:`recording.start.failed`,action:async()=>{await this.recordingManager.startRecording()},properties:{sourceType:e}})}async stopRecording(){let e=this.getCurrentSourceType();return await this.telemetryManager.executeActionWithResult({requestedEvent:`recording.stop.requested`,succeededEvent:`recording.stop.succeeded`,failedEvent:`recording.stop.failed`,action:async()=>{let e=await this.recordingManager.stopRecording();return await this.sourceSwitchManager.handleRecordingStop().catch(()=>{throw Error(`Source switch cleanup failed`)}),this.streamManager.stopStream(),e},properties:{sourceType:e}})}getTabVisibilityOverlayConfig(){return{enabled:this.enableTabVisibilityOverlay,text:this.tabVisibilityOverlayText}}pauseRecording(){this.recordingManager.pauseRecording()}resumeRecording(){this.recordingManager.resumeRecording()}async switchSource(e){await this.telemetryManager.executeAction({requestedEvent:`source.switch.requested`,succeededEvent:`source.switch.succeeded`,failedEvent:`source.switch.failed`,action:async()=>{await this.sourceSwitchManager.toggleSource()},properties:{sourceType:e}})}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 Sm(e),a=`recording-${Date.now()}.mp4`,o=this.getCurrentSourceType(),s;Object.keys(r).length>0&&(s=r),this.telemetryManager.sendEvent(`upload.started`,{filename:a,duration:i,sourceType:o});let c=await this.uploadQueueManager.queueUpload({blob:e,apiKey:t,backendUrl:n,filename:a,duration:i,metadata:void 0,userMetadata:s});this.uploadMetadataManager.setMetadata(c,{filename:a,duration:i,sourceType:o})}getStream(){return this.streamManager.getStream()}isConfigReady(){return this.configManager.isConfigReady()}async ensureConfigReady(){this.isDemo||await this.configManager.fetchConfig()}cleanup(){this.storageManager.destroy(),this.recordingManager.cleanup(),this.audioLevelAnalyzer.stopTracking(),this.sourceSwitchManager.cleanup()}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()}async initializeConfig(e,t){let n=!0;e===null&&(n=!1),t===null&&(n=!1),n&&e!==null&&t!==null&&await this.configManager.initialize(e,t)}applyRecordingConfig(e){e.countdownDuration!==void 0&&this.recordingManager.setCountdownDuration(e.countdownDuration),e.maxRecordingTime!==void 0&&this.recordingManager.setMaxRecordingTime(e.maxRecordingTime),e.enableTabVisibilityOverlay!==void 0&&(this.enableTabVisibilityOverlay=e.enableTabVisibilityOverlay),e.tabVisibilityOverlayText!==void 0&&(this.tabVisibilityOverlayText=e.tabVisibilityOverlayText),this.recordingManager.setTabVisibilityOverlayConfig(this.enableTabVisibilityOverlay,this.tabVisibilityOverlayText)}async initializeStorage(){let e=Sg(this.callbacks);await this.storageManager.initialize(e);let t=this.storageManager.getStorageService();t&&this.uploadService&&(this.uploadQueueManager=new cg(t,this.uploadService),this.uploadQueueManager.setCallbacks({onUploadProgress:(e,t)=>{this.uploadCallbacks.onProgress(t)},onUploadComplete:(e,t)=>{this.uploadCallbacks.onSuccess(t);let n=this.uploadMetadataManager.getMetadata(e);n&&(this.telemetryManager.sendEvent(`upload.succeeded`,{filename:n.filename,duration:n.duration,sourceType:n.sourceType,recordingId:t.id}),this.uploadMetadataManager.clearMetadata(e))},onUploadError:(e,t)=>{this.uploadCallbacks.onError(t);let n=this.uploadMetadataManager.getMetadata(e);n&&(this.telemetryManager.sendEvent(`upload.failed`,{filename:n.filename,duration:n.duration,sourceType:n.sourceType},t),this.uploadMetadataManager.clearMetadata(e))}}))}async validateRecorderSupport(){At();let e=await $m({requiresAudio:!1,requiresWatermark:!1});if(!e.isSupported)throw kt({missingCapabilities:e.missing,resolutionStage:`feature-preflight`})}};let p_=/<a\s+href="(?<href>[^"]+)"(?:\s+target="(?<target>[^"]+)")?\s*>(?<text>[^<]+)<\/a>/,m_=/^[a-zA-Z][a-zA-Z\d+\-.]*:/,h_=`{version}`;function g_(e,t){return e?e.toLowerCase().includes(t):!1}function __(e){let t=e.trim();if(!t)return null;let n=t.toLowerCase();return!m_.test(n)||n.startsWith(`http:`)||n.startsWith(`https:`)?t:null}function v_(e,t,n,r){return e===`browser.unsupported`?r.browserUnsupportedDynamic?y_(r.browserUnsupportedDynamic,t,n):g_(t,`safari`)?r.browserUnsupportedSafari:g_(t,`firefox`)?r.browserUnsupportedFirefox:r.browserUnsupported:r.browserUnsupported}function y_(e,t,n){let r=`This browser`;t&&t.trim().length>0&&(r=t);let i=e.replace(`{browser}`,r);return n&&n.trim().length>0&&n?(i=i.replace(h_,n),i):(i=i.replace(` ({version})`,``),i=i.replace(h_,``),i)}function b_(e){let t=p_.exec(e);if(!t?.groups)return{prefix:e,linkText:null,linkHref:null,linkTarget:null,suffix:``};let n=t.index,r=n+t[0].length,i=e.slice(0,n),a=e.slice(r),o=__(t.groups.href);if(!o)return{prefix:i+t.groups.text+a,linkText:null,linkHref:null,linkTarget:null,suffix:``};let s=null;return t.groups.target&&(s=t.groups.target),{prefix:i,linkText:t.groups.text,linkHref:o,linkTarget:s,suffix:a}}function x_(){let e=Ot(),t=null;e.name.length>0&&(t=e.name);let n=null;return e.version.length>0&&(n=e.version),{browserName:t,browserVersion:n}}function S_(e){let t=t=>{if(!(`code`in t))return;let n=t;if(n.code!==`browser.unsupported`)return;let r=x_(),i=r.browserName;n.browserName&&n.browserName.length>0&&(i=n.browserName);let a=r.browserVersion;n.browserVersion&&n.browserVersion.length>0&&(a=n.browserVersion),e.updateState({errorCode:`browser.unsupported`,browserName:i,browserVersion:a})};return{recording:{onStateChange:t=>{e.updateState({recordingState:t}),t===`idle`&&(e.isProcessingBlob=!1)},onCountdownUpdate:(t,n)=>{e.updateState({recordingState:t,countdown:n})},onTimerUpdate:t=>{e.updateState({timer:t})},onError:n=>{t(n),e.updateState({error:i(n)})},onRecordingComplete:t=>{e.updateState({countdown:null}),e.processRecordingBlob(t).catch(t=>{e.updateState({error:i(t)})})},onClearUploadStatus:()=>{e.updateState({uploadProgress:null})},onStopAudioTracking:()=>{},onGetConfig:()=>{if(!e.controller)throw Error(`Controller not initialized`);return e.isDemo?Promise.resolve(Vt(`mp4`)):e.controller.getConfig()}},sourceSwitch:{onSourceChange:e=>Promise.resolve(),onPreviewUpdate:t=>(e.updateState({stream:t}),Promise.resolve()),onError:n=>{t(n),e.updateState({error:i(n)})},onTransitionStart:t=>{e.updateState({transitionMessage:t})},onTransitionEnd:()=>{e.updateState({transitionMessage:null})}},storage:{onUploadProgress:()=>{},onUploadComplete:()=>{},onUploadError:()=>{}},onStorageCleanupError:t=>{e.updateState({error:t})}}}function C_(e,t){let n=(e=>e===``||e===`default`?null:e)(t);return e.setCameraDevice(n),e.switchVideoDevice(n)}function w_(e,t){let n=(e=>e===``||e===`default`?null:e)(t);return e.setMicDevice(n),e.switchAudioDevice(n)}async function T_(e,t=`camera`){e.isActive()||await e.startStream(),t!==e.getCurrentSourceType()&&await e.switchSource(t),await e.startRecording()}async function E_(e,t,n,r){return await e.stopRecording()}function D_(e){e.pauseRecording()}function O_(e){e.resumeRecording()}async function k_(e,t){await e.switchSource(t)}let A_=`camera`,j_=`screen`,M_=`recording`,N_=`browser.unsupported`,P_=[.8,1.2,.9];function F_(e,t){let{uploadProgress:n,uploadingLabel:r}=e,{overlay:i,fill:a,text:o}=t;if(!i)return;if(n===null){i.style.display=`none`;return}i.style.display=`block`;let s=Math.round(n*100);a&&(a.style.width=`${s}%`),o&&(o.textContent=`${r} ${s}%`)}function I_(e,t){let{transitionMessage:n}=e,{overlay:r,message:i}=t;if(r){if(!n){r.classList.remove(`vidtreo-active`);return}r.classList.add(`vidtreo-active`),i&&(i.textContent=n)}}function L_(e,t){e.textContent=``;let n=document.createTextNode(t.prefix);if(e.append(n),t.linkText&&t.linkHref){let n=document.createElement(`a`),r=t.linkTarget;n.href=t.linkHref,r&&(n.target=r),r===`_blank`&&(n.rel=`noopener noreferrer`),n.textContent=t.linkText,e.append(n)}let r=document.createTextNode(t.suffix);e.append(r)}function R_(e){let{stream:t,transitionMessage:n,isVideoLoaded:r}=e;return{showPreviewSkeleton:!!t&&!r&&!n,showVideoPreview:!!t}}function z_(e,t){let{previewSkeleton:n,videoPreview:r}=t;n&&(e.showPreviewSkeleton?n.style.display=`block`:n.style.display=`none`),r&&(e.showVideoPreview?r.style.display=`block`:r.style.display=`none`)}function B_(e,t,n){let{videoPreview:r}=t,{onVideoLoaded:a,onError:o,startAudioAnalysis:s,stopAudioAnalysis:c}=n;if(r){if(!e){r.srcObject=null,c();return}r.srcObject=e,r.onloadeddata=()=>{a()},r.play().catch(e=>o(i(e))),s(e)}}function V_(e){return{startCameraArea:e.querySelector(`#startCameraArea`),cameraIcon:e.querySelector(`#startCameraArea .vidtreo-camera-icon`),cameraText:e.querySelector(`#startCameraArea .vidtreo-camera-text`),cameraHint:e.querySelector(`#startCameraArea .vidtreo-camera-hint`),previewSkeleton:e.querySelector(`#previewSkeleton`),previewSkeletonText:e.querySelector(`#previewSkeleton .vidtreo-skeleton-text`),videoPreview:e.querySelector(`#videoPreview`),countdownOverlay:e.querySelector(`#countdownOverlay`),countdownNumber:e.querySelector(`#countdownNumber`),recordingTimerRow:e.querySelector(`#recordingTimerRow`),recordingTimer:e.querySelector(`#recordingTimer`),recIndicatorTop:e.querySelector(`#recIndicatorTop`),audioLevelBars:e.querySelector(`#audioLevelBars`)}}function H_(e,t,n){if(e.stream)return{shouldShow:!1,iconClassName:``,browserErrorContent:null,textContent:null,hintText:null};let r=e.errorCode===N_,i=`ph-fill ph-camera`;r&&(i=`ph-fill ph-warning-circle`);let a=null,o=null;r&&(a=b_(n)),r||(o=t.initializingCamera);let s=null;return r||(s=t.grantPermissions),{shouldShow:!0,iconClassName:i,browserErrorContent:a,textContent:o,hintText:s}}function U_(e,t){let n=!1;return e&&(n=!0),{shouldShow:n,text:t.switchingDevice}}function W_(e,t,n){let r=!1;return e===`countdown`&&t!==null&&(r=!0),{shouldShow:r,countdown:t,text:n.recordingStartsIn}}function G_(e,t){return{shouldShow:e,text:t.rec}}function K_(e,t){return{shouldShow:e,timer:t}}function q_(e){return{shouldShow:e}}function J_(e,t){let{state:n,isVideoLoaded:r,isRecording:i,translations:a}=e;Y_(H_(n,a,v_(n.errorCode,n.browserName,n.browserVersion,{browserUnsupported:a.browserUnsupported,browserUnsupportedDynamic:a.browserUnsupportedDynamic,browserUnsupportedSafari:a.browserUnsupportedSafari,browserUnsupportedFirefox:a.browserUnsupportedFirefox})),t),X_(U_(n.transitionMessage,a),t),z_(R_({stream:n.stream,transitionMessage:n.transitionMessage,isVideoLoaded:r}),{previewSkeleton:t.previewSkeleton,videoPreview:t.videoPreview}),Z_(W_(n.recordingState,n.countdown,a),t),Q_(G_(i,a),t),$_(K_(i,n.timer),t),ev(q_(i),t)}function Y_(e,t){let{startCameraArea:n,cameraIcon:r,cameraText:i,cameraHint:a}=t;if(n){if(!e.shouldShow){n.style.display=`none`;return}n.style.display=`block`,r&&(r.innerHTML=`<i class="${e.iconClassName}" style="font-size: 48px;"></i>`),i&&(e.browserErrorContent&&L_(i,e.browserErrorContent),e.textContent&&(i.textContent=e.textContent)),a&&(e.hintText?(a.textContent=e.hintText,a.style.display=`block`):a.style.display=`none`)}}function X_(e,t){let{previewSkeleton:n,previewSkeletonText:r}=t;n&&(e.shouldShow?n.style.display=`block`:n.style.display=`none`,r&&(r.textContent=e.text))}function Z_(e,t){let{countdownOverlay:n,countdownNumber:r}=t;n&&(e.shouldShow?n.classList.add(`vidtreo-active`):n.classList.remove(`vidtreo-active`),r&&e.countdown!==null&&(r.textContent=e.countdown.toString()))}function Q_(e,t){let{recIndicatorTop:n}=t;n&&(e.shouldShow?n.style.display=`block`:n.style.display=`none`)}function $_(e,t){let{recordingTimerRow:n,recordingTimer:r}=t;n&&(e.shouldShow?n.style.display=`flex`:n.style.display=`none`,r&&(r.textContent=e.timer))}function ev(e,t){let{audioLevelBars:n}=t;n&&(e.shouldShow?n.style.display=`flex`:n.style.display=`none`)}let tv=`inline-flex`;function nv(e){let{stream:t,buttonVisibility:n,currentSourceType:r,isMuted:i,recordingState:a,buttonTranslations:o}=e,s=!!t,c=a===`idle`&&s,l=!1;(n.showPauseButton||n.showResumeButton)&&(l=!0);let u=o.pause,d=`ph-fill ph-pause`;n.showResumeButton&&(u=o.resume,d=`ph-fill ph-play`);let f=o.mute,p=`ph-fill ph-microphone`;i&&(f=o.unmute,p=`ph-fill ph-microphone-slash`);let m=`ph-fill ph-monitor`;r!==A_&&(m=`ph-fill ph-camera`);let h=!1;return n.showDownloadButton&&(h=!0),{showRecordingControls:s,showSettingsButton:n.showSettingsButton,showRecordButton:c,showMuteButton:n.showMuteButton,showPauseButton:l,showStopButton:n.showStopButton,showSwitchSourceButton:n.showSwitchSourceButton,showDownloadButton:h,pauseTitle:u,pauseIconClassName:d,muteTitle:f,muteIconClassName:p,switchSourceIconClassName:m,isMuted:i,settingsTitle:o.settings,switchSourceTitle:o.switchSource,downloadTitle:o.download}}function rv(e){return{recordingControls:e.querySelector(`#recordingControls`),settingsButton:e.querySelector(`#btnSettings`),recordButton:e.querySelector(`#btnRecord`),muteButton:e.querySelector(`#btnMute`),muteIcon:e.querySelector(`#iconMute`),pauseButton:e.querySelector(`#btnPause`),pauseIcon:e.querySelector(`#iconPause`),stopButton:e.querySelector(`#btnStop`),switchSourceButton:e.querySelector(`#btnSwitchSource`),switchSourceIcon:e.querySelector(`#iconSwitchSource`),downloadButton:e.querySelector(`#btnDownload`)}}function iv(e,t){let{recordingControls:n,settingsButton:r,recordButton:i,muteButton:a,muteIcon:o,pauseButton:s,pauseIcon:c,stopButton:l,switchSourceButton:u,switchSourceIcon:d,downloadButton:f}=t;ov(n,e),sv(r,e),cv(i,e),lv(a,e),uv(o,e),dv(s,e),fv(c,e),pv(l,e),mv(u,e),hv(d,e),gv(f,e)}function av(e,t,n){e&&(t?e.style.display=n:e.style.display=`none`)}function ov(e,t){av(e,t.showRecordingControls,`block`)}function sv(e,t){av(e,t.showSettingsButton,tv),e&&(e.title=t.settingsTitle)}function cv(e,t){av(e,t.showRecordButton,tv)}function lv(e,t){av(e,t.showMuteButton,tv),e&&(e.title=t.muteTitle,e.classList.toggle(`vidtreo-muted`,t.isMuted))}function uv(e,t){e&&(e.className=t.muteIconClassName)}function dv(e,t){av(e,t.showPauseButton,tv),e&&(e.title=t.pauseTitle)}function fv(e,t){e&&(e.className=t.pauseIconClassName)}function pv(e,t){av(e,t.showStopButton,tv)}function mv(e,t){av(e,t.showSwitchSourceButton,tv),e&&(e.title=t.switchSourceTitle)}function hv(e,t){e&&(e.className=t.switchSourceIconClassName)}function gv(e,t){av(e,t.showDownloadButton,tv),e&&(e.title=t.downloadTitle)}function _v(e){let{stream:t,showSettings:n}=e,r=!1;return t&&n&&(r=!0),{shouldShow:r}}function vv(e,t,n){if(t){if(!e.shouldShow){t.classList.remove(`vidtreo-active`);return}t.classList.add(`vidtreo-active`),n()}}function yv(e){return e.toggleMute(),e.getIsMuted()}function bv(e){if(!e)return;let t=URL.createObjectURL(e),n=document.createElement(`a`);n.href=t,n.download=`recording-${Date.now()}.mp4`,document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(t)}let xv={en:{initializingCamera:`Initializing camera...`,grantPermissions:`Grant camera and microphone permissions when prompted`,browserUnsupported:`This browser is not supported`,browserUnsupportedDynamic:`{browser} ({version}) is not supported, please use <a href="https://www.google.com/chrome/" target="_blank">Chrome</a>`,browserUnsupportedSafari:`Safari is not supported, please use <a href="https://www.google.com/chrome/" target="_blank">Chrome</a>`,browserUnsupportedFirefox:`Firefox is not supported, please use <a href="https://www.google.com/chrome/" target="_blank">Chrome</a>`,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...`,finishing:`Finishing...`,uploading:`Uploading...`,switchingCamera:`Switching camera...`,switchingMicrophone:`Switching microphone...`,failedToStartCamera:`Failed to start camera`,userInAnotherTab:`User in another tab`,download:`Download`,nativeCameraSelectVideo:`Select Video from Gallery`,nativeCameraRecordVideo:`Record with Camera`,errorTitle:`Configuration Error`,errorGeneric:`An error occurred while loading the configuration`,mobileOpenCamera:`Open Camera`,mobileOpenCameraTitle:`Record a Video`,mobileOpenCameraDescription:`Tap the button below to start recording`,mobileCloseCamera:`Close`,mobilePermissionDenied:`Camera Access Denied`,mobilePermissionDeniedDescription:`Please allow camera access in your browser settings to record video.`},es:{initializingCamera:`Inicializando cámara...`,grantPermissions:`Otorga permisos de cámara y micrófono cuando se solicite`,browserUnsupported:`Este navegador no es compatible`,browserUnsupportedDynamic:`{browser} ({version}) no es compatible, por favor usa <a href="https://www.google.com/chrome/" target="_blank">Chrome</a>`,browserUnsupportedSafari:`Safari no es compatible, usa <a href="https://www.google.com/chrome/" target="_blank">Chrome</a>`,browserUnsupportedFirefox:`Firefox no es compatible, usa <a href="https://www.google.com/chrome/" target="_blank">Chrome</a>`,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...`,finishing:`Finalizando...`,uploading:`Subiendo...`,switchingCamera:`Cambiando cámara...`,switchingMicrophone:`Cambiando micrófono...`,failedToStartCamera:`Error al iniciar la cámara`,userInAnotherTab:`Usuario en otra pestaña`,download:`Descargar`,nativeCameraSelectVideo:`Seleccionar Video de la Galería`,nativeCameraRecordVideo:`Grabar con Cámara`,errorTitle:`Error de Configuración`,errorGeneric:`Ocurrió un error al cargar la configuración`,mobileOpenCamera:`Abrir Cámara`,mobileOpenCameraTitle:`Grabar un Video`,mobileOpenCameraDescription:`Toca el botón para comenzar a grabar`,mobileCloseCamera:`Cerrar`,mobilePermissionDenied:`Acceso a Cámara Denegado`,mobilePermissionDeniedDescription:`Por favor permite el acceso a la cámara en la configuración de tu navegador para grabar video.`}};var Sv=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]:(xv[this.lang]||xv.en)[e]}getAll(){return{...xv[this.lang]||xv.en,...this.customTexts}}};let Cv=new Map;function wv(e){e.style.position=`fixed`,e.style.top=`0`,e.style.left=`0`,e.style.width=`100vw`,e.style.height=`100vh`,e.style.height=`100dvh`,e.style.zIndex=`9999`,e.style.pointerEvents=`none`}function Tv(e){e.style.pointerEvents=`auto`}function Ev(e){e.style.pointerEvents=`none`}var Dv=class{constructor(e=`vidtreo-portal-root`){this.portalContainer=null,this.contentWrapper=null,this.isRegistered=!1,this.containerId=e,this.instanceId=`portal-${Date.now()}-${Math.random().toString(36).slice(2,9)}`}get container(){return this.contentWrapper}get isActive(){return this.contentWrapper!==null&&this.portalContainer!==null}open(){let e=document.getElementById(this.containerId);return e||(e=document.createElement(`div`),e.id=this.containerId,wv(e),document.body.appendChild(e)),this.portalContainer=e,this.contentWrapper=document.createElement(`div`),this.contentWrapper.setAttribute(`data-portal-instance`,this.instanceId),this.contentWrapper.style.width=`100%`,this.contentWrapper.style.height=`100%`,this.portalContainer.appendChild(this.contentWrapper),this.registerInstance(),Tv(e),this.contentWrapper}render(e){this.contentWrapper&&(this.contentWrapper.innerHTML=e)}querySelector(e){return this.contentWrapper?this.contentWrapper.querySelector(e):null}close(){this.contentWrapper&&=(this.contentWrapper.innerHTML=``,this.contentWrapper.remove(),null),this.unregisterInstance(),this.updatePortalContainerState()}destroy(){this.close(),this.portalContainer=null}registerInstance(){if(this.isRegistered)return;let e=Cv.get(this.containerId);e||(e=new Set,Cv.set(this.containerId,e)),e.add(this),this.isRegistered=!0}unregisterInstance(){if(!this.isRegistered)return;let e=Cv.get(this.containerId);e&&(e.delete(this),e.size===0&&Cv.delete(this.containerId)),this.isRegistered=!1}updatePortalContainerState(){if(!this.portalContainer)return;let e=Cv.get(this.containerId);e&&e.size>0?Tv(this.portalContainer):(Ev(this.portalContainer),this.portalContainer.childNodes.length===0&&this.portalContainer.remove())}},Ov=class{constructor(e){this.state={isModalOpen:!1,permissionRequested:!1,prevUploading:!1},this.escapeHandler=null,this.initCheckInterval=null,this.callbacks=e,this.portalManager=new Dv}get canCloseModal(){let{recordingState:e}=this.callbacks.getState();return!(e===`recording`||e===`countdown`)}get isModalOpen(){return this.state.isModalOpen}get portal(){return this.portalManager}openModal(){this.state.isModalOpen=!0,this.state.permissionRequested=!1,this.portalManager.open(),document.body.style.overflow=`hidden`,this.setupEscapeHandler(),this.callbacks.renderMobile(),this.requestCameraPreview()}closeModal(){this.canCloseModal&&(this.callbacks.stopPreview(),this.state.isModalOpen=!1,this.state.permissionRequested=!1,document.body.style.overflow=``,this.removeEscapeHandler(),this.portalManager.close(),this.callbacks.renderMobile())}checkUploadCompletion(e){let t=this.state.prevUploading,n=e!==null;this.state.prevUploading=n,t&&!n&&this.state.isModalOpen&&this.closeModal()}requestCameraPreview(){if(this.state.permissionRequested)return;let e=()=>{this.callbacks.isInitialized()?(this.state.permissionRequested=!0,this.callbacks.startPreview().catch(()=>{})):this.initCheckInterval=setTimeout(e,100)};e()}setupEscapeHandler(){this.escapeHandler=e=>{e.key===`Escape`&&this.canCloseModal&&this.closeModal()},document.addEventListener(`keydown`,this.escapeHandler)}removeEscapeHandler(){this.escapeHandler&&=(document.removeEventListener(`keydown`,this.escapeHandler),null)}destroy(){this.removeEscapeHandler(),this.portalManager.destroy(),document.body.style.overflow=``,this.initCheckInterval&&=(clearTimeout(this.initCheckInterval),null)}},kv=class{constructor(e,t){this.state={file:null,transcodingProgress:null,uploadProgress:null,isTranscoding:!1,isConfigLoading:!0,error:null,transcodedBlob:null},this.handler=null,this.config=e,this.callbacks=t;let n=e.backendUrl||`https://core.vidtreo.com`,r=null;e.apiKey&&!e.demo&&(r=ym.getInstance({apiKey:e.apiKey,backendUrl:n}));let i=new lg;this.handler=new jm({apiKey:e.apiKey,backendUrl:n,maxRecordingTime:e.maxRecordingTime,maxFileSize:e.maxFileSize,userMetadata:e.userMetadata},r,i),e.apiKey&&!e.demo?(this.updateState({isConfigLoading:!0}),this.handler.preloadConfig().then(()=>this.updateState({isConfigLoading:!1})).catch(()=>{this.updateState({isConfigLoading:!1,error:`Failed to load settings`})})):this.updateState({isConfigLoading:!1})}updateState(e){this.state={...this.state,...e},this.callbacks.onStateChange()}getState(){return this.state}async handleFileSelect(e){if(this.updateState({error:null}),!this.handler)throw Error(`Handler not initialized`);try{let t=await this.handler.handleFileSelection(e);return this.updateState({file:t}),t}catch(e){let t=i(e),n=e instanceof Error?e:Error(t);throw this.updateState({error:t}),this.callbacks.onError?.(n),n}}async processAndUpload(e){let t=e||this.state.file;if(!(t&&this.handler))return;let n=this.config.demo;try{if(this.updateState({isTranscoding:!0,transcodingProgress:0,error:null}),n){let e=await km(t.file,Bt,e=>{this.updateState({transcodingProgress:e}),this.callbacks.onTranscodingProgress?.(e)});this.updateState({transcodedBlob:e.blob,isTranscoding:!1,transcodingProgress:null})}else{let e=await this.handler.processAndUpload(e=>{this.updateState({transcodingProgress:e}),this.callbacks.onTranscodingProgress?.(e)},e=>{this.updateState({uploadProgress:e}),this.callbacks.onUploadProgress?.(e)});this.updateState({file:null,transcodingProgress:null,uploadProgress:null,isTranscoding:!1}),this.callbacks.onUploadComplete?.({recordingId:e.recordingId||``,uploadUrl:e.uploadUrl||``})}}catch(e){let t=i(e),r=e instanceof Error?e:Error(t);this.updateState({error:t,isTranscoding:!1,transcodingProgress:null,uploadProgress:null,transcodedBlob:null}),this.callbacks.onError?.(r),n||this.callbacks.onUploadError?.(r)}}downloadVideo(){if(!this.state.transcodedBlob)return;let e=URL.createObjectURL(this.state.transcodedBlob),t=document.createElement(`a`);t.href=e,t.download=`recording-${Date.now()}.mp4`,document.body.appendChild(t),t.click(),document.body.removeChild(t),URL.revokeObjectURL(e)}reset(){this.updateState({file:null,transcodingProgress:null,uploadProgress:null,error:null,isTranscoding:!1,transcodedBlob:null})}destroy(){this.handler&&this.handler.cancel(),this.handler=null}};function Av(e){return{preview:{initializingCamera:e.initializingCamera,grantPermissions:e.grantPermissions,browserUnsupported:e.browserUnsupported,browserUnsupportedDynamic:e.browserUnsupportedDynamic,browserUnsupportedSafari:e.browserUnsupportedSafari,browserUnsupportedFirefox:e.browserUnsupportedFirefox,switchingDevice:e.switchingDevice,recordingStartsIn:e.recordingStartsIn,rec:e.rec},buttons:{settings:e.settings,record:e.record,stop:e.stop,pause:e.pause,resume:e.resume,mute:e.mute,unmute:e.unmute,switchSource:e.switchSource,download:e.download},settings:{settings:e.settings,camera:e.camera,microphone:e.microphone}}}var jv=class{constructor(e){if(this.proxyEndpoint=e.proxyEndpoint,this.proxyEndpoint)throw Error(`Proxy mode not yet implemented`);this.service=new lg}uploadVideo(e,t){if(this.proxyEndpoint)throw Error(`Proxy mode not yet implemented`);return this.service.uploadVideo(e,t)}},Mv=`:root{--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% 0%;--vidtreo-z-modal-overlay:9999;--vidtreo-z-settings-panel:200;--vidtreo-z-error-overlay:100;--vidtreo-z-countdown-overlay:20;--vidtreo-z-progress-overlay:20;--vidtreo-z-controls:10}.vidtreo-preview-container{aspect-ratio:9/16;background:hsl(var(--vidtreo-preview-bg));contain:layout style;will-change:auto;backface-visibility:hidden;isolation:isolate;border:none;border-radius:0;justify-content:center;align-items:center;width:100%;display:flex;position:relative;overflow:visible;transform:translateZ(0)}.vidtreo-preview-container:before{display:none}@media (width>=768px){.vidtreo-preview-container{aspect-ratio:16/9}}.vidtreo-camera-area{contain:layout style paint;backface-visibility:hidden;isolation:isolate;will-change:auto;width:100%;height:100%;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;display:none;position:relative;transform:translateZ(0)}.vidtreo-source-transition-overlay{z-index:var(--vidtreo-z-error-overlay);backdrop-filter:blur(4px);contain:layout style paint;backface-visibility:hidden;will-change:opacity;background:#000000b3;border-radius:0;flex-direction:column;justify-content:center;align-items:center;transition:opacity .3s;display:none;position:absolute;inset:0;transform:translateZ(0)}.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{z-index:var(--vidtreo-z-controls);contain:layout style paint;backface-visibility:hidden;will-change:auto;background:#000;border-radius:0;flex-direction:column;justify-content:center;align-items:center;gap:1rem;display:flex;position:absolute;inset:0;transform:translateZ(0)}.vidtreo-skeleton-spinner{border:4px solid #ffffff4d;border-top-color:#fff;border-radius:50%;width:40px;height:40px;animation:.8s linear infinite vidtreo-spin}.vidtreo-skeleton-text{color:#fff;font-size:.875rem;font-weight:500}.vidtreo-video-preview{object-fit:contain;will-change:auto;backface-visibility:hidden;background:#000;border-radius:0;width:100%;height:100%;transition:opacity .3s,transform .3s;display:block;position:absolute;inset:0;transform:translateZ(0)}.vidtreo-video-preview-skeleton{z-index:2;contain:layout style paint;backface-visibility:hidden;will-change:auto;background:#000;border-radius:0;width:100%;height:100%;position:absolute;inset:0;overflow:hidden;transform:translateZ(0)}.vidtreo-skeleton-shimmer{background:linear-gradient(90deg, hsl(var(--vidtreo-muted)) 0%, hsl(var(--vidtreo-muted) / .5) 50%, hsl(var(--vidtreo-muted)) 100%);background-size:200% 100%;animation:1.5s ease-in-out infinite vidtreo-shimmer;position:absolute;inset:0}@keyframes vidtreo-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.vidtreo-video-preview-skeleton.vidtreo-hidden{opacity:0;pointer-events:none;transition:opacity .3s}.vidtreo-video-preview.vidtreo-screen-share{object-fit:cover}.vidtreo-video-preview.vidtreo-transitioning{opacity:.5;transform:scale(.98)}.vidtreo-countdown-overlay{z-index:var(--vidtreo-z-countdown-overlay);contain:layout style paint;backface-visibility:hidden;will-change:auto;background:#000000f2;border-radius:0;justify-content:center;align-items:center;display:none;position:absolute;inset:0;transform:translateZ(0)}.vidtreo-countdown-overlay.vidtreo-active{display:flex}.vidtreo-countdown-content{flex-direction:column;align-items:center;gap:1rem;display:flex}.vidtreo-countdown-number{color:#fff;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:#fff;margin-top:1rem;font-size:.875rem;font-weight:500}.vidtreo-settings-panel{z-index:var(--vidtreo-z-settings-panel);contain:layout style paint;backface-visibility:hidden;background:#0006;border:none;border-radius:.75rem;flex-direction:column;width:90%;margin-left:-47%;padding:.625rem;display:none;position:absolute;bottom:4rem;left:50%;overflow:hidden;transform:translateZ(0)}.vidtreo-settings-panel.vidtreo-active{display:flex}.vidtreo-settings-content{will-change:transform;backface-visibility:hidden;flex-direction:column;width:100%;display:flex;transform:translateZ(0)}.vidtreo-settings-content.vidtreo-slide-right{animation:.3s vidtreo-slideRight}.vidtreo-settings-content.vidtreo-slide-left{animation:.3s vidtreo-slideLeft}.vidtreo-settings-content.vidtreo-slide-none{will-change:auto;animation:none}@keyframes vidtreo-slideIn{0%{opacity:0;transform:translateY(1rem)}to{opacity:1;transform:translateY(0)}}@keyframes vidtreo-slideRight{0%{opacity:0;transform:translate(-100%)}to{opacity:1;transform:translate(0)}}@keyframes vidtreo-slideLeft{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}.vidtreo-settings-header{color:#fff;cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:.75rem;width:100%;margin-bottom:1rem;padding:0;display:flex}.vidtreo-settings-back-icon{color:#fff;flex-shrink:0}.vidtreo-settings-title{color:#fff;margin:0;font-size:.875rem;font-weight:600}.vidtreo-device-options-container{flex-direction:column;gap:.375rem;display:flex}.vidtreo-device-option-nav{cursor:pointer;color:#fff;background:0 0;border:none;border-radius:.5rem;align-items:center;gap:1rem;width:100%;padding:.5rem .75rem;transition:background-color .2s;display:flex}.vidtreo-device-option-nav:hover{background:#fff3}.vidtreo-device-option-nav-content{flex-shrink:0;align-items:center;gap:.75rem;display:flex}.vidtreo-device-option-nav-label{color:#fff;font-size:.875rem;font-weight:500}.vidtreo-device-option-nav-value{flex:1;justify-content:flex-end;align-items:center;gap:.5rem;min-width:0;display:flex}.vidtreo-device-option-nav-value-text{color:#fffc;text-overflow:ellipsis;white-space:nowrap;text-align:right;flex:1;font-size:.875rem;overflow:hidden}.vidtreo-device-option-nav-chevron{color:#fff;font-size:1.25rem;line-height:1}.vidtreo-device-list{flex-direction:column;gap:0;max-height:200px;display:flex;overflow-y:auto}.vidtreo-device-list::-webkit-scrollbar{width:4px}.vidtreo-device-list::-webkit-scrollbar-track{background:0 0}.vidtreo-device-list::-webkit-scrollbar-thumb{background:#fff3;border-radius:2px}.vidtreo-device-list::-webkit-scrollbar-thumb:hover{background:#ffffff4d}.vidtreo-device-option{cursor:pointer;color:#fff;text-align:left;background:0 0;border:none;border-radius:.5rem;align-items:center;gap:.75rem;width:100%;padding:.5rem .75rem;transition:background-color .2s;display:flex}.vidtreo-device-option:hover{background:#fff3}.vidtreo-device-option-check-container{flex-shrink:0;justify-content:center;align-items:center;width:20px;height:20px;display:flex}.vidtreo-device-checkmark-placeholder{flex-shrink:0;width:20px;height:20px}.vidtreo-device-checkmark{color:#fff;flex-shrink:0}.vidtreo-device-option-label{color:#fff;flex:1;font-size:.875rem}.vidtreo-device-empty{color:#fff9;text-align:center;padding:1rem 0;font-size:.875rem}.vidtreo-audio-level-bars{height:1rem;z-index:var(--vidtreo-z-controls);contain:layout style paint;will-change:auto;backface-visibility:hidden;align-items:center;gap:.125rem;display:flex;position:absolute;bottom:.75rem;right:.75rem;transform:translateZ(0)}@media (width>=768px){.vidtreo-audio-level-bars{height:1.25rem}}.vidtreo-audio-level-bar{background:#ffffff80;border-radius:9999px;align-self:flex-end;width:.125rem;transition:all .1s}.vidtreo-recording-controls{z-index:var(--vidtreo-z-controls);contain:layout style;will-change:auto;backface-visibility:hidden;position:absolute;left:50%;transform:translate(-50%)translateZ(0);bottom:12px!important}.vidtreo-recording-controls-row{will-change:auto;justify-content:center;align-items:center;gap:.5rem;display:flex;transform:translateZ(0)}.vidtreo-recording-timer-row{justify-content:space-between;align-items:center;gap:.5rem;display:flex}.vidtreo-recording-timer-badge{z-index:var(--vidtreo-z-controls);contain:layout style paint;will-change:auto;backface-visibility:hidden;background:#0000004d;border:none;border-radius:9999px;align-items:center;gap:.375rem;padding:.25rem .5rem;display:flex;position:absolute;top:.75rem;right:.75rem;transform:translateZ(0);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:#fff;font-family:monospace;font-size:.75rem;font-weight:500}.vidtreo-control-buttons-row{will-change:auto;justify-content:center;align-items:center;gap:.375rem;height:auto;min-height:2rem;display:flex;transform:translateZ(0)}@media (width>=768px){.vidtreo-control-buttons-row{min-height:2.25rem}}.vidtreo-control-button{cursor:pointer;color:#fff;box-sizing:border-box;vertical-align:top;contain:layout style paint;will-change:auto;backface-visibility:hidden;background:#0000004d;border:none;border-radius:9999px;flex-shrink:0;justify-content:center;align-items:center;width:2rem;height:2rem;min-height:2rem;max-height:2rem;margin:0;padding:.25rem;transition:background-color .2s;display:inline-flex;position:relative;transform:translateZ(0)}.vidtreo-control-button:before{content:"";z-index:0;border-radius:9999px;transition:background-color .2s;position:absolute;inset:.25rem}.vidtreo-control-button svg{color:inherit;z-index:1;flex-shrink:0;position:relative;width:22px!important;height:22px!important}@media (width>=768px){.vidtreo-control-button svg{width:24px!important;height:24px!important}.vidtreo-control-button{width:2.25rem;height:2.25rem;min-height:2.25rem;max-height:2.25rem}}.vidtreo-control-button:hover:not(:disabled):before{background:#fff3}.vidtreo-control-button:disabled{opacity:.5;cursor:not-allowed}.vidtreo-control-button.vidtreo-muted:before{background:#0000004d}.vidtreo-control-button.vidtreo-muted:hover:not(:disabled):before{background:#fff3}.vidtreo-record-button{background:hsl(var(--vidtreo-destructive));height:2rem;min-height:2rem;max-height:2rem;color:hsl(var(--vidtreo-destructive-foreground));box-sizing:border-box;vertical-align:top;cursor:pointer;border:none;border-radius:9999px;flex-shrink:0;justify-content:center;align-items:center;gap:.375rem;width:auto;margin:0;padding:0 .75rem;font-size:.75rem;font-weight:500;line-height:1;transition:background-color .2s,filter .2s;display:inline-flex}@media (width>=768px){.vidtreo-record-button{height:2.25rem;min-height:2.25rem;max-height:2.25rem;font-size:.875rem}}.vidtreo-record-button:hover:not(:disabled){filter:brightness(.85)}#startButton.vidtreo-record-button{animation:2s ease-in-out infinite vidtreo-record-glow-pulse}@keyframes vidtreo-record-glow-pulse{0%,to{box-shadow:0 0 8px 2px #ef444466,0 0 16px 4px #ef444433}50%{box-shadow:0 0 16px 4px #ef444499,0 0 32px 8px #ef44444d}}#startButton.vidtreo-record-button:hover:not(:disabled){animation-play-state:paused;box-shadow:0 0 20px 6px #ef4444b3,0 0 40px 10px #ef444459}.vidtreo-rec-indicator-top{contain:layout style paint;will-change:auto;backface-visibility:hidden;background:#0000004d;border:none;border-radius:9999px;align-items:center;gap:.375rem;padding:.25rem .5rem;display:flex;position:absolute;top:.75rem;left:.75rem;transform:translateZ(0);box-shadow:0 1px 3px #0000001a,0 1px 2px -1px #0000001a}.vidtreo-rec-indicator-top span{color:#fff;font-size:.75rem;font-weight:500}.vidtreo-start-camera-area{text-align:center;cursor:pointer;z-index:1;contain:layout style paint;backface-visibility:hidden;will-change:auto;background:#000;border:none;border-radius:0;flex-direction:column;justify-content:center;align-items:center;padding:40px;transition:all .3s;display:flex;position:absolute;inset:0;transform:translateZ(0)}.vidtreo-start-camera-area:hover:not(.vidtreo-loading){background:#000}.vidtreo-start-camera-area.vidtreo-loading{cursor:wait;opacity:.7}.vidtreo-start-camera-area.vidtreo-loading .vidtreo-camera-text{color:#fff;opacity:.7}.vidtreo-camera-icon{color:#fff;justify-content:center;margin-bottom:16px;font-size:48px;display:flex}.vidtreo-camera-text{color:#fff;margin-bottom:8px;font-weight:600}.vidtreo-camera-text a{color:#3b82f6;text-decoration:underline}.vidtreo-camera-text a:hover{color:#2563eb}.vidtreo-camera-hint{color:#fff;opacity:.8;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:#fff;font-size:14px}.vidtreo-error{color:#fff;text-align:center;z-index:var(--vidtreo-z-error-overlay);word-wrap:break-word;background:#dc2626;border:none;border-radius:.5rem;max-width:90%;padding:1rem 1.25rem;font-size:.875rem;font-weight:500;display:none;position:absolute;top:.75rem;left:50%;transform:translate(-50%);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.vidtreo-error.vidtreo-active{animation:.3s ease-out vidtreo-error-fade-in-slide-down;display:block}@keyframes vidtreo-error-fade-in-slide-down{0%{opacity:0;transform:translate(-50%)translateY(-1rem)}to{opacity:1;transform:translate(-50%)translateY(0)}}.vidtreo-upload-progress{margin-top:20px;display:none}.vidtreo-upload-progress.vidtreo-active{display:block}.vidtreo-preview-container .vidtreo-upload-progress{margin-top:0}.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}.vidtreo-preview-error{aspect-ratio:9/16;background:hsl(var(--vidtreo-preview-bg));contain:strict;will-change:auto;backface-visibility:hidden;isolation:isolate;border:none;border-radius:0;justify-content:center;align-items:center;width:100%;display:flex;position:relative;overflow:hidden;transform:translateZ(0)}@media (width>=768px){.vidtreo-preview-error{aspect-ratio:16/9}}.vidtreo-error-content{text-align:center;color:#fff;flex-direction:column;justify-content:center;align-items:center;gap:1rem;max-width:400px;padding:2rem;display:flex}.vidtreo-error-icon{font-size:3rem;line-height:1}.vidtreo-error-title{font-size:1.25rem;font-weight:600;line-height:1.2}.vidtreo-error-message{opacity:.9;word-break:break-word;font-size:.875rem;line-height:1.5}.vidtreo-error-config{text-align:left;border-top:1px solid #fff3;width:100%;margin-top:1.5rem;padding-top:1.5rem}.vidtreo-error-config-title{color:#fff;margin-bottom:.75rem;font-size:.875rem;font-weight:600}.vidtreo-error-config-item{color:#ffffffd9;margin-bottom:.5rem;font-size:.8125rem;line-height:1.6}.vidtreo-error-config-item code{color:#fff;background:#ffffff26;border-radius:.25rem;padding:.125rem .375rem;font-family:monospace;font-size:.75rem}.vidtreo-error-retry{background:hsl(var(--vidtreo-destructive));color:hsl(var(--vidtreo-destructive-foreground));cursor:pointer;border:none;border-radius:.375rem;margin-top:.5rem;padding:.5rem 1rem;font-size:.875rem;font-weight:500;transition:filter .2s}.vidtreo-error-retry:hover:not(:disabled){filter:brightness(.85)}.vidtreo-error-retry:disabled{opacity:.5;cursor:not-allowed}.vidtreo-error-overlay{background:hsl(var(--vidtreo-preview-bg));z-index:var(--vidtreo-z-error-overlay);justify-content:center;align-items:center;display:flex;position:absolute;inset:0}.vidtreo-native-camera-container{aspect-ratio:9/16;background:hsl(var(--vidtreo-preview-bg));border-radius:0;justify-content:center;align-items:center;width:100%;display:flex;position:relative;overflow:hidden}@media (width>=768px){.vidtreo-native-camera-container{aspect-ratio:16/9}}.vidtreo-native-camera-container:has(.vidtreo-native-camera-preview-container){background:0 0}.vidtreo-config-loading-indicator{z-index:var(--vidtreo-z-controls);position:absolute;top:8px;right:8px}.vidtreo-spinner-small{border:2px solid #ffffff4d;border-top-color:#fff;border-radius:50%;width:16px;height:16px;animation:.6s linear infinite spin}.vidtreo-native-camera-empty-state{flex-direction:column;justify-content:center;align-items:center;gap:16px;width:100%;height:100%;padding:24px;display:flex;position:relative}.vidtreo-native-camera-buttons{flex-direction:column;gap:12px;width:100%;max-width:300px;display:flex}.vidtreo-native-camera-process-button,.vidtreo-native-camera-download-button{z-index:30;position:absolute;bottom:24px;left:50%;transform:translate(-50%)}.vidtreo-native-camera-process-button .vidtreo-btn,.vidtreo-native-camera-download-button .vidtreo-btn{min-width:200px}.vidtreo-btn{border-radius:var(--vidtreo-radius);cursor:pointer;border:none;padding:12px 24px;font-size:1rem;font-weight:500;transition:all .2s}.vidtreo-btn:disabled{opacity:.5;cursor:not-allowed}.vidtreo-btn-primary{background:hsl(var(--vidtreo-primary));color:hsl(var(--vidtreo-primary-foreground))}.vidtreo-btn-primary:hover:not(:disabled){filter:brightness(.9)}.vidtreo-btn-secondary{background:hsl(var(--vidtreo-secondary));color:hsl(var(--vidtreo-secondary-foreground));border:1px solid hsl(var(--vidtreo-border))}.vidtreo-btn-secondary:hover:not(:disabled){background:hsl(var(--vidtreo-accent))}.vidtreo-transcoding-progress{width:100%;max-width:400px;padding:16px}.vidtreo-progress-bar{background:#fff3;border-radius:4px;width:100%;height:8px;overflow:hidden}.vidtreo-progress-fill{background:hsl(var(--vidtreo-primary));height:100%;transition:width .3s}.vidtreo-progress-text{text-align:center;color:hsl(var(--vidtreo-foreground));margin-top:8px;font-size:.875rem}.vidtreo-native-camera-preview-container{background:0 0;justify-content:center;align-items:center;width:100%;height:100%;display:flex;position:relative}.vidtreo-native-camera-preview-image{object-fit:contain;width:100%;height:100%;display:block}.vidtreo-progress-overlay{backdrop-filter:blur(4px);width:100%;height:100%;z-index:var(--vidtreo-z-progress-overlay);pointer-events:none;background:#000000b3;flex-direction:column;justify-content:center;align-items:center;display:flex;position:absolute;inset:0}.vidtreo-progress-overlay .vidtreo-transcoding-progress,.vidtreo-progress-overlay .vidtreo-upload-progress{pointer-events:auto;background:0 0;flex-direction:column;align-items:center;gap:12px;width:90%;max-width:400px;padding:0;display:flex;position:relative}.vidtreo-progress-overlay .vidtreo-progress-bar,.vidtreo-progress-overlay .vidtreo-upload-progress-bar{background:#fff3;border-radius:4px;width:100%;height:8px;overflow:hidden}.vidtreo-progress-overlay .vidtreo-progress-fill{background:#fff;height:100%;transition:width .3s}.vidtreo-progress-overlay .vidtreo-progress-text,.vidtreo-progress-overlay .vidtreo-upload-progress-text{text-align:center;color:#fff;margin-top:0;font-size:.875rem;font-weight:500}.vidtreo-progress-overlay .vidtreo-upload-progress-bar{background:#fff3;border-radius:4px;width:100%;height:8px;overflow:hidden}.vidtreo-progress-overlay .vidtreo-upload-progress-fill{background:#fff;height:100%;transition:width .3s}.vidtreo-progress-overlay .vidtreo-progress-indeterminate{background:linear-gradient(90deg,#0000 0%,#fff 50%,#0000 100%) 0 0/200% 100%;width:100%;animation:1.5s ease-in-out infinite vidtreo-progress-indeterminate}@keyframes vidtreo-progress-indeterminate{0%{background-position:200% 0}to{background-position:-200% 0}}.vidtreo-mobile-web-recorder{width:100%;height:100%;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif}.vidtreo-mobile-landing-container{aspect-ratio:4/3;background:hsl(var(--vidtreo-preview-bg));border-radius:0;justify-content:center;align-items:center;width:100%;max-height:100%;display:flex;position:relative;overflow:hidden}.vidtreo-mobile-landing-content{text-align:center;flex-direction:column;justify-content:center;align-items:center;gap:1.25rem;padding:2rem;display:flex}.vidtreo-mobile-landing-title{color:#fff;margin:0;font-size:1.25rem;font-weight:600;line-height:1.3}.vidtreo-mobile-landing-description{color:#ffffffbf;max-width:280px;margin:0;font-size:.875rem;line-height:1.5}.vidtreo-mobile-open-camera-btn{border-radius:9999px;justify-content:center;align-items:center;gap:.625rem;min-width:200px;margin-top:.5rem;padding:.875rem 1.75rem;font-size:1rem;font-weight:600;transition:all .2s;animation:2s ease-in-out infinite vidtreo-btn-glow-pulse;display:inline-flex}@keyframes vidtreo-btn-glow-pulse{0%,to{box-shadow:0 0 8px 2px #ffffff4d,0 0 16px 4px #ffffff26}50%{box-shadow:0 0 16px 4px #ffffff80,0 0 32px 8px #ffffff40}}.vidtreo-mobile-open-camera-btn:hover:not(:disabled){animation-play-state:paused;transform:scale(1.02);box-shadow:0 0 20px 6px #fff9,0 0 40px 10px #ffffff4d}.vidtreo-mobile-open-camera-btn:active:not(:disabled){transform:scale(.98)}.vidtreo-mobile-open-camera-btn:disabled{box-shadow:none;animation:none}#vidtreo-portal-root{z-index:9999;pointer-events:none;width:100vw;height:100dvh;position:fixed;top:0;left:0}#vidtreo-portal-root>*{pointer-events:auto}.vidtreo-mobile-modal-overlay{width:100vw;height:100dvh;z-index:var(--vidtreo-z-modal-overlay);background:#000;flex-direction:column;height:-webkit-fill-available;animation:.3s ease-out vidtreo-modal-fade-in;display:flex;position:fixed;inset:0}@keyframes vidtreo-modal-fade-in{0%{opacity:0}to{opacity:1}}.vidtreo-mobile-modal-header{padding:.75rem;padding-top:calc(.75rem + env(safe-area-inset-top,0px));z-index:var(--vidtreo-z-error-overlay);pointer-events:none;justify-content:center;display:flex;position:absolute;top:0;left:0;right:0}.vidtreo-mobile-modal-close-btn{color:#ffffffe6;cursor:pointer;pointer-events:auto;backdrop-filter:blur(4px);background:#00000080;border:none;border-radius:9999px;justify-content:center;align-items:center;gap:.375rem;height:2rem;padding:0 .75rem;font-size:.75rem;font-weight:500;transition:all .2s;display:flex}.vidtreo-mobile-modal-close-btn:hover:not(:disabled){background:#000000b3}.vidtreo-mobile-modal-close-btn:disabled{opacity:.3;cursor:not-allowed}.vidtreo-mobile-modal-content{width:100%;height:100%;padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px);padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px);flex-direction:column;flex:1;display:flex;position:relative}.vidtreo-mobile-recorder-content{flex-direction:column;width:100%;height:100%;display:flex;position:relative}.vidtreo-mobile-recorder-content .vidtreo-preview-container{aspect-ratio:unset;flex:1;width:100%;height:100%}.vidtreo-mobile-recorder-content .vidtreo-video-preview{object-fit:cover}.vidtreo-mobile-preview{flex:1;aspect-ratio:unset!important;height:100%!important}.vidtreo-mobile-recorder-content .vidtreo-recording-controls{bottom:calc(24px + env(safe-area-inset-bottom,0px))}.vidtreo-mobile-recorder-content .vidtreo-audio-level-bars{bottom:calc(12px + env(safe-area-inset-bottom,0px))}.vidtreo-mobile-recorder-content .vidtreo-settings-panel{bottom:calc(7rem + env(safe-area-inset-bottom,0px))}.vidtreo-mobile-recorder-content .vidtreo-rec-indicator-top,.vidtreo-mobile-recorder-content .vidtreo-recording-timer-badge{top:calc(.75rem + env(safe-area-inset-top,0px));contain:layout style;height:2rem;padding:0 .75rem}.vidtreo-mobile-recorder-content .vidtreo-recording-timer-text{white-space:nowrap;color:#fff;min-width:3rem;font-size:.875rem;display:inline-block}.vidtreo-mobile-recorder-content .vidtreo-error{top:calc(3.5rem + env(safe-area-inset-top,0px))}.vidtreo-mobile-recorder-content .vidtreo-control-buttons-row{gap:.75rem;min-height:4rem}.vidtreo-mobile-recorder-content .vidtreo-control-button{width:4rem;height:4rem;min-height:4rem;max-height:4rem}.vidtreo-mobile-recorder-content .vidtreo-control-button svg{width:1.5rem;height:1.5rem}.vidtreo-mobile-recorder-content .vidtreo-record-button{gap:.5rem;height:4rem;min-height:4rem;max-height:4rem;padding:0 1.5rem;font-size:1rem}.vidtreo-mobile-recorder-content .vidtreo-record-button svg{width:1.5rem;height:1.5rem}`;function Nv(e){return`
9872
- <style>${Mv}</style>
9960
+ `],{type:`application/javascript`})}let f_=zg({createBlob:d_,createObjectUrl:e=>URL.createObjectURL(e),revokeObjectUrl:e=>{URL.revokeObjectURL(e)}});function p_(){return f_.acquire()}function m_(){f_.release()}let h_=1e3;var g_=class{constructor(e={}){this.worker=null,this.hasWorkerUrlLease=!1,this.chunks=[],this.totalSize=0,this.isActive=!1,this.audioTrackClone=null,this.isMuted=!1,this.currentVideoTrack=null,this.isPaused=!1,this.overlayConfig=null,this.readyPromiseResolve=null;let t=e=>new Worker(e,{type:`classic`});e.createWorker&&(t=e.createWorker);let n=()=>typeof MediaStreamTrackProcessor<`u`;e.canUseMainThreadVideoProcessor&&(n=e.canUseMainThreadVideoProcessor);let r=e=>typeof MediaStreamTrackProcessor>`u`?null:new MediaStreamTrackProcessor({track:e}).readable;e.createVideoStreamFromTrack&&(r=e.createVideoStreamFromTrack),this.canUseMainThreadVideoProcessorFn=n,this.createVideoStreamFromTrackFn=r;let i=!!e.createWorker;this.workerProbeManager=new u_({setTimeout:window.setTimeout.bind(window),clearTimeout:window.clearTimeout.bind(window),timeoutMilliseconds:2e3}),this.audioWorkletManager=new Yg({onChunk:e=>{if(!(this.isWorkerActive()&&this.worker))return;let t={type:`audioChunk`,data:e.data,frames:e.frames,numberOfChannels:e.numberOfChannels,sampleRate:e.sampleRate,timestamp:e.timestamp},n=[];e.data.buffer instanceof ArrayBuffer&&n.push(e.data.buffer),this.worker.postMessage(t,n)}});let a=e=>{let t=e.data;switch(t.type){case`ready`:$.debug(`[WorkerProcessor] Worker ready`),this.readyPromiseResolve&&=(this.readyPromiseResolve(),null);break;case Rm:this.workerProbeManager.handleProbeResult(t);break;case`debugLog`:t.payload?$.debug(t.message,t.payload):$.debug(t.message);break;case`error`:$.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`:$.debug(`[WorkerProcessor] State changed:`,t.state),this.isPaused=t.state===`paused`;break;default:$.warn(`[WorkerProcessor] Unknown response type:`,t)}},o=e=>{if($.error(`[WorkerProcessor] Worker error event:`,{message:e.message,filename:e.filename,lineno:e.lineno,colno:e.colno,error:e.error}),this.onError){let t=e.message;t||=`Unknown worker error`,this.onError(Error(t))}},s=typeof Worker<`u`,c=!1;if(s&&(c=!0),i&&(c=!0),!c)throw $.error(`[WorkerProcessor] Web Workers are not supported`),Error(`Web Workers are not supported`);let l=p_();this.hasWorkerUrlLease=!0;try{this.worker=o_({createWorker:t,workerUrl:l,onMessage:a,onError:o,logger:$})}catch(e){throw this.releaseWorkerUrlLease(),e}}getWorkerProbeResult(){let e=this.getWorkerOrThrow();return this.workerProbeManager.getProbeResult(e)}async startProcessing(e,t,n){this.getWorkerOrThrow(),this.ensureProcessingInactive(),this.resetProcessingState(n),this.stopAudioWorklet();let r=this.resolveRecordingFormat(t),i=await this.resolveAudioCodec(t),a=await this.resolveVideoCodec(t,r),o=kg(e);$.debug(`[WorkerProcessor] Starting processing`,{isScreenCapture:o,fps:t.fps,codec:a,bitrate:t.bitrate});let s=this.buildWorkerTranscodeConfig(t,i,a,r),c=e.getVideoTracks(),l=e.getAudioTracks();$.debug(`[WorkerProcessor] Preparing to start processing`,{videoTracksCount:c.length,audioTracksCount:l.length,hasWorker:!!this.worker});let u=this.getVideoInputSelectorDependencies(),d=Xg(c,u),f=Zg(l,u),p=await this.getWorkerProbeResult(),m=Qg(d,p,u),h=e_(u),g=$g(d);n_(d,u),r_(u),t_(d,f,m.videoStream,u);let _=u.getViewportMetadata(),ee;_&&(ee={orientationAngle:_.orientationAngle,windowOrientation:_.windowOrientation});let{audioConfig:v,audioStream:y,shouldStartAudioWorklet:b}=await this.prepareAudioPipeline(f,p),x=this.buildOverlayConfigToSend(),S=s_({videoTrack:m.videoTrack,videoStream:m.videoStream,audioStream:y,isMobileDevice:h,videoSettings:g,viewportMetadata:ee,audioConfig:v,workerConfig:s,overlayConfig:x}),te=l_(m.videoStream,y,m.videoTrack);$.debug(`[WorkerProcessor] Posting message to worker`,{transferablesCount:te.length,messageType:S.type}),await this.postStartMessage(S,te,b)}getWorkerOrThrow(){if(!this.worker)throw Error(`Worker not initialized`);return this.worker}ensureProcessingInactive(){if(this.isActive)throw Error(`Processing already active`)}resetProcessingState(e){this.isActive=!0,this.isMuted=!1,this.isPaused=!1,this.chunks=[],this.totalSize=0,e?this.overlayConfig=e:this.overlayConfig=null}resolveRecordingFormat(e){let t=e.format;return t||=`mp4`,t}async resolveAudioCodec(e){let t=e.audioCodec;return t||=await hm(e.audioBitrate),t}async resolveVideoCodec(e,t){return t===`webm`?await mm(e.width,e.height,e.bitrate):await pm(e.width,e.height,e.bitrate)}buildWorkerTranscodeConfig(e,t,n,r){return{width:e.width,height:e.height,fps:e.fps,bitrate:Ag(e.bitrate),audioCodec:t,audioBitrate:e.audioBitrate,codec:n,keyFrameInterval:5,format:r,watermark:e.watermark}}async prepareAudioPipeline(e,t){if(!e)return $.debug(`[WorkerProcessor] Audio pipeline disabled (no track)`),{audioConfig:null,audioStream:null,shouldStartAudioWorklet:!1};if(this.canUseMainThreadVideoProcessorFn()&&t.hasAudioData){let n=this.createAudioStreamFromTrack(e);if(n)return $.debug(`[WorkerProcessor] Audio pipeline selected`,{path:`main-thread-audio-stream`,hasAudioDataInWorker:t.hasAudioData}),{audioConfig:null,audioStream:n,shouldStartAudioWorklet:!1}}let n=await this.prepareAudioConfig(e);if(n)return $.debug(`[WorkerProcessor] Audio pipeline selected`,{path:`audio-worklet-chunks`,sampleRate:n.sampleRate,numberOfChannels:n.numberOfChannels}),{audioConfig:n,audioStream:null,shouldStartAudioWorklet:!0};throw this.createBrowserUnsupportedError()}buildOverlayConfigToSend(){if(this.overlayConfig)return this.overlayConfig}async postStartMessage(e,t,n){let r=this.getWorkerOrThrow(),i=new Promise(e=>{this.readyPromiseResolve=e});try{r.postMessage(e,t),$.debug(`[WorkerProcessor] Message posted successfully`),await i,$.debug(`[WorkerProcessor] Worker confirmed ready`),n&&await this.startAudioWorkletProcessing()}catch(e){throw $.error(`[WorkerProcessor] Failed to post message:`,e),this.readyPromiseResolve=null,this.stopAudioWorklet(),this.worker&&this.isActive&&this.worker.postMessage({type:`stop`}),this.isActive=!1,e}}pause(){this.worker&&this.isActive&&(this.worker.postMessage({type:`pause`}),this.setAudioWorkletPaused(!0))}resume(){this.isWorkerActive()&&this.worker&&(this.worker.postMessage({type:`resume`}),this.setAudioWorkletPaused(!1))}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`}),this.setAudioWorkletMuted(this.isMuted)}async switchVideoSource(e){if(!(this.isWorkerActive()&&this.worker))return $.debug(`[WorkerProcessor] Cannot switch source - worker not active`,{hasWorker:!!this.worker,isActive:this.isActive}),Promise.resolve();let t=e.getVideoTracks();if($.debug(`[WorkerProcessor] Switching video source`,{videoTracksCount:t.length}),t.length===0)return $.warn(`[WorkerProcessor] No video tracks in new stream`),Promise.resolve();let n=kg(e);$.debug(`[WorkerProcessor] Source type detected`,{isScreenCapture:n,targetFps:30}),this.worker.postMessage({type:`updateFps`,fps:30});let r={type:`updateSourceType`,isScreenCapture:n};this.worker.postMessage(r);let i=this.getVideoInputSelectorDependencies(),a=Xg(t,i);if(!a)return $.warn(`[WorkerProcessor] Unable to prepare video track`),Promise.resolve();$.debug(`[WorkerProcessor] New video track details`,{trackId:a.id,trackKind:a.kind,trackReadyState:a.readyState});let o=Qg(a,await this.getWorkerProbeResult(),i),s=c_(o.videoTrack,o.videoStream),c=l_(o.videoStream,null,o.videoTrack);try{return $.debug(`[WorkerProcessor] Posting switch source message`),this.worker.postMessage(s,c),$.debug(`[WorkerProcessor] Switch source message posted`),new Promise(e=>{setTimeout(()=>{e()},0)})}catch(e){throw $.error(`[WorkerProcessor] Failed to switch source:`,e),e}}finalize(){if(!this.isWorkerActive())throw Error(`Processing not active`);let e=performance.now();return new Promise((t,n)=>{let r=this.worker;if(!r){n(Error(`Worker not initialized`));return}let i=null,a=()=>{i!==null&&(clearTimeout(i),i=null)},o=()=>{r.removeEventListener(`message`,l)},s=!1,c=()=>s?!1:(s=!0,a(),o(),!0),l=r=>{if(s)return;let i=r.data;if(i.type===`stateChange`&&i.state===`stopped`){if(!c())return;this.resetFinalizeRuntimeState(),Promise.resolve().then(()=>this.createBlobFromChunks()).then(e=>{t(e)},t=>{this.rejectFinalizeBlobCreationError(n,t,e)});return}i.type===`error`&&c()&&(this.resetFinalizeRuntimeState(),$.error(`[WorkerProcessor] Finalize failed`,{elapsedSeconds:(performance.now()-e)/h_,error:i.error}),n(Error(i.error)))};i=setTimeout(()=>{c()&&($.error(`[WorkerProcessor] Finalize timeout reached`,{elapsedSeconds:(performance.now()-e)/h_}),this.resetFinalizeRuntimeState(),n(Error(`Finalize timeout`)))},3e4),r.addEventListener(`message`,l),r.postMessage({type:`stop`})})}resetFinalizeRuntimeState(){this.isActive=!1,this.stopAudioWorklet()}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 Rg(t),{blob:new Blob([t],{type:`video/mp4`}),totalSize:this.totalSize}}rejectFinalizeBlobCreationError(e,t,n){if($.error(`[WorkerProcessor] Finalize failed while creating blob`,{elapsedSeconds:(performance.now()-n)/h_,error:i(t)}),t instanceof Error){e(t);return}e(Error(i(t)))}cancel(){return this.worker&&this.isActive&&this.worker.postMessage({type:`stop`}),this.stopAudioWorklet(),this.isActive=!1,this.isPaused=!1,this.chunks=[],this.totalSize=0,Promise.resolve()}getBufferSize(){return this.totalSize}getMutedState(){return this.isMuted}updateTabVisibility(e,t){if(!(this.isWorkerActive()&&this.worker)){$.warn(`[WorkerProcessor] Cannot update visibility - worker not active`,{isActive:this.isActive,hasWorker:!!this.worker});return}$.debug(`[WorkerProcessor] Sending visibility update to worker`,{isHidden:e,timestamp:t,timestampSeconds:t/h_});let n={type:`updateVisibility`,isHidden:e,timestamp:t};this.worker.postMessage(n)}updateSourceType(e){if(!(this.isWorkerActive()&&this.worker)){$.warn(`[WorkerProcessor] Cannot update source type - worker not active`,{isActive:this.isActive,hasWorker:!!this.worker});return}$.debug(`[WorkerProcessor] Sending source type update to worker`,{isScreenCapture:e});let t={type:`updateSourceType`,isScreenCapture:e};this.worker.postMessage(t)}async startAudioWorkletProcessing(){await this.audioWorkletManager.startProcessing()}stopAudioWorklet(){this.audioWorkletManager.stop()}setAudioWorkletMuted(e){this.audioWorkletManager.setMuted(e)}setAudioWorkletPaused(e){this.audioWorkletManager.setPaused(e)}prepareAudioConfig(e){return this.audioWorkletManager.prepareAudioConfig(e)}createAudioStreamFromTrack(e){return!e||typeof MediaStreamTrackProcessor>`u`?null:new MediaStreamTrackProcessor({track:e}).readable}createBrowserUnsupportedError(){return kt({resolutionStage:`feature-preflight`})}getVideoInputSelectorDependencies(){return{stopCurrentVideoTrack:()=>this.stopCurrentVideoTrack(),cloneVideoTrack:e=>this.cloneVideoTrack(e),cloneAudioTrack:e=>this.cloneAudioTrack(e),setCurrentVideoTrack:e=>{this.currentVideoTrack=e},canUseMainThreadVideoProcessor:()=>this.canUseMainThreadVideoProcessorFn(),createVideoStreamFromTrack:e=>this.createVideoStreamFromTrackFn(e),createBrowserUnsupportedError:()=>this.createBrowserUnsupportedError(),getViewportMetadata:()=>{if(typeof window>`u`)return null;let e=window.screen,t,n,r,i;return e&&(i=e.orientation),i?.type&&(t=i.type),i&&typeof i.angle==`number`&&(n=i.angle),typeof window.orientation==`number`&&(r=window.orientation),{innerWidth:window.innerWidth,innerHeight:window.innerHeight,orientation:t,orientationAngle:n,windowOrientation:r}},logger:{debug:(e,t)=>$.debug(e,t),warn:(e,t)=>$.warn(e,t)},isMobileDevice:()=>gm()}}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($.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 $.debug(`[WorkerProcessor] Video track cloned successfully:`,{id:t.id,kind:t.kind,readyState:t.readyState}),t}catch(e){$.error(`[WorkerProcessor] Failed to clone video track:`,e);let t=i(e);throw Error(`Failed to clone video track: ${t}`)}return $.warn(`[WorkerProcessor] Video track clone() not available, using original`),e}cloneAudioTrack(e){if($.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,$.debug(`[WorkerProcessor] Audio track cloned successfully:`,{id:t.id,kind:t.kind,readyState:t.readyState}),t}catch(e){$.error(`[WorkerProcessor] Failed to clone audio track:`,e);let t=i(e);throw Error(`Failed to clone audio track: ${t}`)}return $.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),this.releaseWorkerUrlLease(),this.stopAudioWorklet(),this.isActive=!1,this.isPaused=!1,this.chunks=[],this.totalSize=0}releaseWorkerUrlLease(){this.hasWorkerUrlLease&&=(m_(),!1)}},__=class{constructor(e={}){this.currentVideoStream=null;let t=()=>new g_;e.workerProcessorFactory&&(t=e.workerProcessorFactory);try{this.workerProcessor=t(),$.debug(`[StreamProcessor] Using worker-based processing`)}catch(e){let t=i(e);throw Error(`Failed to initialize worker: ${t}`)}}async startProcessing(e,t,n){this.workerProcessor.setOnBufferUpdate((e,t)=>{$.debug(`[StreamProcessor] Buffer update:`,{size:e,formatted:t}),this.onBufferUpdate&&this.onBufferUpdate(e,t)}),this.workerProcessor.setOnError(e=>{$.error(`[StreamProcessor] Worker error:`,e),this.onError&&this.onError(e)}),this.currentVideoStream=e,await this.workerProcessor.startProcessing(e,t,n)}updateTabVisibility(e,t){this.workerProcessor.updateTabVisibility(e,t)}updateSourceType(e){this.workerProcessor.updateSourceType(e)}pause(){this.workerProcessor.pause()}resume(){this.workerProcessor.resume()}isPausedState(){return this.workerProcessor.isPausedState()}async finalize(){return $.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}setOnBufferUpdate(e){this.onBufferUpdate=e}setOnError(e){this.onError=e}async cancel(){await this.workerProcessor.cancel(),this.workerProcessor.cleanup(),this.currentVideoStream=null}};let v_=1e3,y_=`recording`,b_=`idle`;var x_=class{constructor(e,t){this.recordingState=b_,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.recordingStartTime=null,this.maxTimeRemaining=null,this.recordingSeconds=0,this.recordingIntervalId=null,this.pauseStartTime=null,this.totalPausedTime=0,this.streamProcessor=null,this.originalCameraStream=null,this.enableTabVisibilityOverlay=!1,this.streamManager=e,this.callbacks=t}setCountdownDuration(e){this.countdownDuration=e}setMaxRecordingTime(e){this.maxRecordingTime=e}setTabVisibilityOverlayConfig(e,t){this.enableTabVisibilityOverlay=e,this.tabVisibilityOverlayText=t}getRecordingState(){return this.recordingState}isPausedState(){return this.isPaused}getRecordingSeconds(){return this.recordingSeconds}getStreamProcessor(){return this.streamProcessor}updateSourceType(e){this.recordingState!==y_||!this.streamProcessor||this.streamProcessor.updateSourceType(e)}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=b_,this.cancelCountdown()}}startCountdown(){this.recordingState=`countdown`,this.countdownRemaining=Math.ceil(this.countdownDuration/v_),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)/v_)),this.callbacks.onCountdownUpdate(this.recordingState,this.countdownRemaining)},100),this.countdownTimeoutId=window.setTimeout(async()=>{await this.doStartRecording().catch(()=>{})},this.countdownDuration)}async doStartRecording(){$.debug(`[RecordingManager] doStartRecording called`),this.cancelCountdown(),this.recordingState=y_,this.callbacks.onStateChange(this.recordingState),this.resetRecordingState();let e=this.streamManager.getStream();if($.debug(`[RecordingManager] Current stream:`,{hasStream:!!e,audioTracks:e?.getAudioTracks().length||0,videoTracks:e?.getVideoTracks().length||0}),!e){$.warn(`[RecordingManager] No stream available`),this.handleError(Error(`No stream available for recording`)),this.recordingState=b_,this.callbacks.onStateChange(this.recordingState);return}this.originalCameraStream=e,$.debug(`[RecordingManager] Creating stream processor`),this.streamProcessor=new __,$.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=b_,this.callbacks.onStateChange(this.recordingState);return}if(!t.config){this.handleError(Error(`Failed to get recording config`)),this.recordingState=b_,this.callbacks.onStateChange(this.recordingState);return}$.debug(`[RecordingManager] Starting recording with stream manager`);let n=await this.streamManager.startRecording(this.streamProcessor,t.config,this.enableTabVisibilityOverlay,this.tabVisibilityOverlayText).then(()=>($.info(`[RecordingManager] Recording started successfully`),null)).catch(e=>($.error(`[RecordingManager] Error starting recording:`,e),e));if(n){this.handleError(n),this.recordingState=b_,this.callbacks.onStateChange(this.recordingState);return}this.startRecordingTimer(),this.recordingStartTime=Date.now(),this.maxRecordingTime&&this.maxRecordingTime>0&&(this.maxTimeRemaining=this.maxRecordingTime,this.startMaxTimeTimer())}async stopRecording(){$.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(),$.debug(`[RecordingManager] Stopping recording in stream manager`);let e=(await this.streamManager.stopRecording()).blob;return $.info(`[RecordingManager] Recording stopped, blob size:`,e.size),this.recordingState=b_,this.callbacks.onStateChange(this.recordingState),this.recordingSeconds=0,this.streamProcessor=null,this.callbacks.onRecordingComplete(e),e}catch(e){throw this.handleError(e),this.recordingState=b_,this.callbacks.onStateChange(this.recordingState),e}}pauseRecording(){if(!(this.recordingState!==y_||this.isPaused)&&(this.streamManager.pauseRecording(),this.isPaused=!0,this.clearTimer(this.recordingIntervalId,clearInterval),this.recordingIntervalId=null,this.pauseStartTime=Date.now(),this.maxTimeTimer!==null&&this.recordingStartTime!==null&&this.maxRecordingTime!==null)){let e=Date.now()-this.recordingStartTime-this.totalPausedTime;this.maxTimeRemaining=Math.max(0,this.maxRecordingTime-e),this.clearTimer(this.maxTimeTimer,clearTimeout),this.maxTimeTimer=null}}resumeRecording(){this.recordingState!==y_||!this.isPaused||(this.streamManager.resumeRecording(),this.isPaused=!1,this.updatePausedDuration(),this.startRecordingTimer(),this.maxTimeRemaining!==null&&this.maxTimeRemaining>0&&this.startMaxTimeTimer())}cancelCountdown(){this.clearTimer(this.countdownTimeoutId,clearTimeout),this.countdownTimeoutId=null,this.clearTimer(this.countdownIntervalId,clearInterval),this.countdownIntervalId=null,this.recordingState=b_,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,this.recordingStartTime=null,this.maxTimeRemaining=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(){if(this.recordingIntervalId!==null)return;let e=Yh(this.recordingSeconds);this.callbacks.onTimerUpdate(e),this.recordingIntervalId=window.setInterval(()=>{this.recordingSeconds+=1;let e=Yh(this.recordingSeconds);this.callbacks.onTimerUpdate(e)},1e3)}startMaxTimeTimer(){this.maxTimeRemaining===null||this.maxTimeRemaining<=0||(this.clearTimer(this.maxTimeTimer,clearTimeout),this.maxTimeTimer=window.setTimeout(async()=>{this.recordingState===y_&&!this.isPaused&&await this.stopRecording()},this.maxTimeRemaining))}clearTimer(e,t){e!==null&&t(e)}handleError(e){let t=e instanceof Error?e:Error(i(e));this.callbacks.onError(t)}},S_=class{constructor(e){this.client=null,this.createTelemetryClient=e.createTelemetryClient}initialize(e,t){typeof e==`string`&&e.length>0&&typeof t==`string`&&t.length>0&&(this.client=this.createTelemetryClient(e,t))}sendEvent(e,t,n){if(!this.client)return;let r={name:e};t&&(r={...r,properties:t}),n&&(r={...r,error:n}),this.client.triggerTelemetryEvent(r)}async executeAction(e){e.requestedEvent&&this.sendEvent(e.requestedEvent,e.properties);let t=null;if(await e.action().catch(e=>{t=e}),t)throw this.sendEvent(e.failedEvent,e.properties,t),t;this.sendEvent(e.succeededEvent,e.properties)}async executeActionWithResult(e){e.requestedEvent&&this.sendEvent(e.requestedEvent,e.properties);let t=null,n=null;if(await e.action().then(e=>{n=e}).catch(e=>{t=e}),t)throw this.sendEvent(e.failedEvent,e.properties,t),t;if(this.sendEvent(e.succeededEvent,e.properties),n===null)throw Error(`Telemetry action failed to return result`);return n}},C_=class{constructor(){this.metadataById=new Map}getMetadata(e){return this.metadataById.get(e)}setMetadata(e,t){let n=new Map(this.metadataById);n.set(e,t),this.metadataById=n}clearMetadata(e){let t=new Map(this.metadataById);t.delete(e),this.metadataById=t}};let w_=`[RecorderController]`;var T_=class{constructor(e={}){this.uploadService=null,this.uploadQueueManager=null,this.isInitialized=!1,this.isDemo=!1,this.enableTabVisibilityOverlay=!1,this.callbacks=e,this.streamManager=new eg,this.configManager=new xm,this.storageManager=new uh,this.deviceManager=new Sm(this.streamManager,e.device),this.audioLevelAnalyzer=new o,this.uploadService=new pg,this.uploadCallbacks=Tg(e),this.telemetryManager=new S_({createTelemetryClient:dg}),this.uploadMetadataManager=new C_;let t=Dg(e,{stopAudioTracking:()=>this.audioLevelAnalyzer.stopTracking(),getConfig:()=>this.configManager.getConfig()});this.recordingManager=new x_(this.streamManager,t);let n=Og(e,{isRecording:()=>this.isRecording(),updateSourceType:e=>{this.recordingManager.updateSourceType(e)},getSelectedCameraDeviceId:()=>this.deviceManager.getSelectedCameraDeviceId(),getSelectedMicDeviceId:()=>this.deviceManager.getSelectedMicDeviceId()});this.sourceSwitchManager=new Hh(this.streamManager,n);let r=e.stream;r&&(this.streamManager.on(`streamstart`,({stream:e})=>{$.debug(`${w_} streamstart event received, calling callback`),r.onStreamStart&&r.onStreamStart(e)}),this.streamManager.on(`streamstop`,()=>{$.debug(`${w_} streamstop event received, calling callback`),r.onStreamStop&&r.onStreamStop()}),this.streamManager.on(`error`,({error:e})=>{$.error(`${w_} stream error event received, calling callback`,e),this.telemetryManager.sendEvent(`stream.error`,{sourceType:this.getCurrentSourceType()},e),r.onError&&r.onError(e)}))}async initialize(e){if(this.isInitialized)return;await this.validateRecorderSupport();let t=!1;typeof e.demo==`boolean`&&(t=e.demo),this.isDemo=t;let n=null;typeof e.apiKey==`string`&&e.apiKey.length>0&&(n=e.apiKey);let r=null;typeof e.backendUrl==`string`&&e.backendUrl.length>0&&(r=e.backendUrl),this.telemetryManager.initialize(n,r),await this.telemetryManager.executeAction({requestedEvent:`sdk.init.started`,succeededEvent:`sdk.init.succeeded`,failedEvent:`sdk.init.failed`,action:async()=>{await this.initializeConfig(n,r),this.applyRecordingConfig(e),await this.initializeStorage(),this.isInitialized=!0}})}async startStream(){let e=this.getCurrentSourceType();await this.telemetryManager.executeAction({succeededEvent:`preview.start.succeeded`,failedEvent:`preview.start.failed`,action:async()=>{$.debug(`${w_} startStream called`),await this.streamManager.startStream(),$.debug(`${w_} startStream completed`)},properties:{sourceType:e}})}async stopStream(){await this.streamManager.stopStream()}switchVideoDevice(e){return this.streamManager.switchVideoDevice(e)}switchAudioDevice(e){return this.streamManager.switchAudioDevice(e)}async startRecording(){await this.ensureConfigReady();let e=this.getCurrentSourceType();await this.telemetryManager.executeAction({requestedEvent:`recording.start.requested`,succeededEvent:`recording.start.succeeded`,failedEvent:`recording.start.failed`,action:async()=>{await this.recordingManager.startRecording()},properties:{sourceType:e}})}async stopRecording(){let e=this.getCurrentSourceType();return await this.telemetryManager.executeActionWithResult({requestedEvent:`recording.stop.requested`,succeededEvent:`recording.stop.succeeded`,failedEvent:`recording.stop.failed`,action:async()=>{let e=await this.recordingManager.stopRecording();return await this.sourceSwitchManager.handleRecordingStop().catch(()=>{throw Error(`Source switch cleanup failed`)}),this.streamManager.stopStream(),e},properties:{sourceType:e}})}getTabVisibilityOverlayConfig(){return{enabled:this.enableTabVisibilityOverlay,text:this.tabVisibilityOverlayText}}pauseRecording(){this.recordingManager.pauseRecording()}resumeRecording(){this.recordingManager.resumeRecording()}async switchSource(e){await this.telemetryManager.executeAction({requestedEvent:`source.switch.requested`,succeededEvent:`source.switch.succeeded`,failedEvent:`source.switch.failed`,action:async()=>{await this.sourceSwitchManager.toggleSource()},properties:{sourceType:e}})}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 Cm(e),a=`recording-${Date.now()}.mp4`,o=this.getCurrentSourceType(),s;Object.keys(r).length>0&&(s=r),this.telemetryManager.sendEvent(`upload.started`,{filename:a,duration:i,sourceType:o});let c=await this.uploadQueueManager.queueUpload({blob:e,apiKey:t,backendUrl:n,filename:a,duration:i,metadata:void 0,userMetadata:s});this.uploadMetadataManager.setMetadata(c,{filename:a,duration:i,sourceType:o})}getStream(){return this.streamManager.getStream()}isConfigReady(){return this.configManager.isConfigReady()}async ensureConfigReady(){this.isDemo||await this.configManager.fetchConfig()}cleanup(){this.storageManager.destroy(),this.recordingManager.cleanup(),this.audioLevelAnalyzer.stopTracking(),this.sourceSwitchManager.cleanup()}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()}async initializeConfig(e,t){let n=!0;e===null&&(n=!1),t===null&&(n=!1),n&&e!==null&&t!==null&&await this.configManager.initialize(e,t)}applyRecordingConfig(e){e.countdownDuration!==void 0&&this.recordingManager.setCountdownDuration(e.countdownDuration),e.maxRecordingTime!==void 0&&this.recordingManager.setMaxRecordingTime(e.maxRecordingTime),e.enableTabVisibilityOverlay!==void 0&&(this.enableTabVisibilityOverlay=e.enableTabVisibilityOverlay),e.tabVisibilityOverlayText!==void 0&&(this.tabVisibilityOverlayText=e.tabVisibilityOverlayText),this.recordingManager.setTabVisibilityOverlayConfig(this.enableTabVisibilityOverlay,this.tabVisibilityOverlayText)}async initializeStorage(){let e=Eg(this.callbacks);await this.storageManager.initialize(e);let t=this.storageManager.getStorageService();t&&this.uploadService&&(this.uploadQueueManager=new fg(t,this.uploadService),this.uploadQueueManager.setCallbacks({onUploadProgress:(e,t)=>{this.uploadCallbacks.onProgress(t)},onUploadComplete:(e,t)=>{this.uploadCallbacks.onSuccess(t);let n=this.uploadMetadataManager.getMetadata(e);n&&(this.telemetryManager.sendEvent(`upload.succeeded`,{filename:n.filename,duration:n.duration,sourceType:n.sourceType,recordingId:t.id}),this.uploadMetadataManager.clearMetadata(e))},onUploadError:(e,t)=>{this.uploadCallbacks.onError(t);let n=this.uploadMetadataManager.getMetadata(e);n&&(this.telemetryManager.sendEvent(`upload.failed`,{filename:n.filename,duration:n.duration,sourceType:n.sourceType},t),this.uploadMetadataManager.clearMetadata(e))}}))}async validateRecorderSupport(){At();let e=await th({requiresAudio:!1,requiresWatermark:!1});if(!e.isSupported)throw kt({missingCapabilities:e.missing,resolutionStage:`feature-preflight`})}};let E_=/<a\s+href="(?<href>[^"]+)"(?:\s+target="(?<target>[^"]+)")?\s*>(?<text>[^<]+)<\/a>/,D_=/^[a-zA-Z][a-zA-Z\d+\-.]*:/,O_=`{version}`;function k_(e,t){return e?e.toLowerCase().includes(t):!1}function A_(e){let t=e.trim();if(!t)return null;let n=t.toLowerCase();return!D_.test(n)||n.startsWith(`http:`)||n.startsWith(`https:`)?t:null}function j_(e,t,n,r){return e===`browser.unsupported`?r.browserUnsupportedDynamic?M_(r.browserUnsupportedDynamic,t,n):k_(t,`safari`)?r.browserUnsupportedSafari:k_(t,`firefox`)?r.browserUnsupportedFirefox:r.browserUnsupported:r.browserUnsupported}function M_(e,t,n){let r=`This browser`;t&&t.trim().length>0&&(r=t);let i=e.replace(`{browser}`,r);return n&&n.trim().length>0&&n?(i=i.replace(O_,n),i):(i=i.replace(` ({version})`,``),i=i.replace(O_,``),i)}function N_(e){let t=E_.exec(e);if(!t?.groups)return{prefix:e,linkText:null,linkHref:null,linkTarget:null,suffix:``};let n=t.index,r=n+t[0].length,i=e.slice(0,n),a=e.slice(r),o=A_(t.groups.href);if(!o)return{prefix:i+t.groups.text+a,linkText:null,linkHref:null,linkTarget:null,suffix:``};let s=null;return t.groups.target&&(s=t.groups.target),{prefix:i,linkText:t.groups.text,linkHref:o,linkTarget:s,suffix:a}}function P_(){let e=Ot(),t=null;e.name.length>0&&(t=e.name);let n=null;return e.version.length>0&&(n=e.version),{browserName:t,browserVersion:n}}function F_(e){let t=t=>{if(!(`code`in t))return;let n=t;if(n.code!==`browser.unsupported`)return;let r=P_(),i=r.browserName;n.browserName&&n.browserName.length>0&&(i=n.browserName);let a=r.browserVersion;n.browserVersion&&n.browserVersion.length>0&&(a=n.browserVersion),e.updateState({errorCode:`browser.unsupported`,browserName:i,browserVersion:a})};return{recording:{onStateChange:t=>{e.updateState({recordingState:t}),t===`idle`&&(e.isProcessingBlob=!1)},onCountdownUpdate:(t,n)=>{e.updateState({recordingState:t,countdown:n})},onTimerUpdate:t=>{e.updateState({timer:t})},onError:n=>{t(n),e.updateState({error:i(n)})},onRecordingComplete:t=>{e.updateState({countdown:null}),e.processRecordingBlob(t).catch(t=>{e.updateState({error:i(t)})})},onClearUploadStatus:()=>{e.updateState({uploadProgress:null})},onStopAudioTracking:()=>{},onGetConfig:()=>{if(!e.controller)throw Error(`Controller not initialized`);return e.isDemo?Promise.resolve(Vt(`mp4`)):e.controller.getConfig()}},sourceSwitch:{onSourceChange:e=>Promise.resolve(),onPreviewUpdate:t=>(e.updateState({stream:t}),Promise.resolve()),onError:n=>{t(n),e.updateState({error:i(n)})},onTransitionStart:t=>{e.updateState({transitionMessage:t})},onTransitionEnd:()=>{e.updateState({transitionMessage:null})}},storage:{onUploadProgress:()=>{},onUploadComplete:()=>{},onUploadError:()=>{}},onStorageCleanupError:t=>{e.updateState({error:t})}}}function I_(e,t){let n=(e=>e===``||e===`default`?null:e)(t);return e.setCameraDevice(n),e.switchVideoDevice(n)}function L_(e,t){let n=(e=>e===``||e===`default`?null:e)(t);return e.setMicDevice(n),e.switchAudioDevice(n)}async function R_(e,t=`camera`){e.isActive()||await e.startStream(),t!==e.getCurrentSourceType()&&await e.switchSource(t),await e.startRecording()}async function z_(e,t,n,r){return await e.stopRecording()}function B_(e){e.pauseRecording()}function V_(e){e.resumeRecording()}async function H_(e,t){await e.switchSource(t)}let U_=`camera`,W_=`screen`,G_=`recording`,K_=`browser.unsupported`,q_=[.8,1.2,.9];function J_(e,t){let{uploadProgress:n,uploadingLabel:r}=e,{overlay:i,fill:a,text:o}=t;if(!i)return;if(n===null){i.style.display=`none`;return}i.style.display=`block`;let s=Math.round(n*100);a&&(a.style.width=`${s}%`),o&&(o.textContent=`${r} ${s}%`)}function Y_(e,t){let{transitionMessage:n}=e,{overlay:r,message:i}=t;if(r){if(!n){r.classList.remove(`vidtreo-active`);return}r.classList.add(`vidtreo-active`),i&&(i.textContent=n)}}function X_(e,t){e.textContent=``;let n=document.createTextNode(t.prefix);if(e.append(n),t.linkText&&t.linkHref){let n=document.createElement(`a`),r=t.linkTarget;n.href=t.linkHref,r&&(n.target=r),r===`_blank`&&(n.rel=`noopener noreferrer`),n.textContent=t.linkText,e.append(n)}let r=document.createTextNode(t.suffix);e.append(r)}function Z_(e){let{stream:t,transitionMessage:n,isVideoLoaded:r}=e;return{showPreviewSkeleton:!!t&&!r&&!n,showVideoPreview:!!t}}function Q_(e,t){let{previewSkeleton:n,videoPreview:r}=t;n&&(e.showPreviewSkeleton?n.style.display=`block`:n.style.display=`none`),r&&(e.showVideoPreview?r.style.display=`block`:r.style.display=`none`)}function $_(e,t,n){let{videoPreview:r}=t,{onVideoLoaded:a,onError:o,startAudioAnalysis:s,stopAudioAnalysis:c}=n;if(r){if(!e){r.srcObject=null,c();return}r.srcObject=e,r.onloadeddata=()=>{a()},r.play().catch(e=>o(i(e))),s(e)}}function ev(e){return{startCameraArea:e.querySelector(`#startCameraArea`),cameraIcon:e.querySelector(`#startCameraArea .vidtreo-camera-icon`),cameraText:e.querySelector(`#startCameraArea .vidtreo-camera-text`),cameraHint:e.querySelector(`#startCameraArea .vidtreo-camera-hint`),previewSkeleton:e.querySelector(`#previewSkeleton`),previewSkeletonText:e.querySelector(`#previewSkeleton .vidtreo-skeleton-text`),videoPreview:e.querySelector(`#videoPreview`),countdownOverlay:e.querySelector(`#countdownOverlay`),countdownNumber:e.querySelector(`#countdownNumber`),recordingTimerRow:e.querySelector(`#recordingTimerRow`),recordingTimer:e.querySelector(`#recordingTimer`),recIndicatorTop:e.querySelector(`#recIndicatorTop`),audioLevelBars:e.querySelector(`#audioLevelBars`)}}function tv(e,t,n){if(e.stream)return{shouldShow:!1,iconClassName:``,browserErrorContent:null,textContent:null,hintText:null};let r=e.errorCode===K_,i=`ph-fill ph-camera`;r&&(i=`ph-fill ph-warning-circle`);let a=null,o=null;r&&(a=N_(n)),r||(o=t.initializingCamera);let s=null;return r||(s=t.grantPermissions),{shouldShow:!0,iconClassName:i,browserErrorContent:a,textContent:o,hintText:s}}function nv(e,t){let n=!1;return e&&(n=!0),{shouldShow:n,text:t.switchingDevice}}function rv(e,t,n){let r=!1;return e===`countdown`&&t!==null&&(r=!0),{shouldShow:r,countdown:t,text:n.recordingStartsIn}}function iv(e,t){return{shouldShow:e,text:t.rec}}function av(e,t){return{shouldShow:e,timer:t}}function ov(e){return{shouldShow:e}}function sv(e,t){let{state:n,isVideoLoaded:r,isRecording:i,translations:a}=e;cv(tv(n,a,j_(n.errorCode,n.browserName,n.browserVersion,{browserUnsupported:a.browserUnsupported,browserUnsupportedDynamic:a.browserUnsupportedDynamic,browserUnsupportedSafari:a.browserUnsupportedSafari,browserUnsupportedFirefox:a.browserUnsupportedFirefox})),t),lv(nv(n.transitionMessage,a),t),Q_(Z_({stream:n.stream,transitionMessage:n.transitionMessage,isVideoLoaded:r}),{previewSkeleton:t.previewSkeleton,videoPreview:t.videoPreview}),uv(rv(n.recordingState,n.countdown,a),t),dv(iv(i,a),t),fv(av(i,n.timer),t),pv(ov(i),t)}function cv(e,t){let{startCameraArea:n,cameraIcon:r,cameraText:i,cameraHint:a}=t;if(n){if(!e.shouldShow){n.style.display=`none`;return}n.style.display=`block`,r&&(r.innerHTML=`<i class="${e.iconClassName}" style="font-size: 48px;"></i>`),i&&(e.browserErrorContent&&X_(i,e.browserErrorContent),e.textContent&&(i.textContent=e.textContent)),a&&(e.hintText?(a.textContent=e.hintText,a.style.display=`block`):a.style.display=`none`)}}function lv(e,t){let{previewSkeleton:n,previewSkeletonText:r}=t;n&&(e.shouldShow?n.style.display=`block`:n.style.display=`none`,r&&(r.textContent=e.text))}function uv(e,t){let{countdownOverlay:n,countdownNumber:r}=t;n&&(e.shouldShow?n.classList.add(`vidtreo-active`):n.classList.remove(`vidtreo-active`),r&&e.countdown!==null&&(r.textContent=e.countdown.toString()))}function dv(e,t){let{recIndicatorTop:n}=t;n&&(e.shouldShow?n.style.display=`block`:n.style.display=`none`)}function fv(e,t){let{recordingTimerRow:n,recordingTimer:r}=t;n&&(e.shouldShow?n.style.display=`flex`:n.style.display=`none`,r&&(r.textContent=e.timer))}function pv(e,t){let{audioLevelBars:n}=t;n&&(e.shouldShow?n.style.display=`flex`:n.style.display=`none`)}let mv=`inline-flex`;function hv(e){let{stream:t,buttonVisibility:n,currentSourceType:r,isMuted:i,recordingState:a,buttonTranslations:o}=e,s=!!t,c=a===`idle`&&s,l=!1;(n.showPauseButton||n.showResumeButton)&&(l=!0);let u=o.pause,d=`ph-fill ph-pause`;n.showResumeButton&&(u=o.resume,d=`ph-fill ph-play`);let f=o.mute,p=`ph-fill ph-microphone`;i&&(f=o.unmute,p=`ph-fill ph-microphone-slash`);let m=`ph-fill ph-monitor`;r!==U_&&(m=`ph-fill ph-camera`);let h=!1;return n.showDownloadButton&&(h=!0),{showRecordingControls:s,showSettingsButton:n.showSettingsButton,showRecordButton:c,showMuteButton:n.showMuteButton,showPauseButton:l,showStopButton:n.showStopButton,showSwitchSourceButton:n.showSwitchSourceButton,showDownloadButton:h,pauseTitle:u,pauseIconClassName:d,muteTitle:f,muteIconClassName:p,switchSourceIconClassName:m,isMuted:i,settingsTitle:o.settings,switchSourceTitle:o.switchSource,downloadTitle:o.download}}function gv(e){return{recordingControls:e.querySelector(`#recordingControls`),settingsButton:e.querySelector(`#btnSettings`),recordButton:e.querySelector(`#btnRecord`),muteButton:e.querySelector(`#btnMute`),muteIcon:e.querySelector(`#iconMute`),pauseButton:e.querySelector(`#btnPause`),pauseIcon:e.querySelector(`#iconPause`),stopButton:e.querySelector(`#btnStop`),switchSourceButton:e.querySelector(`#btnSwitchSource`),switchSourceIcon:e.querySelector(`#iconSwitchSource`),downloadButton:e.querySelector(`#btnDownload`)}}function _v(e,t){let{recordingControls:n,settingsButton:r,recordButton:i,muteButton:a,muteIcon:o,pauseButton:s,pauseIcon:c,stopButton:l,switchSourceButton:u,switchSourceIcon:d,downloadButton:f}=t;yv(n,e),bv(r,e),xv(i,e),Sv(a,e),Cv(o,e),wv(s,e),Tv(c,e),Ev(l,e),Dv(u,e),Ov(d,e),kv(f,e)}function vv(e,t,n){e&&(t?e.style.display=n:e.style.display=`none`)}function yv(e,t){vv(e,t.showRecordingControls,`block`)}function bv(e,t){vv(e,t.showSettingsButton,mv),e&&(e.title=t.settingsTitle)}function xv(e,t){vv(e,t.showRecordButton,mv)}function Sv(e,t){vv(e,t.showMuteButton,mv),e&&(e.title=t.muteTitle,e.classList.toggle(`vidtreo-muted`,t.isMuted))}function Cv(e,t){e&&(e.className=t.muteIconClassName)}function wv(e,t){vv(e,t.showPauseButton,mv),e&&(e.title=t.pauseTitle)}function Tv(e,t){e&&(e.className=t.pauseIconClassName)}function Ev(e,t){vv(e,t.showStopButton,mv)}function Dv(e,t){vv(e,t.showSwitchSourceButton,mv),e&&(e.title=t.switchSourceTitle)}function Ov(e,t){e&&(e.className=t.switchSourceIconClassName)}function kv(e,t){vv(e,t.showDownloadButton,mv),e&&(e.title=t.downloadTitle)}function Av(e){let{stream:t,showSettings:n}=e,r=!1;return t&&n&&(r=!0),{shouldShow:r}}function jv(e,t,n){if(t){if(!e.shouldShow){t.classList.remove(`vidtreo-active`);return}t.classList.add(`vidtreo-active`),n()}}function Mv(e){return e.toggleMute(),e.getIsMuted()}function Nv(e){if(!e)return;let t=URL.createObjectURL(e),n=document.createElement(`a`);n.href=t,n.download=`recording-${Date.now()}.mp4`,document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(t)}let Pv={en:{initializingCamera:`Initializing camera...`,grantPermissions:`Grant camera and microphone permissions when prompted`,browserUnsupported:`This browser is not supported`,browserUnsupportedDynamic:`{browser} ({version}) is not supported, please use <a href="https://www.google.com/chrome/" target="_blank">Chrome</a>`,browserUnsupportedSafari:`Safari is not supported, please use <a href="https://www.google.com/chrome/" target="_blank">Chrome</a>`,browserUnsupportedFirefox:`Firefox is not supported, please use <a href="https://www.google.com/chrome/" target="_blank">Chrome</a>`,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...`,finishing:`Finishing...`,uploading:`Uploading...`,switchingCamera:`Switching camera...`,switchingMicrophone:`Switching microphone...`,failedToStartCamera:`Failed to start camera`,userInAnotherTab:`User in another tab`,download:`Download`,nativeCameraSelectVideo:`Select Video from Gallery`,nativeCameraRecordVideo:`Record with Camera`,errorTitle:`Configuration Error`,errorGeneric:`An error occurred while loading the configuration`,mobileOpenCamera:`Open Camera`,mobileOpenCameraTitle:`Record a Video`,mobileOpenCameraDescription:`Tap the button below to start recording`,mobileCloseCamera:`Close`,mobilePermissionDenied:`Camera Access Denied`,mobilePermissionDeniedDescription:`Please allow camera access in your browser settings to record video.`},es:{initializingCamera:`Inicializando cámara...`,grantPermissions:`Otorga permisos de cámara y micrófono cuando se solicite`,browserUnsupported:`Este navegador no es compatible`,browserUnsupportedDynamic:`{browser} ({version}) no es compatible, por favor usa <a href="https://www.google.com/chrome/" target="_blank">Chrome</a>`,browserUnsupportedSafari:`Safari no es compatible, usa <a href="https://www.google.com/chrome/" target="_blank">Chrome</a>`,browserUnsupportedFirefox:`Firefox no es compatible, usa <a href="https://www.google.com/chrome/" target="_blank">Chrome</a>`,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...`,finishing:`Finalizando...`,uploading:`Subiendo...`,switchingCamera:`Cambiando cámara...`,switchingMicrophone:`Cambiando micrófono...`,failedToStartCamera:`Error al iniciar la cámara`,userInAnotherTab:`Usuario en otra pestaña`,download:`Descargar`,nativeCameraSelectVideo:`Seleccionar Video de la Galería`,nativeCameraRecordVideo:`Grabar con Cámara`,errorTitle:`Error de Configuración`,errorGeneric:`Ocurrió un error al cargar la configuración`,mobileOpenCamera:`Abrir Cámara`,mobileOpenCameraTitle:`Grabar un Video`,mobileOpenCameraDescription:`Toca el botón para comenzar a grabar`,mobileCloseCamera:`Cerrar`,mobilePermissionDenied:`Acceso a Cámara Denegado`,mobilePermissionDeniedDescription:`Por favor permite el acceso a la cámara en la configuración de tu navegador para grabar video.`}};var Fv=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]:(Pv[this.lang]||Pv.en)[e]}getAll(){return{...Pv[this.lang]||Pv.en,...this.customTexts}}};let Iv=new Map;function Lv(e){e.style.position=`fixed`,e.style.top=`0`,e.style.left=`0`,e.style.width=`100vw`,e.style.height=`100vh`,e.style.height=`100dvh`,e.style.zIndex=`9999`,e.style.pointerEvents=`none`}function Rv(e){e.style.pointerEvents=`auto`}function zv(e){e.style.pointerEvents=`none`}var Bv=class{constructor(e=`vidtreo-portal-root`){this.portalContainer=null,this.contentWrapper=null,this.isRegistered=!1,this.containerId=e,this.instanceId=`portal-${Date.now()}-${Math.random().toString(36).slice(2,9)}`}get container(){return this.contentWrapper}get isActive(){return this.contentWrapper!==null&&this.portalContainer!==null}open(){let e=document.getElementById(this.containerId);return e||(e=document.createElement(`div`),e.id=this.containerId,Lv(e),document.body.appendChild(e)),this.portalContainer=e,this.contentWrapper=document.createElement(`div`),this.contentWrapper.setAttribute(`data-portal-instance`,this.instanceId),this.contentWrapper.style.width=`100%`,this.contentWrapper.style.height=`100%`,this.portalContainer.appendChild(this.contentWrapper),this.registerInstance(),Rv(e),this.contentWrapper}render(e){this.contentWrapper&&(this.contentWrapper.innerHTML=e)}querySelector(e){return this.contentWrapper?this.contentWrapper.querySelector(e):null}close(){this.contentWrapper&&=(this.contentWrapper.innerHTML=``,this.contentWrapper.remove(),null),this.unregisterInstance(),this.updatePortalContainerState()}destroy(){this.close(),this.portalContainer=null}registerInstance(){if(this.isRegistered)return;let e=Iv.get(this.containerId);e||(e=new Set,Iv.set(this.containerId,e)),e.add(this),this.isRegistered=!0}unregisterInstance(){if(!this.isRegistered)return;let e=Iv.get(this.containerId);e&&(e.delete(this),e.size===0&&Iv.delete(this.containerId)),this.isRegistered=!1}updatePortalContainerState(){if(!this.portalContainer)return;let e=Iv.get(this.containerId);e&&e.size>0?Rv(this.portalContainer):(zv(this.portalContainer),this.portalContainer.childNodes.length===0&&this.portalContainer.remove())}},Vv=class{constructor(e){this.state={isModalOpen:!1,permissionRequested:!1,prevUploading:!1},this.escapeHandler=null,this.initCheckInterval=null,this.callbacks=e,this.portalManager=new Bv}get canCloseModal(){let{recordingState:e}=this.callbacks.getState();return!(e===`recording`||e===`countdown`)}get isModalOpen(){return this.state.isModalOpen}get portal(){return this.portalManager}openModal(){this.state.isModalOpen=!0,this.state.permissionRequested=!1,this.portalManager.open(),document.body.style.overflow=`hidden`,this.setupEscapeHandler(),this.callbacks.renderMobile(),this.requestCameraPreview()}closeModal(){this.canCloseModal&&(this.callbacks.stopPreview(),this.state.isModalOpen=!1,this.state.permissionRequested=!1,document.body.style.overflow=``,this.removeEscapeHandler(),this.portalManager.close(),this.callbacks.renderMobile())}checkUploadCompletion(e){let t=this.state.prevUploading,n=e!==null;this.state.prevUploading=n,t&&!n&&this.state.isModalOpen&&this.closeModal()}requestCameraPreview(){if(this.state.permissionRequested)return;let e=()=>{this.callbacks.isInitialized()?(this.state.permissionRequested=!0,this.callbacks.startPreview().catch(()=>{})):this.initCheckInterval=setTimeout(e,100)};e()}setupEscapeHandler(){this.escapeHandler=e=>{e.key===`Escape`&&this.canCloseModal&&this.closeModal()},document.addEventListener(`keydown`,this.escapeHandler)}removeEscapeHandler(){this.escapeHandler&&=(document.removeEventListener(`keydown`,this.escapeHandler),null)}destroy(){this.removeEscapeHandler(),this.portalManager.destroy(),document.body.style.overflow=``,this.initCheckInterval&&=(clearTimeout(this.initCheckInterval),null)}},Hv=class{constructor(e,t){this.state={file:null,transcodingProgress:null,uploadProgress:null,isTranscoding:!1,isConfigLoading:!0,error:null,transcodedBlob:null},this.handler=null,this.config=e,this.callbacks=t;let n=e.backendUrl||`https://core.vidtreo.com`,r=null;e.apiKey&&!e.demo&&(r=bm.getInstance({apiKey:e.apiKey,backendUrl:n}));let i=new pg;this.handler=new Nm({apiKey:e.apiKey,backendUrl:n,maxRecordingTime:e.maxRecordingTime,maxFileSize:e.maxFileSize,userMetadata:e.userMetadata},r,i),e.apiKey&&!e.demo?(this.updateState({isConfigLoading:!0}),this.handler.preloadConfig().then(()=>this.updateState({isConfigLoading:!1})).catch(()=>{this.updateState({isConfigLoading:!1,error:`Failed to load settings`})})):this.updateState({isConfigLoading:!1})}updateState(e){this.state={...this.state,...e},this.callbacks.onStateChange()}getState(){return this.state}async handleFileSelect(e){if(this.updateState({error:null}),!this.handler)throw Error(`Handler not initialized`);try{let t=await this.handler.handleFileSelection(e);return this.updateState({file:t}),t}catch(e){let t=i(e),n=e instanceof Error?e:Error(t);throw this.updateState({error:t}),this.callbacks.onError?.(n),n}}async processAndUpload(e){let t=e||this.state.file;if(!(t&&this.handler))return;let n=this.config.demo;try{if(this.updateState({isTranscoding:!0,transcodingProgress:0,error:null}),n){let e=await jm(t.file,Bt,e=>{this.updateState({transcodingProgress:e}),this.callbacks.onTranscodingProgress?.(e)});this.updateState({transcodedBlob:e.blob,isTranscoding:!1,transcodingProgress:null})}else{let e=await this.handler.processAndUpload(e=>{this.updateState({transcodingProgress:e}),this.callbacks.onTranscodingProgress?.(e)},e=>{this.updateState({uploadProgress:e}),this.callbacks.onUploadProgress?.(e)});this.updateState({file:null,transcodingProgress:null,uploadProgress:null,isTranscoding:!1}),this.callbacks.onUploadComplete?.({recordingId:e.recordingId||``,uploadUrl:e.uploadUrl||``})}}catch(e){let t=i(e),r=e instanceof Error?e:Error(t);this.updateState({error:t,isTranscoding:!1,transcodingProgress:null,uploadProgress:null,transcodedBlob:null}),this.callbacks.onError?.(r),n||this.callbacks.onUploadError?.(r)}}downloadVideo(){if(!this.state.transcodedBlob)return;let e=URL.createObjectURL(this.state.transcodedBlob),t=document.createElement(`a`);t.href=e,t.download=`recording-${Date.now()}.mp4`,document.body.appendChild(t),t.click(),document.body.removeChild(t),URL.revokeObjectURL(e)}reset(){this.updateState({file:null,transcodingProgress:null,uploadProgress:null,error:null,isTranscoding:!1,transcodedBlob:null})}destroy(){this.handler&&this.handler.cancel(),this.handler=null}};function Uv(e){return{preview:{initializingCamera:e.initializingCamera,grantPermissions:e.grantPermissions,browserUnsupported:e.browserUnsupported,browserUnsupportedDynamic:e.browserUnsupportedDynamic,browserUnsupportedSafari:e.browserUnsupportedSafari,browserUnsupportedFirefox:e.browserUnsupportedFirefox,switchingDevice:e.switchingDevice,recordingStartsIn:e.recordingStartsIn,rec:e.rec},buttons:{settings:e.settings,record:e.record,stop:e.stop,pause:e.pause,resume:e.resume,mute:e.mute,unmute:e.unmute,switchSource:e.switchSource,download:e.download},settings:{settings:e.settings,camera:e.camera,microphone:e.microphone}}}var Wv=class{constructor(e){if(this.proxyEndpoint=e.proxyEndpoint,this.proxyEndpoint)throw Error(`Proxy mode not yet implemented`);this.service=new pg}uploadVideo(e,t){if(this.proxyEndpoint)throw Error(`Proxy mode not yet implemented`);return this.service.uploadVideo(e,t)}},Gv=`:root{--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% 0%;--vidtreo-z-modal-overlay:9999;--vidtreo-z-settings-panel:200;--vidtreo-z-error-overlay:100;--vidtreo-z-countdown-overlay:20;--vidtreo-z-progress-overlay:20;--vidtreo-z-controls:10}.vidtreo-preview-container{aspect-ratio:9/16;background:hsl(var(--vidtreo-preview-bg));contain:layout style;will-change:auto;backface-visibility:hidden;isolation:isolate;border:none;border-radius:0;justify-content:center;align-items:center;width:100%;display:flex;position:relative;overflow:visible;transform:translateZ(0)}.vidtreo-preview-container:before{display:none}@media (width>=768px){.vidtreo-preview-container{aspect-ratio:16/9}}.vidtreo-camera-area{contain:layout style paint;backface-visibility:hidden;isolation:isolate;will-change:auto;width:100%;height:100%;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;display:none;position:relative;transform:translateZ(0)}.vidtreo-source-transition-overlay{z-index:var(--vidtreo-z-error-overlay);backdrop-filter:blur(4px);contain:layout style paint;backface-visibility:hidden;will-change:opacity;background:#000000b3;border-radius:0;flex-direction:column;justify-content:center;align-items:center;transition:opacity .3s;display:none;position:absolute;inset:0;transform:translateZ(0)}.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{z-index:var(--vidtreo-z-controls);contain:layout style paint;backface-visibility:hidden;will-change:auto;background:#000;border-radius:0;flex-direction:column;justify-content:center;align-items:center;gap:1rem;display:flex;position:absolute;inset:0;transform:translateZ(0)}.vidtreo-skeleton-spinner{border:4px solid #ffffff4d;border-top-color:#fff;border-radius:50%;width:40px;height:40px;animation:.8s linear infinite vidtreo-spin}.vidtreo-skeleton-text{color:#fff;font-size:.875rem;font-weight:500}.vidtreo-video-preview{object-fit:contain;will-change:auto;backface-visibility:hidden;background:#000;border-radius:0;width:100%;height:100%;transition:opacity .3s,transform .3s;display:block;position:absolute;inset:0;transform:translateZ(0)}.vidtreo-video-preview-skeleton{z-index:2;contain:layout style paint;backface-visibility:hidden;will-change:auto;background:#000;border-radius:0;width:100%;height:100%;position:absolute;inset:0;overflow:hidden;transform:translateZ(0)}.vidtreo-skeleton-shimmer{background:linear-gradient(90deg, hsl(var(--vidtreo-muted)) 0%, hsl(var(--vidtreo-muted) / .5) 50%, hsl(var(--vidtreo-muted)) 100%);background-size:200% 100%;animation:1.5s ease-in-out infinite vidtreo-shimmer;position:absolute;inset:0}@keyframes vidtreo-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.vidtreo-video-preview-skeleton.vidtreo-hidden{opacity:0;pointer-events:none;transition:opacity .3s}.vidtreo-video-preview.vidtreo-screen-share{object-fit:cover}.vidtreo-video-preview.vidtreo-transitioning{opacity:.5;transform:scale(.98)}.vidtreo-countdown-overlay{z-index:var(--vidtreo-z-countdown-overlay);contain:layout style paint;backface-visibility:hidden;will-change:auto;background:#000000f2;border-radius:0;justify-content:center;align-items:center;display:none;position:absolute;inset:0;transform:translateZ(0)}.vidtreo-countdown-overlay.vidtreo-active{display:flex}.vidtreo-countdown-content{flex-direction:column;align-items:center;gap:1rem;display:flex}.vidtreo-countdown-number{color:#fff;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:#fff;margin-top:1rem;font-size:.875rem;font-weight:500}.vidtreo-settings-panel{z-index:var(--vidtreo-z-settings-panel);contain:layout style paint;backface-visibility:hidden;background:#0006;border:none;border-radius:.75rem;flex-direction:column;width:90%;margin-left:-47%;padding:.625rem;display:none;position:absolute;bottom:4rem;left:50%;overflow:hidden;transform:translateZ(0)}.vidtreo-settings-panel.vidtreo-active{display:flex}.vidtreo-settings-content{will-change:transform;backface-visibility:hidden;flex-direction:column;width:100%;display:flex;transform:translateZ(0)}.vidtreo-settings-content.vidtreo-slide-right{animation:.3s vidtreo-slideRight}.vidtreo-settings-content.vidtreo-slide-left{animation:.3s vidtreo-slideLeft}.vidtreo-settings-content.vidtreo-slide-none{will-change:auto;animation:none}@keyframes vidtreo-slideIn{0%{opacity:0;transform:translateY(1rem)}to{opacity:1;transform:translateY(0)}}@keyframes vidtreo-slideRight{0%{opacity:0;transform:translate(-100%)}to{opacity:1;transform:translate(0)}}@keyframes vidtreo-slideLeft{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}.vidtreo-settings-header{color:#fff;cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:.75rem;width:100%;margin-bottom:1rem;padding:0;display:flex}.vidtreo-settings-back-icon{color:#fff;flex-shrink:0}.vidtreo-settings-title{color:#fff;margin:0;font-size:.875rem;font-weight:600}.vidtreo-device-options-container{flex-direction:column;gap:.375rem;display:flex}.vidtreo-device-option-nav{cursor:pointer;color:#fff;background:0 0;border:none;border-radius:.5rem;align-items:center;gap:1rem;width:100%;padding:.5rem .75rem;transition:background-color .2s;display:flex}.vidtreo-device-option-nav:hover{background:#fff3}.vidtreo-device-option-nav-content{flex-shrink:0;align-items:center;gap:.75rem;display:flex}.vidtreo-device-option-nav-label{color:#fff;font-size:.875rem;font-weight:500}.vidtreo-device-option-nav-value{flex:1;justify-content:flex-end;align-items:center;gap:.5rem;min-width:0;display:flex}.vidtreo-device-option-nav-value-text{color:#fffc;text-overflow:ellipsis;white-space:nowrap;text-align:right;flex:1;font-size:.875rem;overflow:hidden}.vidtreo-device-option-nav-chevron{color:#fff;font-size:1.25rem;line-height:1}.vidtreo-device-list{flex-direction:column;gap:0;max-height:200px;display:flex;overflow-y:auto}.vidtreo-device-list::-webkit-scrollbar{width:4px}.vidtreo-device-list::-webkit-scrollbar-track{background:0 0}.vidtreo-device-list::-webkit-scrollbar-thumb{background:#fff3;border-radius:2px}.vidtreo-device-list::-webkit-scrollbar-thumb:hover{background:#ffffff4d}.vidtreo-device-option{cursor:pointer;color:#fff;text-align:left;background:0 0;border:none;border-radius:.5rem;align-items:center;gap:.75rem;width:100%;padding:.5rem .75rem;transition:background-color .2s;display:flex}.vidtreo-device-option:hover{background:#fff3}.vidtreo-device-option-check-container{flex-shrink:0;justify-content:center;align-items:center;width:20px;height:20px;display:flex}.vidtreo-device-checkmark-placeholder{flex-shrink:0;width:20px;height:20px}.vidtreo-device-checkmark{color:#fff;flex-shrink:0}.vidtreo-device-option-label{color:#fff;flex:1;font-size:.875rem}.vidtreo-device-empty{color:#fff9;text-align:center;padding:1rem 0;font-size:.875rem}.vidtreo-audio-level-bars{height:1rem;z-index:var(--vidtreo-z-controls);contain:layout style paint;will-change:auto;backface-visibility:hidden;align-items:center;gap:.125rem;display:flex;position:absolute;bottom:.75rem;right:.75rem;transform:translateZ(0)}@media (width>=768px){.vidtreo-audio-level-bars{height:1.25rem}}.vidtreo-audio-level-bar{background:#ffffff80;border-radius:9999px;align-self:flex-end;width:.125rem;transition:all .1s}.vidtreo-recording-controls{z-index:var(--vidtreo-z-controls);contain:layout style;will-change:auto;backface-visibility:hidden;position:absolute;left:50%;transform:translate(-50%)translateZ(0);bottom:12px!important}.vidtreo-recording-controls-row{will-change:auto;justify-content:center;align-items:center;gap:.5rem;display:flex;transform:translateZ(0)}.vidtreo-recording-timer-row{justify-content:space-between;align-items:center;gap:.5rem;display:flex}.vidtreo-recording-timer-badge{z-index:var(--vidtreo-z-controls);contain:layout style paint;will-change:auto;backface-visibility:hidden;background:#0000004d;border:none;border-radius:9999px;align-items:center;gap:.375rem;padding:.25rem .5rem;display:flex;position:absolute;top:.75rem;right:.75rem;transform:translateZ(0);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:#fff;font-family:monospace;font-size:.75rem;font-weight:500}.vidtreo-control-buttons-row{will-change:auto;justify-content:center;align-items:center;gap:.375rem;height:auto;min-height:2rem;display:flex;transform:translateZ(0)}@media (width>=768px){.vidtreo-control-buttons-row{min-height:2.25rem}}.vidtreo-control-button{cursor:pointer;color:#fff;box-sizing:border-box;vertical-align:top;contain:layout style paint;will-change:auto;backface-visibility:hidden;background:#0000004d;border:none;border-radius:9999px;flex-shrink:0;justify-content:center;align-items:center;width:2rem;height:2rem;min-height:2rem;max-height:2rem;margin:0;padding:.25rem;transition:background-color .2s;display:inline-flex;position:relative;transform:translateZ(0)}.vidtreo-control-button:before{content:"";z-index:0;border-radius:9999px;transition:background-color .2s;position:absolute;inset:.25rem}.vidtreo-control-button svg{color:inherit;z-index:1;flex-shrink:0;position:relative;width:22px!important;height:22px!important}@media (width>=768px){.vidtreo-control-button svg{width:24px!important;height:24px!important}.vidtreo-control-button{width:2.25rem;height:2.25rem;min-height:2.25rem;max-height:2.25rem}}.vidtreo-control-button:hover:not(:disabled):before{background:#fff3}.vidtreo-control-button:disabled{opacity:.5;cursor:not-allowed}.vidtreo-control-button.vidtreo-muted:before{background:#0000004d}.vidtreo-control-button.vidtreo-muted:hover:not(:disabled):before{background:#fff3}.vidtreo-record-button{background:hsl(var(--vidtreo-destructive));height:2rem;min-height:2rem;max-height:2rem;color:hsl(var(--vidtreo-destructive-foreground));box-sizing:border-box;vertical-align:top;cursor:pointer;border:none;border-radius:9999px;flex-shrink:0;justify-content:center;align-items:center;gap:.375rem;width:auto;margin:0;padding:0 .75rem;font-size:.75rem;font-weight:500;line-height:1;transition:background-color .2s,filter .2s;display:inline-flex}@media (width>=768px){.vidtreo-record-button{height:2.25rem;min-height:2.25rem;max-height:2.25rem;font-size:.875rem}}.vidtreo-record-button:hover:not(:disabled){filter:brightness(.85)}#startButton.vidtreo-record-button{animation:2s ease-in-out infinite vidtreo-record-glow-pulse}@keyframes vidtreo-record-glow-pulse{0%,to{box-shadow:0 0 8px 2px #ef444466,0 0 16px 4px #ef444433}50%{box-shadow:0 0 16px 4px #ef444499,0 0 32px 8px #ef44444d}}#startButton.vidtreo-record-button:hover:not(:disabled){animation-play-state:paused;box-shadow:0 0 20px 6px #ef4444b3,0 0 40px 10px #ef444459}.vidtreo-rec-indicator-top{contain:layout style paint;will-change:auto;backface-visibility:hidden;background:#0000004d;border:none;border-radius:9999px;align-items:center;gap:.375rem;padding:.25rem .5rem;display:flex;position:absolute;top:.75rem;left:.75rem;transform:translateZ(0);box-shadow:0 1px 3px #0000001a,0 1px 2px -1px #0000001a}.vidtreo-rec-indicator-top span{color:#fff;font-size:.75rem;font-weight:500}.vidtreo-start-camera-area{text-align:center;cursor:pointer;z-index:1;contain:layout style paint;backface-visibility:hidden;will-change:auto;background:#000;border:none;border-radius:0;flex-direction:column;justify-content:center;align-items:center;padding:40px;transition:all .3s;display:flex;position:absolute;inset:0;transform:translateZ(0)}.vidtreo-start-camera-area:hover:not(.vidtreo-loading){background:#000}.vidtreo-start-camera-area.vidtreo-loading{cursor:wait;opacity:.7}.vidtreo-start-camera-area.vidtreo-loading .vidtreo-camera-text{color:#fff;opacity:.7}.vidtreo-camera-icon{color:#fff;justify-content:center;margin-bottom:16px;font-size:48px;display:flex}.vidtreo-camera-text{color:#fff;margin-bottom:8px;font-weight:600}.vidtreo-camera-text a{color:#3b82f6;text-decoration:underline}.vidtreo-camera-text a:hover{color:#2563eb}.vidtreo-camera-hint{color:#fff;opacity:.8;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:#fff;font-size:14px}.vidtreo-error{color:#fff;text-align:center;z-index:var(--vidtreo-z-error-overlay);word-wrap:break-word;background:#dc2626;border:none;border-radius:.5rem;max-width:90%;padding:1rem 1.25rem;font-size:.875rem;font-weight:500;display:none;position:absolute;top:.75rem;left:50%;transform:translate(-50%);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.vidtreo-error.vidtreo-active{animation:.3s ease-out vidtreo-error-fade-in-slide-down;display:block}@keyframes vidtreo-error-fade-in-slide-down{0%{opacity:0;transform:translate(-50%)translateY(-1rem)}to{opacity:1;transform:translate(-50%)translateY(0)}}.vidtreo-upload-progress{margin-top:20px;display:none}.vidtreo-upload-progress.vidtreo-active{display:block}.vidtreo-preview-container .vidtreo-upload-progress{margin-top:0}.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}.vidtreo-preview-error{aspect-ratio:9/16;background:hsl(var(--vidtreo-preview-bg));contain:strict;will-change:auto;backface-visibility:hidden;isolation:isolate;border:none;border-radius:0;justify-content:center;align-items:center;width:100%;display:flex;position:relative;overflow:hidden;transform:translateZ(0)}@media (width>=768px){.vidtreo-preview-error{aspect-ratio:16/9}}.vidtreo-error-content{text-align:center;color:#fff;flex-direction:column;justify-content:center;align-items:center;gap:1rem;max-width:400px;padding:2rem;display:flex}.vidtreo-error-icon{font-size:3rem;line-height:1}.vidtreo-error-title{font-size:1.25rem;font-weight:600;line-height:1.2}.vidtreo-error-message{opacity:.9;word-break:break-word;font-size:.875rem;line-height:1.5}.vidtreo-error-config{text-align:left;border-top:1px solid #fff3;width:100%;margin-top:1.5rem;padding-top:1.5rem}.vidtreo-error-config-title{color:#fff;margin-bottom:.75rem;font-size:.875rem;font-weight:600}.vidtreo-error-config-item{color:#ffffffd9;margin-bottom:.5rem;font-size:.8125rem;line-height:1.6}.vidtreo-error-config-item code{color:#fff;background:#ffffff26;border-radius:.25rem;padding:.125rem .375rem;font-family:monospace;font-size:.75rem}.vidtreo-error-retry{background:hsl(var(--vidtreo-destructive));color:hsl(var(--vidtreo-destructive-foreground));cursor:pointer;border:none;border-radius:.375rem;margin-top:.5rem;padding:.5rem 1rem;font-size:.875rem;font-weight:500;transition:filter .2s}.vidtreo-error-retry:hover:not(:disabled){filter:brightness(.85)}.vidtreo-error-retry:disabled{opacity:.5;cursor:not-allowed}.vidtreo-error-overlay{background:hsl(var(--vidtreo-preview-bg));z-index:var(--vidtreo-z-error-overlay);justify-content:center;align-items:center;display:flex;position:absolute;inset:0}.vidtreo-native-camera-container{aspect-ratio:9/16;background:hsl(var(--vidtreo-preview-bg));border-radius:0;justify-content:center;align-items:center;width:100%;display:flex;position:relative;overflow:hidden}@media (width>=768px){.vidtreo-native-camera-container{aspect-ratio:16/9}}.vidtreo-native-camera-container:has(.vidtreo-native-camera-preview-container){background:0 0}.vidtreo-config-loading-indicator{z-index:var(--vidtreo-z-controls);position:absolute;top:8px;right:8px}.vidtreo-spinner-small{border:2px solid #ffffff4d;border-top-color:#fff;border-radius:50%;width:16px;height:16px;animation:.6s linear infinite spin}.vidtreo-native-camera-empty-state{flex-direction:column;justify-content:center;align-items:center;gap:16px;width:100%;height:100%;padding:24px;display:flex;position:relative}.vidtreo-native-camera-buttons{flex-direction:column;gap:12px;width:100%;max-width:300px;display:flex}.vidtreo-native-camera-process-button,.vidtreo-native-camera-download-button{z-index:30;position:absolute;bottom:24px;left:50%;transform:translate(-50%)}.vidtreo-native-camera-process-button .vidtreo-btn,.vidtreo-native-camera-download-button .vidtreo-btn{min-width:200px}.vidtreo-btn{border-radius:var(--vidtreo-radius);cursor:pointer;border:none;padding:12px 24px;font-size:1rem;font-weight:500;transition:all .2s}.vidtreo-btn:disabled{opacity:.5;cursor:not-allowed}.vidtreo-btn-primary{background:hsl(var(--vidtreo-primary));color:hsl(var(--vidtreo-primary-foreground))}.vidtreo-btn-primary:hover:not(:disabled){filter:brightness(.9)}.vidtreo-btn-secondary{background:hsl(var(--vidtreo-secondary));color:hsl(var(--vidtreo-secondary-foreground));border:1px solid hsl(var(--vidtreo-border))}.vidtreo-btn-secondary:hover:not(:disabled){background:hsl(var(--vidtreo-accent))}.vidtreo-transcoding-progress{width:100%;max-width:400px;padding:16px}.vidtreo-progress-bar{background:#fff3;border-radius:4px;width:100%;height:8px;overflow:hidden}.vidtreo-progress-fill{background:hsl(var(--vidtreo-primary));height:100%;transition:width .3s}.vidtreo-progress-text{text-align:center;color:hsl(var(--vidtreo-foreground));margin-top:8px;font-size:.875rem}.vidtreo-native-camera-preview-container{background:0 0;justify-content:center;align-items:center;width:100%;height:100%;display:flex;position:relative}.vidtreo-native-camera-preview-image{object-fit:contain;width:100%;height:100%;display:block}.vidtreo-progress-overlay{backdrop-filter:blur(4px);width:100%;height:100%;z-index:var(--vidtreo-z-progress-overlay);pointer-events:none;background:#000000b3;flex-direction:column;justify-content:center;align-items:center;display:flex;position:absolute;inset:0}.vidtreo-progress-overlay .vidtreo-transcoding-progress,.vidtreo-progress-overlay .vidtreo-upload-progress{pointer-events:auto;background:0 0;flex-direction:column;align-items:center;gap:12px;width:90%;max-width:400px;padding:0;display:flex;position:relative}.vidtreo-progress-overlay .vidtreo-progress-bar,.vidtreo-progress-overlay .vidtreo-upload-progress-bar{background:#fff3;border-radius:4px;width:100%;height:8px;overflow:hidden}.vidtreo-progress-overlay .vidtreo-progress-fill{background:#fff;height:100%;transition:width .3s}.vidtreo-progress-overlay .vidtreo-progress-text,.vidtreo-progress-overlay .vidtreo-upload-progress-text{text-align:center;color:#fff;margin-top:0;font-size:.875rem;font-weight:500}.vidtreo-progress-overlay .vidtreo-upload-progress-bar{background:#fff3;border-radius:4px;width:100%;height:8px;overflow:hidden}.vidtreo-progress-overlay .vidtreo-upload-progress-fill{background:#fff;height:100%;transition:width .3s}.vidtreo-progress-overlay .vidtreo-progress-indeterminate{background:linear-gradient(90deg,#0000 0%,#fff 50%,#0000 100%) 0 0/200% 100%;width:100%;animation:1.5s ease-in-out infinite vidtreo-progress-indeterminate}@keyframes vidtreo-progress-indeterminate{0%{background-position:200% 0}to{background-position:-200% 0}}.vidtreo-mobile-web-recorder{width:100%;height:100%;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif}.vidtreo-mobile-landing-container{aspect-ratio:4/3;background:hsl(var(--vidtreo-preview-bg));border-radius:0;justify-content:center;align-items:center;width:100%;max-height:100%;display:flex;position:relative;overflow:hidden}.vidtreo-mobile-landing-content{text-align:center;flex-direction:column;justify-content:center;align-items:center;gap:1.25rem;padding:2rem;display:flex}.vidtreo-mobile-landing-title{color:#fff;margin:0;font-size:1.25rem;font-weight:600;line-height:1.3}.vidtreo-mobile-landing-description{color:#ffffffbf;max-width:280px;margin:0;font-size:.875rem;line-height:1.5}.vidtreo-mobile-open-camera-btn{border-radius:9999px;justify-content:center;align-items:center;gap:.625rem;min-width:200px;margin-top:.5rem;padding:.875rem 1.75rem;font-size:1rem;font-weight:600;transition:all .2s;animation:2s ease-in-out infinite vidtreo-btn-glow-pulse;display:inline-flex}@keyframes vidtreo-btn-glow-pulse{0%,to{box-shadow:0 0 8px 2px #ffffff4d,0 0 16px 4px #ffffff26}50%{box-shadow:0 0 16px 4px #ffffff80,0 0 32px 8px #ffffff40}}.vidtreo-mobile-open-camera-btn:hover:not(:disabled){animation-play-state:paused;transform:scale(1.02);box-shadow:0 0 20px 6px #fff9,0 0 40px 10px #ffffff4d}.vidtreo-mobile-open-camera-btn:active:not(:disabled){transform:scale(.98)}.vidtreo-mobile-open-camera-btn:disabled{box-shadow:none;animation:none}#vidtreo-portal-root{z-index:9999;pointer-events:none;width:100vw;height:100dvh;position:fixed;top:0;left:0}#vidtreo-portal-root>*{pointer-events:auto}.vidtreo-mobile-modal-overlay{width:100vw;height:100dvh;z-index:var(--vidtreo-z-modal-overlay);background:#000;flex-direction:column;height:-webkit-fill-available;animation:.3s ease-out vidtreo-modal-fade-in;display:flex;position:fixed;inset:0}@keyframes vidtreo-modal-fade-in{0%{opacity:0}to{opacity:1}}.vidtreo-mobile-modal-header{padding:.75rem;padding-top:calc(.75rem + env(safe-area-inset-top,0px));z-index:var(--vidtreo-z-error-overlay);pointer-events:none;justify-content:center;display:flex;position:absolute;top:0;left:0;right:0}.vidtreo-mobile-modal-close-btn{color:#ffffffe6;cursor:pointer;pointer-events:auto;backdrop-filter:blur(4px);background:#00000080;border:none;border-radius:9999px;justify-content:center;align-items:center;gap:.375rem;height:2rem;padding:0 .75rem;font-size:.75rem;font-weight:500;transition:all .2s;display:flex}.vidtreo-mobile-modal-close-btn:hover:not(:disabled){background:#000000b3}.vidtreo-mobile-modal-close-btn:disabled{opacity:.3;cursor:not-allowed}.vidtreo-mobile-modal-content{width:100%;height:100%;padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px);padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px);flex-direction:column;flex:1;display:flex;position:relative}.vidtreo-mobile-recorder-content{flex-direction:column;width:100%;height:100%;display:flex;position:relative}.vidtreo-mobile-recorder-content .vidtreo-preview-container{aspect-ratio:unset;flex:1;width:100%;height:100%}.vidtreo-mobile-recorder-content .vidtreo-video-preview{object-fit:cover}.vidtreo-mobile-preview{flex:1;aspect-ratio:unset!important;height:100%!important}.vidtreo-mobile-recorder-content .vidtreo-recording-controls{bottom:calc(24px + env(safe-area-inset-bottom,0px))}.vidtreo-mobile-recorder-content .vidtreo-audio-level-bars{bottom:calc(12px + env(safe-area-inset-bottom,0px))}.vidtreo-mobile-recorder-content .vidtreo-settings-panel{bottom:calc(7rem + env(safe-area-inset-bottom,0px))}.vidtreo-mobile-recorder-content .vidtreo-rec-indicator-top,.vidtreo-mobile-recorder-content .vidtreo-recording-timer-badge{top:calc(.75rem + env(safe-area-inset-top,0px));contain:layout style;height:2rem;padding:0 .75rem}.vidtreo-mobile-recorder-content .vidtreo-recording-timer-text{white-space:nowrap;color:#fff;min-width:3rem;font-size:.875rem;display:inline-block}.vidtreo-mobile-recorder-content .vidtreo-error{top:calc(3.5rem + env(safe-area-inset-top,0px))}.vidtreo-mobile-recorder-content .vidtreo-control-buttons-row{gap:.75rem;min-height:4rem}.vidtreo-mobile-recorder-content .vidtreo-control-button{width:4rem;height:4rem;min-height:4rem;max-height:4rem}.vidtreo-mobile-recorder-content .vidtreo-control-button svg{width:1.5rem;height:1.5rem}.vidtreo-mobile-recorder-content .vidtreo-record-button{gap:.5rem;height:4rem;min-height:4rem;max-height:4rem;padding:0 1.5rem;font-size:1rem}.vidtreo-mobile-recorder-content .vidtreo-record-button svg{width:1.5rem;height:1.5rem}`;function Kv(e){return`
9961
+ <style>${Gv}</style>
9873
9962
  <div class="vidtreo-mobile-landing-container">
9874
9963
  <div class="vidtreo-mobile-landing-content">
9875
9964
  <h2 class="vidtreo-mobile-landing-title">
@@ -9887,8 +9976,8 @@ new RecorderWorker;
9887
9976
  </button>
9888
9977
  </div>
9889
9978
  </div>
9890
- `}function Pv(e,t,n){return`
9891
- <style>${Mv}</style>
9979
+ `}function qv(e,t,n){return`
9980
+ <style>${Gv}</style>
9892
9981
  <div class="vidtreo-mobile-modal-overlay" role="dialog" aria-modal="true" aria-label="${e.t(`mobileOpenCameraTitle`)}">
9893
9982
  <div class="vidtreo-mobile-modal-header">
9894
9983
  <!-- Left: Recording Indicator -->
@@ -9923,8 +10012,8 @@ new RecorderWorker;
9923
10012
  ${n}
9924
10013
  </div>
9925
10014
  </div>
9926
- `}function Fv(e){return`
9927
- <style>${Mv}</style>
10015
+ `}function Jv(e){return`
10016
+ <style>${Gv}</style>
9928
10017
  <div class="vidtreo-native-camera-container">
9929
10018
  <input
9930
10019
  type="file"
@@ -9984,7 +10073,7 @@ new RecorderWorker;
9984
10073
 
9985
10074
  <div class="vidtreo-error" id="nativeError" style="display: none;"></div>
9986
10075
  </div>
9987
- `}function Iv(e){return`
10076
+ `}function Yv(e){return`
9988
10077
  <div class="vidtreo-mobile-recorder-content">
9989
10078
  <div class="vidtreo-preview-container vidtreo-mobile-preview">
9990
10079
 
@@ -10150,8 +10239,8 @@ new RecorderWorker;
10150
10239
  <div class="vidtreo-error" id="error" style="display: none;"></div>
10151
10240
  </div>
10152
10241
  </div>
10153
- `}let Lv=()=>`
10154
- <style>${Mv}</style>
10242
+ `}let Xv=()=>`
10243
+ <style>${Gv}</style>
10155
10244
  <div class="vidtreo-camera-area vidtreo-active" id="cameraArea">
10156
10245
  <!-- Error Boundary / Preview Container -->
10157
10246
  <div class="vidtreo-preview-container">
@@ -10337,7 +10426,7 @@ new RecorderWorker;
10337
10426
  <!-- Error Message -->
10338
10427
  <div class="vidtreo-error" id="error" style="display: none;"></div>
10339
10428
  </div>
10340
- `;function Rv(e,t,n,r){return{showSettingsButton:!e&&r.enableDeviceChange!==!1,showMuteButton:e&&r.enableMute!==!1,showPauseButton:e&&r.enablePause!==!1&&t===`recording`&&!n,showResumeButton:e&&r.enablePause!==!1&&n,showStopButton:e,showSwitchSourceButton:e&&r.enableSourceSwitching!==!1}}let zv=/^https?:\/\//i;function Bv(e){return e?zv.test(e)?e:`https://${e}`:`https://core.vidtreo.com`}function Vv(e,t,n){let r=e.getAttribute(t);return r===null?n:r!==`false`}function Hv(e,t){let n=e.getAttribute(t);if(!n)return;let r=Number.parseInt(n,10);if(!Number.isNaN(r))return r}function Uv(e,t){let n={apiKey:e.getAttribute(`api-key`)||``,backendUrl:Bv(e.getAttribute(`backend-url`)),demo:Vv(e,`demo`,!1),enableSourceSwitching:Vv(e,`enable-source-switching`,!0),enableMute:Vv(e,`enable-mute`,!0),enablePause:Vv(e,`enable-pause`,!0),enableDeviceChange:Vv(e,`enable-device-change`,!0),enableTabVisibilityOverlay:Vv(e,`enable-tab-visibility-overlay`,!1)},r=Hv(e,`countdown-duration`);r!==void 0&&(n.countdownDuration=r);let a=Hv(e,`max-recording-time`);a!==void 0&&(n.maxRecordingTime=a);let o=e.getAttribute(`user-metadata`);if(o)try{let e=JSON.parse(o);Object.assign(t,e),n.userMetadata=t}catch(e){throw Error(`Invalid user-metadata JSON: ${i(e)}`)}return n}function Wv(){if(typeof document>`u`||document.querySelector(`script[src*="@phosphor-icons/web"]`))return;let e=document.createElement(`script`);e.src=`https://unpkg.com/@phosphor-icons/web`,e.async=!0,document.head.appendChild(e)}let Gv={requiresAudio:!1,requiresWatermark:!1},Kv={recordingState:`idle`,stream:null,isVideoLoaded:!1,isMuted:!1,isPaused:!1,showSettings:!1,error:null,errorCode:null,browserName:null,browserVersion:null,countdown:null,timer:`00:00`,uploadProgress:null,transitionMessage:null,recordedBlob:null,devices:{cameras:[],microphones:[],selectedCamera:null,selectedMic:null},configError:null};var qv=class extends HTMLElement{constructor(...e){super(...e),this.controller=null,this.uploadService=null,this.state={...Kv},this.config={},this.isMounted=!1,this.connectionGeneration=0,this.initialized=!1,this.isInitializing=!1,this.isProcessingBlob=!1,this.audioBarsContainer=null,this.previewContentElements=null,this.recordingControlsElements=null,this.videoPreviewElements=null,this.overlayElements=null,this.settingsPanelElement=null,this.audioContext=null,this.analyser=null,this.animationFrameId=null,this.mobileManager=null,this.nativeCameraManager=null,this.i18n=new Sv,this.settingsView=`main`,this.slideDirection=`none`}static{this.observedAttributes=[`api-key`,`backend-url`,`countdown-duration`,`max-recording-time`,`user-metadata`,`enable-source-switching`,`enable-mute`,`enable-pause`,`enable-device-change`,`enable-tab-visibility-overlay`,`demo`,`mobile-mode`,`lang`]}get isDemo(){return this.hasAttribute(`demo`)&&this.getAttribute(`demo`)!==`false`}get lang(){return this.getAttribute(`lang`)||`en`}async connectedCallback(){this.connectionGeneration+=1;let e=this.connectionGeneration;this.i18n.setLang(this.lang);let t=this.shouldProbeWebRecorderSupport();if(await this.probeWebRecorderSupport(t,e),this.shouldAbortConnection(e))return;let n=this.getEffectiveMobileMode();this.initializeRecorderForMobileMode(n)}disconnectedCallback(){this.connectionGeneration+=1,this.isMounted=!1,this.mobileManager?.destroy(),this.nativeCameraManager?.destroy(),this.cleanup()}async probeWebRecorderSupport(e,t){this.isMounted||(this.isMounted=!0,e&&await $m(Gv).then(e=>{if(!this.shouldAbortConnection(t)){if(!e.isSupported){this.updateUnsupportedBrowserState();return}this.updateState({errorCode:null,browserName:null,browserVersion:null})}}).catch(()=>{this.shouldAbortConnection(t)||this.updateUnsupportedBrowserState()}))}updateUnsupportedBrowserState(){let e=x_();this.updateState({errorCode:N_,browserName:e.browserName,browserVersion:e.browserVersion})}clearBrowserUnsupportedState(){this.updateState({errorCode:null,browserName:null,browserVersion:null})}applyBrowserUnsupportedStateFromError(e){if(!(e&&typeof e==`object`&&`code`in e))return;let t=e;if(t.code!==N_)return;let n=x_(),r=n.browserName;t.browserName&&t.browserName.length>0&&(r=t.browserName);let i=n.browserVersion;t.browserVersion&&t.browserVersion.length>0&&(i=t.browserVersion),this.updateState({errorCode:N_,browserName:r,browserVersion:i})}resolveBrowserErrorState(){let e=this.state.errorCode,t=this.state.browserName,n=this.state.browserVersion;if(e===N_&&t===null){let e=x_();t=e.browserName,n===null&&(n=e.browserVersion)}return{errorCode:e,browserName:t,browserVersion:n}}shouldAbortConnection(e){return!this.isConnected||e!==this.connectionGeneration}initializeRecorderForMobileMode(e){if(e===`native`){this.initNativeCamera();return}if(e===`overlay`){this.mobileManager=new Ov({getState:()=>({recordingState:this.state.recordingState,uploadProgress:this.state.uploadProgress}),isInitialized:()=>this.initialized,startPreview:()=>this.startPreview(),stopPreview:()=>this.stopPreview(),renderMobile:()=>this.renderMobile()}),this.renderMobile(),this.init();return}this.innerHTML=Lv(),this.init()}getRequestedMobileMode(){let e=this.getAttribute(`mobile-mode`);return e===null?null:e===`embed`?`embed`:e===`native`?`native`:`overlay`}shouldProbeWebRecorderSupport(){return this.getRequestedMobileMode()!==`native`}getEffectiveMobileMode(){let e=this.getRequestedMobileMode();return e===null?`overlay`:e}initNativeCamera(){this.config=Uv(this,{}),this.nativeCameraManager=new kv({apiKey:this.config.apiKey,backendUrl:this.config.backendUrl,maxRecordingTime:this.config.maxRecordingTime,userMetadata:this.config.userMetadata,demo:this.isDemo},{onStateChange:()=>this.renderNativeCamera(),onUploadComplete:e=>{this.dispatchEvent(new CustomEvent(`recording-complete`,{detail:e,bubbles:!0,composed:!0}))},onError:e=>{this.dispatchEvent(new CustomEvent(`error`,{detail:{error:e.message},bubbles:!0,composed:!0}))}}),this.renderNativeCamera(),Wv()}renderNativeCamera(){if(!this.nativeCameraManager)return;let e=this.nativeCameraManager.getState();this.innerHTML=Fv(this.i18n);let t=e.file!==null,n=!(t||e.isTranscoding)&&e.uploadProgress===null&&!e.transcodedBlob;this.setElementDisplay(`#nativeCameraEmptyState`,n),this.setElementDisplay(`#nativePreviewContainer`,t||!!e.transcodedBlob),this.setElementDisplay(`#nativeProgressOverlay`,e.isTranscoding||e.uploadProgress!==null),this.updateNativeCameraProgress(e),this.updateNativeCameraPreview(e,t);let r=this.isDemo&&!!e.transcodedBlob&&!e.isTranscoding&&e.uploadProgress===null;this.setElementDisplay(`#nativeActions`,r),this.updateNativeCameraError(e),this.setupNativeCameraListeners()}setElementDisplay(e,t){let n=this.querySelector(e);n instanceof HTMLElement&&(t&&(n.style.display=``),t||(n.style.display=`none`))}updateNativeCameraProgress(e){let t=this.querySelector(`#nativeUploadProgressFill`),n=this.querySelector(`#nativeUploadProgressText`),r=null;t instanceof HTMLElement&&(r=t);let i=e.uploadProgress!==null,a=e.isTranscoding&&!i,o=0;e.uploadProgress!==null&&(o=e.uploadProgress);let s=0;e.transcodingProgress!==null&&(s=e.transcodingProgress),i&&this.setElementDisplay(`#nativeUploadProgress`,!0),r&&i&&(r.style.width=`${o}%`),n&&i&&(n.textContent=`${this.i18n.t(`uploading`)} ${Math.round(o)}%`),a&&this.setElementDisplay(`#nativeUploadProgress`,!0),r&&a&&(r.style.width=`${s}%`),n&&a&&(n.textContent=`${this.i18n.t(`finishing`)} ${Math.round(s)}%`)}updateNativeCameraPreview(e,t){let n=this.querySelector(`#nativeVideoPreview`);if(n){if(t&&e.file){n.src=URL.createObjectURL(e.file.file);return}e.transcodedBlob&&(n.src=URL.createObjectURL(e.transcodedBlob))}}updateNativeCameraError(e){let t=this.querySelector(`#nativeError`);t instanceof HTMLElement&&(e.error?(t.style.display=``,t.textContent=e.error):t.style.display=`none`)}setupNativeCameraListeners(){let e=this.querySelector(`#btnSelectVideo`),t=this.querySelector(`#btnRecordVideo`),n=this.querySelector(`#btnNativeRetake`),r=this.querySelector(`#nativeCameraInput`);e?.addEventListener(`click`,()=>{r&&(r.accept=`video/*`,r.removeAttribute(`capture`),r.click())}),t?.addEventListener(`click`,()=>{r&&(r.accept=`video/*`,r.setAttribute(`capture`,`environment`),r.click())}),n?.addEventListener(`click`,()=>{this.nativeCameraManager?.reset()}),r?.addEventListener(`change`,async e=>{let t=e.target,n=t.files?.[0];if(n&&this.nativeCameraManager)try{let e=await this.nativeCameraManager.handleFileSelect(n);await this.nativeCameraManager.processAndUpload(e)}catch{}t.value=``})}attributeChangedCallback(e,t,n){t!==n&&[`api-key`,`backend-url`,`demo`].includes(e)&&(this.initialized&&this.cleanup(),this.init())}async init(){if(!this.isInitializing){this.isInitializing=!0;try{this.initialized&&this.cleanup(),this.config=Uv(this,{});let e=this.config.apiKey||``,t=this.config.backendUrl||``;if(!(this.isDemo||e)){this.updateState({configError:Error(`apiKey is required. Provide it as an attribute or ensure demo mode is enabled.`)}),this.isInitializing=!1;return}this.isDemo||(this.uploadService=new jv({apiKey:e,backendUrl:t})),this.controller=new f_(S_(this));let n={...this.config};if(await this.controller.initialize(n),this.initialized=!0,this.updateState({configError:null}),this.clearBrowserUnsupportedState(),this.mobileManager){Wv();return}this.cacheUiElements(),this.setupEventListeners(),Wv(),setTimeout(()=>this.startPreview(),100)}catch(e){this.applyBrowserUnsupportedStateFromError(e),this.updateState({error:i(e)})}finally{this.isInitializing=!1}}}renderConfigError(){let e=this.state,t=!!e.configError;if(this.toggleDisplay(`#configErrorOverlay`,t),t&&e.configError){let t=e.configError.message.includes(`apiKey is required`);this.toggleDisplay(`#configErrorMessageDefault`,!t),this.toggleDisplay(`#configErrorDetails`,t),t||this.setText(`#configErrorMessageDefault`,e.configError.message)}}cleanup(){this.controller&&=(this.controller.cleanup(),null),this.stopAudioAnalysis(),this.initialized=!1,this.state={...Kv}}updateState(e){let t={...this.state,...e};e.stream!==void 0&&(t={...t,isVideoLoaded:!1}),e.recordingState!==void 0&&t.showSettings&&t.recordingState===M_&&(t={...t,showSettings:!1}),this.state=t,this.mobileManager&&e.uploadProgress!==void 0&&this.mobileManager.checkUploadCompletion(this.state.uploadProgress),this.render(),e.stream!==void 0&&this.handleStreamUpdate(this.state.stream),this.state.devices.cameras.length===0&&this.state.stream&&this.updateDevices()}async updateDevices(){if(!this.controller)return;let e=this.controller.getDeviceManager(),t=await e.getAvailableDevices();this.updateState({devices:{cameras:t.videoinput,microphones:t.audioinput,selectedCamera:e.getSelectedCameraDeviceId(),selectedMic:e.getSelectedMicDeviceId()}})}handleStreamUpdate(e){this.videoPreviewElements||this.cacheUiElements(),this.videoPreviewElements&&B_(e,this.videoPreviewElements,{onVideoLoaded:()=>{this.updateState({isVideoLoaded:!0})},onError:e=>{this.updateState({error:e})},startAudioAnalysis:e=>this.startAudioAnalysis(e),stopAudioAnalysis:()=>this.stopAudioAnalysis()})}startAudioAnalysis(e){if(this.stopAudioAnalysis(),e.getAudioTracks().length!==0)try{this.audioContext=new AudioContext;let t=this.audioContext.createMediaStreamSource(e);this.analyser=this.audioContext.createAnalyser(),this.analyser.fftSize=64,t.connect(this.analyser);let n=new Uint8Array(this.analyser.frequencyBinCount),r=()=>{if(!this.analyser)return;this.analyser.getByteFrequencyData(n);let e=0;for(let t of n)e+=t;let t=e/n.length,i=Math.min(1,t/128);this.renderAudioBars(i),this.animationFrameId=requestAnimationFrame(r)};r()}catch(e){this.updateState({error:i(e)})}}stopAudioAnalysis(){this.animationFrameId&&=(cancelAnimationFrame(this.animationFrameId),null),this.audioContext&&=(this.audioContext.close(),null)}renderAudioBars(e){if(!this.audioBarsContainer)return;let t=P_,n=``;if(!this.state.isMuted)for(let r of t){let t=Math.max(4,e*24*r);n+=`<div class="vidtreo-audio-level-bar" style="height: ${t}px;"></div>`}this.audioBarsContainer.innerHTML=n}render(){if(this.mobileManager&&!this.mobileManager.isModalOpen||(this.previewContentElements&&this.recordingControlsElements&&this.overlayElements&&this.videoPreviewElements||this.cacheUiElements(),!(this.previewContentElements&&this.recordingControlsElements&&this.overlayElements&&this.videoPreviewElements)))return;let e=this.i18n.getAll(),t=Av(e),n=this.state.recordingState===M_||this.state.isPaused,r={enableDeviceChange:this.config.enableDeviceChange,enableMute:this.config.enableMute,enablePause:this.config.enablePause,enableSourceSwitching:this.config.enableSourceSwitching},i=Rv(n,this.state.recordingState,this.state.isPaused,r),a=!1;this.isDemo&&!n&&this.state.recordingState===`idle`&&this.state.recordedBlob!==null&&(a=!0);let o={...i,showDownloadButton:a},s=A_;this.controller&&(s=this.controller.getCurrentSourceType());let{errorCode:c,browserName:l,browserVersion:u}=this.resolveBrowserErrorState();J_({state:{stream:this.state.stream,transitionMessage:this.state.transitionMessage,recordingState:this.state.recordingState,countdown:this.state.countdown,timer:this.state.timer,isMuted:this.state.isMuted,isPaused:this.state.isPaused,errorCode:c,browserName:l,browserVersion:u},isVideoLoaded:this.state.isVideoLoaded,isRecording:n,controller:this.controller,audioLevel:0,buttonVisibility:o,currentSourceType:s,onStartRecording:()=>this.handleRecord(),onStopRecording:()=>this.handleStop(),onSwitchSource:()=>this.handleSwitch(),onToggleSettings:()=>this.updateState({showSettings:!this.state.showSettings}),onToggleMute:()=>this.handleMute(),onPause:()=>this.handlePauseToggle(),onResume:()=>this.handlePauseToggle(),onLoadedChange:()=>this.updateState({isVideoLoaded:!0}),onDownload:()=>this.handleDownload(),translations:t.preview,buttonTranslations:t.buttons},this.previewContentElements),iv(nv({stream:this.state.stream,buttonVisibility:o,currentSourceType:s,isMuted:this.state.isMuted,onDownload:()=>this.handleDownload(),onPause:()=>this.handlePauseToggle(),onResume:()=>this.handlePauseToggle(),onStartRecording:()=>this.handleRecord(),onStopRecording:()=>this.handleStop(),onSwitchSource:()=>this.handleSwitch(),onToggleMute:()=>this.handleMute(),onToggleSettings:()=>this.updateState({showSettings:!this.state.showSettings}),recordingState:this.state.recordingState,buttonTranslations:t.buttons}),this.recordingControlsElements),F_({uploadProgress:this.state.uploadProgress,uploadingLabel:e.uploading},{overlay:this.overlayElements.uploadOverlay,fill:this.overlayElements.uploadFill,text:this.overlayElements.uploadText}),I_({transitionMessage:this.state.transitionMessage},{overlay:this.overlayElements.transitionOverlay,message:this.overlayElements.transitionMessage}),vv(_v({stream:this.state.stream,showSettings:this.state.showSettings,devices:this.state.devices,onCameraChange:e=>this.handleCameraChange(e),onMicChange:e=>this.handleMicChange(e),translations:t.settings}),this.settingsPanelElement,()=>this.renderSettings()),this.renderStatusSection(),this.renderMobileIndicators(n),this.renderConfigError()}renderStatusSection(){let e=this.state;this.toggleDisplay(`#error`,!!e.error);let t=``;e.error&&(t=e.error),this.setText(`#error`,t)}renderMobileIndicators(e){this.mobileManager?.isModalOpen&&(this.toggleDisplay(`#mobileRecIndicator`,e),this.toggleDisplay(`#mobileTimerBadge`,e),this.setText(`#mobileTimer`,this.state.timer))}toggleDisplay(e,t){let n=this.queryMobileElement(e);if(!n)return;if(!t){n.style.display=`none`;return}let r=n.tagName===`BUTTON`,i=e.includes(`row`)||e.includes(`controls`)||e.includes(`Overlay`)||e.includes(`Indicator`)||e.includes(`Timer`)||e.includes(`Bars`),a=`block`;r&&(a=`inline-flex`),!r&&i&&(a=`flex`),n.style.display=a}setText(e,t){let n=this.queryMobileElement(e);n&&(n.textContent=t)}async startPreview(){if(this.controller)try{await this.controller.startStream(),this.updateState({stream:this.controller.getStream()}),this.clearBrowserUnsupportedState()}catch(e){this.applyBrowserUnsupportedStateFromError(e),this.updateState({error:i(e)})}}stopPreview(){if(!this.controller)return;this.stopAudioAnalysis();let e=this.controller.getStream();if(e)for(let t of e.getTracks())t.stop();this.controller.getStreamManager().stopStream(),this.updateState({stream:null,error:null,errorCode:null,browserName:null,browserVersion:null})}renderMobile(){if(!this.mobileManager)return;let e=this.mobileManager.portal;if(!this.mobileManager.isModalOpen){this.innerHTML=Nv(this.i18n),this.setupMobileLandingListeners(),Wv();return}let t=Iv(this.i18n),n=Pv(this.i18n,this.mobileManager.canCloseModal,t);e.render(n),this.setupMobileModalListeners(),this.setupEventListeners(),this.cacheUiElements(),this.handleStreamUpdate(this.state.stream),this.render(),Wv()}queryMobileElement(e){return this.mobileManager?.isModalOpen&&this.mobileManager.portal.isActive?this.mobileManager.portal.querySelector(e):this.querySelector(e)}getQueryRoot(){return this.mobileManager?.isModalOpen&&this.mobileManager.portal.isActive?this.mobileManager.portal:this}cacheUiElements(){let e=this.getQueryRoot();this.previewContentElements=V_(e),this.recordingControlsElements=rv(e),this.videoPreviewElements={previewSkeleton:this.previewContentElements.previewSkeleton,videoPreview:this.previewContentElements.videoPreview},this.audioBarsContainer=this.previewContentElements.audioLevelBars,this.overlayElements={uploadOverlay:e.querySelector(`#uploadProgressOverlay`),uploadFill:e.querySelector(`#uploadProgressFill`),uploadText:e.querySelector(`#uploadProgressText`),transitionOverlay:e.querySelector(`#sourceTransitionOverlay`),transitionMessage:e.querySelector(`#transitionMessage`)},this.settingsPanelElement=e.querySelector(`#settingsPanel`)}setupMobileLandingListeners(){this.querySelector(`#btnMobileOpenCamera`)?.addEventListener(`click`,()=>this.mobileManager?.openModal())}setupMobileModalListeners(){this.queryMobileElement(`#btnMobileCloseModal`)?.addEventListener(`click`,()=>this.mobileManager?.closeModal())}handleCameraChange(e){return this.handleDeviceChange(e,`camera`)}handleMicChange(e){return this.handleDeviceChange(e,`mic`)}async handleDeviceChange(e,t){if(!this.controller)return;let n=C_(this.controller,e);t===`mic`&&(n=w_(this.controller,e)),await n.then(e=>{this.updateState({stream:e})}).catch(e=>{this.updateState({error:i(e)})});let r=this.state.devices;t===`camera`&&(r={...this.state.devices,selectedCamera:e}),t===`mic`&&(r={...this.state.devices,selectedMic:e}),this.updateState({devices:r})}async handleRecord(){if(this.controller)try{await this.controller.ensureConfigReady(),this.updateState({configError:null}),await T_(this.controller,A_)}catch(e){this.applyBrowserUnsupportedStateFromError(e),this.updateState({configError:Error(i(e)),error:i(e)})}}async processRecordingBlob(e){if(!this.isProcessingBlob){this.isProcessingBlob=!0;try{if(this.isDemo){this.updateState({recordedBlob:e});return}if(!this.uploadService)throw Error(`Upload service not ready`);let t=`recording-${Date.now()}.mp4`;try{let n=await this.uploadService.uploadVideo(e,{apiKey:this.config.apiKey||``,backendUrl:this.config.backendUrl||``,filename:t,userMetadata:this.config.userMetadata,onProgress:e=>{this.updateState({uploadProgress:e})}});this.updateState({uploadProgress:null}),this.dispatchEvent(new CustomEvent(`upload-complete`,{detail:n}))}catch(e){throw this.updateState({uploadProgress:null}),e}}finally{this.isProcessingBlob=!1}}}async handleStop(){if(this.controller)try{let e=await E_(this.controller,this.isDemo,()=>{},()=>{});e&&await this.processRecordingBlob(e)}catch(e){this.applyBrowserUnsupportedStateFromError(e),this.updateState({error:i(e)})}}handlePauseToggle(){this.controller&&(this.state.isPaused&&O_(this.controller),this.state.isPaused||D_(this.controller),this.updateState({isPaused:this.controller.isPaused()}))}handleDownload(){this.state.recordedBlob&&bv(this.state.recordedBlob)}handleMute(){this.controller&&(yv(this.controller),this.updateState({isMuted:this.controller.getIsMuted()}))}async handleSwitch(){if(!this.controller)return;let e=this.controller.getCurrentSourceType(),t=A_;e===A_&&(t=j_),e===j_&&(t=A_);try{await k_(this.controller,t)}catch(e){this.applyBrowserUnsupportedStateFromError(e),this.updateState({error:i(e)})}}setupEventListeners(){let e=(e,t)=>{let n=this.queryMobileElement(e);n&&n.addEventListener(`click`,t)};e(`#btnRecord`,()=>this.handleRecord()),e(`#btnStop`,()=>this.handleStop()),e(`#btnPause`,()=>this.handlePauseToggle()),e(`#btnDownload`,()=>this.handleDownload()),e(`#btnMute`,()=>this.handleMute()),e(`#btnSwitchSource`,()=>this.handleSwitch());let t=this.queryMobileElement(`#startCameraArea`);t&&t.addEventListener(`click`,()=>this.startPreview());let n=this.queryMobileElement(`#btnSettings`),r=this.queryMobileElement(`#settingsPanel`);n&&r&&n.addEventListener(`click`,()=>{let e=!this.state.showSettings;this.updateState({showSettings:e}),e&&this.populateSettings()});let i=this.queryMobileElement(`#btnSettingsBack`);i&&r&&i.addEventListener(`click`,()=>{}),this.setupSettingsListeners()}setupSettingsListeners(){let e=this.queryMobileElement(`#btnCameraMenu`);e&&e.addEventListener(`click`,()=>this.navigateSettings(`camera`));let t=this.queryMobileElement(`#btnMicMenu`);t&&t.addEventListener(`click`,()=>this.navigateSettings(`microphone`));let n=this.queryMobileElement(`#btnSettingsBack`);n&&n.addEventListener(`click`,e=>{e.stopPropagation(),this.settingsView!==`main`&&this.navigateSettings(`main`)})}navigateSettings(e){e===`main`?this.slideDirection=`left`:this.slideDirection=`right`,this.settingsView=e,this.renderSettings(),setTimeout(()=>{this.slideDirection=`none`,this.renderSettings()},300)}renderSettings(){this.updateSettingsContent(),this.renderSettingsView()}updateSettingsContent(){let e=this.queryMobileElement(`#settingsContent`);e&&(e.classList.remove(`vidtreo-slide-left`,`vidtreo-slide-right`,`vidtreo-slide-none`),this.slideDirection!==`none`&&e.classList.add(`vidtreo-slide-${this.slideDirection}`))}renderSettingsView(){let e=this.queryMobileElement(`#settingsMain`),t=this.queryMobileElement(`#cameraList`),n=this.queryMobileElement(`#micList`),r=this.queryMobileElement(`#btnSettingsBack`);e&&(e.style.display=`none`),t&&(t.style.display=`none`),n&&(n.style.display=`none`),r&&(r.style.display=`none`),this.settingsView===`main`&&this.renderSettingsMain(e,r),this.settingsView===`camera`&&this.renderSettingsCamera(t,r),this.settingsView===`microphone`&&this.renderSettingsMicrophone(n,r)}renderSettingsMain(e,t){e&&(e.style.display=`flex`),t&&(t.style.display=`none`),this.updateCurrentDeviceLabels()}updateCurrentDeviceLabels(){let e=this.state.devices.cameras.filter(e=>e.deviceId&&e.deviceId.trim()!==``),t=this.state.devices.microphones.filter(e=>e.deviceId&&e.deviceId.trim()!==``),n=e.find(e=>e.deviceId===this.state.devices.selectedCamera),r=t.find(e=>e.deviceId===this.state.devices.selectedMic),i=n?.label||e[0]?.label||`Camera`,a=r?.label||t[0]?.label||`Microphone`;this.setText(`#currentCameraName`,i),this.setText(`#currentMicName`,a)}renderSettingsCamera(e,t){e&&(e.style.display=`flex`,this.renderDeviceList(e,this.state.devices.cameras,this.state.devices.selectedCamera,`camera`));let n=this.queryMobileElement(`.vidtreo-settings-title`),r=this.queryMobileElement(`.vidtreo-settings-back-icon`);t&&(t.style.display=`flex`,t.style.cursor=`pointer`,t.onclick=()=>this.navigateSettings(`main`)),n&&(n.textContent=`Camera`),r&&(r.style.display=`flex`)}renderSettingsMicrophone(e,t){e&&(e.style.display=`flex`,this.renderDeviceList(e,this.state.devices.microphones,this.state.devices.selectedMic,`mic`));let n=this.queryMobileElement(`.vidtreo-settings-title`),r=this.queryMobileElement(`.vidtreo-settings-back-icon`);t&&(t.style.display=`flex`,t.style.cursor=`pointer`,t.onclick=()=>this.navigateSettings(`main`)),n&&(n.textContent=`Microphone`),r&&(r.style.display=`flex`)}renderDeviceList(e,t,n,r){if(!t||t.length===0){e.innerHTML=`<div class="vidtreo-device-empty">No devices found</div>`;return}e.innerHTML=``;for(let i of t){let t=document.createElement(`button`);t.className=`vidtreo-device-option`;let a=i.deviceId===n,o=`<span class="vidtreo-device-checkmark-placeholder"></span>`;a&&(o=`<i class="ph-fill ph-check vidtreo-device-checkmark" style="display: flex; font-size: 20px;"></i>`);let s=i.label;s||=`Device ${i.deviceId.slice(0,8)}`,t.innerHTML=`
10429
+ `;function Zv(e,t,n,r){return{showSettingsButton:!e&&r.enableDeviceChange!==!1,showMuteButton:e&&r.enableMute!==!1,showPauseButton:e&&r.enablePause!==!1&&t===`recording`&&!n,showResumeButton:e&&r.enablePause!==!1&&n,showStopButton:e,showSwitchSourceButton:e&&r.enableSourceSwitching!==!1}}let Qv=/^https?:\/\//i;function $v(e){return e?Qv.test(e)?e:`https://${e}`:`https://core.vidtreo.com`}function ey(e,t,n){let r=e.getAttribute(t);return r===null?n:r!==`false`}function ty(e,t){let n=e.getAttribute(t);if(!n)return;let r=Number.parseInt(n,10);if(!Number.isNaN(r))return r}function ny(e,t){let n={apiKey:e.getAttribute(`api-key`)||``,backendUrl:$v(e.getAttribute(`backend-url`)),demo:ey(e,`demo`,!1),enableSourceSwitching:ey(e,`enable-source-switching`,!0),enableMute:ey(e,`enable-mute`,!0),enablePause:ey(e,`enable-pause`,!0),enableDeviceChange:ey(e,`enable-device-change`,!0),enableTabVisibilityOverlay:ey(e,`enable-tab-visibility-overlay`,!1)},r=ty(e,`countdown-duration`);r!==void 0&&(n.countdownDuration=r);let a=ty(e,`max-recording-time`);a!==void 0&&(n.maxRecordingTime=a);let o=e.getAttribute(`user-metadata`);if(o)try{let e=JSON.parse(o);Object.assign(t,e),n.userMetadata=t}catch(e){throw Error(`Invalid user-metadata JSON: ${i(e)}`)}return n}function ry(){if(typeof document>`u`||document.querySelector(`script[src*="@phosphor-icons/web"]`))return;let e=document.createElement(`script`);e.src=`https://unpkg.com/@phosphor-icons/web`,e.async=!0,document.head.appendChild(e)}let iy={requiresAudio:!1,requiresWatermark:!1},ay={recordingState:`idle`,stream:null,isVideoLoaded:!1,isMuted:!1,isPaused:!1,showSettings:!1,error:null,errorCode:null,browserName:null,browserVersion:null,countdown:null,timer:`00:00`,uploadProgress:null,transitionMessage:null,recordedBlob:null,devices:{cameras:[],microphones:[],selectedCamera:null,selectedMic:null},configError:null};var oy=class extends HTMLElement{constructor(...e){super(...e),this.controller=null,this.uploadService=null,this.state={...ay},this.config={},this.isMounted=!1,this.connectionGeneration=0,this.initialized=!1,this.isInitializing=!1,this.isProcessingBlob=!1,this.audioBarsContainer=null,this.previewContentElements=null,this.recordingControlsElements=null,this.videoPreviewElements=null,this.overlayElements=null,this.settingsPanelElement=null,this.audioContext=null,this.analyser=null,this.animationFrameId=null,this.mobileManager=null,this.nativeCameraManager=null,this.i18n=new Fv,this.settingsView=`main`,this.slideDirection=`none`}static{this.observedAttributes=[`api-key`,`backend-url`,`countdown-duration`,`max-recording-time`,`user-metadata`,`enable-source-switching`,`enable-mute`,`enable-pause`,`enable-device-change`,`enable-tab-visibility-overlay`,`demo`,`mobile-mode`,`lang`]}get isDemo(){return this.hasAttribute(`demo`)&&this.getAttribute(`demo`)!==`false`}get lang(){return this.getAttribute(`lang`)||`en`}async connectedCallback(){this.connectionGeneration+=1;let e=this.connectionGeneration;this.i18n.setLang(this.lang);let t=this.shouldProbeWebRecorderSupport();if(await this.probeWebRecorderSupport(t,e),this.shouldAbortConnection(e))return;let n=this.getEffectiveMobileMode();this.initializeRecorderForMobileMode(n)}disconnectedCallback(){this.connectionGeneration+=1,this.isMounted=!1,this.mobileManager?.destroy(),this.nativeCameraManager?.destroy(),this.cleanup()}async probeWebRecorderSupport(e,t){this.isMounted||(this.isMounted=!0,e&&await th(iy).then(e=>{if(!this.shouldAbortConnection(t)){if(!e.isSupported){this.updateUnsupportedBrowserState();return}this.updateState({errorCode:null,browserName:null,browserVersion:null})}}).catch(()=>{this.shouldAbortConnection(t)||this.updateUnsupportedBrowserState()}))}updateUnsupportedBrowserState(){let e=P_();this.updateState({errorCode:K_,browserName:e.browserName,browserVersion:e.browserVersion})}clearBrowserUnsupportedState(){this.updateState({errorCode:null,browserName:null,browserVersion:null})}applyBrowserUnsupportedStateFromError(e){if(!(e&&typeof e==`object`&&`code`in e))return;let t=e;if(t.code!==K_)return;let n=P_(),r=n.browserName;t.browserName&&t.browserName.length>0&&(r=t.browserName);let i=n.browserVersion;t.browserVersion&&t.browserVersion.length>0&&(i=t.browserVersion),this.updateState({errorCode:K_,browserName:r,browserVersion:i})}resolveBrowserErrorState(){let e=this.state.errorCode,t=this.state.browserName,n=this.state.browserVersion;if(e===K_&&t===null){let e=P_();t=e.browserName,n===null&&(n=e.browserVersion)}return{errorCode:e,browserName:t,browserVersion:n}}shouldAbortConnection(e){return!this.isConnected||e!==this.connectionGeneration}initializeRecorderForMobileMode(e){if(e===`native`){this.initNativeCamera();return}if(e===`overlay`){this.mobileManager=new Vv({getState:()=>({recordingState:this.state.recordingState,uploadProgress:this.state.uploadProgress}),isInitialized:()=>this.initialized,startPreview:()=>this.startPreview(),stopPreview:()=>this.stopPreview(),renderMobile:()=>this.renderMobile()}),this.renderMobile(),this.init();return}this.innerHTML=Xv(),this.init()}getRequestedMobileMode(){let e=this.getAttribute(`mobile-mode`);return e===null?null:e===`embed`?`embed`:e===`native`?`native`:`overlay`}shouldProbeWebRecorderSupport(){return this.getRequestedMobileMode()!==`native`}getEffectiveMobileMode(){let e=this.getRequestedMobileMode();return e===null?`overlay`:e}initNativeCamera(){this.config=ny(this,{}),this.nativeCameraManager=new Hv({apiKey:this.config.apiKey,backendUrl:this.config.backendUrl,maxRecordingTime:this.config.maxRecordingTime,userMetadata:this.config.userMetadata,demo:this.isDemo},{onStateChange:()=>this.renderNativeCamera(),onUploadComplete:e=>{this.dispatchEvent(new CustomEvent(`recording-complete`,{detail:e,bubbles:!0,composed:!0}))},onError:e=>{this.dispatchEvent(new CustomEvent(`error`,{detail:{error:e.message},bubbles:!0,composed:!0}))}}),this.renderNativeCamera(),ry()}renderNativeCamera(){if(!this.nativeCameraManager)return;let e=this.nativeCameraManager.getState();this.innerHTML=Jv(this.i18n);let t=e.file!==null,n=!(t||e.isTranscoding)&&e.uploadProgress===null&&!e.transcodedBlob;this.setElementDisplay(`#nativeCameraEmptyState`,n),this.setElementDisplay(`#nativePreviewContainer`,t||!!e.transcodedBlob),this.setElementDisplay(`#nativeProgressOverlay`,e.isTranscoding||e.uploadProgress!==null),this.updateNativeCameraProgress(e),this.updateNativeCameraPreview(e,t);let r=this.isDemo&&!!e.transcodedBlob&&!e.isTranscoding&&e.uploadProgress===null;this.setElementDisplay(`#nativeActions`,r),this.updateNativeCameraError(e),this.setupNativeCameraListeners()}setElementDisplay(e,t){let n=this.querySelector(e);n instanceof HTMLElement&&(t&&(n.style.display=``),t||(n.style.display=`none`))}updateNativeCameraProgress(e){let t=this.querySelector(`#nativeUploadProgressFill`),n=this.querySelector(`#nativeUploadProgressText`),r=null;t instanceof HTMLElement&&(r=t);let i=e.uploadProgress!==null,a=e.isTranscoding&&!i,o=0;e.uploadProgress!==null&&(o=e.uploadProgress);let s=0;e.transcodingProgress!==null&&(s=e.transcodingProgress),i&&this.setElementDisplay(`#nativeUploadProgress`,!0),r&&i&&(r.style.width=`${o}%`),n&&i&&(n.textContent=`${this.i18n.t(`uploading`)} ${Math.round(o)}%`),a&&this.setElementDisplay(`#nativeUploadProgress`,!0),r&&a&&(r.style.width=`${s}%`),n&&a&&(n.textContent=`${this.i18n.t(`finishing`)} ${Math.round(s)}%`)}updateNativeCameraPreview(e,t){let n=this.querySelector(`#nativeVideoPreview`);if(n){if(t&&e.file){n.src=URL.createObjectURL(e.file.file);return}e.transcodedBlob&&(n.src=URL.createObjectURL(e.transcodedBlob))}}updateNativeCameraError(e){let t=this.querySelector(`#nativeError`);t instanceof HTMLElement&&(e.error?(t.style.display=``,t.textContent=e.error):t.style.display=`none`)}setupNativeCameraListeners(){let e=this.querySelector(`#btnSelectVideo`),t=this.querySelector(`#btnRecordVideo`),n=this.querySelector(`#btnNativeRetake`),r=this.querySelector(`#nativeCameraInput`);e?.addEventListener(`click`,()=>{r&&(r.accept=`video/*`,r.removeAttribute(`capture`),r.click())}),t?.addEventListener(`click`,()=>{r&&(r.accept=`video/*`,r.setAttribute(`capture`,`environment`),r.click())}),n?.addEventListener(`click`,()=>{this.nativeCameraManager?.reset()}),r?.addEventListener(`change`,async e=>{let t=e.target,n=t.files?.[0];if(n&&this.nativeCameraManager)try{let e=await this.nativeCameraManager.handleFileSelect(n);await this.nativeCameraManager.processAndUpload(e)}catch{}t.value=``})}attributeChangedCallback(e,t,n){t!==n&&[`api-key`,`backend-url`,`demo`].includes(e)&&(this.initialized&&this.cleanup(),this.init())}async init(){if(!this.isInitializing){this.isInitializing=!0;try{this.initialized&&this.cleanup(),this.config=ny(this,{});let e=this.config.apiKey||``,t=this.config.backendUrl||``;if(!(this.isDemo||e)){this.updateState({configError:Error(`apiKey is required. Provide it as an attribute or ensure demo mode is enabled.`)}),this.isInitializing=!1;return}this.isDemo||(this.uploadService=new Wv({apiKey:e,backendUrl:t})),this.controller=new T_(F_(this));let n={...this.config};if(await this.controller.initialize(n),this.initialized=!0,this.updateState({configError:null}),this.clearBrowserUnsupportedState(),this.mobileManager){ry();return}this.cacheUiElements(),this.setupEventListeners(),ry(),setTimeout(()=>this.startPreview(),100)}catch(e){this.applyBrowserUnsupportedStateFromError(e),this.updateState({error:i(e)})}finally{this.isInitializing=!1}}}renderConfigError(){let e=this.state,t=!!e.configError;if(this.toggleDisplay(`#configErrorOverlay`,t),t&&e.configError){let t=e.configError.message.includes(`apiKey is required`);this.toggleDisplay(`#configErrorMessageDefault`,!t),this.toggleDisplay(`#configErrorDetails`,t),t||this.setText(`#configErrorMessageDefault`,e.configError.message)}}cleanup(){this.controller&&=(this.controller.cleanup(),null),this.stopAudioAnalysis(),this.initialized=!1,this.state={...ay}}updateState(e){let t={...this.state,...e};e.stream!==void 0&&(t={...t,isVideoLoaded:!1}),e.recordingState!==void 0&&t.showSettings&&t.recordingState===G_&&(t={...t,showSettings:!1}),this.state=t,this.mobileManager&&e.uploadProgress!==void 0&&this.mobileManager.checkUploadCompletion(this.state.uploadProgress),this.render(),e.stream!==void 0&&this.handleStreamUpdate(this.state.stream),this.state.devices.cameras.length===0&&this.state.stream&&this.updateDevices()}async updateDevices(){if(!this.controller)return;let e=this.controller.getDeviceManager(),t=await e.getAvailableDevices();this.updateState({devices:{cameras:t.videoinput,microphones:t.audioinput,selectedCamera:e.getSelectedCameraDeviceId(),selectedMic:e.getSelectedMicDeviceId()}})}handleStreamUpdate(e){this.videoPreviewElements||this.cacheUiElements(),this.videoPreviewElements&&$_(e,this.videoPreviewElements,{onVideoLoaded:()=>{this.updateState({isVideoLoaded:!0})},onError:e=>{this.updateState({error:e})},startAudioAnalysis:e=>this.startAudioAnalysis(e),stopAudioAnalysis:()=>this.stopAudioAnalysis()})}startAudioAnalysis(e){if(this.stopAudioAnalysis(),e.getAudioTracks().length!==0)try{this.audioContext=new AudioContext;let t=this.audioContext.createMediaStreamSource(e);this.analyser=this.audioContext.createAnalyser(),this.analyser.fftSize=64,t.connect(this.analyser);let n=new Uint8Array(this.analyser.frequencyBinCount),r=()=>{if(!this.analyser)return;this.analyser.getByteFrequencyData(n);let e=0;for(let t of n)e+=t;let t=e/n.length,i=Math.min(1,t/128);this.renderAudioBars(i),this.animationFrameId=requestAnimationFrame(r)};r()}catch(e){this.updateState({error:i(e)})}}stopAudioAnalysis(){this.animationFrameId&&=(cancelAnimationFrame(this.animationFrameId),null),this.audioContext&&=(this.audioContext.close(),null)}renderAudioBars(e){if(!this.audioBarsContainer)return;let t=q_,n=``;if(!this.state.isMuted)for(let r of t){let t=Math.max(4,e*24*r);n+=`<div class="vidtreo-audio-level-bar" style="height: ${t}px;"></div>`}this.audioBarsContainer.innerHTML=n}render(){if(this.mobileManager&&!this.mobileManager.isModalOpen||(this.previewContentElements&&this.recordingControlsElements&&this.overlayElements&&this.videoPreviewElements||this.cacheUiElements(),!(this.previewContentElements&&this.recordingControlsElements&&this.overlayElements&&this.videoPreviewElements)))return;let e=this.i18n.getAll(),t=Uv(e),n=this.state.recordingState===G_||this.state.isPaused,r={enableDeviceChange:this.config.enableDeviceChange,enableMute:this.config.enableMute,enablePause:this.config.enablePause,enableSourceSwitching:this.config.enableSourceSwitching},i=Zv(n,this.state.recordingState,this.state.isPaused,r),a=!1;this.isDemo&&!n&&this.state.recordingState===`idle`&&this.state.recordedBlob!==null&&(a=!0);let o={...i,showDownloadButton:a},s=U_;this.controller&&(s=this.controller.getCurrentSourceType());let{errorCode:c,browserName:l,browserVersion:u}=this.resolveBrowserErrorState();sv({state:{stream:this.state.stream,transitionMessage:this.state.transitionMessage,recordingState:this.state.recordingState,countdown:this.state.countdown,timer:this.state.timer,isMuted:this.state.isMuted,isPaused:this.state.isPaused,errorCode:c,browserName:l,browserVersion:u},isVideoLoaded:this.state.isVideoLoaded,isRecording:n,controller:this.controller,audioLevel:0,buttonVisibility:o,currentSourceType:s,onStartRecording:()=>this.handleRecord(),onStopRecording:()=>this.handleStop(),onSwitchSource:()=>this.handleSwitch(),onToggleSettings:()=>this.updateState({showSettings:!this.state.showSettings}),onToggleMute:()=>this.handleMute(),onPause:()=>this.handlePauseToggle(),onResume:()=>this.handlePauseToggle(),onLoadedChange:()=>this.updateState({isVideoLoaded:!0}),onDownload:()=>this.handleDownload(),translations:t.preview,buttonTranslations:t.buttons},this.previewContentElements),_v(hv({stream:this.state.stream,buttonVisibility:o,currentSourceType:s,isMuted:this.state.isMuted,onDownload:()=>this.handleDownload(),onPause:()=>this.handlePauseToggle(),onResume:()=>this.handlePauseToggle(),onStartRecording:()=>this.handleRecord(),onStopRecording:()=>this.handleStop(),onSwitchSource:()=>this.handleSwitch(),onToggleMute:()=>this.handleMute(),onToggleSettings:()=>this.updateState({showSettings:!this.state.showSettings}),recordingState:this.state.recordingState,buttonTranslations:t.buttons}),this.recordingControlsElements),J_({uploadProgress:this.state.uploadProgress,uploadingLabel:e.uploading},{overlay:this.overlayElements.uploadOverlay,fill:this.overlayElements.uploadFill,text:this.overlayElements.uploadText}),Y_({transitionMessage:this.state.transitionMessage},{overlay:this.overlayElements.transitionOverlay,message:this.overlayElements.transitionMessage}),jv(Av({stream:this.state.stream,showSettings:this.state.showSettings,devices:this.state.devices,onCameraChange:e=>this.handleCameraChange(e),onMicChange:e=>this.handleMicChange(e),translations:t.settings}),this.settingsPanelElement,()=>this.renderSettings()),this.renderStatusSection(),this.renderMobileIndicators(n),this.renderConfigError()}renderStatusSection(){let e=this.state;this.toggleDisplay(`#error`,!!e.error);let t=``;e.error&&(t=e.error),this.setText(`#error`,t)}renderMobileIndicators(e){this.mobileManager?.isModalOpen&&(this.toggleDisplay(`#mobileRecIndicator`,e),this.toggleDisplay(`#mobileTimerBadge`,e),this.setText(`#mobileTimer`,this.state.timer))}toggleDisplay(e,t){let n=this.queryMobileElement(e);if(!n)return;if(!t){n.style.display=`none`;return}let r=n.tagName===`BUTTON`,i=e.includes(`row`)||e.includes(`controls`)||e.includes(`Overlay`)||e.includes(`Indicator`)||e.includes(`Timer`)||e.includes(`Bars`),a=`block`;r&&(a=`inline-flex`),!r&&i&&(a=`flex`),n.style.display=a}setText(e,t){let n=this.queryMobileElement(e);n&&(n.textContent=t)}async startPreview(){if(this.controller)try{await this.controller.startStream(),this.updateState({stream:this.controller.getStream()}),this.clearBrowserUnsupportedState()}catch(e){this.applyBrowserUnsupportedStateFromError(e),this.updateState({error:i(e)})}}stopPreview(){if(!this.controller)return;this.stopAudioAnalysis();let e=this.controller.getStream();if(e)for(let t of e.getTracks())t.stop();this.controller.getStreamManager().stopStream(),this.updateState({stream:null,error:null,errorCode:null,browserName:null,browserVersion:null})}renderMobile(){if(!this.mobileManager)return;let e=this.mobileManager.portal;if(!this.mobileManager.isModalOpen){this.innerHTML=Kv(this.i18n),this.setupMobileLandingListeners(),ry();return}let t=Yv(this.i18n),n=qv(this.i18n,this.mobileManager.canCloseModal,t);e.render(n),this.setupMobileModalListeners(),this.setupEventListeners(),this.cacheUiElements(),this.handleStreamUpdate(this.state.stream),this.render(),ry()}queryMobileElement(e){return this.mobileManager?.isModalOpen&&this.mobileManager.portal.isActive?this.mobileManager.portal.querySelector(e):this.querySelector(e)}getQueryRoot(){return this.mobileManager?.isModalOpen&&this.mobileManager.portal.isActive?this.mobileManager.portal:this}cacheUiElements(){let e=this.getQueryRoot();this.previewContentElements=ev(e),this.recordingControlsElements=gv(e),this.videoPreviewElements={previewSkeleton:this.previewContentElements.previewSkeleton,videoPreview:this.previewContentElements.videoPreview},this.audioBarsContainer=this.previewContentElements.audioLevelBars,this.overlayElements={uploadOverlay:e.querySelector(`#uploadProgressOverlay`),uploadFill:e.querySelector(`#uploadProgressFill`),uploadText:e.querySelector(`#uploadProgressText`),transitionOverlay:e.querySelector(`#sourceTransitionOverlay`),transitionMessage:e.querySelector(`#transitionMessage`)},this.settingsPanelElement=e.querySelector(`#settingsPanel`)}setupMobileLandingListeners(){this.querySelector(`#btnMobileOpenCamera`)?.addEventListener(`click`,()=>this.mobileManager?.openModal())}setupMobileModalListeners(){this.queryMobileElement(`#btnMobileCloseModal`)?.addEventListener(`click`,()=>this.mobileManager?.closeModal())}handleCameraChange(e){return this.handleDeviceChange(e,`camera`)}handleMicChange(e){return this.handleDeviceChange(e,`mic`)}async handleDeviceChange(e,t){if(!this.controller)return;let n=I_(this.controller,e);t===`mic`&&(n=L_(this.controller,e)),await n.then(e=>{this.updateState({stream:e})}).catch(e=>{this.updateState({error:i(e)})});let r=this.state.devices;t===`camera`&&(r={...this.state.devices,selectedCamera:e}),t===`mic`&&(r={...this.state.devices,selectedMic:e}),this.updateState({devices:r})}async handleRecord(){if(this.controller)try{await this.controller.ensureConfigReady(),this.updateState({configError:null}),await R_(this.controller,U_)}catch(e){this.applyBrowserUnsupportedStateFromError(e),this.updateState({configError:Error(i(e)),error:i(e)})}}async processRecordingBlob(e){if(!this.isProcessingBlob){this.isProcessingBlob=!0;try{if(this.isDemo){this.updateState({recordedBlob:e});return}if(!this.uploadService)throw Error(`Upload service not ready`);let t=`recording-${Date.now()}.mp4`;this.updateState({uploadProgress:0});try{let n=await this.uploadService.uploadVideo(e,{apiKey:this.config.apiKey||``,backendUrl:this.config.backendUrl||``,filename:t,userMetadata:this.config.userMetadata,onProgress:e=>{this.updateState({uploadProgress:e})}});this.updateState({uploadProgress:null}),this.dispatchEvent(new CustomEvent(`upload-complete`,{detail:n}))}catch(e){throw this.updateState({uploadProgress:null}),e}}finally{this.isProcessingBlob=!1}}}async handleStop(){if(this.controller)try{let e=await z_(this.controller,this.isDemo,()=>{},()=>{});e&&await this.processRecordingBlob(e)}catch(e){this.applyBrowserUnsupportedStateFromError(e),this.updateState({error:i(e)})}}handlePauseToggle(){this.controller&&(this.state.isPaused&&V_(this.controller),this.state.isPaused||B_(this.controller),this.updateState({isPaused:this.controller.isPaused()}))}handleDownload(){this.state.recordedBlob&&Nv(this.state.recordedBlob)}handleMute(){this.controller&&(Mv(this.controller),this.updateState({isMuted:this.controller.getIsMuted()}))}async handleSwitch(){if(!this.controller)return;let e=this.controller.getCurrentSourceType(),t=U_;e===U_&&(t=W_),e===W_&&(t=U_);try{await H_(this.controller,t)}catch(e){this.applyBrowserUnsupportedStateFromError(e),this.updateState({error:i(e)})}}setupEventListeners(){let e=(e,t)=>{let n=this.queryMobileElement(e);n&&n.addEventListener(`click`,t)};e(`#btnRecord`,()=>this.handleRecord()),e(`#btnStop`,()=>this.handleStop()),e(`#btnPause`,()=>this.handlePauseToggle()),e(`#btnDownload`,()=>this.handleDownload()),e(`#btnMute`,()=>this.handleMute()),e(`#btnSwitchSource`,()=>this.handleSwitch());let t=this.queryMobileElement(`#startCameraArea`);t&&t.addEventListener(`click`,()=>this.startPreview());let n=this.queryMobileElement(`#btnSettings`),r=this.queryMobileElement(`#settingsPanel`);n&&r&&n.addEventListener(`click`,()=>{let e=!this.state.showSettings;this.updateState({showSettings:e}),e&&this.populateSettings()});let i=this.queryMobileElement(`#btnSettingsBack`);i&&r&&i.addEventListener(`click`,()=>{}),this.setupSettingsListeners()}setupSettingsListeners(){let e=this.queryMobileElement(`#btnCameraMenu`);e&&e.addEventListener(`click`,()=>this.navigateSettings(`camera`));let t=this.queryMobileElement(`#btnMicMenu`);t&&t.addEventListener(`click`,()=>this.navigateSettings(`microphone`));let n=this.queryMobileElement(`#btnSettingsBack`);n&&n.addEventListener(`click`,e=>{e.stopPropagation(),this.settingsView!==`main`&&this.navigateSettings(`main`)})}navigateSettings(e){e===`main`?this.slideDirection=`left`:this.slideDirection=`right`,this.settingsView=e,this.renderSettings(),setTimeout(()=>{this.slideDirection=`none`,this.renderSettings()},300)}renderSettings(){this.updateSettingsContent(),this.renderSettingsView()}updateSettingsContent(){let e=this.queryMobileElement(`#settingsContent`);e&&(e.classList.remove(`vidtreo-slide-left`,`vidtreo-slide-right`,`vidtreo-slide-none`),this.slideDirection!==`none`&&e.classList.add(`vidtreo-slide-${this.slideDirection}`))}renderSettingsView(){let e=this.queryMobileElement(`#settingsMain`),t=this.queryMobileElement(`#cameraList`),n=this.queryMobileElement(`#micList`),r=this.queryMobileElement(`#btnSettingsBack`);e&&(e.style.display=`none`),t&&(t.style.display=`none`),n&&(n.style.display=`none`),r&&(r.style.display=`none`),this.settingsView===`main`&&this.renderSettingsMain(e,r),this.settingsView===`camera`&&this.renderSettingsCamera(t,r),this.settingsView===`microphone`&&this.renderSettingsMicrophone(n,r)}renderSettingsMain(e,t){e&&(e.style.display=`flex`),t&&(t.style.display=`none`),this.updateCurrentDeviceLabels()}updateCurrentDeviceLabels(){let e=this.state.devices.cameras.filter(e=>e.deviceId&&e.deviceId.trim()!==``),t=this.state.devices.microphones.filter(e=>e.deviceId&&e.deviceId.trim()!==``),n=e.find(e=>e.deviceId===this.state.devices.selectedCamera),r=t.find(e=>e.deviceId===this.state.devices.selectedMic),i=n?.label||e[0]?.label||`Camera`,a=r?.label||t[0]?.label||`Microphone`;this.setText(`#currentCameraName`,i),this.setText(`#currentMicName`,a)}renderSettingsCamera(e,t){e&&(e.style.display=`flex`,this.renderDeviceList(e,this.state.devices.cameras,this.state.devices.selectedCamera,`camera`));let n=this.queryMobileElement(`.vidtreo-settings-title`),r=this.queryMobileElement(`.vidtreo-settings-back-icon`);t&&(t.style.display=`flex`,t.style.cursor=`pointer`,t.onclick=()=>this.navigateSettings(`main`)),n&&(n.textContent=`Camera`),r&&(r.style.display=`flex`)}renderSettingsMicrophone(e,t){e&&(e.style.display=`flex`,this.renderDeviceList(e,this.state.devices.microphones,this.state.devices.selectedMic,`mic`));let n=this.queryMobileElement(`.vidtreo-settings-title`),r=this.queryMobileElement(`.vidtreo-settings-back-icon`);t&&(t.style.display=`flex`,t.style.cursor=`pointer`,t.onclick=()=>this.navigateSettings(`main`)),n&&(n.textContent=`Microphone`),r&&(r.style.display=`flex`)}renderDeviceList(e,t,n,r){if(!t||t.length===0){e.innerHTML=`<div class="vidtreo-device-empty">No devices found</div>`;return}e.innerHTML=``;for(let i of t){let t=document.createElement(`button`);t.className=`vidtreo-device-option`;let a=i.deviceId===n,o=`<span class="vidtreo-device-checkmark-placeholder"></span>`;a&&(o=`<i class="ph-fill ph-check vidtreo-device-checkmark" style="display: flex; font-size: 20px;"></i>`);let s=i.label;s||=`Device ${i.deviceId.slice(0,8)}`,t.innerHTML=`
10341
10430
  <div class="vidtreo-device-option-check-container">${o}</div>
10342
10431
  <span class="vidtreo-device-option-label">${s}</span>
10343
- `,t.onclick=()=>{r===`camera`&&this.handleCameraChange(i.deviceId),r===`mic`&&this.handleMicChange(i.deviceId),this.navigateSettings(`main`)},e.appendChild(t)}}populateSettings(){this.settingsView=`main`,this.slideDirection=`none`,this.renderSettings()}};return customElements.get(`vidtreo-recorder`)||customElements.define(`vidtreo-recorder`,qv),e.VidtreoRecorder=qv,e})({});
10432
+ `,t.onclick=()=>{r===`camera`&&this.handleCameraChange(i.deviceId),r===`mic`&&this.handleMicChange(i.deviceId),this.navigateSettings(`main`)},e.appendChild(t)}}populateSettings(){this.settingsView=`main`,this.slideDirection=`none`,this.renderSettings()}};return customElements.get(`vidtreo-recorder`)||customElements.define(`vidtreo-recorder`,oy),e.VidtreoRecorder=oy,e})({});