assemblyai 4.5.0-beta.0 → 4.6.0
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 +41 -0
- package/README.md +53 -9
- package/dist/assemblyai.streaming.umd.js +317 -0
- package/dist/assemblyai.streaming.umd.min.js +1 -0
- package/dist/assemblyai.umd.js +160 -12
- package/dist/assemblyai.umd.min.js +1 -1
- package/dist/browser.mjs +154 -11
- package/dist/bun.mjs +154 -11
- package/dist/deno.mjs +154 -11
- package/dist/exports/index.d.ts +2 -0
- package/dist/exports/streaming.d.ts +4 -0
- package/dist/index.cjs +160 -12
- package/dist/index.mjs +160 -12
- package/dist/node.cjs +154 -11
- package/dist/node.mjs +154 -11
- package/dist/polyfills/fetch/default.d.ts +1 -0
- package/dist/polyfills/fetch/workerd.d.ts +1 -0
- package/dist/services/base.d.ts +1 -0
- package/dist/services/lemur/index.d.ts +8 -1
- package/dist/services/realtime/service.d.ts +60 -0
- package/dist/services/transcripts/index.d.ts +16 -3
- package/dist/streaming.browser.mjs +268 -0
- package/dist/streaming.cjs +306 -0
- package/dist/streaming.mjs +303 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/openapi.generated.d.ts +75 -29
- package/dist/types/services/index.d.ts +7 -0
- package/dist/types/transcripts/index.d.ts +9 -0
- package/dist/utils/userAgent.d.ts +2 -0
- package/dist/workerd.mjs +751 -0
- package/docs/reference-types-from-js.md +27 -0
- package/package.json +57 -25
- package/src/exports/index.ts +2 -0
- package/src/exports/streaming.ts +4 -0
- package/src/polyfills/fetch/default.ts +3 -0
- package/src/polyfills/fetch/workerd.ts +1 -0
- package/src/services/base.ts +27 -7
- package/src/services/files/index.ts +19 -2
- package/src/services/index.ts +2 -1
- package/src/services/lemur/index.ts +12 -0
- package/src/services/realtime/service.ts +65 -0
- package/src/services/transcripts/index.ts +41 -4
- package/src/types/index.ts +9 -0
- package/src/types/openapi.generated.ts +224 -48
- package/src/types/services/index.ts +8 -0
- package/src/types/transcripts/index.ts +10 -0
- package/src/utils/path.ts +1 -0
- package/src/utils/userAgent.ts +51 -0
package/dist/bun.mjs
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
import ws from 'ws';
|
|
2
2
|
|
|
3
|
+
const DEFAULT_FETCH_INIT = {
|
|
4
|
+
cache: "no-store",
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const buildUserAgent = (userAgent) => defaultUserAgentString +
|
|
8
|
+
(userAgent === false
|
|
9
|
+
? ""
|
|
10
|
+
: " AssemblyAI/1.0 (" +
|
|
11
|
+
Object.entries({ ...defaultUserAgent, ...userAgent })
|
|
12
|
+
.map(([key, item]) => item ? `${key}=${item.name}/${item.version}` : "")
|
|
13
|
+
.join(" ") +
|
|
14
|
+
")");
|
|
15
|
+
let defaultUserAgentString = "";
|
|
16
|
+
if (typeof navigator !== "undefined" && navigator.userAgent) {
|
|
17
|
+
defaultUserAgentString += navigator.userAgent;
|
|
18
|
+
}
|
|
19
|
+
const defaultUserAgent = {
|
|
20
|
+
sdk: { name: "JavaScript", version: "4.6.0" },
|
|
21
|
+
};
|
|
22
|
+
if (typeof process !== "undefined") {
|
|
23
|
+
if (process.versions.node && defaultUserAgentString.indexOf("Node") === -1) {
|
|
24
|
+
defaultUserAgent.runtime_env = {
|
|
25
|
+
name: "Node",
|
|
26
|
+
version: process.versions.node,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
if (process.versions.bun && defaultUserAgentString.indexOf("Bun") === -1) {
|
|
30
|
+
defaultUserAgent.runtime_env = {
|
|
31
|
+
name: "Bun",
|
|
32
|
+
version: process.versions.bun,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (typeof Deno !== "undefined") {
|
|
37
|
+
if (process.versions.bun && defaultUserAgentString.indexOf("Deno") === -1) {
|
|
38
|
+
defaultUserAgent.runtime_env = { name: "Deno", version: Deno.version.deno };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
3
42
|
/**
|
|
4
43
|
* Base class for services that communicate with the API.
|
|
5
44
|
*/
|
|
@@ -10,15 +49,32 @@ class BaseService {
|
|
|
10
49
|
*/
|
|
11
50
|
constructor(params) {
|
|
12
51
|
this.params = params;
|
|
52
|
+
if (params.userAgent === false) {
|
|
53
|
+
this.userAgent = undefined;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this.userAgent = buildUserAgent(params.userAgent || {});
|
|
57
|
+
}
|
|
13
58
|
}
|
|
14
59
|
async fetch(input, init) {
|
|
15
|
-
init = init
|
|
16
|
-
|
|
17
|
-
init.headers = {
|
|
60
|
+
init = { ...DEFAULT_FETCH_INIT, ...init };
|
|
61
|
+
let headers = {
|
|
18
62
|
Authorization: this.params.apiKey,
|
|
19
63
|
"Content-Type": "application/json",
|
|
20
|
-
...init.headers,
|
|
21
64
|
};
|
|
65
|
+
if (DEFAULT_FETCH_INIT?.headers)
|
|
66
|
+
headers = { ...headers, ...DEFAULT_FETCH_INIT.headers };
|
|
67
|
+
if (init?.headers)
|
|
68
|
+
headers = { ...headers, ...init.headers };
|
|
69
|
+
if (this.userAgent) {
|
|
70
|
+
headers["User-Agent"] = this.userAgent;
|
|
71
|
+
// chromium browsers have a bug where the user agent can't be modified
|
|
72
|
+
if (typeof window !== "undefined" && "chrome" in window) {
|
|
73
|
+
headers["AssemblyAI-Agent"] =
|
|
74
|
+
this.userAgent;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
init.headers = headers;
|
|
22
78
|
if (!input.startsWith("http"))
|
|
23
79
|
input = this.params.baseUrl + input;
|
|
24
80
|
const response = await fetch(input, init);
|
|
@@ -71,6 +127,9 @@ class LemurService extends BaseService {
|
|
|
71
127
|
body: JSON.stringify(params),
|
|
72
128
|
});
|
|
73
129
|
}
|
|
130
|
+
getResponse(id) {
|
|
131
|
+
return this.fetchJson(`/lemur/v3/${id}`);
|
|
132
|
+
}
|
|
74
133
|
/**
|
|
75
134
|
* Delete the data for a previously submitted LeMUR request.
|
|
76
135
|
* @param id - ID of the LeMUR request
|
|
@@ -134,7 +193,14 @@ class RealtimeError extends Error {
|
|
|
134
193
|
const defaultRealtimeUrl = "wss://api.assemblyai.com/v2/realtime/ws";
|
|
135
194
|
const forceEndOfUtteranceMessage = `{"force_end_utterance":true}`;
|
|
136
195
|
const terminateSessionMessage = `{"terminate_session":true}`;
|
|
196
|
+
/**
|
|
197
|
+
* RealtimeTranscriber connects to the Streaming Speech-to-Text API and lets you transcribe audio in real-time.
|
|
198
|
+
*/
|
|
137
199
|
class RealtimeTranscriber {
|
|
200
|
+
/**
|
|
201
|
+
* Create a new RealtimeTranscriber.
|
|
202
|
+
* @param params - Parameters to configure the RealtimeTranscriber
|
|
203
|
+
*/
|
|
138
204
|
constructor(params) {
|
|
139
205
|
this.listeners = {};
|
|
140
206
|
this.realtimeUrl = params.realtimeUrl ?? defaultRealtimeUrl;
|
|
@@ -174,10 +240,19 @@ class RealtimeTranscriber {
|
|
|
174
240
|
url.search = searchParams.toString();
|
|
175
241
|
return url;
|
|
176
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* Add a listener for an event.
|
|
245
|
+
* @param event - The event to listen for.
|
|
246
|
+
* @param listener - The function to call when the event is emitted.
|
|
247
|
+
*/
|
|
177
248
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
178
249
|
on(event, listener) {
|
|
179
250
|
this.listeners[event] = listener;
|
|
180
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* Connect to the server and begin a new session.
|
|
254
|
+
* @returns A promise that resolves when the connection is established and the session begins.
|
|
255
|
+
*/
|
|
181
256
|
connect() {
|
|
182
257
|
return new Promise((resolve) => {
|
|
183
258
|
if (this.socket) {
|
|
@@ -256,9 +331,17 @@ class RealtimeTranscriber {
|
|
|
256
331
|
};
|
|
257
332
|
});
|
|
258
333
|
}
|
|
334
|
+
/**
|
|
335
|
+
* Send audio data to the server.
|
|
336
|
+
* @param audio - The audio data to send to the server.
|
|
337
|
+
*/
|
|
259
338
|
sendAudio(audio) {
|
|
260
339
|
this.send(audio);
|
|
261
340
|
}
|
|
341
|
+
/**
|
|
342
|
+
* Create a writable stream that can be used to send audio data to the server.
|
|
343
|
+
* @returns A writable stream that can be used to send audio data to the server.
|
|
344
|
+
*/
|
|
262
345
|
stream() {
|
|
263
346
|
return new WritableStream({
|
|
264
347
|
write: (chunk) => {
|
|
@@ -286,6 +369,11 @@ class RealtimeTranscriber {
|
|
|
286
369
|
}
|
|
287
370
|
this.socket.send(data);
|
|
288
371
|
}
|
|
372
|
+
/**
|
|
373
|
+
* Close the connection to the server.
|
|
374
|
+
* @param waitForSessionTermination - If true, the method will wait for the session to be terminated before closing the connection.
|
|
375
|
+
* While waiting for the session to be terminated, you will receive the final transcript and session information.
|
|
376
|
+
*/
|
|
289
377
|
async close(waitForSessionTermination = true) {
|
|
290
378
|
if (this.socket) {
|
|
291
379
|
if (this.socket.readyState === this.socket.OPEN) {
|
|
@@ -351,6 +439,8 @@ function getPath(path) {
|
|
|
351
439
|
return null;
|
|
352
440
|
if (path.startsWith("https"))
|
|
353
441
|
return null;
|
|
442
|
+
if (path.startsWith("data:"))
|
|
443
|
+
return null;
|
|
354
444
|
if (path.startsWith("file://"))
|
|
355
445
|
return path.substring(7);
|
|
356
446
|
if (path.startsWith("file:"))
|
|
@@ -392,8 +482,13 @@ class TranscriptService extends BaseService {
|
|
|
392
482
|
audioUrl = await this.files.upload(path);
|
|
393
483
|
}
|
|
394
484
|
else {
|
|
395
|
-
|
|
396
|
-
|
|
485
|
+
if (audio.startsWith("data:")) {
|
|
486
|
+
audioUrl = await this.files.upload(audio);
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
// audio is not a local path, and not a data-URI, assume it's a normal URL
|
|
490
|
+
audioUrl = audio;
|
|
491
|
+
}
|
|
397
492
|
}
|
|
398
493
|
}
|
|
399
494
|
else {
|
|
@@ -544,13 +639,43 @@ class TranscriptService extends BaseService {
|
|
|
544
639
|
return await response.text();
|
|
545
640
|
}
|
|
546
641
|
/**
|
|
547
|
-
* Retrieve
|
|
642
|
+
* Retrieve the redacted audio URL of a transcript.
|
|
548
643
|
* @param id - The identifier of the transcript.
|
|
549
|
-
* @returns A promise that resolves to the
|
|
644
|
+
* @returns A promise that resolves to the details of the redacted audio.
|
|
645
|
+
* @deprecated Use `redactedAudio` instead.
|
|
550
646
|
*/
|
|
551
647
|
redactions(id) {
|
|
648
|
+
return this.redactedAudio(id);
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Retrieve the redacted audio URL of a transcript.
|
|
652
|
+
* @param id - The identifier of the transcript.
|
|
653
|
+
* @returns A promise that resolves to the details of the redacted audio.
|
|
654
|
+
*/
|
|
655
|
+
redactedAudio(id) {
|
|
552
656
|
return this.fetchJson(`/v2/transcript/${id}/redacted-audio`);
|
|
553
657
|
}
|
|
658
|
+
/**
|
|
659
|
+
* Retrieve the redacted audio file of a transcript.
|
|
660
|
+
* @param id - The identifier of the transcript.
|
|
661
|
+
* @returns A promise that resolves to the fetch HTTP response of the redacted audio file.
|
|
662
|
+
*/
|
|
663
|
+
async redactedAudioFile(id) {
|
|
664
|
+
const { redacted_audio_url, status } = await this.redactedAudio(id);
|
|
665
|
+
if (status !== "redacted_audio_ready") {
|
|
666
|
+
throw new Error(`Redacted audio status is ${status}`);
|
|
667
|
+
}
|
|
668
|
+
const response = await fetch(redacted_audio_url);
|
|
669
|
+
if (!response.ok) {
|
|
670
|
+
throw new Error(`Failed to fetch redacted audio: ${response.statusText}`);
|
|
671
|
+
}
|
|
672
|
+
return {
|
|
673
|
+
arrayBuffer: response.arrayBuffer.bind(response),
|
|
674
|
+
blob: response.blob.bind(response),
|
|
675
|
+
body: response.body,
|
|
676
|
+
bodyUsed: response.bodyUsed,
|
|
677
|
+
};
|
|
678
|
+
}
|
|
554
679
|
}
|
|
555
680
|
function deprecateConformer2(params) {
|
|
556
681
|
if (!params)
|
|
@@ -570,8 +695,14 @@ class FileService extends BaseService {
|
|
|
570
695
|
*/
|
|
571
696
|
async upload(input) {
|
|
572
697
|
let fileData;
|
|
573
|
-
if (typeof input === "string")
|
|
574
|
-
|
|
698
|
+
if (typeof input === "string") {
|
|
699
|
+
if (input.startsWith("data:")) {
|
|
700
|
+
fileData = dataUrlToBlob(input);
|
|
701
|
+
}
|
|
702
|
+
else {
|
|
703
|
+
fileData = await readFile(input);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
575
706
|
else
|
|
576
707
|
fileData = input;
|
|
577
708
|
const data = await this.fetchJson("/v2/upload", {
|
|
@@ -585,6 +716,17 @@ class FileService extends BaseService {
|
|
|
585
716
|
return data.upload_url;
|
|
586
717
|
}
|
|
587
718
|
}
|
|
719
|
+
function dataUrlToBlob(dataUrl) {
|
|
720
|
+
const arr = dataUrl.split(",");
|
|
721
|
+
const mime = arr[0].match(/:(.*?);/)[1];
|
|
722
|
+
const bstr = atob(arr[1]);
|
|
723
|
+
let n = bstr.length;
|
|
724
|
+
const u8arr = new Uint8Array(n);
|
|
725
|
+
while (n--) {
|
|
726
|
+
u8arr[n] = bstr.charCodeAt(n);
|
|
727
|
+
}
|
|
728
|
+
return new Blob([u8arr], { type: mime });
|
|
729
|
+
}
|
|
588
730
|
|
|
589
731
|
const defaultBaseUrl = "https://api.assemblyai.com";
|
|
590
732
|
class AssemblyAI {
|
|
@@ -594,8 +736,9 @@ class AssemblyAI {
|
|
|
594
736
|
*/
|
|
595
737
|
constructor(params) {
|
|
596
738
|
params.baseUrl = params.baseUrl || defaultBaseUrl;
|
|
597
|
-
if (params.baseUrl && params.baseUrl.endsWith("/"))
|
|
739
|
+
if (params.baseUrl && params.baseUrl.endsWith("/")) {
|
|
598
740
|
params.baseUrl = params.baseUrl.slice(0, -1);
|
|
741
|
+
}
|
|
599
742
|
this.files = new FileService(params);
|
|
600
743
|
this.transcripts = new TranscriptService(params, this.files);
|
|
601
744
|
this.lemur = new LemurService(params);
|
package/dist/deno.mjs
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
import ws from 'ws';
|
|
2
2
|
|
|
3
|
+
const DEFAULT_FETCH_INIT = {
|
|
4
|
+
cache: "no-store",
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const buildUserAgent = (userAgent) => defaultUserAgentString +
|
|
8
|
+
(userAgent === false
|
|
9
|
+
? ""
|
|
10
|
+
: " AssemblyAI/1.0 (" +
|
|
11
|
+
Object.entries({ ...defaultUserAgent, ...userAgent })
|
|
12
|
+
.map(([key, item]) => item ? `${key}=${item.name}/${item.version}` : "")
|
|
13
|
+
.join(" ") +
|
|
14
|
+
")");
|
|
15
|
+
let defaultUserAgentString = "";
|
|
16
|
+
if (typeof navigator !== "undefined" && navigator.userAgent) {
|
|
17
|
+
defaultUserAgentString += navigator.userAgent;
|
|
18
|
+
}
|
|
19
|
+
const defaultUserAgent = {
|
|
20
|
+
sdk: { name: "JavaScript", version: "4.6.0" },
|
|
21
|
+
};
|
|
22
|
+
if (typeof process !== "undefined") {
|
|
23
|
+
if (process.versions.node && defaultUserAgentString.indexOf("Node") === -1) {
|
|
24
|
+
defaultUserAgent.runtime_env = {
|
|
25
|
+
name: "Node",
|
|
26
|
+
version: process.versions.node,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
if (process.versions.bun && defaultUserAgentString.indexOf("Bun") === -1) {
|
|
30
|
+
defaultUserAgent.runtime_env = {
|
|
31
|
+
name: "Bun",
|
|
32
|
+
version: process.versions.bun,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (typeof Deno !== "undefined") {
|
|
37
|
+
if (process.versions.bun && defaultUserAgentString.indexOf("Deno") === -1) {
|
|
38
|
+
defaultUserAgent.runtime_env = { name: "Deno", version: Deno.version.deno };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
3
42
|
/**
|
|
4
43
|
* Base class for services that communicate with the API.
|
|
5
44
|
*/
|
|
@@ -10,15 +49,32 @@ class BaseService {
|
|
|
10
49
|
*/
|
|
11
50
|
constructor(params) {
|
|
12
51
|
this.params = params;
|
|
52
|
+
if (params.userAgent === false) {
|
|
53
|
+
this.userAgent = undefined;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this.userAgent = buildUserAgent(params.userAgent || {});
|
|
57
|
+
}
|
|
13
58
|
}
|
|
14
59
|
async fetch(input, init) {
|
|
15
|
-
init = init
|
|
16
|
-
|
|
17
|
-
init.headers = {
|
|
60
|
+
init = { ...DEFAULT_FETCH_INIT, ...init };
|
|
61
|
+
let headers = {
|
|
18
62
|
Authorization: this.params.apiKey,
|
|
19
63
|
"Content-Type": "application/json",
|
|
20
|
-
...init.headers,
|
|
21
64
|
};
|
|
65
|
+
if (DEFAULT_FETCH_INIT?.headers)
|
|
66
|
+
headers = { ...headers, ...DEFAULT_FETCH_INIT.headers };
|
|
67
|
+
if (init?.headers)
|
|
68
|
+
headers = { ...headers, ...init.headers };
|
|
69
|
+
if (this.userAgent) {
|
|
70
|
+
headers["User-Agent"] = this.userAgent;
|
|
71
|
+
// chromium browsers have a bug where the user agent can't be modified
|
|
72
|
+
if (typeof window !== "undefined" && "chrome" in window) {
|
|
73
|
+
headers["AssemblyAI-Agent"] =
|
|
74
|
+
this.userAgent;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
init.headers = headers;
|
|
22
78
|
if (!input.startsWith("http"))
|
|
23
79
|
input = this.params.baseUrl + input;
|
|
24
80
|
const response = await fetch(input, init);
|
|
@@ -71,6 +127,9 @@ class LemurService extends BaseService {
|
|
|
71
127
|
body: JSON.stringify(params),
|
|
72
128
|
});
|
|
73
129
|
}
|
|
130
|
+
getResponse(id) {
|
|
131
|
+
return this.fetchJson(`/lemur/v3/${id}`);
|
|
132
|
+
}
|
|
74
133
|
/**
|
|
75
134
|
* Delete the data for a previously submitted LeMUR request.
|
|
76
135
|
* @param id - ID of the LeMUR request
|
|
@@ -134,7 +193,14 @@ class RealtimeError extends Error {
|
|
|
134
193
|
const defaultRealtimeUrl = "wss://api.assemblyai.com/v2/realtime/ws";
|
|
135
194
|
const forceEndOfUtteranceMessage = `{"force_end_utterance":true}`;
|
|
136
195
|
const terminateSessionMessage = `{"terminate_session":true}`;
|
|
196
|
+
/**
|
|
197
|
+
* RealtimeTranscriber connects to the Streaming Speech-to-Text API and lets you transcribe audio in real-time.
|
|
198
|
+
*/
|
|
137
199
|
class RealtimeTranscriber {
|
|
200
|
+
/**
|
|
201
|
+
* Create a new RealtimeTranscriber.
|
|
202
|
+
* @param params - Parameters to configure the RealtimeTranscriber
|
|
203
|
+
*/
|
|
138
204
|
constructor(params) {
|
|
139
205
|
this.listeners = {};
|
|
140
206
|
this.realtimeUrl = params.realtimeUrl ?? defaultRealtimeUrl;
|
|
@@ -174,10 +240,19 @@ class RealtimeTranscriber {
|
|
|
174
240
|
url.search = searchParams.toString();
|
|
175
241
|
return url;
|
|
176
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* Add a listener for an event.
|
|
245
|
+
* @param event - The event to listen for.
|
|
246
|
+
* @param listener - The function to call when the event is emitted.
|
|
247
|
+
*/
|
|
177
248
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
178
249
|
on(event, listener) {
|
|
179
250
|
this.listeners[event] = listener;
|
|
180
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* Connect to the server and begin a new session.
|
|
254
|
+
* @returns A promise that resolves when the connection is established and the session begins.
|
|
255
|
+
*/
|
|
181
256
|
connect() {
|
|
182
257
|
return new Promise((resolve) => {
|
|
183
258
|
if (this.socket) {
|
|
@@ -256,9 +331,17 @@ class RealtimeTranscriber {
|
|
|
256
331
|
};
|
|
257
332
|
});
|
|
258
333
|
}
|
|
334
|
+
/**
|
|
335
|
+
* Send audio data to the server.
|
|
336
|
+
* @param audio - The audio data to send to the server.
|
|
337
|
+
*/
|
|
259
338
|
sendAudio(audio) {
|
|
260
339
|
this.send(audio);
|
|
261
340
|
}
|
|
341
|
+
/**
|
|
342
|
+
* Create a writable stream that can be used to send audio data to the server.
|
|
343
|
+
* @returns A writable stream that can be used to send audio data to the server.
|
|
344
|
+
*/
|
|
262
345
|
stream() {
|
|
263
346
|
return new WritableStream({
|
|
264
347
|
write: (chunk) => {
|
|
@@ -286,6 +369,11 @@ class RealtimeTranscriber {
|
|
|
286
369
|
}
|
|
287
370
|
this.socket.send(data);
|
|
288
371
|
}
|
|
372
|
+
/**
|
|
373
|
+
* Close the connection to the server.
|
|
374
|
+
* @param waitForSessionTermination - If true, the method will wait for the session to be terminated before closing the connection.
|
|
375
|
+
* While waiting for the session to be terminated, you will receive the final transcript and session information.
|
|
376
|
+
*/
|
|
289
377
|
async close(waitForSessionTermination = true) {
|
|
290
378
|
if (this.socket) {
|
|
291
379
|
if (this.socket.readyState === this.socket.OPEN) {
|
|
@@ -351,6 +439,8 @@ function getPath(path) {
|
|
|
351
439
|
return null;
|
|
352
440
|
if (path.startsWith("https"))
|
|
353
441
|
return null;
|
|
442
|
+
if (path.startsWith("data:"))
|
|
443
|
+
return null;
|
|
354
444
|
if (path.startsWith("file://"))
|
|
355
445
|
return path.substring(7);
|
|
356
446
|
if (path.startsWith("file:"))
|
|
@@ -392,8 +482,13 @@ class TranscriptService extends BaseService {
|
|
|
392
482
|
audioUrl = await this.files.upload(path);
|
|
393
483
|
}
|
|
394
484
|
else {
|
|
395
|
-
|
|
396
|
-
|
|
485
|
+
if (audio.startsWith("data:")) {
|
|
486
|
+
audioUrl = await this.files.upload(audio);
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
// audio is not a local path, and not a data-URI, assume it's a normal URL
|
|
490
|
+
audioUrl = audio;
|
|
491
|
+
}
|
|
397
492
|
}
|
|
398
493
|
}
|
|
399
494
|
else {
|
|
@@ -544,13 +639,43 @@ class TranscriptService extends BaseService {
|
|
|
544
639
|
return await response.text();
|
|
545
640
|
}
|
|
546
641
|
/**
|
|
547
|
-
* Retrieve
|
|
642
|
+
* Retrieve the redacted audio URL of a transcript.
|
|
548
643
|
* @param id - The identifier of the transcript.
|
|
549
|
-
* @returns A promise that resolves to the
|
|
644
|
+
* @returns A promise that resolves to the details of the redacted audio.
|
|
645
|
+
* @deprecated Use `redactedAudio` instead.
|
|
550
646
|
*/
|
|
551
647
|
redactions(id) {
|
|
648
|
+
return this.redactedAudio(id);
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Retrieve the redacted audio URL of a transcript.
|
|
652
|
+
* @param id - The identifier of the transcript.
|
|
653
|
+
* @returns A promise that resolves to the details of the redacted audio.
|
|
654
|
+
*/
|
|
655
|
+
redactedAudio(id) {
|
|
552
656
|
return this.fetchJson(`/v2/transcript/${id}/redacted-audio`);
|
|
553
657
|
}
|
|
658
|
+
/**
|
|
659
|
+
* Retrieve the redacted audio file of a transcript.
|
|
660
|
+
* @param id - The identifier of the transcript.
|
|
661
|
+
* @returns A promise that resolves to the fetch HTTP response of the redacted audio file.
|
|
662
|
+
*/
|
|
663
|
+
async redactedAudioFile(id) {
|
|
664
|
+
const { redacted_audio_url, status } = await this.redactedAudio(id);
|
|
665
|
+
if (status !== "redacted_audio_ready") {
|
|
666
|
+
throw new Error(`Redacted audio status is ${status}`);
|
|
667
|
+
}
|
|
668
|
+
const response = await fetch(redacted_audio_url);
|
|
669
|
+
if (!response.ok) {
|
|
670
|
+
throw new Error(`Failed to fetch redacted audio: ${response.statusText}`);
|
|
671
|
+
}
|
|
672
|
+
return {
|
|
673
|
+
arrayBuffer: response.arrayBuffer.bind(response),
|
|
674
|
+
blob: response.blob.bind(response),
|
|
675
|
+
body: response.body,
|
|
676
|
+
bodyUsed: response.bodyUsed,
|
|
677
|
+
};
|
|
678
|
+
}
|
|
554
679
|
}
|
|
555
680
|
function deprecateConformer2(params) {
|
|
556
681
|
if (!params)
|
|
@@ -570,8 +695,14 @@ class FileService extends BaseService {
|
|
|
570
695
|
*/
|
|
571
696
|
async upload(input) {
|
|
572
697
|
let fileData;
|
|
573
|
-
if (typeof input === "string")
|
|
574
|
-
|
|
698
|
+
if (typeof input === "string") {
|
|
699
|
+
if (input.startsWith("data:")) {
|
|
700
|
+
fileData = dataUrlToBlob(input);
|
|
701
|
+
}
|
|
702
|
+
else {
|
|
703
|
+
fileData = await readFile(input);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
575
706
|
else
|
|
576
707
|
fileData = input;
|
|
577
708
|
const data = await this.fetchJson("/v2/upload", {
|
|
@@ -585,6 +716,17 @@ class FileService extends BaseService {
|
|
|
585
716
|
return data.upload_url;
|
|
586
717
|
}
|
|
587
718
|
}
|
|
719
|
+
function dataUrlToBlob(dataUrl) {
|
|
720
|
+
const arr = dataUrl.split(",");
|
|
721
|
+
const mime = arr[0].match(/:(.*?);/)[1];
|
|
722
|
+
const bstr = atob(arr[1]);
|
|
723
|
+
let n = bstr.length;
|
|
724
|
+
const u8arr = new Uint8Array(n);
|
|
725
|
+
while (n--) {
|
|
726
|
+
u8arr[n] = bstr.charCodeAt(n);
|
|
727
|
+
}
|
|
728
|
+
return new Blob([u8arr], { type: mime });
|
|
729
|
+
}
|
|
588
730
|
|
|
589
731
|
const defaultBaseUrl = "https://api.assemblyai.com";
|
|
590
732
|
class AssemblyAI {
|
|
@@ -594,8 +736,9 @@ class AssemblyAI {
|
|
|
594
736
|
*/
|
|
595
737
|
constructor(params) {
|
|
596
738
|
params.baseUrl = params.baseUrl || defaultBaseUrl;
|
|
597
|
-
if (params.baseUrl && params.baseUrl.endsWith("/"))
|
|
739
|
+
if (params.baseUrl && params.baseUrl.endsWith("/")) {
|
|
598
740
|
params.baseUrl = params.baseUrl.slice(0, -1);
|
|
741
|
+
}
|
|
599
742
|
this.files = new FileService(params);
|
|
600
743
|
this.transcripts = new TranscriptService(params, this.files);
|
|
601
744
|
this.lemur = new LemurService(params);
|