assemblyai
Advanced tools
Comparing version 4.2.3 to 4.3.0
# Changelog | ||
## [4.3.0] - 2024-02-15 | ||
### Added | ||
- Add `RealtimeTranscriber.configureEndUtteranceSilenceThreshold` function | ||
- Add `RealtimeTranscriber.forceEndUtterance` function | ||
- Add `end_utterance_silence_threshold` property to `CreateRealtimeTranscriberParams` and `RealtimeTranscriberParams` types. | ||
## [4.2.3] - 2024-02-13 | ||
### Added | ||
- Add `speech_model` field to `TranscriptParams` and add `SpeechModel` type. | ||
## [4.2.2] - 2024-01-29 | ||
@@ -4,0 +18,0 @@ |
@@ -198,2 +198,4 @@ (function (global, factory) { | ||
const defaultRealtimeUrl = "wss://api.assemblyai.com/v2/realtime/ws"; | ||
const forceEndOfUtteranceMessage = `{"force_end_utterance":true}`; | ||
const terminateSessionMessage = `{"terminate_session":true}`; | ||
class RealtimeTranscriber { | ||
@@ -207,2 +209,4 @@ constructor(params) { | ||
this.encoding = params.encoding; | ||
this.end_utterance_silence_threshold = | ||
params.end_utterance_silence_threshold; | ||
if ("token" in params && params.token) | ||
@@ -254,2 +258,9 @@ this.token = params.token; | ||
this.socket.binaryType = "arraybuffer"; | ||
this.socket.onopen = () => { | ||
if (this.end_utterance_silence_threshold === undefined || | ||
this.end_utterance_silence_threshold === null) { | ||
return; | ||
} | ||
this.configureEndUtteranceSilenceThreshold(this.end_utterance_silence_threshold); | ||
}; | ||
this.socket.onclose = ({ code, reason }) => { | ||
@@ -311,6 +322,3 @@ var _a, _b; | ||
sendAudio(audio) { | ||
if (!this.socket || this.socket.readyState !== WebSocket$1.OPEN) { | ||
throw new Error("Socket is not open for communication"); | ||
} | ||
this.socket.send(audio); | ||
this.send(audio); | ||
} | ||
@@ -324,2 +332,22 @@ stream() { | ||
} | ||
/** | ||
* Manually end an utterance | ||
*/ | ||
forceEndUtterance() { | ||
this.send(forceEndOfUtteranceMessage); | ||
} | ||
/** | ||
* Configure the threshold for how long to wait before ending an utterance. Default is 700ms. | ||
* @param threshold The duration of the end utterance silence threshold in milliseconds | ||
* @format integer | ||
*/ | ||
configureEndUtteranceSilenceThreshold(threshold) { | ||
this.send(`{"end_utterance_silence_threshold":${threshold}}`); | ||
} | ||
send(data) { | ||
if (!this.socket || this.socket.readyState !== WebSocket$1.OPEN) { | ||
throw new Error("Socket is not open for communication"); | ||
} | ||
this.socket.send(data); | ||
} | ||
close(waitForSessionTermination = true) { | ||
@@ -329,3 +357,2 @@ return __awaiter(this, void 0, void 0, function* () { | ||
if (this.socket.readyState === WebSocket$1.OPEN) { | ||
const terminateSessionMessage = `{"terminate_session": true}`; | ||
if (waitForSessionTermination) { | ||
@@ -332,0 +359,0 @@ const sessionTerminatedPromise = new Promise((resolve) => { |
@@ -1,1 +0,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";function t(e,t,s,i){return new(s||(s=Promise))((function(o,n){function r(e){try{c(i.next(e))}catch(e){n(e)}}function a(e){try{c(i.throw(e))}catch(e){n(e)}}function c(e){var t;e.done?o(e.value):(t=e.value,t instanceof s?t:new s((function(e){e(t)}))).then(r,a)}c((i=i.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class s{constructor(e){this.params=e}fetch(e,s){var i;return t(this,void 0,void 0,(function*(){(s=null!=s?s:{}).headers=null!==(i=s.headers)&&void 0!==i?i:{},s.headers=Object.assign({Authorization:this.params.apiKey,"Content-Type":"application/json"},s.headers),e.startsWith("http")||(e=this.params.baseUrl+e);const t=yield fetch(e,s);if(t.status>=400){let e;const s=yield t.text();if(s){try{e=JSON.parse(s)}catch(e){}if(null==e?void 0:e.error)throw new Error(e.error);throw new Error(s)}throw new Error(`HTTP Error: ${t.status} ${t.statusText}`)}return t}))}fetchJson(e,s){return t(this,void 0,void 0,(function*(){return(yield this.fetch(e,s)).json()}))}}class i extends s{summary(e){return this.fetchJson("/lemur/v3/generate/summary",{method:"POST",body:JSON.stringify(e)})}questionAnswer(e){return this.fetchJson("/lemur/v3/generate/question-answer",{method:"POST",body:JSON.stringify(e)})}actionItems(e){return this.fetchJson("/lemur/v3/generate/action-items",{method:"POST",body:JSON.stringify(e)})}task(e){return this.fetchJson("/lemur/v3/generate/task",{method:"POST",body:JSON.stringify(e)})}purgeRequestData(e){return this.fetchJson(`/lemur/v3/${e}`,{method:"DELETE"})}}const{WritableStream:o}="undefined"!=typeof window?window:"undefined"!=typeof global?global:globalThis;var n=null;"undefined"!=typeof WebSocket?n=WebSocket:"undefined"!=typeof MozWebSocket?n=MozWebSocket:"undefined"!=typeof global?n=global.WebSocket||global.MozWebSocket:"undefined"!=typeof window?n=window.WebSocket||window.MozWebSocket:"undefined"!=typeof self&&(n=self.WebSocket||self.MozWebSocket);var r,a=n;!function(e){e[e.BadSampleRate=4e3]="BadSampleRate",e[e.AuthFailed=4001]="AuthFailed",e[e.InsufficientFundsOrFreeAccount=4002]="InsufficientFundsOrFreeAccount",e[e.NonexistentSessionId=4004]="NonexistentSessionId",e[e.SessionExpired=4008]="SessionExpired",e[e.ClosedSession=4010]="ClosedSession",e[e.RateLimited=4029]="RateLimited",e[e.UniqueSessionViolation=4030]="UniqueSessionViolation",e[e.SessionTimeout=4031]="SessionTimeout",e[e.AudioTooShort=4032]="AudioTooShort",e[e.AudioTooLong=4033]="AudioTooLong",e[e.BadJson=4100]="BadJson",e[e.BadSchema=4101]="BadSchema",e[e.TooManyStreams=4102]="TooManyStreams",e[e.Reconnected=4103]="Reconnected",e[e.ReconnectAttemptsExhausted=1013]="ReconnectAttemptsExhausted"}(r||(r={}));const c={[r.BadSampleRate]:"Sample rate must be a positive integer",[r.AuthFailed]:"Not Authorized",[r.InsufficientFundsOrFreeAccount]:"Insufficient funds or you are using a free account. This feature is paid-only and requires you to add a credit card. Please visit https://assemblyai.com/dashboard/ to add a credit card to your account.",[r.NonexistentSessionId]:"Session ID does not exist",[r.SessionExpired]:"Session has expired",[r.ClosedSession]:"Session is closed",[r.RateLimited]:"Rate limited",[r.UniqueSessionViolation]:"Unique session violation",[r.SessionTimeout]:"Session Timeout",[r.AudioTooShort]:"Audio too short",[r.AudioTooLong]:"Audio too long",[r.BadJson]:"Bad JSON",[r.BadSchema]:"Bad schema",[r.TooManyStreams]:"Too many streams",[r.Reconnected]:"Reconnected",[r.ReconnectAttemptsExhausted]:"Reconnect attempts exhausted"};class l extends Error{}class d{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,"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),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=new a(t.toString()):this.socket=new a(t.toString(),{headers:{Authorization:this.apiKey}}),this.socket.binaryType="arraybuffer",this.socket.onclose=({code:e,reason:t})=>{var s,i;t||e in r&&(t=c[e]),null===(i=(s=this.listeners).close)||void 0===i||i.call(s,e,t)},this.socket.onerror=e=>{var t,s,i,o;e.error?null===(s=(t=this.listeners).error)||void 0===s||s.call(t,e.error):null===(o=(i=this.listeners).error)||void 0===o||o.call(i,new Error(e.message))},this.socket.onmessage=({data:t})=>{var s,i,o,n,r,a,c,d,u,h,f,p,m;const y=JSON.parse(t.toString());if("error"in y)null===(i=(s=this.listeners).error)||void 0===i||i.call(s,new l(y.error));else switch(y.message_type){case"SessionBegins":{const t={sessionId:y.session_id,expiresAt:new Date(y.expires_at)};e(t),null===(n=(o=this.listeners).open)||void 0===n||n.call(o,t);break}case"PartialTranscript":y.created=new Date(y.created),null===(a=(r=this.listeners).transcript)||void 0===a||a.call(r,y),null===(d=(c=this.listeners)["transcript.partial"])||void 0===d||d.call(c,y);break;case"FinalTranscript":y.created=new Date(y.created),null===(h=(u=this.listeners).transcript)||void 0===h||h.call(u,y),null===(p=(f=this.listeners)["transcript.final"])||void 0===p||p.call(f,y);break;case"SessionTerminated":null===(m=this.sessionTerminatedResolve)||void 0===m||m.call(this)}}}))}sendAudio(e){if(!this.socket||this.socket.readyState!==a.OPEN)throw new Error("Socket is not open for communication");this.socket.send(e)}stream(){return new o({write:e=>{this.sendAudio(e)}})}close(e=!0){return t(this,void 0,void 0,(function*(){if(this.socket){if(this.socket.readyState===a.OPEN){const t='{"terminate_session": true}';if(e){const e=new Promise((e=>{this.sessionTerminatedResolve=e}));this.socket.send(t),yield e}else this.socket.send(t)}"removeAllListeners"in this.socket&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}class u extends s{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 t(this,void 0,void 0,(function*(){return(yield this.fetchJson("/v2/realtime/token",{method:"POST",body:JSON.stringify(e)})).token}))}}function h(e){return e.startsWith("http")||e.startsWith("https")?null:e.startsWith("file://")?e.substring(7):e.startsWith("file:")?e.substring(5):e}class f extends s{constructor(e,t){super(e),this.files=t}transcribe(e,s){return t(this,void 0,void 0,(function*(){const t=yield this.submit(e);return yield this.waitUntilReady(t.id,s)}))}submit(e){return t(this,void 0,void 0,(function*(){const{audio:t}=e,s=function(e,t){var s={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&t.indexOf(i)<0&&(s[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(i=Object.getOwnPropertySymbols(e);o<i.length;o++)t.indexOf(i[o])<0&&Object.prototype.propertyIsEnumerable.call(e,i[o])&&(s[i[o]]=e[i[o]])}return s}(e,["audio"]);let i;if("string"==typeof t){const e=h(t);i=null!==e?yield this.files.upload(e):t}else i=yield this.files.upload(t);return yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(Object.assign(Object.assign({},s),{audio_url:i}))})}))}create(e,s){var i;return t(this,void 0,void 0,(function*(){const t=h(e.audio_url);if(null!==t){const s=yield this.files.upload(t);e.audio_url=s}const o=yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(e)});return null===(i=null==s?void 0:s.poll)||void 0===i||i?yield this.waitUntilReady(o.id,s):o}))}waitUntilReady(e,s){var i,o;return t(this,void 0,void 0,(function*(){const t=null!==(i=null==s?void 0:s.pollingInterval)&&void 0!==i?i:3e3,n=null!==(o=null==s?void 0:s.pollingTimeout)&&void 0!==o?o:-1,r=Date.now();for(;;){const s=yield this.get(e);if("completed"===s.status||"error"===s.status)return s;if(n>0&&Date.now()-r>n)throw new Error("Polling timeout");yield new Promise((e=>setTimeout(e,t)))}}))}get(e){return this.fetchJson(`/v2/transcript/${e}`)}list(e){return t(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 s;return[t,(null===(s=e[t])||void 0===s?void 0:s.toString())||""]})))}`);const s=yield this.fetchJson(t);for(const e of s.transcripts)e.created=new Date(e.created),e.completed&&(e.completed=new Date(e.completed));return s}))}delete(e){return this.fetchJson(`/v2/transcript/${e}`,{method:"DELETE"})}wordSearch(e,t){const s=new URLSearchParams({words:t.join(",")});return this.fetchJson(`/v2/transcript/${e}/word-search?${s.toString()}`)}sentences(e){return this.fetchJson(`/v2/transcript/${e}/sentences`)}paragraphs(e){return this.fetchJson(`/v2/transcript/${e}/paragraphs`)}subtitles(e,s="srt",i){return t(this,void 0,void 0,(function*(){let t=`/v2/transcript/${e}/${s}`;if(i){const e=new URLSearchParams;e.set("chars_per_caption",i.toString()),t+=`?${e.toString()}`}const o=yield this.fetch(t);return yield o.text()}))}redactions(e){return this.fetchJson(`/v2/transcript/${e}/redacted-audio`)}}class p extends s{upload(e){return t(this,void 0,void 0,(function*(){let s;s="string"==typeof e?yield function(e){return t(this,void 0,void 0,(function*(){throw new Error("Interacting with the file system is not supported in this environment.")}))}():e;return(yield this.fetchJson("/v2/upload",{method:"POST",body:s,headers:{"Content-Type":"application/octet-stream"},duplex:"half"})).upload_url}))}}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 p(e),this.transcripts=new f(e,this.files),this.lemur=new i(e),this.realtime=new u(e)}},e.FileService=p,e.LemurService=i,e.RealtimeService=class extends d{},e.RealtimeServiceFactory=class extends u{},e.RealtimeTranscriber=d,e.RealtimeTranscriberFactory=u,e.TranscriptService=f})); | ||
!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";function t(e,t,s,i){return new(s||(s=Promise))((function(n,o){function r(e){try{c(i.next(e))}catch(e){o(e)}}function a(e){try{c(i.throw(e))}catch(e){o(e)}}function c(e){var t;e.done?n(e.value):(t=e.value,t instanceof s?t:new s((function(e){e(t)}))).then(r,a)}c((i=i.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class s{constructor(e){this.params=e}fetch(e,s){var i;return t(this,void 0,void 0,(function*(){(s=null!=s?s:{}).headers=null!==(i=s.headers)&&void 0!==i?i:{},s.headers=Object.assign({Authorization:this.params.apiKey,"Content-Type":"application/json"},s.headers),e.startsWith("http")||(e=this.params.baseUrl+e);const t=yield fetch(e,s);if(t.status>=400){let e;const s=yield t.text();if(s){try{e=JSON.parse(s)}catch(e){}if(null==e?void 0:e.error)throw new Error(e.error);throw new Error(s)}throw new Error(`HTTP Error: ${t.status} ${t.statusText}`)}return t}))}fetchJson(e,s){return t(this,void 0,void 0,(function*(){return(yield this.fetch(e,s)).json()}))}}class i extends s{summary(e){return this.fetchJson("/lemur/v3/generate/summary",{method:"POST",body:JSON.stringify(e)})}questionAnswer(e){return this.fetchJson("/lemur/v3/generate/question-answer",{method:"POST",body:JSON.stringify(e)})}actionItems(e){return this.fetchJson("/lemur/v3/generate/action-items",{method:"POST",body:JSON.stringify(e)})}task(e){return this.fetchJson("/lemur/v3/generate/task",{method:"POST",body:JSON.stringify(e)})}purgeRequestData(e){return this.fetchJson(`/lemur/v3/${e}`,{method:"DELETE"})}}const{WritableStream:n}="undefined"!=typeof window?window:"undefined"!=typeof global?global:globalThis;var o=null;"undefined"!=typeof WebSocket?o=WebSocket:"undefined"!=typeof MozWebSocket?o=MozWebSocket:"undefined"!=typeof global?o=global.WebSocket||global.MozWebSocket:"undefined"!=typeof window?o=window.WebSocket||window.MozWebSocket:"undefined"!=typeof self&&(o=self.WebSocket||self.MozWebSocket);var r,a=o;!function(e){e[e.BadSampleRate=4e3]="BadSampleRate",e[e.AuthFailed=4001]="AuthFailed",e[e.InsufficientFundsOrFreeAccount=4002]="InsufficientFundsOrFreeAccount",e[e.NonexistentSessionId=4004]="NonexistentSessionId",e[e.SessionExpired=4008]="SessionExpired",e[e.ClosedSession=4010]="ClosedSession",e[e.RateLimited=4029]="RateLimited",e[e.UniqueSessionViolation=4030]="UniqueSessionViolation",e[e.SessionTimeout=4031]="SessionTimeout",e[e.AudioTooShort=4032]="AudioTooShort",e[e.AudioTooLong=4033]="AudioTooLong",e[e.BadJson=4100]="BadJson",e[e.BadSchema=4101]="BadSchema",e[e.TooManyStreams=4102]="TooManyStreams",e[e.Reconnected=4103]="Reconnected",e[e.ReconnectAttemptsExhausted=1013]="ReconnectAttemptsExhausted"}(r||(r={}));const c={[r.BadSampleRate]:"Sample rate must be a positive integer",[r.AuthFailed]:"Not Authorized",[r.InsufficientFundsOrFreeAccount]:"Insufficient funds or you are using a free account. This feature is paid-only and requires you to add a credit card. Please visit https://assemblyai.com/dashboard/ to add a credit card to your account.",[r.NonexistentSessionId]:"Session ID does not exist",[r.SessionExpired]:"Session has expired",[r.ClosedSession]:"Session is closed",[r.RateLimited]:"Rate limited",[r.UniqueSessionViolation]:"Unique session violation",[r.SessionTimeout]:"Session Timeout",[r.AudioTooShort]:"Audio too short",[r.AudioTooLong]:"Audio too long",[r.BadJson]:"Bad JSON",[r.BadSchema]:"Bad schema",[r.TooManyStreams]:"Too many streams",[r.Reconnected]:"Reconnected",[r.ReconnectAttemptsExhausted]:"Reconnect attempts exhausted"};class l extends Error{}const d='{"terminate_session":true}';class h{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.end_utterance_silence_threshold=e.end_utterance_silence_threshold,"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),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=new a(t.toString()):this.socket=new a(t.toString(),{headers:{Authorization:this.apiKey}}),this.socket.binaryType="arraybuffer",this.socket.onopen=()=>{void 0!==this.end_utterance_silence_threshold&&null!==this.end_utterance_silence_threshold&&this.configureEndUtteranceSilenceThreshold(this.end_utterance_silence_threshold)},this.socket.onclose=({code:e,reason:t})=>{var s,i;t||e in r&&(t=c[e]),null===(i=(s=this.listeners).close)||void 0===i||i.call(s,e,t)},this.socket.onerror=e=>{var t,s,i,n;e.error?null===(s=(t=this.listeners).error)||void 0===s||s.call(t,e.error):null===(n=(i=this.listeners).error)||void 0===n||n.call(i,new Error(e.message))},this.socket.onmessage=({data:t})=>{var s,i,n,o,r,a,c,d,h,u,f,p,m;const y=JSON.parse(t.toString());if("error"in y)null===(i=(s=this.listeners).error)||void 0===i||i.call(s,new l(y.error));else switch(y.message_type){case"SessionBegins":{const t={sessionId:y.session_id,expiresAt:new Date(y.expires_at)};e(t),null===(o=(n=this.listeners).open)||void 0===o||o.call(n,t);break}case"PartialTranscript":y.created=new Date(y.created),null===(a=(r=this.listeners).transcript)||void 0===a||a.call(r,y),null===(d=(c=this.listeners)["transcript.partial"])||void 0===d||d.call(c,y);break;case"FinalTranscript":y.created=new Date(y.created),null===(u=(h=this.listeners).transcript)||void 0===u||u.call(h,y),null===(p=(f=this.listeners)["transcript.final"])||void 0===p||p.call(f,y);break;case"SessionTerminated":null===(m=this.sessionTerminatedResolve)||void 0===m||m.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!==a.OPEN)throw new Error("Socket is not open for communication");this.socket.send(e)}close(e=!0){return t(this,void 0,void 0,(function*(){if(this.socket){if(this.socket.readyState===a.OPEN)if(e){const e=new Promise((e=>{this.sessionTerminatedResolve=e}));this.socket.send(d),yield e}else this.socket.send(d);"removeAllListeners"in this.socket&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}class u extends s{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 h(t)}createTemporaryToken(e){return t(this,void 0,void 0,(function*(){return(yield this.fetchJson("/v2/realtime/token",{method:"POST",body:JSON.stringify(e)})).token}))}}function f(e){return e.startsWith("http")||e.startsWith("https")?null:e.startsWith("file://")?e.substring(7):e.startsWith("file:")?e.substring(5):e}class p extends s{constructor(e,t){super(e),this.files=t}transcribe(e,s){return t(this,void 0,void 0,(function*(){const t=yield this.submit(e);return yield this.waitUntilReady(t.id,s)}))}submit(e){return t(this,void 0,void 0,(function*(){const{audio:t}=e,s=function(e,t){var s={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&t.indexOf(i)<0&&(s[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var n=0;for(i=Object.getOwnPropertySymbols(e);n<i.length;n++)t.indexOf(i[n])<0&&Object.prototype.propertyIsEnumerable.call(e,i[n])&&(s[i[n]]=e[i[n]])}return s}(e,["audio"]);let i;if("string"==typeof t){const e=f(t);i=null!==e?yield this.files.upload(e):t}else i=yield this.files.upload(t);return yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(Object.assign(Object.assign({},s),{audio_url:i}))})}))}create(e,s){var i;return t(this,void 0,void 0,(function*(){const t=f(e.audio_url);if(null!==t){const s=yield this.files.upload(t);e.audio_url=s}const n=yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(e)});return null===(i=null==s?void 0:s.poll)||void 0===i||i?yield this.waitUntilReady(n.id,s):n}))}waitUntilReady(e,s){var i,n;return t(this,void 0,void 0,(function*(){const t=null!==(i=null==s?void 0:s.pollingInterval)&&void 0!==i?i:3e3,o=null!==(n=null==s?void 0:s.pollingTimeout)&&void 0!==n?n:-1,r=Date.now();for(;;){const s=yield this.get(e);if("completed"===s.status||"error"===s.status)return s;if(o>0&&Date.now()-r>o)throw new Error("Polling timeout");yield new Promise((e=>setTimeout(e,t)))}}))}get(e){return this.fetchJson(`/v2/transcript/${e}`)}list(e){return t(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 s;return[t,(null===(s=e[t])||void 0===s?void 0:s.toString())||""]})))}`);const s=yield this.fetchJson(t);for(const e of s.transcripts)e.created=new Date(e.created),e.completed&&(e.completed=new Date(e.completed));return s}))}delete(e){return this.fetchJson(`/v2/transcript/${e}`,{method:"DELETE"})}wordSearch(e,t){const s=new URLSearchParams({words:t.join(",")});return this.fetchJson(`/v2/transcript/${e}/word-search?${s.toString()}`)}sentences(e){return this.fetchJson(`/v2/transcript/${e}/sentences`)}paragraphs(e){return this.fetchJson(`/v2/transcript/${e}/paragraphs`)}subtitles(e,s="srt",i){return t(this,void 0,void 0,(function*(){let t=`/v2/transcript/${e}/${s}`;if(i){const e=new URLSearchParams;e.set("chars_per_caption",i.toString()),t+=`?${e.toString()}`}const n=yield this.fetch(t);return yield n.text()}))}redactions(e){return this.fetchJson(`/v2/transcript/${e}/redacted-audio`)}}class m extends s{upload(e){return t(this,void 0,void 0,(function*(){let s;s="string"==typeof e?yield function(e){return t(this,void 0,void 0,(function*(){throw new Error("Interacting with the file system is not supported in this environment.")}))}():e;return(yield this.fetchJson("/v2/upload",{method:"POST",body:s,headers:{"Content-Type":"application/octet-stream"},duplex:"half"})).upload_url}))}}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 m(e),this.transcripts=new p(e,this.files),this.lemur=new i(e),this.realtime=new u(e)}},e.FileService=m,e.LemurService=i,e.RealtimeService=class extends h{},e.RealtimeServiceFactory=class extends u{},e.RealtimeTranscriber=h,e.RealtimeTranscriberFactory=u,e.TranscriptService=p})); |
@@ -9,2 +9,3 @@ import { RealtimeTranscriberParams, RealtimeTranscript, PartialTranscript, FinalTranscript, SessionBeginsEventData, AudioData } from "../.."; | ||
private token?; | ||
private end_utterance_silence_threshold?; | ||
private socket?; | ||
@@ -24,2 +25,13 @@ private listeners; | ||
stream(): WritableStream<AudioData>; | ||
/** | ||
* Manually end an utterance | ||
*/ | ||
forceEndUtterance(): void; | ||
/** | ||
* Configure the threshold for how long to wait before ending an utterance. Default is 700ms. | ||
* @param threshold The duration of the end utterance silence threshold in milliseconds | ||
* @format integer | ||
*/ | ||
configureEndUtteranceSilenceThreshold(threshold: number): void; | ||
private send; | ||
close(waitForSessionTermination?: boolean): Promise<void>; | ||
@@ -26,0 +38,0 @@ } |
@@ -12,2 +12,7 @@ /** | ||
export type AudioEncoding = "pcm_s16le" | "pcm_mulaw"; | ||
/** @description Configure the threshold for how long to wait before ending an utterance. Default is 700ms. */ | ||
export type ConfigureEndUtteranceSilenceThreshold = { | ||
/** @description The duration threshold in milliseconds */ | ||
end_utterance_silence_threshold: number; | ||
}; | ||
export type FinalTranscript = RealtimeBaseTranscript & { | ||
@@ -24,2 +29,7 @@ /** | ||
}; | ||
/** @description Manually end an utterance */ | ||
export type ForceEndUtterance = { | ||
/** @description A boolean value to communicate that you wish to force the end of the utterance */ | ||
force_end_utterance: boolean; | ||
}; | ||
/** @enum {string} */ | ||
@@ -26,0 +36,0 @@ export type MessageType = "SessionBegins" | "PartialTranscript" | "FinalTranscript" | "SessionTerminated"; |
import { AudioEncoding, FinalTranscript, PartialTranscript, RealtimeTranscript, RealtimeTranscriptType } from "../asyncapi.generated"; | ||
type CreateRealtimeTranscriberParams = { | ||
/** | ||
* The WebSocket URL that the RealtimeTranscriber connects to | ||
*/ | ||
realtimeUrl?: string; | ||
/** | ||
* The sample rate of the streamed audio | ||
*/ | ||
sampleRate?: number; | ||
/** | ||
* Add up to 2500 characters of custom vocabulary | ||
*/ | ||
wordBoost?: string[]; | ||
/** | ||
* The encoding of the audio data | ||
*/ | ||
encoding?: AudioEncoding; | ||
/** | ||
* The duration of the end utterance silence threshold in milliseconds | ||
*/ | ||
end_utterance_silence_threshold?: number; | ||
} & ({ | ||
/** | ||
* The API key used to authenticate the RealtimeTranscriber | ||
* Using an API key to authenticate the RealtimeTranscriber is not supported in the browser. | ||
*/ | ||
apiKey?: string; | ||
} | { | ||
/** | ||
* The temporary token used to authenticate the RealtimeTranscriber | ||
*/ | ||
token: string; | ||
@@ -17,9 +40,32 @@ }); | ||
type RealtimeTranscriberParams = { | ||
/** | ||
* The WebSocket URL that the RealtimeTranscriber connects to | ||
*/ | ||
realtimeUrl?: string; | ||
/** | ||
* The sample rate of the streamed audio | ||
*/ | ||
sampleRate?: number; | ||
/** | ||
* Add up to 2500 characters of custom vocabulary | ||
*/ | ||
wordBoost?: string[]; | ||
/** | ||
* The encoding of the audio data | ||
*/ | ||
encoding?: AudioEncoding; | ||
/** | ||
* The duration of the end utterance silence threshold in milliseconds | ||
*/ | ||
end_utterance_silence_threshold?: number; | ||
} & ({ | ||
/** | ||
* The API key used to authenticate the RealtimeTranscriber. | ||
* Using an API key to authenticate the RealtimeTranscriber is not supported in the browser. | ||
*/ | ||
apiKey: string; | ||
} | { | ||
/** | ||
* The temporary token used to authenticate the RealtimeTranscriber | ||
*/ | ||
token: string; | ||
@@ -26,0 +72,0 @@ }); |
{ | ||
"name": "assemblyai", | ||
"version": "4.2.3", | ||
"version": "4.3.0", | ||
"description": "The AssemblyAI JavaScript SDK provides an easy-to-use interface for interacting with the AssemblyAI API, which supports async and real-time transcription, as well as the latest LeMUR models.", | ||
@@ -5,0 +5,0 @@ "engines": { |
@@ -23,3 +23,23 @@ import { WritableStream } from "#streams"; | ||
const defaultRealtimeUrl = "wss://api.assemblyai.com/v2/realtime/ws"; | ||
const forceEndOfUtteranceMessage = `{"force_end_utterance":true}`; | ||
const terminateSessionMessage = `{"terminate_session":true}`; | ||
type BufferLike = | ||
| string | ||
| Buffer | ||
| DataView | ||
| number | ||
| ArrayBufferView | ||
| Uint8Array | ||
| ArrayBuffer | ||
| SharedArrayBuffer | ||
| ReadonlyArray<unknown> | ||
| ReadonlyArray<number> | ||
| { valueOf(): ArrayBuffer } | ||
| { valueOf(): SharedArrayBuffer } | ||
| { valueOf(): Uint8Array } | ||
| { valueOf(): ReadonlyArray<number> } | ||
| { valueOf(): string } | ||
| { [Symbol.toPrimitive](hint: string): string }; | ||
export class RealtimeTranscriber { | ||
@@ -32,2 +52,3 @@ private realtimeUrl: string; | ||
private token?: string; | ||
private end_utterance_silence_threshold?: number; | ||
private socket?: WebSocket; | ||
@@ -42,2 +63,4 @@ private listeners: RealtimeListeners = {}; | ||
this.encoding = params.encoding; | ||
this.end_utterance_silence_threshold = | ||
params.end_utterance_silence_threshold; | ||
if ("token" in params && params.token) this.token = params.token; | ||
@@ -111,2 +134,14 @@ if ("apiKey" in params && params.apiKey) this.apiKey = params.apiKey; | ||
this.socket.onopen = () => { | ||
if ( | ||
this.end_utterance_silence_threshold === undefined || | ||
this.end_utterance_silence_threshold === null | ||
) { | ||
return; | ||
} | ||
this.configureEndUtteranceSilenceThreshold( | ||
this.end_utterance_silence_threshold | ||
); | ||
}; | ||
this.socket.onclose = ({ code, reason }: CloseEvent) => { | ||
@@ -166,6 +201,3 @@ if (!reason) { | ||
sendAudio(audio: AudioData) { | ||
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) { | ||
throw new Error("Socket is not open for communication"); | ||
} | ||
this.socket.send(audio); | ||
this.send(audio); | ||
} | ||
@@ -181,6 +213,28 @@ | ||
/** | ||
* Manually end an utterance | ||
*/ | ||
forceEndUtterance() { | ||
this.send(forceEndOfUtteranceMessage); | ||
} | ||
/** | ||
* Configure the threshold for how long to wait before ending an utterance. Default is 700ms. | ||
* @param threshold The duration of the end utterance silence threshold in milliseconds | ||
* @format integer | ||
*/ | ||
configureEndUtteranceSilenceThreshold(threshold: number) { | ||
this.send(`{"end_utterance_silence_threshold":${threshold}}`); | ||
} | ||
private send(data: BufferLike) { | ||
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) { | ||
throw new Error("Socket is not open for communication"); | ||
} | ||
this.socket.send(data); | ||
} | ||
async close(waitForSessionTermination = true) { | ||
if (this.socket) { | ||
if (this.socket.readyState === WebSocket.OPEN) { | ||
const terminateSessionMessage = `{"terminate_session": true}`; | ||
if (waitForSessionTermination) { | ||
@@ -187,0 +241,0 @@ const sessionTerminatedPromise = new Promise<void>((resolve) => { |
@@ -31,2 +31,8 @@ // this file is generated by typescript/scripts/generate-types.ts | ||
/** @description Configure the threshold for how long to wait before ending an utterance. Default is 700ms. */ | ||
export type ConfigureEndUtteranceSilenceThreshold = { | ||
/** @description The duration threshold in milliseconds */ | ||
end_utterance_silence_threshold: number; | ||
}; | ||
export type FinalTranscript = RealtimeBaseTranscript & { | ||
@@ -44,2 +50,8 @@ /** | ||
/** @description Manually end an utterance */ | ||
export type ForceEndUtterance = { | ||
/** @description A boolean value to communicate that you wish to force the end of the utterance */ | ||
force_end_utterance: boolean; | ||
}; | ||
/** @enum {string} */ | ||
@@ -46,0 +58,0 @@ export type MessageType = |
@@ -10,11 +10,34 @@ import { | ||
type CreateRealtimeTranscriberParams = { | ||
/** | ||
* The WebSocket URL that the RealtimeTranscriber connects to | ||
*/ | ||
realtimeUrl?: string; | ||
/** | ||
* The sample rate of the streamed audio | ||
*/ | ||
sampleRate?: number; | ||
/** | ||
* Add up to 2500 characters of custom vocabulary | ||
*/ | ||
wordBoost?: string[]; | ||
/** | ||
* The encoding of the audio data | ||
*/ | ||
encoding?: AudioEncoding; | ||
/** | ||
* The duration of the end utterance silence threshold in milliseconds | ||
*/ | ||
end_utterance_silence_threshold?: number; | ||
} & ( | ||
| { | ||
/** | ||
* The API key used to authenticate the RealtimeTranscriber | ||
* Using an API key to authenticate the RealtimeTranscriber is not supported in the browser. | ||
*/ | ||
apiKey?: string; | ||
} | ||
| { | ||
/** | ||
* The temporary token used to authenticate the RealtimeTranscriber | ||
*/ | ||
token: string; | ||
@@ -30,11 +53,34 @@ } | ||
type RealtimeTranscriberParams = { | ||
/** | ||
* The WebSocket URL that the RealtimeTranscriber connects to | ||
*/ | ||
realtimeUrl?: string; | ||
/** | ||
* The sample rate of the streamed audio | ||
*/ | ||
sampleRate?: number; | ||
/** | ||
* Add up to 2500 characters of custom vocabulary | ||
*/ | ||
wordBoost?: string[]; | ||
/** | ||
* The encoding of the audio data | ||
*/ | ||
encoding?: AudioEncoding; | ||
/** | ||
* The duration of the end utterance silence threshold in milliseconds | ||
*/ | ||
end_utterance_silence_threshold?: number; | ||
} & ( | ||
| { | ||
/** | ||
* The API key used to authenticate the RealtimeTranscriber. | ||
* Using an API key to authenticate the RealtimeTranscriber is not supported in the browser. | ||
*/ | ||
apiKey: string; | ||
} | ||
| { | ||
/** | ||
* The temporary token used to authenticate the RealtimeTranscriber | ||
*/ | ||
token: string; | ||
@@ -41,0 +87,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
462997
11696