assemblyai 4.36.3 → 4.36.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.36.4]
4
+
5
+ - Add `aac` to the streaming `encoding` options — accepts an AAC stream in ADTS framing. Like `opus`/`ogg_opus`, AAC is self-describing, so `sampleRate` is optional for it (it remains required for PCM encodings and for dual-channel mode)
6
+ - Add opt-in `sessionHeartbeat` streaming param — when enabled, the server emits a periodic `Heartbeat` message, surfaced via the new `heartbeat` event with `total_audio_received_ms`, `total_duration_ms`, `realtime_factor`, and `max_speech_probability`. Requires the `universal-3-5-pro` streaming model
7
+
3
8
  ## [4.36.3]
4
9
 
5
10
  - Target the canonical `/v1` sync API routes (`/v1/transcribe`, `/v1/warm`); the unprefixed paths remain served for older SDK versions
@@ -643,9 +643,12 @@ Learn more at https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/docs/c
643
643
  if (!(this.token || this.apiKey)) {
644
644
  throw new Error("API key or temporary token is required.");
645
645
  }
646
- const isOpus = params.encoding === "opus" || params.encoding === "ogg_opus";
647
- if (params.sampleRate === undefined && (!isOpus || params.channels)) {
648
- throw new Error('`sampleRate` is required; it may only be omitted when `encoding` is "opus" or "ogg_opus" (the Opus stream is self-describing) and dual-channel mode is not used.');
646
+ const isSelfDescribing = params.encoding === "opus" ||
647
+ params.encoding === "ogg_opus" ||
648
+ params.encoding === "aac";
649
+ if (params.sampleRate === undefined &&
650
+ (!isSelfDescribing || params.channels)) {
651
+ 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.');
649
652
  }
650
653
  if (params.channels) {
651
654
  if (params.channels.length !== 2) {
@@ -723,6 +726,9 @@ Learn more at https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/docs/c
723
726
  if (this.params.formatTurns) {
724
727
  searchParams.set("format_turns", this.params.formatTurns.toString());
725
728
  }
729
+ if (this.params.sessionHeartbeat !== undefined) {
730
+ searchParams.set("session_heartbeat", this.params.sessionHeartbeat.toString());
731
+ }
726
732
  if (this.params.encoding) {
727
733
  searchParams.set("encoding", this.params.encoding.toString());
728
734
  }
@@ -958,7 +964,7 @@ Learn more at https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/docs/c
958
964
  (_c = (_b = this.listeners).error) === null || _c === void 0 ? void 0 : _c.call(_b, error);
959
965
  };
960
966
  this.socket.onmessage = ({ data }) => {
961
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
967
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
962
968
  const message = JSON.parse(data.toString());
963
969
  if ("error" in message) {
964
970
  const err = new StreamingError(message.error);
@@ -1018,8 +1024,12 @@ Learn more at https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/docs/c
1018
1024
  (_p = (_o = this.listeners).warning) === null || _p === void 0 ? void 0 : _p.call(_o, warning);
1019
1025
  break;
1020
1026
  }
1027
+ case "Heartbeat": {
1028
+ (_r = (_q = this.listeners).heartbeat) === null || _r === void 0 ? void 0 : _r.call(_q, message);
1029
+ break;
1030
+ }
1021
1031
  case "Termination": {
1022
- (_q = this.sessionTerminatedResolve) === null || _q === void 0 ? void 0 : _q.call(this);
1032
+ (_s = this.sessionTerminatedResolve) === null || _s === void 0 ? void 0 : _s.call(this);
1023
1033
  break;
1024
1034
  }
1025
1035
  }
@@ -1381,7 +1391,7 @@ Learn more at https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/docs/c
1381
1391
  defaultUserAgentString += navigator.userAgent;
1382
1392
  }
1383
1393
  const defaultUserAgent = {
1384
- sdk: { name: "JavaScript", version: "4.36.3" },
1394
+ sdk: { name: "JavaScript", version: "4.36.4" },
1385
1395
  };
1386
1396
  if (typeof process !== "undefined") {
1387
1397
  if (process.versions.node && defaultUserAgentString.indexOf("Node") === -1) {
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).assemblyai={})}(this,(function(e){"use strict";class t extends Error{constructor(e="DualChannelCapture requires a browser environment (AudioContext is undefined)."){super(e),this.name="BrowserOnlyError"}}function s(e,t,s,n){return new(s||(s=Promise))((function(i,r){function o(e){try{l(n.next(e))}catch(e){r(e)}}function a(e){try{l(n.throw(e))}catch(e){r(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof s?t:new s((function(e){e(t)}))).then(o,a)}l((n=n.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;const{WritableStream:n}="undefined"!=typeof window?window:"undefined"!=typeof global?global:globalThis;var i,r;const o=null!==(r=null!==(i=null!==WebSocket&&void 0!==WebSocket?WebSocket:null===global||void 0===global?void 0:global.WebSocket)&&void 0!==i?i:null===window||void 0===window?void 0:window.WebSocket)&&void 0!==r?r:null===self||void 0===self?void 0:self.WebSocket,a=(e,t)=>t?new o(e,t):new o(e),l={[4e3]:"Sample rate must be a positive integer",[4001]:"Not Authorized",[4002]:"Insufficient funds",[4003]:"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.",[4004]:"Session ID does not exist",[4008]:"Session has expired",[4010]:"Session is closed",[4029]:"Rate limited",[4030]:"Unique session violation",[4031]:"Session Timeout",[4032]:"Audio too short",[4033]:"Audio too long",[4034]:"Audio too small to transcode",[4100]:"Bad JSON",[4101]:"Bad schema",[4102]:"Too many streams",[4103]:"This session has been reconnected. This WebSocket is no longer valid.",[1013]:"Reconnect attempts exhausted",[4104]:"Could not parse word boost parameter"};class c extends Error{}const h=4e3,d=4001,u=4002,m=4003,p=4101,f={[3005]:"Server error",[3006]:"Input validation error",[3007]:"Audio chunk duration violation",[3008]:"Session expired: maximum session duration exceeded",[3009]:"Too many concurrent sessions",[h]:"Sample rate must be a positive integer",[d]:"Not Authorized",[u]:"Insufficient funds",[m]:"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.",[4004]:"Session ID does not exist",[4008]:"Session has expired",[4010]:"Session is closed",[4029]:"Rate limited",[4030]:"Unique session violation",[4031]:"Session Timeout",[4032]:"Audio too short",[4033]:"Audio too long",[4034]:"Audio too small to transcode",[p]:"Bad schema",[4102]:"Too many streams",[4103]:"This session has been reconnected. This WebSocket is no longer valid."};class v extends Error{}const g='{"terminate_session":true}';class w{constructor(e){var t,s;if(this.listeners={},this.realtimeUrl=null!==(t=e.realtimeUrl)&&void 0!==t?t:"wss://api.assemblyai.com/v2/realtime/ws",this.sampleRate=null!==(s=e.sampleRate)&&void 0!==s?s: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=>{if(this.socket)throw new Error("Already connected");const t=this.connectionUrl();this.token?this.socket=a(t.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=a(t.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})=>{var s,n;t||e in l&&(t=l[e]),null===(n=(s=this.listeners).close)||void 0===n||n.call(s,e,t)},this.socket.onerror=e=>{var t,s,n,i;e.error?null===(s=(t=this.listeners).error)||void 0===s||s.call(t,e.error):null===(i=(n=this.listeners).error)||void 0===i||i.call(n,new Error(e.message))},this.socket.onmessage=({data:t})=>{var s,n,i,r,o,a,l,h,d,u,m,p,f,v,g;const w=JSON.parse(t.toString());if("error"in w)null===(n=(s=this.listeners).error)||void 0===n||n.call(s,new c(w.error));else switch(w.message_type){case"SessionBegins":{const t={sessionId:w.session_id,expiresAt:new Date(w.expires_at)};e(t),null===(r=(i=this.listeners).open)||void 0===r||r.call(i,t);break}case"PartialTranscript":w.created=new Date(w.created),null===(a=(o=this.listeners).transcript)||void 0===a||a.call(o,w),null===(h=(l=this.listeners)["transcript.partial"])||void 0===h||h.call(l,w);break;case"FinalTranscript":w.created=new Date(w.created),null===(u=(d=this.listeners).transcript)||void 0===u||u.call(d,w),null===(p=(m=this.listeners)["transcript.final"])||void 0===p||p.call(m,w);break;case"SessionInformation":null===(v=(f=this.listeners).session_information)||void 0===v||v.call(f,w);break;case"SessionTerminated":null===(g=this.sessionTerminatedResolve)||void 0===g||g.call(this)}}}))}sendAudio(e){this.send(e)}stream(){return new n({write:e=>{this.sendAudio(e)}})}forceEndUtterance(){this.send('{"force_end_utterance":true}')}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)}close(){return s(this,arguments,void 0,(function*(e=!0){var t;if(this.socket){if(this.socket.readyState===this.socket.OPEN)if(e){const e=new Promise((e=>{this.sessionTerminatedResolve=e}));this.socket.send(g),yield e}else this.socket.send(g);(null===(t=this.socket)||void 0===t?void 0:t.removeAllListeners)&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}class y{constructor(e={}){var t,s,n,i;this.hangoverRemaining=0,this.thresholdRatio=null!==(t=e.thresholdRatio)&&void 0!==t?t:3,this.noiseFloorAlpha=null!==(s=e.noiseFloorAlpha)&&void 0!==s?s:.05,this.hangoverFrames=null!==(n=e.hangoverFrames)&&void 0!==n?n:10,this.initialNoiseFloor=null!==(i=e.initialNoiseFloor)&&void 0!==i?i: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 n=s>this.noiseFloor*this.thresholdRatio;return n?this.hangoverRemaining=this.hangoverFrames:this.hangoverRemaining>0?(this.hangoverRemaining--,n=!0):this.noiseFloor=this.noiseFloor*(1-this.noiseFloorAlpha)+s*this.noiseFloorAlpha,{active:n,energy:s}}reset(){this.noiseFloor=this.initialNoiseFloor,this.hangoverRemaining=0}}class k{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 n=this.head;n<this.frames.length;n++){const i=this.frames[n];if(!(i.ts<e)){if(i.ts>t)break;s.push(i)}}return s}clear(){this.frames=[],this.head=0}}function S(e,t,s){const n=function(e){var t;const s=new Map;for(const n of e)n.active&&s.set(n.channel,(null!==(t=s.get(n.channel))&&void 0!==t?t:0)+n.rms);return s}(t.framesInWindow(e.start,e.end));if(0===n.size)return"unknown";const i=[...n.entries()].sort(((e,t)=>t[1]-e[1]));if(1===i.length)return i[0][0];const[r,o]=i[0],[a,l]=i[1];return o>=s.dominanceRatio*l||o>l?r:l>o?a:"unknown"}function b(e){var t;const s=new Map;for(const n of e){if(!n.channel||"unknown"===n.channel)continue;const e=Math.max(0,n.end-n.start);s.set(n.channel,(null!==(t=s.get(n.channel))&&void 0!==t?t:0)+e)}if(0===s.size)return"unknown";const n=[...s.entries()].sort(((e,t)=>t[1]-e[1]));if(1===n.length)return n[0][0];const[i,r]=n[0],[,o]=n[1];return r===o?"unknown":i}function _(e,t,s){for(const n of e.words)n.channel=S(n,t,s);e.channel=b(e.words)}const T='{"type":"Terminate"}',A=new Set([h,d,u,m,p]);function x(e){return 1e3!==e&&!A.has(e)}class P{constructor(e){var t,s,n,i,r,o,a,l,c;if(this.listeners={},this.isDualChannel=!1,this.vadFrameSamples=0,this.minChunkSamples=0,this.maxChunkSamples=0,this.params=Object.assign(Object.assign({},e),{websocketBaseUrl:e.websocketBaseUrl||"wss://streaming.assemblyai.com/v3/ws"}),"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 h="opus"===e.encoding||"ogg_opus"===e.encoding;if(void 0===e.sampleRate&&(!h||e.channels))throw new Error('`sampleRate` is required; it may only be omitted when `encoding` is "opus" or "ogg_opus" (the Opus stream is 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 h=e.channels.map((e=>e.name));if(new Set(h).size!==h.length)throw new Error("StreamingTranscriber.channels names must be unique.");this.isDualChannel=!0,this.channelNames=h;const d=null!==(t=e.channelAttribution)&&void 0!==t?t:{};this.attributionParams={dominanceRatio:null!==(s=d.dominanceRatio)&&void 0!==s?s:4,timelineWindowMs:null!==(n=d.timelineWindowMs)&&void 0!==n?n:3e4,createVad:null!==(i=d.createVad)&&void 0!==i?i:()=>new y,flushIntervalMs:null!==(r=d.flushIntervalMs)&&void 0!==r?r:50,resolveUnknownChannelsMethod:null!==(o=d.resolveUnknownChannelsMethod)&&void 0!==o?o:"window",resolutionWindowWords:null!==(a=d.resolutionWindowWords)&&void 0!==a?a:2,speakerHistoryMinRmsEvidence:null!==(l=d.speakerHistoryMinRmsEvidence)&&void 0!==l?l:.5,speakerHistoryDominanceRatio:null!==(c=d.speakerHistoryDominanceRatio)&&void 0!==c?c:3},"speaker-history"===this.attributionParams.resolveUnknownChannelsMethod&&(this.speakerHistory=new Map);const u=e.sampleRate;this.vadFrameSamples=Math.max(1,Math.round(.02*u)),this.minChunkSamples=Math.max(1,Math.round(.05*u)),this.maxChunkSamples=Math.max(this.minChunkSamples,Math.round(.2*u)),this.channelBuffers=new Map(h.map((e=>[e,[]]))),this.channelSamplesReceived=new Map(h.map((e=>[e,0]))),this.channelVadFloatBuffers=new Map(h.map((e=>[e,new Float32Array(this.vadFrameSamples)]))),this.channelVadBufferIdx=new Map(h.map((e=>[e,0]))),this.channelVads=new Map(h.map((e=>[e,this.attributionParams.createVad(e)]))),this.timeline=new k(this.attributionParams.timelineWindowMs)}}connectionUrl(){var e,t;const s=new URL(null!==(e=this.params.websocketBaseUrl)&&void 0!==e?e:"");if("wss:"!==s.protocol)throw new Error("Invalid protocol, must be wss");const n=new URLSearchParams;this.token&&n.set("token",this.token),void 0!==this.params.sampleRate&&n.set("sample_rate",this.params.sampleRate.toString()),this.params.endOfTurnConfidenceThreshold&&n.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 i=null!==(t=this.params.minTurnSilence)&&void 0!==t?t:this.params.minEndOfTurnSilenceWhenConfident;return void 0!==i&&n.set("min_turn_silence",i.toString()),this.params.maxTurnSilence&&n.set("max_turn_silence",this.params.maxTurnSilence.toString()),void 0!==this.params.vadThreshold&&n.set("vad_threshold",this.params.vadThreshold.toString()),this.params.formatTurns&&n.set("format_turns",this.params.formatTurns.toString()),this.params.encoding&&n.set("encoding",this.params.encoding.toString()),this.params.keytermsPrompt?n.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."),n.set("keyterms_prompt",JSON.stringify(this.params.keyterms))),this.params.prompt&&n.set("prompt",this.params.prompt),this.params.agentContext&&n.set("agent_context",this.params.agentContext),this.params.filterProfanity&&n.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&&n.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."),n.set("language_code",this.params.languageCode)),void 0!==this.params.languageCodes&&n.set("language_codes",JSON.stringify(this.params.languageCodes)),void 0!==this.params.languageDetection&&n.set("language_detection",this.params.languageDetection.toString()),this.params.domain&&n.set("domain",this.params.domain),void 0!==this.params.inactivityTimeout&&n.set("inactivity_timeout",this.params.inactivityTimeout.toString()),void 0!==this.params.speakerLabels&&n.set("speaker_labels",this.params.speakerLabels.toString()),void 0!==this.params.maxSpeakers&&n.set("max_speakers",this.params.maxSpeakers.toString()),this.params.voiceFocus&&n.set("voice_focus",this.params.voiceFocus),void 0!==this.params.voiceFocusThreshold&&n.set("voice_focus_threshold",this.params.voiceFocusThreshold.toString()),void 0!==this.params.continuousPartials&&n.set("continuous_partials",this.params.continuousPartials.toString()),void 0!==this.params.interruptionDelay&&n.set("interruption_delay",this.params.interruptionDelay.toString()),void 0!==this.params.turnLeftPadMs&&n.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."),n.set("_customer_support_audio_capture",this.params.customerSupportAudioCapture.toString())),this.params.webhookUrl&&n.set("webhook_url",this.params.webhookUrl),this.params.webhookAuthHeaderName&&n.set("webhook_auth_header_name",this.params.webhookAuthHeaderName),this.params.webhookAuthHeaderValue&&n.set("webhook_auth_header_value",this.params.webhookAuthHeaderValue),void 0!==this.params.includePartialTurns&&n.set("include_partial_turns",this.params.includePartialTurns.toString()),void 0!==this.params.redactPii&&n.set("redact_pii",this.params.redactPii.toString()),void 0!==this.params.redactPiiPolicies&&n.set("redact_pii_policies",JSON.stringify(this.params.redactPiiPolicies)),void 0!==this.params.redactPiiSub&&n.set("redact_pii_sub",this.params.redactPiiSub),void 0!==this.params.mode&&n.set("mode",this.params.mode),void 0!==this.params.llmGateway&&n.set("llm_gateway",JSON.stringify(this.params.llmGateway)),s.search=n.toString(),s}on(e,t){this.listeners[e]=t}connect(){return s(this,void 0,void 0,(function*(){var e,t;if(this.socket)throw new Error("Already connected");const s=null!==(e=this.params.maxConnectionRetries)&&void 0!==e?e:2,n=null!==(t=this.params.connectionRetryDelay)&&void 0!==t?t:500;let i;for(let e=0;e<=s;e++)try{return yield this.connectOnce()}catch(t){i=t;if(!(!0===t.retryable)||e===s)throw t;console.warn(`Streaming connect attempt ${e+1}/${s+1} failed (${t.message}); retrying`),n>0&&(yield new Promise((e=>setTimeout(e,n))))}throw null!=i?i:new Error("Failed to connect to streaming server")}))}connectOnce(){return new Promise(((e,t)=>{var s;const n=this.connectionUrl(),i=null!==(s=this.params.connectTimeout)&&void 0!==s?s:1e3;let r,o=!1;const l=e=>{o||(o=!0,r&&clearTimeout(r),this.discardPendingSocket(),t(e))};i>0&&(r=setTimeout((()=>{const e=new v(`Streaming connection timed out after ${i}ms`);e.retryable=!0,l(e)}),i)),this.token?this.socket=a(n.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=a(n.toString(),{headers:{Authorization:this.apiKey}})),this.socket.binaryType="arraybuffer",this.socket.onopen=()=>{},this.socket.onclose=({code:e,reason:t})=>{var s,n;if(t||e in f&&(t=f[e]),!o){const s=new v(t||`Streaming connection closed (code=${e})`);return s.code=e,s.retryable=x(e),void l(s)}this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=void 0),null===(n=(s=this.listeners).close)||void 0===n||n.call(s,e,t)},this.socket.onerror=e=>{var t,s,n;const i=null!==(t=e.error)&&void 0!==t?t:new Error(e.message);if(!o)return i.retryable=!0,void l(i);null===(n=(s=this.listeners).error)||void 0===n||n.call(s,i)},this.socket.onmessage=({data:t})=>{var s,n,i,a,c,h,d,u,m,p,f,g,w,y,k;const S=JSON.parse(t.toString());if("error"in S){const e=new v(S.error);if("error_code"in S&&(e.code=S.error_code),!o){const t=e;return t.retryable=void 0===e.code||x(e.code),void l(t)}null===(n=(s=this.listeners).error)||void 0===n||n.call(s,e)}else{switch(S.type){case"Begin":b=S,o||(o=!0,r&&clearTimeout(r),e(b)),null===(a=(i=this.listeners).open)||void 0===a||a.call(i,S);break;case"Turn":if(this.isDualChannel&&this.timeline&&this.attributionParams)switch(_(S,this.timeline,{dominanceRatio:this.attributionParams.dominanceRatio}),this.attributionParams.resolveUnknownChannelsMethod){case"window":this.resolveUnknownChannelsByWindow(S);break;case"speaker-history":this.resolveUnknownChannelsBySpeakerHistory(S)}null===(h=(c=this.listeners).turn)||void 0===h||h.call(c,S);break;case"SpeechStarted":null===(u=(d=this.listeners).speechStarted)||void 0===u||u.call(d,S);break;case"LLMGatewayResponse":null===(p=(m=this.listeners).llmGatewayResponse)||void 0===p||p.call(m,S);break;case"SpeakerRevision":null===(g=(f=this.listeners).speakerRevision)||void 0===g||g.call(f,S);break;case"Warning":{const e=S;console.warn(`Streaming warning (code=${e.warning_code}): ${e.warning}`),null===(y=(w=this.listeners).warning)||void 0===y||y.call(w,e);break}case"Termination":null===(k=this.sessionTerminatedResolve)||void 0===k||k.call(this)}var b}}}))}discardPendingSocket(){if(this.socket){try{this.socket.removeAllListeners&&this.socket.removeAllListeners(),this.socket.close()}catch(e){}this.socket=void 0}}stream(){return new n({write:e=>{this.sendAudio(e)}})}sendAudio(e,t){if(this.isDualChannel){if(!(null==t?void 0: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){var s,n;const i=function(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)}(t),r=this.channelBuffers.get(e),o=this.channelVadFloatBuffers.get(e);let a=this.channelVadBufferIdx.get(e),l=this.channelSamplesReceived.get(e);const c=this.channelVads.get(e),h=this.params.sampleRate,d=this.vadFrameSamples;for(let t=0;t<i.length;t++){const u=i[t];if(r.push(u),o[a++]=u/32768,l++,a===d){const t=c.process(o),i={ts:l/h*1e3,channel:e,active:t.active,rms:t.energy};this.timeline.pushFrame(i),null===(n=(s=this.listeners).vad)||void 0===n||n.call(s,i),a=0}}this.channelVadBufferIdx.set(e,a),this.channelSamplesReceived.set(e,l),this.flushTimer||this.startFlushTimer()}startFlushTimer(){this.flushTimer=setInterval((()=>this.flushMix()),this.attributionParams.flushIntervalMs)}flushMix(e=!1){var t,s;if(!this.channelNames||!this.channelBuffers)return;const n=this.channelNames.map((e=>this.channelBuffers.get(e))),i=n.length;for(;;){let r=1/0;for(const e of n)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 o=new Int16Array(r);for(let e=0;e<r;e++){let t=0;for(let s=0;s<i;s++)t+=n[s][e];const s=Math.round(t/i);o[e]=s<-32768?-32768:s>32767?32767:s}for(const e of n)e.splice(0,r);try{this.send(o.buffer)}catch(e){return void(null===(s=(t=this.listeners).error)||void 0===s||s.call(t,e))}}}resolveUnknownChannelsByWindow(e){var t;if(!this.attributionParams)return;const s=this.attributionParams.resolutionWindowWords,n=e.words;let i=!1;for(let e=0;e<n.length;e++){if("unknown"!==n[e].channel)continue;const r=new Map,o=Math.max(0,e-s),a=Math.min(n.length-1,e+s);for(let s=o;s<=a;s++){if(s===e)continue;const i=n[s].channel;i&&"unknown"!==i&&r.set(i,(null!==(t=r.get(i))&&void 0!==t?t:0)+1)}if(0===r.size)continue;let l,c=0,h=!1;for(const[e,t]of r)t>c?(l=e,c=t,h=!1):t===c&&(h=!0);l&&!h&&(n[e].channel=l,n[e].channelResolved=!0,i=!0)}i&&(e.channel=b(n))}resolveUnknownChannelsBySpeakerHistory(e){var t;if(!this.timeline||!this.attributionParams||!this.speakerHistory)return;const s=this.attributionParams.speakerHistoryMinRmsEvidence,n=this.attributionParams.speakerHistoryDominanceRatio;for(const s of e.words){if(!s.speaker)continue;const e=this.timeline.framesInWindow(s.start,s.end);let n=this.speakerHistory.get(s.speaker);n||(n=new Map,this.speakerHistory.set(s.speaker,n));for(const s of e)s.active&&n.set(s.channel,(null!==(t=n.get(s.channel))&&void 0!==t?t:0)+s.rms)}let i=!1;for(const t of e.words){if("unknown"!==t.channel||!t.speaker)continue;const e=this.speakerHistory.get(t.speaker);if(!e||0===e.size)continue;let r,o=0,a=0,l=0;for(const[t,s]of e)o+=s,s>a?(l=a,a=s,r=t):s>l&&(l=s);o<s||(l>0&&a<n*l||r&&(t.channel=r,t.channelResolved=!0,i=!0))}i&&(e.channel=b(e.words))}updateConfiguration(e){const{min_end_of_turn_silence_when_confident:t,min_turn_silence:s}=e,n=function(e,t){var s={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(s[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(n=Object.getOwnPropertySymbols(e);i<n.length;i++)t.indexOf(n[i])<0&&Object.prototype.propertyIsEnumerable.call(e,n[i])&&(s[n[i]]=e[n[i]])}return s}(e,["min_end_of_turn_silence_when_confident","min_turn_silence"]);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 i=null!=s?s:t,r=Object.assign(Object.assign({type:"UpdateConfiguration"},n),void 0!==i?{min_turn_silence:i}:{});this.send(JSON.stringify(r))}forceEndpoint(){this.send(JSON.stringify({type:"ForceEndpoint"}))}keepAlive(){this.send(JSON.stringify({type:"KeepAlive"}))}send(e){if(!this.socket||this.socket.readyState!==this.socket.OPEN)throw new Error("Socket is not open for communication");this.socket.send(e)}close(){return s(this,arguments,void 0,(function*(e=!0){var t;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(T),yield e}else this.socket.send(T);(null===(t=this.socket)||void 0===t?void 0:t.removeAllListeners)&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}const R={cache:"no-store"};let E="";"undefined"!=typeof navigator&&navigator.userAgent&&(E+=navigator.userAgent);const O={sdk:{name:"JavaScript",version:"4.36.3"}};"undefined"!=typeof process&&(process.versions.node&&-1===E.indexOf("Node")&&(O.runtime_env={name:"Node",version:process.versions.node}),process.versions.bun&&-1===E.indexOf("Bun")&&(O.runtime_env={name:"Bun",version:process.versions.bun})),"undefined"!=typeof Deno&&process.versions.bun&&-1===E.indexOf("Deno")&&(O.runtime_env={name:"Deno",version:Deno.version.deno});class M{constructor(e){var t;this.params=e,!1===e.userAgent?this.userAgent=void 0:this.userAgent=(t=e.userAgent||{},E+(!1===t?"":" AssemblyAI/1.0 ("+Object.entries(Object.assign(Object.assign({},O),t)).map((([e,t])=>t?`${e}=${t.name}/${t.version}`:"")).join(" ")+")"))}fetchResponse(e,t){return s(this,void 0,void 0,(function*(){t=Object.assign(Object.assign({},R),t);let s={Authorization:this.params.apiKey};return t.body instanceof FormData||(s["Content-Type"]="application/json"),(null==R?void 0:R.headers)&&(s=Object.assign(Object.assign({},s),R.headers)),(null==t?void 0:t.headers)&&(s=Object.assign(Object.assign({},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),yield fetch(e,t)}))}fetch(e,t){return s(this,void 0,void 0,(function*(){const s=yield this.fetchResponse(e,t);if(s.status>=400){let e;const t=yield s.text();if(t){try{e=JSON.parse(t)}catch(e){}if(null==e?void 0:e.error)throw new Error(e.error);throw new Error(t)}throw new Error(`HTTP Error: ${s.status} ${s.statusText}`)}return s}))}fetchJson(e,t){return s(this,void 0,void 0,(function*(){return(yield this.fetch(e,t)).json()}))}}class C extends M{constructor(e){super(e),this.baseServiceParams=e}transcriber(e){const t=Object.assign({},e);return t.token||t.apiKey||(t.apiKey=this.baseServiceParams.apiKey),new P(t)}createTemporaryToken(e){return s(this,void 0,void 0,(function*(){const t=new URLSearchParams;Object.entries(e).forEach((([e,s])=>{null!=s&&t.append(e,String(s))}));const s=t.toString(),n=s?`/v3/token?${s}`:"/v3/token";return(yield this.fetchJson(n,{method:"GET"})).token}))}}e.BrowserOnlyError=t,e.DualChannelCapture=class{constructor(e){var s;if(this.running=!1,void 0===globalThis.AudioContext)throw new t;this.params={micStream:e.micStream,systemStream:e.systemStream,transcriber:e.transcriber,targetSampleRate:null!==(s=e.targetSampleRate)&&void 0!==s?s:16e3}}on(e,t){"error"===e&&(this.errorListener=t)}start(){return s(this,void 0,void 0,(function*(){if(this.running)throw new Error("DualChannelCapture already started");this.context=new AudioContext;const e=new Blob(['\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'],{type:"application/javascript"}),t=URL.createObjectURL(e);try{yield 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=>{var s;try{this.params.transcriber.sendAudio(t.data.pcm,{channel:e})}catch(e){null===(s=this.errorListener)||void 0===s||s.call(this,e)}},t}stop(){return s(this,void 0,void 0,(function*(){var e,t,s,n,i,r;if(this.running){this.running=!1;try{null===(e=this.micEncoder)||void 0===e||e.port.close(),null===(t=this.sysEncoder)||void 0===t||t.port.close(),null===(s=this.micEncoder)||void 0===s||s.disconnect(),null===(n=this.sysEncoder)||void 0===n||n.disconnect(),null===(i=this.micSource)||void 0===i||i.disconnect(),null===(r=this.sysSource)||void 0===r||r.disconnect()}catch(e){}this.context&&"closed"!==this.context.state&&(yield this.context.close()),this.context=void 0,this.micSource=void 0,this.sysSource=void 0,this.micEncoder=void 0,this.sysEncoder=void 0}}))}},e.EnergyVad=y,e.LinearResampler=class{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){var t;if(this.sourceRate===this.targetRate)return e;const s=new Float32Array(Math.ceil(e.length/this.ratio)+1);let n=0,i=this.fractional;for(;i<e.length;){const t=Math.floor(i),r=i-t,o=0===t?this.lastSample:e[t-1],a=e[t];s[n++]=o+(a-o)*r,i+=this.ratio}return this.lastSample=null!==(t=e[e.length-1])&&void 0!==t?t:this.lastSample,this.fractional=i-e.length,s.subarray(0,n)}reset(){this.lastSample=0,this.fractional=0}},e.RealtimeService=class extends w{},e.RealtimeTranscriber=w,e.StreamingServiceFactory=class extends C{},e.StreamingTranscriber=P,e.StreamingTranscriberFactory=C,e.VadTimeline=k,e.attributeTurn=_,e.attributeWord=S,e.float32ToPcm16=function(e){const t=new ArrayBuffer(2*e.length),s=new DataView(t);for(let t=0;t<e.length;t++){const n=Math.max(-1,Math.min(1,e[t]));s.setInt16(2*t,n<0?32768*n:32767*n,!0)}return t},e.rollUpTurnChannel=b}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).assemblyai={})}(this,(function(e){"use strict";class t extends Error{constructor(e="DualChannelCapture requires a browser environment (AudioContext is undefined)."){super(e),this.name="BrowserOnlyError"}}function s(e,t,s,n){return new(s||(s=Promise))((function(i,r){function o(e){try{l(n.next(e))}catch(e){r(e)}}function a(e){try{l(n.throw(e))}catch(e){r(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof s?t:new s((function(e){e(t)}))).then(o,a)}l((n=n.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;const{WritableStream:n}="undefined"!=typeof window?window:"undefined"!=typeof global?global:globalThis;var i,r;const o=null!==(r=null!==(i=null!==WebSocket&&void 0!==WebSocket?WebSocket:null===global||void 0===global?void 0:global.WebSocket)&&void 0!==i?i:null===window||void 0===window?void 0:window.WebSocket)&&void 0!==r?r:null===self||void 0===self?void 0:self.WebSocket,a=(e,t)=>t?new o(e,t):new o(e),l={[4e3]:"Sample rate must be a positive integer",[4001]:"Not Authorized",[4002]:"Insufficient funds",[4003]:"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.",[4004]:"Session ID does not exist",[4008]:"Session has expired",[4010]:"Session is closed",[4029]:"Rate limited",[4030]:"Unique session violation",[4031]:"Session Timeout",[4032]:"Audio too short",[4033]:"Audio too long",[4034]:"Audio too small to transcode",[4100]:"Bad JSON",[4101]:"Bad schema",[4102]:"Too many streams",[4103]:"This session has been reconnected. This WebSocket is no longer valid.",[1013]:"Reconnect attempts exhausted",[4104]:"Could not parse word boost parameter"};class c extends Error{}const h=4e3,d=4001,u=4002,m=4003,p=4101,f={[3005]:"Server error",[3006]:"Input validation error",[3007]:"Audio chunk duration violation",[3008]:"Session expired: maximum session duration exceeded",[3009]:"Too many concurrent sessions",[h]:"Sample rate must be a positive integer",[d]:"Not Authorized",[u]:"Insufficient funds",[m]:"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.",[4004]:"Session ID does not exist",[4008]:"Session has expired",[4010]:"Session is closed",[4029]:"Rate limited",[4030]:"Unique session violation",[4031]:"Session Timeout",[4032]:"Audio too short",[4033]:"Audio too long",[4034]:"Audio too small to transcode",[p]:"Bad schema",[4102]:"Too many streams",[4103]:"This session has been reconnected. This WebSocket is no longer valid."};class v extends Error{}const g='{"terminate_session":true}';class w{constructor(e){var t,s;if(this.listeners={},this.realtimeUrl=null!==(t=e.realtimeUrl)&&void 0!==t?t:"wss://api.assemblyai.com/v2/realtime/ws",this.sampleRate=null!==(s=e.sampleRate)&&void 0!==s?s: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=>{if(this.socket)throw new Error("Already connected");const t=this.connectionUrl();this.token?this.socket=a(t.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=a(t.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})=>{var s,n;t||e in l&&(t=l[e]),null===(n=(s=this.listeners).close)||void 0===n||n.call(s,e,t)},this.socket.onerror=e=>{var t,s,n,i;e.error?null===(s=(t=this.listeners).error)||void 0===s||s.call(t,e.error):null===(i=(n=this.listeners).error)||void 0===i||i.call(n,new Error(e.message))},this.socket.onmessage=({data:t})=>{var s,n,i,r,o,a,l,h,d,u,m,p,f,v,g;const w=JSON.parse(t.toString());if("error"in w)null===(n=(s=this.listeners).error)||void 0===n||n.call(s,new c(w.error));else switch(w.message_type){case"SessionBegins":{const t={sessionId:w.session_id,expiresAt:new Date(w.expires_at)};e(t),null===(r=(i=this.listeners).open)||void 0===r||r.call(i,t);break}case"PartialTranscript":w.created=new Date(w.created),null===(a=(o=this.listeners).transcript)||void 0===a||a.call(o,w),null===(h=(l=this.listeners)["transcript.partial"])||void 0===h||h.call(l,w);break;case"FinalTranscript":w.created=new Date(w.created),null===(u=(d=this.listeners).transcript)||void 0===u||u.call(d,w),null===(p=(m=this.listeners)["transcript.final"])||void 0===p||p.call(m,w);break;case"SessionInformation":null===(v=(f=this.listeners).session_information)||void 0===v||v.call(f,w);break;case"SessionTerminated":null===(g=this.sessionTerminatedResolve)||void 0===g||g.call(this)}}}))}sendAudio(e){this.send(e)}stream(){return new n({write:e=>{this.sendAudio(e)}})}forceEndUtterance(){this.send('{"force_end_utterance":true}')}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)}close(){return s(this,arguments,void 0,(function*(e=!0){var t;if(this.socket){if(this.socket.readyState===this.socket.OPEN)if(e){const e=new Promise((e=>{this.sessionTerminatedResolve=e}));this.socket.send(g),yield e}else this.socket.send(g);(null===(t=this.socket)||void 0===t?void 0:t.removeAllListeners)&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}class y{constructor(e={}){var t,s,n,i;this.hangoverRemaining=0,this.thresholdRatio=null!==(t=e.thresholdRatio)&&void 0!==t?t:3,this.noiseFloorAlpha=null!==(s=e.noiseFloorAlpha)&&void 0!==s?s:.05,this.hangoverFrames=null!==(n=e.hangoverFrames)&&void 0!==n?n:10,this.initialNoiseFloor=null!==(i=e.initialNoiseFloor)&&void 0!==i?i: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 n=s>this.noiseFloor*this.thresholdRatio;return n?this.hangoverRemaining=this.hangoverFrames:this.hangoverRemaining>0?(this.hangoverRemaining--,n=!0):this.noiseFloor=this.noiseFloor*(1-this.noiseFloorAlpha)+s*this.noiseFloorAlpha,{active:n,energy:s}}reset(){this.noiseFloor=this.initialNoiseFloor,this.hangoverRemaining=0}}class k{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 n=this.head;n<this.frames.length;n++){const i=this.frames[n];if(!(i.ts<e)){if(i.ts>t)break;s.push(i)}}return s}clear(){this.frames=[],this.head=0}}function b(e,t,s){const n=function(e){var t;const s=new Map;for(const n of e)n.active&&s.set(n.channel,(null!==(t=s.get(n.channel))&&void 0!==t?t:0)+n.rms);return s}(t.framesInWindow(e.start,e.end));if(0===n.size)return"unknown";const i=[...n.entries()].sort(((e,t)=>t[1]-e[1]));if(1===i.length)return i[0][0];const[r,o]=i[0],[a,l]=i[1];return o>=s.dominanceRatio*l||o>l?r:l>o?a:"unknown"}function S(e){var t;const s=new Map;for(const n of e){if(!n.channel||"unknown"===n.channel)continue;const e=Math.max(0,n.end-n.start);s.set(n.channel,(null!==(t=s.get(n.channel))&&void 0!==t?t:0)+e)}if(0===s.size)return"unknown";const n=[...s.entries()].sort(((e,t)=>t[1]-e[1]));if(1===n.length)return n[0][0];const[i,r]=n[0],[,o]=n[1];return r===o?"unknown":i}function _(e,t,s){for(const n of e.words)n.channel=b(n,t,s);e.channel=S(e.words)}const T='{"type":"Terminate"}',A=new Set([h,d,u,m,p]);function x(e){return 1e3!==e&&!A.has(e)}class P{constructor(e){var t,s,n,i,r,o,a,l,c;if(this.listeners={},this.isDualChannel=!1,this.vadFrameSamples=0,this.minChunkSamples=0,this.maxChunkSamples=0,this.params=Object.assign(Object.assign({},e),{websocketBaseUrl:e.websocketBaseUrl||"wss://streaming.assemblyai.com/v3/ws"}),"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 h="opus"===e.encoding||"ogg_opus"===e.encoding||"aac"===e.encoding;if(void 0===e.sampleRate&&(!h||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 h=e.channels.map((e=>e.name));if(new Set(h).size!==h.length)throw new Error("StreamingTranscriber.channels names must be unique.");this.isDualChannel=!0,this.channelNames=h;const d=null!==(t=e.channelAttribution)&&void 0!==t?t:{};this.attributionParams={dominanceRatio:null!==(s=d.dominanceRatio)&&void 0!==s?s:4,timelineWindowMs:null!==(n=d.timelineWindowMs)&&void 0!==n?n:3e4,createVad:null!==(i=d.createVad)&&void 0!==i?i:()=>new y,flushIntervalMs:null!==(r=d.flushIntervalMs)&&void 0!==r?r:50,resolveUnknownChannelsMethod:null!==(o=d.resolveUnknownChannelsMethod)&&void 0!==o?o:"window",resolutionWindowWords:null!==(a=d.resolutionWindowWords)&&void 0!==a?a:2,speakerHistoryMinRmsEvidence:null!==(l=d.speakerHistoryMinRmsEvidence)&&void 0!==l?l:.5,speakerHistoryDominanceRatio:null!==(c=d.speakerHistoryDominanceRatio)&&void 0!==c?c:3},"speaker-history"===this.attributionParams.resolveUnknownChannelsMethod&&(this.speakerHistory=new Map);const u=e.sampleRate;this.vadFrameSamples=Math.max(1,Math.round(.02*u)),this.minChunkSamples=Math.max(1,Math.round(.05*u)),this.maxChunkSamples=Math.max(this.minChunkSamples,Math.round(.2*u)),this.channelBuffers=new Map(h.map((e=>[e,[]]))),this.channelSamplesReceived=new Map(h.map((e=>[e,0]))),this.channelVadFloatBuffers=new Map(h.map((e=>[e,new Float32Array(this.vadFrameSamples)]))),this.channelVadBufferIdx=new Map(h.map((e=>[e,0]))),this.channelVads=new Map(h.map((e=>[e,this.attributionParams.createVad(e)]))),this.timeline=new k(this.attributionParams.timelineWindowMs)}}connectionUrl(){var e,t;const s=new URL(null!==(e=this.params.websocketBaseUrl)&&void 0!==e?e:"");if("wss:"!==s.protocol)throw new Error("Invalid protocol, must be wss");const n=new URLSearchParams;this.token&&n.set("token",this.token),void 0!==this.params.sampleRate&&n.set("sample_rate",this.params.sampleRate.toString()),this.params.endOfTurnConfidenceThreshold&&n.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 i=null!==(t=this.params.minTurnSilence)&&void 0!==t?t:this.params.minEndOfTurnSilenceWhenConfident;return void 0!==i&&n.set("min_turn_silence",i.toString()),this.params.maxTurnSilence&&n.set("max_turn_silence",this.params.maxTurnSilence.toString()),void 0!==this.params.vadThreshold&&n.set("vad_threshold",this.params.vadThreshold.toString()),this.params.formatTurns&&n.set("format_turns",this.params.formatTurns.toString()),void 0!==this.params.sessionHeartbeat&&n.set("session_heartbeat",this.params.sessionHeartbeat.toString()),this.params.encoding&&n.set("encoding",this.params.encoding.toString()),this.params.keytermsPrompt?n.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."),n.set("keyterms_prompt",JSON.stringify(this.params.keyterms))),this.params.prompt&&n.set("prompt",this.params.prompt),this.params.agentContext&&n.set("agent_context",this.params.agentContext),this.params.filterProfanity&&n.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&&n.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."),n.set("language_code",this.params.languageCode)),void 0!==this.params.languageCodes&&n.set("language_codes",JSON.stringify(this.params.languageCodes)),void 0!==this.params.languageDetection&&n.set("language_detection",this.params.languageDetection.toString()),this.params.domain&&n.set("domain",this.params.domain),void 0!==this.params.inactivityTimeout&&n.set("inactivity_timeout",this.params.inactivityTimeout.toString()),void 0!==this.params.speakerLabels&&n.set("speaker_labels",this.params.speakerLabels.toString()),void 0!==this.params.maxSpeakers&&n.set("max_speakers",this.params.maxSpeakers.toString()),this.params.voiceFocus&&n.set("voice_focus",this.params.voiceFocus),void 0!==this.params.voiceFocusThreshold&&n.set("voice_focus_threshold",this.params.voiceFocusThreshold.toString()),void 0!==this.params.continuousPartials&&n.set("continuous_partials",this.params.continuousPartials.toString()),void 0!==this.params.interruptionDelay&&n.set("interruption_delay",this.params.interruptionDelay.toString()),void 0!==this.params.turnLeftPadMs&&n.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."),n.set("_customer_support_audio_capture",this.params.customerSupportAudioCapture.toString())),this.params.webhookUrl&&n.set("webhook_url",this.params.webhookUrl),this.params.webhookAuthHeaderName&&n.set("webhook_auth_header_name",this.params.webhookAuthHeaderName),this.params.webhookAuthHeaderValue&&n.set("webhook_auth_header_value",this.params.webhookAuthHeaderValue),void 0!==this.params.includePartialTurns&&n.set("include_partial_turns",this.params.includePartialTurns.toString()),void 0!==this.params.redactPii&&n.set("redact_pii",this.params.redactPii.toString()),void 0!==this.params.redactPiiPolicies&&n.set("redact_pii_policies",JSON.stringify(this.params.redactPiiPolicies)),void 0!==this.params.redactPiiSub&&n.set("redact_pii_sub",this.params.redactPiiSub),void 0!==this.params.mode&&n.set("mode",this.params.mode),void 0!==this.params.llmGateway&&n.set("llm_gateway",JSON.stringify(this.params.llmGateway)),s.search=n.toString(),s}on(e,t){this.listeners[e]=t}connect(){return s(this,void 0,void 0,(function*(){var e,t;if(this.socket)throw new Error("Already connected");const s=null!==(e=this.params.maxConnectionRetries)&&void 0!==e?e:2,n=null!==(t=this.params.connectionRetryDelay)&&void 0!==t?t:500;let i;for(let e=0;e<=s;e++)try{return yield this.connectOnce()}catch(t){i=t;if(!(!0===t.retryable)||e===s)throw t;console.warn(`Streaming connect attempt ${e+1}/${s+1} failed (${t.message}); retrying`),n>0&&(yield new Promise((e=>setTimeout(e,n))))}throw null!=i?i:new Error("Failed to connect to streaming server")}))}connectOnce(){return new Promise(((e,t)=>{var s;const n=this.connectionUrl(),i=null!==(s=this.params.connectTimeout)&&void 0!==s?s:1e3;let r,o=!1;const l=e=>{o||(o=!0,r&&clearTimeout(r),this.discardPendingSocket(),t(e))};i>0&&(r=setTimeout((()=>{const e=new v(`Streaming connection timed out after ${i}ms`);e.retryable=!0,l(e)}),i)),this.token?this.socket=a(n.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=a(n.toString(),{headers:{Authorization:this.apiKey}})),this.socket.binaryType="arraybuffer",this.socket.onopen=()=>{},this.socket.onclose=({code:e,reason:t})=>{var s,n;if(t||e in f&&(t=f[e]),!o){const s=new v(t||`Streaming connection closed (code=${e})`);return s.code=e,s.retryable=x(e),void l(s)}this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=void 0),null===(n=(s=this.listeners).close)||void 0===n||n.call(s,e,t)},this.socket.onerror=e=>{var t,s,n;const i=null!==(t=e.error)&&void 0!==t?t:new Error(e.message);if(!o)return i.retryable=!0,void l(i);null===(n=(s=this.listeners).error)||void 0===n||n.call(s,i)},this.socket.onmessage=({data:t})=>{var s,n,i,a,c,h,d,u,m,p,f,g,w,y,k,b,S;const T=JSON.parse(t.toString());if("error"in T){const e=new v(T.error);if("error_code"in T&&(e.code=T.error_code),!o){const t=e;return t.retryable=void 0===e.code||x(e.code),void l(t)}null===(n=(s=this.listeners).error)||void 0===n||n.call(s,e)}else{switch(T.type){case"Begin":A=T,o||(o=!0,r&&clearTimeout(r),e(A)),null===(a=(i=this.listeners).open)||void 0===a||a.call(i,T);break;case"Turn":if(this.isDualChannel&&this.timeline&&this.attributionParams)switch(_(T,this.timeline,{dominanceRatio:this.attributionParams.dominanceRatio}),this.attributionParams.resolveUnknownChannelsMethod){case"window":this.resolveUnknownChannelsByWindow(T);break;case"speaker-history":this.resolveUnknownChannelsBySpeakerHistory(T)}null===(h=(c=this.listeners).turn)||void 0===h||h.call(c,T);break;case"SpeechStarted":null===(u=(d=this.listeners).speechStarted)||void 0===u||u.call(d,T);break;case"LLMGatewayResponse":null===(p=(m=this.listeners).llmGatewayResponse)||void 0===p||p.call(m,T);break;case"SpeakerRevision":null===(g=(f=this.listeners).speakerRevision)||void 0===g||g.call(f,T);break;case"Warning":{const e=T;console.warn(`Streaming warning (code=${e.warning_code}): ${e.warning}`),null===(y=(w=this.listeners).warning)||void 0===y||y.call(w,e);break}case"Heartbeat":null===(b=(k=this.listeners).heartbeat)||void 0===b||b.call(k,T);break;case"Termination":null===(S=this.sessionTerminatedResolve)||void 0===S||S.call(this)}var A}}}))}discardPendingSocket(){if(this.socket){try{this.socket.removeAllListeners&&this.socket.removeAllListeners(),this.socket.close()}catch(e){}this.socket=void 0}}stream(){return new n({write:e=>{this.sendAudio(e)}})}sendAudio(e,t){if(this.isDualChannel){if(!(null==t?void 0: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){var s,n;const i=function(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)}(t),r=this.channelBuffers.get(e),o=this.channelVadFloatBuffers.get(e);let a=this.channelVadBufferIdx.get(e),l=this.channelSamplesReceived.get(e);const c=this.channelVads.get(e),h=this.params.sampleRate,d=this.vadFrameSamples;for(let t=0;t<i.length;t++){const u=i[t];if(r.push(u),o[a++]=u/32768,l++,a===d){const t=c.process(o),i={ts:l/h*1e3,channel:e,active:t.active,rms:t.energy};this.timeline.pushFrame(i),null===(n=(s=this.listeners).vad)||void 0===n||n.call(s,i),a=0}}this.channelVadBufferIdx.set(e,a),this.channelSamplesReceived.set(e,l),this.flushTimer||this.startFlushTimer()}startFlushTimer(){this.flushTimer=setInterval((()=>this.flushMix()),this.attributionParams.flushIntervalMs)}flushMix(e=!1){var t,s;if(!this.channelNames||!this.channelBuffers)return;const n=this.channelNames.map((e=>this.channelBuffers.get(e))),i=n.length;for(;;){let r=1/0;for(const e of n)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 o=new Int16Array(r);for(let e=0;e<r;e++){let t=0;for(let s=0;s<i;s++)t+=n[s][e];const s=Math.round(t/i);o[e]=s<-32768?-32768:s>32767?32767:s}for(const e of n)e.splice(0,r);try{this.send(o.buffer)}catch(e){return void(null===(s=(t=this.listeners).error)||void 0===s||s.call(t,e))}}}resolveUnknownChannelsByWindow(e){var t;if(!this.attributionParams)return;const s=this.attributionParams.resolutionWindowWords,n=e.words;let i=!1;for(let e=0;e<n.length;e++){if("unknown"!==n[e].channel)continue;const r=new Map,o=Math.max(0,e-s),a=Math.min(n.length-1,e+s);for(let s=o;s<=a;s++){if(s===e)continue;const i=n[s].channel;i&&"unknown"!==i&&r.set(i,(null!==(t=r.get(i))&&void 0!==t?t:0)+1)}if(0===r.size)continue;let l,c=0,h=!1;for(const[e,t]of r)t>c?(l=e,c=t,h=!1):t===c&&(h=!0);l&&!h&&(n[e].channel=l,n[e].channelResolved=!0,i=!0)}i&&(e.channel=S(n))}resolveUnknownChannelsBySpeakerHistory(e){var t;if(!this.timeline||!this.attributionParams||!this.speakerHistory)return;const s=this.attributionParams.speakerHistoryMinRmsEvidence,n=this.attributionParams.speakerHistoryDominanceRatio;for(const s of e.words){if(!s.speaker)continue;const e=this.timeline.framesInWindow(s.start,s.end);let n=this.speakerHistory.get(s.speaker);n||(n=new Map,this.speakerHistory.set(s.speaker,n));for(const s of e)s.active&&n.set(s.channel,(null!==(t=n.get(s.channel))&&void 0!==t?t:0)+s.rms)}let i=!1;for(const t of e.words){if("unknown"!==t.channel||!t.speaker)continue;const e=this.speakerHistory.get(t.speaker);if(!e||0===e.size)continue;let r,o=0,a=0,l=0;for(const[t,s]of e)o+=s,s>a?(l=a,a=s,r=t):s>l&&(l=s);o<s||(l>0&&a<n*l||r&&(t.channel=r,t.channelResolved=!0,i=!0))}i&&(e.channel=S(e.words))}updateConfiguration(e){const{min_end_of_turn_silence_when_confident:t,min_turn_silence:s}=e,n=function(e,t){var s={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(s[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(n=Object.getOwnPropertySymbols(e);i<n.length;i++)t.indexOf(n[i])<0&&Object.prototype.propertyIsEnumerable.call(e,n[i])&&(s[n[i]]=e[n[i]])}return s}(e,["min_end_of_turn_silence_when_confident","min_turn_silence"]);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 i=null!=s?s:t,r=Object.assign(Object.assign({type:"UpdateConfiguration"},n),void 0!==i?{min_turn_silence:i}:{});this.send(JSON.stringify(r))}forceEndpoint(){this.send(JSON.stringify({type:"ForceEndpoint"}))}keepAlive(){this.send(JSON.stringify({type:"KeepAlive"}))}send(e){if(!this.socket||this.socket.readyState!==this.socket.OPEN)throw new Error("Socket is not open for communication");this.socket.send(e)}close(){return s(this,arguments,void 0,(function*(e=!0){var t;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(T),yield e}else this.socket.send(T);(null===(t=this.socket)||void 0===t?void 0:t.removeAllListeners)&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}const R={cache:"no-store"};let E="";"undefined"!=typeof navigator&&navigator.userAgent&&(E+=navigator.userAgent);const O={sdk:{name:"JavaScript",version:"4.36.4"}};"undefined"!=typeof process&&(process.versions.node&&-1===E.indexOf("Node")&&(O.runtime_env={name:"Node",version:process.versions.node}),process.versions.bun&&-1===E.indexOf("Bun")&&(O.runtime_env={name:"Bun",version:process.versions.bun})),"undefined"!=typeof Deno&&process.versions.bun&&-1===E.indexOf("Deno")&&(O.runtime_env={name:"Deno",version:Deno.version.deno});class M{constructor(e){var t;this.params=e,!1===e.userAgent?this.userAgent=void 0:this.userAgent=(t=e.userAgent||{},E+(!1===t?"":" AssemblyAI/1.0 ("+Object.entries(Object.assign(Object.assign({},O),t)).map((([e,t])=>t?`${e}=${t.name}/${t.version}`:"")).join(" ")+")"))}fetchResponse(e,t){return s(this,void 0,void 0,(function*(){t=Object.assign(Object.assign({},R),t);let s={Authorization:this.params.apiKey};return t.body instanceof FormData||(s["Content-Type"]="application/json"),(null==R?void 0:R.headers)&&(s=Object.assign(Object.assign({},s),R.headers)),(null==t?void 0:t.headers)&&(s=Object.assign(Object.assign({},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),yield fetch(e,t)}))}fetch(e,t){return s(this,void 0,void 0,(function*(){const s=yield this.fetchResponse(e,t);if(s.status>=400){let e;const t=yield s.text();if(t){try{e=JSON.parse(t)}catch(e){}if(null==e?void 0:e.error)throw new Error(e.error);throw new Error(t)}throw new Error(`HTTP Error: ${s.status} ${s.statusText}`)}return s}))}fetchJson(e,t){return s(this,void 0,void 0,(function*(){return(yield this.fetch(e,t)).json()}))}}class C extends M{constructor(e){super(e),this.baseServiceParams=e}transcriber(e){const t=Object.assign({},e);return t.token||t.apiKey||(t.apiKey=this.baseServiceParams.apiKey),new P(t)}createTemporaryToken(e){return s(this,void 0,void 0,(function*(){const t=new URLSearchParams;Object.entries(e).forEach((([e,s])=>{null!=s&&t.append(e,String(s))}));const s=t.toString(),n=s?`/v3/token?${s}`:"/v3/token";return(yield this.fetchJson(n,{method:"GET"})).token}))}}e.BrowserOnlyError=t,e.DualChannelCapture=class{constructor(e){var s;if(this.running=!1,void 0===globalThis.AudioContext)throw new t;this.params={micStream:e.micStream,systemStream:e.systemStream,transcriber:e.transcriber,targetSampleRate:null!==(s=e.targetSampleRate)&&void 0!==s?s:16e3}}on(e,t){"error"===e&&(this.errorListener=t)}start(){return s(this,void 0,void 0,(function*(){if(this.running)throw new Error("DualChannelCapture already started");this.context=new AudioContext;const e=new Blob(['\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'],{type:"application/javascript"}),t=URL.createObjectURL(e);try{yield 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=>{var s;try{this.params.transcriber.sendAudio(t.data.pcm,{channel:e})}catch(e){null===(s=this.errorListener)||void 0===s||s.call(this,e)}},t}stop(){return s(this,void 0,void 0,(function*(){var e,t,s,n,i,r;if(this.running){this.running=!1;try{null===(e=this.micEncoder)||void 0===e||e.port.close(),null===(t=this.sysEncoder)||void 0===t||t.port.close(),null===(s=this.micEncoder)||void 0===s||s.disconnect(),null===(n=this.sysEncoder)||void 0===n||n.disconnect(),null===(i=this.micSource)||void 0===i||i.disconnect(),null===(r=this.sysSource)||void 0===r||r.disconnect()}catch(e){}this.context&&"closed"!==this.context.state&&(yield this.context.close()),this.context=void 0,this.micSource=void 0,this.sysSource=void 0,this.micEncoder=void 0,this.sysEncoder=void 0}}))}},e.EnergyVad=y,e.LinearResampler=class{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){var t;if(this.sourceRate===this.targetRate)return e;const s=new Float32Array(Math.ceil(e.length/this.ratio)+1);let n=0,i=this.fractional;for(;i<e.length;){const t=Math.floor(i),r=i-t,o=0===t?this.lastSample:e[t-1],a=e[t];s[n++]=o+(a-o)*r,i+=this.ratio}return this.lastSample=null!==(t=e[e.length-1])&&void 0!==t?t:this.lastSample,this.fractional=i-e.length,s.subarray(0,n)}reset(){this.lastSample=0,this.fractional=0}},e.RealtimeService=class extends w{},e.RealtimeTranscriber=w,e.StreamingServiceFactory=class extends C{},e.StreamingTranscriber=P,e.StreamingTranscriberFactory=C,e.VadTimeline=k,e.attributeTurn=_,e.attributeWord=b,e.float32ToPcm16=function(e){const t=new ArrayBuffer(2*e.length),s=new DataView(t);for(let t=0;t<e.length;t++){const n=Math.max(-1,Math.min(1,e[t]));s.setInt16(2*t,n<0?32768*n:32767*n,!0)}return t},e.rollUpTurnChannel=S}));
@@ -111,7 +111,7 @@
111
111
  defaultUserAgentString += navigator.userAgent;
112
112
  }
113
113
  const defaultUserAgent = {
114
- sdk: { name: "JavaScript", version: "4.36.3" },
114
+ sdk: { name: "JavaScript", version: "4.36.4" },
115
115
  };
116
116
  if (typeof process !== "undefined") {
117
117
  if (process.versions.node && defaultUserAgentString.indexOf("Node") === -1) {
@@ -1527,9 +1527,12 @@ Learn more at https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/docs/c
1527
1527
  if (!(this.token || this.apiKey)) {
1528
1528
  throw new Error("API key or temporary token is required.");
1529
1529
  }
1530
- const isOpus = params.encoding === "opus" || params.encoding === "ogg_opus";
1531
- if (params.sampleRate === undefined && (!isOpus || params.channels)) {
1532
- throw new Error('`sampleRate` is required; it may only be omitted when `encoding` is "opus" or "ogg_opus" (the Opus stream is self-describing) and dual-channel mode is not used.');
1530
+ const isSelfDescribing = params.encoding === "opus" ||
1531
+ params.encoding === "ogg_opus" ||
1532
+ params.encoding === "aac";
1533
+ if (params.sampleRate === undefined &&
1534
+ (!isSelfDescribing || params.channels)) {
1535
+ 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.');
1533
1536
  }
1534
1537
  if (params.channels) {
1535
1538
  if (params.channels.length !== 2) {
@@ -1607,6 +1610,9 @@ Learn more at https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/docs/c
1607
1610
  if (this.params.formatTurns) {
1608
1611
  searchParams.set("format_turns", this.params.formatTurns.toString());
1609
1612
  }
1613
+ if (this.params.sessionHeartbeat !== undefined) {
1614
+ searchParams.set("session_heartbeat", this.params.sessionHeartbeat.toString());
1615
+ }
1610
1616
  if (this.params.encoding) {
1611
1617
  searchParams.set("encoding", this.params.encoding.toString());
1612
1618
  }
@@ -1842,7 +1848,7 @@ Learn more at https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/docs/c
1842
1848
  (_c = (_b = this.listeners).error) === null || _c === void 0 ? void 0 : _c.call(_b, error);
1843
1849
  };
1844
1850
  this.socket.onmessage = ({ data }) => {
1845
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
1851
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
1846
1852
  const message = JSON.parse(data.toString());
1847
1853
  if ("error" in message) {
1848
1854
  const err = new StreamingError(message.error);
@@ -1902,8 +1908,12 @@ Learn more at https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/docs/c
1902
1908
  (_p = (_o = this.listeners).warning) === null || _p === void 0 ? void 0 : _p.call(_o, warning);
1903
1909
  break;
1904
1910
  }
1911
+ case "Heartbeat": {
1912
+ (_r = (_q = this.listeners).heartbeat) === null || _r === void 0 ? void 0 : _r.call(_q, message);
1913
+ break;
1914
+ }
1905
1915
  case "Termination": {
1906
- (_q = this.sessionTerminatedResolve) === null || _q === void 0 ? void 0 : _q.call(this);
1916
+ (_s = this.sessionTerminatedResolve) === null || _s === void 0 ? void 0 : _s.call(this);
1907
1917
  break;
1908
1918
  }
1909
1919
  }
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).assemblyai={})}(this,(function(e){"use strict";const t="universal-3-5-pro";class n extends Error{constructor(e="DualChannelCapture requires a browser environment (AudioContext is undefined)."){super(e),this.name="BrowserOnlyError"}}function s(e,t){var n={};for(var s in e)Object.prototype.hasOwnProperty.call(e,s)&&t.indexOf(s)<0&&(n[s]=e[s]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(s=Object.getOwnPropertySymbols(e);i<s.length;i++)t.indexOf(s[i])<0&&Object.prototype.propertyIsEnumerable.call(e,s[i])&&(n[s[i]]=e[s[i]])}return n}function i(e,t,n,s){return new(n||(n=Promise))((function(i,r){function o(e){try{l(s.next(e))}catch(e){r(e)}}function a(e){try{l(s.throw(e))}catch(e){r(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(o,a)}l((s=s.apply(e,t||[])).next())}))}function r(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],s=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&s>=e.length&&(e=void 0),{value:e&&e[s++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function o(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e=r(e),t={},s("next"),s("throw"),s("return"),t[Symbol.asyncIterator]=function(){return this},t);function s(n){t[n]=e[n]&&function(t){return new Promise((function(s,i){(function(e,t,n,s){Promise.resolve(s).then((function(t){e({value:t,done:n})}),t)})(s,i,(t=e[n](t)).done,t.value)}))}}}"function"==typeof SuppressedError&&SuppressedError;const a=function(e){return i(this,void 0,void 0,(function*(){throw new Error("Interacting with the file system is not supported in this environment.")}))},l={cache:"no-store"};let c="";"undefined"!=typeof navigator&&navigator.userAgent&&(c+=navigator.userAgent);const h={sdk:{name:"JavaScript",version:"4.36.3"}};"undefined"!=typeof process&&(process.versions.node&&-1===c.indexOf("Node")&&(h.runtime_env={name:"Node",version:process.versions.node}),process.versions.bun&&-1===c.indexOf("Bun")&&(h.runtime_env={name:"Bun",version:process.versions.bun})),"undefined"!=typeof Deno&&process.versions.bun&&-1===c.indexOf("Deno")&&(h.runtime_env={name:"Deno",version:Deno.version.deno});class d{constructor(e){var t;this.params=e,!1===e.userAgent?this.userAgent=void 0:this.userAgent=(t=e.userAgent||{},c+(!1===t?"":" AssemblyAI/1.0 ("+Object.entries(Object.assign(Object.assign({},h),t)).map((([e,t])=>t?`${e}=${t.name}/${t.version}`:"")).join(" ")+")"))}fetchResponse(e,t){return i(this,void 0,void 0,(function*(){t=Object.assign(Object.assign({},l),t);let n={Authorization:this.params.apiKey};return t.body instanceof FormData||(n["Content-Type"]="application/json"),(null==l?void 0:l.headers)&&(n=Object.assign(Object.assign({},n),l.headers)),(null==t?void 0:t.headers)&&(n=Object.assign(Object.assign({},n),t.headers)),this.userAgent&&(n["User-Agent"]=this.userAgent,"undefined"!=typeof window&&"chrome"in window&&(n["AssemblyAI-Agent"]=this.userAgent)),t.headers=n,e.startsWith("http")||(e=this.params.baseUrl+e),yield fetch(e,t)}))}fetch(e,t){return i(this,void 0,void 0,(function*(){const n=yield this.fetchResponse(e,t);if(n.status>=400){let e;const t=yield n.text();if(t){try{e=JSON.parse(t)}catch(e){}if(null==e?void 0:e.error)throw new Error(e.error);throw new Error(t)}throw new Error(`HTTP Error: ${n.status} ${n.statusText}`)}return n}))}fetchJson(e,t){return i(this,void 0,void 0,(function*(){return(yield this.fetch(e,t)).json()}))}}class u extends Error{constructor(e,t,n,s){super(e),this.status=t,this.errorCode=n,this.retryAfter=s,this.name="SyncTranscriptError"}}function m(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 p="X-AAI-Model",f=4096,v=2048,y=100,g=4096,w=[".pcm",".raw"];class b extends d{constructor(e){super(e)}transcribe(e){return i(this,arguments,void 0,(function*(e,n={},s={}){var r,l;const{bytes:c,filename:h,contentType:d}=yield function(e,t){return i(this,void 0,void 0,(function*(){var n;let s,r,l="";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=function(e){const t=e.split(",")[1],n=atob(t),s=new Uint8Array(n.length);for(let e=0;e<n.length;e++)s[e]=n.charCodeAt(e);return s}(e);else{const t=null!==(n=m(e))&&void 0!==n?n:e;s=yield _(yield a()),r=S(t),l=k(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(yield e.arrayBuffer());const t=e.name;t&&(r=S(t),l=k(r))}else if(function(e){return"function"==typeof(null==e?void 0:e.getReader)}(e))s=yield _(e);else{if(!function(e){return"function"==typeof(null==e?void 0:e[Symbol.asyncIterator])}(e))throw new TypeError("unsupported audio input type");{s=yield function(e){return i(this,void 0,void 0,(function*(){var t,n,s,i,r,a,l;const c=[];try{for(t=!0,n=o(e);!(i=(s=yield n.next()).done);t=!0){l=s.value,t=!1;const e=l;c.push(e)}}catch(e){r={error:e}}finally{try{t||i||!(a=n.return)||(yield a.call(n))}finally{if(r)throw r.error}}return T(c)}))}(e);const t=e.path;"string"==typeof t&&(r=S(t),l=k(r))}}const c=void 0!==t.sample_rate||void 0!==t.channels,h=w.includes(l)||c;if(h&&(void 0===t.sample_rate||void 0===t.channels))throw new Error("raw PCM audio requires both sample_rate and channels in the config");return r||(r=h?"audio.pcm":"audio.wav"),{bytes:s,filename:r,contentType:h?"audio/pcm":"audio/wav"}}))}(e,n),b=new FormData;b.append("audio",new Blob([c],{type:d}),h);const A=function(e){if(void 0!==e.prompt&&e.prompt.length>f)throw new Error(`prompt exceeds 4096 characters (got ${e.prompt.length})`);const t={};void 0!==e.prompt&&(t.prompt=e.prompt);const n=function(e){if(!e)return;const t=e.map((e=>e.trim())).filter((e=>e.length>0)),n=t.reduce(((e,t)=>e+t.length),0);if(n>v)throw new Error(`keyterms_prompt exceeds ${v} characters (got ${n})`);return t.length>0?t:void 0}(e.keyterms_prompt);n&&(t.keyterms_prompt=n);const s=function(e){if(void 0===e)return;let t=("string"==typeof e?[e]:e).map((e=>e.trim())).filter((e=>e.length>0)),n=t.reduce(((e,t)=>e+t.length),0);for(;t.length>0&&(t.length>y||n>g);)n-=t[0].length,t=t.slice(1);return t.length>0?t:void 0}(e.conversation_context);s&&(t.conversation_context=s);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);return Object.keys(t).length>0?t:void 0}(n);A&&b.append("config",new Blob([JSON.stringify(A)],{type:"application/json"}));const P=yield this.fetchResponse("/v1/transcribe",{method:"POST",body:b,headers:{[p]:null!==(r=n.model)&&void 0!==r?r:t},signal:AbortSignal.timeout(null!==(l=s.timeout)&&void 0!==l?l:6e4)});if(200!==P.status)throw yield function(e){return i(this,void 0,void 0,(function*(){let t,n;const s=yield e.text();try{const e=JSON.parse(s);e&&"object"==typeof e&&!Array.isArray(e)&&("string"==typeof e.error_code&&(t=e.error_code),void 0===t&&"string"==typeof e.title&&(t=e.title.toLowerCase().replace(/ /g,"_")),"string"==typeof e.detail?n=e.detail:"string"==typeof e.message&&(n=e.message))}catch(e){s&&(n=s)}n||(n=`sync transcription failed with status ${e.status}`);const i=e.headers.get("retry-after"),r=i&&/^\d+$/.test(i)?parseInt(i,10):void 0;return new u(n,e.status,t,r)}))}(P);return yield P.json()}))}warm(e){return i(this,void 0,void 0,(function*(){var n;try{return yield this.fetchResponse("/v1/warm",{method:"GET",headers:{[p]:null!==(n=null==e?void 0:e.model)&&void 0!==n?n:t},signal:AbortSignal.timeout(1e4)}),!0}catch(e){return!1}}))}}function S(e){var t;return null!==(t=e.split(/[\\/]/).pop())&&void 0!==t?t:e}function k(e){const t=e.lastIndexOf(".");return t>0?e.slice(t).toLowerCase():""}function _(e){return i(this,void 0,void 0,(function*(){const t=[],n=e.getReader();for(;;){const{done:e,value:s}=yield n.read();if(e)break;t.push(s)}return T(t)}))}function T(e){const t=e.reduce(((e,t)=>e+t.length),0),n=new Uint8Array(t);let s=0;for(const t of e)n.set(t,s),s+=t.length;return n}const A={[4e3]:"Sample rate must be a positive integer",[4001]:"Not Authorized",[4002]:"Insufficient funds",[4003]:"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.",[4004]:"Session ID does not exist",[4008]:"Session has expired",[4010]:"Session is closed",[4029]:"Rate limited",[4030]:"Unique session violation",[4031]:"Session Timeout",[4032]:"Audio too short",[4033]:"Audio too long",[4034]:"Audio too small to transcode",[4100]:"Bad JSON",[4101]:"Bad schema",[4102]:"Too many streams",[4103]:"This session has been reconnected. This WebSocket is no longer valid.",[1013]:"Reconnect attempts exhausted",[4104]:"Could not parse word boost parameter"};class P extends Error{}const x=4e3,O=4001,R=4002,E=4003,U=4101,C={[3005]:"Server error",[3006]:"Input validation error",[3007]:"Audio chunk duration violation",[3008]:"Session expired: maximum session duration exceeded",[3009]:"Too many concurrent sessions",[x]:"Sample rate must be a positive integer",[O]:"Not Authorized",[R]:"Insufficient funds",[E]:"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.",[4004]:"Session ID does not exist",[4008]:"Session has expired",[4010]:"Session is closed",[4029]:"Rate limited",[4030]:"Unique session violation",[4031]:"Session Timeout",[4032]:"Audio too short",[4033]:"Audio too long",[4034]:"Audio too small to transcode",[U]:"Bad schema",[4102]:"Too many streams",[4103]:"This session has been reconnected. This WebSocket is no longer valid."};class M extends Error{}class I extends d{summary(e,t){return this.fetchJson("/lemur/v3/generate/summary",{method:"POST",body:JSON.stringify(e),signal:t})}questionAnswer(e,t){return this.fetchJson("/lemur/v3/generate/question-answer",{method:"POST",body:JSON.stringify(e),signal:t})}actionItems(e,t){return this.fetchJson("/lemur/v3/generate/action-items",{method:"POST",body:JSON.stringify(e),signal:t})}task(e,t){return this.fetchJson("/lemur/v3/generate/task",{method:"POST",body:JSON.stringify(e),signal:t})}getResponse(e,t){return this.fetchJson(`/lemur/v3/${e}`,{signal:t})}purgeRequestData(e,t){return this.fetchJson(`/lemur/v3/${e}`,{method:"DELETE",signal:t})}}const{WritableStream:W}="undefined"!=typeof window?window:"undefined"!=typeof global?global:globalThis;var B,F;const N=null!==(F=null!==(B=null!==WebSocket&&void 0!==WebSocket?WebSocket:null===global||void 0===global?void 0:global.WebSocket)&&void 0!==B?B:null===window||void 0===window?void 0:window.WebSocket)&&void 0!==F?F:null===self||void 0===self?void 0:self.WebSocket,J=(e,t)=>t?new N(e,t):new N(e),j='{"terminate_session":true}';class D{constructor(e){var t,n;if(this.listeners={},this.realtimeUrl=null!==(t=e.realtimeUrl)&&void 0!==t?t:"wss://api.assemblyai.com/v2/realtime/ws",this.sampleRate=null!==(n=e.sampleRate)&&void 0!==n?n: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=>{if(this.socket)throw new Error("Already connected");const t=this.connectionUrl();this.token?this.socket=J(t.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=J(t.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})=>{var n,s;t||e in A&&(t=A[e]),null===(s=(n=this.listeners).close)||void 0===s||s.call(n,e,t)},this.socket.onerror=e=>{var t,n,s,i;e.error?null===(n=(t=this.listeners).error)||void 0===n||n.call(t,e.error):null===(i=(s=this.listeners).error)||void 0===i||i.call(s,new Error(e.message))},this.socket.onmessage=({data:t})=>{var n,s,i,r,o,a,l,c,h,d,u,m,p,f,v;const y=JSON.parse(t.toString());if("error"in y)null===(s=(n=this.listeners).error)||void 0===s||s.call(n,new P(y.error));else switch(y.message_type){case"SessionBegins":{const t={sessionId:y.session_id,expiresAt:new Date(y.expires_at)};e(t),null===(r=(i=this.listeners).open)||void 0===r||r.call(i,t);break}case"PartialTranscript":y.created=new Date(y.created),null===(a=(o=this.listeners).transcript)||void 0===a||a.call(o,y),null===(c=(l=this.listeners)["transcript.partial"])||void 0===c||c.call(l,y);break;case"FinalTranscript":y.created=new Date(y.created),null===(d=(h=this.listeners).transcript)||void 0===d||d.call(h,y),null===(m=(u=this.listeners)["transcript.final"])||void 0===m||m.call(u,y);break;case"SessionInformation":null===(f=(p=this.listeners).session_information)||void 0===f||f.call(p,y);break;case"SessionTerminated":null===(v=this.sessionTerminatedResolve)||void 0===v||v.call(this)}}}))}sendAudio(e){this.send(e)}stream(){return new W({write:e=>{this.sendAudio(e)}})}forceEndUtterance(){this.send('{"force_end_utterance":true}')}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)}close(){return i(this,arguments,void 0,(function*(e=!0){var t;if(this.socket){if(this.socket.readyState===this.socket.OPEN)if(e){const e=new Promise((e=>{this.sessionTerminatedResolve=e}));this.socket.send(j),yield e}else this.socket.send(j);(null===(t=this.socket)||void 0===t?void 0:t.removeAllListeners)&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}class L extends d{constructor(e){super(e),this.rtFactoryParams=e}createService(e){return this.transcriber(e)}transcriber(e){const t=Object.assign({},e);return t.token||t.apiKey||(t.apiKey=this.rtFactoryParams.apiKey),new D(t)}createTemporaryToken(e){return i(this,void 0,void 0,(function*(){return(yield this.fetchJson("/v2/realtime/token",{method:"POST",body:JSON.stringify(e)})).token}))}}class $ extends d{constructor(e,t){super(e),this.files=t}transcribe(e,t){return i(this,void 0,void 0,(function*(){const n=yield this.submit(e);return yield this.waitUntilReady(n.id,t)}))}submit(e){return i(this,void 0,void 0,(function*(){let t,n;if("audio"in e){const{audio:i}=e,r=s(e,["audio"]);if("string"==typeof i){const e=m(i);t=null!==e?yield this.files.upload(e):i.startsWith("data:")?yield this.files.upload(i):i}else t=yield this.files.upload(i);n=Object.assign(Object.assign({},r),{audio_url:t})}else n=e;return yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(n)})}))}create(e,t){return i(this,void 0,void 0,(function*(){var n;const s=m(e.audio_url);if(null!==s){const t=yield this.files.upload(s);e.audio_url=t}const i=yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(e)});return null===(n=null==t?void 0:t.poll)||void 0===n||n?yield this.waitUntilReady(i.id,t):i}))}waitUntilReady(e,t){return i(this,void 0,void 0,(function*(){var n,s;const i=null!==(n=null==t?void 0:t.pollingInterval)&&void 0!==n?n:3e3,r=null!==(s=null==t?void 0:t.pollingTimeout)&&void 0!==s?s:-1,o=Date.now();for(;;){const t=yield this.get(e);if("completed"===t.status||"error"===t.status)return t;if(r>0&&Date.now()-o>r)throw new Error("Polling timeout");yield new Promise((e=>setTimeout(e,i)))}}))}get(e){return this.fetchJson(`/v2/transcript/${e}`)}list(e){return i(this,void 0,void 0,(function*(){let t="/v2/transcript";"string"==typeof e?t=e:e&&(t=`${t}?${new URLSearchParams(Object.keys(e).map((t=>{var n;return[t,(null===(n=e[t])||void 0===n?void 0:n.toString())||""]})))}`);const n=yield this.fetchJson(t);for(const e of n.transcripts)e.created=new Date(e.created),e.completed&&(e.completed=new Date(e.completed));return n}))}delete(e){return this.fetchJson(`/v2/transcript/${e}`,{method:"DELETE"})}wordSearch(e,t){const n=new URLSearchParams({words:t.join(",")});return this.fetchJson(`/v2/transcript/${e}/word-search?${n.toString()}`)}sentences(e){return this.fetchJson(`/v2/transcript/${e}/sentences`)}paragraphs(e){return this.fetchJson(`/v2/transcript/${e}/paragraphs`)}subtitles(e){return i(this,arguments,void 0,(function*(e,t="srt",n){let s=`/v2/transcript/${e}/${t}`;if(n){const e=new URLSearchParams;e.set("chars_per_caption",n.toString()),s+=`?${e.toString()}`}const i=yield this.fetch(s);return yield i.text()}))}redactions(e){return this.redactedAudio(e)}redactedAudio(e){return this.fetchJson(`/v2/transcript/${e}/redacted-audio`)}redactedAudioFile(e){return i(this,void 0,void 0,(function*(){const{redacted_audio_url:t,status:n}=yield this.redactedAudio(e);if("redacted_audio_ready"!==n)throw new Error(`Redacted audio status is ${n}`);const s=yield fetch(t);if(!s.ok)throw new Error(`Failed to fetch redacted audio: ${s.statusText}`);return{arrayBuffer:s.arrayBuffer.bind(s),blob:s.blob.bind(s),body:s.body,bodyUsed:s.bodyUsed}}))}}class K extends d{upload(e){return i(this,void 0,void 0,(function*(){let t;t="string"==typeof e?e.startsWith("data:")?function(e){const t=e.split(","),n=t[0].match(/:(.*?);/)[1],s=atob(t[1]);let i=s.length;const r=new Uint8Array(i);for(;i--;)r[i]=s.charCodeAt(i);return new Blob([r],{type:n})}(e):yield a():e;return(yield this.fetchJson("/v2/upload",{method:"POST",body:t,headers:{"Content-Type":"application/octet-stream"},duplex:"half"})).upload_url}))}}class H{constructor(e={}){var t,n,s,i;this.hangoverRemaining=0,this.thresholdRatio=null!==(t=e.thresholdRatio)&&void 0!==t?t:3,this.noiseFloorAlpha=null!==(n=e.noiseFloorAlpha)&&void 0!==n?n:.05,this.hangoverFrames=null!==(s=e.hangoverFrames)&&void 0!==s?s:10,this.initialNoiseFloor=null!==(i=e.initialNoiseFloor)&&void 0!==i?i:1e-4,this.noiseFloor=this.initialNoiseFloor}process(e){let t=0;for(let n=0;n<e.length;n++)t+=e[n]*e[n];const n=e.length>0?Math.sqrt(t/e.length):0;let s=n>this.noiseFloor*this.thresholdRatio;return s?this.hangoverRemaining=this.hangoverFrames:this.hangoverRemaining>0?(this.hangoverRemaining--,s=!0):this.noiseFloor=this.noiseFloor*(1-this.noiseFloorAlpha)+n*this.noiseFloorAlpha,{active:s,energy:n}}reset(){this.noiseFloor=this.initialNoiseFloor,this.hangoverRemaining=0}}class V{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 n=[];for(let s=this.head;s<this.frames.length;s++){const i=this.frames[s];if(!(i.ts<e)){if(i.ts>t)break;n.push(i)}}return n}clear(){this.frames=[],this.head=0}}function q(e,t,n){const s=function(e){var t;const n=new Map;for(const s of e)s.active&&n.set(s.channel,(null!==(t=n.get(s.channel))&&void 0!==t?t:0)+s.rms);return n}(t.framesInWindow(e.start,e.end));if(0===s.size)return"unknown";const i=[...s.entries()].sort(((e,t)=>t[1]-e[1]));if(1===i.length)return i[0][0];const[r,o]=i[0],[a,l]=i[1];return o>=n.dominanceRatio*l||o>l?r:l>o?a:"unknown"}function z(e){var t;const n=new Map;for(const s of e){if(!s.channel||"unknown"===s.channel)continue;const e=Math.max(0,s.end-s.start);n.set(s.channel,(null!==(t=n.get(s.channel))&&void 0!==t?t:0)+e)}if(0===n.size)return"unknown";const s=[...n.entries()].sort(((e,t)=>t[1]-e[1]));if(1===s.length)return s[0][0];const[i,r]=s[0],[,o]=s[1];return r===o?"unknown":i}function G(e,t,n){for(const s of e.words)s.channel=q(s,t,n);e.channel=z(e.words)}const X='{"type":"Terminate"}',Q=new Set([x,O,R,E,U]);function Y(e){return 1e3!==e&&!Q.has(e)}class Z{constructor(e){var t,n,s,i,r,o,a,l,c;if(this.listeners={},this.isDualChannel=!1,this.vadFrameSamples=0,this.minChunkSamples=0,this.maxChunkSamples=0,this.params=Object.assign(Object.assign({},e),{websocketBaseUrl:e.websocketBaseUrl||"wss://streaming.assemblyai.com/v3/ws"}),"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 h="opus"===e.encoding||"ogg_opus"===e.encoding;if(void 0===e.sampleRate&&(!h||e.channels))throw new Error('`sampleRate` is required; it may only be omitted when `encoding` is "opus" or "ogg_opus" (the Opus stream is 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 h=e.channels.map((e=>e.name));if(new Set(h).size!==h.length)throw new Error("StreamingTranscriber.channels names must be unique.");this.isDualChannel=!0,this.channelNames=h;const d=null!==(t=e.channelAttribution)&&void 0!==t?t:{};this.attributionParams={dominanceRatio:null!==(n=d.dominanceRatio)&&void 0!==n?n:4,timelineWindowMs:null!==(s=d.timelineWindowMs)&&void 0!==s?s:3e4,createVad:null!==(i=d.createVad)&&void 0!==i?i:()=>new H,flushIntervalMs:null!==(r=d.flushIntervalMs)&&void 0!==r?r:50,resolveUnknownChannelsMethod:null!==(o=d.resolveUnknownChannelsMethod)&&void 0!==o?o:"window",resolutionWindowWords:null!==(a=d.resolutionWindowWords)&&void 0!==a?a:2,speakerHistoryMinRmsEvidence:null!==(l=d.speakerHistoryMinRmsEvidence)&&void 0!==l?l:.5,speakerHistoryDominanceRatio:null!==(c=d.speakerHistoryDominanceRatio)&&void 0!==c?c:3},"speaker-history"===this.attributionParams.resolveUnknownChannelsMethod&&(this.speakerHistory=new Map);const u=e.sampleRate;this.vadFrameSamples=Math.max(1,Math.round(.02*u)),this.minChunkSamples=Math.max(1,Math.round(.05*u)),this.maxChunkSamples=Math.max(this.minChunkSamples,Math.round(.2*u)),this.channelBuffers=new Map(h.map((e=>[e,[]]))),this.channelSamplesReceived=new Map(h.map((e=>[e,0]))),this.channelVadFloatBuffers=new Map(h.map((e=>[e,new Float32Array(this.vadFrameSamples)]))),this.channelVadBufferIdx=new Map(h.map((e=>[e,0]))),this.channelVads=new Map(h.map((e=>[e,this.attributionParams.createVad(e)]))),this.timeline=new V(this.attributionParams.timelineWindowMs)}}connectionUrl(){var e,t;const n=new URL(null!==(e=this.params.websocketBaseUrl)&&void 0!==e?e:"");if("wss:"!==n.protocol)throw new Error("Invalid protocol, must be wss");const s=new URLSearchParams;this.token&&s.set("token",this.token),void 0!==this.params.sampleRate&&s.set("sample_rate",this.params.sampleRate.toString()),this.params.endOfTurnConfidenceThreshold&&s.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 i=null!==(t=this.params.minTurnSilence)&&void 0!==t?t:this.params.minEndOfTurnSilenceWhenConfident;return void 0!==i&&s.set("min_turn_silence",i.toString()),this.params.maxTurnSilence&&s.set("max_turn_silence",this.params.maxTurnSilence.toString()),void 0!==this.params.vadThreshold&&s.set("vad_threshold",this.params.vadThreshold.toString()),this.params.formatTurns&&s.set("format_turns",this.params.formatTurns.toString()),this.params.encoding&&s.set("encoding",this.params.encoding.toString()),this.params.keytermsPrompt?s.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."),s.set("keyterms_prompt",JSON.stringify(this.params.keyterms))),this.params.prompt&&s.set("prompt",this.params.prompt),this.params.agentContext&&s.set("agent_context",this.params.agentContext),this.params.filterProfanity&&s.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&&s.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."),s.set("language_code",this.params.languageCode)),void 0!==this.params.languageCodes&&s.set("language_codes",JSON.stringify(this.params.languageCodes)),void 0!==this.params.languageDetection&&s.set("language_detection",this.params.languageDetection.toString()),this.params.domain&&s.set("domain",this.params.domain),void 0!==this.params.inactivityTimeout&&s.set("inactivity_timeout",this.params.inactivityTimeout.toString()),void 0!==this.params.speakerLabels&&s.set("speaker_labels",this.params.speakerLabels.toString()),void 0!==this.params.maxSpeakers&&s.set("max_speakers",this.params.maxSpeakers.toString()),this.params.voiceFocus&&s.set("voice_focus",this.params.voiceFocus),void 0!==this.params.voiceFocusThreshold&&s.set("voice_focus_threshold",this.params.voiceFocusThreshold.toString()),void 0!==this.params.continuousPartials&&s.set("continuous_partials",this.params.continuousPartials.toString()),void 0!==this.params.interruptionDelay&&s.set("interruption_delay",this.params.interruptionDelay.toString()),void 0!==this.params.turnLeftPadMs&&s.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."),s.set("_customer_support_audio_capture",this.params.customerSupportAudioCapture.toString())),this.params.webhookUrl&&s.set("webhook_url",this.params.webhookUrl),this.params.webhookAuthHeaderName&&s.set("webhook_auth_header_name",this.params.webhookAuthHeaderName),this.params.webhookAuthHeaderValue&&s.set("webhook_auth_header_value",this.params.webhookAuthHeaderValue),void 0!==this.params.includePartialTurns&&s.set("include_partial_turns",this.params.includePartialTurns.toString()),void 0!==this.params.redactPii&&s.set("redact_pii",this.params.redactPii.toString()),void 0!==this.params.redactPiiPolicies&&s.set("redact_pii_policies",JSON.stringify(this.params.redactPiiPolicies)),void 0!==this.params.redactPiiSub&&s.set("redact_pii_sub",this.params.redactPiiSub),void 0!==this.params.mode&&s.set("mode",this.params.mode),void 0!==this.params.llmGateway&&s.set("llm_gateway",JSON.stringify(this.params.llmGateway)),n.search=s.toString(),n}on(e,t){this.listeners[e]=t}connect(){return i(this,void 0,void 0,(function*(){var e,t;if(this.socket)throw new Error("Already connected");const n=null!==(e=this.params.maxConnectionRetries)&&void 0!==e?e:2,s=null!==(t=this.params.connectionRetryDelay)&&void 0!==t?t:500;let i;for(let e=0;e<=n;e++)try{return yield this.connectOnce()}catch(t){i=t;if(!(!0===t.retryable)||e===n)throw t;console.warn(`Streaming connect attempt ${e+1}/${n+1} failed (${t.message}); retrying`),s>0&&(yield new Promise((e=>setTimeout(e,s))))}throw null!=i?i:new Error("Failed to connect to streaming server")}))}connectOnce(){return new Promise(((e,t)=>{var n;const s=this.connectionUrl(),i=null!==(n=this.params.connectTimeout)&&void 0!==n?n:1e3;let r,o=!1;const a=e=>{o||(o=!0,r&&clearTimeout(r),this.discardPendingSocket(),t(e))};i>0&&(r=setTimeout((()=>{const e=new M(`Streaming connection timed out after ${i}ms`);e.retryable=!0,a(e)}),i)),this.token?this.socket=J(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=J(s.toString(),{headers:{Authorization:this.apiKey}})),this.socket.binaryType="arraybuffer",this.socket.onopen=()=>{},this.socket.onclose=({code:e,reason:t})=>{var n,s;if(t||e in C&&(t=C[e]),!o){const n=new M(t||`Streaming connection closed (code=${e})`);return n.code=e,n.retryable=Y(e),void a(n)}this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=void 0),null===(s=(n=this.listeners).close)||void 0===s||s.call(n,e,t)},this.socket.onerror=e=>{var t,n,s;const i=null!==(t=e.error)&&void 0!==t?t:new Error(e.message);if(!o)return i.retryable=!0,void a(i);null===(s=(n=this.listeners).error)||void 0===s||s.call(n,i)},this.socket.onmessage=({data:t})=>{var n,s,i,l,c,h,d,u,m,p,f,v,y,g,w;const b=JSON.parse(t.toString());if("error"in b){const e=new M(b.error);if("error_code"in b&&(e.code=b.error_code),!o){const t=e;return t.retryable=void 0===e.code||Y(e.code),void a(t)}null===(s=(n=this.listeners).error)||void 0===s||s.call(n,e)}else{switch(b.type){case"Begin":S=b,o||(o=!0,r&&clearTimeout(r),e(S)),null===(l=(i=this.listeners).open)||void 0===l||l.call(i,b);break;case"Turn":if(this.isDualChannel&&this.timeline&&this.attributionParams)switch(G(b,this.timeline,{dominanceRatio:this.attributionParams.dominanceRatio}),this.attributionParams.resolveUnknownChannelsMethod){case"window":this.resolveUnknownChannelsByWindow(b);break;case"speaker-history":this.resolveUnknownChannelsBySpeakerHistory(b)}null===(h=(c=this.listeners).turn)||void 0===h||h.call(c,b);break;case"SpeechStarted":null===(u=(d=this.listeners).speechStarted)||void 0===u||u.call(d,b);break;case"LLMGatewayResponse":null===(p=(m=this.listeners).llmGatewayResponse)||void 0===p||p.call(m,b);break;case"SpeakerRevision":null===(v=(f=this.listeners).speakerRevision)||void 0===v||v.call(f,b);break;case"Warning":{const e=b;console.warn(`Streaming warning (code=${e.warning_code}): ${e.warning}`),null===(g=(y=this.listeners).warning)||void 0===g||g.call(y,e);break}case"Termination":null===(w=this.sessionTerminatedResolve)||void 0===w||w.call(this)}var S}}}))}discardPendingSocket(){if(this.socket){try{this.socket.removeAllListeners&&this.socket.removeAllListeners(),this.socket.close()}catch(e){}this.socket=void 0}}stream(){return new W({write:e=>{this.sendAudio(e)}})}sendAudio(e,t){if(this.isDualChannel){if(!(null==t?void 0: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){var n,s;const i=function(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)}(t),r=this.channelBuffers.get(e),o=this.channelVadFloatBuffers.get(e);let a=this.channelVadBufferIdx.get(e),l=this.channelSamplesReceived.get(e);const c=this.channelVads.get(e),h=this.params.sampleRate,d=this.vadFrameSamples;for(let t=0;t<i.length;t++){const u=i[t];if(r.push(u),o[a++]=u/32768,l++,a===d){const t=c.process(o),i={ts:l/h*1e3,channel:e,active:t.active,rms:t.energy};this.timeline.pushFrame(i),null===(s=(n=this.listeners).vad)||void 0===s||s.call(n,i),a=0}}this.channelVadBufferIdx.set(e,a),this.channelSamplesReceived.set(e,l),this.flushTimer||this.startFlushTimer()}startFlushTimer(){this.flushTimer=setInterval((()=>this.flushMix()),this.attributionParams.flushIntervalMs)}flushMix(e=!1){var t,n;if(!this.channelNames||!this.channelBuffers)return;const s=this.channelNames.map((e=>this.channelBuffers.get(e))),i=s.length;for(;;){let r=1/0;for(const e of s)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 o=new Int16Array(r);for(let e=0;e<r;e++){let t=0;for(let n=0;n<i;n++)t+=s[n][e];const n=Math.round(t/i);o[e]=n<-32768?-32768:n>32767?32767:n}for(const e of s)e.splice(0,r);try{this.send(o.buffer)}catch(e){return void(null===(n=(t=this.listeners).error)||void 0===n||n.call(t,e))}}}resolveUnknownChannelsByWindow(e){var t;if(!this.attributionParams)return;const n=this.attributionParams.resolutionWindowWords,s=e.words;let i=!1;for(let e=0;e<s.length;e++){if("unknown"!==s[e].channel)continue;const r=new Map,o=Math.max(0,e-n),a=Math.min(s.length-1,e+n);for(let n=o;n<=a;n++){if(n===e)continue;const i=s[n].channel;i&&"unknown"!==i&&r.set(i,(null!==(t=r.get(i))&&void 0!==t?t:0)+1)}if(0===r.size)continue;let l,c=0,h=!1;for(const[e,t]of r)t>c?(l=e,c=t,h=!1):t===c&&(h=!0);l&&!h&&(s[e].channel=l,s[e].channelResolved=!0,i=!0)}i&&(e.channel=z(s))}resolveUnknownChannelsBySpeakerHistory(e){var t;if(!this.timeline||!this.attributionParams||!this.speakerHistory)return;const n=this.attributionParams.speakerHistoryMinRmsEvidence,s=this.attributionParams.speakerHistoryDominanceRatio;for(const n of e.words){if(!n.speaker)continue;const e=this.timeline.framesInWindow(n.start,n.end);let s=this.speakerHistory.get(n.speaker);s||(s=new Map,this.speakerHistory.set(n.speaker,s));for(const n of e)n.active&&s.set(n.channel,(null!==(t=s.get(n.channel))&&void 0!==t?t:0)+n.rms)}let i=!1;for(const t of e.words){if("unknown"!==t.channel||!t.speaker)continue;const e=this.speakerHistory.get(t.speaker);if(!e||0===e.size)continue;let r,o=0,a=0,l=0;for(const[t,n]of e)o+=n,n>a?(l=a,a=n,r=t):n>l&&(l=n);o<n||(l>0&&a<s*l||r&&(t.channel=r,t.channelResolved=!0,i=!0))}i&&(e.channel=z(e.words))}updateConfiguration(e){const{min_end_of_turn_silence_when_confident:t,min_turn_silence:n}=e,i=s(e,["min_end_of_turn_silence_when_confident","min_turn_silence"]);void 0!==t&&(void 0!==n?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 r=null!=n?n:t,o=Object.assign(Object.assign({type:"UpdateConfiguration"},i),void 0!==r?{min_turn_silence:r}:{});this.send(JSON.stringify(o))}forceEndpoint(){this.send(JSON.stringify({type:"ForceEndpoint"}))}keepAlive(){this.send(JSON.stringify({type:"KeepAlive"}))}send(e){if(!this.socket||this.socket.readyState!==this.socket.OPEN)throw new Error("Socket is not open for communication");this.socket.send(e)}close(){return i(this,arguments,void 0,(function*(e=!0){var t;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(X),yield e}else this.socket.send(X);(null===(t=this.socket)||void 0===t?void 0:t.removeAllListeners)&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}class ee extends d{constructor(e){super(e),this.baseServiceParams=e}transcriber(e){const t=Object.assign({},e);return t.token||t.apiKey||(t.apiKey=this.baseServiceParams.apiKey),new Z(t)}createTemporaryToken(e){return i(this,void 0,void 0,(function*(){const t=new URLSearchParams;Object.entries(e).forEach((([e,n])=>{null!=n&&t.append(e,String(n))}));const n=t.toString(),s=n?`/v3/token?${n}`:"/v3/token";return(yield this.fetchJson(s,{method:"GET"})).token}))}}e.AssemblyAI=class{constructor(e){e.baseUrl=e.baseUrl||"https://api.assemblyai.com",e.baseUrl&&e.baseUrl.endsWith("/")&&(e.baseUrl=e.baseUrl.slice(0,-1)),this.files=new K(e),this.transcripts=new $(e,this.files),this.lemur=new I(e),this.realtime=new L(e),this.streaming=new ee(Object.assign(Object.assign({},e),{baseUrl:e.streamingBaseUrl||"https://streaming.assemblyai.com"}));let t=e.syncBaseUrl||"https://sync.assemblyai.com";t.endsWith("/")&&(t=t.slice(0,-1)),this.sync=new b(Object.assign(Object.assign({},e),{baseUrl:t}))}},e.BrowserOnlyError=n,e.DualChannelCapture=class{constructor(e){var t;if(this.running=!1,void 0===globalThis.AudioContext)throw new n;this.params={micStream:e.micStream,systemStream:e.systemStream,transcriber:e.transcriber,targetSampleRate:null!==(t=e.targetSampleRate)&&void 0!==t?t:16e3}}on(e,t){"error"===e&&(this.errorListener=t)}start(){return i(this,void 0,void 0,(function*(){if(this.running)throw new Error("DualChannelCapture already started");this.context=new AudioContext;const e=new Blob(['\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'],{type:"application/javascript"}),t=URL.createObjectURL(e);try{yield 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=>{var n;try{this.params.transcriber.sendAudio(t.data.pcm,{channel:e})}catch(e){null===(n=this.errorListener)||void 0===n||n.call(this,e)}},t}stop(){return i(this,void 0,void 0,(function*(){var e,t,n,s,i,r;if(this.running){this.running=!1;try{null===(e=this.micEncoder)||void 0===e||e.port.close(),null===(t=this.sysEncoder)||void 0===t||t.port.close(),null===(n=this.micEncoder)||void 0===n||n.disconnect(),null===(s=this.sysEncoder)||void 0===s||s.disconnect(),null===(i=this.micSource)||void 0===i||i.disconnect(),null===(r=this.sysSource)||void 0===r||r.disconnect()}catch(e){}this.context&&"closed"!==this.context.state&&(yield this.context.close()),this.context=void 0,this.micSource=void 0,this.sysSource=void 0,this.micEncoder=void 0,this.sysEncoder=void 0}}))}},e.EnergyVad=H,e.FileService=K,e.LemurService=I,e.LinearResampler=class{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){var t;if(this.sourceRate===this.targetRate)return e;const n=new Float32Array(Math.ceil(e.length/this.ratio)+1);let s=0,i=this.fractional;for(;i<e.length;){const t=Math.floor(i),r=i-t,o=0===t?this.lastSample:e[t-1],a=e[t];n[s++]=o+(a-o)*r,i+=this.ratio}return this.lastSample=null!==(t=e[e.length-1])&&void 0!==t?t:this.lastSample,this.fractional=i-e.length,n.subarray(0,s)}reset(){this.lastSample=0,this.fractional=0}},e.RealtimeService=class extends D{},e.RealtimeServiceFactory=class extends L{},e.RealtimeTranscriber=D,e.RealtimeTranscriberFactory=L,e.StreamingTranscriber=Z,e.SyncTranscriber=b,e.SyncTranscriptError=u,e.TranscriptService=$,e.VadTimeline=V,e.attributeTurn=G,e.attributeWord=q,e.defaultSyncSpeechModel=t,e.float32ToPcm16=function(e){const t=new ArrayBuffer(2*e.length),n=new DataView(t);for(let t=0;t<e.length;t++){const s=Math.max(-1,Math.min(1,e[t]));n.setInt16(2*t,s<0?32768*s:32767*s,!0)}return t},e.rollUpTurnChannel=z}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).assemblyai={})}(this,(function(e){"use strict";const t="universal-3-5-pro";class n extends Error{constructor(e="DualChannelCapture requires a browser environment (AudioContext is undefined)."){super(e),this.name="BrowserOnlyError"}}function s(e,t){var n={};for(var s in e)Object.prototype.hasOwnProperty.call(e,s)&&t.indexOf(s)<0&&(n[s]=e[s]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(s=Object.getOwnPropertySymbols(e);i<s.length;i++)t.indexOf(s[i])<0&&Object.prototype.propertyIsEnumerable.call(e,s[i])&&(n[s[i]]=e[s[i]])}return n}function i(e,t,n,s){return new(n||(n=Promise))((function(i,r){function o(e){try{l(s.next(e))}catch(e){r(e)}}function a(e){try{l(s.throw(e))}catch(e){r(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(o,a)}l((s=s.apply(e,t||[])).next())}))}function r(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],s=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&s>=e.length&&(e=void 0),{value:e&&e[s++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function o(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e=r(e),t={},s("next"),s("throw"),s("return"),t[Symbol.asyncIterator]=function(){return this},t);function s(n){t[n]=e[n]&&function(t){return new Promise((function(s,i){(function(e,t,n,s){Promise.resolve(s).then((function(t){e({value:t,done:n})}),t)})(s,i,(t=e[n](t)).done,t.value)}))}}}"function"==typeof SuppressedError&&SuppressedError;const a=function(e){return i(this,void 0,void 0,(function*(){throw new Error("Interacting with the file system is not supported in this environment.")}))},l={cache:"no-store"};let c="";"undefined"!=typeof navigator&&navigator.userAgent&&(c+=navigator.userAgent);const h={sdk:{name:"JavaScript",version:"4.36.4"}};"undefined"!=typeof process&&(process.versions.node&&-1===c.indexOf("Node")&&(h.runtime_env={name:"Node",version:process.versions.node}),process.versions.bun&&-1===c.indexOf("Bun")&&(h.runtime_env={name:"Bun",version:process.versions.bun})),"undefined"!=typeof Deno&&process.versions.bun&&-1===c.indexOf("Deno")&&(h.runtime_env={name:"Deno",version:Deno.version.deno});class d{constructor(e){var t;this.params=e,!1===e.userAgent?this.userAgent=void 0:this.userAgent=(t=e.userAgent||{},c+(!1===t?"":" AssemblyAI/1.0 ("+Object.entries(Object.assign(Object.assign({},h),t)).map((([e,t])=>t?`${e}=${t.name}/${t.version}`:"")).join(" ")+")"))}fetchResponse(e,t){return i(this,void 0,void 0,(function*(){t=Object.assign(Object.assign({},l),t);let n={Authorization:this.params.apiKey};return t.body instanceof FormData||(n["Content-Type"]="application/json"),(null==l?void 0:l.headers)&&(n=Object.assign(Object.assign({},n),l.headers)),(null==t?void 0:t.headers)&&(n=Object.assign(Object.assign({},n),t.headers)),this.userAgent&&(n["User-Agent"]=this.userAgent,"undefined"!=typeof window&&"chrome"in window&&(n["AssemblyAI-Agent"]=this.userAgent)),t.headers=n,e.startsWith("http")||(e=this.params.baseUrl+e),yield fetch(e,t)}))}fetch(e,t){return i(this,void 0,void 0,(function*(){const n=yield this.fetchResponse(e,t);if(n.status>=400){let e;const t=yield n.text();if(t){try{e=JSON.parse(t)}catch(e){}if(null==e?void 0:e.error)throw new Error(e.error);throw new Error(t)}throw new Error(`HTTP Error: ${n.status} ${n.statusText}`)}return n}))}fetchJson(e,t){return i(this,void 0,void 0,(function*(){return(yield this.fetch(e,t)).json()}))}}class u extends Error{constructor(e,t,n,s){super(e),this.status=t,this.errorCode=n,this.retryAfter=s,this.name="SyncTranscriptError"}}function m(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 p="X-AAI-Model",f=4096,v=2048,y=100,g=4096,w=[".pcm",".raw"];class b extends d{constructor(e){super(e)}transcribe(e){return i(this,arguments,void 0,(function*(e,n={},s={}){var r,l;const{bytes:c,filename:h,contentType:d}=yield function(e,t){return i(this,void 0,void 0,(function*(){var n;let s,r,l="";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=function(e){const t=e.split(",")[1],n=atob(t),s=new Uint8Array(n.length);for(let e=0;e<n.length;e++)s[e]=n.charCodeAt(e);return s}(e);else{const t=null!==(n=m(e))&&void 0!==n?n:e;s=yield _(yield a()),r=S(t),l=k(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(yield e.arrayBuffer());const t=e.name;t&&(r=S(t),l=k(r))}else if(function(e){return"function"==typeof(null==e?void 0:e.getReader)}(e))s=yield _(e);else{if(!function(e){return"function"==typeof(null==e?void 0:e[Symbol.asyncIterator])}(e))throw new TypeError("unsupported audio input type");{s=yield function(e){return i(this,void 0,void 0,(function*(){var t,n,s,i,r,a,l;const c=[];try{for(t=!0,n=o(e);!(i=(s=yield n.next()).done);t=!0){l=s.value,t=!1;const e=l;c.push(e)}}catch(e){r={error:e}}finally{try{t||i||!(a=n.return)||(yield a.call(n))}finally{if(r)throw r.error}}return T(c)}))}(e);const t=e.path;"string"==typeof t&&(r=S(t),l=k(r))}}const c=void 0!==t.sample_rate||void 0!==t.channels,h=w.includes(l)||c;if(h&&(void 0===t.sample_rate||void 0===t.channels))throw new Error("raw PCM audio requires both sample_rate and channels in the config");return r||(r=h?"audio.pcm":"audio.wav"),{bytes:s,filename:r,contentType:h?"audio/pcm":"audio/wav"}}))}(e,n),b=new FormData;b.append("audio",new Blob([c],{type:d}),h);const A=function(e){if(void 0!==e.prompt&&e.prompt.length>f)throw new Error(`prompt exceeds 4096 characters (got ${e.prompt.length})`);const t={};void 0!==e.prompt&&(t.prompt=e.prompt);const n=function(e){if(!e)return;const t=e.map((e=>e.trim())).filter((e=>e.length>0)),n=t.reduce(((e,t)=>e+t.length),0);if(n>v)throw new Error(`keyterms_prompt exceeds ${v} characters (got ${n})`);return t.length>0?t:void 0}(e.keyterms_prompt);n&&(t.keyterms_prompt=n);const s=function(e){if(void 0===e)return;let t=("string"==typeof e?[e]:e).map((e=>e.trim())).filter((e=>e.length>0)),n=t.reduce(((e,t)=>e+t.length),0);for(;t.length>0&&(t.length>y||n>g);)n-=t[0].length,t=t.slice(1);return t.length>0?t:void 0}(e.conversation_context);s&&(t.conversation_context=s);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);return Object.keys(t).length>0?t:void 0}(n);A&&b.append("config",new Blob([JSON.stringify(A)],{type:"application/json"}));const P=yield this.fetchResponse("/v1/transcribe",{method:"POST",body:b,headers:{[p]:null!==(r=n.model)&&void 0!==r?r:t},signal:AbortSignal.timeout(null!==(l=s.timeout)&&void 0!==l?l:6e4)});if(200!==P.status)throw yield function(e){return i(this,void 0,void 0,(function*(){let t,n;const s=yield e.text();try{const e=JSON.parse(s);e&&"object"==typeof e&&!Array.isArray(e)&&("string"==typeof e.error_code&&(t=e.error_code),void 0===t&&"string"==typeof e.title&&(t=e.title.toLowerCase().replace(/ /g,"_")),"string"==typeof e.detail?n=e.detail:"string"==typeof e.message&&(n=e.message))}catch(e){s&&(n=s)}n||(n=`sync transcription failed with status ${e.status}`);const i=e.headers.get("retry-after"),r=i&&/^\d+$/.test(i)?parseInt(i,10):void 0;return new u(n,e.status,t,r)}))}(P);return yield P.json()}))}warm(e){return i(this,void 0,void 0,(function*(){var n;try{return yield this.fetchResponse("/v1/warm",{method:"GET",headers:{[p]:null!==(n=null==e?void 0:e.model)&&void 0!==n?n:t},signal:AbortSignal.timeout(1e4)}),!0}catch(e){return!1}}))}}function S(e){var t;return null!==(t=e.split(/[\\/]/).pop())&&void 0!==t?t:e}function k(e){const t=e.lastIndexOf(".");return t>0?e.slice(t).toLowerCase():""}function _(e){return i(this,void 0,void 0,(function*(){const t=[],n=e.getReader();for(;;){const{done:e,value:s}=yield n.read();if(e)break;t.push(s)}return T(t)}))}function T(e){const t=e.reduce(((e,t)=>e+t.length),0),n=new Uint8Array(t);let s=0;for(const t of e)n.set(t,s),s+=t.length;return n}const A={[4e3]:"Sample rate must be a positive integer",[4001]:"Not Authorized",[4002]:"Insufficient funds",[4003]:"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.",[4004]:"Session ID does not exist",[4008]:"Session has expired",[4010]:"Session is closed",[4029]:"Rate limited",[4030]:"Unique session violation",[4031]:"Session Timeout",[4032]:"Audio too short",[4033]:"Audio too long",[4034]:"Audio too small to transcode",[4100]:"Bad JSON",[4101]:"Bad schema",[4102]:"Too many streams",[4103]:"This session has been reconnected. This WebSocket is no longer valid.",[1013]:"Reconnect attempts exhausted",[4104]:"Could not parse word boost parameter"};class P extends Error{}const x=4e3,O=4001,R=4002,E=4003,U=4101,C={[3005]:"Server error",[3006]:"Input validation error",[3007]:"Audio chunk duration violation",[3008]:"Session expired: maximum session duration exceeded",[3009]:"Too many concurrent sessions",[x]:"Sample rate must be a positive integer",[O]:"Not Authorized",[R]:"Insufficient funds",[E]:"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.",[4004]:"Session ID does not exist",[4008]:"Session has expired",[4010]:"Session is closed",[4029]:"Rate limited",[4030]:"Unique session violation",[4031]:"Session Timeout",[4032]:"Audio too short",[4033]:"Audio too long",[4034]:"Audio too small to transcode",[U]:"Bad schema",[4102]:"Too many streams",[4103]:"This session has been reconnected. This WebSocket is no longer valid."};class M extends Error{}class I extends d{summary(e,t){return this.fetchJson("/lemur/v3/generate/summary",{method:"POST",body:JSON.stringify(e),signal:t})}questionAnswer(e,t){return this.fetchJson("/lemur/v3/generate/question-answer",{method:"POST",body:JSON.stringify(e),signal:t})}actionItems(e,t){return this.fetchJson("/lemur/v3/generate/action-items",{method:"POST",body:JSON.stringify(e),signal:t})}task(e,t){return this.fetchJson("/lemur/v3/generate/task",{method:"POST",body:JSON.stringify(e),signal:t})}getResponse(e,t){return this.fetchJson(`/lemur/v3/${e}`,{signal:t})}purgeRequestData(e,t){return this.fetchJson(`/lemur/v3/${e}`,{method:"DELETE",signal:t})}}const{WritableStream:W}="undefined"!=typeof window?window:"undefined"!=typeof global?global:globalThis;var B,F;const N=null!==(F=null!==(B=null!==WebSocket&&void 0!==WebSocket?WebSocket:null===global||void 0===global?void 0:global.WebSocket)&&void 0!==B?B:null===window||void 0===window?void 0:window.WebSocket)&&void 0!==F?F:null===self||void 0===self?void 0:self.WebSocket,J=(e,t)=>t?new N(e,t):new N(e),j='{"terminate_session":true}';class D{constructor(e){var t,n;if(this.listeners={},this.realtimeUrl=null!==(t=e.realtimeUrl)&&void 0!==t?t:"wss://api.assemblyai.com/v2/realtime/ws",this.sampleRate=null!==(n=e.sampleRate)&&void 0!==n?n: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=>{if(this.socket)throw new Error("Already connected");const t=this.connectionUrl();this.token?this.socket=J(t.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=J(t.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})=>{var n,s;t||e in A&&(t=A[e]),null===(s=(n=this.listeners).close)||void 0===s||s.call(n,e,t)},this.socket.onerror=e=>{var t,n,s,i;e.error?null===(n=(t=this.listeners).error)||void 0===n||n.call(t,e.error):null===(i=(s=this.listeners).error)||void 0===i||i.call(s,new Error(e.message))},this.socket.onmessage=({data:t})=>{var n,s,i,r,o,a,l,c,h,d,u,m,p,f,v;const y=JSON.parse(t.toString());if("error"in y)null===(s=(n=this.listeners).error)||void 0===s||s.call(n,new P(y.error));else switch(y.message_type){case"SessionBegins":{const t={sessionId:y.session_id,expiresAt:new Date(y.expires_at)};e(t),null===(r=(i=this.listeners).open)||void 0===r||r.call(i,t);break}case"PartialTranscript":y.created=new Date(y.created),null===(a=(o=this.listeners).transcript)||void 0===a||a.call(o,y),null===(c=(l=this.listeners)["transcript.partial"])||void 0===c||c.call(l,y);break;case"FinalTranscript":y.created=new Date(y.created),null===(d=(h=this.listeners).transcript)||void 0===d||d.call(h,y),null===(m=(u=this.listeners)["transcript.final"])||void 0===m||m.call(u,y);break;case"SessionInformation":null===(f=(p=this.listeners).session_information)||void 0===f||f.call(p,y);break;case"SessionTerminated":null===(v=this.sessionTerminatedResolve)||void 0===v||v.call(this)}}}))}sendAudio(e){this.send(e)}stream(){return new W({write:e=>{this.sendAudio(e)}})}forceEndUtterance(){this.send('{"force_end_utterance":true}')}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)}close(){return i(this,arguments,void 0,(function*(e=!0){var t;if(this.socket){if(this.socket.readyState===this.socket.OPEN)if(e){const e=new Promise((e=>{this.sessionTerminatedResolve=e}));this.socket.send(j),yield e}else this.socket.send(j);(null===(t=this.socket)||void 0===t?void 0:t.removeAllListeners)&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}class L extends d{constructor(e){super(e),this.rtFactoryParams=e}createService(e){return this.transcriber(e)}transcriber(e){const t=Object.assign({},e);return t.token||t.apiKey||(t.apiKey=this.rtFactoryParams.apiKey),new D(t)}createTemporaryToken(e){return i(this,void 0,void 0,(function*(){return(yield this.fetchJson("/v2/realtime/token",{method:"POST",body:JSON.stringify(e)})).token}))}}class $ extends d{constructor(e,t){super(e),this.files=t}transcribe(e,t){return i(this,void 0,void 0,(function*(){const n=yield this.submit(e);return yield this.waitUntilReady(n.id,t)}))}submit(e){return i(this,void 0,void 0,(function*(){let t,n;if("audio"in e){const{audio:i}=e,r=s(e,["audio"]);if("string"==typeof i){const e=m(i);t=null!==e?yield this.files.upload(e):i.startsWith("data:")?yield this.files.upload(i):i}else t=yield this.files.upload(i);n=Object.assign(Object.assign({},r),{audio_url:t})}else n=e;return yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(n)})}))}create(e,t){return i(this,void 0,void 0,(function*(){var n;const s=m(e.audio_url);if(null!==s){const t=yield this.files.upload(s);e.audio_url=t}const i=yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(e)});return null===(n=null==t?void 0:t.poll)||void 0===n||n?yield this.waitUntilReady(i.id,t):i}))}waitUntilReady(e,t){return i(this,void 0,void 0,(function*(){var n,s;const i=null!==(n=null==t?void 0:t.pollingInterval)&&void 0!==n?n:3e3,r=null!==(s=null==t?void 0:t.pollingTimeout)&&void 0!==s?s:-1,o=Date.now();for(;;){const t=yield this.get(e);if("completed"===t.status||"error"===t.status)return t;if(r>0&&Date.now()-o>r)throw new Error("Polling timeout");yield new Promise((e=>setTimeout(e,i)))}}))}get(e){return this.fetchJson(`/v2/transcript/${e}`)}list(e){return i(this,void 0,void 0,(function*(){let t="/v2/transcript";"string"==typeof e?t=e:e&&(t=`${t}?${new URLSearchParams(Object.keys(e).map((t=>{var n;return[t,(null===(n=e[t])||void 0===n?void 0:n.toString())||""]})))}`);const n=yield this.fetchJson(t);for(const e of n.transcripts)e.created=new Date(e.created),e.completed&&(e.completed=new Date(e.completed));return n}))}delete(e){return this.fetchJson(`/v2/transcript/${e}`,{method:"DELETE"})}wordSearch(e,t){const n=new URLSearchParams({words:t.join(",")});return this.fetchJson(`/v2/transcript/${e}/word-search?${n.toString()}`)}sentences(e){return this.fetchJson(`/v2/transcript/${e}/sentences`)}paragraphs(e){return this.fetchJson(`/v2/transcript/${e}/paragraphs`)}subtitles(e){return i(this,arguments,void 0,(function*(e,t="srt",n){let s=`/v2/transcript/${e}/${t}`;if(n){const e=new URLSearchParams;e.set("chars_per_caption",n.toString()),s+=`?${e.toString()}`}const i=yield this.fetch(s);return yield i.text()}))}redactions(e){return this.redactedAudio(e)}redactedAudio(e){return this.fetchJson(`/v2/transcript/${e}/redacted-audio`)}redactedAudioFile(e){return i(this,void 0,void 0,(function*(){const{redacted_audio_url:t,status:n}=yield this.redactedAudio(e);if("redacted_audio_ready"!==n)throw new Error(`Redacted audio status is ${n}`);const s=yield fetch(t);if(!s.ok)throw new Error(`Failed to fetch redacted audio: ${s.statusText}`);return{arrayBuffer:s.arrayBuffer.bind(s),blob:s.blob.bind(s),body:s.body,bodyUsed:s.bodyUsed}}))}}class H extends d{upload(e){return i(this,void 0,void 0,(function*(){let t;t="string"==typeof e?e.startsWith("data:")?function(e){const t=e.split(","),n=t[0].match(/:(.*?);/)[1],s=atob(t[1]);let i=s.length;const r=new Uint8Array(i);for(;i--;)r[i]=s.charCodeAt(i);return new Blob([r],{type:n})}(e):yield a():e;return(yield this.fetchJson("/v2/upload",{method:"POST",body:t,headers:{"Content-Type":"application/octet-stream"},duplex:"half"})).upload_url}))}}class K{constructor(e={}){var t,n,s,i;this.hangoverRemaining=0,this.thresholdRatio=null!==(t=e.thresholdRatio)&&void 0!==t?t:3,this.noiseFloorAlpha=null!==(n=e.noiseFloorAlpha)&&void 0!==n?n:.05,this.hangoverFrames=null!==(s=e.hangoverFrames)&&void 0!==s?s:10,this.initialNoiseFloor=null!==(i=e.initialNoiseFloor)&&void 0!==i?i:1e-4,this.noiseFloor=this.initialNoiseFloor}process(e){let t=0;for(let n=0;n<e.length;n++)t+=e[n]*e[n];const n=e.length>0?Math.sqrt(t/e.length):0;let s=n>this.noiseFloor*this.thresholdRatio;return s?this.hangoverRemaining=this.hangoverFrames:this.hangoverRemaining>0?(this.hangoverRemaining--,s=!0):this.noiseFloor=this.noiseFloor*(1-this.noiseFloorAlpha)+n*this.noiseFloorAlpha,{active:s,energy:n}}reset(){this.noiseFloor=this.initialNoiseFloor,this.hangoverRemaining=0}}class V{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 n=[];for(let s=this.head;s<this.frames.length;s++){const i=this.frames[s];if(!(i.ts<e)){if(i.ts>t)break;n.push(i)}}return n}clear(){this.frames=[],this.head=0}}function q(e,t,n){const s=function(e){var t;const n=new Map;for(const s of e)s.active&&n.set(s.channel,(null!==(t=n.get(s.channel))&&void 0!==t?t:0)+s.rms);return n}(t.framesInWindow(e.start,e.end));if(0===s.size)return"unknown";const i=[...s.entries()].sort(((e,t)=>t[1]-e[1]));if(1===i.length)return i[0][0];const[r,o]=i[0],[a,l]=i[1];return o>=n.dominanceRatio*l||o>l?r:l>o?a:"unknown"}function z(e){var t;const n=new Map;for(const s of e){if(!s.channel||"unknown"===s.channel)continue;const e=Math.max(0,s.end-s.start);n.set(s.channel,(null!==(t=n.get(s.channel))&&void 0!==t?t:0)+e)}if(0===n.size)return"unknown";const s=[...n.entries()].sort(((e,t)=>t[1]-e[1]));if(1===s.length)return s[0][0];const[i,r]=s[0],[,o]=s[1];return r===o?"unknown":i}function G(e,t,n){for(const s of e.words)s.channel=q(s,t,n);e.channel=z(e.words)}const X='{"type":"Terminate"}',Q=new Set([x,O,R,E,U]);function Y(e){return 1e3!==e&&!Q.has(e)}class Z{constructor(e){var t,n,s,i,r,o,a,l,c;if(this.listeners={},this.isDualChannel=!1,this.vadFrameSamples=0,this.minChunkSamples=0,this.maxChunkSamples=0,this.params=Object.assign(Object.assign({},e),{websocketBaseUrl:e.websocketBaseUrl||"wss://streaming.assemblyai.com/v3/ws"}),"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 h="opus"===e.encoding||"ogg_opus"===e.encoding||"aac"===e.encoding;if(void 0===e.sampleRate&&(!h||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 h=e.channels.map((e=>e.name));if(new Set(h).size!==h.length)throw new Error("StreamingTranscriber.channels names must be unique.");this.isDualChannel=!0,this.channelNames=h;const d=null!==(t=e.channelAttribution)&&void 0!==t?t:{};this.attributionParams={dominanceRatio:null!==(n=d.dominanceRatio)&&void 0!==n?n:4,timelineWindowMs:null!==(s=d.timelineWindowMs)&&void 0!==s?s:3e4,createVad:null!==(i=d.createVad)&&void 0!==i?i:()=>new K,flushIntervalMs:null!==(r=d.flushIntervalMs)&&void 0!==r?r:50,resolveUnknownChannelsMethod:null!==(o=d.resolveUnknownChannelsMethod)&&void 0!==o?o:"window",resolutionWindowWords:null!==(a=d.resolutionWindowWords)&&void 0!==a?a:2,speakerHistoryMinRmsEvidence:null!==(l=d.speakerHistoryMinRmsEvidence)&&void 0!==l?l:.5,speakerHistoryDominanceRatio:null!==(c=d.speakerHistoryDominanceRatio)&&void 0!==c?c:3},"speaker-history"===this.attributionParams.resolveUnknownChannelsMethod&&(this.speakerHistory=new Map);const u=e.sampleRate;this.vadFrameSamples=Math.max(1,Math.round(.02*u)),this.minChunkSamples=Math.max(1,Math.round(.05*u)),this.maxChunkSamples=Math.max(this.minChunkSamples,Math.round(.2*u)),this.channelBuffers=new Map(h.map((e=>[e,[]]))),this.channelSamplesReceived=new Map(h.map((e=>[e,0]))),this.channelVadFloatBuffers=new Map(h.map((e=>[e,new Float32Array(this.vadFrameSamples)]))),this.channelVadBufferIdx=new Map(h.map((e=>[e,0]))),this.channelVads=new Map(h.map((e=>[e,this.attributionParams.createVad(e)]))),this.timeline=new V(this.attributionParams.timelineWindowMs)}}connectionUrl(){var e,t;const n=new URL(null!==(e=this.params.websocketBaseUrl)&&void 0!==e?e:"");if("wss:"!==n.protocol)throw new Error("Invalid protocol, must be wss");const s=new URLSearchParams;this.token&&s.set("token",this.token),void 0!==this.params.sampleRate&&s.set("sample_rate",this.params.sampleRate.toString()),this.params.endOfTurnConfidenceThreshold&&s.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 i=null!==(t=this.params.minTurnSilence)&&void 0!==t?t:this.params.minEndOfTurnSilenceWhenConfident;return void 0!==i&&s.set("min_turn_silence",i.toString()),this.params.maxTurnSilence&&s.set("max_turn_silence",this.params.maxTurnSilence.toString()),void 0!==this.params.vadThreshold&&s.set("vad_threshold",this.params.vadThreshold.toString()),this.params.formatTurns&&s.set("format_turns",this.params.formatTurns.toString()),void 0!==this.params.sessionHeartbeat&&s.set("session_heartbeat",this.params.sessionHeartbeat.toString()),this.params.encoding&&s.set("encoding",this.params.encoding.toString()),this.params.keytermsPrompt?s.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."),s.set("keyterms_prompt",JSON.stringify(this.params.keyterms))),this.params.prompt&&s.set("prompt",this.params.prompt),this.params.agentContext&&s.set("agent_context",this.params.agentContext),this.params.filterProfanity&&s.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&&s.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."),s.set("language_code",this.params.languageCode)),void 0!==this.params.languageCodes&&s.set("language_codes",JSON.stringify(this.params.languageCodes)),void 0!==this.params.languageDetection&&s.set("language_detection",this.params.languageDetection.toString()),this.params.domain&&s.set("domain",this.params.domain),void 0!==this.params.inactivityTimeout&&s.set("inactivity_timeout",this.params.inactivityTimeout.toString()),void 0!==this.params.speakerLabels&&s.set("speaker_labels",this.params.speakerLabels.toString()),void 0!==this.params.maxSpeakers&&s.set("max_speakers",this.params.maxSpeakers.toString()),this.params.voiceFocus&&s.set("voice_focus",this.params.voiceFocus),void 0!==this.params.voiceFocusThreshold&&s.set("voice_focus_threshold",this.params.voiceFocusThreshold.toString()),void 0!==this.params.continuousPartials&&s.set("continuous_partials",this.params.continuousPartials.toString()),void 0!==this.params.interruptionDelay&&s.set("interruption_delay",this.params.interruptionDelay.toString()),void 0!==this.params.turnLeftPadMs&&s.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."),s.set("_customer_support_audio_capture",this.params.customerSupportAudioCapture.toString())),this.params.webhookUrl&&s.set("webhook_url",this.params.webhookUrl),this.params.webhookAuthHeaderName&&s.set("webhook_auth_header_name",this.params.webhookAuthHeaderName),this.params.webhookAuthHeaderValue&&s.set("webhook_auth_header_value",this.params.webhookAuthHeaderValue),void 0!==this.params.includePartialTurns&&s.set("include_partial_turns",this.params.includePartialTurns.toString()),void 0!==this.params.redactPii&&s.set("redact_pii",this.params.redactPii.toString()),void 0!==this.params.redactPiiPolicies&&s.set("redact_pii_policies",JSON.stringify(this.params.redactPiiPolicies)),void 0!==this.params.redactPiiSub&&s.set("redact_pii_sub",this.params.redactPiiSub),void 0!==this.params.mode&&s.set("mode",this.params.mode),void 0!==this.params.llmGateway&&s.set("llm_gateway",JSON.stringify(this.params.llmGateway)),n.search=s.toString(),n}on(e,t){this.listeners[e]=t}connect(){return i(this,void 0,void 0,(function*(){var e,t;if(this.socket)throw new Error("Already connected");const n=null!==(e=this.params.maxConnectionRetries)&&void 0!==e?e:2,s=null!==(t=this.params.connectionRetryDelay)&&void 0!==t?t:500;let i;for(let e=0;e<=n;e++)try{return yield this.connectOnce()}catch(t){i=t;if(!(!0===t.retryable)||e===n)throw t;console.warn(`Streaming connect attempt ${e+1}/${n+1} failed (${t.message}); retrying`),s>0&&(yield new Promise((e=>setTimeout(e,s))))}throw null!=i?i:new Error("Failed to connect to streaming server")}))}connectOnce(){return new Promise(((e,t)=>{var n;const s=this.connectionUrl(),i=null!==(n=this.params.connectTimeout)&&void 0!==n?n:1e3;let r,o=!1;const a=e=>{o||(o=!0,r&&clearTimeout(r),this.discardPendingSocket(),t(e))};i>0&&(r=setTimeout((()=>{const e=new M(`Streaming connection timed out after ${i}ms`);e.retryable=!0,a(e)}),i)),this.token?this.socket=J(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=J(s.toString(),{headers:{Authorization:this.apiKey}})),this.socket.binaryType="arraybuffer",this.socket.onopen=()=>{},this.socket.onclose=({code:e,reason:t})=>{var n,s;if(t||e in C&&(t=C[e]),!o){const n=new M(t||`Streaming connection closed (code=${e})`);return n.code=e,n.retryable=Y(e),void a(n)}this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=void 0),null===(s=(n=this.listeners).close)||void 0===s||s.call(n,e,t)},this.socket.onerror=e=>{var t,n,s;const i=null!==(t=e.error)&&void 0!==t?t:new Error(e.message);if(!o)return i.retryable=!0,void a(i);null===(s=(n=this.listeners).error)||void 0===s||s.call(n,i)},this.socket.onmessage=({data:t})=>{var n,s,i,l,c,h,d,u,m,p,f,v,y,g,w,b,S;const k=JSON.parse(t.toString());if("error"in k){const e=new M(k.error);if("error_code"in k&&(e.code=k.error_code),!o){const t=e;return t.retryable=void 0===e.code||Y(e.code),void a(t)}null===(s=(n=this.listeners).error)||void 0===s||s.call(n,e)}else{switch(k.type){case"Begin":_=k,o||(o=!0,r&&clearTimeout(r),e(_)),null===(l=(i=this.listeners).open)||void 0===l||l.call(i,k);break;case"Turn":if(this.isDualChannel&&this.timeline&&this.attributionParams)switch(G(k,this.timeline,{dominanceRatio:this.attributionParams.dominanceRatio}),this.attributionParams.resolveUnknownChannelsMethod){case"window":this.resolveUnknownChannelsByWindow(k);break;case"speaker-history":this.resolveUnknownChannelsBySpeakerHistory(k)}null===(h=(c=this.listeners).turn)||void 0===h||h.call(c,k);break;case"SpeechStarted":null===(u=(d=this.listeners).speechStarted)||void 0===u||u.call(d,k);break;case"LLMGatewayResponse":null===(p=(m=this.listeners).llmGatewayResponse)||void 0===p||p.call(m,k);break;case"SpeakerRevision":null===(v=(f=this.listeners).speakerRevision)||void 0===v||v.call(f,k);break;case"Warning":{const e=k;console.warn(`Streaming warning (code=${e.warning_code}): ${e.warning}`),null===(g=(y=this.listeners).warning)||void 0===g||g.call(y,e);break}case"Heartbeat":null===(b=(w=this.listeners).heartbeat)||void 0===b||b.call(w,k);break;case"Termination":null===(S=this.sessionTerminatedResolve)||void 0===S||S.call(this)}var _}}}))}discardPendingSocket(){if(this.socket){try{this.socket.removeAllListeners&&this.socket.removeAllListeners(),this.socket.close()}catch(e){}this.socket=void 0}}stream(){return new W({write:e=>{this.sendAudio(e)}})}sendAudio(e,t){if(this.isDualChannel){if(!(null==t?void 0: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){var n,s;const i=function(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)}(t),r=this.channelBuffers.get(e),o=this.channelVadFloatBuffers.get(e);let a=this.channelVadBufferIdx.get(e),l=this.channelSamplesReceived.get(e);const c=this.channelVads.get(e),h=this.params.sampleRate,d=this.vadFrameSamples;for(let t=0;t<i.length;t++){const u=i[t];if(r.push(u),o[a++]=u/32768,l++,a===d){const t=c.process(o),i={ts:l/h*1e3,channel:e,active:t.active,rms:t.energy};this.timeline.pushFrame(i),null===(s=(n=this.listeners).vad)||void 0===s||s.call(n,i),a=0}}this.channelVadBufferIdx.set(e,a),this.channelSamplesReceived.set(e,l),this.flushTimer||this.startFlushTimer()}startFlushTimer(){this.flushTimer=setInterval((()=>this.flushMix()),this.attributionParams.flushIntervalMs)}flushMix(e=!1){var t,n;if(!this.channelNames||!this.channelBuffers)return;const s=this.channelNames.map((e=>this.channelBuffers.get(e))),i=s.length;for(;;){let r=1/0;for(const e of s)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 o=new Int16Array(r);for(let e=0;e<r;e++){let t=0;for(let n=0;n<i;n++)t+=s[n][e];const n=Math.round(t/i);o[e]=n<-32768?-32768:n>32767?32767:n}for(const e of s)e.splice(0,r);try{this.send(o.buffer)}catch(e){return void(null===(n=(t=this.listeners).error)||void 0===n||n.call(t,e))}}}resolveUnknownChannelsByWindow(e){var t;if(!this.attributionParams)return;const n=this.attributionParams.resolutionWindowWords,s=e.words;let i=!1;for(let e=0;e<s.length;e++){if("unknown"!==s[e].channel)continue;const r=new Map,o=Math.max(0,e-n),a=Math.min(s.length-1,e+n);for(let n=o;n<=a;n++){if(n===e)continue;const i=s[n].channel;i&&"unknown"!==i&&r.set(i,(null!==(t=r.get(i))&&void 0!==t?t:0)+1)}if(0===r.size)continue;let l,c=0,h=!1;for(const[e,t]of r)t>c?(l=e,c=t,h=!1):t===c&&(h=!0);l&&!h&&(s[e].channel=l,s[e].channelResolved=!0,i=!0)}i&&(e.channel=z(s))}resolveUnknownChannelsBySpeakerHistory(e){var t;if(!this.timeline||!this.attributionParams||!this.speakerHistory)return;const n=this.attributionParams.speakerHistoryMinRmsEvidence,s=this.attributionParams.speakerHistoryDominanceRatio;for(const n of e.words){if(!n.speaker)continue;const e=this.timeline.framesInWindow(n.start,n.end);let s=this.speakerHistory.get(n.speaker);s||(s=new Map,this.speakerHistory.set(n.speaker,s));for(const n of e)n.active&&s.set(n.channel,(null!==(t=s.get(n.channel))&&void 0!==t?t:0)+n.rms)}let i=!1;for(const t of e.words){if("unknown"!==t.channel||!t.speaker)continue;const e=this.speakerHistory.get(t.speaker);if(!e||0===e.size)continue;let r,o=0,a=0,l=0;for(const[t,n]of e)o+=n,n>a?(l=a,a=n,r=t):n>l&&(l=n);o<n||(l>0&&a<s*l||r&&(t.channel=r,t.channelResolved=!0,i=!0))}i&&(e.channel=z(e.words))}updateConfiguration(e){const{min_end_of_turn_silence_when_confident:t,min_turn_silence:n}=e,i=s(e,["min_end_of_turn_silence_when_confident","min_turn_silence"]);void 0!==t&&(void 0!==n?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 r=null!=n?n:t,o=Object.assign(Object.assign({type:"UpdateConfiguration"},i),void 0!==r?{min_turn_silence:r}:{});this.send(JSON.stringify(o))}forceEndpoint(){this.send(JSON.stringify({type:"ForceEndpoint"}))}keepAlive(){this.send(JSON.stringify({type:"KeepAlive"}))}send(e){if(!this.socket||this.socket.readyState!==this.socket.OPEN)throw new Error("Socket is not open for communication");this.socket.send(e)}close(){return i(this,arguments,void 0,(function*(e=!0){var t;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(X),yield e}else this.socket.send(X);(null===(t=this.socket)||void 0===t?void 0:t.removeAllListeners)&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}class ee extends d{constructor(e){super(e),this.baseServiceParams=e}transcriber(e){const t=Object.assign({},e);return t.token||t.apiKey||(t.apiKey=this.baseServiceParams.apiKey),new Z(t)}createTemporaryToken(e){return i(this,void 0,void 0,(function*(){const t=new URLSearchParams;Object.entries(e).forEach((([e,n])=>{null!=n&&t.append(e,String(n))}));const n=t.toString(),s=n?`/v3/token?${n}`:"/v3/token";return(yield this.fetchJson(s,{method:"GET"})).token}))}}e.AssemblyAI=class{constructor(e){e.baseUrl=e.baseUrl||"https://api.assemblyai.com",e.baseUrl&&e.baseUrl.endsWith("/")&&(e.baseUrl=e.baseUrl.slice(0,-1)),this.files=new H(e),this.transcripts=new $(e,this.files),this.lemur=new I(e),this.realtime=new L(e),this.streaming=new ee(Object.assign(Object.assign({},e),{baseUrl:e.streamingBaseUrl||"https://streaming.assemblyai.com"}));let t=e.syncBaseUrl||"https://sync.assemblyai.com";t.endsWith("/")&&(t=t.slice(0,-1)),this.sync=new b(Object.assign(Object.assign({},e),{baseUrl:t}))}},e.BrowserOnlyError=n,e.DualChannelCapture=class{constructor(e){var t;if(this.running=!1,void 0===globalThis.AudioContext)throw new n;this.params={micStream:e.micStream,systemStream:e.systemStream,transcriber:e.transcriber,targetSampleRate:null!==(t=e.targetSampleRate)&&void 0!==t?t:16e3}}on(e,t){"error"===e&&(this.errorListener=t)}start(){return i(this,void 0,void 0,(function*(){if(this.running)throw new Error("DualChannelCapture already started");this.context=new AudioContext;const e=new Blob(['\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'],{type:"application/javascript"}),t=URL.createObjectURL(e);try{yield 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=>{var n;try{this.params.transcriber.sendAudio(t.data.pcm,{channel:e})}catch(e){null===(n=this.errorListener)||void 0===n||n.call(this,e)}},t}stop(){return i(this,void 0,void 0,(function*(){var e,t,n,s,i,r;if(this.running){this.running=!1;try{null===(e=this.micEncoder)||void 0===e||e.port.close(),null===(t=this.sysEncoder)||void 0===t||t.port.close(),null===(n=this.micEncoder)||void 0===n||n.disconnect(),null===(s=this.sysEncoder)||void 0===s||s.disconnect(),null===(i=this.micSource)||void 0===i||i.disconnect(),null===(r=this.sysSource)||void 0===r||r.disconnect()}catch(e){}this.context&&"closed"!==this.context.state&&(yield this.context.close()),this.context=void 0,this.micSource=void 0,this.sysSource=void 0,this.micEncoder=void 0,this.sysEncoder=void 0}}))}},e.EnergyVad=K,e.FileService=H,e.LemurService=I,e.LinearResampler=class{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){var t;if(this.sourceRate===this.targetRate)return e;const n=new Float32Array(Math.ceil(e.length/this.ratio)+1);let s=0,i=this.fractional;for(;i<e.length;){const t=Math.floor(i),r=i-t,o=0===t?this.lastSample:e[t-1],a=e[t];n[s++]=o+(a-o)*r,i+=this.ratio}return this.lastSample=null!==(t=e[e.length-1])&&void 0!==t?t:this.lastSample,this.fractional=i-e.length,n.subarray(0,s)}reset(){this.lastSample=0,this.fractional=0}},e.RealtimeService=class extends D{},e.RealtimeServiceFactory=class extends L{},e.RealtimeTranscriber=D,e.RealtimeTranscriberFactory=L,e.StreamingTranscriber=Z,e.SyncTranscriber=b,e.SyncTranscriptError=u,e.TranscriptService=$,e.VadTimeline=V,e.attributeTurn=G,e.attributeWord=q,e.defaultSyncSpeechModel=t,e.float32ToPcm16=function(e){const t=new ArrayBuffer(2*e.length),n=new DataView(t);for(let t=0;t<e.length;t++){const s=Math.max(-1,Math.min(1,e[t]));n.setInt16(2*t,s<0?32768*s:32767*s,!0)}return t},e.rollUpTurnChannel=z}));
package/dist/browser.mjs CHANGED
@@ -39,7 +39,7 @@ if (typeof navigator !== "undefined" && navigator.userAgent) {
39
39
  defaultUserAgentString += navigator.userAgent;
40
40
  }
41
41
  const defaultUserAgent = {
42
- sdk: { name: "JavaScript", version: "4.36.3" },
42
+ sdk: { name: "JavaScript", version: "4.36.4" },
43
43
  };
44
44
  if (typeof process !== "undefined") {
45
45
  if (process.versions.node && defaultUserAgentString.indexOf("Node") === -1) {
@@ -1386,9 +1386,12 @@ class StreamingTranscriber {
1386
1386
  if (!(this.token || this.apiKey)) {
1387
1387
  throw new Error("API key or temporary token is required.");
1388
1388
  }
1389
- const isOpus = params.encoding === "opus" || params.encoding === "ogg_opus";
1390
- if (params.sampleRate === undefined && (!isOpus || params.channels)) {
1391
- throw new Error('`sampleRate` is required; it may only be omitted when `encoding` is "opus" or "ogg_opus" (the Opus stream is self-describing) and dual-channel mode is not used.');
1389
+ const isSelfDescribing = params.encoding === "opus" ||
1390
+ params.encoding === "ogg_opus" ||
1391
+ params.encoding === "aac";
1392
+ if (params.sampleRate === undefined &&
1393
+ (!isSelfDescribing || params.channels)) {
1394
+ 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.');
1392
1395
  }
1393
1396
  if (params.channels) {
1394
1397
  if (params.channels.length !== 2) {
@@ -1466,6 +1469,9 @@ class StreamingTranscriber {
1466
1469
  if (this.params.formatTurns) {
1467
1470
  searchParams.set("format_turns", this.params.formatTurns.toString());
1468
1471
  }
1472
+ if (this.params.sessionHeartbeat !== undefined) {
1473
+ searchParams.set("session_heartbeat", this.params.sessionHeartbeat.toString());
1474
+ }
1469
1475
  if (this.params.encoding) {
1470
1476
  searchParams.set("encoding", this.params.encoding.toString());
1471
1477
  }
@@ -1754,6 +1760,10 @@ Learn more at https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/docs/c
1754
1760
  this.listeners.warning?.(warning);
1755
1761
  break;
1756
1762
  }
1763
+ case "Heartbeat": {
1764
+ this.listeners.heartbeat?.(message);
1765
+ break;
1766
+ }
1757
1767
  case "Termination": {
1758
1768
  this.sessionTerminatedResolve?.();
1759
1769
  break;
package/dist/bun.mjs CHANGED
@@ -37,7 +37,7 @@ if (typeof navigator !== "undefined" && navigator.userAgent) {
37
37
  defaultUserAgentString += navigator.userAgent;
38
38
  }
39
39
  const defaultUserAgent = {
40
- sdk: { name: "JavaScript", version: "4.36.3" },
40
+ sdk: { name: "JavaScript", version: "4.36.4" },
41
41
  };
42
42
  if (typeof process !== "undefined") {
43
43
  if (process.versions.node && defaultUserAgentString.indexOf("Node") === -1) {
@@ -1368,9 +1368,12 @@ class StreamingTranscriber {
1368
1368
  if (!(this.token || this.apiKey)) {
1369
1369
  throw new Error("API key or temporary token is required.");
1370
1370
  }
1371
- const isOpus = params.encoding === "opus" || params.encoding === "ogg_opus";
1372
- if (params.sampleRate === undefined && (!isOpus || params.channels)) {
1373
- throw new Error('`sampleRate` is required; it may only be omitted when `encoding` is "opus" or "ogg_opus" (the Opus stream is self-describing) and dual-channel mode is not used.');
1371
+ const isSelfDescribing = params.encoding === "opus" ||
1372
+ params.encoding === "ogg_opus" ||
1373
+ params.encoding === "aac";
1374
+ if (params.sampleRate === undefined &&
1375
+ (!isSelfDescribing || params.channels)) {
1376
+ 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.');
1374
1377
  }
1375
1378
  if (params.channels) {
1376
1379
  if (params.channels.length !== 2) {
@@ -1448,6 +1451,9 @@ class StreamingTranscriber {
1448
1451
  if (this.params.formatTurns) {
1449
1452
  searchParams.set("format_turns", this.params.formatTurns.toString());
1450
1453
  }
1454
+ if (this.params.sessionHeartbeat !== undefined) {
1455
+ searchParams.set("session_heartbeat", this.params.sessionHeartbeat.toString());
1456
+ }
1451
1457
  if (this.params.encoding) {
1452
1458
  searchParams.set("encoding", this.params.encoding.toString());
1453
1459
  }
@@ -1732,6 +1738,10 @@ class StreamingTranscriber {
1732
1738
  this.listeners.warning?.(warning);
1733
1739
  break;
1734
1740
  }
1741
+ case "Heartbeat": {
1742
+ this.listeners.heartbeat?.(message);
1743
+ break;
1744
+ }
1735
1745
  case "Termination": {
1736
1746
  this.sessionTerminatedResolve?.();
1737
1747
  break;