1(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[400],{257:function(e,t,n){"use strict";var o,a;e.exports=(null==(o=n.g.process)?void 0:o.env)&&"object"==typeof(null==(a=n.g.process)?void 0:a.env)?n.g.process:n(4227)},4227:function(e){!function(){var t={229:function(e){var t,n,o,a=e.exports={};function s(){throw Error("setTimeout has not been defined")}function i(){throw Error("clearTimeout has not been defined")}function r(e){if(t===setTimeout)return setTimeout(e,0);if((t===s||!t)&&setTimeout)return t=setTimeout,setTimeout(e,0);try{return t(e,0)}catch(n){try{return t.call(null,e,0)}catch(n){return t.call(this,e,0)}}}!function(){try{t="function"==typeof setTimeout?setTimeout:s}catch(e){t=s}try{n="function"==typeof clearTimeout?clearTimeout:i}catch(e){n=i}}();var c=[],l=!1,u=-1;function d(){l&&o&&(l=!1,o.length?c=o.concat(c):u=-1,c.length&&h())}function h(){if(!l){var e=r(d);l=!0;for(var t=c.length;t;){for(o=c,c=[];++u<t;)o&&o[u].run();u=-1,t=c.length}o=null,l=!1,function(e){if(n===clearTimeout)return clearTimeout(e);if((n===i||!n)&&clearTimeout)return n=clearTimeout,clearTimeout(e);try{n(e)}catch(t){try{return n.call(null,e)}catch(t){return n.call(this,e)}}}(e)}}function p(e,t){this.fun=e,this.array=t}function m(){}a.nextTick=function(e){var t=Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];c.push(new p(e,t)),1!==c.length||l||r(h)},p.prototype.run=function(){this.fun.apply(null,this.array)},a.title="browser",a.browser=!0,a.env={},a.argv=[],a.version="",a.versions={},a.on=m,a.addListener=m,a.once=m,a.off=m,a.removeListener=m,a.removeAllListeners=m,a.emit=m,a.prependListener=m,a.prependOnceListener=m,a.listeners=function(e){return[]},a.binding=function(e){throw Error("process.binding is not supported")},a.cwd=function(){return"/"},a.chdir=function(e){throw Error("process.chdir is not supported")},a.umask=function(){return 0}}},n={};function o(e){var a=n[e];if(void 0!==a)return a.exports;var s=n[e]={exports:{}},i=!0;try{t[e](s,s.exports,o),i=!1}finally{i&&delete n[e]}return s.exports}o.ab="//";var a=o(229);e.exports=a}()},3422:function(e,t,n){"use strict";function o(e){let{textOnly:t}=e.overrides?.conversation??{},{textOnly:n}=e;return"boolean"==typeof n?("boolean"==typeof t&&n!==t&&console.warn(`Conflicting textOnly options provided: ${n} via options.textOnly (will be used) and ${t} via options.overrides.conversation.textOnly (will be ignored)`),n):"boolean"==typeof t?t:void 0}n.d(t,{ri:function(){return q}});class a{options;connection;lastInterruptTimestamp=0;mode="listening";status="connecting";volume=1;currentEventId=1;lastFeedbackEventId=0;canSendFeedback=!1;static getFullOptions(e){let t=o(e);return{clientTools:{},onConnect:()=>{},onDebug:()=>{},onDisconnect:()=>{},onError:()=>{},onMessage:()=>{},onAudio:()=>{},onModeChange:()=>{},onStatusChange:()=>{},onCanSendFeedbackChange:()=>{},onInterruption:()=>{},...e,textOnly:t,overrides:{...e.overrides,conversation:{...e.overrides?.conversation,textOnly:t}}}}constructor(e,t){this.options=e,this.connection=t,this.options.onConnect&&this.options.onConnect({conversationId:t.conversationId}),this.connection.onMessage(this.onMessage),this.connection.onDisconnect(this.endSessionWithDetails),this.connection.onModeChange(e=>this.updateMode(e)),this.updateStatus("connected")}endSession(){return this.endSessionWithDetails({reason:"user"})}endSessionWithDetails=async e=>{("connected"===this.status||"connecting"===this.status)&&(this.updateStatus("disconnecting"),await this.handleEndSession(),this.updateStatus("disconnected"),this.options.onDisconnect&&this.options.onDisconnect(e))};async handleEndSession(){this.connection.close()}updateMode(e){e!==this.mode&&(this.mode=e,this.options.onModeChange&&this.options.onModeChange({mode:e}))}updateStatus(e){e!==this.status&&(this.status=e,this.options.onStatusChange&&this.options.onStatusChange({status:e}))}updateCanSendFeedback(){let e=this.currentEventId!==this.lastFeedbackEventId;this.canSendFeedback!==e&&(this.canSendFeedback=e,this.options.onCanSendFeedbackChange&&this.options.onCanSendFeedbackChange({canSendFeedback:e}))}handleInterruption(e){e.interruption_event&&(this.lastInterruptTimestamp=e.interruption_event.event_id,this.options.onInterruption&&this.options.onInterruption({event_id:e.interruption_event.event_id}))}handleAgentResponse(e){this.options.onMessage&&this.options.onMessage({source:"ai",role:"agent",message:e.agent_response_event.agent_response,event_id:e.agent_response_event.event_id})}handleUserTranscript(e){this.options.onMessage&&this.options.onMessage({source:"user",role:"user",message:e.user_transcription_event.user_transcript,event_id:e.user_transcription_event.event_id})}handleTentativeAgentResponse(e){this.options.onDebug&&this.options.onDebug({type:"tentative_agent_response",response:e.tentative_agent_response_internal_event.tentative_agent_response})}handleVadScore(e){this.options.onVadScore&&this.options.onVadScore({vadScore:e.vad_score_event.vad_score})}async handleClientToolCall(e){if(Object.prototype.hasOwnProperty.call(this.options.clientTools,e.client_tool_call.tool_name))try{let t=await this.options.clientTools[e.client_tool_call.tool_name](e.client_tool_call.parameters)??"Client tool execution successful.",n="object"==typeof t?JSON.stringify(t):String(t);this.connection.sendMessage({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:n,is_error:!1})}catch(t){this.onError(`Client tool execution failed with following error: ${t?.message}`,{clientToolName:e.client_tool_call.tool_name}),this.connection.sendMessage({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:`Client tool execution failed: ${t?.message}`,is_error:!0})}else{if(this.options.onUnhandledClientToolCall){this.options.onUnhandledClientToolCall(e.client_tool_call);return}this.onError(`Client tool with name ${e.client_tool_call.tool_name} is not defined on client`,{clientToolName:e.client_tool_call.tool_name}),this.connection.sendMessage({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:`Client tool with name ${e.client_tool_call.tool_name} is not defined on client`,is_error:!0})}}handleAudio(e){}handleMCPToolCall(e){this.options.onMCPToolCall&&this.options.onMCPToolCall(e.mcp_tool_call)}
1handleMCPConnectionStatus(e){this.options.onMCPConnectionStatus&&this.options.onMCPConnectionStatus(e.mcp_connection_status)}handleAgentToolRequest(e){this.options.onAgentToolRequest&&this.options.onAgentToolRequest(e.agent_tool_request)}handleAgentToolResponse(e){"end_call"===e.agent_tool_response.tool_name&&this.endSessionWithDetails({reason:"agent",context:new CloseEvent("end_call",{reason:"Agent ended the call"})}),this.options.onAgentToolResponse&&this.options.onAgentToolResponse(e.agent_tool_response)}handleConversationMetadata(e){this.options.onConversationMetadata&&this.options.onConversationMetadata(e.conversation_initiation_metadata_event)}handleAsrInitiationMetadata(e){this.options.onAsrInitiationMetadata&&this.options.onAsrInitiationMetadata(e.asr_initiation_metadata_event)}handleAgentChatResponsePart(e){this.options.onAgentChatResponsePart&&this.options.onAgentChatResponsePart(e.text_response_part)}handleGuardrailTriggered(e){this.options.onGuardrailTriggered&&this.options.onGuardrailTriggered()}handleErrorEvent(e){let t=e.error_event.error_type,n=e.error_event.message||e.error_event.reason||"Unknown error";if("max_duration_exceeded"===t){this.endSessionWithDetails({reason:"error",message:n,context:new Event("max_duration_exceeded")});return}this.onError(`Server error: ${n}`,{errorType:t,code:e.error_event.code,debugMessage:e.error_event.debug_message,details:e.error_event.details})}onMessage=async e=>{switch(e.type){case"interruption":this.handleInterruption(e);return;case"agent_response":this.handleAgentResponse(e);return;case"user_transcript":this.handleUserTranscript(e);return;case"internal_tentative_agent_response":this.handleTentativeAgentResponse(e);return;case"client_tool_call":try{await this.handleClientToolCall(e)}catch(t){this.onError(`Unexpected error in client tool call handling: ${t instanceof Error?t.message:String(t)}`,{clientToolName:e.client_tool_call.tool_name,toolCallId:e.client_tool_call.tool_call_id})}return;case"audio":this.handleAudio(e);return;case"vad_score":this.handleVadScore(e);return;case"ping":this.connection.sendMessage({type:"pong",event_id:e.ping_event.event_id});return;case"mcp_tool_call":this.handleMCPToolCall(e);return;case"mcp_connection_status":this.handleMCPConnectionStatus(e);return;case"agent_tool_request":this.handleAgentToolRequest(e);return;case"agent_tool_response":this.handleAgentToolResponse(e);return;case"conversation_initiation_metadata":this.handleConversationMetadata(e);return;case"asr_initiation_metadata":this.handleAsrInitiationMetadata(e);return;case"agent_chat_response_part":this.handleAgentChatResponsePart(e);return;case"guardrail_triggered":this.handleGuardrailTriggered(e);return;case"error":this.handleErrorEvent(e);return;default:this.options.onDebug&&this.options.onDebug(e);return}};onError(e,t){console.error(e,t),this.options.onError&&this.options.onError(e,t)}getId(){return this.connection.conversationId}isOpen(){return"connected"===this.status}sendFeedback(e){if(!this.canSendFeedback){console.warn(0===this.lastFeedbackEventId?"Cannot send feedback: the conversation has not started yet.":"Cannot send feedback: feedback has already been sent for the current response.");return}this.connection.sendMessage({type:"feedback",score:e?"like":"dislike",event_id:this.currentEventId}),this.lastFeedbackEventId=this.currentEventId,this.updateCanSendFeedback()}sendContextualUpdate(e){this.connection.sendMessage({type:"contextual_update",text:e})}sendUserMessage(e){this.connection.sendMessage({type:"user_message",text:e})}sendUserActivity(){this.connection.sendMessage({type:"user_activity"})}sendMCPToolApprovalResult(e,t){this.connection.sendMessage({type:"mcp_tool_approval_result",tool_call_id:e,is_approved:t})}sendMultimodalMessage(e){this.connection.sendMessage({type:"multimodal_message",text:e.text?{type:"user_message",text:e.text}:void 0,file:e.fileId?{type:"file_input",file_id:e.fileId}:void 0})}}class s{queue=[];disconnectionDetails=null;onDisconnectCallback=null;onMessageCallback=null;onModeChangeCallback=null;onDebug;constructor(e={}){this.onDebug=e.onDebug}debug(e){this.onDebug&&this.onDebug(e)}onMessage(e){this.onMessageCallback=e;let t=this.queue;this.queue=[],t.length>0&&queueMicrotask(()=>{t.forEach(e)})}onDisconnect(e){this.onDisconnectCallback=e;
1let t=this.disconnectionDetails;t&&queueMicrotask(()=>{e(t)})}onModeChange(e){this.onModeChangeCallback=e}updateMode(e){this.onModeChangeCallback?.(e)}disconnect(e){this.disconnectionDetails||(this.disconnectionDetails=e,this.onDisconnectCallback?.(e))}handleMessage(e){this.onMessageCallback?this.onMessageCallback(e):this.queue.push(e)}}function i(e){let[t,n]=e.split("_");if(!["pcm","ulaw"].includes(t))throw Error(`Invalid format: ${e}`);let o=Number.parseInt(n);if(Number.isNaN(o))throw Error(`Invalid sample rate: ${n}`);return{format:t,sampleRate:o}}let r=Object.freeze({name:"js_sdk",version:"1.1.1"}),c="conversation_initiation_client_data";function l(e){let t={type:c};return e.overrides&&(t.conversation_config_override={agent:{prompt:e.overrides.agent?.prompt,first_message:e.overrides.agent?.firstMessage,language:e.overrides.agent?.language},tts:{voice_id:e.overrides.tts?.voiceId,speed:e.overrides.tts?.speed,stability:e.overrides.tts?.stability,similarity_boost:e.overrides.tts?.similarityBoost},conversation:{text_only:e.overrides.conversation?.textOnly}}),e.customLlmExtraBody&&(t.custom_llm_extra_body=e.customLlmExtraBody),e.dynamicVariables&&(t.dynamic_variables=e.dynamicVariables),e.userId&&(t.user_id=e.userId),t.source_info={source:r.name,version:r.version},e.toolMockConfig&&(t.tool_mock_config={mocking_strategy:e.toolMockConfig.mockingStrategy,mocked_tool_names:e.toolMockConfig.mockedToolNames,fallback_strategy:e.toolMockConfig.fallbackStrategy}),t}class u extends Error{closeCode;closeReason;constructor(e,t){super(e),this.name="SessionConnectionError",this.closeCode=t?.closeCode,this.closeReason=t?.closeReason}}class d extends s{socket;conversationId;inputFormat;outputFormat;outputListeners=new Set;constructor(e,t,n,o){super(),this.socket=e,this.conversationId=t,this.inputFormat=n,this.outputFormat=o,this.socket.addEventListener("error",e=>{setTimeout(()=>this.disconnect({reason:"error",message:"The connection was closed due to a socket error.",context:e}),0)}),this.socket.addEventListener("close",e=>{this.disconnect(1e3===e.code?{reason:"agent",context:e,closeCode:e.code,closeReason:e.reason||void 0}:{reason:"error",message:e.reason||"The connection was closed by the server.",context:e,closeCode:e.code,closeReason:e.reason||void 0})}),this.socket.addEventListener("message",e=>{try{let t=JSON.parse(e.data);if(!t.type){this.debug({type:"invalid_event",message:"Received invalid socket event",data:e.data});return}this.handleMessage(t)}catch(t){this.debug({type:"parsing_error",message:"Failed to parse socket message",error:t instanceof Error?t.message:String(t),data:e.data})}})}static async create(e){let t=null;try{let n;let o=e.origin??"wss://api.elevenlabs.io",{name:a,version:s}=r;if(e.signedUrl){let t=e.signedUrl.includes("?")?"&":"?";n=`${e.signedUrl}${t}source=${a}&version=${s}`}else n=`${o}/v1/convai/conversation?agent_id=${e.agentId}&source=${a}&version=${s}`;e.environment&&(n+=`&environment=${encodeURIComponent(e.environment)}`);let c=["convai"];e.authorization&&c.push(`bearer.${e.authorization}`),t=new WebSocket(n,c);let{conversation_id:h,agent_output_audio_format:p,user_input_audio_format:m}=await new Promise((n,o)=>{t.addEventListener("open",()=>{let n=l(e);t?.send(JSON.stringify(n))},{once:!0}),t.addEventListener("error",e=>{setTimeout(()=>o(new u("The connection was closed due to a socket error.")),0)}),t.addEventListener("close",e=>{let t=e.reason||(1e3===e.code?"Connection closed normally before session could be established.":"Connection closed unexpectedly before session could be established.");o(new u(t,{closeCode:e.code,closeReason:e.reason||void 0}))}),t.addEventListener("message",e=>{let t=JSON.parse(e.data);t.type&&("conversation_initiation_metadata"===t.type?n(t.conversation_initiation_metadata_event):console.warn("First received message is not conversation metadata."))},{once:!0})}),g=i(m??"pcm_16000"),f=i(p);return new d(t,h,g,f)}catch(e){throw t?.close(),e}}close(){this.socket.close(1e3,"User ended conversation")}sendMessage(e){this.socket.send(JSON.stringify(e))}addListener(e){this.outputListeners.add(e)}removeListener(e){this.outputListeners.delete(e)}handleMessage(e){if(super.handleMessage(e),"audio"===e.type&&e.audio_event.audio_base_64){let t={audio_base_64:e.audio_event.audio_base_64};
1this.outputListeners.forEach(e=>e(t))}}}var h,p,m,g,f,v,y=n(3819);function _(e){let t=new Uint8Array(e);return window.btoa(String.fromCharCode(...t))}let w=new Map;function b(e,t){return async(n,o)=>{let a=w.get(e);if(a)return n.addModule(a);if(o)try{await n.addModule(o),w.set(e,o);return}catch(t){throw Error(`Failed to load the ${e} worklet module from path: ${o}. Error: ${t}`)}let s=new Blob([t],{type:"application/javascript"}),i=URL.createObjectURL(s);try{await n.addModule(i),w.set(e,i);return}catch{URL.revokeObjectURL(i)}try{let o=btoa(t),a=`data:application/javascript;base64,${o}`;await n.addModule(a),w.set(e,a)}catch(t){throw Error(`Failed to load the ${e} worklet module. Make sure the browser supports AudioWorklets. If you are using a strict CSP, you may need to self-host the worklet files.`)}}}let C=b("rawAudioProcessor",`/* 2 * ulaw encoding logic taken from the wavefile library 3 * https://github.com/rochars/wavefile/blob/master/lib/codecs/mulaw.js 4 * USED BY @elevenlabs/client 5 */ 6 7const BIAS = 0x84; 8const CLIP = 32635; 9const encodeTable = [ 10 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, 11 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 12 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 13 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 14 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 15 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 16 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 17 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 18 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 19 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 20 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 21 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 22 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 23 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 24 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 25 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 26]; 27 28function encodeSample(sample) { 29 let sign; 30 let exponent; 31 let mantissa; 32 let muLawSample; 33 sign = (sample >> 8) & 0x80; 34 if (sign !== 0) sample = -sample; 35 sample = sample + BIAS; 36 if (sample > CLIP) sample = CLIP; 37 exponent = encodeTable[(sample>>7) & 0xFF]; 38 mantissa = (sample >> (exponent+3)) & 0x0F; 39 muLawSample = ~(sign | (exponent << 4) | mantissa); 40 41 return muLawSample; 42} 43 44class RawAudioProcessor extends AudioWorkletProcessor { 45 constructor() { 46 super(); 47 48 this.port.onmessage = ({ data }) => { 49 switch (data.type) { 50 case "setFormat": 51 this.isMuted = false; 52 this.buffer = []; // Initialize an empty buffer 53 this.bufferSize = data.sampleRate / 10; 54 this.format = data.format; 55 56 if (globalThis.LibSampleRate && sampleRate !== data.sampleRate) { 57 globalThis.LibSampleRate.create(1, sampleRate, data.sampleRate).then(resampler => { 58 this.resampler = resampler; 59 }); 60 } 61 break; 62 case "setMuted": 63 this.isMuted = data.isMuted; 64 break; 65 } 66 }; 67 } 68 process(inputs) { 69 if (!this.buffer) { 70 return true; 71 } 72 73 const input = inputs[0]; // Get the first input node 74 if (input.length > 0) { 75 let channelData = input[0]; // Get the first channel's data 76 77 // Resample the audio if necessary 78 if (this.resampler) { 79 channelData = this.resampler.full(channelData); 80 } 81 82 // Add channel data to the buffer 83 this.buffer.push(...channelData); 84 // Get max volume 85 let sum = 0.0; 86 for (let i = 0; i < channelData.length; i++) { 87 sum += channelData[i] * channelData[i]; 88 } 89 const maxVolume = Math.sqrt(sum / channelData.length); 90 // Check if buffer size has reached or exceeded the threshold 91 if (this.buffer.length >= this.bufferSize) { 92 const float32Array = this.isMuted 93 ? new Float32Array(this.buffer.length) 94 : new Float32Array(this.buffer); 95 96 let encodedArray = this.format === "ulaw" 97 ? new Uint8Array(float32Array.length) 98 : new Int16Array(float32Array.length); 99 100 // Iterate through the Float32Array and convert each sample to PCM16 101 for (let i = 0; i < float32Array.length; i++) { 102 // Clamp the value to the range [-1, 1] 103 let sample = Math.max(-1, Math.min(1, float32Array[i])); 104 105 // Scale the sample to the range [-32768, 32767] 106 let value = sample < 0 ? sample * 32768 : sample * 32767; 107 if (this.format === "ulaw") { 108 value = encodeSample(Math.round(value)); 109 } 110 111 encodedArray[i] = value; 112 } 113 114 // Send the buffered data to the main script 115 this.port.postMessage([encodedArray, maxVolume]); 116 117 // Clear the buffer after sending 118 this.buffer = []; 119 } 120 } 121 return true; // Continue processing 122 } 123} 124registerProcessor("rawAudioProcessor", RawAudioProcessor); 125`);class k extends s{conversationId;inputFormat;outputFormat;room;isConnected=!1;audioEventId=1;audioCaptureContext=null;audioElements=[];outputDeviceId=null;outputAnalyser=null;outputFrequencyData=null;_isMuted=!1;input={close:async()=>
125{if(this.isConnected)try{this.room.localParticipant.audioTrackPublications.forEach(e=>{e.track&&e.track.stop()})}catch(e){console.warn("Error stopping local tracks:",e)}},setDevice:async e=>{if(e?.sampleRate!==void 0||e?.format!==void 0||e?.preferHeadphonesForIosDevices!==void 0)throw Error("WebRTC input device does not support sampleRate, format, or preferHeadphonesForIosDevices options");let t=e?.inputDeviceId;t&&await this.setAudioInputDevice(t)},setMuted:async e=>{if(!this.isConnected||!this.room.localParticipant){console.warn("Cannot set microphone muted: room not connected or no local participant");return}let t=this.room.localParticipant.getTrackPublication(y.fQ.Source.Microphone);if(t?.track)try{e?await t.track.mute():await t.track.unmute()}catch(t){await this.room.localParticipant.setMicrophoneEnabled(!e)}else await this.room.localParticipant.setMicrophoneEnabled(!e);this._isMuted=e},isMuted:()=>this._isMuted,getAnalyser:()=>void 0};output={close:async()=>{},setDevice:async e=>{if(e?.sampleRate!==void 0||e?.format!==void 0)throw Error("WebRTC output device does not support sampleRate or format options");let t=e?.outputDeviceId;t&&await this.setAudioOutputDevice(t)},setVolume:e=>{this.setAudioVolume(e)},interrupt:e=>{},getAnalyser:()=>this.outputAnalyser??void 0};constructor(e,t,n,o,a={}){super(a),this.room=e,this.conversationId=t,this.inputFormat=n,this.outputFormat=o,this.setupRoomEventListeners()}static async create(e){let t;if("conversationToken"in e&&e.conversationToken)t=e.conversationToken;else if("agentId"in e&&e.agentId)try{let{name:n,version:o}=r,a=(e.origin??"https://api.elevenlabs.io").replace(/^wss:\/\//,"https://"),s=`${a}/v1/convai/conversation/token?agent_id=${e.agentId}&source=${n}&version=${o}`;e.environment&&(s+=`&environment=${encodeURIComponent(e.environment)}`);let i=await fetch(s);if(!i.ok)throw Error(`ElevenLabs API returned ${i.status} ${i.statusText}`);if(!(t=(await i.json()).token))throw Error("No conversation token received from API")}catch(n){let t=n instanceof Error?n.message:String(n);throw n instanceof Error&&n.message.includes("401")&&(t="Your agent has authentication enabled, but no signed URL or conversation token was provided."),Error(`Failed to fetch conversation token for agent ${e.agentId}: ${t}`)}else throw Error("Either conversationToken or agentId is required for WebRTC connection");let n=new y.du;try{let o=`room_${Date.now()}`,a=i("pcm_48000"),s=i("pcm_48000"),r=new k(n,o,a,s,e),u=e.livekitUrl||"wss://livekit.rtc.elevenlabs.io",d=e.textOnly?Promise.resolve():new Promise((e,t)=>{n.once(y.TQ.SignalConnected,()=>{n.localParticipant.setMicrophoneEnabled(!0).then(()=>e()).catch(t)})});await n.connect(u,t),await new Promise(e=>{if(r.isConnected)e();else{let t=()=>{n.off(y.TQ.Connected,t),e()};n.on(y.TQ.Connected,t)}}),await d,n.name&&(r.conversationId=n.name.match(/(conv_[a-zA-Z0-9]+)/)?.[0]||n.name);let h=l(e);return r.debug({type:c,message:h}),await r.sendMessage(h),r}catch(e){throw await n.disconnect(),e}}setupRoomEventListeners(){this.room.on(y.TQ.Connected,async()=>{this.isConnected=!0}),this.room.on(y.TQ.Disconnected,e=>{this.isConnected=!1,this.disconnect({reason:"agent",context:new CloseEvent("close",{reason:e?.toString()})})}),this.room.on(y.TQ.ConnectionStateChanged,e=>{e===y.em.Disconnected&&(this.isConnected=!1,this.disconnect({reason:"error",message:`LiveKit connection state changed to ${e}`,context:new Event("connection_state_changed")}))}),this.room.on(y.TQ.DataReceived,(e,t)=>{try{let t=JSON.parse(new TextDecoder().decode(e));if("audio"===t.type)return;t.type?this.handleMessage(t):console.warn("Invalid socket event received:",t)}catch(t){console.warn("Failed to parse incoming data message:",t),console.warn("Raw payload:",new TextDecoder().decode(e))}}),this.room.on(y.TQ.TrackSubscribed,async(e,t,n)=>{if(e.kind===y.fQ.Kind.Audio&&n.identity.includes("agent")){let t=e.attach();if(t.autoplay=!0,t.controls=!1,this.outputDeviceId&&t.setSinkId)try{await t.setSinkId(this.outputDeviceId)}catch(e){console.warn("Failed to set output device for new audio element:",e)}t.style.display="none",document.body.appendChild(t),this.audioElements.push(t),1===this.audioElements.length&&this.onDebug?.({type:"audio_element_ready"}),await this.setupAudioCapture(e)}}),this.room.on(y.TQ.ActiveSpeakersChanged,async e=>{e.length>0?this.updateMode(e[0].identity.startsWith("agent")?"speaking":"listening"):this.updateMode("listening")}),this.room.on(y.TQ.ParticipantDisconnected,e=>{e.identity?.startsWith("agent")&&this.disconnect({reason:"agent",context:new CloseEvent("close",{reason:"agent disconnected"})})})}close(){if(this.isConnected){try{this.room.localParticipant.audioTrackPublications.forEach(e
125=>{e.track&&e.track.stop()})}catch(e){console.warn("Error stopping local tracks:",e)}this.audioCaptureContext&&(this.audioCaptureContext.close().catch(e=>{console.warn("Error closing audio capture context:",e)}),this.audioCaptureContext=null),this.audioElements.forEach(e=>{e.parentNode&&e.parentNode.removeChild(e)}),this.audioElements=[],this.room.disconnect()}}async sendMessage(e){if(!this.isConnected||!this.room.localParticipant){console.warn("Cannot send message: room not connected or no local participant");return}if(!("user_audio_chunk"in e))try{let t=new TextEncoder().encode(JSON.stringify(e));await this.room.localParticipant.publishData(t,{reliable:!0})}catch(t){this.debug({type:"send_message_error",message:{message:e,error:t}}),console.error("Failed to send message via WebRTC:",t)}}getRoom(){return this.room}async setupAudioCapture(e){try{let t=new AudioContext;this.audioCaptureContext=t,this.outputAnalyser=t.createAnalyser(),this.outputAnalyser.fftSize=2048,this.outputAnalyser.smoothingTimeConstant=.8;let n=new MediaStream([e.mediaStreamTrack]),o=t.createMediaStreamSource(n);o.connect(this.outputAnalyser),await C(t.audioWorklet);let a=new AudioWorkletNode(t,"rawAudioProcessor");this.outputAnalyser.connect(a),a.port.postMessage({type:"setFormat",format:this.outputFormat.format,sampleRate:this.outputFormat.sampleRate}),a.port.onmessage=e=>{let[t,n]=e.data;if(n>.01){let e=_(t.buffer),n=this.audioEventId++;this.handleMessage({type:"audio",audio_event:{audio_base_64:e,event_id:n}})}},o.connect(a)}catch(e){console.warn("Failed to set up audio capture:",e)}}setAudioVolume(e){this.audioElements.forEach(t=>{t.volume=e})}async setAudioOutputDevice(e){if(!("setSinkId"in HTMLAudioElement.prototype))throw Error("setSinkId is not supported in this browser");let t=this.audioElements.map(async t=>{try{await t.setSinkId(e)}catch(e){throw console.error("Failed to set sink ID for audio element:",e),e}});await Promise.all(t),this.outputDeviceId=e}async setAudioInputDevice(e){if(!this.isConnected||!this.room.localParticipant)throw Error("Cannot change input device: room not connected or no local participant");try{let t=this.room.localParticipant.getTrackPublication(y.fQ.Source.Microphone);t?.track&&(await t.track.stop(),await this.room.localParticipant.unpublishTrack(t.track));let n=await (0,y.s1)({deviceId:{exact:e},echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,channelCount:{ideal:1}});await this.room.localParticipant.publishTrack(n,{name:"microphone",source:y.fQ.Source.Microphone})}catch(e){console.error("Failed to change input device:",e);try{await this.room.localParticipant.setMicrophoneEnabled(!0)}catch(e){console.error("Failed to recover microphone after device switch error:",e)}throw e}}getOutputByteFrequencyData(){return this.outputAnalyser?(this.outputFrequencyData??=new Uint8Array(this.outputAnalyser.frequencyBinCount),this.outputAnalyser.getByteFrequencyData(this.outputFrequencyData),this.outputFrequencyData):null}}async function S(e){let t=function(e){let t="signedUrl"in e&&e.signedUrl;if(t&&"webrtc"===e.connectionType)throw Error("signedUrl only supports websocket connections. Remove connectionType or set it to 'websocket'.");return e.connectionType?e.connectionType:"conversationToken"in e&&e.conversationToken?"webrtc":t?"websocket":e.textOnly?"websocket":"webrtc"}(e);switch(t){case"websocket":return d.create(e);case"webrtc":return k.create(e);default:throw Error(`Unknown connection type: ${t}`)}}function E(){return["iPad Simulator","iPhone Simulator","iPod Simulator","iPad","iPhone","iPod"].includes(navigator.platform)||navigator.userAgent.includes("Mac")&&"ontouchend"in document}async function A(e={default:0,android:3e3}){let t=e.default;/android/i.test(navigator.userAgent)?t=e.android??t:E()&&(t=e.ios??t),t>0&&await new Promise(e=>setTimeout(e,t))}let T=new Uint8Array(0);class M extends a{type="text";setVolume(){throw Error("setVolume is not supported in text conversations")}setMicMuted(){throw Error("setMicMuted is not supported in text conversations")}getInputByteFrequencyData(){return T}getOutputByteFrequencyData(){return T}getInputVolume(){return 0}getOutputVolume(){return 0}static async startSession(e){let t=a.getFullOptions(e);t.onStatusChange&&t.onStatusChange({status:"connecting"}),t.onCanSendFeedbackChange&&t.onCanSendFeedbackChange({canSendFeedback:!1}),t.onModeChange&&t.onModeChange({mode:"listening"}),t.onCanSendFeedbackChange&&t.onCanSendFeedbackChange({canSendFeedback:!1});let n=null;try{return await A(t.connectionDelay),n=await S(t),new M(t,n)}catch(e){throw t.onStatusChange&&t.onStatusChange({status:"disconnected"}),n?.close(),e}}}let I=b("audioConcatProcessor",`/* 126 * ulaw decoding logic taken from the wavefile library 127 * https://github.com/rochars/wavefile/blob/master/lib/codecs/mulaw.js 128 * USED BY @elevenlabs/client 129 */ 130 131const decodeTable = [0, 132, 396, 924, 1980, 4092, 8316, 16764]; 132 133function decodeSample(muLawSample) { 134 let sign; 135 let exponent; 136 let mantissa; 137 let sample; 138 muLawSample = ~muLawSample; 139 sign = muLawSample & 0x80; 140 exponent = (muLawSample >> 4) & 0x07; 141 mantissa = muLawSample & 0x0f; 142 sample = decodeTable[exponent] + (mantissa << (exponent + 3)); 143 if (sign !== 0) sample = -sample; 144 145 return sample; 146} 147 148class AudioConcatProcessor extends AudioWorkletProcessor { 149 constructor() { 150 super(); 151 this.buffers = []; // Initialize an empty buffer 152 this.cursor = 0; 153 this.currentBuffer = null; 154 this.wasInterrupted = false;
155 this.finished = false; 156 157 this.port.onmessage = ({ data }) => { 158 switch (data.type) { 159 case "setFormat": 160 this.format = data.format; 161 if (globalThis.LibSampleRate && sampleRate !== data.sampleRate) { 162 globalThis.LibSampleRate.create( 163 1, 164 data.sampleRate, 165 sampleRate 166 ).then(resampler => { 167 this.resampler = resampler; 168 }); 169 } 170 break; 171 case "buffer": 172 this.wasInterrupted = false; 173 this.buffers.push( 174 this.format === "ulaw" 175 ? new Uint8Array(data.buffer) 176 : new Int16Array(data.buffer) 177 ); 178 break; 179 case "interrupt": 180 this.wasInterrupted = true; 181 break; 182 case "clearInterrupted": 183 if (this.wasInterrupted) { 184 this.wasInterrupted = false; 185 this.buffers = []; 186 this.currentBuffer = null; 187 } 188 } 189 }; 190 } 191 process(_, outputs) { 192 let finished = false; 193 const output = outputs[0][0]; 194 for (let i = 0; i < output.length; i++) { 195 if (!this.currentBuffer) { 196 if (this.buffers.length === 0) { 197 finished = true; 198 break; 199 } 200 this.currentBuffer = this.buffers.shift(); 201 if (this.resampler) { 202 this.currentBuffer = this.resampler.full(this.currentBuffer); 203 } 204 this.cursor = 0; 205 } 206 207 let value = this.currentBuffer[this.cursor]; 208 if (this.format === "ulaw") { 209 value = decodeSample(value); 210 } 211 output[i] = value / 32768; 212 this.cursor++; 213 214 if (this.cursor >= this.currentBuffer.length) { 215 this.currentBuffer = null; 216 } 217 } 218 219 if (this.finished !== finished) { 220 this.finished = finished; 221 this.port.postMessage({ type: "process", finished }); 222 } 223 224 return true; // Continue processing 225 } 226} 227 228registerProcessor("audioConcatProcessor", AudioConcatProcessor); 229`);async function D(e,t){await e.audioWorklet.addModule(t||"https://cdn.jsdelivr.net/npm/@alexanderolsen/[email protected]/dist/libsamplerate.worklet.js")}class R{context;analyser;gain;worklet;audioElement;static async create({sampleRate:e,format:t,outputDeviceId:n,workletPaths:o,libsampleratePath:a}){let s=null,i=null;try{let r=navigator.mediaDevices.getSupportedConstraints().sampleRate,c=(s=new AudioContext(r?{sampleRate:e}:{})).createAnalyser(),l=s.createGain();(i=new Audio).src="",i.load(),i.autoplay=!0,i.style.display="none",document.body.appendChild(i);let u=s.createMediaStreamDestination();i.srcObject=u.stream,l.connect(c),c.connect(u),r&&s.sampleRate===e||(s.sampleRate!==e&&console.warn(`[ConversationalAI] Sample rate ${e} not available, resampling to ${s.sampleRate}`),await D(s,a)),await I(s.audioWorklet,o?.audioConcatProcessor);let d=new AudioWorkletNode(s,"audioConcatProcessor");return d.port.postMessage({type:"setFormat",format:t,sampleRate:e}),d.connect(l),await s.resume(),n&&i.setSinkId&&await i.setSinkId(n),new R(s,c,l,d,i)}catch(e){throw i?.parentNode&&i.parentNode.removeChild(i),i?.pause(),s&&"closed"!==s.state&&await s.close(),e}}volume=1;interrupted=!1;interruptTimeout=null;constructor(e,t,n,o,a){this.context=e,this.analyser=t,this.gain=n,this.worklet=o,this.audioElement=a,this.worklet.port.start()}getAnalyser(){return this.analyser}addListener(e){this.worklet.port.addEventListener("message",e)}removeListener(e){this.worklet.port.removeEventListener("message",e)}setVolume(e){this.volume=e,this.gain.gain.value=e}playAudio(e){this.interrupted||this.worklet.port.postMessage({type:"buffer",buffer:e})}interrupt(e=2e3){this.interrupted=!0,this.interruptTimeout&&(clearTimeout(this.interruptTimeout),this.interruptTimeout=null),this.worklet.port.postMessage({type:"interrupt"}),this.gain.gain.exponentialRampToValueAtTime(1e-4,this.context.currentTime+e/1e3),this.interruptTimeout=setTimeout(()=>{this.interrupted=!1,this.gain.gain.value=this.volume,this.worklet.port.postMessage({type:"clearInterrupted"}),this.interruptTimeout=null},e)}async setDevice(e){if(!("setSinkId"in HTMLAudioElement.prototype))throw Error("setSinkId is not supported in this browser");let t=e?.outputDeviceId;await this.audioElement.setSinkId(t||"")}async close(){this.interruptTimeout&&(clearTimeout(this.interruptTimeout),this.interruptTimeout=null),this.audioElement.parentNode&&this.audioElement.parentNode.removeChild(this.audioElement),this.audioElement.pause(),await this.context.close()}}let x={echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,channelCount:{ideal:1}};class P{context;analyser;worklet;inputStream;mediaStreamSource;permissions;onError;static async create({sampleRate:e,format:t,preferHeadphonesForIosDevices:n,inputDeviceId:o,workletPaths:a,libsampleratePath:s,onError:i}){let r=null,c=null;try{let l={sampleRate:{ideal:e},...x};if(E()&&n){let e=(await window.navigator.mediaDevices.enumerateDevices()).find(e=>"audioinput"===e.kind&&["airpod","headphone","earphone"].find(t=>e.label.toLowerCase().includes(t)));e&&(l.deviceId={ideal:e.deviceId})}o&&(l.deviceId=P.getDeviceIdConstraint(o));let u=navigator.mediaDevices.getSupportedConstraints().sampleRate,d=(r=new window.AudioContext(u?{sampleRate:e}:{})).createAnalyser();u||await D(r,s),await C(r.audioWorklet,a?.rawAudioProcessor);let h={voiceIsolation:!0,...l};c=await navigator.mediaDevices.getUserMedia({audio:h});let p=r.createMediaStreamSource(c),m=new AudioWorkletNode(r,"rawAudioProcessor");m.port.postMessage({type:"setFormat",format:t,sampleRate:e}),p.connect(d),d.connect(m),await r.resume();let g=await navigator.permissions.query({name:"microphone"});return new P(r,d,m,c,p,g,i)}
229catch(e){throw c?.getTracks().forEach(e=>{e.stop()}),r?.close(),e}}static getDeviceIdConstraint(e){if(e)return E()?{ideal:e}:{exact:e}}muted=!1;constructor(e,t,n,o,a,s,i=console.error){this.context=e,this.analyser=t,this.worklet=n,this.inputStream=o,this.mediaStreamSource=a,this.permissions=s,this.onError=i,this.permissions.addEventListener("change",this.handlePermissionsChange),this.worklet.port.start()}getAnalyser(){return this.analyser}isMuted(){return this.muted}addListener(e){this.worklet.port.addEventListener("message",e)}removeListener(e){this.worklet.port.removeEventListener("message",e)}forgetInputStreamAndSource(){for(let e of this.inputStream.getTracks())e.stop();this.mediaStreamSource.disconnect()}async close(){this.forgetInputStreamAndSource(),this.permissions.removeEventListener("change",this.handlePermissionsChange),await this.context.close()}async setMuted(e){this.muted=e,this.worklet.port.postMessage({type:"setMuted",isMuted:e})}settingInput=!1;async setDevice(e){try{if(this.settingInput)throw Error("Input device is already being set");this.settingInput=!0;let t=e?.inputDeviceId,n={...x};t&&(n.deviceId=P.getDeviceIdConstraint(t));let o={voiceIsolation:!0,...n},a=await navigator.mediaDevices.getUserMedia({audio:o});this.forgetInputStreamAndSource(),this.inputStream=a,this.mediaStreamSource=this.context.createMediaStreamSource(a),this.mediaStreamSource.connect(this.analyser)}catch(e){throw this.onError("Failed to switch input device:",e),e}finally{this.settingInput=!1}}handlePermissionsChange=()=>{if("denied"===this.permissions.state)this.onError("Microphone permission denied");else if(!this.settingInput){let[e]=this.inputStream.getAudioTracks(),{deviceId:t}=e?.getSettings()??{};this.setDevice({inputDeviceId:t}).catch(e=>{this.onError("Failed to reset input device after permission change:",e)})}}}async function F(e,t){if(t instanceof k)return{input:t.input,output:t.output,playbackEventTarget:null,detach:()=>{}};if(t instanceof d){let[n,o]=await Promise.all([P.create({...t.inputFormat,preferHeadphonesForIosDevices:e.preferHeadphonesForIosDevices,inputDeviceId:e.inputDeviceId,workletPaths:e.workletPaths,libsampleratePath:e.libsampleratePath}),R.create({...t.outputFormat,outputDeviceId:e.outputDeviceId,workletPaths:e.workletPaths})]),a=function(e,t){let n=e=>{let n=e.data[0];t.sendMessage({user_audio_chunk:_(n.buffer)})};return e.addListener(n),()=>{e.removeListener(n)}}(n,t),s=function(e,t){let n=e=>{t.playAudio(function(e){let t=window.atob(e),n=t.length,o=new Uint8Array(n);for(let e=0;e<n;e++)o[e]=t.charCodeAt(e);return o.buffer}(e.audio_base_64))};return e.addListener(n),()=>{e.removeListener(n)}}(t,o);return{input:n,output:o,playbackEventTarget:o,detach:()=>{a(),s()}}}throw Error(`Unsupported connection type: ${t.constructor.name}`)}async function L(e){let t=await S(e),n=await F(e,t);return{connection:t,...n}}let U=new Uint8Array(0);class O extends a{input;output;playbackEventTarget;cleanUp;wakeLock;type="voice";static async requestWakeLock(){if("wakeLock"in navigator)try{return await navigator.wakeLock.request("screen")}catch(e){}return null}static async startSession(e){let t=a.getFullOptions(e);t.onStatusChange&&t.onStatusChange({status:"connecting"}),t.onCanSendFeedbackChange&&t.onCanSendFeedbackChange({canSendFeedback:!1});let n=null,o=e.useWakeLock??!0,s=null;o&&(s=await O.requestWakeLock());try{n=await navigator.mediaDevices.getUserMedia({audio:!0}),await A(t.connectionDelay);let e=await L(t);return n?.getTracks().forEach(e=>{e.stop()}),n=null,new O(t,e.connection,e.input,e.output,e.playbackEventTarget,e.detach,s)}catch(e){t.onStatusChange&&t.onStatusChange({status:"disconnected"}),n?.getTracks().forEach(e=>{e.stop()});try{await s?.release(),s=null}catch(e){}throw e}}inputFrequencyData;outputFrequencyData;visibilityChangeHandler=null;handlePlaybackEvent=e=>{"process"===e.data.type&&this.updateMode(e.data.finished?"listening":"speaking")};constructor(e,t,n,o,a,s,i){super(e,t),this.input=n,this.output=o,this.playbackEventTarget=a,this.cleanUp=s,this.wakeLock=i,a?.addListener(this.handlePlaybackEvent),i&&(this.visibilityChangeHandler=()=>{"visible"===document.visibilityState&&this.wakeLock?.released&&O.requestWakeLock().then(e=>{this.wakeLock=e})},document.addEventListener("visibilitychange",this.visibilityChangeHandler))}async handleEndSession(){this.cleanUp(),this.playbackEventTarget?.removeListener(this.handlePlaybackEvent),this.playbackEventTarget=null,await super.handleEndSession(),this.visibilityChangeHandler&&document.removeEventListener("visibilitychange",this.visibilityChangeHandler);try{await this.wakeLock?.release(),this.wakeLock=null}catch(e){}await this.input.close(),await this.output.close()}handleInterruption(e){super.handleInterruption(e),this.updateMode("listening"),this.output.interrupt()}handleAudio(e){super.handleAudio(e),e.audio_event.alignment&&this.options.onAudioAlignment&&this.options.onAudioAlignment(e.audio_event.alignment),this.lastInterruptTimestamp<=e.audio_event.event_id&&(e.audio_event.audio_base_64&&this.options.onAudio?.(e.audio_event.audio_base_64),this.currentEventId=e.audio_event.event_id,this.updateCanSendFeedback(),this.updateMode("speaking"))}calculateVolume=e=>{if(0===e.length)return 0;let t=0;for(let n=0;n<e.length;n++)t+=e[n]/255;return(t/=e.length)<0?0:t>1?1:t};setMicMuted(e){this.input.setMuted(e).catch(e=>{this.options.onError?.("Failed to set input muted state",e)})}getInputByteFrequencyData(){let e=this.input.getAnalyser();return e?(this.inputFrequencyData??=new Uint8Array(e.frequencyBinCount),e.getByteFrequencyData(this.inputFrequencyData),this.inputFrequencyData):U}getOutputByteFrequencyData(){if(this.connection instanceof k)return this.connection.getOutputByteFrequencyData()||new Uint8Array(1024);let e=this.output.getAnalyser();return e?(this.outputFrequencyData??=new Uint8Array(e.frequencyBinCount),e.getByteFrequencyData(this.outputFrequencyData),this.outputFrequencyData):U}getInputVolume(){return this.calculateVolume(this.getInputByteFrequencyData())}getOutputVolume(){return this.calculateVolume(this.getOutputByteFrequencyData())}async changeInputDevice({sampleRate:e,format:t,preferHeadphonesForIosDevices:n,inputDeviceId:o}){try{await this.input.setDevice({inputDeviceId:o,sampleRate:e,format:t,preferHeadphonesForIosDevices:n})}catch(e){throw console.error("Error changing input device",e),e}}async changeOutputDevice({sampleRate:e,format:t,outputDeviceId:n}){try{await this.output.setDevice({outputDeviceId:n,sampleRate:e,format:t})}catch(e){throw console.error("Error changing output device",e),e}}setVolume=({volume:e})=>{let t=Number.isFinite(e)?Math.min(1,Math.max(0,e)):1;this.volume=t,this.output.setVolume(t)}}(h=g||(g={})).SESSION_STARTED="session_started",h.PARTIAL_TRANSCRIPT="partial_transcript",h.COMMITTED_TRANSCRIPT="committed_transcript",h.COMMITTED_TRANSCRIPT_WITH_TIMESTAMPS="committed_transcript_with_timestamps",h.AUTH_ERROR="auth_error",h.ERROR="error",h.OPEN="open",h.CLOSE="close",h.QUOTA_EXCEEDED="quota_exceeded",h.COMMIT_THROTTLED="commit_throttled",h.TRANSCRIBER_ERROR="transcriber_error",h.UNACCEPTED_TERMS="unaccepted_terms",h.RATE_LIMITED="rate_limited",h.INPUT_ERROR="input_error",h.QUEUE_OVERFLOW="queue_overflow",h.RESOURCE_EXHAUSTED="resource_exhausted",h.SESSION_TIME_LIMIT_EXCEEDED="session_time_limit_exceeded",h.CHUNK_SIZE_EXCEEDED="chunk_size_exceeded",h.INSUFFICIENT_AU
229DIO_ACTIVITY="insufficient_audio_activity",b("scribeAudioProcessor",`/* 230 * Scribe Audio Processor for converting microphone audio to PCM16 format 231 * Supports resampling for browsers like Firefox that don't support 232 * AudioContext sample rate constraints. 233 * USED BY @elevenlabs/client 234 */ 235 236class ScribeAudioProcessor extends AudioWorkletProcessor { 237 constructor() { 238 super(); 239 this.buffer = []; 240 this.bufferSize = 4096; // Buffer size for optimal chunk transmission 241 242 // Resampling state 243 this.inputSampleRate = null; 244 this.outputSampleRate = null; 245 this.resampleRatio = 1; 246 this.lastSample = 0; 247 this.resampleAccumulator = 0; 248 249 this.port.onmessage = ({ data }) => { 250 if (data.type === "configure") { 251 this.inputSampleRate = data.inputSampleRate; 252 this.outputSampleRate = data.outputSampleRate; 253 if (this.inputSampleRate && this.outputSampleRate) { 254 this.resampleRatio = this.inputSampleRate / this.outputSampleRate; 255 } 256 } 257 }; 258 } 259 260 // Linear interpolation resampling 261 resample(inputData) { 262 if (this.resampleRatio === 1 || !this.inputSampleRate) { 263 return inputData; 264 } 265 266 const outputSamples = []; 267 268 for (let i = 0; i < inputData.length; i++) { 269 const currentSample = inputData[i]; 270 271 // Generate output samples using linear interpolation 272 while (this.resampleAccumulator < 1) { 273 const interpolated = 274 this.lastSample + 275 (currentSample - this.lastSample) * this.resampleAccumulator; 276 outputSamples.push(interpolated); 277 this.resampleAccumulator += this.resampleRatio; 278 } 279 280 this.resampleAccumulator -= 1; 281 this.lastSample = currentSample; 282 } 283 284 return new Float32Array(outputSamples); 285 } 286 287 process(inputs) { 288 const input = inputs[0]; 289 if (input.length > 0) { 290 let channelData = input[0]; // Get first channel (mono) 291 292 // Resample if needed (for Firefox and other browsers that don't 293 // support AudioContext sample rate constraints) 294 if (this.resampleRatio !== 1) { 295 channelData = this.resample(channelData); 296 } 297 298 // Add incoming audio to buffer 299 for (let i = 0; i < channelData.length; i++) { 300 this.buffer.push(channelData[i]); 301 } 302 303 // When buffer reaches threshold, convert and send 304 if (this.buffer.length >= this.bufferSize) { 305 const float32Array = new Float32Array(this.buffer); 306 const int16Array = new Int16Array(float32Array.length); 307 308 // Convert Float32 [-1, 1] to Int16 [-32768, 32767] 309 for (let i = 0; i < float32Array.length; i++) { 310 // Clamp the value to prevent overflow 311 const sample = Math.max(-1, Math.min(1, float32Array[i])); 312 // Scale to PCM16 range 313 int16Array[i] = sample < 0 ? sample * 32768 : sample * 32767; 314 } 315 316 // Send to main thread as transferable ArrayBuffer 317 this.port.postMessage( 318 { 319 audioData: int16Array.buffer 320 }, 321 [int16Array.buffer] 322 ); 323 324 // Clear buffer 325 this.buffer = []; 326 } 327 } 328 329 return true; // Continue processing 330 } 331} 332 333registerProcessor("scribeAudioProcessor", ScribeAudioProcessor); 334 335`),(p=f||(f={})).PCM_8000="pcm_8000",p.PCM_16000="pcm_16000",p.PCM_22050="pcm_22050",p.PCM_24000="pcm_24000",p.PCM_44100="pcm_44100",p.PCM_48000="pcm_48000",p.ULAW_8000="ulaw_8000",(m=v||(v={})).MANUAL="manual",m.VAD="vad";let q={startSession:e=>o(e)?M.startSession(e):O.startSession(e)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.