assemblyai 3.1.3 → 4.0.0-beta.1

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.
@@ -0,0 +1,618 @@
1
+ 'use strict';
2
+
3
+ var isomorphicStreams = require('@swimburger/isomorphic-streams');
4
+ var WebSocket = require('isomorphic-ws');
5
+ var fs = require('fs');
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 __rest(s, e) {
25
+ var t = {};
26
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
27
+ t[p] = s[p];
28
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
29
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
30
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
31
+ t[p[i]] = s[p[i]];
32
+ }
33
+ return t;
34
+ }
35
+
36
+ function __awaiter(thisArg, _arguments, P, generator) {
37
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
38
+ return new (P || (P = Promise))(function (resolve, reject) {
39
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
40
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
41
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
42
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
43
+ });
44
+ }
45
+
46
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
47
+ var e = new Error(message);
48
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
49
+ };
50
+
51
+ /**
52
+ * Base class for services that communicate with the API.
53
+ */
54
+ class BaseService {
55
+ /**
56
+ * Create a new service.
57
+ * @param params The parameters to use for the service.
58
+ */
59
+ constructor(params) {
60
+ this.params = params;
61
+ }
62
+ fetch(input, init) {
63
+ var _a;
64
+ return __awaiter(this, void 0, void 0, function* () {
65
+ init = init !== null && init !== void 0 ? init : {};
66
+ init.headers = (_a = init.headers) !== null && _a !== void 0 ? _a : {};
67
+ init.headers = Object.assign({ Authorization: this.params.apiKey, "Content-Type": "application/json" }, init.headers);
68
+ if (!input.startsWith("http"))
69
+ input = this.params.baseUrl + input;
70
+ const response = yield fetch(input, init);
71
+ if (response.status >= 400) {
72
+ let json;
73
+ const text = yield response.text();
74
+ if (text) {
75
+ try {
76
+ json = JSON.parse(text);
77
+ }
78
+ catch (_b) {
79
+ /* empty */
80
+ }
81
+ if (json === null || json === void 0 ? void 0 : json.error)
82
+ throw new Error(json.error);
83
+ throw new Error(text);
84
+ }
85
+ throw new Error(`HTTP Error: ${response.status} ${response.statusText}`);
86
+ }
87
+ return response;
88
+ });
89
+ }
90
+ fetchJson(input, init) {
91
+ return __awaiter(this, void 0, void 0, function* () {
92
+ const response = yield this.fetch(input, init);
93
+ return response.json();
94
+ });
95
+ }
96
+ }
97
+
98
+ class LemurService extends BaseService {
99
+ summary(params) {
100
+ return this.fetchJson("/lemur/v3/generate/summary", {
101
+ method: "POST",
102
+ body: JSON.stringify(params),
103
+ });
104
+ }
105
+ questionAnswer(params) {
106
+ return this.fetchJson("/lemur/v3/generate/question-answer", {
107
+ method: "POST",
108
+ body: JSON.stringify(params),
109
+ });
110
+ }
111
+ actionItems(params) {
112
+ return this.fetchJson("/lemur/v3/generate/action-items", {
113
+ method: "POST",
114
+ body: JSON.stringify(params),
115
+ });
116
+ }
117
+ task(params) {
118
+ return this.fetchJson("/lemur/v3/generate/task", {
119
+ method: "POST",
120
+ body: JSON.stringify(params),
121
+ });
122
+ }
123
+ /**
124
+ * Delete the data for a previously submitted LeMUR request.
125
+ * @param id ID of the LeMUR request
126
+ */
127
+ purgeRequestData(id) {
128
+ return this.fetchJson(`/lemur/v3/${id}`, {
129
+ method: "DELETE",
130
+ });
131
+ }
132
+ }
133
+
134
+ var RealtimeErrorType;
135
+ (function (RealtimeErrorType) {
136
+ RealtimeErrorType[RealtimeErrorType["BadSampleRate"] = 4000] = "BadSampleRate";
137
+ RealtimeErrorType[RealtimeErrorType["AuthFailed"] = 4001] = "AuthFailed";
138
+ // Both InsufficientFunds and FreeAccount error use 4002
139
+ RealtimeErrorType[RealtimeErrorType["InsufficientFundsOrFreeAccount"] = 4002] = "InsufficientFundsOrFreeAccount";
140
+ RealtimeErrorType[RealtimeErrorType["NonexistentSessionId"] = 4004] = "NonexistentSessionId";
141
+ RealtimeErrorType[RealtimeErrorType["SessionExpired"] = 4008] = "SessionExpired";
142
+ RealtimeErrorType[RealtimeErrorType["ClosedSession"] = 4010] = "ClosedSession";
143
+ RealtimeErrorType[RealtimeErrorType["RateLimited"] = 4029] = "RateLimited";
144
+ RealtimeErrorType[RealtimeErrorType["UniqueSessionViolation"] = 4030] = "UniqueSessionViolation";
145
+ RealtimeErrorType[RealtimeErrorType["SessionTimeout"] = 4031] = "SessionTimeout";
146
+ RealtimeErrorType[RealtimeErrorType["AudioTooShort"] = 4032] = "AudioTooShort";
147
+ RealtimeErrorType[RealtimeErrorType["AudioTooLong"] = 4033] = "AudioTooLong";
148
+ RealtimeErrorType[RealtimeErrorType["BadJson"] = 4100] = "BadJson";
149
+ RealtimeErrorType[RealtimeErrorType["BadSchema"] = 4101] = "BadSchema";
150
+ RealtimeErrorType[RealtimeErrorType["TooManyStreams"] = 4102] = "TooManyStreams";
151
+ RealtimeErrorType[RealtimeErrorType["Reconnected"] = 4103] = "Reconnected";
152
+ RealtimeErrorType[RealtimeErrorType["ReconnectAttemptsExhausted"] = 1013] = "ReconnectAttemptsExhausted";
153
+ })(RealtimeErrorType || (RealtimeErrorType = {}));
154
+ const RealtimeErrorMessages = {
155
+ [RealtimeErrorType.BadSampleRate]: "Sample rate must be a positive integer",
156
+ [RealtimeErrorType.AuthFailed]: "Not Authorized",
157
+ [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.",
158
+ [RealtimeErrorType.NonexistentSessionId]: "Session ID does not exist",
159
+ [RealtimeErrorType.SessionExpired]: "Session has expired",
160
+ [RealtimeErrorType.ClosedSession]: "Session is closed",
161
+ [RealtimeErrorType.RateLimited]: "Rate limited",
162
+ [RealtimeErrorType.UniqueSessionViolation]: "Unique session violation",
163
+ [RealtimeErrorType.SessionTimeout]: "Session Timeout",
164
+ [RealtimeErrorType.AudioTooShort]: "Audio too short",
165
+ [RealtimeErrorType.AudioTooLong]: "Audio too long",
166
+ [RealtimeErrorType.BadJson]: "Bad JSON",
167
+ [RealtimeErrorType.BadSchema]: "Bad schema",
168
+ [RealtimeErrorType.TooManyStreams]: "Too many streams",
169
+ [RealtimeErrorType.Reconnected]: "Reconnected",
170
+ [RealtimeErrorType.ReconnectAttemptsExhausted]: "Reconnect attempts exhausted",
171
+ };
172
+ class RealtimeError extends Error {
173
+ }
174
+
175
+ const defaultRealtimeUrl = "wss://api.assemblyai.com/v2/realtime/ws";
176
+ class RealtimeService {
177
+ constructor(params) {
178
+ var _a, _b;
179
+ this.listeners = {};
180
+ this.realtimeUrl = (_a = params.realtimeUrl) !== null && _a !== void 0 ? _a : defaultRealtimeUrl;
181
+ this.sampleRate = (_b = params.sampleRate) !== null && _b !== void 0 ? _b : 16000;
182
+ this.wordBoost = params.wordBoost;
183
+ if ("apiKey" in params && params.apiKey)
184
+ this.apiKey = params.apiKey;
185
+ if ("token" in params && params.token)
186
+ this.token = params.token;
187
+ if (!(this.apiKey || this.token)) {
188
+ throw new Error("API key or temporary token is required.");
189
+ }
190
+ }
191
+ connectionUrl() {
192
+ const url = new URL(this.realtimeUrl);
193
+ if (url.protocol !== "wss:") {
194
+ throw new Error("Invalid protocol, must be wss");
195
+ }
196
+ const searchParams = new URLSearchParams();
197
+ if (this.token) {
198
+ searchParams.set("token", this.token);
199
+ }
200
+ searchParams.set("sample_rate", this.sampleRate.toString());
201
+ if (this.wordBoost && this.wordBoost.length > 0) {
202
+ searchParams.set("word_boost", JSON.stringify(this.wordBoost));
203
+ }
204
+ url.search = searchParams.toString();
205
+ return url;
206
+ }
207
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
208
+ on(event, listener) {
209
+ this.listeners[event] = listener;
210
+ }
211
+ connect() {
212
+ return new Promise((resolve) => {
213
+ if (this.socket) {
214
+ throw new Error("Already connected");
215
+ }
216
+ const url = this.connectionUrl();
217
+ if (this.token) {
218
+ this.socket = new WebSocket(url.toString());
219
+ }
220
+ else {
221
+ this.socket = new WebSocket(url.toString(), {
222
+ headers: { Authorization: this.apiKey },
223
+ });
224
+ }
225
+ this.socket.onclose = ({ code, reason }) => {
226
+ var _a, _b;
227
+ if (!reason) {
228
+ if (code in RealtimeErrorType) {
229
+ reason = RealtimeErrorMessages[code];
230
+ }
231
+ }
232
+ (_b = (_a = this.listeners).close) === null || _b === void 0 ? void 0 : _b.call(_a, code, reason);
233
+ };
234
+ this.socket.onerror = (event) => {
235
+ var _a, _b, _c, _d;
236
+ if (event.error)
237
+ (_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, event.error);
238
+ else
239
+ (_d = (_c = this.listeners).error) === null || _d === void 0 ? void 0 : _d.call(_c, new Error(event.message));
240
+ };
241
+ this.socket.onmessage = ({ data }) => {
242
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
243
+ const message = JSON.parse(data.toString());
244
+ if ("error" in message) {
245
+ (_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, new RealtimeError(message.error));
246
+ return;
247
+ }
248
+ switch (message.message_type) {
249
+ case "SessionBegins": {
250
+ const openObject = {
251
+ sessionId: message.session_id,
252
+ expiresAt: new Date(message.expires_at),
253
+ };
254
+ resolve(openObject);
255
+ (_d = (_c = this.listeners).open) === null || _d === void 0 ? void 0 : _d.call(_c, openObject);
256
+ break;
257
+ }
258
+ case "PartialTranscript": {
259
+ // message.created is actually a string when coming from the socket
260
+ message.created = new Date(message.created);
261
+ (_f = (_e = this.listeners).transcript) === null || _f === void 0 ? void 0 : _f.call(_e, message);
262
+ (_h = (_g = this.listeners)["transcript.partial"]) === null || _h === void 0 ? void 0 : _h.call(_g, message);
263
+ break;
264
+ }
265
+ case "FinalTranscript": {
266
+ // message.created is actually a string when coming from the socket
267
+ message.created = new Date(message.created);
268
+ (_k = (_j = this.listeners).transcript) === null || _k === void 0 ? void 0 : _k.call(_j, message);
269
+ (_m = (_l = this.listeners)["transcript.final"]) === null || _m === void 0 ? void 0 : _m.call(_l, message);
270
+ break;
271
+ }
272
+ case "SessionTerminated": {
273
+ (_o = this.sessionTerminatedResolve) === null || _o === void 0 ? void 0 : _o.call(this);
274
+ break;
275
+ }
276
+ }
277
+ };
278
+ });
279
+ }
280
+ sendAudio(audio) {
281
+ if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
282
+ throw new Error("Socket is not open for communication");
283
+ }
284
+ let audioData;
285
+ if (typeof Buffer !== "undefined") {
286
+ audioData = Buffer.from(audio).toString("base64");
287
+ }
288
+ else {
289
+ // Buffer is not available in the browser by default
290
+ // https://stackoverflow.com/a/42334410/2919731
291
+ audioData = btoa(new Uint8Array(audio).reduce((data, byte) => data + String.fromCharCode(byte), ""));
292
+ }
293
+ const payload = {
294
+ audio_data: audioData,
295
+ };
296
+ this.socket.send(JSON.stringify(payload));
297
+ }
298
+ stream() {
299
+ return new isomorphicStreams.WritableStream({
300
+ write: (chunk) => {
301
+ this.sendAudio(chunk);
302
+ },
303
+ });
304
+ }
305
+ close(waitForSessionTermination = true) {
306
+ return __awaiter(this, void 0, void 0, function* () {
307
+ if (this.socket) {
308
+ if (this.socket.readyState === WebSocket.OPEN) {
309
+ const terminateSessionMessage = `{"terminate_session": true}`;
310
+ if (waitForSessionTermination) {
311
+ const sessionTerminatedPromise = new Promise((resolve) => {
312
+ this.sessionTerminatedResolve = resolve;
313
+ });
314
+ this.socket.send(terminateSessionMessage);
315
+ yield sessionTerminatedPromise;
316
+ }
317
+ else {
318
+ this.socket.send(terminateSessionMessage);
319
+ }
320
+ }
321
+ if ("removeAllListeners" in this.socket)
322
+ this.socket.removeAllListeners();
323
+ this.socket.close();
324
+ }
325
+ this.listeners = {};
326
+ this.socket = undefined;
327
+ });
328
+ }
329
+ }
330
+
331
+ class RealtimeServiceFactory extends BaseService {
332
+ constructor(params) {
333
+ super(params);
334
+ this.rtFactoryParams = params;
335
+ }
336
+ createService(params) {
337
+ if (!params)
338
+ params = { apiKey: this.rtFactoryParams.apiKey };
339
+ else if (!("token" in params) && !params.apiKey) {
340
+ params.apiKey = this.rtFactoryParams.apiKey;
341
+ }
342
+ return new RealtimeService(params);
343
+ }
344
+ createTemporaryToken(params) {
345
+ return __awaiter(this, void 0, void 0, function* () {
346
+ const data = yield this.fetchJson("/v2/realtime/token", {
347
+ method: "POST",
348
+ body: JSON.stringify(params),
349
+ });
350
+ return data.token;
351
+ });
352
+ }
353
+ }
354
+
355
+ class TranscriptService extends BaseService {
356
+ constructor(params, files) {
357
+ super(params);
358
+ this.files = files;
359
+ }
360
+ /**
361
+ * Transcribe an audio file. This will create a transcript and wait until the transcript status is "completed" or "error".
362
+ * @param params The parameters to transcribe an audio file.
363
+ * @param options The options to transcribe an audio file.
364
+ * @returns A promise that resolves to the transcript. The transcript status is "completed" or "error".
365
+ */
366
+ transcribe(params, options) {
367
+ return __awaiter(this, void 0, void 0, function* () {
368
+ const transcript = yield this.submit(params);
369
+ return yield this.waitUntilReady(transcript.id, options);
370
+ });
371
+ }
372
+ /**
373
+ * Submits a transcription job for an audio file. This will not wait until the transcript status is "completed" or "error".
374
+ * @param params The parameters to start the transcription of an audio file.
375
+ * @returns A promise that resolves to the queued transcript.
376
+ */
377
+ submit(params) {
378
+ return __awaiter(this, void 0, void 0, function* () {
379
+ const { audio } = params, createParams = __rest(params, ["audio"]);
380
+ let audioUrl;
381
+ if (typeof audio === "string") {
382
+ const path = getPath(audio);
383
+ if (path !== null) {
384
+ // audio is local path, upload local file
385
+ audioUrl = yield this.files.upload(path);
386
+ }
387
+ else {
388
+ // audio is not a local path, assume it's a URL
389
+ audioUrl = audio;
390
+ }
391
+ }
392
+ else {
393
+ // audio is of uploadable type
394
+ audioUrl = yield this.files.upload(audio);
395
+ }
396
+ const data = yield this.fetchJson("/v2/transcript", {
397
+ method: "POST",
398
+ body: JSON.stringify(Object.assign(Object.assign({}, createParams), { audio_url: audioUrl })),
399
+ });
400
+ return data;
401
+ });
402
+ }
403
+ /**
404
+ * Create a transcript.
405
+ * @param params The parameters to create a transcript.
406
+ * @param options The options used for creating the new transcript.
407
+ * @returns A promise that resolves to the transcript.
408
+ * @deprecated Use `transcribe` instead to transcribe a audio file that includes polling, or `submit` to transcribe a audio file without polling.
409
+ */
410
+ create(params, options) {
411
+ var _a;
412
+ return __awaiter(this, void 0, void 0, function* () {
413
+ const path = getPath(params.audio_url);
414
+ if (path !== null) {
415
+ const uploadUrl = yield this.files.upload(path);
416
+ params.audio_url = uploadUrl;
417
+ }
418
+ const data = yield this.fetchJson("/v2/transcript", {
419
+ method: "POST",
420
+ body: JSON.stringify(params),
421
+ });
422
+ if ((_a = options === null || options === void 0 ? void 0 : options.poll) !== null && _a !== void 0 ? _a : true) {
423
+ return yield this.waitUntilReady(data.id, options);
424
+ }
425
+ return data;
426
+ });
427
+ }
428
+ /**
429
+ * Wait until the transcript ready, either the status is "completed" or "error".
430
+ * @param transcriptId The ID of the transcript.
431
+ * @param options The options to wait until the transcript is ready.
432
+ * @returns A promise that resolves to the transcript. The transcript status is "completed" or "error".
433
+ */
434
+ waitUntilReady(transcriptId, options) {
435
+ var _a, _b;
436
+ return __awaiter(this, void 0, void 0, function* () {
437
+ const pollingInterval = (_a = options === null || options === void 0 ? void 0 : options.pollingInterval) !== null && _a !== void 0 ? _a : 3000;
438
+ const pollingTimeout = (_b = options === null || options === void 0 ? void 0 : options.pollingTimeout) !== null && _b !== void 0 ? _b : -1;
439
+ const startTime = Date.now();
440
+ // eslint-disable-next-line no-constant-condition
441
+ while (true) {
442
+ const transcript = yield this.get(transcriptId);
443
+ if (transcript.status === "completed" || transcript.status === "error") {
444
+ return transcript;
445
+ }
446
+ else if (pollingTimeout > 0 &&
447
+ Date.now() - startTime > pollingTimeout) {
448
+ throw new Error("Polling timeout");
449
+ }
450
+ else {
451
+ yield new Promise((resolve) => setTimeout(resolve, pollingInterval));
452
+ }
453
+ }
454
+ });
455
+ }
456
+ /**
457
+ * Retrieve a transcript.
458
+ * @param id The identifier of the transcript.
459
+ * @returns A promise that resolves to the transcript.
460
+ */
461
+ get(id) {
462
+ return this.fetchJson(`/v2/transcript/${id}`);
463
+ }
464
+ /**
465
+ * Retrieves a page of transcript listings.
466
+ * @param parameters The parameters to filter the transcript list by, or the URL to retrieve the transcript list from.
467
+ */
468
+ list(parameters) {
469
+ return __awaiter(this, void 0, void 0, function* () {
470
+ let url = "/v2/transcript";
471
+ if (typeof parameters === "string") {
472
+ url = parameters;
473
+ }
474
+ else if (parameters) {
475
+ url = `${url}?${new URLSearchParams(Object.keys(parameters).map((key) => {
476
+ var _a;
477
+ return [
478
+ key,
479
+ ((_a = parameters[key]) === null || _a === void 0 ? void 0 : _a.toString()) || "",
480
+ ];
481
+ }))}`;
482
+ }
483
+ const data = yield this.fetchJson(url);
484
+ for (const transcriptListItem of data.transcripts) {
485
+ transcriptListItem.created = new Date(transcriptListItem.created);
486
+ if (transcriptListItem.completed) {
487
+ transcriptListItem.completed = new Date(transcriptListItem.completed);
488
+ }
489
+ }
490
+ return data;
491
+ });
492
+ }
493
+ /**
494
+ * Delete a transcript
495
+ * @param id The identifier of the transcript.
496
+ * @returns A promise that resolves to the transcript.
497
+ */
498
+ delete(id) {
499
+ return this.fetchJson(`/v2/transcript/${id}`, { method: "DELETE" });
500
+ }
501
+ /**
502
+ * Search through the transcript for a specific set of keywords.
503
+ * You can search for individual words, numbers, or phrases containing up to five words or numbers.
504
+ * @param id The identifier of the transcript.
505
+ * @param words Keywords to search for.
506
+ * @return A promise that resolves to the sentences.
507
+ */
508
+ wordSearch(id, words) {
509
+ const params = new URLSearchParams({ words: words.join(",") });
510
+ return this.fetchJson(`/v2/transcript/${id}/word-search?${params.toString()}`);
511
+ }
512
+ /**
513
+ * Retrieve all sentences of a transcript.
514
+ * @param id The identifier of the transcript.
515
+ * @return A promise that resolves to the sentences.
516
+ */
517
+ sentences(id) {
518
+ return this.fetchJson(`/v2/transcript/${id}/sentences`);
519
+ }
520
+ /**
521
+ * Retrieve all paragraphs of a transcript.
522
+ * @param id The identifier of the transcript.
523
+ * @return A promise that resolves to the paragraphs.
524
+ */
525
+ paragraphs(id) {
526
+ return this.fetchJson(`/v2/transcript/${id}/paragraphs`);
527
+ }
528
+ /**
529
+ * Retrieve subtitles of a transcript.
530
+ * @param id The identifier of the transcript.
531
+ * @param format The format of the subtitles.
532
+ * @param chars_per_caption The maximum number of characters per caption.
533
+ * @return A promise that resolves to the subtitles text.
534
+ */
535
+ subtitles(id, format = "srt", chars_per_caption) {
536
+ return __awaiter(this, void 0, void 0, function* () {
537
+ let url = `/v2/transcript/${id}/${format}`;
538
+ if (chars_per_caption) {
539
+ const params = new URLSearchParams();
540
+ params.set("chars_per_caption", chars_per_caption.toString());
541
+ url += `?${params.toString()}`;
542
+ }
543
+ const response = yield this.fetch(url);
544
+ return yield response.text();
545
+ });
546
+ }
547
+ /**
548
+ * Retrieve redactions of a transcript.
549
+ * @param id The identifier of the transcript.
550
+ * @return A promise that resolves to the subtitles text.
551
+ */
552
+ redactions(id) {
553
+ return this.fetchJson(`/v2/transcript/${id}/redacted-audio`);
554
+ }
555
+ }
556
+ function getPath(path) {
557
+ let url;
558
+ try {
559
+ url = new URL(path);
560
+ if (url.protocol === "file:")
561
+ return url.pathname;
562
+ else
563
+ return null;
564
+ }
565
+ catch (_a) {
566
+ return path;
567
+ }
568
+ }
569
+
570
+ class FileService extends BaseService {
571
+ /**
572
+ * Upload a local file to AssemblyAI.
573
+ * @param input The local file path to upload, or a stream or buffer of the file to upload.
574
+ * @return A promise that resolves to the uploaded file URL.
575
+ */
576
+ upload(input) {
577
+ return __awaiter(this, void 0, void 0, function* () {
578
+ let fileData;
579
+ if (typeof input === "string")
580
+ fileData = fs.createReadStream(input);
581
+ else
582
+ fileData = input;
583
+ const data = yield this.fetchJson("/v2/upload", {
584
+ method: "POST",
585
+ body: fileData,
586
+ headers: {
587
+ "Content-Type": "application/octet-stream",
588
+ },
589
+ duplex: "half",
590
+ });
591
+ return data.upload_url;
592
+ });
593
+ }
594
+ }
595
+
596
+ const defaultBaseUrl = "https://api.assemblyai.com";
597
+ class AssemblyAI {
598
+ /**
599
+ * Create a new AssemblyAI client.
600
+ * @param params The parameters for the service, including the API key and base URL, if any.
601
+ */
602
+ constructor(params) {
603
+ params.baseUrl = params.baseUrl || defaultBaseUrl;
604
+ if (params.baseUrl && params.baseUrl.endsWith("/"))
605
+ params.baseUrl = params.baseUrl.slice(0, -1);
606
+ this.files = new FileService(params);
607
+ this.transcripts = new TranscriptService(params, this.files);
608
+ this.lemur = new LemurService(params);
609
+ this.realtime = new RealtimeServiceFactory(params);
610
+ }
611
+ }
612
+
613
+ exports.AssemblyAI = AssemblyAI;
614
+ exports.FileService = FileService;
615
+ exports.LemurService = LemurService;
616
+ exports.RealtimeService = RealtimeService;
617
+ exports.RealtimeServiceFactory = RealtimeServiceFactory;
618
+ exports.TranscriptService = TranscriptService;