assemblyai 4.5.0-beta.0 → 4.5.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 +34 -0
- package/README.md +53 -9
- package/dist/assemblyai.streaming.umd.js +288 -0
- package/dist/assemblyai.streaming.umd.min.js +1 -0
- package/dist/assemblyai.umd.js +131 -12
- package/dist/assemblyai.umd.min.js +1 -1
- package/dist/browser.mjs +125 -11
- package/dist/bun.mjs +125 -11
- package/dist/deno.mjs +125 -11
- package/dist/exports/index.d.ts +2 -0
- package/dist/exports/streaming.d.ts +4 -0
- package/dist/index.cjs +131 -12
- package/dist/index.mjs +131 -12
- package/dist/node.cjs +125 -11
- package/dist/node.mjs +125 -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/transcripts/index.d.ts +16 -3
- package/dist/streaming.browser.mjs +239 -0
- package/dist/streaming.cjs +277 -0
- package/dist/streaming.mjs +274 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/openapi.generated.d.ts +60 -23
- 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 +722 -0
- package/docs/reference-types-from-js.md +27 -0
- package/package.json +39 -19
- 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/transcripts/index.ts +41 -4
- package/src/types/index.ts +9 -0
- package/src/types/openapi.generated.ts +198 -41
- 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/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
|
+
|
|
2
3
|
## [4.5.0]
|
|
3
4
|
|
|
5
|
+
- You can now retrieve previous LeMUR responses using `client.lemur.getResponse<LemurTask>("YOUR_REQUEST_ID")`.
|
|
6
|
+
- LeMUR functions now return `usage` with the number of `input_tokens` and `output_tokens`.
|
|
7
|
+
|
|
8
|
+
## [4.4.7]
|
|
9
|
+
|
|
10
|
+
- Rename `TranscriptService.redactions` function to `TranscriptService.redactedAudio`.
|
|
11
|
+
- Add `TranscriptService.redactedAudioFile` function.
|
|
12
|
+
- Add `workerd` export to fix `cache` issue with `fetch` on Cloudflare Workers.
|
|
13
|
+
|
|
14
|
+
## [4.4.6]
|
|
15
|
+
|
|
16
|
+
- Fix Rollup exports so \_\_SDK_VERSION\_\_ is properly replaced with the version of the SDK.
|
|
17
|
+
|
|
18
|
+
## [4.4.5]
|
|
19
|
+
|
|
20
|
+
- Add new `PiiPolicy` enum values
|
|
21
|
+
|
|
22
|
+
## [4.4.4]
|
|
23
|
+
|
|
24
|
+
- Add an export that only includes the Streaming STT code. You can use the export
|
|
25
|
+
- by importing `assemblyai/streaming`,
|
|
26
|
+
- or by loading the `assemblyai.streaming.umd.js` file, or `assemblyai.streaming.umd.min.js` file in a script-tag.
|
|
27
|
+
- Add new `EntityType` enum values
|
|
28
|
+
|
|
29
|
+
## [4.4.3] - 2024-05-09
|
|
30
|
+
|
|
31
|
+
- Add react-native exports that resolve to the browser version of the library.
|
|
32
|
+
|
|
33
|
+
## [4.4.2] - 2024-05-03
|
|
34
|
+
|
|
4
35
|
### Changed
|
|
36
|
+
|
|
37
|
+
- Caching is disabled for all HTTP request made by the SDK
|
|
38
|
+
- Accept data-URIs in `client.files.upload(dataUri)`, `client.transcripts.submit(audio: dataUri)`, `client.transcripts.transcribe(audio: dataUri)`.
|
|
5
39
|
- Change how the WebSocket libraries are imported for better compatibility across frameworks and runtimes.
|
|
6
40
|
The library no longer relies on a internal `#ws` import, and instead compiles the imports into the dist bundles.
|
|
7
41
|
Browser builds will use the native `WebSocket`, other builds will use the `ws` package.
|
package/README.md
CHANGED
|
@@ -53,6 +53,38 @@ const client = new AssemblyAI({
|
|
|
53
53
|
|
|
54
54
|
You can now use the `client` object to interact with the AssemblyAI API.
|
|
55
55
|
|
|
56
|
+
### Using a CDN
|
|
57
|
+
|
|
58
|
+
You can use automatic CDNs like [UNPKG](https://unpkg.com/) to load the library from a script tag.
|
|
59
|
+
|
|
60
|
+
- Replace `:version` with the desired version or `latest`.
|
|
61
|
+
- Remove `.min` to load the non-minified version.
|
|
62
|
+
- Remove `.streaming` to load the entire SDK. Keep `.streaming` to load the Streaming STT specific version.
|
|
63
|
+
|
|
64
|
+
```html
|
|
65
|
+
<!-- Unminified full SDK -->
|
|
66
|
+
<script src="https://www.unpkg.com/assemblyai@:version/dist/assemblyai.umd.js"></script>
|
|
67
|
+
<!-- Minified full SDK -->
|
|
68
|
+
<script src="https://www.unpkg.com/assemblyai@:version/dist/assemblyai.umd.min.js"></script>
|
|
69
|
+
<!-- Unminified Streaming STT only -->
|
|
70
|
+
<script src="https://www.unpkg.com/assemblyai@:version/dist/assemblyai.streaming.umd.js"></script>
|
|
71
|
+
<!-- Minified Streaming STT only -->
|
|
72
|
+
<script src="https://www.unpkg.com/assemblyai@:version/dist/assemblyai.streaming.umd.min.js"></script>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The script creates a global `assemblyai` variable containing all the services.
|
|
76
|
+
Here's how you create a `RealtimeTranscriber` object.
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
const { RealtimeTranscriber } = assemblyai;
|
|
80
|
+
const transcriber = new RealtimeTranscriber({
|
|
81
|
+
token: "[GENERATE TEMPORARY AUTH TOKEN IN YOUR API]",
|
|
82
|
+
...
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
For type support in your IDE, see [Reference types from JavaScript](./docs/reference-types-from-js.md).
|
|
87
|
+
|
|
56
88
|
## Speech-To-Text
|
|
57
89
|
|
|
58
90
|
### Transcribe audio and video files
|
|
@@ -227,18 +259,26 @@ const rt = client.realtime.transcriber({
|
|
|
227
259
|
});
|
|
228
260
|
```
|
|
229
261
|
|
|
230
|
-
You can also generate a temporary auth token for real-time.
|
|
231
|
-
|
|
232
|
-
```typescript
|
|
233
|
-
const token = await client.realtime.createTemporaryToken({ expires_in = 60 });
|
|
234
|
-
const rt = client.realtime.transcriber({
|
|
235
|
-
token: token,
|
|
236
|
-
});
|
|
237
|
-
```
|
|
238
|
-
|
|
239
262
|
> [!WARNING]
|
|
240
263
|
> Storing your API key in client-facing applications exposes your API key.
|
|
241
264
|
> Generate a temporary auth token on the server and pass it to your client.
|
|
265
|
+
> _Server code_:
|
|
266
|
+
>
|
|
267
|
+
> ```typescript
|
|
268
|
+
> const token = await client.realtime.createTemporaryToken({ expires_in = 60 });
|
|
269
|
+
> // TODO: return token to client
|
|
270
|
+
> ```
|
|
271
|
+
>
|
|
272
|
+
> _Client code_:
|
|
273
|
+
>
|
|
274
|
+
> ```typescript
|
|
275
|
+
> import { RealtimeTranscriber } from "assemblyai"; // or "assemblyai/streaming"
|
|
276
|
+
> // TODO: implement getToken to retrieve token from server
|
|
277
|
+
> const token = await getToken();
|
|
278
|
+
> const rt = new RealtimeTranscriber({
|
|
279
|
+
> token,
|
|
280
|
+
> });
|
|
281
|
+
> ```
|
|
242
282
|
|
|
243
283
|
You can configure the following events.
|
|
244
284
|
|
|
@@ -344,3 +384,7 @@ const response = await client.lemur.purgeRequestData(lemurResponse.request_id);
|
|
|
344
384
|
```
|
|
345
385
|
|
|
346
386
|
</details>
|
|
387
|
+
|
|
388
|
+
## Contributing
|
|
389
|
+
|
|
390
|
+
If you want to contribute to the JavaScript SDK, follow the guidelines in [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.assemblyai = {}));
|
|
5
|
+
})(this, (function (exports) { 'use strict';
|
|
6
|
+
|
|
7
|
+
/******************************************************************************
|
|
8
|
+
Copyright (c) Microsoft Corporation.
|
|
9
|
+
|
|
10
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
11
|
+
purpose with or without fee is hereby granted.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
14
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
15
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
16
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
17
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
18
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
19
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
20
|
+
***************************************************************************** */
|
|
21
|
+
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
25
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
26
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
27
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
28
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
29
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
30
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
35
|
+
var e = new Error(message);
|
|
36
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const { WritableStream } = typeof window !== "undefined"
|
|
40
|
+
? window
|
|
41
|
+
: typeof global !== "undefined"
|
|
42
|
+
? global
|
|
43
|
+
: globalThis;
|
|
44
|
+
|
|
45
|
+
var _a, _b;
|
|
46
|
+
const PolyfillWebSocket = (_b = (_a = WebSocket !== null && WebSocket !== void 0 ? WebSocket : global === null || global === void 0 ? void 0 : global.WebSocket) !== null && _a !== void 0 ? _a : window === null || window === void 0 ? void 0 : window.WebSocket) !== null && _b !== void 0 ? _b : self === null || self === void 0 ? void 0 : self.WebSocket;
|
|
47
|
+
const factory = (url, params) => {
|
|
48
|
+
if (params) {
|
|
49
|
+
return new PolyfillWebSocket(url, params);
|
|
50
|
+
}
|
|
51
|
+
return new PolyfillWebSocket(url);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
var RealtimeErrorType;
|
|
55
|
+
(function (RealtimeErrorType) {
|
|
56
|
+
RealtimeErrorType[RealtimeErrorType["BadSampleRate"] = 4000] = "BadSampleRate";
|
|
57
|
+
RealtimeErrorType[RealtimeErrorType["AuthFailed"] = 4001] = "AuthFailed";
|
|
58
|
+
// Both InsufficientFunds and FreeAccount error use 4002
|
|
59
|
+
RealtimeErrorType[RealtimeErrorType["InsufficientFundsOrFreeAccount"] = 4002] = "InsufficientFundsOrFreeAccount";
|
|
60
|
+
RealtimeErrorType[RealtimeErrorType["NonexistentSessionId"] = 4004] = "NonexistentSessionId";
|
|
61
|
+
RealtimeErrorType[RealtimeErrorType["SessionExpired"] = 4008] = "SessionExpired";
|
|
62
|
+
RealtimeErrorType[RealtimeErrorType["ClosedSession"] = 4010] = "ClosedSession";
|
|
63
|
+
RealtimeErrorType[RealtimeErrorType["RateLimited"] = 4029] = "RateLimited";
|
|
64
|
+
RealtimeErrorType[RealtimeErrorType["UniqueSessionViolation"] = 4030] = "UniqueSessionViolation";
|
|
65
|
+
RealtimeErrorType[RealtimeErrorType["SessionTimeout"] = 4031] = "SessionTimeout";
|
|
66
|
+
RealtimeErrorType[RealtimeErrorType["AudioTooShort"] = 4032] = "AudioTooShort";
|
|
67
|
+
RealtimeErrorType[RealtimeErrorType["AudioTooLong"] = 4033] = "AudioTooLong";
|
|
68
|
+
RealtimeErrorType[RealtimeErrorType["BadJson"] = 4100] = "BadJson";
|
|
69
|
+
RealtimeErrorType[RealtimeErrorType["BadSchema"] = 4101] = "BadSchema";
|
|
70
|
+
RealtimeErrorType[RealtimeErrorType["TooManyStreams"] = 4102] = "TooManyStreams";
|
|
71
|
+
RealtimeErrorType[RealtimeErrorType["Reconnected"] = 4103] = "Reconnected";
|
|
72
|
+
RealtimeErrorType[RealtimeErrorType["ReconnectAttemptsExhausted"] = 1013] = "ReconnectAttemptsExhausted";
|
|
73
|
+
})(RealtimeErrorType || (RealtimeErrorType = {}));
|
|
74
|
+
const RealtimeErrorMessages = {
|
|
75
|
+
[RealtimeErrorType.BadSampleRate]: "Sample rate must be a positive integer",
|
|
76
|
+
[RealtimeErrorType.AuthFailed]: "Not Authorized",
|
|
77
|
+
[RealtimeErrorType.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.",
|
|
78
|
+
[RealtimeErrorType.NonexistentSessionId]: "Session ID does not exist",
|
|
79
|
+
[RealtimeErrorType.SessionExpired]: "Session has expired",
|
|
80
|
+
[RealtimeErrorType.ClosedSession]: "Session is closed",
|
|
81
|
+
[RealtimeErrorType.RateLimited]: "Rate limited",
|
|
82
|
+
[RealtimeErrorType.UniqueSessionViolation]: "Unique session violation",
|
|
83
|
+
[RealtimeErrorType.SessionTimeout]: "Session Timeout",
|
|
84
|
+
[RealtimeErrorType.AudioTooShort]: "Audio too short",
|
|
85
|
+
[RealtimeErrorType.AudioTooLong]: "Audio too long",
|
|
86
|
+
[RealtimeErrorType.BadJson]: "Bad JSON",
|
|
87
|
+
[RealtimeErrorType.BadSchema]: "Bad schema",
|
|
88
|
+
[RealtimeErrorType.TooManyStreams]: "Too many streams",
|
|
89
|
+
[RealtimeErrorType.Reconnected]: "Reconnected",
|
|
90
|
+
[RealtimeErrorType.ReconnectAttemptsExhausted]: "Reconnect attempts exhausted",
|
|
91
|
+
};
|
|
92
|
+
class RealtimeError extends Error {
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const defaultRealtimeUrl = "wss://api.assemblyai.com/v2/realtime/ws";
|
|
96
|
+
const forceEndOfUtteranceMessage = `{"force_end_utterance":true}`;
|
|
97
|
+
const terminateSessionMessage = `{"terminate_session":true}`;
|
|
98
|
+
class RealtimeTranscriber {
|
|
99
|
+
constructor(params) {
|
|
100
|
+
var _a, _b;
|
|
101
|
+
this.listeners = {};
|
|
102
|
+
this.realtimeUrl = (_a = params.realtimeUrl) !== null && _a !== void 0 ? _a : defaultRealtimeUrl;
|
|
103
|
+
this.sampleRate = (_b = params.sampleRate) !== null && _b !== void 0 ? _b : 16000;
|
|
104
|
+
this.wordBoost = params.wordBoost;
|
|
105
|
+
this.encoding = params.encoding;
|
|
106
|
+
this.endUtteranceSilenceThreshold = params.endUtteranceSilenceThreshold;
|
|
107
|
+
this.disablePartialTranscripts = params.disablePartialTranscripts;
|
|
108
|
+
if ("token" in params && params.token)
|
|
109
|
+
this.token = params.token;
|
|
110
|
+
if ("apiKey" in params && params.apiKey)
|
|
111
|
+
this.apiKey = params.apiKey;
|
|
112
|
+
if (!(this.token || this.apiKey)) {
|
|
113
|
+
throw new Error("API key or temporary token is required.");
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
connectionUrl() {
|
|
117
|
+
const url = new URL(this.realtimeUrl);
|
|
118
|
+
if (url.protocol !== "wss:") {
|
|
119
|
+
throw new Error("Invalid protocol, must be wss");
|
|
120
|
+
}
|
|
121
|
+
const searchParams = new URLSearchParams();
|
|
122
|
+
if (this.token) {
|
|
123
|
+
searchParams.set("token", this.token);
|
|
124
|
+
}
|
|
125
|
+
searchParams.set("sample_rate", this.sampleRate.toString());
|
|
126
|
+
if (this.wordBoost && this.wordBoost.length > 0) {
|
|
127
|
+
searchParams.set("word_boost", JSON.stringify(this.wordBoost));
|
|
128
|
+
}
|
|
129
|
+
if (this.encoding) {
|
|
130
|
+
searchParams.set("encoding", this.encoding);
|
|
131
|
+
}
|
|
132
|
+
searchParams.set("enable_extra_session_information", "true");
|
|
133
|
+
if (this.disablePartialTranscripts) {
|
|
134
|
+
searchParams.set("disable_partial_transcripts", this.disablePartialTranscripts.toString());
|
|
135
|
+
}
|
|
136
|
+
url.search = searchParams.toString();
|
|
137
|
+
return url;
|
|
138
|
+
}
|
|
139
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
140
|
+
on(event, listener) {
|
|
141
|
+
this.listeners[event] = listener;
|
|
142
|
+
}
|
|
143
|
+
connect() {
|
|
144
|
+
return new Promise((resolve) => {
|
|
145
|
+
if (this.socket) {
|
|
146
|
+
throw new Error("Already connected");
|
|
147
|
+
}
|
|
148
|
+
const url = this.connectionUrl();
|
|
149
|
+
if (this.token) {
|
|
150
|
+
this.socket = factory(url.toString());
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
this.socket = factory(url.toString(), {
|
|
154
|
+
headers: { Authorization: this.apiKey },
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
this.socket.binaryType = "arraybuffer";
|
|
158
|
+
this.socket.onopen = () => {
|
|
159
|
+
if (this.endUtteranceSilenceThreshold === undefined ||
|
|
160
|
+
this.endUtteranceSilenceThreshold === null) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
this.configureEndUtteranceSilenceThreshold(this.endUtteranceSilenceThreshold);
|
|
164
|
+
};
|
|
165
|
+
this.socket.onclose = ({ code, reason }) => {
|
|
166
|
+
var _a, _b;
|
|
167
|
+
if (!reason) {
|
|
168
|
+
if (code in RealtimeErrorType) {
|
|
169
|
+
reason = RealtimeErrorMessages[code];
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
(_b = (_a = this.listeners).close) === null || _b === void 0 ? void 0 : _b.call(_a, code, reason);
|
|
173
|
+
};
|
|
174
|
+
this.socket.onerror = (event) => {
|
|
175
|
+
var _a, _b, _c, _d;
|
|
176
|
+
if (event.error)
|
|
177
|
+
(_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, event.error);
|
|
178
|
+
else
|
|
179
|
+
(_d = (_c = this.listeners).error) === null || _d === void 0 ? void 0 : _d.call(_c, new Error(event.message));
|
|
180
|
+
};
|
|
181
|
+
this.socket.onmessage = ({ data }) => {
|
|
182
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
183
|
+
const message = JSON.parse(data.toString());
|
|
184
|
+
if ("error" in message) {
|
|
185
|
+
(_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, new RealtimeError(message.error));
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
switch (message.message_type) {
|
|
189
|
+
case "SessionBegins": {
|
|
190
|
+
const openObject = {
|
|
191
|
+
sessionId: message.session_id,
|
|
192
|
+
expiresAt: new Date(message.expires_at),
|
|
193
|
+
};
|
|
194
|
+
resolve(openObject);
|
|
195
|
+
(_d = (_c = this.listeners).open) === null || _d === void 0 ? void 0 : _d.call(_c, openObject);
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
case "PartialTranscript": {
|
|
199
|
+
// message.created is actually a string when coming from the socket
|
|
200
|
+
message.created = new Date(message.created);
|
|
201
|
+
(_f = (_e = this.listeners).transcript) === null || _f === void 0 ? void 0 : _f.call(_e, message);
|
|
202
|
+
(_h = (_g = this.listeners)["transcript.partial"]) === null || _h === void 0 ? void 0 : _h.call(_g, message);
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
case "FinalTranscript": {
|
|
206
|
+
// message.created is actually a string when coming from the socket
|
|
207
|
+
message.created = new Date(message.created);
|
|
208
|
+
(_k = (_j = this.listeners).transcript) === null || _k === void 0 ? void 0 : _k.call(_j, message);
|
|
209
|
+
(_m = (_l = this.listeners)["transcript.final"]) === null || _m === void 0 ? void 0 : _m.call(_l, message);
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
case "SessionInformation": {
|
|
213
|
+
(_p = (_o = this.listeners).session_information) === null || _p === void 0 ? void 0 : _p.call(_o, message);
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
case "SessionTerminated": {
|
|
217
|
+
(_q = this.sessionTerminatedResolve) === null || _q === void 0 ? void 0 : _q.call(this);
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
sendAudio(audio) {
|
|
225
|
+
this.send(audio);
|
|
226
|
+
}
|
|
227
|
+
stream() {
|
|
228
|
+
return new WritableStream({
|
|
229
|
+
write: (chunk) => {
|
|
230
|
+
this.sendAudio(chunk);
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Manually end an utterance
|
|
236
|
+
*/
|
|
237
|
+
forceEndUtterance() {
|
|
238
|
+
this.send(forceEndOfUtteranceMessage);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Configure the threshold for how long to wait before ending an utterance. Default is 700ms.
|
|
242
|
+
* @param threshold - The duration of the end utterance silence threshold in milliseconds.
|
|
243
|
+
* This value must be an integer between 0 and 20_000.
|
|
244
|
+
*/
|
|
245
|
+
configureEndUtteranceSilenceThreshold(threshold) {
|
|
246
|
+
this.send(`{"end_utterance_silence_threshold":${threshold}}`);
|
|
247
|
+
}
|
|
248
|
+
send(data) {
|
|
249
|
+
if (!this.socket || this.socket.readyState !== this.socket.OPEN) {
|
|
250
|
+
throw new Error("Socket is not open for communication");
|
|
251
|
+
}
|
|
252
|
+
this.socket.send(data);
|
|
253
|
+
}
|
|
254
|
+
close() {
|
|
255
|
+
return __awaiter(this, arguments, void 0, function* (waitForSessionTermination = true) {
|
|
256
|
+
var _a;
|
|
257
|
+
if (this.socket) {
|
|
258
|
+
if (this.socket.readyState === this.socket.OPEN) {
|
|
259
|
+
if (waitForSessionTermination) {
|
|
260
|
+
const sessionTerminatedPromise = new Promise((resolve) => {
|
|
261
|
+
this.sessionTerminatedResolve = resolve;
|
|
262
|
+
});
|
|
263
|
+
this.socket.send(terminateSessionMessage);
|
|
264
|
+
yield sessionTerminatedPromise;
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
this.socket.send(terminateSessionMessage);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.removeAllListeners)
|
|
271
|
+
this.socket.removeAllListeners();
|
|
272
|
+
this.socket.close();
|
|
273
|
+
}
|
|
274
|
+
this.listeners = {};
|
|
275
|
+
this.socket = undefined;
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* @deprecated Use RealtimeTranscriber instead
|
|
281
|
+
*/
|
|
282
|
+
class RealtimeService extends RealtimeTranscriber {
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
exports.RealtimeService = RealtimeService;
|
|
286
|
+
exports.RealtimeTranscriber = RealtimeTranscriber;
|
|
287
|
+
|
|
288
|
+
}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).assemblyai={})}(this,(function(e){"use strict";function t(e,t,s,i){return new(s||(s=Promise))((function(o,n){function r(e){try{l(i.next(e))}catch(e){n(e)}}function a(e){try{l(i.throw(e))}catch(e){n(e)}}function l(e){var t;e.done?o(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;const{WritableStream:s}="undefined"!=typeof window?window:"undefined"!=typeof global?global:globalThis;var i,o;const n=null!==(o=null!==(i=null!==WebSocket&&void 0!==WebSocket?WebSocket:null===global||void 0===global?void 0:global.WebSocket)&&void 0!==i?i:null===window||void 0===window?void 0:window.WebSocket)&&void 0!==o?o:null===self||void 0===self?void 0:self.WebSocket,r=(e,t)=>t?new n(e,t):new n(e);var a;!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"}(a||(a={}));const l={[a.BadSampleRate]:"Sample rate must be a positive integer",[a.AuthFailed]:"Not Authorized",[a.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.",[a.NonexistentSessionId]:"Session ID does not exist",[a.SessionExpired]:"Session has expired",[a.ClosedSession]:"Session is closed",[a.RateLimited]:"Rate limited",[a.UniqueSessionViolation]:"Unique session violation",[a.SessionTimeout]:"Session Timeout",[a.AudioTooShort]:"Audio too short",[a.AudioTooLong]:"Audio too long",[a.BadJson]:"Bad JSON",[a.BadSchema]:"Bad schema",[a.TooManyStreams]:"Too many streams",[a.Reconnected]:"Reconnected",[a.ReconnectAttemptsExhausted]:"Reconnect attempts exhausted"};class c 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.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=r(t.toString()):this.socket=r(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 a&&(t=l[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,l,d,h,u,p,m,S,f,v;const w=JSON.parse(t.toString());if("error"in w)null===(i=(s=this.listeners).error)||void 0===i||i.call(s,new c(w.error));else switch(w.message_type){case"SessionBegins":{const t={sessionId:w.session_id,expiresAt:new Date(w.expires_at)};e(t),null===(n=(o=this.listeners).open)||void 0===n||n.call(o,t);break}case"PartialTranscript":w.created=new Date(w.created),null===(a=(r=this.listeners).transcript)||void 0===a||a.call(r,w),null===(d=(l=this.listeners)["transcript.partial"])||void 0===d||d.call(l,w);break;case"FinalTranscript":w.created=new Date(w.created),null===(u=(h=this.listeners).transcript)||void 0===u||u.call(h,w),null===(m=(p=this.listeners)["transcript.final"])||void 0===m||m.call(p,w);break;case"SessionInformation":null===(f=(S=this.listeners).session_information)||void 0===f||f.call(S,w);break;case"SessionTerminated":null===(v=this.sessionTerminatedResolve)||void 0===v||v.call(this)}}}))}sendAudio(e){this.send(e)}stream(){return new s({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(d),yield e}else this.socket.send(d);(null===(t=this.socket)||void 0===t?void 0:t.removeAllListeners)&&this.socket.removeAllListeners(),this.socket.close()}this.listeners={},this.socket=void 0}))}}e.RealtimeService=class extends h{},e.RealtimeTranscriber=h}));
|
package/dist/assemblyai.umd.js
CHANGED
|
@@ -48,6 +48,45 @@
|
|
|
48
48
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
+
const DEFAULT_FETCH_INIT = {
|
|
52
|
+
cache: "no-store",
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const buildUserAgent = (userAgent) => defaultUserAgentString +
|
|
56
|
+
(userAgent === false
|
|
57
|
+
? ""
|
|
58
|
+
: " AssemblyAI/1.0 (" +
|
|
59
|
+
Object.entries(Object.assign(Object.assign({}, defaultUserAgent), userAgent))
|
|
60
|
+
.map(([key, item]) => item ? `${key}=${item.name}/${item.version}` : "")
|
|
61
|
+
.join(" ") +
|
|
62
|
+
")");
|
|
63
|
+
let defaultUserAgentString = "";
|
|
64
|
+
if (typeof navigator !== "undefined" && navigator.userAgent) {
|
|
65
|
+
defaultUserAgentString += navigator.userAgent;
|
|
66
|
+
}
|
|
67
|
+
const defaultUserAgent = {
|
|
68
|
+
sdk: { name: "JavaScript", version: "4.5.0" },
|
|
69
|
+
};
|
|
70
|
+
if (typeof process !== "undefined") {
|
|
71
|
+
if (process.versions.node && defaultUserAgentString.indexOf("Node") === -1) {
|
|
72
|
+
defaultUserAgent.runtime_env = {
|
|
73
|
+
name: "Node",
|
|
74
|
+
version: process.versions.node,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
if (process.versions.bun && defaultUserAgentString.indexOf("Bun") === -1) {
|
|
78
|
+
defaultUserAgent.runtime_env = {
|
|
79
|
+
name: "Bun",
|
|
80
|
+
version: process.versions.bun,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (typeof Deno !== "undefined") {
|
|
85
|
+
if (process.versions.bun && defaultUserAgentString.indexOf("Deno") === -1) {
|
|
86
|
+
defaultUserAgent.runtime_env = { name: "Deno", version: Deno.version.deno };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
51
90
|
/**
|
|
52
91
|
* Base class for services that communicate with the API.
|
|
53
92
|
*/
|
|
@@ -58,13 +97,33 @@
|
|
|
58
97
|
*/
|
|
59
98
|
constructor(params) {
|
|
60
99
|
this.params = params;
|
|
100
|
+
if (params.userAgent === false) {
|
|
101
|
+
this.userAgent = undefined;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
this.userAgent = buildUserAgent(params.userAgent || {});
|
|
105
|
+
}
|
|
61
106
|
}
|
|
62
107
|
fetch(input, init) {
|
|
63
108
|
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
109
|
+
init = Object.assign(Object.assign({}, DEFAULT_FETCH_INIT), init);
|
|
110
|
+
let headers = {
|
|
111
|
+
Authorization: this.params.apiKey,
|
|
112
|
+
"Content-Type": "application/json",
|
|
113
|
+
};
|
|
114
|
+
if (DEFAULT_FETCH_INIT === null || DEFAULT_FETCH_INIT === void 0 ? void 0 : DEFAULT_FETCH_INIT.headers)
|
|
115
|
+
headers = Object.assign(Object.assign({}, headers), DEFAULT_FETCH_INIT.headers);
|
|
116
|
+
if (init === null || init === void 0 ? void 0 : init.headers)
|
|
117
|
+
headers = Object.assign(Object.assign({}, headers), init.headers);
|
|
118
|
+
if (this.userAgent) {
|
|
119
|
+
headers["User-Agent"] = this.userAgent;
|
|
120
|
+
// chromium browsers have a bug where the user agent can't be modified
|
|
121
|
+
if (typeof window !== "undefined" && "chrome" in window) {
|
|
122
|
+
headers["AssemblyAI-Agent"] =
|
|
123
|
+
this.userAgent;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
init.headers = headers;
|
|
68
127
|
if (!input.startsWith("http"))
|
|
69
128
|
input = this.params.baseUrl + input;
|
|
70
129
|
const response = yield fetch(input, init);
|
|
@@ -75,7 +134,7 @@
|
|
|
75
134
|
try {
|
|
76
135
|
json = JSON.parse(text);
|
|
77
136
|
}
|
|
78
|
-
catch (
|
|
137
|
+
catch (_a) {
|
|
79
138
|
/* empty */
|
|
80
139
|
}
|
|
81
140
|
if (json === null || json === void 0 ? void 0 : json.error)
|
|
@@ -120,6 +179,9 @@
|
|
|
120
179
|
body: JSON.stringify(params),
|
|
121
180
|
});
|
|
122
181
|
}
|
|
182
|
+
getResponse(id) {
|
|
183
|
+
return this.fetchJson(`/lemur/v3/${id}`);
|
|
184
|
+
}
|
|
123
185
|
/**
|
|
124
186
|
* Delete the data for a previously submitted LeMUR request.
|
|
125
187
|
* @param id - ID of the LeMUR request
|
|
@@ -416,6 +478,8 @@
|
|
|
416
478
|
return null;
|
|
417
479
|
if (path.startsWith("https"))
|
|
418
480
|
return null;
|
|
481
|
+
if (path.startsWith("data:"))
|
|
482
|
+
return null;
|
|
419
483
|
if (path.startsWith("file://"))
|
|
420
484
|
return path.substring(7);
|
|
421
485
|
if (path.startsWith("file:"))
|
|
@@ -460,8 +524,13 @@
|
|
|
460
524
|
audioUrl = yield this.files.upload(path);
|
|
461
525
|
}
|
|
462
526
|
else {
|
|
463
|
-
|
|
464
|
-
|
|
527
|
+
if (audio.startsWith("data:")) {
|
|
528
|
+
audioUrl = yield this.files.upload(audio);
|
|
529
|
+
}
|
|
530
|
+
else {
|
|
531
|
+
// audio is not a local path, and not a data-URI, assume it's a normal URL
|
|
532
|
+
audioUrl = audio;
|
|
533
|
+
}
|
|
465
534
|
}
|
|
466
535
|
}
|
|
467
536
|
else {
|
|
@@ -626,13 +695,45 @@
|
|
|
626
695
|
});
|
|
627
696
|
}
|
|
628
697
|
/**
|
|
629
|
-
* Retrieve
|
|
698
|
+
* Retrieve the redacted audio URL of a transcript.
|
|
630
699
|
* @param id - The identifier of the transcript.
|
|
631
|
-
* @returns A promise that resolves to the
|
|
700
|
+
* @returns A promise that resolves to the details of the redacted audio.
|
|
701
|
+
* @deprecated Use `redactedAudio` instead.
|
|
632
702
|
*/
|
|
633
703
|
redactions(id) {
|
|
704
|
+
return this.redactedAudio(id);
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Retrieve the redacted audio URL of a transcript.
|
|
708
|
+
* @param id - The identifier of the transcript.
|
|
709
|
+
* @returns A promise that resolves to the details of the redacted audio.
|
|
710
|
+
*/
|
|
711
|
+
redactedAudio(id) {
|
|
634
712
|
return this.fetchJson(`/v2/transcript/${id}/redacted-audio`);
|
|
635
713
|
}
|
|
714
|
+
/**
|
|
715
|
+
* Retrieve the redacted audio file of a transcript.
|
|
716
|
+
* @param id - The identifier of the transcript.
|
|
717
|
+
* @returns A promise that resolves to the fetch HTTP response of the redacted audio file.
|
|
718
|
+
*/
|
|
719
|
+
redactedAudioFile(id) {
|
|
720
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
721
|
+
const { redacted_audio_url, status } = yield this.redactedAudio(id);
|
|
722
|
+
if (status !== "redacted_audio_ready") {
|
|
723
|
+
throw new Error(`Redacted audio status is ${status}`);
|
|
724
|
+
}
|
|
725
|
+
const response = yield fetch(redacted_audio_url);
|
|
726
|
+
if (!response.ok) {
|
|
727
|
+
throw new Error(`Failed to fetch redacted audio: ${response.statusText}`);
|
|
728
|
+
}
|
|
729
|
+
return {
|
|
730
|
+
arrayBuffer: response.arrayBuffer.bind(response),
|
|
731
|
+
blob: response.blob.bind(response),
|
|
732
|
+
body: response.body,
|
|
733
|
+
bodyUsed: response.bodyUsed,
|
|
734
|
+
};
|
|
735
|
+
});
|
|
736
|
+
}
|
|
636
737
|
}
|
|
637
738
|
function deprecateConformer2(params) {
|
|
638
739
|
if (!params)
|
|
@@ -659,8 +760,14 @@
|
|
|
659
760
|
upload(input) {
|
|
660
761
|
return __awaiter(this, void 0, void 0, function* () {
|
|
661
762
|
let fileData;
|
|
662
|
-
if (typeof input === "string")
|
|
663
|
-
|
|
763
|
+
if (typeof input === "string") {
|
|
764
|
+
if (input.startsWith("data:")) {
|
|
765
|
+
fileData = dataUrlToBlob(input);
|
|
766
|
+
}
|
|
767
|
+
else {
|
|
768
|
+
fileData = yield readFile();
|
|
769
|
+
}
|
|
770
|
+
}
|
|
664
771
|
else
|
|
665
772
|
fileData = input;
|
|
666
773
|
const data = yield this.fetchJson("/v2/upload", {
|
|
@@ -675,6 +782,17 @@
|
|
|
675
782
|
});
|
|
676
783
|
}
|
|
677
784
|
}
|
|
785
|
+
function dataUrlToBlob(dataUrl) {
|
|
786
|
+
const arr = dataUrl.split(",");
|
|
787
|
+
const mime = arr[0].match(/:(.*?);/)[1];
|
|
788
|
+
const bstr = atob(arr[1]);
|
|
789
|
+
let n = bstr.length;
|
|
790
|
+
const u8arr = new Uint8Array(n);
|
|
791
|
+
while (n--) {
|
|
792
|
+
u8arr[n] = bstr.charCodeAt(n);
|
|
793
|
+
}
|
|
794
|
+
return new Blob([u8arr], { type: mime });
|
|
795
|
+
}
|
|
678
796
|
|
|
679
797
|
const defaultBaseUrl = "https://api.assemblyai.com";
|
|
680
798
|
class AssemblyAI {
|
|
@@ -684,8 +802,9 @@
|
|
|
684
802
|
*/
|
|
685
803
|
constructor(params) {
|
|
686
804
|
params.baseUrl = params.baseUrl || defaultBaseUrl;
|
|
687
|
-
if (params.baseUrl && params.baseUrl.endsWith("/"))
|
|
805
|
+
if (params.baseUrl && params.baseUrl.endsWith("/")) {
|
|
688
806
|
params.baseUrl = params.baseUrl.slice(0, -1);
|
|
807
|
+
}
|
|
689
808
|
this.files = new FileService(params);
|
|
690
809
|
this.transcripts = new TranscriptService(params, this.files);
|
|
691
810
|
this.lemur = new LemurService(params);
|