assemblyai 4.4.1 → 4.4.2-beta.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/dist/bun.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import WebSocket from '#ws';
1
+ import ws from 'ws';
2
2
 
3
3
  /**
4
4
  * Base class for services that communicate with the API.
@@ -19,6 +19,7 @@ class BaseService {
19
19
  "Content-Type": "application/json",
20
20
  ...init.headers,
21
21
  };
22
+ init.cache = "no-store";
22
23
  if (!input.startsWith("http"))
23
24
  input = this.params.baseUrl + input;
24
25
  const response = await fetch(input, init);
@@ -88,6 +89,8 @@ const { WritableStream } = typeof window !== "undefined"
88
89
  ? global
89
90
  : globalThis;
90
91
 
92
+ const factory = (url, params) => new ws(url, params);
93
+
91
94
  var RealtimeErrorType;
92
95
  (function (RealtimeErrorType) {
93
96
  RealtimeErrorType[RealtimeErrorType["BadSampleRate"] = 4000] = "BadSampleRate";
@@ -183,10 +186,10 @@ class RealtimeTranscriber {
183
186
  }
184
187
  const url = this.connectionUrl();
185
188
  if (this.token) {
186
- this.socket = new WebSocket(url.toString());
189
+ this.socket = factory(url.toString());
187
190
  }
188
191
  else {
189
- this.socket = new WebSocket(url.toString(), {
192
+ this.socket = factory(url.toString(), {
190
193
  headers: { Authorization: this.apiKey },
191
194
  });
192
195
  }
@@ -279,14 +282,14 @@ class RealtimeTranscriber {
279
282
  this.send(`{"end_utterance_silence_threshold":${threshold}}`);
280
283
  }
281
284
  send(data) {
282
- if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
285
+ if (!this.socket || this.socket.readyState !== this.socket.OPEN) {
283
286
  throw new Error("Socket is not open for communication");
284
287
  }
285
288
  this.socket.send(data);
286
289
  }
287
290
  async close(waitForSessionTermination = true) {
288
291
  if (this.socket) {
289
- if (this.socket.readyState === WebSocket.OPEN) {
292
+ if (this.socket.readyState === this.socket.OPEN) {
290
293
  if (waitForSessionTermination) {
291
294
  const sessionTerminatedPromise = new Promise((resolve) => {
292
295
  this.sessionTerminatedResolve = resolve;
@@ -298,7 +301,7 @@ class RealtimeTranscriber {
298
301
  this.socket.send(terminateSessionMessage);
299
302
  }
300
303
  }
301
- if ("removeAllListeners" in this.socket)
304
+ if (this.socket?.removeAllListeners)
302
305
  this.socket.removeAllListeners();
303
306
  this.socket.close();
304
307
  }
@@ -349,6 +352,8 @@ function getPath(path) {
349
352
  return null;
350
353
  if (path.startsWith("https"))
351
354
  return null;
355
+ if (path.startsWith("data:"))
356
+ return null;
352
357
  if (path.startsWith("file://"))
353
358
  return path.substring(7);
354
359
  if (path.startsWith("file:"))
@@ -390,8 +395,13 @@ class TranscriptService extends BaseService {
390
395
  audioUrl = await this.files.upload(path);
391
396
  }
392
397
  else {
393
- // audio is not a local path, assume it's a URL
394
- audioUrl = audio;
398
+ if (audio.startsWith("data:")) {
399
+ audioUrl = await this.files.upload(audio);
400
+ }
401
+ else {
402
+ // audio is not a local path, and not a data-URI, assume it's a normal URL
403
+ audioUrl = audio;
404
+ }
395
405
  }
396
406
  }
397
407
  else {
@@ -568,8 +578,14 @@ class FileService extends BaseService {
568
578
  */
569
579
  async upload(input) {
570
580
  let fileData;
571
- if (typeof input === "string")
572
- fileData = await readFile(input);
581
+ if (typeof input === "string") {
582
+ if (input.startsWith("data:")) {
583
+ fileData = dataUrlToBlob(input);
584
+ }
585
+ else {
586
+ fileData = await readFile(input);
587
+ }
588
+ }
573
589
  else
574
590
  fileData = input;
575
591
  const data = await this.fetchJson("/v2/upload", {
@@ -583,6 +599,17 @@ class FileService extends BaseService {
583
599
  return data.upload_url;
584
600
  }
585
601
  }
602
+ function dataUrlToBlob(dataUrl) {
603
+ const arr = dataUrl.split(",");
604
+ const mime = arr[0].match(/:(.*?);/)[1];
605
+ const bstr = atob(arr[1]);
606
+ let n = bstr.length;
607
+ const u8arr = new Uint8Array(n);
608
+ while (n--) {
609
+ u8arr[n] = bstr.charCodeAt(n);
610
+ }
611
+ return new Blob([u8arr], { type: mime });
612
+ }
586
613
 
587
614
  const defaultBaseUrl = "https://api.assemblyai.com";
588
615
  class AssemblyAI {
package/dist/deno.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import WebSocket from '#ws';
1
+ import ws from 'ws';
2
2
 
3
3
  /**
4
4
  * Base class for services that communicate with the API.
@@ -19,6 +19,7 @@ class BaseService {
19
19
  "Content-Type": "application/json",
20
20
  ...init.headers,
21
21
  };
22
+ init.cache = "no-store";
22
23
  if (!input.startsWith("http"))
23
24
  input = this.params.baseUrl + input;
24
25
  const response = await fetch(input, init);
@@ -88,6 +89,8 @@ const { WritableStream } = typeof window !== "undefined"
88
89
  ? global
89
90
  : globalThis;
90
91
 
92
+ const factory = (url, params) => new ws(url, params);
93
+
91
94
  var RealtimeErrorType;
92
95
  (function (RealtimeErrorType) {
93
96
  RealtimeErrorType[RealtimeErrorType["BadSampleRate"] = 4000] = "BadSampleRate";
@@ -183,10 +186,10 @@ class RealtimeTranscriber {
183
186
  }
184
187
  const url = this.connectionUrl();
185
188
  if (this.token) {
186
- this.socket = new WebSocket(url.toString());
189
+ this.socket = factory(url.toString());
187
190
  }
188
191
  else {
189
- this.socket = new WebSocket(url.toString(), {
192
+ this.socket = factory(url.toString(), {
190
193
  headers: { Authorization: this.apiKey },
191
194
  });
192
195
  }
@@ -279,14 +282,14 @@ class RealtimeTranscriber {
279
282
  this.send(`{"end_utterance_silence_threshold":${threshold}}`);
280
283
  }
281
284
  send(data) {
282
- if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
285
+ if (!this.socket || this.socket.readyState !== this.socket.OPEN) {
283
286
  throw new Error("Socket is not open for communication");
284
287
  }
285
288
  this.socket.send(data);
286
289
  }
287
290
  async close(waitForSessionTermination = true) {
288
291
  if (this.socket) {
289
- if (this.socket.readyState === WebSocket.OPEN) {
292
+ if (this.socket.readyState === this.socket.OPEN) {
290
293
  if (waitForSessionTermination) {
291
294
  const sessionTerminatedPromise = new Promise((resolve) => {
292
295
  this.sessionTerminatedResolve = resolve;
@@ -298,7 +301,7 @@ class RealtimeTranscriber {
298
301
  this.socket.send(terminateSessionMessage);
299
302
  }
300
303
  }
301
- if ("removeAllListeners" in this.socket)
304
+ if (this.socket?.removeAllListeners)
302
305
  this.socket.removeAllListeners();
303
306
  this.socket.close();
304
307
  }
@@ -349,6 +352,8 @@ function getPath(path) {
349
352
  return null;
350
353
  if (path.startsWith("https"))
351
354
  return null;
355
+ if (path.startsWith("data:"))
356
+ return null;
352
357
  if (path.startsWith("file://"))
353
358
  return path.substring(7);
354
359
  if (path.startsWith("file:"))
@@ -390,8 +395,13 @@ class TranscriptService extends BaseService {
390
395
  audioUrl = await this.files.upload(path);
391
396
  }
392
397
  else {
393
- // audio is not a local path, assume it's a URL
394
- audioUrl = audio;
398
+ if (audio.startsWith("data:")) {
399
+ audioUrl = await this.files.upload(audio);
400
+ }
401
+ else {
402
+ // audio is not a local path, and not a data-URI, assume it's a normal URL
403
+ audioUrl = audio;
404
+ }
395
405
  }
396
406
  }
397
407
  else {
@@ -568,8 +578,14 @@ class FileService extends BaseService {
568
578
  */
569
579
  async upload(input) {
570
580
  let fileData;
571
- if (typeof input === "string")
572
- fileData = await readFile(input);
581
+ if (typeof input === "string") {
582
+ if (input.startsWith("data:")) {
583
+ fileData = dataUrlToBlob(input);
584
+ }
585
+ else {
586
+ fileData = await readFile(input);
587
+ }
588
+ }
573
589
  else
574
590
  fileData = input;
575
591
  const data = await this.fetchJson("/v2/upload", {
@@ -583,6 +599,17 @@ class FileService extends BaseService {
583
599
  return data.upload_url;
584
600
  }
585
601
  }
602
+ function dataUrlToBlob(dataUrl) {
603
+ const arr = dataUrl.split(",");
604
+ const mime = arr[0].match(/:(.*?);/)[1];
605
+ const bstr = atob(arr[1]);
606
+ let n = bstr.length;
607
+ const u8arr = new Uint8Array(n);
608
+ while (n--) {
609
+ u8arr[n] = bstr.charCodeAt(n);
610
+ }
611
+ return new Blob([u8arr], { type: mime });
612
+ }
586
613
 
587
614
  const defaultBaseUrl = "https://api.assemblyai.com";
588
615
  class AssemblyAI {
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var WebSocket = require('#ws');
3
+ var ws = require('ws');
4
4
 
5
5
  /******************************************************************************
6
6
  Copyright (c) Microsoft Corporation.
@@ -63,6 +63,7 @@ class BaseService {
63
63
  init = init !== null && init !== void 0 ? init : {};
64
64
  init.headers = (_a = init.headers) !== null && _a !== void 0 ? _a : {};
65
65
  init.headers = Object.assign({ Authorization: this.params.apiKey, "Content-Type": "application/json" }, init.headers);
66
+ init.cache = "no-store";
66
67
  if (!input.startsWith("http"))
67
68
  input = this.params.baseUrl + input;
68
69
  const response = yield fetch(input, init);
@@ -135,6 +136,8 @@ const { WritableStream } = typeof window !== "undefined"
135
136
  ? global
136
137
  : globalThis;
137
138
 
139
+ const factory = (url, params) => new ws(url, params);
140
+
138
141
  var RealtimeErrorType;
139
142
  (function (RealtimeErrorType) {
140
143
  RealtimeErrorType[RealtimeErrorType["BadSampleRate"] = 4000] = "BadSampleRate";
@@ -231,10 +234,10 @@ class RealtimeTranscriber {
231
234
  }
232
235
  const url = this.connectionUrl();
233
236
  if (this.token) {
234
- this.socket = new WebSocket(url.toString());
237
+ this.socket = factory(url.toString());
235
238
  }
236
239
  else {
237
- this.socket = new WebSocket(url.toString(), {
240
+ this.socket = factory(url.toString(), {
238
241
  headers: { Authorization: this.apiKey },
239
242
  });
240
243
  }
@@ -330,15 +333,16 @@ class RealtimeTranscriber {
330
333
  this.send(`{"end_utterance_silence_threshold":${threshold}}`);
331
334
  }
332
335
  send(data) {
333
- if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
336
+ if (!this.socket || this.socket.readyState !== this.socket.OPEN) {
334
337
  throw new Error("Socket is not open for communication");
335
338
  }
336
339
  this.socket.send(data);
337
340
  }
338
341
  close() {
339
342
  return __awaiter(this, arguments, void 0, function* (waitForSessionTermination = true) {
343
+ var _a;
340
344
  if (this.socket) {
341
- if (this.socket.readyState === WebSocket.OPEN) {
345
+ if (this.socket.readyState === this.socket.OPEN) {
342
346
  if (waitForSessionTermination) {
343
347
  const sessionTerminatedPromise = new Promise((resolve) => {
344
348
  this.sessionTerminatedResolve = resolve;
@@ -350,7 +354,7 @@ class RealtimeTranscriber {
350
354
  this.socket.send(terminateSessionMessage);
351
355
  }
352
356
  }
353
- if ("removeAllListeners" in this.socket)
357
+ if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.removeAllListeners)
354
358
  this.socket.removeAllListeners();
355
359
  this.socket.close();
356
360
  }
@@ -404,6 +408,8 @@ function getPath(path) {
404
408
  return null;
405
409
  if (path.startsWith("https"))
406
410
  return null;
411
+ if (path.startsWith("data:"))
412
+ return null;
407
413
  if (path.startsWith("file://"))
408
414
  return path.substring(7);
409
415
  if (path.startsWith("file:"))
@@ -448,8 +454,13 @@ class TranscriptService extends BaseService {
448
454
  audioUrl = yield this.files.upload(path);
449
455
  }
450
456
  else {
451
- // audio is not a local path, assume it's a URL
452
- audioUrl = audio;
457
+ if (audio.startsWith("data:")) {
458
+ audioUrl = yield this.files.upload(audio);
459
+ }
460
+ else {
461
+ // audio is not a local path, and not a data-URI, assume it's a normal URL
462
+ audioUrl = audio;
463
+ }
453
464
  }
454
465
  }
455
466
  else {
@@ -647,8 +658,14 @@ class FileService extends BaseService {
647
658
  upload(input) {
648
659
  return __awaiter(this, void 0, void 0, function* () {
649
660
  let fileData;
650
- if (typeof input === "string")
651
- fileData = yield readFile();
661
+ if (typeof input === "string") {
662
+ if (input.startsWith("data:")) {
663
+ fileData = dataUrlToBlob(input);
664
+ }
665
+ else {
666
+ fileData = yield readFile();
667
+ }
668
+ }
652
669
  else
653
670
  fileData = input;
654
671
  const data = yield this.fetchJson("/v2/upload", {
@@ -663,6 +680,17 @@ class FileService extends BaseService {
663
680
  });
664
681
  }
665
682
  }
683
+ function dataUrlToBlob(dataUrl) {
684
+ const arr = dataUrl.split(",");
685
+ const mime = arr[0].match(/:(.*?);/)[1];
686
+ const bstr = atob(arr[1]);
687
+ let n = bstr.length;
688
+ const u8arr = new Uint8Array(n);
689
+ while (n--) {
690
+ u8arr[n] = bstr.charCodeAt(n);
691
+ }
692
+ return new Blob([u8arr], { type: mime });
693
+ }
666
694
 
667
695
  const defaultBaseUrl = "https://api.assemblyai.com";
668
696
  class AssemblyAI {
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import WebSocket from '#ws';
1
+ import ws from 'ws';
2
2
 
3
3
  /******************************************************************************
4
4
  Copyright (c) Microsoft Corporation.
@@ -61,6 +61,7 @@ class BaseService {
61
61
  init = init !== null && init !== void 0 ? init : {};
62
62
  init.headers = (_a = init.headers) !== null && _a !== void 0 ? _a : {};
63
63
  init.headers = Object.assign({ Authorization: this.params.apiKey, "Content-Type": "application/json" }, init.headers);
64
+ init.cache = "no-store";
64
65
  if (!input.startsWith("http"))
65
66
  input = this.params.baseUrl + input;
66
67
  const response = yield fetch(input, init);
@@ -133,6 +134,8 @@ const { WritableStream } = typeof window !== "undefined"
133
134
  ? global
134
135
  : globalThis;
135
136
 
137
+ const factory = (url, params) => new ws(url, params);
138
+
136
139
  var RealtimeErrorType;
137
140
  (function (RealtimeErrorType) {
138
141
  RealtimeErrorType[RealtimeErrorType["BadSampleRate"] = 4000] = "BadSampleRate";
@@ -229,10 +232,10 @@ class RealtimeTranscriber {
229
232
  }
230
233
  const url = this.connectionUrl();
231
234
  if (this.token) {
232
- this.socket = new WebSocket(url.toString());
235
+ this.socket = factory(url.toString());
233
236
  }
234
237
  else {
235
- this.socket = new WebSocket(url.toString(), {
238
+ this.socket = factory(url.toString(), {
236
239
  headers: { Authorization: this.apiKey },
237
240
  });
238
241
  }
@@ -328,15 +331,16 @@ class RealtimeTranscriber {
328
331
  this.send(`{"end_utterance_silence_threshold":${threshold}}`);
329
332
  }
330
333
  send(data) {
331
- if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
334
+ if (!this.socket || this.socket.readyState !== this.socket.OPEN) {
332
335
  throw new Error("Socket is not open for communication");
333
336
  }
334
337
  this.socket.send(data);
335
338
  }
336
339
  close() {
337
340
  return __awaiter(this, arguments, void 0, function* (waitForSessionTermination = true) {
341
+ var _a;
338
342
  if (this.socket) {
339
- if (this.socket.readyState === WebSocket.OPEN) {
343
+ if (this.socket.readyState === this.socket.OPEN) {
340
344
  if (waitForSessionTermination) {
341
345
  const sessionTerminatedPromise = new Promise((resolve) => {
342
346
  this.sessionTerminatedResolve = resolve;
@@ -348,7 +352,7 @@ class RealtimeTranscriber {
348
352
  this.socket.send(terminateSessionMessage);
349
353
  }
350
354
  }
351
- if ("removeAllListeners" in this.socket)
355
+ if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.removeAllListeners)
352
356
  this.socket.removeAllListeners();
353
357
  this.socket.close();
354
358
  }
@@ -402,6 +406,8 @@ function getPath(path) {
402
406
  return null;
403
407
  if (path.startsWith("https"))
404
408
  return null;
409
+ if (path.startsWith("data:"))
410
+ return null;
405
411
  if (path.startsWith("file://"))
406
412
  return path.substring(7);
407
413
  if (path.startsWith("file:"))
@@ -446,8 +452,13 @@ class TranscriptService extends BaseService {
446
452
  audioUrl = yield this.files.upload(path);
447
453
  }
448
454
  else {
449
- // audio is not a local path, assume it's a URL
450
- audioUrl = audio;
455
+ if (audio.startsWith("data:")) {
456
+ audioUrl = yield this.files.upload(audio);
457
+ }
458
+ else {
459
+ // audio is not a local path, and not a data-URI, assume it's a normal URL
460
+ audioUrl = audio;
461
+ }
451
462
  }
452
463
  }
453
464
  else {
@@ -645,8 +656,14 @@ class FileService extends BaseService {
645
656
  upload(input) {
646
657
  return __awaiter(this, void 0, void 0, function* () {
647
658
  let fileData;
648
- if (typeof input === "string")
649
- fileData = yield readFile();
659
+ if (typeof input === "string") {
660
+ if (input.startsWith("data:")) {
661
+ fileData = dataUrlToBlob(input);
662
+ }
663
+ else {
664
+ fileData = yield readFile();
665
+ }
666
+ }
650
667
  else
651
668
  fileData = input;
652
669
  const data = yield this.fetchJson("/v2/upload", {
@@ -661,6 +678,17 @@ class FileService extends BaseService {
661
678
  });
662
679
  }
663
680
  }
681
+ function dataUrlToBlob(dataUrl) {
682
+ const arr = dataUrl.split(",");
683
+ const mime = arr[0].match(/:(.*?);/)[1];
684
+ const bstr = atob(arr[1]);
685
+ let n = bstr.length;
686
+ const u8arr = new Uint8Array(n);
687
+ while (n--) {
688
+ u8arr[n] = bstr.charCodeAt(n);
689
+ }
690
+ return new Blob([u8arr], { type: mime });
691
+ }
664
692
 
665
693
  const defaultBaseUrl = "https://api.assemblyai.com";
666
694
  class AssemblyAI {
package/dist/node.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var web = require('stream/web');
4
- var WebSocket = require('#ws');
4
+ var ws = require('ws');
5
5
  var fs = require('fs');
6
6
  var stream = require('stream');
7
7
 
@@ -24,6 +24,7 @@ class BaseService {
24
24
  "Content-Type": "application/json",
25
25
  ...init.headers,
26
26
  };
27
+ init.cache = "no-store";
27
28
  if (!input.startsWith("http"))
28
29
  input = this.params.baseUrl + input;
29
30
  const response = await fetch(input, init);
@@ -87,6 +88,8 @@ class LemurService extends BaseService {
87
88
  }
88
89
  }
89
90
 
91
+ const factory = (url, params) => new ws(url, params);
92
+
90
93
  var RealtimeErrorType;
91
94
  (function (RealtimeErrorType) {
92
95
  RealtimeErrorType[RealtimeErrorType["BadSampleRate"] = 4000] = "BadSampleRate";
@@ -182,10 +185,10 @@ class RealtimeTranscriber {
182
185
  }
183
186
  const url = this.connectionUrl();
184
187
  if (this.token) {
185
- this.socket = new WebSocket(url.toString());
188
+ this.socket = factory(url.toString());
186
189
  }
187
190
  else {
188
- this.socket = new WebSocket(url.toString(), {
191
+ this.socket = factory(url.toString(), {
189
192
  headers: { Authorization: this.apiKey },
190
193
  });
191
194
  }
@@ -278,14 +281,14 @@ class RealtimeTranscriber {
278
281
  this.send(`{"end_utterance_silence_threshold":${threshold}}`);
279
282
  }
280
283
  send(data) {
281
- if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
284
+ if (!this.socket || this.socket.readyState !== this.socket.OPEN) {
282
285
  throw new Error("Socket is not open for communication");
283
286
  }
284
287
  this.socket.send(data);
285
288
  }
286
289
  async close(waitForSessionTermination = true) {
287
290
  if (this.socket) {
288
- if (this.socket.readyState === WebSocket.OPEN) {
291
+ if (this.socket.readyState === this.socket.OPEN) {
289
292
  if (waitForSessionTermination) {
290
293
  const sessionTerminatedPromise = new Promise((resolve) => {
291
294
  this.sessionTerminatedResolve = resolve;
@@ -297,7 +300,7 @@ class RealtimeTranscriber {
297
300
  this.socket.send(terminateSessionMessage);
298
301
  }
299
302
  }
300
- if ("removeAllListeners" in this.socket)
303
+ if (this.socket?.removeAllListeners)
301
304
  this.socket.removeAllListeners();
302
305
  this.socket.close();
303
306
  }
@@ -348,6 +351,8 @@ function getPath(path) {
348
351
  return null;
349
352
  if (path.startsWith("https"))
350
353
  return null;
354
+ if (path.startsWith("data:"))
355
+ return null;
351
356
  if (path.startsWith("file://"))
352
357
  return path.substring(7);
353
358
  if (path.startsWith("file:"))
@@ -389,8 +394,13 @@ class TranscriptService extends BaseService {
389
394
  audioUrl = await this.files.upload(path);
390
395
  }
391
396
  else {
392
- // audio is not a local path, assume it's a URL
393
- audioUrl = audio;
397
+ if (audio.startsWith("data:")) {
398
+ audioUrl = await this.files.upload(audio);
399
+ }
400
+ else {
401
+ // audio is not a local path, and not a data-URI, assume it's a normal URL
402
+ audioUrl = audio;
403
+ }
394
404
  }
395
405
  }
396
406
  else {
@@ -567,8 +577,14 @@ class FileService extends BaseService {
567
577
  */
568
578
  async upload(input) {
569
579
  let fileData;
570
- if (typeof input === "string")
571
- fileData = await readFile(input);
580
+ if (typeof input === "string") {
581
+ if (input.startsWith("data:")) {
582
+ fileData = dataUrlToBlob(input);
583
+ }
584
+ else {
585
+ fileData = await readFile(input);
586
+ }
587
+ }
572
588
  else
573
589
  fileData = input;
574
590
  const data = await this.fetchJson("/v2/upload", {
@@ -582,6 +598,17 @@ class FileService extends BaseService {
582
598
  return data.upload_url;
583
599
  }
584
600
  }
601
+ function dataUrlToBlob(dataUrl) {
602
+ const arr = dataUrl.split(",");
603
+ const mime = arr[0].match(/:(.*?);/)[1];
604
+ const bstr = atob(arr[1]);
605
+ let n = bstr.length;
606
+ const u8arr = new Uint8Array(n);
607
+ while (n--) {
608
+ u8arr[n] = bstr.charCodeAt(n);
609
+ }
610
+ return new Blob([u8arr], { type: mime });
611
+ }
585
612
 
586
613
  const defaultBaseUrl = "https://api.assemblyai.com";
587
614
  class AssemblyAI {