/**
 * Minified by jsDelivr using Terser v5.48.0.
 * Original file: /npm/assemblyai@4.41.5/dist/browser.mjs
 *
 * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
 */
const defaultSyncSpeechModel="universal-3-5-pro";class BrowserOnlyError extends Error{constructor(e="DualChannelCapture requires a browser environment (AudioContext is undefined)."){super(e),this.name="BrowserOnlyError"}}const readFile=async function(e){throw new Error("Interacting with the file system is not supported in this environment.")},DEFAULT_FETCH_INIT={cache:"no-store"},buildUserAgent=e=>defaultUserAgentString+(!1===e?"":" AssemblyAI/1.0 ("+Object.entries({...defaultUserAgent,...e}).map(([e,t])=>t?`${e}=${t.name}/${t.version}`:"").join(" ")+")");let defaultUserAgentString="";"undefined"!=typeof navigator&&navigator.userAgent&&(defaultUserAgentString+=navigator.userAgent);const defaultUserAgent={sdk:{name:"JavaScript",version:"4.41.5"}};"undefined"!=typeof process&&(process.versions.node&&-1===defaultUserAgentString.indexOf("Node")&&(defaultUserAgent.runtime_env={name:"Node",version:process.versions.node}),process.versions.bun&&-1===defaultUserAgentString.indexOf("Bun")&&(defaultUserAgent.runtime_env={name:"Bun",version:process.versions.bun})),"undefined"!=typeof Deno&&process.versions.bun&&-1===defaultUserAgentString.indexOf("Deno")&&(defaultUserAgent.runtime_env={name:"Deno",version:Deno.version.deno});class BaseService{constructor(e){this.params=e,!1===e.userAgent?this.userAgent=void 0:this.userAgent=buildUserAgent(e.userAgent||{})}async fetchResponse(e,t){t={...DEFAULT_FETCH_INIT,...t};let s={Authorization:this.params.apiKey};return t.body instanceof FormData||(s["Content-Type"]="application/json"),DEFAULT_FETCH_INIT?.headers&&(s={...s,...DEFAULT_FETCH_INIT.headers}),t?.headers&&(s={...s,...t.headers}),this.userAgent&&(s["User-Agent"]=this.userAgent,"undefined"!=typeof window&&"chrome"in window&&(s["AssemblyAI-Agent"]=this.userAgent)),t.headers=s,e.startsWith("http")||(e=this.params.baseUrl+e),await fetch(e,t)}async fetch(e,t){const s=await this.fetchResponse(e,t);if(s.status>=400){let e;const t=await s.text();if(t){try{e=JSON.parse(t)}catch{}if(e?.error)throw new Error(e.error);throw new Error(t)}throw new Error(`HTTP Error: ${s.status} ${s.statusText}`)}return s}async fetchJson(e,t){return(await this.fetch(e,t)).json()}}class SyncTranscriptError extends Error{constructor(e,t,s,r){super(e),this.status=t,this.errorCode=s,this.retryAfter=r,this.name="SyncTranscriptError"}}function getPath(e){return e.startsWith("http")||e.startsWith("https")||e.startsWith("data:")?null:e.startsWith("file://")?e.substring(7):e.startsWith("file:")?e.substring(5):e}const encoder=new TextEncoder;function multipartBoundary(){let e="";for(;e.length<32;)e+=Math.random().toString(36).slice(2);return`----assemblyai-${e.slice(0,32)}`}function escapeFormParam(e){return e.replace(/["\\\x00-\x1a\x1c-\x1f]/g,e=>'"'===e?"%22":"\\"===e?"\\\\":`%${e.charCodeAt(0).toString(16).toUpperCase().padStart(2,"0")}`)}function multipartHead(e){const{boundary:t,config:s,filename:r,contentType:n}=e;return encoder.encode(`--${t}\r\nContent-Disposition: form-data; name="config"\r\nContent-Type: application/json\r\n\r\n`+JSON.stringify(s??{})+"\r\n"+`--${t}\r\nContent-Disposition: form-data; `+`name="audio"; filename="${escapeFormParam(r)}"\r\n`+`Content-Type: ${n}\r\n\r\n`)}function multipartClosing(e){return encoder.encode(`\r\n--${e}--\r\n`)}function asBytes(e){if(e instanceof Uint8Array)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);if("string"==typeof e)throw new TypeError("live audio chunks must be bytes (Uint8Array, Buffer or ArrayBuffer), not strings. Read the source in binary mode or encode the output.");throw new TypeError(`live audio chunks must be bytes (Uint8Array, Buffer or ArrayBuffer), got ${describe(e)}`)}function describe(e){return null===e?"null":"object"!=typeof e?typeof e:e.constructor?.name??"object"}function isWebReadableStream(e){return"function"==typeof e?.getReader}function isIterable(e){const t=e;return"function"==typeof t?.[Symbol.asyncIterator]||"function"==typeof t?.[Symbol.iterator]}function isAsyncIterable(e){return"function"==typeof e?.[Symbol.asyncIterator]}async function*liveChunks(e){if(isWebReadableStream(e)){const t=e.getReader();try{for(;;){const{done:e,value:s}=await t.read();if(e)return;yield asBytes(s)}}finally{t.releaseLock()}}else for await(const t of e)yield asBytes(t)}function liveBody(e){const{head:t,chunks:s,closing:r}=e,n=s[Symbol.asyncIterator]();let i=!1,a=!1,o=()=>{};const c=new Promise(e=>{o=()=>{a=!0,e({done:!0,value:void 0})}}),l={error:void 0,finish:()=>o(),stream:new ReadableStream({async pull(e){if(!i)return i=!0,void e.enqueue(t);try{for(;;){const t=a?{done:!0,value:void 0}:await Promise.race([n.next(),c]);if(t.done)return a&&n.return?.().catch(()=>{}),e.enqueue(r),void e.close();if(t.value.byteLength>0)return void e.enqueue(t.value)}}catch(e){throw l.error=e,e}},async cancel(){await(n.return?.())}})};return l}class ChunkQueue{constructor(){this.items=[],this.ended=!1}push(e){this.items.push(e),this.wake?.()}end(){this.ended=!0,this.wake?.()}async*[Symbol.asyncIterator](){for(;;)if(this.items.length>0)yield this.items.shift();else{if(this.ended)return;await new Promise(e=>{this.wake=e}),this.wake=void 0}}}class LiveSession{constructor(e){this.queue=new ChunkQueue,this.controller=new AbortController,this.isClosed=!1,this.isAborted=!1,this.isSettled=!1,this.outcome=e(this.queue,this.controller.signal);const t=()=>{this.isSettled=!0};this.outcome.then(t,t)}get closed(){return this.isClosed}write(e){if(this.isClosed||this.isSettled)return;const t=asBytes(e);t.byteLength>0&&this.queue.push(t)}close(){this.isClosed||(this.isClosed=!0,this.queue.end())}async result(){if(this.isAborted)throw new Error("the live session was aborted; there is no result");return this.close(),await this.outcome}async abort(){if(!this.isAborted&&!this.isSettled){this.isAborted=!0,this.isClosed=!0,this.queue.end(),this.controller.abort();try{await this.outcome}catch{}}}stream(){return new WritableStream({write:e=>this.write(e),close:()=>this.close(),abort:()=>this.abort()})}}async function errorFromResponse$1(e,t,s){let r,n;const i=await e.text();try{const e=JSON.parse(i);e&&"object"==typeof e&&!Array.isArray(e)&&("string"==typeof e.error_code&&(r=e.error_code),void 0===r&&"string"==typeof e.title&&(r=e.title.toLowerCase().replace(/ /g,"_")),"string"==typeof e.detail?n=e.detail:"string"==typeof e.message?n=e.message:"string"==typeof e.error&&(n=e.error))}catch{i&&(n=i)}n||(n=`${s} failed with status ${e.status}`);const a=e.headers.get("retry-after"),o=a&&/^\d+$/.test(a)?parseInt(a,10):void 0;return new t(n,e.status,r,o)}const pcmSuffixes=[".pcm",".raw"],defaultContentType="audio/wav";function resolveFormat(e,t,s,r,n){const i=void 0!==e.sample_rate||void 0!==e.channels,a=pcmSuffixes.includes(t)||i;if(a&&(void 0===e.sample_rate||void 0===e.channels))throw new Error(`raw PCM audio requires both sample_rate and channels in ${n}`);return{filename:s??(a?"audio.pcm":"audio.wav"),contentType:a?"audio/pcm":r[t]??"audio/wav"}}function deadlineSignal(e,t){const s=AbortSignal.timeout(e);if(!t)return s;const r=new AbortController,n=e=>()=>r.abort(e.reason);return t.aborted&&r.abort(t.reason),t.addEventListener("abort",n(t),{once:!0}),s.addEventListener("abort",n(s),{once:!0}),r.signal}function basename(e){return e.split(/[\\/]/).pop()??e}function extname(e){const t=e.lastIndexOf(".");return t>0?e.slice(t).toLowerCase():""}function dataUrlToBytes(e){const t=e.split(",")[1],s=atob(t),r=new Uint8Array(s.length);for(let e=0;e<s.length;e++)r[e]=s.charCodeAt(e);return r}async function readStream(e){const t=[],s=e.getReader();for(;;){const{done:e,value:r}=await s.read();if(e)break;t.push(r)}return concatChunks(t)}async function readAsyncIterable(e){const t=[];for await(const s of e)t.push(s);return concatChunks(t)}function concatChunks(e){const t=e.reduce((e,t)=>e+t.length,0),s=new Uint8Array(t);let r=0;for(const t of e)s.set(t,r),r+=t.length;return s}function checkLiveInput(e){if(e instanceof Uint8Array||e instanceof ArrayBuffer||e instanceof Blob)throw new TypeError("transcribeLive() expects a stream or iterable of audio chunks, not the whole audio. Audio you already hold belongs in transcribe(), which is faster for it.");if("string"==typeof e)throw new TypeError("transcribeLive() expects a stream or iterable of audio chunks, not a path. Open the file as a stream, or use transcribe() to let the SDK read it.");if(!isWebReadableStream(e)&&!isIterable(e))throw new TypeError(`unsupported live audio input type: ${describe(e)}`)}class SyncLiveSession extends LiveSession{}const transcribeLiveEndpoint$1="/v1/transcribe/live",warmEndpoint$1="/v1/warm",modelHeader="X-AAI-Model",defaultLiveTimeoutMs$1=18e4,warmTimeoutMs$1=1e4,maxPromptLength=6e3,maxKeytermsPromptLength$1=8e3,maxKeytermsCount$1=100,maxContextTurns=500,maxContextLength=16e3,contentTypes$1={},configName$1="the config";class SyncTranscriber extends BaseService{constructor(e){super(e)}async transcribe(e,t={},s={}){const{bytes:r,filename:n,contentType:i}=await resolveAudio(e,t),a=deadlineSignal(s.timeout??18e4,s.signal);return await this.postLive(singleChunk$1(r),e,t,a,{filename:n,contentType:i})}async transcribeLive(e,t={},s={}){checkLiveInput(e);const r=deadlineSignal(s.timeout??18e4,s.signal);return await this.postLive(liveChunks(e),e,t,r)}openLive(e={},t={}){return new SyncLiveSession((s,r)=>this.postLive(s,void 0,e,deadlineSignal(t.timeout??18e4,r)))}async postLive(e,t,s,r,n){const{filename:i,contentType:a}=n??resolveLiveFormat(t,s),o=multipartBoundary(),c=liveBody({head:multipartHead({boundary:o,config:buildConfigJson$1(s),filename:i,contentType:a}),chunks:e,closing:multipartClosing(o)});let l;try{l=await this.fetchResponse("/v1/transcribe/live",{method:"POST",body:c.stream,headers:{[modelHeader]:s.model??"universal-3-5-pro","Content-Type":`multipart/form-data; boundary=${o}`},duplex:"half",signal:r})}catch(e){throw c.error??e}if(200!==l.status)throw c.finish(),await syncError(l);return await l.json()}async warm(e){try{return await this.fetchResponse("/v1/warm",{method:"GET",headers:{[modelHeader]:e?.model??"universal-3-5-pro"},signal:AbortSignal.timeout(1e4)}),!0}catch{return!1}}}async function*singleChunk$1(e){yield e}async function resolveAudio(e,t){let s,r,n="";if("string"==typeof e){if(/^https?:\/\//i.test(e))throw new Error("SyncTranscriber does not accept URLs. Pass a local file path or audio bytes, or use client.transcripts for URL/async transcription.");if(e.startsWith("data:"))s=dataUrlToBytes(e);else{const t=getPath(e)??e;s=await readStream(await readFile()),r=basename(t),n=extname(r)}}else if(e instanceof Uint8Array)s=e;else if(e instanceof ArrayBuffer)s=new Uint8Array(e);else if(e instanceof Blob){s=new Uint8Array(await e.arrayBuffer());const t=e.name;t&&(r=basename(t),n=extname(r))}else if(isWebReadableStream(e))s=await readStream(e);else{if(!isAsyncIterable(e))throw new TypeError("unsupported audio input type");{s=await readAsyncIterable(e);const t=e.path;"string"==typeof t&&(r=basename(t),n=extname(r))}}return{bytes:s,...resolveFormat(t,n,r,contentTypes$1,"the config")}}function resolveLiveFormat(e,t){const s=e?.path,r="string"==typeof s?basename(s):void 0;return resolveFormat(t,r?extname(r):"",r,contentTypes$1,"the config")}function buildConfigJson$1(e){if(void 0!==e.prompt&&e.prompt.length>6e3)throw new Error(`prompt exceeds 6000 characters (got ${e.prompt.length})`);const t={};void 0!==e.prompt&&(t.prompt=e.prompt);const s=normalizeKeytermsPrompt$1(e.keyterms_prompt);s&&(t.keyterms_prompt=s);const r=normalizeConversationContext(e.conversation_context);return r&&(t.conversation_context=r),void 0!==e.language_codes&&(t.language_codes=e.language_codes),void 0!==e.sample_rate&&(t.sample_rate=e.sample_rate),void 0!==e.channels&&(t.channels=e.channels),void 0!==e.timestamps&&(t.timestamps=e.timestamps),Object.keys(t).length>0?t:void 0}function normalizeKeytermsPrompt$1(e){if(!e)return;const t=e.map(e=>e.trim()).filter(e=>e.length>0);if(t.length>100)throw new Error(`keyterms_prompt exceeds 100 terms (got ${t.length})`);const s=t.reduce((e,t)=>e+t.length,0);if(s>8e3)throw new Error(`keyterms_prompt exceeds 8000 characters (got ${s})`);return t.length>0?t:void 0}function normalizeConversationContext(e){if(void 0===e)return;let t=("string"==typeof e?[e]:e).map(e=>e.trim()).filter(e=>e.length>0),s=t.reduce((e,t)=>e+t.length,0);for(;t.length>0&&(t.length>500||s>16e3);)s-=t[0].length,t=t.slice(1);return t.length>0?t:void 0}async function syncError(e){return await errorFromResponse$1(e,SyncTranscriptError,"sync transcription")}class DictationError extends Error{constructor(e,t,s,r){super(e),this.status=t,this.errorCode=s,this.retryAfter=r,this.name="DictationError"}}class DictationLiveSession extends LiveSession{}const transcribeLiveEndpoint="/v1/transcribe/live",warmEndpoint="/v1/warm",defaultLiveTimeoutMs=3e5,warmTimeoutMs=1e4,maxSttPromptLength=6e3,maxKeytermsPromptLength=8e3,maxKeytermsCount=100,maxLlmInstructionLength=2048,configName="the config",contentTypes={".wav":"audio/wav",".pcm":"audio/pcm",".raw":"audio/pcm",".mp3":"audio/mpeg",".aac":"audio/aac",".mp4":"audio/mp4",".m4a":"audio/x-m4a",".ogg":"audio/ogg",".opus":"audio/opus",".flac":"audio/flac",".webm":"audio/webm"};class DictationTranscriber extends BaseService{constructor(e){super(e)}async transcribeLive(e,t={},s={}){const r=await resolveSource(e),{filename:n,contentType:i}=resolveFormat(t,r.suffix,r.filename,contentTypes,configName),a=deadlineSignal(s.timeout??3e5,s.signal);return await this.postLive(r.chunks,n,i,t,a)}openLive(e={},t={}){return new DictationLiveSession(async(s,r)=>{const{filename:n,contentType:i}=resolveFormat(e,"",void 0,contentTypes,configName);return await this.postLive(s,n,i,e,deadlineSignal(t.timeout??3e5,r))})}async postLive(e,t,s,r,n){const i=multipartBoundary(),a=liveBody({head:multipartHead({boundary:i,config:buildConfigJson(r),filename:t,contentType:s}),chunks:e,closing:multipartClosing(i)});let o;try{o=await this.fetchResponse("/v1/transcribe/live",{method:"POST",body:a.stream,headers:{"Content-Type":`multipart/form-data; boundary=${i}`},duplex:"half",signal:n})}catch(e){throw a.error??e}if(200!==o.status)throw a.finish(),await errorFromResponse$1(o,DictationError,"dictation transcription");const c=await o.json();return{...c,final_text:c.llm_response??c.text}}async warm(){try{return await this.fetchResponse("/v1/warm",{method:"GET",signal:AbortSignal.timeout(1e4)}),!0}catch{return!1}}}async function resolveSource(e){if("string"==typeof e){if(/^https?:\/\//i.test(e))throw new Error("DictationTranscriber does not accept URLs. Pass a local file path, audio bytes, a Blob or a stream of audio chunks, or use client.transcripts for URL transcription.");if(e.startsWith("data:"))return{chunks:singleChunk(dataUrlToBytes(e)),suffix:""};const t=basename(getPath(e)??e);return{chunks:singleChunk(await readStream(await readFile())),filename:t,suffix:extname(t)}}if(e instanceof Uint8Array)return{chunks:singleChunk(e),suffix:""};if(e instanceof ArrayBuffer)return{chunks:singleChunk(new Uint8Array(e)),suffix:""};if(e instanceof Blob){const t=new Uint8Array(await e.arrayBuffer()),s=e.name,r=s?basename(s):void 0;return{chunks:singleChunk(t),filename:r,suffix:r?extname(r):""}}if(isWebReadableStream(e)||isIterable(e)){const t=e.path,s="string"==typeof t?basename(t):void 0;return{chunks:liveChunks(e),filename:s,suffix:s?extname(s):""}}throw new TypeError(`unsupported audio input type: ${describe(e)}`)}async function*singleChunk(e){yield e}function buildConfigJson(e){if(void 0!==e.stt_prompt&&e.stt_prompt.length>6e3)throw new Error(`stt_prompt exceeds 6000 characters (got ${e.stt_prompt.length})`);if(void 0!==e.llm_instruction&&e.llm_instruction.length>2048)throw new Error(`llm_instruction exceeds 2048 characters (got ${e.llm_instruction.length})`);const t={};void 0!==e.sample_rate&&(t.sample_rate=e.sample_rate),void 0!==e.channels&&(t.channels=e.channels),void 0!==e.language_codes&&(t.language_codes=e.language_codes),void 0!==e.stt_prompt&&(t.stt_prompt=e.stt_prompt);const s=normalizeKeytermsPrompt(e.keyterms_prompt);return s&&(t.keyterms_prompt=s),void 0!==e.llm_instruction&&(t.llm_instruction=e.llm_instruction),t}function normalizeKeytermsPrompt(e){if(!e)return;const t=e.map(e=>e.trim()).filter(e=>e.length>0);if(t.length>100)throw new Error(`keyterms_prompt exceeds 100 terms (got ${t.length})`);const s=t.reduce((e,t)=>e+t.length,0);if(s>8e3)throw new Error(`keyterms_prompt exceeds 8000 characters (got ${s})`);return t.length>0?t:void 0}class LlmGatewayError extends Error{constructor(e,t,s,r){super(e),this.status=t,this.requestId=s,this.errors=r,this.name="LlmGatewayError"}}class LlmGatewayService extends BaseService{constructor(e){super(e)}async chatCompletions(e){if(e.stream)throw new Error("LlmGatewayService.chatCompletions does not support stream: true yet");const t=await this.fetchResponse("/v1/chat/completions",{method:"POST",body:JSON.stringify(e)});if(!t.ok)throw await errorFromResponse(t);return await t.json()}async listModels(){const e=await this.fetchResponse("/v1/models",{method:"GET"});if(!e.ok)throw await errorFromResponse(e);return await e.json()}async understanding(e){const t=await this.fetchResponse("/v1/understanding",{method:"POST",body:JSON.stringify(e)});if(!t.ok)throw await errorFromResponse(t);return await t.json()}async validateUnderstanding(e){const t=await this.fetchResponse("/v1/understanding/validate",{method:"POST",body:JSON.stringify(e)});if(!t.ok)throw await errorFromResponse(t)}}async function errorFromResponse(e){let t,s,r;const n=await e.text();try{const e=JSON.parse(n);e&&"object"==typeof e&&!Array.isArray(e)&&("string"==typeof e.message?t=e.message:"string"==typeof e.error&&(t=e.error),"string"==typeof e.request_id&&(s=e.request_id),Array.isArray(e.metadata?.errors)&&(r=e.metadata.errors))}catch{n&&(t=n)}return t||(t=`llm gateway request failed with status ${e.status}`),new LlmGatewayError(t,e.status,s,r)}const RealtimeErrorType={BadSampleRate:4e3,AuthFailed:4001,InsufficientFundsOrFreeAccount:4002,InsufficientFunds:4002,FreeTierUser:4003,NonexistentSessionId:4004,SessionExpired:4008,ClosedSession:4010,RateLimited:4029,UniqueSessionViolation:4030,SessionTimeout:4031,AudioTooShort:4032,AudioTooLong:4033,AudioTooSmallToTranscode:4034,BadJson:4100,BadSchema:4101,TooManyStreams:4102,Reconnected:4103,ReconnectAttemptsExhausted:1013,WordBoostParameterParsingFailed:4104},RealtimeErrorMessages={[RealtimeErrorType.BadSampleRate]:"Sample rate must be a positive integer",[RealtimeErrorType.AuthFailed]:"Not Authorized",[RealtimeErrorType.InsufficientFunds]:"Insufficient funds",[RealtimeErrorType.FreeTierUser]:"This feature is paid-only and requires you to add a credit card. Please visit https://app.assemblyai.com/ to add a credit card to your account.",[RealtimeErrorType.NonexistentSessionId]:"Session ID does not exist",[RealtimeErrorType.SessionExpired]:"Session has expired",[RealtimeErrorType.ClosedSession]:"Session is closed",[RealtimeErrorType.RateLimited]:"Rate limited",[RealtimeErrorType.UniqueSessionViolation]:"Unique session violation",[RealtimeErrorType.SessionTimeout]:"Session Timeout",[RealtimeErrorType.AudioTooShort]:"Audio too short",[RealtimeErrorType.AudioTooLong]:"Audio too long",[RealtimeErrorType.AudioTooSmallToTranscode]:"Audio too small to transcode",[RealtimeErrorType.BadJson]:"Bad JSON",[RealtimeErrorType.BadSchema]:"Bad schema",[RealtimeErrorType.TooManyStreams]:"Too many streams",[RealtimeErrorType.Reconnected]:"This session has been reconnected. This WebSocket is no longer valid.",[RealtimeErrorType.ReconnectAttemptsExhausted]:"Reconnect attempts exhausted",[RealtimeErrorType.WordBoostParameterParsingFailed]:"Could not parse word boost parameter"};class RealtimeError extends Error{}const StreamingErrorType={BadSampleRate:4e3,AuthFailed:4001,InsufficientFunds:4002,FreeTierUser:4003,NonexistentSessionId:4004,SessionExpired:4008,ClosedSession:4010,RateLimited:4029,UniqueSessionViolation:4030,SessionTimeout:4031,AudioTooShort:4032,AudioTooLong:4033,AudioTooSmallToTranscode:4034,BadSchema:4101,TooManyStreams:4102,Reconnected:4103,ServerError:3005,InputValidationError:3006,AudioChunkDurationViolation:3007,MaxSessionDurationExceeded:3008,ConcurrencyLimitExceeded:3009},StreamingErrorMessages={[StreamingErrorType.ServerError]:"Server error",[StreamingErrorType.InputValidationError]:"Input validation error",[StreamingErrorType.AudioChunkDurationViolation]:"Audio chunk duration violation",[StreamingErrorType.MaxSessionDurationExceeded]:"Session expired: maximum session duration exceeded",[StreamingErrorType.ConcurrencyLimitExceeded]:"Too many concurrent sessions",[StreamingErrorType.BadSampleRate]:"Sample rate must be a positive integer",[StreamingErrorType.AuthFailed]:"Not Authorized",[StreamingErrorType.InsufficientFunds]:"Insufficient funds",[StreamingErrorType.FreeTierUser]:"This feature is paid-only and requires you to add a credit card. Please visit https://app.assemblyai.com/ to add a credit card to your account.",[StreamingErrorType.NonexistentSessionId]:"Session ID does not exist",[StreamingErrorType.SessionExpired]:"Session has expired",[StreamingErrorType.ClosedSession]:"Session is closed",[StreamingErrorType.RateLimited]:"Rate limited",[StreamingErrorType.UniqueSessionViolation]:"Unique session violation",[StreamingErrorType.SessionTimeout]:"Session Timeout",[StreamingErrorType.AudioTooShort]:"Audio too short",[StreamingErrorType.AudioTooLong]:"Audio too long",[StreamingErrorType.AudioTooSmallToTranscode]:"Audio too small to transcode",[StreamingErrorType.BadSchema]:"Bad schema",[StreamingErrorType.TooManyStreams]:"Too many streams",[StreamingErrorType.Reconnected]:"This session has been reconnected. This WebSocket is no longer valid."};class StreamingError extends Error{}const{WritableStream:WritableStream$1}="undefined"!=typeof window?window:"undefined"!=typeof global?global:globalThis,PolyfillWebSocket=WebSocket??global?.WebSocket??window?.WebSocket??self?.WebSocket,factory=(e,t)=>t?new PolyfillWebSocket(e,t):new PolyfillWebSocket(e),defaultRealtimeUrl="wss://api.assemblyai.com/v2/realtime/ws",forceEndOfUtteranceMessage='{"force_end_utterance":true}',terminateSessionMessage$1='{"terminate_session":true}',DEFAULT_TERMINATION_TIMEOUT_MS$1=5e3;class RealtimeTranscriber{constructor(e){if(this.listeners={},this.realtimeUrl=e.realtimeUrl??defaultRealtimeUrl,this.sampleRate=e.sampleRate??16e3,this.wordBoost=e.wordBoost,this.encoding=e.encoding,this.endUtteranceSilenceThreshold=e.endUtteranceSilenceThreshold,this.disablePartialTranscripts=e.disablePartialTranscripts,"token"in e&&e.token&&(this.token=e.token),"apiKey"in e&&e.apiKey&&(this.apiKey=e.apiKey),!this.token&&!this.apiKey)throw new Error("API key or temporary token is required.")}connectionUrl(){const e=new URL(this.realtimeUrl);if("wss:"!==e.protocol)throw new Error("Invalid protocol, must be wss");const t=new URLSearchParams;return this.token&&t.set("token",this.token),t.set("sample_rate",this.sampleRate.toString()),this.wordBoost&&this.wordBoost.length>0&&t.set("word_boost",JSON.stringify(this.wordBoost)),this.encoding&&t.set("encoding",this.encoding),t.set("enable_extra_session_information","true"),this.disablePartialTranscripts&&t.set("disable_partial_transcripts",this.disablePartialTranscripts.toString()),e.search=t.toString(),e}on(e,t){this.listeners[e]=t}connect(){return new Promise((e,t)=>{if(this.socket)throw new Error("Already connected");this.connectReject=t;const s=this.connectionUrl();this.token?this.socket=factory(s.toString()):(console.warn("API key authentication is not supported for the RealtimeTranscriber in browser environment. Use temporary token authentication instead.\nLearn more at https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/docs/compat.md#browser-compatibility."),this.socket=factory(s.toString(),{headers:{Authorization:this.apiKey}})),this.socket.binaryType="arraybuffer",this.socket.onopen=()=>{void 0!==this.endUtteranceSilenceThreshold&&null!==this.endUtteranceSilenceThreshold&&this.configureEndUtteranceSilenceThreshold(this.endUtteranceSilenceThreshold)},this.socket.onclose=({code:e,reason:t})=>{t||e in RealtimeErrorMessages&&(t=RealtimeErrorMessages[e]),this.resolveSessionTermination();const s=this.connectReject;s&&(this.connectReject=void 0,this.discardPendingSocket(),s(new Error(`Realtime connection closed before session started: ${e} ${t??""}`.trim()))),this.listeners.close?.(e,t)},this.socket.onerror=e=>{const t=e.error?e.error:new Error(e.message),s=this.connectReject;s&&(this.connectReject=void 0,this.discardPendingSocket(),s(t)),this.listeners.error?.(t)},this.socket.onmessage=({data:t})=>{const s=JSON.parse(t.toString());if("error"in s)this.listeners.error?.(new RealtimeError(s.error));else switch(s.message_type){case"SessionBegins":{const t={sessionId:s.session_id,expiresAt:new Date(s.expires_at)};this.connectReject=void 0,e(t),this.listeners.open?.(t);break}case"PartialTranscript":s.created=new Date(s.created),this.listeners.transcript?.(s),this.listeners["transcript.partial"]?.(s);break;case"FinalTranscript":s.created=new Date(s.created),this.listeners.transcript?.(s),this.listeners["transcript.final"]?.(s);break;case"SessionInformation":this.listeners.session_information?.(s);break;case"SessionTerminated":this.resolveSessionTermination()}}})}sendAudio(e){this.send(e)}stream(){return new WritableStream$1({write:e=>{this.sendAudio(e)}})}forceEndUtterance(){this.send(forceEndOfUtteranceMessage)}configureEndUtteranceSilenceThreshold(e){this.send(`{"end_utterance_silence_threshold":${e}}`)}send(e){if(!this.socket||this.socket.readyState!==this.socket.OPEN)throw new Error("Socket is not open for communication");this.socket.send(e)}resolveSessionTermination(){const e=this.sessionTerminatedResolve;this.sessionTerminatedResolve=void 0,e?.()}discardPendingSocket(){if(this.socket){try{this.socket.removeAllListeners&&(this.socket.removeAllListeners(),this.socket.onerror=()=>{}),this.socket.close()}catch{}this.socket=void 0}}async waitForTermination(e,t){if(t<=0)return void await e;let s;try{await Promise.race([e,new Promise(e=>{s=setTimeout(e,t)})])}finally{s&&clearTimeout(s),this.sessionTerminatedResolve=void 0}}async close(e=!0,t=5e3){if(this.socket){if(this.socket.readyState===this.socket.OPEN)if(e){const e=new Promise(e=>{this.sessionTerminatedResolve=e});this.socket.send(terminateSessionMessage$1),await this.waitForTermination(e,t)}else this.socket.send(terminateSessionMessage$1);this.socket?.removeAllListeners&&(this.socket.removeAllListeners(),this.socket.onerror=()=>{}),this.socket.close()}this.listeners={},this.socket=void 0}}class RealtimeService extends RealtimeTranscriber{}class RealtimeTranscriberFactory extends BaseService{constructor(e){super(e),this.rtFactoryParams=e}createService(e){return this.transcriber(e)}transcriber(e){const t={...e};return t.token||t.apiKey||(t.apiKey=this.rtFactoryParams.apiKey),new RealtimeTranscriber(t)}async createTemporaryToken(e){return(await this.fetchJson("/v2/realtime/token",{method:"POST",body:JSON.stringify(e)})).token}}class RealtimeServiceFactory extends RealtimeTranscriberFactory{}class TranscriptService extends BaseService{constructor(e,t){super(e),this.files=t}async transcribe(e,t){const s=await this.submit(e);return await this.waitUntilReady(s.id,t)}async submit(e){let t,s;if("audio"in e){const{audio:r,...n}=e;if("string"==typeof r){const e=getPath(r);t=null!==e?await this.files.upload(e):r.startsWith("data:")?await this.files.upload(r):r}else t=await this.files.upload(r);s={...n,audio_url:t}}else s=e;return await this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(s)})}async create(e,t){const s=getPath(e.audio_url);if(null!==s){const t=await this.files.upload(s);e.audio_url=t}const r=await this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(e)});return t?.poll??1?await this.waitUntilReady(r.id,t):r}async waitUntilReady(e,t){const s=t?.pollingInterval??3e3,r=t?.pollingTimeout??-1,n=Date.now();for(;;){const t=await this.get(e);if("completed"===t.status||"error"===t.status)return t;if(r>0&&Date.now()-n>r)throw new Error("Polling timeout");await new Promise(e=>setTimeout(e,s))}}get(e){return this.fetchJson(`/v2/transcript/${e}`)}async list(e){let t="/v2/transcript";"string"==typeof e?t=e:e&&(t=`${t}?${new URLSearchParams(Object.keys(e).map(t=>[t,e[t]?.toString()||""]))}`);const s=await this.fetchJson(t);for(const e of s.transcripts)e.created=new Date(e.created),e.completed&&(e.completed=new Date(e.completed));return s}delete(e){return this.fetchJson(`/v2/transcript/${e}`,{method:"DELETE"})}wordSearch(e,t){const s=new URLSearchParams({words:t.join(",")});return this.fetchJson(`/v2/transcript/${e}/word-search?${s.toString()}`)}sentences(e){return this.fetchJson(`/v2/transcript/${e}/sentences`)}paragraphs(e){return this.fetchJson(`/v2/transcript/${e}/paragraphs`)}async subtitles(e,t="srt",s){let r=`/v2/transcript/${e}/${t}`;if(s){const e=new URLSearchParams;e.set("chars_per_caption",s.toString()),r+=`?${e.toString()}`}const n=await this.fetch(r);return await n.text()}redactions(e){return this.redactedAudio(e)}redactedAudio(e){return this.fetchJson(`/v2/transcript/${e}/redacted-audio`)}async redactedAudioFile(e){const{redacted_audio_url:t,status:s}=await this.redactedAudio(e);if("redacted_audio_ready"!==s)throw new Error(`Redacted audio status is ${s}`);const r=await fetch(t);if(!r.ok)throw new Error(`Failed to fetch redacted audio: ${r.statusText}`);return{arrayBuffer:r.arrayBuffer.bind(r),blob:r.blob.bind(r),body:r.body,bodyUsed:r.bodyUsed}}}class FileService extends BaseService{async upload(e){let t;t="string"==typeof e?e.startsWith("data:")?dataUrlToBlob(e):await readFile():e;return(await this.fetchJson("/v2/upload",{method:"POST",body:t,headers:{"Content-Type":"application/octet-stream"},duplex:"half"})).upload_url}}function dataUrlToBlob(e){const t=e.split(","),s=t[0].match(/:(.*?);/)[1],r=atob(t[1]);let n=r.length;const i=new Uint8Array(n);for(;n--;)i[n]=r.charCodeAt(n);return new Blob([i],{type:s})}class EnergyVad{constructor(e={}){this.hangoverRemaining=0,this.thresholdRatio=e.thresholdRatio??3,this.noiseFloorAlpha=e.noiseFloorAlpha??.05,this.hangoverFrames=e.hangoverFrames??10,this.initialNoiseFloor=e.initialNoiseFloor??1e-4,this.noiseFloor=this.initialNoiseFloor}process(e){let t=0;for(let s=0;s<e.length;s++)t+=e[s]*e[s];const s=e.length>0?Math.sqrt(t/e.length):0;let r=s>this.noiseFloor*this.thresholdRatio;return r?this.hangoverRemaining=this.hangoverFrames:this.hangoverRemaining>0?(this.hangoverRemaining--,r=!0):this.noiseFloor=this.noiseFloor*(1-this.noiseFloorAlpha)+s*this.noiseFloorAlpha,{active:r,energy:s}}reset(){this.noiseFloor=this.initialNoiseFloor,this.hangoverRemaining=0}}class VadTimeline{constructor(e){this.windowMs=e,this.frames=[],this.head=0}pushFrame(e){this.frames.push(e);const t=e.ts-this.windowMs;for(;this.head<this.frames.length&&this.frames[this.head].ts<t;)this.head++;this.head>1024&&2*this.head>this.frames.length&&(this.frames=this.frames.slice(this.head),this.head=0)}framesInWindow(e,t){const s=[];for(let r=this.head;r<this.frames.length;r++){const n=this.frames[r];if(!(n.ts<e)){if(n.ts>t)break;s.push(n)}}return s}clear(){this.frames=[],this.head=0}}function scoreChannels(e){const t=new Map;for(const s of e)s.active&&t.set(s.channel,(t.get(s.channel)??0)+s.rms);return t}function attributeWord(e,t,s){const r=scoreChannels(t.framesInWindow(e.start,e.end));if(0===r.size)return"unknown";const n=[...r.entries()].sort((e,t)=>t[1]-e[1]);if(1===n.length)return n[0][0];const[i,a]=n[0],[o,c]=n[1];return a>=s.dominanceRatio*c||a>c?i:c>a?o:"unknown"}function rollUpTurnChannel(e){const t=new Map;for(const s of e){if(!s.channel||"unknown"===s.channel)continue;const e=Math.max(0,s.end-s.start);t.set(s.channel,(t.get(s.channel)??0)+e)}if(0===t.size)return"unknown";const s=[...t.entries()].sort((e,t)=>t[1]-e[1]);if(1===s.length)return s[0][0];const[r,n]=s[0],[,i]=s[1];return n===i?"unknown":r}function attributeTurn(e,t,s){for(const r of e.words)r.channel=attributeWord(r,t,s);e.channel=rollUpTurnChannel(e.words)}function toInt16View(e){if(e instanceof Int16Array)return e;if(ArrayBuffer.isView(e)){const t=e;return new Int16Array(t.buffer,t.byteOffset,Math.floor(t.byteLength/2))}return new Int16Array(e)}const defaultStreamingUrl$1="wss://streaming.assemblyai.com/v3/ws",terminateSessionMessage='{"type":"Terminate"}',DEFAULT_CONNECT_TIMEOUT_MS=1e3,DEFAULT_TERMINATION_TIMEOUT_MS=5e3,DEFAULT_MAX_CONNECTION_RETRIES=2,DEFAULT_CONNECTION_RETRY_DELAY_MS=500,NON_RETRYABLE_CLOSE_CODES=new Set([StreamingErrorType.BadSampleRate,StreamingErrorType.AuthFailed,StreamingErrorType.InsufficientFunds,StreamingErrorType.FreeTierUser,StreamingErrorType.BadSchema]);function isRetryableCloseCode(e){return 1e3!==e&&!NON_RETRYABLE_CLOSE_CODES.has(e)}const MAX_CHUNK_MS=200,MIN_CHUNK_MS=50;class StreamingTranscriber{constructor(e){if(this.listeners={},this.isDualChannel=!1,this.vadFrameSamples=0,this.minChunkSamples=0,this.maxChunkSamples=0,this.params={...e,websocketBaseUrl:e.websocketBaseUrl||defaultStreamingUrl$1},"token"in e&&e.token&&(this.token=e.token),"apiKey"in e&&e.apiKey&&(this.apiKey=e.apiKey),!this.token&&!this.apiKey)throw new Error("API key or temporary token is required.");const t="opus"===e.encoding||"ogg_opus"===e.encoding||"aac"===e.encoding;if(void 0===e.sampleRate&&(!t||e.channels))throw new Error('`sampleRate` is required; it may only be omitted when `encoding` is "opus", "ogg_opus", or "aac" (these streams are self-describing) and dual-channel mode is not used.');if(e.channels){if(2!==e.channels.length)throw new Error("StreamingTranscriber.channels must have exactly 2 entries.");const t=e.channels.map(e=>e.name);if(new Set(t).size!==t.length)throw new Error("StreamingTranscriber.channels names must be unique.");this.isDualChannel=!0,this.channelNames=t;const s=e.channelAttribution??{};this.attributionParams={dominanceRatio:s.dominanceRatio??4,timelineWindowMs:s.timelineWindowMs??3e4,createVad:s.createVad??(()=>new EnergyVad),flushIntervalMs:s.flushIntervalMs??50,resolveUnknownChannelsMethod:s.resolveUnknownChannelsMethod??"window",resolutionWindowWords:s.resolutionWindowWords??2,speakerHistoryMinRmsEvidence:s.speakerHistoryMinRmsEvidence??.5,speakerHistoryDominanceRatio:s.speakerHistoryDominanceRatio??3},"speaker-history"===this.attributionParams.resolveUnknownChannelsMethod&&(this.speakerHistory=new Map);const r=e.sampleRate;this.vadFrameSamples=Math.max(1,Math.round(.02*r)),this.minChunkSamples=Math.max(1,Math.round(.05*r)),this.maxChunkSamples=Math.max(this.minChunkSamples,Math.round(.2*r)),this.channelBuffers=new Map(t.map(e=>[e,[]])),this.channelSamplesReceived=new Map(t.map(e=>[e,0])),this.channelVadFloatBuffers=new Map(t.map(e=>[e,new Float32Array(this.vadFrameSamples)])),this.channelVadBufferIdx=new Map(t.map(e=>[e,0])),this.channelVads=new Map(t.map(e=>[e,this.attributionParams.createVad(e)])),this.timeline=new VadTimeline(this.attributionParams.timelineWindowMs)}}resolveSessionTermination(){const e=this.sessionTerminatedResolve;this.sessionTerminatedResolve=void 0,e?.()}connectionUrl(){const e=new URL(this.params.websocketBaseUrl??"");if("wss:"!==e.protocol)throw new Error("Invalid protocol, must be wss");const t=new URLSearchParams;this.token&&t.set("token",this.token),void 0!==this.params.sampleRate&&t.set("sample_rate",this.params.sampleRate.toString()),this.params.endOfTurnConfidenceThreshold&&t.set("end_of_turn_confidence_threshold",this.params.endOfTurnConfidenceThreshold.toString()),void 0!==this.params.minEndOfTurnSilenceWhenConfident&&(void 0!==this.params.minTurnSilence?console.warn("[Deprecation Warning] Both `minEndOfTurnSilenceWhenConfident` and `minTurnSilence` are set. Using `minTurnSilence`; `minEndOfTurnSilenceWhenConfident` is deprecated."):console.warn("[Deprecation Warning] `minEndOfTurnSilenceWhenConfident` is deprecated and will be removed in a future release. Please use `minTurnSilence` instead."));const s=this.params.minTurnSilence??this.params.minEndOfTurnSilenceWhenConfident;return void 0!==s&&t.set("min_turn_silence",s.toString()),this.params.maxTurnSilence&&t.set("max_turn_silence",this.params.maxTurnSilence.toString()),void 0!==this.params.vadThreshold&&t.set("vad_threshold",this.params.vadThreshold.toString()),this.params.formatTurns&&t.set("format_turns",this.params.formatTurns.toString()),void 0!==this.params.sessionHeartbeat&&t.set("session_heartbeat",this.params.sessionHeartbeat.toString()),void 0!==this.params.acknowledgeSilence&&t.set("acknowledge_silence",this.params.acknowledgeSilence.toString()),this.params.encoding&&t.set("encoding",this.params.encoding.toString()),this.params.keytermsPrompt?t.set("keyterms_prompt",JSON.stringify(this.params.keytermsPrompt)):this.params.keyterms&&(console.warn("[Deprecation Warning] `keyterms` is deprecated and will be removed in a future release. Please use `keytermsPrompt` instead."),t.set("keyterms_prompt",JSON.stringify(this.params.keyterms))),this.params.prompt&&t.set("prompt",this.params.prompt),this.params.agentContext&&t.set("agent_context",this.params.agentContext),this.params.filterProfanity&&t.set("filter_profanity",this.params.filterProfanity.toString()),"u3-pro"===this.params.speechModel&&console.warn("[Deprecation Warning] The speech model `u3-pro` is deprecated and will be removed in a future release. Please use `u3-rt-pro` instead."),void 0!==this.params.speechModel&&t.set("speech_model",this.params.speechModel.toString()),void 0!==this.params.languageCode&&(console.warn("[Deprecation Warning] `languageCode` is deprecated and will be removed in a future release. Please use `languageCodes` instead."),t.set("language_code",this.params.languageCode)),void 0!==this.params.languageCodes&&t.set("language_codes",JSON.stringify(this.params.languageCodes)),void 0!==this.params.languageDetection&&t.set("language_detection",this.params.languageDetection.toString()),this.params.domain&&t.set("domain",this.params.domain),void 0!==this.params.inactivityTimeout&&t.set("inactivity_timeout",this.params.inactivityTimeout.toString()),void 0!==this.params.speakerLabels&&t.set("speaker_labels",this.params.speakerLabels.toString()),void 0!==this.params.maxSpeakers&&t.set("max_speakers",this.params.maxSpeakers.toString()),void 0!==this.params.speakerLabelsRevisionIntervalMs&&t.set("speaker_labels_revision_interval_ms",this.params.speakerLabelsRevisionIntervalMs.toString()),this.params.voiceFocus&&t.set("voice_focus",this.params.voiceFocus),void 0!==this.params.voiceFocusThreshold&&t.set("voice_focus_threshold",this.params.voiceFocusThreshold.toString()),void 0!==this.params.continuousPartials&&t.set("continuous_partials",this.params.continuousPartials.toString()),void 0!==this.params.interruptionDelay&&t.set("interruption_delay",this.params.interruptionDelay.toString()),void 0!==this.params.turnLeftPadMs&&t.set("turn_left_pad_ms",this.params.turnLeftPadMs.toString()),this.params.customerSupportAudioCapture&&(console.warn("`customerSupportAudioCapture=true` will record session audio. Only enable this when explicitly coordinating with AssemblyAI support."),t.set("_customer_support_audio_capture",this.params.customerSupportAudioCapture.toString())),this.params.webhookUrl&&t.set("webhook_url",this.params.webhookUrl),this.params.webhookAuthHeaderName&&t.set("webhook_auth_header_name",this.params.webhookAuthHeaderName),this.params.webhookAuthHeaderValue&&t.set("webhook_auth_header_value",this.params.webhookAuthHeaderValue),void 0!==this.params.includePartialTurns&&t.set("include_partial_turns",this.params.includePartialTurns.toString()),void 0!==this.params.redactPii&&t.set("redact_pii",this.params.redactPii.toString()),void 0!==this.params.redactPiiPolicies&&t.set("redact_pii_policies",JSON.stringify(this.params.redactPiiPolicies)),void 0!==this.params.redactPiiSub&&t.set("redact_pii_sub",this.params.redactPiiSub),void 0!==this.params.mode&&t.set("mode",this.params.mode),void 0!==this.params.llmGateway&&t.set("llm_gateway",JSON.stringify(this.params.llmGateway)),e.search=t.toString(),e}on(e,t){this.listeners[e]=t}async connect(){if(this.socket)throw new Error("Already connected");const e=this.params.maxConnectionRetries??2,t=this.params.connectionRetryDelay??500;let s;for(let r=0;r<=e;r++)try{return await this.connectOnce()}catch(n){s=n;if(!(!0===n.retryable)||r===e)throw n;console.warn(`Streaming connect attempt ${r+1}/${e+1} failed (${n.message}); retrying`),t>0&&await new Promise(e=>setTimeout(e,t))}throw s??new Error("Failed to connect to streaming server")}connectOnce(){return new Promise((e,t)=>{const s=this.connectionUrl(),r=this.params.connectTimeout??1e3;let n,i=!1;const a=e=>{i||(i=!0,n&&clearTimeout(n),this.discardPendingSocket(),t(e))};r>0&&(n=setTimeout(()=>{const e=new StreamingError(`Streaming connection timed out after ${r}ms`);e.retryable=!0,a(e)},r)),this.token?this.socket=factory(s.toString()):(console.warn("API key authentication is not supported for the StreamingTranscriber in browser environment. Use temporary token authentication instead.\nLearn more at https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/docs/compat.md#browser-compatibility."),this.socket=factory(s.toString(),{headers:{Authorization:this.apiKey}})),this.socket.binaryType="arraybuffer",this.socket.onopen=()=>{},this.socket.onclose=({code:e,reason:t})=>{if(t||e in StreamingErrorMessages&&(t=StreamingErrorMessages[e]),!i){const s=new StreamingError(t||`Streaming connection closed (code=${e})`);return s.code=e,s.retryable=isRetryableCloseCode(e),void a(s)}this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=void 0),this.resolveSessionTermination(),this.listeners.close?.(e,t)},this.socket.onerror=e=>{const t=e.error??new Error(e.message);if(!i)return t.retryable=!0,void a(t);this.listeners.error?.(t)},this.socket.onmessage=({data:t})=>{const s=JSON.parse(t.toString());if("error"in s){const e=new StreamingError(s.error);if("error_code"in s&&(e.code=s.error_code),!i){const t=e;return t.retryable=void 0===e.code||isRetryableCloseCode(e.code),void a(t)}return void this.listeners.error?.(e)}switch(s.type){case"Begin":r=s,i||(i=!0,n&&clearTimeout(n),e(r)),this.listeners.open?.(s);break;case"Turn":if(this.isDualChannel&&this.timeline&&this.attributionParams)switch(attributeTurn(s,this.timeline,{dominanceRatio:this.attributionParams.dominanceRatio}),this.attributionParams.resolveUnknownChannelsMethod){case"window":this.resolveUnknownChannelsByWindow(s);break;case"speaker-history":this.resolveUnknownChannelsBySpeakerHistory(s)}this.listeners.turn?.(s);break;case"SpeechStarted":this.listeners.speechStarted?.(s);break;case"LLMGatewayResponse":this.listeners.llmGatewayResponse?.(s);break;case"SpeakerRevision":this.listeners.speakerRevision?.(s);break;case"Warning":{const e=s;console.warn(`Streaming warning (code=${e.warning_code}): ${e.warning}`),this.listeners.warning?.(e);break}case"Heartbeat":this.listeners.heartbeat?.(s);break;case"Silence":this.listeners.silence?.(s);break;case"Termination":this.resolveSessionTermination()}var r}})}discardPendingSocket(){if(this.socket){try{this.socket.removeAllListeners&&(this.socket.removeAllListeners(),this.socket.onerror=()=>{}),this.socket.close()}catch{}this.socket=void 0}}stream(){return new WritableStream$1({write:e=>{this.sendAudio(e)}})}sendAudio(e,t){if(this.isDualChannel){if(!t?.channel)throw new Error("StreamingTranscriber is in dual-channel mode; sendAudio requires { channel }.");if(!this.channelNames.includes(t.channel))throw new Error(`Unknown channel "${t.channel}"; declared channels: ${this.channelNames.join(", ")}.`);this.ingestChannelAudio(t.channel,e)}else this.send(e)}ingestChannelAudio(e,t){const s=toInt16View(t),r=this.channelBuffers.get(e),n=this.channelVadFloatBuffers.get(e);let i=this.channelVadBufferIdx.get(e),a=this.channelSamplesReceived.get(e);const o=this.channelVads.get(e),c=this.params.sampleRate,l=this.vadFrameSamples;for(let t=0;t<s.length;t++){const h=s[t];if(r.push(h),n[i++]=h/32768,a++,i===l){const t=o.process(n),s={ts:a/c*1e3,channel:e,active:t.active,rms:t.energy};this.timeline.pushFrame(s),this.listeners.vad?.(s),i=0}}this.channelVadBufferIdx.set(e,i),this.channelSamplesReceived.set(e,a),this.flushTimer||this.startFlushTimer()}startFlushTimer(){this.flushTimer=setInterval(()=>this.flushMix(),this.attributionParams.flushIntervalMs)}flushMix(e=!1){if(!this.channelNames||!this.channelBuffers)return;const t=this.channelNames.map(e=>this.channelBuffers.get(e)),s=t.length;for(;;){let r=1/0;for(const e of t)e.length<r&&(r=e.length);if(!Number.isFinite(r)||0===r)return;if(!e&&r<this.minChunkSamples)return;r>this.maxChunkSamples&&(r=this.maxChunkSamples);const n=new Int16Array(r);for(let e=0;e<r;e++){let r=0;for(let n=0;n<s;n++)r+=t[n][e];const i=Math.round(r/s);n[e]=i<-32768?-32768:i>32767?32767:i}for(const e of t)e.splice(0,r);try{this.send(n.buffer)}catch(e){return void this.listeners.error?.(e)}}}resolveUnknownChannelsByWindow(e){if(!this.attributionParams)return;const t=this.attributionParams.resolutionWindowWords,s=e.words;let r=!1;for(let e=0;e<s.length;e++){if("unknown"!==s[e].channel)continue;const n=new Map,i=Math.max(0,e-t),a=Math.min(s.length-1,e+t);for(let t=i;t<=a;t++){if(t===e)continue;const r=s[t].channel;r&&"unknown"!==r&&n.set(r,(n.get(r)??0)+1)}if(0===n.size)continue;let o,c=0,l=!1;for(const[e,t]of n)t>c?(o=e,c=t,l=!1):t===c&&(l=!0);o&&!l&&(s[e].channel=o,s[e].channelResolved=!0,r=!0)}r&&(e.channel=rollUpTurnChannel(s))}resolveUnknownChannelsBySpeakerHistory(e){if(!this.timeline||!this.attributionParams||!this.speakerHistory)return;const t=this.attributionParams.speakerHistoryMinRmsEvidence,s=this.attributionParams.speakerHistoryDominanceRatio;for(const t of e.words){if(!t.speaker)continue;const e=this.timeline.framesInWindow(t.start,t.end);let s=this.speakerHistory.get(t.speaker);s||(s=new Map,this.speakerHistory.set(t.speaker,s));for(const t of e)t.active&&s.set(t.channel,(s.get(t.channel)??0)+t.rms)}let r=!1;for(const n of e.words){if("unknown"!==n.channel||!n.speaker)continue;const e=this.speakerHistory.get(n.speaker);if(!e||0===e.size)continue;let i,a=0,o=0,c=0;for(const[t,s]of e)a+=s,s>o?(c=o,o=s,i=t):s>c&&(c=s);a<t||(c>0&&o<s*c||i&&(n.channel=i,n.channelResolved=!0,r=!0))}r&&(e.channel=rollUpTurnChannel(e.words))}updateConfiguration(e){const{min_end_of_turn_silence_when_confident:t,min_turn_silence:s,...r}=e;void 0!==t&&(void 0!==s?console.warn("[Deprecation Warning] Both `min_end_of_turn_silence_when_confident` and `min_turn_silence` are set. Using `min_turn_silence`; `min_end_of_turn_silence_when_confident` is deprecated."):console.warn("[Deprecation Warning] `min_end_of_turn_silence_when_confident` is deprecated and will be removed in a future release. Please use `min_turn_silence` instead."));const n=s??t,i={type:"UpdateConfiguration",...r,...void 0!==n?{min_turn_silence:n}:{}};this.send(JSON.stringify(i))}forceEndpoint(){this.send(JSON.stringify({type:"ForceEndpoint"}))}keepAlive(){this.send(JSON.stringify({type:"KeepAlive"}))}async waitForTermination(e,t){if(t<=0)return void await e;let s;try{await Promise.race([e,new Promise(e=>{s=setTimeout(e,t)})])}finally{s&&clearTimeout(s),this.sessionTerminatedResolve=void 0}}send(e){if(!this.socket||this.socket.readyState!==this.socket.OPEN)throw new Error("Socket is not open for communication");this.socket.send(e)}async close(e=!0,t=5e3){if(this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=void 0,this.flushMix(!0)),this.socket){if(this.socket.readyState===this.socket.OPEN)if(e){const e=new Promise(e=>{this.sessionTerminatedResolve=e});this.socket.send('{"type":"Terminate"}'),await this.waitForTermination(e,t)}else this.socket.send('{"type":"Terminate"}');this.socket?.removeAllListeners&&(this.socket.removeAllListeners(),this.socket.onerror=()=>{}),this.socket.close()}this.listeners={},this.socket=void 0}}class StreamingTranscriberFactory extends BaseService{constructor(e){super(e),this.baseServiceParams=e}transcriber(e){const t={...e};return t.token||t.apiKey||(t.apiKey=this.baseServiceParams.apiKey),new StreamingTranscriber(t)}async createTemporaryToken(e){const t=new URLSearchParams;Object.entries(e).forEach(([e,s])=>{null!=s&&t.append(e,String(s))});const s=t.toString(),r=s?`/v3/token?${s}`:"/v3/token";return(await this.fetchJson(r,{method:"GET"})).token}}const pcm16EncoderWorkletSource='\nclass Pcm16EncoderProcessor extends AudioWorkletProcessor {\n  constructor(options) {\n    super();\n    const opts = (options && options.processorOptions) || {};\n    this.targetRate = opts.targetRate || 16000;\n    this.chunkMs = opts.chunkMs || 50;\n    this.ratio = sampleRate / this.targetRate;\n    this.chunkSize = Math.round(this.targetRate * this.chunkMs / 1000);\n    this.buffer = new Int16Array(this.chunkSize);\n    this.bufferIdx = 0;\n    this.samplesSent = 0;\n    this.lastSample = 0;\n    this.fractional = 0;\n  }\n\n  process(inputs) {\n    const input = inputs[0];\n    if (!input || input.length === 0 || !input[0] || input[0].length === 0) {\n      return true;\n    }\n    const mono = input[0];\n    let pos = this.fractional;\n    while (pos < mono.length) {\n      const i = Math.floor(pos);\n      const frac = pos - i;\n      const a = i === 0 ? this.lastSample : mono[i - 1];\n      const b = mono[i];\n      const sample = a + (b - a) * frac;\n      const clamped = sample < -1 ? -1 : sample > 1 ? 1 : sample;\n      this.buffer[this.bufferIdx++] = clamped < 0 ? clamped * 0x8000 : clamped * 0x7fff;\n      if (this.bufferIdx === this.chunkSize) {\n        const out = new Int16Array(this.chunkSize);\n        out.set(this.buffer);\n        this.samplesSent += this.chunkSize;\n        this.port.postMessage(\n          { pcm: out.buffer, samplesSent: this.samplesSent },\n          [out.buffer],\n        );\n        this.bufferIdx = 0;\n      }\n      pos += this.ratio;\n    }\n    this.lastSample = mono[mono.length - 1];\n    this.fractional = pos - mono.length;\n    return true;\n  }\n}\nregisterProcessor("aai-pcm16-encoder", Pcm16EncoderProcessor);\n',PCM16_ENCODER_PROCESSOR_NAME="aai-pcm16-encoder",DEFAULT_TARGET_RATE=16e3,DEFAULT_CHUNK_MS=50,MIC_CHANNEL="mic",SYSTEM_CHANNEL="system";class DualChannelCapture{constructor(e){if(this.running=!1,void 0===globalThis.AudioContext)throw new BrowserOnlyError;this.params={micStream:e.micStream,systemStream:e.systemStream,transcriber:e.transcriber,targetSampleRate:e.targetSampleRate??16e3}}on(e,t){"error"===e&&(this.errorListener=t)}async start(){if(this.running)throw new Error("DualChannelCapture already started");this.context=new AudioContext;const e=new Blob([pcm16EncoderWorkletSource],{type:"application/javascript"}),t=URL.createObjectURL(e);try{await this.context.audioWorklet.addModule(t)}finally{URL.revokeObjectURL(t)}this.micSource=this.context.createMediaStreamSource(this.params.micStream),this.sysSource=this.context.createMediaStreamSource(this.params.systemStream),this.micEncoder=this.makeEncoder("mic"),this.sysEncoder=this.makeEncoder("system"),this.micSource.connect(this.micEncoder),this.sysSource.connect(this.sysEncoder),this.running=!0}makeEncoder(e){const t=new AudioWorkletNode(this.context,"aai-pcm16-encoder",{numberOfInputs:1,numberOfOutputs:0,channelCount:1,channelCountMode:"explicit",channelInterpretation:"speakers",processorOptions:{targetRate:this.params.targetSampleRate,chunkMs:50}});return t.port.onmessage=t=>{try{this.params.transcriber.sendAudio(t.data.pcm,{channel:e})}catch(e){this.errorListener?.(e)}},t}async stop(){if(this.running){this.running=!1;try{this.micEncoder?.port.close(),this.sysEncoder?.port.close(),this.micEncoder?.disconnect(),this.sysEncoder?.disconnect(),this.micSource?.disconnect(),this.sysSource?.disconnect()}catch{}this.context&&"closed"!==this.context.state&&await this.context.close(),this.context=void 0,this.micSource=void 0,this.sysSource=void 0,this.micEncoder=void 0,this.sysEncoder=void 0}}}class LinearResampler{constructor(e,t){if(this.sourceRate=e,this.targetRate=t,this.lastSample=0,this.fractional=0,e<=0||t<=0)throw new Error("sourceRate and targetRate must be positive");this.ratio=e/t}process(e){if(this.sourceRate===this.targetRate)return e;const t=new Float32Array(Math.ceil(e.length/this.ratio)+1);let s=0,r=this.fractional;for(;r<e.length;){const n=Math.floor(r),i=r-n,a=0===n?this.lastSample:e[n-1],o=e[n];t[s++]=a+(o-a)*i,r+=this.ratio}return this.lastSample=e[e.length-1]??this.lastSample,this.fractional=r-e.length,t.subarray(0,s)}reset(){this.lastSample=0,this.fractional=0}}function float32ToPcm16(e){const t=new ArrayBuffer(2*e.length),s=new DataView(t);for(let t=0;t<e.length;t++){const r=Math.max(-1,Math.min(1,e[t]));s.setInt16(2*t,r<0?32768*r:32767*r,!0)}return t}const defaultBaseUrl="https://api.assemblyai.com",defaultStreamingUrl="https://streaming.assemblyai.com",defaultSyncUrl="https://sync.assemblyai.com",defaultDictationUrl="https://dictation.assemblyai.com",defaultLlmGatewayUrl="https://llm-gateway.assemblyai.com";class AssemblyAI{constructor(e){e.baseUrl=e.baseUrl||defaultBaseUrl,e.baseUrl&&e.baseUrl.endsWith("/")&&(e.baseUrl=e.baseUrl.slice(0,-1)),this.files=new FileService(e),this.transcripts=new TranscriptService(e,this.files),this.realtime=new RealtimeTranscriberFactory(e),this.streaming=new StreamingTranscriberFactory({...e,baseUrl:e.streamingBaseUrl||defaultStreamingUrl});let t=e.syncBaseUrl||defaultSyncUrl;t.endsWith("/")&&(t=t.slice(0,-1)),this.sync=new SyncTranscriber({...e,baseUrl:t});let s=e.dictationBaseUrl||defaultDictationUrl;s.endsWith("/")&&(s=s.slice(0,-1)),this.dictation=new DictationTranscriber({...e,baseUrl:s});let r=e.llmGatewayBaseUrl||defaultLlmGatewayUrl;r.endsWith("/")&&(r=r.slice(0,-1)),this.llmGateway=new LlmGatewayService({...e,baseUrl:r})}}export{AssemblyAI,BrowserOnlyError,DictationError,DictationLiveSession,DictationTranscriber,DualChannelCapture,EnergyVad,FileService,LinearResampler,LlmGatewayError,LlmGatewayService,RealtimeService,RealtimeServiceFactory,RealtimeTranscriber,RealtimeTranscriberFactory,StreamingTranscriber,SyncLiveSession,SyncTranscriber,SyncTranscriptError,TranscriptService,VadTimeline,attributeTurn,attributeWord,defaultSyncSpeechModel,float32ToPcm16,rollUpTurnChannel};
//# sourceMappingURL=/sm/c45a4b59d68409b87bc0ccb07078d2cd9cf0854441d79e0b243f71ae25a31bff.map