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/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,48 @@
|
|
|
1
1
|
# Changelog
|
|
2
|
+
|
|
3
|
+
## [4.6.0]
|
|
4
|
+
|
|
5
|
+
- Add more TSDoc comments for `RealtimeService` documentation
|
|
6
|
+
- Add new LeMUR models
|
|
7
|
+
- Add `TranscriptWebhookNotification` which is a union of `TranscriptReadyNotification` or `RedactedAudioNotification`
|
|
8
|
+
- Add `RedactedAudioNotification` which represents the body of the PII redacted audio webhook notification.
|
|
9
|
+
|
|
2
10
|
## [4.5.0]
|
|
3
11
|
|
|
12
|
+
- You can now retrieve previous LeMUR responses using `client.lemur.getResponse<LemurTask>("YOUR_REQUEST_ID")`.
|
|
13
|
+
- LeMUR functions now return `usage` with the number of `input_tokens` and `output_tokens`.
|
|
14
|
+
|
|
15
|
+
## [4.4.7]
|
|
16
|
+
|
|
17
|
+
- Rename `TranscriptService.redactions` function to `TranscriptService.redactedAudio`.
|
|
18
|
+
- Add `TranscriptService.redactedAudioFile` function.
|
|
19
|
+
- Add `workerd` export to fix `cache` issue with `fetch` on Cloudflare Workers.
|
|
20
|
+
|
|
21
|
+
## [4.4.6]
|
|
22
|
+
|
|
23
|
+
- Fix Rollup exports so \_\_SDK_VERSION\_\_ is properly replaced with the version of the SDK.
|
|
24
|
+
|
|
25
|
+
## [4.4.5]
|
|
26
|
+
|
|
27
|
+
- Add new `PiiPolicy` enum values
|
|
28
|
+
|
|
29
|
+
## [4.4.4]
|
|
30
|
+
|
|
31
|
+
- Add an export that only includes the Streaming STT code. You can use the export
|
|
32
|
+
- by importing `assemblyai/streaming`,
|
|
33
|
+
- or by loading the `assemblyai.streaming.umd.js` file, or `assemblyai.streaming.umd.min.js` file in a script-tag.
|
|
34
|
+
- Add new `EntityType` enum values
|
|
35
|
+
|
|
36
|
+
## [4.4.3] - 2024-05-09
|
|
37
|
+
|
|
38
|
+
- Add react-native exports that resolve to the browser version of the library.
|
|
39
|
+
|
|
40
|
+
## [4.4.2] - 2024-05-03
|
|
41
|
+
|
|
4
42
|
### Changed
|
|
43
|
+
|
|
44
|
+
- Caching is disabled for all HTTP request made by the SDK
|
|
45
|
+
- Accept data-URIs in `client.files.upload(dataUri)`, `client.transcripts.submit(audio: dataUri)`, `client.transcripts.transcribe(audio: dataUri)`.
|
|
5
46
|
- Change how the WebSocket libraries are imported for better compatibility across frameworks and runtimes.
|
|
6
47
|
The library no longer relies on a internal `#ws` import, and instead compiles the imports into the dist bundles.
|
|
7
48
|
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,317 @@
|
|
|
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
|
+
/**
|
|
99
|
+
* RealtimeTranscriber connects to the Streaming Speech-to-Text API and lets you transcribe audio in real-time.
|
|
100
|
+
*/
|
|
101
|
+
class RealtimeTranscriber {
|
|
102
|
+
/**
|
|
103
|
+
* Create a new RealtimeTranscriber.
|
|
104
|
+
* @param params - Parameters to configure the RealtimeTranscriber
|
|
105
|
+
*/
|
|
106
|
+
constructor(params) {
|
|
107
|
+
var _a, _b;
|
|
108
|
+
this.listeners = {};
|
|
109
|
+
this.realtimeUrl = (_a = params.realtimeUrl) !== null && _a !== void 0 ? _a : defaultRealtimeUrl;
|
|
110
|
+
this.sampleRate = (_b = params.sampleRate) !== null && _b !== void 0 ? _b : 16000;
|
|
111
|
+
this.wordBoost = params.wordBoost;
|
|
112
|
+
this.encoding = params.encoding;
|
|
113
|
+
this.endUtteranceSilenceThreshold = params.endUtteranceSilenceThreshold;
|
|
114
|
+
this.disablePartialTranscripts = params.disablePartialTranscripts;
|
|
115
|
+
if ("token" in params && params.token)
|
|
116
|
+
this.token = params.token;
|
|
117
|
+
if ("apiKey" in params && params.apiKey)
|
|
118
|
+
this.apiKey = params.apiKey;
|
|
119
|
+
if (!(this.token || this.apiKey)) {
|
|
120
|
+
throw new Error("API key or temporary token is required.");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
connectionUrl() {
|
|
124
|
+
const url = new URL(this.realtimeUrl);
|
|
125
|
+
if (url.protocol !== "wss:") {
|
|
126
|
+
throw new Error("Invalid protocol, must be wss");
|
|
127
|
+
}
|
|
128
|
+
const searchParams = new URLSearchParams();
|
|
129
|
+
if (this.token) {
|
|
130
|
+
searchParams.set("token", this.token);
|
|
131
|
+
}
|
|
132
|
+
searchParams.set("sample_rate", this.sampleRate.toString());
|
|
133
|
+
if (this.wordBoost && this.wordBoost.length > 0) {
|
|
134
|
+
searchParams.set("word_boost", JSON.stringify(this.wordBoost));
|
|
135
|
+
}
|
|
136
|
+
if (this.encoding) {
|
|
137
|
+
searchParams.set("encoding", this.encoding);
|
|
138
|
+
}
|
|
139
|
+
searchParams.set("enable_extra_session_information", "true");
|
|
140
|
+
if (this.disablePartialTranscripts) {
|
|
141
|
+
searchParams.set("disable_partial_transcripts", this.disablePartialTranscripts.toString());
|
|
142
|
+
}
|
|
143
|
+
url.search = searchParams.toString();
|
|
144
|
+
return url;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Add a listener for an event.
|
|
148
|
+
* @param event - The event to listen for.
|
|
149
|
+
* @param listener - The function to call when the event is emitted.
|
|
150
|
+
*/
|
|
151
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
152
|
+
on(event, listener) {
|
|
153
|
+
this.listeners[event] = listener;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Connect to the server and begin a new session.
|
|
157
|
+
* @returns A promise that resolves when the connection is established and the session begins.
|
|
158
|
+
*/
|
|
159
|
+
connect() {
|
|
160
|
+
return new Promise((resolve) => {
|
|
161
|
+
if (this.socket) {
|
|
162
|
+
throw new Error("Already connected");
|
|
163
|
+
}
|
|
164
|
+
const url = this.connectionUrl();
|
|
165
|
+
if (this.token) {
|
|
166
|
+
this.socket = factory(url.toString());
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
this.socket = factory(url.toString(), {
|
|
170
|
+
headers: { Authorization: this.apiKey },
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
this.socket.binaryType = "arraybuffer";
|
|
174
|
+
this.socket.onopen = () => {
|
|
175
|
+
if (this.endUtteranceSilenceThreshold === undefined ||
|
|
176
|
+
this.endUtteranceSilenceThreshold === null) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
this.configureEndUtteranceSilenceThreshold(this.endUtteranceSilenceThreshold);
|
|
180
|
+
};
|
|
181
|
+
this.socket.onclose = ({ code, reason }) => {
|
|
182
|
+
var _a, _b;
|
|
183
|
+
if (!reason) {
|
|
184
|
+
if (code in RealtimeErrorType) {
|
|
185
|
+
reason = RealtimeErrorMessages[code];
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
(_b = (_a = this.listeners).close) === null || _b === void 0 ? void 0 : _b.call(_a, code, reason);
|
|
189
|
+
};
|
|
190
|
+
this.socket.onerror = (event) => {
|
|
191
|
+
var _a, _b, _c, _d;
|
|
192
|
+
if (event.error)
|
|
193
|
+
(_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, event.error);
|
|
194
|
+
else
|
|
195
|
+
(_d = (_c = this.listeners).error) === null || _d === void 0 ? void 0 : _d.call(_c, new Error(event.message));
|
|
196
|
+
};
|
|
197
|
+
this.socket.onmessage = ({ data }) => {
|
|
198
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
199
|
+
const message = JSON.parse(data.toString());
|
|
200
|
+
if ("error" in message) {
|
|
201
|
+
(_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, new RealtimeError(message.error));
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
switch (message.message_type) {
|
|
205
|
+
case "SessionBegins": {
|
|
206
|
+
const openObject = {
|
|
207
|
+
sessionId: message.session_id,
|
|
208
|
+
expiresAt: new Date(message.expires_at),
|
|
209
|
+
};
|
|
210
|
+
resolve(openObject);
|
|
211
|
+
(_d = (_c = this.listeners).open) === null || _d === void 0 ? void 0 : _d.call(_c, openObject);
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
case "PartialTranscript": {
|
|
215
|
+
// message.created is actually a string when coming from the socket
|
|
216
|
+
message.created = new Date(message.created);
|
|
217
|
+
(_f = (_e = this.listeners).transcript) === null || _f === void 0 ? void 0 : _f.call(_e, message);
|
|
218
|
+
(_h = (_g = this.listeners)["transcript.partial"]) === null || _h === void 0 ? void 0 : _h.call(_g, message);
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
case "FinalTranscript": {
|
|
222
|
+
// message.created is actually a string when coming from the socket
|
|
223
|
+
message.created = new Date(message.created);
|
|
224
|
+
(_k = (_j = this.listeners).transcript) === null || _k === void 0 ? void 0 : _k.call(_j, message);
|
|
225
|
+
(_m = (_l = this.listeners)["transcript.final"]) === null || _m === void 0 ? void 0 : _m.call(_l, message);
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
case "SessionInformation": {
|
|
229
|
+
(_p = (_o = this.listeners).session_information) === null || _p === void 0 ? void 0 : _p.call(_o, message);
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
case "SessionTerminated": {
|
|
233
|
+
(_q = this.sessionTerminatedResolve) === null || _q === void 0 ? void 0 : _q.call(this);
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Send audio data to the server.
|
|
242
|
+
* @param audio - The audio data to send to the server.
|
|
243
|
+
*/
|
|
244
|
+
sendAudio(audio) {
|
|
245
|
+
this.send(audio);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Create a writable stream that can be used to send audio data to the server.
|
|
249
|
+
* @returns A writable stream that can be used to send audio data to the server.
|
|
250
|
+
*/
|
|
251
|
+
stream() {
|
|
252
|
+
return new WritableStream({
|
|
253
|
+
write: (chunk) => {
|
|
254
|
+
this.sendAudio(chunk);
|
|
255
|
+
},
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Manually end an utterance
|
|
260
|
+
*/
|
|
261
|
+
forceEndUtterance() {
|
|
262
|
+
this.send(forceEndOfUtteranceMessage);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Configure the threshold for how long to wait before ending an utterance. Default is 700ms.
|
|
266
|
+
* @param threshold - The duration of the end utterance silence threshold in milliseconds.
|
|
267
|
+
* This value must be an integer between 0 and 20_000.
|
|
268
|
+
*/
|
|
269
|
+
configureEndUtteranceSilenceThreshold(threshold) {
|
|
270
|
+
this.send(`{"end_utterance_silence_threshold":${threshold}}`);
|
|
271
|
+
}
|
|
272
|
+
send(data) {
|
|
273
|
+
if (!this.socket || this.socket.readyState !== this.socket.OPEN) {
|
|
274
|
+
throw new Error("Socket is not open for communication");
|
|
275
|
+
}
|
|
276
|
+
this.socket.send(data);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Close the connection to the server.
|
|
280
|
+
* @param waitForSessionTermination - If true, the method will wait for the session to be terminated before closing the connection.
|
|
281
|
+
* While waiting for the session to be terminated, you will receive the final transcript and session information.
|
|
282
|
+
*/
|
|
283
|
+
close() {
|
|
284
|
+
return __awaiter(this, arguments, void 0, function* (waitForSessionTermination = true) {
|
|
285
|
+
var _a;
|
|
286
|
+
if (this.socket) {
|
|
287
|
+
if (this.socket.readyState === this.socket.OPEN) {
|
|
288
|
+
if (waitForSessionTermination) {
|
|
289
|
+
const sessionTerminatedPromise = new Promise((resolve) => {
|
|
290
|
+
this.sessionTerminatedResolve = resolve;
|
|
291
|
+
});
|
|
292
|
+
this.socket.send(terminateSessionMessage);
|
|
293
|
+
yield sessionTerminatedPromise;
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
this.socket.send(terminateSessionMessage);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.removeAllListeners)
|
|
300
|
+
this.socket.removeAllListeners();
|
|
301
|
+
this.socket.close();
|
|
302
|
+
}
|
|
303
|
+
this.listeners = {};
|
|
304
|
+
this.socket = undefined;
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* @deprecated Use RealtimeTranscriber instead
|
|
310
|
+
*/
|
|
311
|
+
class RealtimeService extends RealtimeTranscriber {
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
exports.RealtimeService = RealtimeService;
|
|
315
|
+
exports.RealtimeTranscriber = RealtimeTranscriber;
|
|
316
|
+
|
|
317
|
+
}));
|
|
@@ -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}));
|