assemblyai 4.12.2 → 4.13.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/index.cjs CHANGED
@@ -63,7 +63,7 @@ if (typeof navigator !== "undefined" && navigator.userAgent) {
63
63
  defaultUserAgentString += navigator.userAgent;
64
64
  }
65
65
  const defaultUserAgent = {
66
- sdk: { name: "JavaScript", version: "4.12.2" },
66
+ sdk: { name: "JavaScript", version: "4.13.0" },
67
67
  };
68
68
  if (typeof process !== "undefined") {
69
69
  if (process.versions.node && defaultUserAgentString.indexOf("Node") === -1) {
@@ -256,9 +256,48 @@ const RealtimeErrorMessages = {
256
256
  class RealtimeError extends Error {
257
257
  }
258
258
 
259
+ const StreamingErrorType = {
260
+ BadSampleRate: 4000,
261
+ AuthFailed: 4001,
262
+ InsufficientFunds: 4002,
263
+ FreeTierUser: 4003,
264
+ NonexistentSessionId: 4004,
265
+ SessionExpired: 4008,
266
+ ClosedSession: 4010,
267
+ RateLimited: 4029,
268
+ UniqueSessionViolation: 4030,
269
+ SessionTimeout: 4031,
270
+ AudioTooShort: 4032,
271
+ AudioTooLong: 4033,
272
+ AudioTooSmallToTranscode: 4034,
273
+ BadSchema: 4101,
274
+ TooManyStreams: 4102,
275
+ Reconnected: 4103,
276
+ };
277
+ const StreamingErrorMessages = {
278
+ [StreamingErrorType.BadSampleRate]: "Sample rate must be a positive integer",
279
+ [StreamingErrorType.AuthFailed]: "Not Authorized",
280
+ [StreamingErrorType.InsufficientFunds]: "Insufficient funds",
281
+ [StreamingErrorType.FreeTierUser]: "This feature is paid-only and requires you to add a credit card. Please visit https://app.assemblyai.com/ to add a credit card to your account.",
282
+ [StreamingErrorType.NonexistentSessionId]: "Session ID does not exist",
283
+ [StreamingErrorType.SessionExpired]: "Session has expired",
284
+ [StreamingErrorType.ClosedSession]: "Session is closed",
285
+ [StreamingErrorType.RateLimited]: "Rate limited",
286
+ [StreamingErrorType.UniqueSessionViolation]: "Unique session violation",
287
+ [StreamingErrorType.SessionTimeout]: "Session Timeout",
288
+ [StreamingErrorType.AudioTooShort]: "Audio too short",
289
+ [StreamingErrorType.AudioTooLong]: "Audio too long",
290
+ [StreamingErrorType.AudioTooSmallToTranscode]: "Audio too small to transcode",
291
+ [StreamingErrorType.BadSchema]: "Bad schema",
292
+ [StreamingErrorType.TooManyStreams]: "Too many streams",
293
+ [StreamingErrorType.Reconnected]: "This session has been reconnected. This WebSocket is no longer valid.",
294
+ };
295
+ class StreamingError extends Error {
296
+ }
297
+
259
298
  const defaultRealtimeUrl = "wss://api.assemblyai.com/v2/realtime/ws";
260
299
  const forceEndOfUtteranceMessage = `{"force_end_utterance":true}`;
261
- const terminateSessionMessage = `{"terminate_session":true}`;
300
+ const terminateSessionMessage$1 = `{"terminate_session":true}`;
262
301
  /**
263
302
  * RealtimeTranscriber connects to the Streaming Speech-to-Text API and lets you transcribe audio in real-time.
264
303
  */
@@ -453,11 +492,11 @@ class RealtimeTranscriber {
453
492
  const sessionTerminatedPromise = new Promise((resolve) => {
454
493
  this.sessionTerminatedResolve = resolve;
455
494
  });
456
- this.socket.send(terminateSessionMessage);
495
+ this.socket.send(terminateSessionMessage$1);
457
496
  yield sessionTerminatedPromise;
458
497
  }
459
498
  else {
460
- this.socket.send(terminateSessionMessage);
499
+ this.socket.send(terminateSessionMessage$1);
461
500
  }
462
501
  }
463
502
  if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.removeAllListeners)
@@ -820,7 +859,174 @@ function dataUrlToBlob(dataUrl) {
820
859
  return new Blob([u8arr], { type: mime });
821
860
  }
822
861
 
862
+ const defaultStreamingUrl$1 = "wss://streaming.assemblyai.com/v3/ws";
863
+ const terminateSessionMessage = `{"type":"Terminate"}`;
864
+ class StreamingTranscriber {
865
+ constructor(params) {
866
+ this.listeners = {};
867
+ this.params = Object.assign(Object.assign({}, params), { websocketBaseUrl: params.websocketBaseUrl || defaultStreamingUrl$1 });
868
+ if ("token" in params && params.token)
869
+ this.token = params.token;
870
+ if ("apiKey" in params && params.apiKey)
871
+ this.apiKey = params.apiKey;
872
+ if (!(this.token || this.apiKey)) {
873
+ throw new Error("API key or temporary token is required.");
874
+ }
875
+ }
876
+ connectionUrl() {
877
+ var _a;
878
+ const url = new URL((_a = this.params.websocketBaseUrl) !== null && _a !== void 0 ? _a : "");
879
+ if (url.protocol !== "wss:") {
880
+ throw new Error("Invalid protocol, must be wss");
881
+ }
882
+ const searchParams = new URLSearchParams();
883
+ searchParams.set("sample_rate", this.params.sampleRate.toString());
884
+ if (this.params.endOfTurnConfidenceThreshold) {
885
+ searchParams.set("end_of_turn_confidence_threshold", this.params.endOfTurnConfidenceThreshold.toString());
886
+ }
887
+ if (this.params.minEndOfTurnSilenceWhenConfident) {
888
+ searchParams.set("min_end_of_turn_silence_when_confident", this.params.minEndOfTurnSilenceWhenConfident.toString());
889
+ }
890
+ if (this.params.maxTurnSilence) {
891
+ searchParams.set("max_turn_silence", this.params.maxTurnSilence.toString());
892
+ }
893
+ if (this.params.formatTurns) {
894
+ searchParams.set("format_turns", this.params.formatTurns.toString());
895
+ }
896
+ url.search = searchParams.toString();
897
+ return url;
898
+ }
899
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
900
+ on(event, listener) {
901
+ this.listeners[event] = listener;
902
+ }
903
+ connect() {
904
+ return new Promise((resolve) => {
905
+ if (this.socket) {
906
+ throw new Error("Already connected");
907
+ }
908
+ const url = this.connectionUrl();
909
+ this.socket = factory(url.toString(), {
910
+ headers: { Authorization: this.token || this.apiKey },
911
+ });
912
+ this.socket.binaryType = "arraybuffer";
913
+ this.socket.onopen = () => { };
914
+ this.socket.onclose = ({ code, reason }) => {
915
+ var _a, _b;
916
+ if (!reason) {
917
+ if (code in StreamingErrorMessages) {
918
+ reason = StreamingErrorMessages[code];
919
+ }
920
+ }
921
+ (_b = (_a = this.listeners).close) === null || _b === void 0 ? void 0 : _b.call(_a, code, reason);
922
+ };
923
+ this.socket.onerror = (event) => {
924
+ var _a, _b, _c, _d;
925
+ if (event.error)
926
+ (_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, event.error);
927
+ else
928
+ (_d = (_c = this.listeners).error) === null || _d === void 0 ? void 0 : _d.call(_c, new Error(event.message));
929
+ };
930
+ this.socket.onmessage = ({ data }) => {
931
+ var _a, _b, _c, _d, _e, _f, _g;
932
+ const message = JSON.parse(data.toString());
933
+ if ("error" in message) {
934
+ (_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, new StreamingError(message.error));
935
+ return;
936
+ }
937
+ switch (message.type) {
938
+ case "Begin": {
939
+ resolve(message);
940
+ (_d = (_c = this.listeners).open) === null || _d === void 0 ? void 0 : _d.call(_c, message);
941
+ break;
942
+ }
943
+ case "Turn": {
944
+ (_f = (_e = this.listeners).turn) === null || _f === void 0 ? void 0 : _f.call(_e, message);
945
+ break;
946
+ }
947
+ case "Termination": {
948
+ (_g = this.sessionTerminatedResolve) === null || _g === void 0 ? void 0 : _g.call(this);
949
+ break;
950
+ }
951
+ }
952
+ };
953
+ });
954
+ }
955
+ stream() {
956
+ return new WritableStream({
957
+ write: (chunk) => {
958
+ this.sendAudio(chunk);
959
+ },
960
+ });
961
+ }
962
+ sendAudio(audio) {
963
+ this.send(audio);
964
+ }
965
+ send(data) {
966
+ if (!this.socket || this.socket.readyState !== this.socket.OPEN) {
967
+ throw new Error("Socket is not open for communication");
968
+ }
969
+ this.socket.send(data);
970
+ }
971
+ close() {
972
+ return __awaiter(this, arguments, void 0, function* (waitForSessionTermination = true) {
973
+ var _a;
974
+ if (this.socket) {
975
+ if (this.socket.readyState === this.socket.OPEN) {
976
+ if (waitForSessionTermination) {
977
+ const sessionTerminatedPromise = new Promise((resolve) => {
978
+ this.sessionTerminatedResolve = resolve;
979
+ });
980
+ this.socket.send(terminateSessionMessage);
981
+ yield sessionTerminatedPromise;
982
+ }
983
+ else {
984
+ this.socket.send(terminateSessionMessage);
985
+ }
986
+ }
987
+ if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.removeAllListeners)
988
+ this.socket.removeAllListeners();
989
+ this.socket.close();
990
+ }
991
+ this.listeners = {};
992
+ this.socket = undefined;
993
+ });
994
+ }
995
+ }
996
+
997
+ class StreamingTranscriberFactory extends BaseService {
998
+ constructor(params) {
999
+ super(params);
1000
+ this.baseServiceParams = params;
1001
+ }
1002
+ transcriber(params) {
1003
+ const serviceParams = Object.assign({}, params);
1004
+ if (!serviceParams.token && !serviceParams.apiKey) {
1005
+ serviceParams.apiKey = this.baseServiceParams.apiKey;
1006
+ }
1007
+ return new StreamingTranscriber(serviceParams);
1008
+ }
1009
+ createTemporaryToken(params) {
1010
+ return __awaiter(this, void 0, void 0, function* () {
1011
+ const searchParams = new URLSearchParams();
1012
+ // Add each param to the search params
1013
+ Object.entries(params).forEach(([key, value]) => {
1014
+ if (value !== undefined && value !== null) {
1015
+ searchParams.append(key, String(value));
1016
+ }
1017
+ });
1018
+ const queryString = searchParams.toString();
1019
+ const url = queryString ? `/v3/token?${queryString}` : "/v3/token";
1020
+ const data = yield this.fetchJson(url, {
1021
+ method: "GET",
1022
+ });
1023
+ return data.token;
1024
+ });
1025
+ }
1026
+ }
1027
+
823
1028
  const defaultBaseUrl = "https://api.assemblyai.com";
1029
+ const defaultStreamingUrl = "https://streaming.assemblyai.com";
824
1030
  class AssemblyAI {
825
1031
  /**
826
1032
  * Create a new AssemblyAI client.
@@ -835,6 +1041,7 @@ class AssemblyAI {
835
1041
  this.transcripts = new TranscriptService(params, this.files);
836
1042
  this.lemur = new LemurService(params);
837
1043
  this.realtime = new RealtimeTranscriberFactory(params);
1044
+ this.streaming = new StreamingTranscriberFactory(Object.assign(Object.assign({}, params), { baseUrl: params.streamingBaseUrl || defaultStreamingUrl }));
838
1045
  }
839
1046
  }
840
1047
 
@@ -845,4 +1052,5 @@ exports.RealtimeService = RealtimeService;
845
1052
  exports.RealtimeServiceFactory = RealtimeServiceFactory;
846
1053
  exports.RealtimeTranscriber = RealtimeTranscriber;
847
1054
  exports.RealtimeTranscriberFactory = RealtimeTranscriberFactory;
1055
+ exports.StreamingTranscriber = StreamingTranscriber;
848
1056
  exports.TranscriptService = TranscriptService;
package/dist/index.mjs CHANGED
@@ -61,7 +61,7 @@ if (typeof navigator !== "undefined" && navigator.userAgent) {
61
61
  defaultUserAgentString += navigator.userAgent;
62
62
  }
63
63
  const defaultUserAgent = {
64
- sdk: { name: "JavaScript", version: "4.12.2" },
64
+ sdk: { name: "JavaScript", version: "4.13.0" },
65
65
  };
66
66
  if (typeof process !== "undefined") {
67
67
  if (process.versions.node && defaultUserAgentString.indexOf("Node") === -1) {
@@ -254,9 +254,48 @@ const RealtimeErrorMessages = {
254
254
  class RealtimeError extends Error {
255
255
  }
256
256
 
257
+ const StreamingErrorType = {
258
+ BadSampleRate: 4000,
259
+ AuthFailed: 4001,
260
+ InsufficientFunds: 4002,
261
+ FreeTierUser: 4003,
262
+ NonexistentSessionId: 4004,
263
+ SessionExpired: 4008,
264
+ ClosedSession: 4010,
265
+ RateLimited: 4029,
266
+ UniqueSessionViolation: 4030,
267
+ SessionTimeout: 4031,
268
+ AudioTooShort: 4032,
269
+ AudioTooLong: 4033,
270
+ AudioTooSmallToTranscode: 4034,
271
+ BadSchema: 4101,
272
+ TooManyStreams: 4102,
273
+ Reconnected: 4103,
274
+ };
275
+ const StreamingErrorMessages = {
276
+ [StreamingErrorType.BadSampleRate]: "Sample rate must be a positive integer",
277
+ [StreamingErrorType.AuthFailed]: "Not Authorized",
278
+ [StreamingErrorType.InsufficientFunds]: "Insufficient funds",
279
+ [StreamingErrorType.FreeTierUser]: "This feature is paid-only and requires you to add a credit card. Please visit https://app.assemblyai.com/ to add a credit card to your account.",
280
+ [StreamingErrorType.NonexistentSessionId]: "Session ID does not exist",
281
+ [StreamingErrorType.SessionExpired]: "Session has expired",
282
+ [StreamingErrorType.ClosedSession]: "Session is closed",
283
+ [StreamingErrorType.RateLimited]: "Rate limited",
284
+ [StreamingErrorType.UniqueSessionViolation]: "Unique session violation",
285
+ [StreamingErrorType.SessionTimeout]: "Session Timeout",
286
+ [StreamingErrorType.AudioTooShort]: "Audio too short",
287
+ [StreamingErrorType.AudioTooLong]: "Audio too long",
288
+ [StreamingErrorType.AudioTooSmallToTranscode]: "Audio too small to transcode",
289
+ [StreamingErrorType.BadSchema]: "Bad schema",
290
+ [StreamingErrorType.TooManyStreams]: "Too many streams",
291
+ [StreamingErrorType.Reconnected]: "This session has been reconnected. This WebSocket is no longer valid.",
292
+ };
293
+ class StreamingError extends Error {
294
+ }
295
+
257
296
  const defaultRealtimeUrl = "wss://api.assemblyai.com/v2/realtime/ws";
258
297
  const forceEndOfUtteranceMessage = `{"force_end_utterance":true}`;
259
- const terminateSessionMessage = `{"terminate_session":true}`;
298
+ const terminateSessionMessage$1 = `{"terminate_session":true}`;
260
299
  /**
261
300
  * RealtimeTranscriber connects to the Streaming Speech-to-Text API and lets you transcribe audio in real-time.
262
301
  */
@@ -451,11 +490,11 @@ class RealtimeTranscriber {
451
490
  const sessionTerminatedPromise = new Promise((resolve) => {
452
491
  this.sessionTerminatedResolve = resolve;
453
492
  });
454
- this.socket.send(terminateSessionMessage);
493
+ this.socket.send(terminateSessionMessage$1);
455
494
  yield sessionTerminatedPromise;
456
495
  }
457
496
  else {
458
- this.socket.send(terminateSessionMessage);
497
+ this.socket.send(terminateSessionMessage$1);
459
498
  }
460
499
  }
461
500
  if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.removeAllListeners)
@@ -818,7 +857,174 @@ function dataUrlToBlob(dataUrl) {
818
857
  return new Blob([u8arr], { type: mime });
819
858
  }
820
859
 
860
+ const defaultStreamingUrl$1 = "wss://streaming.assemblyai.com/v3/ws";
861
+ const terminateSessionMessage = `{"type":"Terminate"}`;
862
+ class StreamingTranscriber {
863
+ constructor(params) {
864
+ this.listeners = {};
865
+ this.params = Object.assign(Object.assign({}, params), { websocketBaseUrl: params.websocketBaseUrl || defaultStreamingUrl$1 });
866
+ if ("token" in params && params.token)
867
+ this.token = params.token;
868
+ if ("apiKey" in params && params.apiKey)
869
+ this.apiKey = params.apiKey;
870
+ if (!(this.token || this.apiKey)) {
871
+ throw new Error("API key or temporary token is required.");
872
+ }
873
+ }
874
+ connectionUrl() {
875
+ var _a;
876
+ const url = new URL((_a = this.params.websocketBaseUrl) !== null && _a !== void 0 ? _a : "");
877
+ if (url.protocol !== "wss:") {
878
+ throw new Error("Invalid protocol, must be wss");
879
+ }
880
+ const searchParams = new URLSearchParams();
881
+ searchParams.set("sample_rate", this.params.sampleRate.toString());
882
+ if (this.params.endOfTurnConfidenceThreshold) {
883
+ searchParams.set("end_of_turn_confidence_threshold", this.params.endOfTurnConfidenceThreshold.toString());
884
+ }
885
+ if (this.params.minEndOfTurnSilenceWhenConfident) {
886
+ searchParams.set("min_end_of_turn_silence_when_confident", this.params.minEndOfTurnSilenceWhenConfident.toString());
887
+ }
888
+ if (this.params.maxTurnSilence) {
889
+ searchParams.set("max_turn_silence", this.params.maxTurnSilence.toString());
890
+ }
891
+ if (this.params.formatTurns) {
892
+ searchParams.set("format_turns", this.params.formatTurns.toString());
893
+ }
894
+ url.search = searchParams.toString();
895
+ return url;
896
+ }
897
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
898
+ on(event, listener) {
899
+ this.listeners[event] = listener;
900
+ }
901
+ connect() {
902
+ return new Promise((resolve) => {
903
+ if (this.socket) {
904
+ throw new Error("Already connected");
905
+ }
906
+ const url = this.connectionUrl();
907
+ this.socket = factory(url.toString(), {
908
+ headers: { Authorization: this.token || this.apiKey },
909
+ });
910
+ this.socket.binaryType = "arraybuffer";
911
+ this.socket.onopen = () => { };
912
+ this.socket.onclose = ({ code, reason }) => {
913
+ var _a, _b;
914
+ if (!reason) {
915
+ if (code in StreamingErrorMessages) {
916
+ reason = StreamingErrorMessages[code];
917
+ }
918
+ }
919
+ (_b = (_a = this.listeners).close) === null || _b === void 0 ? void 0 : _b.call(_a, code, reason);
920
+ };
921
+ this.socket.onerror = (event) => {
922
+ var _a, _b, _c, _d;
923
+ if (event.error)
924
+ (_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, event.error);
925
+ else
926
+ (_d = (_c = this.listeners).error) === null || _d === void 0 ? void 0 : _d.call(_c, new Error(event.message));
927
+ };
928
+ this.socket.onmessage = ({ data }) => {
929
+ var _a, _b, _c, _d, _e, _f, _g;
930
+ const message = JSON.parse(data.toString());
931
+ if ("error" in message) {
932
+ (_b = (_a = this.listeners).error) === null || _b === void 0 ? void 0 : _b.call(_a, new StreamingError(message.error));
933
+ return;
934
+ }
935
+ switch (message.type) {
936
+ case "Begin": {
937
+ resolve(message);
938
+ (_d = (_c = this.listeners).open) === null || _d === void 0 ? void 0 : _d.call(_c, message);
939
+ break;
940
+ }
941
+ case "Turn": {
942
+ (_f = (_e = this.listeners).turn) === null || _f === void 0 ? void 0 : _f.call(_e, message);
943
+ break;
944
+ }
945
+ case "Termination": {
946
+ (_g = this.sessionTerminatedResolve) === null || _g === void 0 ? void 0 : _g.call(this);
947
+ break;
948
+ }
949
+ }
950
+ };
951
+ });
952
+ }
953
+ stream() {
954
+ return new WritableStream({
955
+ write: (chunk) => {
956
+ this.sendAudio(chunk);
957
+ },
958
+ });
959
+ }
960
+ sendAudio(audio) {
961
+ this.send(audio);
962
+ }
963
+ send(data) {
964
+ if (!this.socket || this.socket.readyState !== this.socket.OPEN) {
965
+ throw new Error("Socket is not open for communication");
966
+ }
967
+ this.socket.send(data);
968
+ }
969
+ close() {
970
+ return __awaiter(this, arguments, void 0, function* (waitForSessionTermination = true) {
971
+ var _a;
972
+ if (this.socket) {
973
+ if (this.socket.readyState === this.socket.OPEN) {
974
+ if (waitForSessionTermination) {
975
+ const sessionTerminatedPromise = new Promise((resolve) => {
976
+ this.sessionTerminatedResolve = resolve;
977
+ });
978
+ this.socket.send(terminateSessionMessage);
979
+ yield sessionTerminatedPromise;
980
+ }
981
+ else {
982
+ this.socket.send(terminateSessionMessage);
983
+ }
984
+ }
985
+ if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.removeAllListeners)
986
+ this.socket.removeAllListeners();
987
+ this.socket.close();
988
+ }
989
+ this.listeners = {};
990
+ this.socket = undefined;
991
+ });
992
+ }
993
+ }
994
+
995
+ class StreamingTranscriberFactory extends BaseService {
996
+ constructor(params) {
997
+ super(params);
998
+ this.baseServiceParams = params;
999
+ }
1000
+ transcriber(params) {
1001
+ const serviceParams = Object.assign({}, params);
1002
+ if (!serviceParams.token && !serviceParams.apiKey) {
1003
+ serviceParams.apiKey = this.baseServiceParams.apiKey;
1004
+ }
1005
+ return new StreamingTranscriber(serviceParams);
1006
+ }
1007
+ createTemporaryToken(params) {
1008
+ return __awaiter(this, void 0, void 0, function* () {
1009
+ const searchParams = new URLSearchParams();
1010
+ // Add each param to the search params
1011
+ Object.entries(params).forEach(([key, value]) => {
1012
+ if (value !== undefined && value !== null) {
1013
+ searchParams.append(key, String(value));
1014
+ }
1015
+ });
1016
+ const queryString = searchParams.toString();
1017
+ const url = queryString ? `/v3/token?${queryString}` : "/v3/token";
1018
+ const data = yield this.fetchJson(url, {
1019
+ method: "GET",
1020
+ });
1021
+ return data.token;
1022
+ });
1023
+ }
1024
+ }
1025
+
821
1026
  const defaultBaseUrl = "https://api.assemblyai.com";
1027
+ const defaultStreamingUrl = "https://streaming.assemblyai.com";
822
1028
  class AssemblyAI {
823
1029
  /**
824
1030
  * Create a new AssemblyAI client.
@@ -833,7 +1039,8 @@ class AssemblyAI {
833
1039
  this.transcripts = new TranscriptService(params, this.files);
834
1040
  this.lemur = new LemurService(params);
835
1041
  this.realtime = new RealtimeTranscriberFactory(params);
1042
+ this.streaming = new StreamingTranscriberFactory(Object.assign(Object.assign({}, params), { baseUrl: params.streamingBaseUrl || defaultStreamingUrl }));
836
1043
  }
837
1044
  }
838
1045
 
839
- export { AssemblyAI, FileService, LemurService, RealtimeService, RealtimeServiceFactory, RealtimeTranscriber, RealtimeTranscriberFactory, TranscriptService };
1046
+ export { AssemblyAI, FileService, LemurService, RealtimeService, RealtimeServiceFactory, RealtimeTranscriber, RealtimeTranscriberFactory, StreamingTranscriber, TranscriptService };