assemblyai
Advanced tools
Comparing version 4.5.0-beta.0 to 4.5.0
# Changelog | ||
## [4.5.0] | ||
- You can now retrieve previous LeMUR responses using `client.lemur.getResponse<LemurTask>("YOUR_REQUEST_ID")`. | ||
- LeMUR functions now return `usage` with the number of `input_tokens` and `output_tokens`. | ||
## [4.4.7] | ||
- Rename `TranscriptService.redactions` function to `TranscriptService.redactedAudio`. | ||
- Add `TranscriptService.redactedAudioFile` function. | ||
- Add `workerd` export to fix `cache` issue with `fetch` on Cloudflare Workers. | ||
## [4.4.6] | ||
- Fix Rollup exports so \_\_SDK_VERSION\_\_ is properly replaced with the version of the SDK. | ||
## [4.4.5] | ||
- Add new `PiiPolicy` enum values | ||
## [4.4.4] | ||
- Add an export that only includes the Streaming STT code. You can use the export | ||
- by importing `assemblyai/streaming`, | ||
- or by loading the `assemblyai.streaming.umd.js` file, or `assemblyai.streaming.umd.min.js` file in a script-tag. | ||
- Add new `EntityType` enum values | ||
## [4.4.3] - 2024-05-09 | ||
- Add react-native exports that resolve to the browser version of the library. | ||
## [4.4.2] - 2024-05-03 | ||
### Changed | ||
- Caching is disabled for all HTTP request made by the SDK | ||
- Accept data-URIs in `client.files.upload(dataUri)`, `client.transcripts.submit(audio: dataUri)`, `client.transcripts.transcribe(audio: dataUri)`. | ||
- Change how the WebSocket libraries are imported for better compatibility across frameworks and runtimes. | ||
@@ -6,0 +40,0 @@ The library no longer relies on a internal `#ws` import, and instead compiles the imports into the dist bundles. |
@@ -51,2 +51,41 @@ (function (global, factory) { | ||
const DEFAULT_FETCH_INIT = { | ||
cache: "no-store", | ||
}; | ||
const buildUserAgent = (userAgent) => defaultUserAgentString + | ||
(userAgent === false | ||
? "" | ||
: " AssemblyAI/1.0 (" + | ||
Object.entries(Object.assign(Object.assign({}, defaultUserAgent), userAgent)) | ||
.map(([key, item]) => item ? `${key}=${item.name}/${item.version}` : "") | ||
.join(" ") + | ||
")"); | ||
let defaultUserAgentString = ""; | ||
if (typeof navigator !== "undefined" && navigator.userAgent) { | ||
defaultUserAgentString += navigator.userAgent; | ||
} | ||
const defaultUserAgent = { | ||
sdk: { name: "JavaScript", version: "4.5.0" }, | ||
}; | ||
if (typeof process !== "undefined") { | ||
if (process.versions.node && defaultUserAgentString.indexOf("Node") === -1) { | ||
defaultUserAgent.runtime_env = { | ||
name: "Node", | ||
version: process.versions.node, | ||
}; | ||
} | ||
if (process.versions.bun && defaultUserAgentString.indexOf("Bun") === -1) { | ||
defaultUserAgent.runtime_env = { | ||
name: "Bun", | ||
version: process.versions.bun, | ||
}; | ||
} | ||
} | ||
if (typeof Deno !== "undefined") { | ||
if (process.versions.bun && defaultUserAgentString.indexOf("Deno") === -1) { | ||
defaultUserAgent.runtime_env = { name: "Deno", version: Deno.version.deno }; | ||
} | ||
} | ||
/** | ||
@@ -62,9 +101,29 @@ * Base class for services that communicate with the API. | ||
this.params = params; | ||
if (params.userAgent === false) { | ||
this.userAgent = undefined; | ||
} | ||
else { | ||
this.userAgent = buildUserAgent(params.userAgent || {}); | ||
} | ||
} | ||
fetch(input, init) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
var _a; | ||
init = init !== null && init !== void 0 ? init : {}; | ||
init.headers = (_a = init.headers) !== null && _a !== void 0 ? _a : {}; | ||
init.headers = Object.assign({ Authorization: this.params.apiKey, "Content-Type": "application/json" }, init.headers); | ||
init = Object.assign(Object.assign({}, DEFAULT_FETCH_INIT), init); | ||
let headers = { | ||
Authorization: this.params.apiKey, | ||
"Content-Type": "application/json", | ||
}; | ||
if (DEFAULT_FETCH_INIT === null || DEFAULT_FETCH_INIT === void 0 ? void 0 : DEFAULT_FETCH_INIT.headers) | ||
headers = Object.assign(Object.assign({}, headers), DEFAULT_FETCH_INIT.headers); | ||
if (init === null || init === void 0 ? void 0 : init.headers) | ||
headers = Object.assign(Object.assign({}, headers), init.headers); | ||
if (this.userAgent) { | ||
headers["User-Agent"] = this.userAgent; | ||
// chromium browsers have a bug where the user agent can't be modified | ||
if (typeof window !== "undefined" && "chrome" in window) { | ||
headers["AssemblyAI-Agent"] = | ||
this.userAgent; | ||
} | ||
} | ||
init.headers = headers; | ||
if (!input.startsWith("http")) | ||
@@ -80,3 +139,3 @@ input = this.params.baseUrl + input; | ||
} | ||
catch (_b) { | ||
catch (_a) { | ||
/* empty */ | ||
@@ -126,2 +185,5 @@ } | ||
} | ||
getResponse(id) { | ||
return this.fetchJson(`/lemur/v3/${id}`); | ||
} | ||
/** | ||
@@ -423,2 +485,4 @@ * Delete the data for a previously submitted LeMUR request. | ||
return null; | ||
if (path.startsWith("data:")) | ||
return null; | ||
if (path.startsWith("file://")) | ||
@@ -468,4 +532,9 @@ return path.substring(7); | ||
else { | ||
// audio is not a local path, assume it's a URL | ||
audioUrl = audio; | ||
if (audio.startsWith("data:")) { | ||
audioUrl = yield this.files.upload(audio); | ||
} | ||
else { | ||
// audio is not a local path, and not a data-URI, assume it's a normal URL | ||
audioUrl = audio; | ||
} | ||
} | ||
@@ -635,9 +704,41 @@ } | ||
/** | ||
* Retrieve redactions of a transcript. | ||
* Retrieve the redacted audio URL of a transcript. | ||
* @param id - The identifier of the transcript. | ||
* @returns A promise that resolves to the subtitles text. | ||
* @returns A promise that resolves to the details of the redacted audio. | ||
* @deprecated Use `redactedAudio` instead. | ||
*/ | ||
redactions(id) { | ||
return this.redactedAudio(id); | ||
} | ||
/** | ||
* Retrieve the redacted audio URL of a transcript. | ||
* @param id - The identifier of the transcript. | ||
* @returns A promise that resolves to the details of the redacted audio. | ||
*/ | ||
redactedAudio(id) { | ||
return this.fetchJson(`/v2/transcript/${id}/redacted-audio`); | ||
} | ||
/** | ||
* Retrieve the redacted audio file of a transcript. | ||
* @param id - The identifier of the transcript. | ||
* @returns A promise that resolves to the fetch HTTP response of the redacted audio file. | ||
*/ | ||
redactedAudioFile(id) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const { redacted_audio_url, status } = yield this.redactedAudio(id); | ||
if (status !== "redacted_audio_ready") { | ||
throw new Error(`Redacted audio status is ${status}`); | ||
} | ||
const response = yield fetch(redacted_audio_url); | ||
if (!response.ok) { | ||
throw new Error(`Failed to fetch redacted audio: ${response.statusText}`); | ||
} | ||
return { | ||
arrayBuffer: response.arrayBuffer.bind(response), | ||
blob: response.blob.bind(response), | ||
body: response.body, | ||
bodyUsed: response.bodyUsed, | ||
}; | ||
}); | ||
} | ||
} | ||
@@ -669,4 +770,10 @@ function deprecateConformer2(params) { | ||
let fileData; | ||
if (typeof input === "string") | ||
fileData = yield readFile(); | ||
if (typeof input === "string") { | ||
if (input.startsWith("data:")) { | ||
fileData = dataUrlToBlob(input); | ||
} | ||
else { | ||
fileData = yield readFile(); | ||
} | ||
} | ||
else | ||
@@ -686,2 +793,13 @@ fileData = input; | ||
} | ||
function dataUrlToBlob(dataUrl) { | ||
const arr = dataUrl.split(","); | ||
const mime = arr[0].match(/:(.*?);/)[1]; | ||
const bstr = atob(arr[1]); | ||
let n = bstr.length; | ||
const u8arr = new Uint8Array(n); | ||
while (n--) { | ||
u8arr[n] = bstr.charCodeAt(n); | ||
} | ||
return new Blob([u8arr], { type: mime }); | ||
} | ||
@@ -696,4 +814,5 @@ const defaultBaseUrl = "https://api.assemblyai.com"; | ||
params.baseUrl = params.baseUrl || defaultBaseUrl; | ||
if (params.baseUrl && params.baseUrl.endsWith("/")) | ||
if (params.baseUrl && params.baseUrl.endsWith("/")) { | ||
params.baseUrl = params.baseUrl.slice(0, -1); | ||
} | ||
this.files = new FileService(params); | ||
@@ -700,0 +819,0 @@ this.transcripts = new TranscriptService(params, this.files); |
@@ -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(n,o){function r(e){try{l(i.next(e))}catch(e){o(e)}}function a(e){try{l(i.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?n(e.value):(t=e.value,t instanceof s?t:new s((function(e){e(t)}))).then(r,a)}l((i=i.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class s{constructor(e){this.params=e}fetch(e,s){return t(this,void 0,void 0,(function*(){var t;(s=null!=s?s:{}).headers=null!==(t=s.headers)&&void 0!==t?t:{},s.headers=Object.assign({Authorization:this.params.apiKey,"Content-Type":"application/json"},s.headers),e.startsWith("http")||(e=this.params.baseUrl+e);const i=yield fetch(e,s);if(i.status>=400){let e;const t=yield i.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: ${i.status} ${i.statusText}`)}return i}))}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,r;const a=null!==(r=null!==(o=null!==WebSocket&&void 0!==WebSocket?WebSocket:null===global||void 0===global?void 0:global.WebSocket)&&void 0!==o?o:null===window||void 0===window?void 0:window.WebSocket)&&void 0!==r?r:null===self||void 0===self?void 0:self.WebSocket,l=(e,t)=>t?new a(e,t):new a(e);var c;!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"}(c||(c={}));const d={[c.BadSampleRate]:"Sample rate must be a positive integer",[c.AuthFailed]:"Not Authorized",[c.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.",[c.NonexistentSessionId]:"Session ID does not exist",[c.SessionExpired]:"Session has expired",[c.ClosedSession]:"Session is closed",[c.RateLimited]:"Rate limited",[c.UniqueSessionViolation]:"Unique session violation",[c.SessionTimeout]:"Session Timeout",[c.AudioTooShort]:"Audio too short",[c.AudioTooLong]:"Audio too long",[c.BadJson]:"Bad JSON",[c.BadSchema]:"Bad schema",[c.TooManyStreams]:"Too many streams",[c.Reconnected]:"Reconnected",[c.ReconnectAttemptsExhausted]:"Reconnect attempts exhausted"};class h extends Error{}const u='{"terminate_session":true}';class p{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=l(t.toString()):this.socket=l(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,i;t||e in c&&(t=d[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,l,c,d,u,p,f,m,v,y;const S=JSON.parse(t.toString());if("error"in S)null===(i=(s=this.listeners).error)||void 0===i||i.call(s,new h(S.error));else switch(S.message_type){case"SessionBegins":{const t={sessionId:S.session_id,expiresAt:new Date(S.expires_at)};e(t),null===(o=(n=this.listeners).open)||void 0===o||o.call(n,t);break}case"PartialTranscript":S.created=new Date(S.created),null===(a=(r=this.listeners).transcript)||void 0===a||a.call(r,S),null===(c=(l=this.listeners)["transcript.partial"])||void 0===c||c.call(l,S);break;case"FinalTranscript":S.created=new Date(S.created),null===(u=(d=this.listeners).transcript)||void 0===u||u.call(d,S),null===(f=(p=this.listeners)["transcript.final"])||void 0===f||f.call(p,S);break;case"SessionInformation":null===(v=(m=this.listeners).session_information)||void 0===v||v.call(m,S);break;case"SessionTerminated":null===(y=this.sessionTerminatedResolve)||void 0===y||y.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 t(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(u),yield e}else this.socket.send(u);(null===(t=this.socket)||void 0===t?void 0:t.removeAllListeners)&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}class f 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 p(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 m(e){return e.startsWith("http")||e.startsWith("https")?null:e.startsWith("file://")?e.substring(7):e.startsWith("file:")?e.substring(5):e}class v extends s{constructor(e,t){super(e),this.files=t}transcribe(e,s){return t(this,void 0,void 0,(function*(){y(e);const t=yield this.submit(e);return yield this.waitUntilReady(t.id,s)}))}submit(e){return t(this,void 0,void 0,(function*(){let t,s;if(y(e),"audio"in e){const{audio:i}=e,n=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"]);if("string"==typeof i){const e=m(i);t=null!==e?yield this.files.upload(e):i}else t=yield this.files.upload(i);s=Object.assign(Object.assign({},n),{audio_url:t})}else s=e;return yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(s)})}))}create(e,s){return t(this,void 0,void 0,(function*(){var t;y(e);const i=m(e.audio_url);if(null!==i){const t=yield this.files.upload(i);e.audio_url=t}const n=yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(e)});return null===(t=null==s?void 0:s.poll)||void 0===t||t?yield this.waitUntilReady(n.id,s):n}))}waitUntilReady(e,s){return t(this,void 0,void 0,(function*(){var t,i;const n=null!==(t=null==s?void 0:s.pollingInterval)&&void 0!==t?t:3e3,o=null!==(i=null==s?void 0:s.pollingTimeout)&&void 0!==i?i:-1,r=Date.now();for(;;){const t=yield this.get(e);if("completed"===t.status||"error"===t.status)return t;if(o>0&&Date.now()-r>o)throw new Error("Polling timeout");yield new Promise((e=>setTimeout(e,n)))}}))}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){return t(this,arguments,void 0,(function*(e,t="srt",s){let i=`/v2/transcript/${e}/${t}`;if(s){const e=new URLSearchParams;e.set("chars_per_caption",s.toString()),i+=`?${e.toString()}`}const n=yield this.fetch(i);return yield n.text()}))}redactions(e){return this.fetchJson(`/v2/transcript/${e}/redacted-audio`)}}function y(e){e&&"conformer-2"===e.speech_model&&console.warn("The speech_model conformer-2 option is deprecated and will stop working in the near future. Use best or nano instead.")}class S 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 S(e),this.transcripts=new v(e,this.files),this.lemur=new i(e),this.realtime=new f(e)}},e.FileService=S,e.LemurService=i,e.RealtimeService=class extends p{},e.RealtimeServiceFactory=class extends f{},e.RealtimeTranscriber=p,e.RealtimeTranscriberFactory=f,e.TranscriptService=v})); | ||
!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;const s={cache:"no-store"};let i="";"undefined"!=typeof navigator&&navigator.userAgent&&(i+=navigator.userAgent);const n={sdk:{name:"JavaScript",version:"4.5.0"}};"undefined"!=typeof process&&(process.versions.node&&-1===i.indexOf("Node")&&(n.runtime_env={name:"Node",version:process.versions.node}),process.versions.bun&&-1===i.indexOf("Bun")&&(n.runtime_env={name:"Bun",version:process.versions.bun})),"undefined"!=typeof Deno&&process.versions.bun&&-1===i.indexOf("Deno")&&(n.runtime_env={name:"Deno",version:Deno.version.deno});class o{constructor(e){var t;this.params=e,!1===e.userAgent?this.userAgent=void 0:this.userAgent=(t=e.userAgent||{},i+(!1===t?"":" AssemblyAI/1.0 ("+Object.entries(Object.assign(Object.assign({},n),t)).map((([e,t])=>t?`${e}=${t.name}/${t.version}`:"")).join(" ")+")"))}fetch(e,i){return t(this,void 0,void 0,(function*(){i=Object.assign(Object.assign({},s),i);let t={Authorization:this.params.apiKey,"Content-Type":"application/json"};(null==s?void 0:s.headers)&&(t=Object.assign(Object.assign({},t),s.headers)),(null==i?void 0:i.headers)&&(t=Object.assign(Object.assign({},t),i.headers)),this.userAgent&&(t["User-Agent"]=this.userAgent,"undefined"!=typeof window&&"chrome"in window&&(t["AssemblyAI-Agent"]=this.userAgent)),i.headers=t,e.startsWith("http")||(e=this.params.baseUrl+e);const n=yield fetch(e,i);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,s){return t(this,void 0,void 0,(function*(){return(yield this.fetch(e,s)).json()}))}}class r extends o{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)})}getResponse(e){return this.fetchJson(`/lemur/v3/${e}`)}purgeRequestData(e){return this.fetchJson(`/lemur/v3/${e}`,{method:"DELETE"})}}const{WritableStream:a}="undefined"!=typeof window?window:"undefined"!=typeof global?global:globalThis;var c,d;const l=null!==(d=null!==(c=null!==WebSocket&&void 0!==WebSocket?WebSocket:null===global||void 0===global?void 0:global.WebSocket)&&void 0!==c?c:null===window||void 0===window?void 0:window.WebSocket)&&void 0!==d?d:null===self||void 0===self?void 0:self.WebSocket,u=(e,t)=>t?new l(e,t):new l(e);var h;!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"}(h||(h={}));const f={[h.BadSampleRate]:"Sample rate must be a positive integer",[h.AuthFailed]:"Not Authorized",[h.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.",[h.NonexistentSessionId]:"Session ID does not exist",[h.SessionExpired]:"Session has expired",[h.ClosedSession]:"Session is closed",[h.RateLimited]:"Rate limited",[h.UniqueSessionViolation]:"Unique session violation",[h.SessionTimeout]:"Session Timeout",[h.AudioTooShort]:"Audio too short",[h.AudioTooLong]:"Audio too long",[h.BadJson]:"Bad JSON",[h.BadSchema]:"Bad schema",[h.TooManyStreams]:"Too many streams",[h.Reconnected]:"Reconnected",[h.ReconnectAttemptsExhausted]:"Reconnect attempts exhausted"};class p extends Error{}const m='{"terminate_session":true}';class v{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=u(t.toString()):this.socket=u(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,i;t||e in h&&(t=f[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,l,u,h,f,m,v,y;const b=JSON.parse(t.toString());if("error"in b)null===(i=(s=this.listeners).error)||void 0===i||i.call(s,new p(b.error));else switch(b.message_type){case"SessionBegins":{const t={sessionId:b.session_id,expiresAt:new Date(b.expires_at)};e(t),null===(o=(n=this.listeners).open)||void 0===o||o.call(n,t);break}case"PartialTranscript":b.created=new Date(b.created),null===(a=(r=this.listeners).transcript)||void 0===a||a.call(r,b),null===(d=(c=this.listeners)["transcript.partial"])||void 0===d||d.call(c,b);break;case"FinalTranscript":b.created=new Date(b.created),null===(u=(l=this.listeners).transcript)||void 0===u||u.call(l,b),null===(f=(h=this.listeners)["transcript.final"])||void 0===f||f.call(h,b);break;case"SessionInformation":null===(v=(m=this.listeners).session_information)||void 0===v||v.call(m,b);break;case"SessionTerminated":null===(y=this.sessionTerminatedResolve)||void 0===y||y.call(this)}}}))}sendAudio(e){this.send(e)}stream(){return new a({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 t(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(m),yield e}else this.socket.send(m);(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 extends o{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 v(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 b(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}class S extends o{constructor(e,t){super(e),this.files=t}transcribe(e,s){return t(this,void 0,void 0,(function*(){g(e);const t=yield this.submit(e);return yield this.waitUntilReady(t.id,s)}))}submit(e){return t(this,void 0,void 0,(function*(){let t,s;if(g(e),"audio"in e){const{audio:i}=e,n=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"]);if("string"==typeof i){const e=b(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);s=Object.assign(Object.assign({},n),{audio_url:t})}else s=e;return yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(s)})}))}create(e,s){return t(this,void 0,void 0,(function*(){var t;g(e);const i=b(e.audio_url);if(null!==i){const t=yield this.files.upload(i);e.audio_url=t}const n=yield this.fetchJson("/v2/transcript",{method:"POST",body:JSON.stringify(e)});return null===(t=null==s?void 0:s.poll)||void 0===t||t?yield this.waitUntilReady(n.id,s):n}))}waitUntilReady(e,s){return t(this,void 0,void 0,(function*(){var t,i;const n=null!==(t=null==s?void 0:s.pollingInterval)&&void 0!==t?t:3e3,o=null!==(i=null==s?void 0:s.pollingTimeout)&&void 0!==i?i:-1,r=Date.now();for(;;){const t=yield this.get(e);if("completed"===t.status||"error"===t.status)return t;if(o>0&&Date.now()-r>o)throw new Error("Polling timeout");yield new Promise((e=>setTimeout(e,n)))}}))}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){return t(this,arguments,void 0,(function*(e,t="srt",s){let i=`/v2/transcript/${e}/${t}`;if(s){const e=new URLSearchParams;e.set("chars_per_caption",s.toString()),i+=`?${e.toString()}`}const n=yield this.fetch(i);return yield n.text()}))}redactions(e){return this.redactedAudio(e)}redactedAudio(e){return this.fetchJson(`/v2/transcript/${e}/redacted-audio`)}redactedAudioFile(e){return t(this,void 0,void 0,(function*(){const{redacted_audio_url:t,status:s}=yield this.redactedAudio(e);if("redacted_audio_ready"!==s)throw new Error(`Redacted audio status is ${s}`);const i=yield fetch(t);if(!i.ok)throw new Error(`Failed to fetch redacted audio: ${i.statusText}`);return{arrayBuffer:i.arrayBuffer.bind(i),blob:i.blob.bind(i),body:i.body,bodyUsed:i.bodyUsed}}))}}function g(e){e&&"conformer-2"===e.speech_model&&console.warn("The speech_model conformer-2 option is deprecated and will stop working in the near future. Use best or nano instead.")}class w extends o{upload(e){return t(this,void 0,void 0,(function*(){let s;s="string"==typeof e?e.startsWith("data:")?function(e){const t=e.split(","),s=t[0].match(/:(.*?);/)[1],i=atob(t[1]);let n=i.length;const o=new Uint8Array(n);for(;n--;)o[n]=i.charCodeAt(n);return new Blob([o],{type:s})}(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 w(e),this.transcripts=new S(e,this.files),this.lemur=new r(e),this.realtime=new y(e)}},e.FileService=w,e.LemurService=r,e.RealtimeService=class extends v{},e.RealtimeServiceFactory=class extends y{},e.RealtimeTranscriber=v,e.RealtimeTranscriberFactory=y,e.TranscriptService=S})); |
@@ -7,2 +7,3 @@ import { BaseServiceParams } from ".."; | ||
private params; | ||
private userAgent; | ||
/** | ||
@@ -9,0 +10,0 @@ * Create a new service. |
@@ -1,2 +0,2 @@ | ||
import { LemurSummaryParams, LemurActionItemsParams, LemurQuestionAnswerParams, LemurTaskParams, LemurSummaryResponse, LemurQuestionAnswerResponse, LemurActionItemsResponse, LemurTaskResponse, PurgeLemurRequestDataResponse } from "../.."; | ||
import { LemurSummaryParams, LemurActionItemsParams, LemurQuestionAnswerParams, LemurTaskParams, LemurSummaryResponse, LemurQuestionAnswerResponse, LemurActionItemsResponse, LemurTaskResponse, PurgeLemurRequestDataResponse, LemurResponse } from "../.."; | ||
import { BaseService } from "../base"; | ||
@@ -9,2 +9,9 @@ export declare class LemurService extends BaseService { | ||
/** | ||
* Retrieve a LeMUR response that was previously generated. | ||
* @param id - The ID of the LeMUR request you previously made. This would be found in the response of the original request. | ||
* @returns The LeMUR response. | ||
*/ | ||
getResponse<T extends LemurResponse>(id: string): Promise<T>; | ||
getResponse(id: string): Promise<LemurResponse>; | ||
/** | ||
* Delete the data for a previously submitted LeMUR request. | ||
@@ -11,0 +18,0 @@ * @param id - ID of the LeMUR request |
import { BaseService } from "../base"; | ||
import { ParagraphsResponse, SentencesResponse, Transcript, TranscriptList, TranscriptParams, CreateTranscriptOptions, SubtitleFormat, RedactedAudioResponse, ListTranscriptParams, WordSearchResponse, BaseServiceParams, PollingOptions, TranscribeParams, TranscribeOptions, SubmitParams } from "../.."; | ||
import { ParagraphsResponse, SentencesResponse, Transcript, TranscriptList, TranscriptParams, CreateTranscriptOptions, SubtitleFormat, RedactedAudioResponse, ListTranscriptParams, WordSearchResponse, BaseServiceParams, PollingOptions, TranscribeParams, TranscribeOptions, SubmitParams, RedactedAudioFile } from "../.."; | ||
import { FileService } from "../files"; | ||
@@ -81,7 +81,20 @@ export declare class TranscriptService extends BaseService { | ||
/** | ||
* Retrieve redactions of a transcript. | ||
* Retrieve the redacted audio URL of a transcript. | ||
* @param id - The identifier of the transcript. | ||
* @returns A promise that resolves to the subtitles text. | ||
* @returns A promise that resolves to the details of the redacted audio. | ||
* @deprecated Use `redactedAudio` instead. | ||
*/ | ||
redactions(id: string): Promise<RedactedAudioResponse>; | ||
/** | ||
* Retrieve the redacted audio URL of a transcript. | ||
* @param id - The identifier of the transcript. | ||
* @returns A promise that resolves to the details of the redacted audio. | ||
*/ | ||
redactedAudio(id: string): Promise<RedactedAudioResponse>; | ||
/** | ||
* Retrieve the redacted audio file of a transcript. | ||
* @param id - The identifier of the transcript. | ||
* @returns A promise that resolves to the fetch HTTP response of the redacted audio file. | ||
*/ | ||
redactedAudioFile(id: string): Promise<RedactedAudioFile>; | ||
} |
@@ -8,1 +8,8 @@ export * from "./files"; | ||
export * from "./deprecated"; | ||
export type UserAgentItem = { | ||
name: string; | ||
version: string; | ||
}; | ||
export type UserAgent = { | ||
[component: string]: UserAgentItem | undefined | null | false; | ||
}; |
@@ -0,5 +1,12 @@ | ||
import { UserAgent } from ".."; | ||
type BaseServiceParams = { | ||
apiKey: string; | ||
baseUrl?: string; | ||
/** | ||
* The AssemblyAI user agent to use for requests. | ||
* The provided components will be merged into the default AssemblyAI user agent. | ||
* If `false`, the AssemblyAI user agent will be removed. | ||
*/ | ||
userAgent?: UserAgent | false; | ||
}; | ||
export type { BaseServiceParams }; |
@@ -49,1 +49,10 @@ import { FileUploadParams } from "../files"; | ||
export type TranscribeOptions = PollingOptions; | ||
/** | ||
* The PII redacted audio file, transmitted over the network. | ||
*/ | ||
export type RedactedAudioFile = { | ||
arrayBuffer: () => Promise<ArrayBuffer>; | ||
blob: () => Promise<Blob>; | ||
body: ReadableStream<Uint8Array> | null; | ||
bodyUsed: boolean; | ||
}; |
{ | ||
"name": "assemblyai", | ||
"version": "4.5.0-beta.0", | ||
"version": "4.5.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.", | ||
@@ -10,15 +10,16 @@ "engines": { | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"types": "./dist/exports/index.d.ts", | ||
"bun": { | ||
"types": "./dist/index.d.ts", | ||
"types": "./dist/exports/index.d.ts", | ||
"default": "./dist/bun.mjs" | ||
}, | ||
"deno": { | ||
"types": "./dist/index.d.ts", | ||
"types": "./dist/exports/index.d.ts", | ||
"default": "./dist/deno.mjs" | ||
}, | ||
"workerd": "./dist/index.mjs", | ||
"workerd": "./dist/workerd.mjs", | ||
"browser": "./dist/browser.mjs", | ||
"react-native": "./dist/browser.mjs", | ||
"node": { | ||
"types": "./dist/index.d.ts", | ||
"types": "./dist/exports/index.d.ts", | ||
"import": "./dist/node.mjs", | ||
@@ -31,5 +32,16 @@ "require": "./dist/node.cjs" | ||
}, | ||
"./streaming": { | ||
"types": "./dist/exports/streaming.d.ts", | ||
"browser": "./dist/streaming.browser.mjs", | ||
"import": "./dist/streaming.mjs", | ||
"require": "./dist/streaming.cjs", | ||
"default": "./dist/streaming.cjs" | ||
}, | ||
"./package.json": "./package.json" | ||
}, | ||
"imports": { | ||
"#fetch": { | ||
"workerd": "./src/polyfills/fetch/workerd.ts", | ||
"default": "./src/polyfills/fetch/default.ts" | ||
}, | ||
"#fs": { | ||
@@ -52,2 +64,4 @@ "node": "./src/polyfills/fs/node.ts", | ||
"type": "commonjs", | ||
"react-native": "./dist/browser.mjs", | ||
"browser": "./dist/browser.mjs", | ||
"main": "./dist/index.cjs", | ||
@@ -63,3 +77,3 @@ "require": "./dist/index.cjs", | ||
"publishConfig": { | ||
"tag": "beta", | ||
"tag": "latest", | ||
"access": "public", | ||
@@ -71,7 +85,11 @@ "registry": "https://registry.npmjs.org/" | ||
"clean": "rimraf dist/* && rimraf temp/* && rimraf temp-docs/*", | ||
"lint": "eslint -c .eslintrc.json '{src,tests}/**/*.{js,ts}' && publint && tsc --noEmit -p tsconfig.json", | ||
"test": "pnpm run test:unit && pnpm run test:integration", | ||
"lint": "pnpm lint:eslint && pnpm lint:tsc && pnpm lint:format && pnpm lint:publint", | ||
"lint:eslint": "eslint -c .eslintrc.json '{src,tests}/**/*.{js,ts}'", | ||
"lint:tsc": "tsc --noEmit -p tsconfig.json", | ||
"lint:format": "prettier --check --no-error-on-unmatched-pattern {*,**/*}", | ||
"lint:publint": "publint", | ||
"test": "pnpm test:unit && pnpm test:integration", | ||
"test:unit": "jest --config jest.unit.config.js --testTimeout 1000", | ||
"test:integration": "jest --config jest.integration.config.js --testTimeout 360000", | ||
"format": "prettier '**/*' --write", | ||
"format": "prettier --write --no-error-on-unmatched-pattern {*,**/*}", | ||
"generate:types": "tsx ./scripts/generate-types.ts && prettier 'src/types/*.generated.ts' --write", | ||
@@ -105,12 +123,13 @@ "generate:reference": "typedoc", | ||
"devDependencies": { | ||
"@babel/preset-env": "^7.24.0", | ||
"@babel/preset-typescript": "^7.23.3", | ||
"@babel/preset-env": "^7.24.5", | ||
"@babel/preset-typescript": "^7.24.1", | ||
"@rollup/plugin-node-resolve": "^15.2.3", | ||
"@rollup/plugin-replace": "^5.0.5", | ||
"@rollup/plugin-terser": "^0.4.4", | ||
"@rollup/plugin-typescript": "^11.1.6", | ||
"@types/jest": "^29.5.12", | ||
"@types/node": "^18.11.9", | ||
"@types/node": "^18.19.32", | ||
"@types/websocket": "^1.0.10", | ||
"@types/ws": "^8.5.10", | ||
"@typescript-eslint/eslint-plugin": "^7.2.0", | ||
"@typescript-eslint/eslint-plugin": "^7.8.0", | ||
"dotenv": "^16.4.5", | ||
@@ -124,2 +143,3 @@ "eslint": "^8.57.0", | ||
"jest-websocket-mock": "^2.5.0", | ||
"jsr": "^0.12.4", | ||
"mock-socket": "^9.3.1", | ||
@@ -130,12 +150,12 @@ "openapi-typescript": "^6.7.5", | ||
"rimraf": "^5.0.5", | ||
"rollup": "^4.13.0", | ||
"rollup": "^4.17.2", | ||
"ts-jest": "^29.1.2", | ||
"tslib": "^2.5.3", | ||
"typescript": "^5.4.2", | ||
"typedoc": "^0.25.12", | ||
"typedoc-plugin-extras": "^3.0.0" | ||
"typedoc": "^0.25.13", | ||
"typedoc-plugin-extras": "^3.0.0", | ||
"typescript": "^5.4.5" | ||
}, | ||
"dependencies": { | ||
"ws": "^8.16.0" | ||
"ws": "^8.17.0" | ||
} | ||
} |
@@ -56,2 +56,34 @@ <img src="https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/assemblyai.png?raw=true" width="500"/> | ||
### Using a CDN | ||
You can use automatic CDNs like [UNPKG](https://unpkg.com/) to load the library from a script tag. | ||
- Replace `:version` with the desired version or `latest`. | ||
- Remove `.min` to load the non-minified version. | ||
- Remove `.streaming` to load the entire SDK. Keep `.streaming` to load the Streaming STT specific version. | ||
```html | ||
<!-- Unminified full SDK --> | ||
<script src="https://www.unpkg.com/assemblyai@:version/dist/assemblyai.umd.js"></script> | ||
<!-- Minified full SDK --> | ||
<script src="https://www.unpkg.com/assemblyai@:version/dist/assemblyai.umd.min.js"></script> | ||
<!-- Unminified Streaming STT only --> | ||
<script src="https://www.unpkg.com/assemblyai@:version/dist/assemblyai.streaming.umd.js"></script> | ||
<!-- Minified Streaming STT only --> | ||
<script src="https://www.unpkg.com/assemblyai@:version/dist/assemblyai.streaming.umd.min.js"></script> | ||
``` | ||
The script creates a global `assemblyai` variable containing all the services. | ||
Here's how you create a `RealtimeTranscriber` object. | ||
```js | ||
const { RealtimeTranscriber } = assemblyai; | ||
const transcriber = new RealtimeTranscriber({ | ||
token: "[GENERATE TEMPORARY AUTH TOKEN IN YOUR API]", | ||
... | ||
}); | ||
``` | ||
For type support in your IDE, see [Reference types from JavaScript](./docs/reference-types-from-js.md). | ||
## Speech-To-Text | ||
@@ -231,14 +263,22 @@ | ||
You can also generate a temporary auth token for real-time. | ||
```typescript | ||
const token = await client.realtime.createTemporaryToken({ expires_in = 60 }); | ||
const rt = client.realtime.transcriber({ | ||
token: token, | ||
}); | ||
``` | ||
> [!WARNING] | ||
> Storing your API key in client-facing applications exposes your API key. | ||
> Generate a temporary auth token on the server and pass it to your client. | ||
> _Server code_: | ||
> | ||
> ```typescript | ||
> const token = await client.realtime.createTemporaryToken({ expires_in = 60 }); | ||
> // TODO: return token to client | ||
> ``` | ||
> | ||
> _Client code_: | ||
> | ||
> ```typescript | ||
> import { RealtimeTranscriber } from "assemblyai"; // or "assemblyai/streaming" | ||
> // TODO: implement getToken to retrieve token from server | ||
> const token = await getToken(); | ||
> const rt = new RealtimeTranscriber({ | ||
> token, | ||
> }); | ||
> ``` | ||
@@ -349,1 +389,5 @@ You can configure the following events. | ||
</details> | ||
## Contributing | ||
If you want to contribute to the JavaScript SDK, follow the guidelines in [CONTRIBUTING.md](./CONTRIBUTING.md). |
@@ -1,3 +0,4 @@ | ||
import { BaseServiceParams } from ".."; | ||
import { Error as JsonError } from ".."; | ||
import { DEFAULT_FETCH_INIT } from "#fetch"; | ||
import { BaseServiceParams, Error as JsonError } from ".."; | ||
import { buildUserAgent } from "../utils/userAgent"; | ||
@@ -8,2 +9,3 @@ /** | ||
export abstract class BaseService { | ||
private userAgent: string | undefined; | ||
/** | ||
@@ -13,3 +15,9 @@ * Create a new service. | ||
*/ | ||
constructor(private params: BaseServiceParams) {} | ||
constructor(private params: BaseServiceParams) { | ||
if (params.userAgent === false) { | ||
this.userAgent = undefined; | ||
} else { | ||
this.userAgent = buildUserAgent(params.userAgent || {}); | ||
} | ||
} | ||
protected async fetch( | ||
@@ -19,9 +27,21 @@ input: string, | ||
): Promise<Response> { | ||
init = init ?? {}; | ||
init.headers = init.headers ?? {}; | ||
init.headers = { | ||
init = { ...DEFAULT_FETCH_INIT, ...init }; | ||
let headers = { | ||
Authorization: this.params.apiKey, | ||
"Content-Type": "application/json", | ||
...init.headers, | ||
}; | ||
if (DEFAULT_FETCH_INIT?.headers) | ||
headers = { ...headers, ...DEFAULT_FETCH_INIT.headers }; | ||
if (init?.headers) headers = { ...headers, ...init.headers }; | ||
if (this.userAgent) { | ||
(headers as Record<string, string>)["User-Agent"] = this.userAgent; | ||
// chromium browsers have a bug where the user agent can't be modified | ||
if (typeof window !== "undefined" && "chrome" in window) { | ||
(headers as Record<string, string>)["AssemblyAI-Agent"] = | ||
this.userAgent; | ||
} | ||
} | ||
init.headers = headers; | ||
if (!input.startsWith("http")) input = this.params.baseUrl + input; | ||
@@ -28,0 +48,0 @@ |
@@ -13,4 +13,9 @@ import { readFile } from "#fs"; | ||
let fileData: FileUploadData; | ||
if (typeof input === "string") fileData = await readFile(input); | ||
else fileData = input; | ||
if (typeof input === "string") { | ||
if (input.startsWith("data:")) { | ||
fileData = dataUrlToBlob(input); | ||
} else { | ||
fileData = await readFile(input); | ||
} | ||
} else fileData = input; | ||
@@ -28,1 +33,13 @@ const data = await this.fetchJson<UploadedFile>("/v2/upload", { | ||
} | ||
function dataUrlToBlob(dataUrl: string) { | ||
const arr = dataUrl.split(","); | ||
const mime = arr[0].match(/:(.*?);/)![1]; | ||
const bstr = atob(arr[1]); | ||
let n = bstr.length; | ||
const u8arr = new Uint8Array(n); | ||
while (n--) { | ||
u8arr[n] = bstr.charCodeAt(n); | ||
} | ||
return new Blob([u8arr], { type: mime }); | ||
} |
@@ -41,4 +41,5 @@ import { BaseServiceParams } from ".."; | ||
params.baseUrl = params.baseUrl || defaultBaseUrl; | ||
if (params.baseUrl && params.baseUrl.endsWith("/")) | ||
if (params.baseUrl && params.baseUrl.endsWith("/")) { | ||
params.baseUrl = params.baseUrl.slice(0, -1); | ||
} | ||
this.files = new FileService(params); | ||
@@ -45,0 +46,0 @@ this.transcripts = new TranscriptService(params, this.files); |
@@ -11,2 +11,3 @@ import { | ||
PurgeLemurRequestDataResponse, | ||
LemurResponse, | ||
} from "../.."; | ||
@@ -55,2 +56,13 @@ import { BaseService } from "../base"; | ||
/** | ||
* Retrieve a LeMUR response that was previously generated. | ||
* @param id - The ID of the LeMUR request you previously made. This would be found in the response of the original request. | ||
* @returns The LeMUR response. | ||
*/ | ||
getResponse<T extends LemurResponse>(id: string): Promise<T>; | ||
getResponse(id: string): Promise<LemurResponse>; | ||
getResponse(id: string): Promise<LemurResponse> { | ||
return this.fetchJson<LemurResponse>(`/lemur/v3/${id}`); | ||
} | ||
/** | ||
* Delete the data for a previously submitted LeMUR request. | ||
@@ -57,0 +69,0 @@ * @param id - ID of the LeMUR request |
@@ -19,2 +19,3 @@ import { BaseService } from "../base"; | ||
SpeechModel, | ||
RedactedAudioFile, | ||
} from "../.."; | ||
@@ -64,4 +65,8 @@ import { FileService } from "../files"; | ||
} else { | ||
// audio is not a local path, assume it's a URL | ||
audioUrl = audio; | ||
if (audio.startsWith("data:")) { | ||
audioUrl = await this.files.upload(audio); | ||
} else { | ||
// audio is not a local path, and not a data-URI, assume it's a normal URL | ||
audioUrl = audio; | ||
} | ||
} | ||
@@ -245,7 +250,17 @@ } else { | ||
/** | ||
* Retrieve redactions of a transcript. | ||
* Retrieve the redacted audio URL of a transcript. | ||
* @param id - The identifier of the transcript. | ||
* @returns A promise that resolves to the subtitles text. | ||
* @returns A promise that resolves to the details of the redacted audio. | ||
* @deprecated Use `redactedAudio` instead. | ||
*/ | ||
redactions(id: string): Promise<RedactedAudioResponse> { | ||
return this.redactedAudio(id); | ||
} | ||
/** | ||
* Retrieve the redacted audio URL of a transcript. | ||
* @param id - The identifier of the transcript. | ||
* @returns A promise that resolves to the details of the redacted audio. | ||
*/ | ||
redactedAudio(id: string): Promise<RedactedAudioResponse> { | ||
return this.fetchJson<RedactedAudioResponse>( | ||
@@ -255,2 +270,24 @@ `/v2/transcript/${id}/redacted-audio`, | ||
} | ||
/** | ||
* Retrieve the redacted audio file of a transcript. | ||
* @param id - The identifier of the transcript. | ||
* @returns A promise that resolves to the fetch HTTP response of the redacted audio file. | ||
*/ | ||
async redactedAudioFile(id: string): Promise<RedactedAudioFile> { | ||
const { redacted_audio_url, status } = await this.redactedAudio(id); | ||
if (status !== "redacted_audio_ready") { | ||
throw new Error(`Redacted audio status is ${status}`); | ||
} | ||
const response = await fetch(redacted_audio_url); | ||
if (!response.ok) { | ||
throw new Error(`Failed to fetch redacted audio: ${response.statusText}`); | ||
} | ||
return { | ||
arrayBuffer: response.arrayBuffer.bind(response), | ||
blob: response.blob.bind(response), | ||
body: response.body, | ||
bodyUsed: response.bodyUsed, | ||
}; | ||
} | ||
} | ||
@@ -257,0 +294,0 @@ |
@@ -8,1 +8,10 @@ export * from "./files"; | ||
export * from "./deprecated"; | ||
export type UserAgentItem = { | ||
name: string; | ||
version: string; | ||
}; | ||
export type UserAgent = { | ||
[component: string]: UserAgentItem | undefined | null | false; | ||
}; |
@@ -0,6 +1,14 @@ | ||
import { UserAgent } from ".."; | ||
type BaseServiceParams = { | ||
apiKey: string; | ||
baseUrl?: string; | ||
/** | ||
* The AssemblyAI user agent to use for requests. | ||
* The provided components will be merged into the default AssemblyAI user agent. | ||
* If `false`, the AssemblyAI user agent will be removed. | ||
*/ | ||
userAgent?: UserAgent | false; | ||
}; | ||
export type { BaseServiceParams }; |
@@ -57,1 +57,11 @@ import { FileUploadParams } from "../files"; | ||
export type TranscribeOptions = PollingOptions; | ||
/** | ||
* The PII redacted audio file, transmitted over the network. | ||
*/ | ||
export type RedactedAudioFile = { | ||
arrayBuffer: () => Promise<ArrayBuffer>; | ||
blob: () => Promise<Blob>; | ||
body: ReadableStream<Uint8Array> | null; | ||
bodyUsed: boolean; | ||
}; |
export function getPath(path: string) { | ||
if (path.startsWith("http")) return null; | ||
if (path.startsWith("https")) return null; | ||
if (path.startsWith("data:")) return null; | ||
if (path.startsWith("file://")) return path.substring(7); | ||
@@ -5,0 +6,0 @@ if (path.startsWith("file:")) return path.substring(5); |
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
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
648916
91
16734
0
391
31
20
Updatedws@^8.17.0