@fonoster/apiserver 0.6.2 → 0.7.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.
Files changed (109) hide show
  1. package/dist/applications/buildService.d.ts +3 -3
  2. package/dist/applications/createApplication.d.ts +2 -2
  3. package/dist/applications/createGetFnUtil.d.ts +2 -2
  4. package/dist/applications/deleteApplication.d.ts +3 -3
  5. package/dist/applications/getApplication.d.ts +2 -2
  6. package/dist/applications/getApplication.js +1 -3
  7. package/dist/applications/types.d.ts +1 -1
  8. package/dist/applications/utils/applicationWithEncodedStruct.js +20 -1
  9. package/dist/applications/utils/convertToApplicationData.js +1 -1
  10. package/dist/applications/utils/getApplicationValidationSchema.d.ts +3 -3
  11. package/dist/applications/utils/getApplicationValidationSchema.js +6 -3
  12. package/dist/applications/utils/prepareForValidation.js +1 -1
  13. package/dist/calls/ListCallsRequestSchema.d.ts +1 -4
  14. package/dist/calls/ListCallsRequestSchema.js +0 -4
  15. package/dist/calls/buildService.d.ts +2 -2
  16. package/dist/calls/buildService.js +6 -5
  17. package/dist/calls/createCall.d.ts +6 -4
  18. package/dist/calls/createCall.js +18 -8
  19. package/dist/calls/createFetchCalls.js +3 -7
  20. package/dist/calls/createFetchSingleCall.js +9 -2
  21. package/dist/calls/{trackCall.d.ts → makeTrackCall.d.ts} +3 -3
  22. package/dist/calls/makeTrackCall.js +67 -0
  23. package/dist/calls/runCallManager.js +12 -13
  24. package/dist/calls/types.d.ts +8 -42
  25. package/dist/calls/types.js +5 -38
  26. package/dist/core/seed.js +20 -0
  27. package/dist/core/services.d.ts +24 -25
  28. package/dist/envs.d.ts +0 -2
  29. package/dist/envs.js +1 -3
  30. package/dist/events/createInfluxDbPub.js +2 -1
  31. package/dist/events/mapCallDirectionToEnum.d.ts +3 -0
  32. package/dist/events/mapCallDirectionToEnum.js +37 -0
  33. package/dist/events/nats.js +5 -6
  34. package/dist/events/transformEvent.d.ts +2 -0
  35. package/dist/events/transformEvent.js +72 -0
  36. package/dist/index.js +4 -5
  37. package/dist/utils/index.d.ts +2 -0
  38. package/dist/utils/index.js +2 -0
  39. package/dist/utils/makeHandleDialEventsWithNats.d.ts +5 -0
  40. package/dist/{voice/handlers/StasisEnd.js → utils/makeHandleDialEventsWithNats.js} +10 -15
  41. package/dist/utils/makeHandleDialEventsWithVoiceClient.d.ts +5 -0
  42. package/dist/{voice/handlers/dial/handleDialEvents.js → utils/makeHandleDialEventsWithVoiceClient.js} +6 -17
  43. package/dist/utils/mapDialStatus.d.ts +3 -0
  44. package/dist/utils/mapDialStatus.js +38 -0
  45. package/dist/voice/VoiceClientImpl.d.ts +10 -1
  46. package/dist/voice/VoiceClientImpl.js +47 -7
  47. package/dist/voice/VoiceDispatcher.d.ts +6 -2
  48. package/dist/voice/VoiceDispatcher.js +50 -37
  49. package/dist/voice/connectToAri.js +3 -1
  50. package/dist/voice/createExternalMediaConfig.d.ts +3 -0
  51. package/dist/voice/createExternalMediaConfig.js +4 -1
  52. package/dist/voice/handlers/Answer.js +1 -1
  53. package/dist/voice/handlers/Hangup.js +1 -1
  54. package/dist/voice/handlers/Mute.js +1 -1
  55. package/dist/voice/handlers/Play.js +2 -2
  56. package/dist/voice/handlers/PlayDtmf.js +1 -1
  57. package/dist/voice/handlers/PlaybackControl.js +1 -1
  58. package/dist/voice/handlers/Record.js +2 -2
  59. package/dist/voice/handlers/Say.js +2 -2
  60. package/dist/voice/handlers/StreamGather.d.ts +3 -0
  61. package/dist/voice/handlers/StreamGather.js +66 -0
  62. package/dist/voice/handlers/Unmute.js +1 -1
  63. package/dist/voice/handlers/dial/Dial.js +10 -6
  64. package/dist/voice/handlers/gather/Gather.js +5 -4
  65. package/dist/voice/handlers/index.d.ts +12 -0
  66. package/dist/voice/handlers/index.js +46 -0
  67. package/dist/voice/handlers/{awaitForPlaybackFinished.js → utils/awaitForPlaybackFinished.js} +1 -1
  68. package/dist/voice/handlers/{awaitForRecordingFinished.js → utils/awaitForRecordingFinished.js} +1 -1
  69. package/dist/voice/handlers/utils/index.d.ts +3 -0
  70. package/dist/voice/handlers/utils/index.js +37 -0
  71. package/dist/voice/handlers/utils/isDtmf.d.ts +2 -0
  72. package/dist/voice/handlers/utils/isDtmf.js +24 -0
  73. package/dist/voice/integrations/findIntegrationsCredentials.d.ts +1 -1
  74. package/dist/voice/integrations/findIntegrationsCredentials.js +2 -1
  75. package/dist/voice/integrations/getSttConfig.d.ts +4 -2
  76. package/dist/voice/integrations/getSttConfig.js +4 -1
  77. package/dist/voice/integrations/getTtsConfig.d.ts +2 -1
  78. package/dist/voice/integrations/getTtsConfig.js +5 -1
  79. package/dist/voice/integrations/makeCreateContainer.js +1 -1
  80. package/dist/voice/integrations/types.d.ts +1 -1
  81. package/dist/voice/makeCreateVoiceClient.js +4 -10
  82. package/dist/voice/makeGetChannelVar.d.ts +2 -1
  83. package/dist/voice/makeGetChannelVar.js +13 -0
  84. package/dist/voice/stt/AbstractSpeechToText.d.ts +4 -3
  85. package/dist/voice/stt/Deepgram.d.ts +18 -0
  86. package/dist/voice/stt/Deepgram.js +156 -0
  87. package/dist/voice/stt/Google.d.ts +5 -6
  88. package/dist/voice/stt/Google.js +13 -13
  89. package/dist/voice/stt/SpeechToTextFactory.js +2 -0
  90. package/dist/voice/stt/types.d.ts +22 -10
  91. package/dist/voice/stt/types.js +7 -0
  92. package/dist/voice/tts/Deepgram.d.ts +25 -0
  93. package/dist/voice/tts/Deepgram.js +122 -0
  94. package/dist/voice/tts/Google.d.ts +2 -1
  95. package/dist/voice/tts/Google.js +7 -8
  96. package/dist/voice/tts/TextToSpeechFactory.js +2 -0
  97. package/dist/voice/types/ari.d.ts +2 -1
  98. package/dist/voice/types/ari.js +1 -0
  99. package/dist/voice/types/voice.d.ts +9 -1
  100. package/package.json +10 -9
  101. package/dist/calls/createTrackCallSubscriber.d.ts +0 -5
  102. package/dist/calls/createTrackCallSubscriber.js +0 -52
  103. package/dist/calls/trackCall.js +0 -63
  104. package/dist/voice/handlers/StasisEnd.d.ts +0 -4
  105. package/dist/voice/handlers/dial/handleDialEvents.d.ts +0 -5
  106. /package/dist/voice/handlers/{awaitForPlaybackFinished.d.ts → utils/awaitForPlaybackFinished.d.ts} +0 -0
  107. /package/dist/voice/handlers/{awaitForRecordingFinished.d.ts → utils/awaitForRecordingFinished.d.ts} +0 -0
  108. /package/dist/voice/handlers/{withErrorHandling.d.ts → utils/withErrorHandling.d.ts} +0 -0
  109. /package/dist/voice/handlers/{withErrorHandling.js → utils/withErrorHandling.js} +0 -0
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /*
18
+ * Copyright (C) 2024 by Fonoster Inc (https://fonoster.com)
19
+ * http://github.com/fonoster/fonoster
20
+ *
21
+ * This file is part of Fonoster
22
+ *
23
+ * Licensed under the MIT License (the "License");
24
+ * you may not use this file except in compliance with
25
+ * the License. You may obtain a copy of the License at
26
+ *
27
+ * https://opensource.org/licenses/MIT
28
+ *
29
+ * Unless required by applicable law or agreed to in writing, software
30
+ * distributed under the License is distributed on an "AS IS" BASIS,
31
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32
+ * See the License for the specific language governing permissions and
33
+ * limitations under the License.
34
+ */
35
+ __exportStar(require("./awaitForPlaybackFinished"), exports);
36
+ __exportStar(require("./awaitForRecordingFinished"), exports);
37
+ __exportStar(require("./isDtmf"), exports);
@@ -0,0 +1,2 @@
1
+ declare function isDtmf(digit: string): boolean;
2
+ export { isDtmf };
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isDtmf = isDtmf;
4
+ /*
5
+ * Copyright (C) 2024 by Fonoster Inc (https://fonoster.com)
6
+ * http://github.com/fonoster/fonoster
7
+ *
8
+ * This file is part of Fonoster
9
+ *
10
+ * Licensed under the MIT License (the "License");
11
+ * you may not use this file except in compliance with
12
+ * the License. You may obtain a copy of the License at
13
+ *
14
+ * https://opensource.org/licenses/MIT
15
+ *
16
+ * Unless required by applicable law or agreed to in writing, software
17
+ * distributed under the License is distributed on an "AS IS" BASIS,
18
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ * See the License for the specific language governing permissions and
20
+ * limitations under the License.
21
+ */
22
+ function isDtmf(digit) {
23
+ return /^[0-9*#]+$/.test(digit);
24
+ }
@@ -1,3 +1,3 @@
1
1
  import { IntegrationConfig } from "./types";
2
- declare function findIntegrationsCredentials(integrations: IntegrationConfig[], engine: string): IntegrationConfig;
2
+ declare function findIntegrationsCredentials(integrations: IntegrationConfig[], engine: string): Record<string, unknown>;
3
3
  export { findIntegrationsCredentials };
@@ -2,5 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.findIntegrationsCredentials = findIntegrationsCredentials;
4
4
  function findIntegrationsCredentials(integrations, engine) {
5
- return integrations.find((i) => i.productRef === engine);
5
+ var _a;
6
+ return (_a = integrations.find((i) => i.productRef === engine)) === null || _a === void 0 ? void 0 : _a.credentials;
6
7
  }
@@ -2,7 +2,9 @@ import { VoiceLanguage } from "@fonoster/common";
2
2
  import { Application } from "@fonoster/types";
3
3
  import { IntegrationConfig } from "./types";
4
4
  declare function getSttConfig(integrations: IntegrationConfig[], app: Application): {
5
- credentials: IntegrationConfig;
6
- languageCode: VoiceLanguage;
5
+ config: {
6
+ languageCode: VoiceLanguage;
7
+ };
8
+ credentials: Record<string, unknown>;
7
9
  };
8
10
  export { getSttConfig };
@@ -5,5 +5,8 @@ const findIntegrationsCredentials_1 = require("./findIntegrationsCredentials");
5
5
  function getSttConfig(integrations, app) {
6
6
  const config = app.speechToText.config;
7
7
  const credentials = (0, findIntegrationsCredentials_1.findIntegrationsCredentials)(integrations, app.speechToText.productRef);
8
- return Object.assign(Object.assign({}, config), { credentials });
8
+ return {
9
+ config,
10
+ credentials
11
+ };
9
12
  }
@@ -1,7 +1,8 @@
1
1
  import { Application } from "@fonoster/types";
2
2
  import { IntegrationConfig } from "./types";
3
3
  declare function getTtsConfig(integrations: IntegrationConfig[], app: Application): {
4
- credentials: IntegrationConfig;
4
+ config: Record<string, unknown>;
5
+ credentials: Record<string, unknown>;
5
6
  pathToFiles: string;
6
7
  };
7
8
  export { getTtsConfig };
@@ -6,5 +6,9 @@ const envs_1 = require("../../envs");
6
6
  function getTtsConfig(integrations, app) {
7
7
  const config = app.textToSpeech.config;
8
8
  const credentials = (0, findIntegrationsCredentials_1.findIntegrationsCredentials)(integrations, app.textToSpeech.productRef);
9
- return Object.assign(Object.assign({}, config), { credentials, pathToFiles: envs_1.TTS_PATH_TO_FILES });
9
+ return {
10
+ config,
11
+ credentials,
12
+ pathToFiles: envs_1.TTS_PATH_TO_FILES
13
+ };
10
14
  }
@@ -80,7 +80,7 @@ function makeCreateContainer(prisma, pathToIntegrations) {
80
80
  return {
81
81
  ref: appRef,
82
82
  accessKeyId: app.accessKeyId,
83
- appEndpoint: app.appEndpoint,
83
+ endpoint: app.endpoint,
84
84
  tts,
85
85
  stt
86
86
  };
@@ -7,7 +7,7 @@ type IntegrationConfig = {
7
7
  type IntegrationsContainer = {
8
8
  ref: string;
9
9
  accessKeyId: string;
10
- appEndpoint: string;
10
+ endpoint: string;
11
11
  tts: AbstractTextToSpeech<unknown>;
12
12
  stt: AbstractSpeechToText<unknown>;
13
13
  };
@@ -43,24 +43,18 @@ function makeCreateVoiceClient(createContainer) {
43
43
  const { ari, event, channel } = params;
44
44
  const { id: sessionRef, caller } = event.channel;
45
45
  const { name: callerName, number: callerNumber } = caller;
46
- const getChannelVar = (0, makeGetChannelVar_1.makeGetChannelVar)(channel);
46
+ const getChannelVar = (0, makeGetChannelVar_1.makeGetChannelVarWithoutThrow)(channel);
47
47
  // Variables set by Asterisk's dialplan
48
48
  const appRef = (_a = (yield getChannelVar(types_1.ChannelVar.APP_REF))) === null || _a === void 0 ? void 0 : _a.value;
49
49
  const ingressNumber = ((_b = (yield getChannelVar(types_1.ChannelVar.INGRESS_NUMBER))) === null || _b === void 0 ? void 0 : _b.value) || "";
50
- const { accessKeyId, appEndpoint, tts, stt } = yield createContainer(appRef);
50
+ const { accessKeyId, endpoint, tts, stt } = yield createContainer(appRef);
51
51
  const sessionToken = yield createToken({ accessKeyId, appRef });
52
- let metadataStr;
53
- try {
54
- metadataStr = (_c = (yield getChannelVar(types_1.ChannelVar.METADATA))) === null || _c === void 0 ? void 0 : _c.value;
55
- }
56
- catch (e) {
57
- // Do nothing
58
- }
52
+ const metadataStr = (_c = (yield getChannelVar(types_1.ChannelVar.METADATA))) === null || _c === void 0 ? void 0 : _c.value;
59
53
  const config = {
60
54
  appRef,
61
55
  sessionRef,
62
56
  accessKeyId,
63
- appEndpoint,
57
+ endpoint,
64
58
  callerName,
65
59
  callerNumber,
66
60
  ingressNumber,
@@ -1,4 +1,5 @@
1
1
  import { Channel } from "ari-client";
2
2
  import { ChannelVar } from "./types";
3
3
  declare function makeGetChannelVar(channel: Channel): (variable: ChannelVar) => Promise<import("ari-client").Variable>;
4
- export { makeGetChannelVar };
4
+ declare function makeGetChannelVarWithoutThrow(channel: Channel): (variable: ChannelVar) => Promise<import("ari-client").Variable>;
5
+ export { makeGetChannelVar, makeGetChannelVarWithoutThrow };
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.makeGetChannelVar = makeGetChannelVar;
13
+ exports.makeGetChannelVarWithoutThrow = makeGetChannelVarWithoutThrow;
13
14
  const ChannelVarNotFoundError_1 = require("./ChannelVarNotFoundError");
14
15
  function makeGetChannelVar(channel) {
15
16
  return (variable) => __awaiter(this, void 0, void 0, function* () {
@@ -23,3 +24,15 @@ function makeGetChannelVar(channel) {
23
24
  }
24
25
  });
25
26
  }
27
+ function makeGetChannelVarWithoutThrow(channel) {
28
+ return (variable) => __awaiter(this, void 0, void 0, function* () {
29
+ try {
30
+ return yield channel.getChannelVar({
31
+ variable
32
+ });
33
+ }
34
+ catch (e) {
35
+ return null;
36
+ }
37
+ });
38
+ }
@@ -1,11 +1,12 @@
1
1
  import { Stream } from "stream";
2
2
  import * as z from "zod";
3
- import { SpeechResult, StreamSpeechResult, SttConfig } from "./types";
4
- declare abstract class AbstractSpeechToText<E, T extends SttConfig = SttConfig> {
3
+ import { SpeechResult, StreamSpeech, SttConfig } from "./types";
4
+ import { SpeechToText } from "../types";
5
+ declare abstract class AbstractSpeechToText<E, T extends SttConfig = SttConfig> implements SpeechToText {
5
6
  abstract readonly engineName: E;
6
7
  config: T;
7
8
  constructor(config: T);
8
- abstract streamTranscribe(stream: Stream): StreamSpeechResult;
9
+ abstract streamTranscribe(stream: Stream): StreamSpeech;
9
10
  abstract transcribe(stream: Stream): Promise<SpeechResult>;
10
11
  getName(): E;
11
12
  static getConfigValidationSchema(): z.Schema;
@@ -0,0 +1,18 @@
1
+ import { Stream } from "stream";
2
+ import * as z from "zod";
3
+ import { AbstractSpeechToText } from "./AbstractSpeechToText";
4
+ import { DeepgramSttConfig, SpeechResult, StreamSpeech } from "./types";
5
+ import { SpeechToText } from "../types";
6
+ declare const DeepgramClient: any;
7
+ declare const ENGINE_NAME = "stt.deepgram";
8
+ declare class Deepgram extends AbstractSpeechToText<typeof ENGINE_NAME> implements SpeechToText {
9
+ client: typeof DeepgramClient;
10
+ engineConfig: DeepgramSttConfig;
11
+ readonly engineName = "stt.deepgram";
12
+ constructor(config: DeepgramSttConfig);
13
+ streamTranscribe(stream: Stream): StreamSpeech;
14
+ transcribe(stream: Stream): Promise<SpeechResult>;
15
+ static getConfigValidationSchema(): z.Schema;
16
+ static getCredentialsValidationSchema(): z.Schema;
17
+ }
18
+ export { Deepgram, ENGINE_NAME };
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.ENGINE_NAME = exports.Deepgram = void 0;
36
+ /* eslint-disable @typescript-eslint/no-var-requires */
37
+ /*
38
+ * Copyright (C) 2024 by Fonoster Inc (https://fonoster.com)
39
+ * http://github.com/fonoster/fonoster
40
+ *
41
+ * This file is part of Fonoster
42
+ *
43
+ * Licensed under the MIT License (the "License");
44
+ * you may not use this file except in compliance with
45
+ * the License. You may obtain a copy of the License at
46
+ *
47
+ * https://opensource.org/licenses/MIT
48
+ *
49
+ * Unless required by applicable law or agreed to in writing, software
50
+ * distributed under the License is distributed on an "AS IS" BASIS,
51
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
52
+ * See the License for the specific language governing permissions and
53
+ * limitations under the License.
54
+ */
55
+ const stream_1 = require("stream");
56
+ const common_1 = require("@fonoster/common");
57
+ const logger_1 = require("@fonoster/logger");
58
+ const z = __importStar(require("zod"));
59
+ const AbstractSpeechToText_1 = require("./AbstractSpeechToText");
60
+ const types_1 = require("./types");
61
+ const { DeepgramClient, LiveTranscriptionEvents, createClient } = require("@deepgram/sdk"); // Why Deepgram :(
62
+ const ENGINE_NAME = "stt.deepgram";
63
+ exports.ENGINE_NAME = ENGINE_NAME;
64
+ const logger = (0, logger_1.getLogger)({ service: "apiserver", filePath: __filename });
65
+ class Deepgram extends AbstractSpeechToText_1.AbstractSpeechToText {
66
+ constructor(config) {
67
+ super(config);
68
+ this.engineName = ENGINE_NAME;
69
+ this.client = createClient(config.credentials.apiKey);
70
+ this.engineConfig = config;
71
+ }
72
+ streamTranscribe(stream) {
73
+ const connection = this.client.listen.live(buildTranscribeConfig(this.engineConfig.config));
74
+ const out = new stream_1.Stream();
75
+ connection.on(LiveTranscriptionEvents.Open, () => {
76
+ // WARNING: This is a workaround to keep the connection open while the system
77
+ // is playing a file which causes the stream to be paused. We need to look into why
78
+ // the stream is being paused.
79
+ const keepAliveInterval = setInterval(() => {
80
+ const keepAliveMsg = JSON.stringify({ type: "KeepAlive" });
81
+ connection.send(keepAliveMsg);
82
+ }, 3000);
83
+ stream.on("data", (chunk) => {
84
+ connection.send(chunk);
85
+ });
86
+ connection.on(LiveTranscriptionEvents.Transcript, (data) => {
87
+ if (!data.channel.alternatives[0].transcript || !data.speech_final) {
88
+ return;
89
+ }
90
+ out.emit("data", {
91
+ speech: data.channel.alternatives[0].transcript
92
+ });
93
+ });
94
+ connection.on(LiveTranscriptionEvents.Error, (err) => {
95
+ logger.warn("error on Deepgram connection", { err });
96
+ clearInterval(keepAliveInterval);
97
+ connection.destroy();
98
+ });
99
+ });
100
+ return out;
101
+ }
102
+ transcribe(stream) {
103
+ return __awaiter(this, void 0, void 0, function* () {
104
+ return new Promise((resolve, reject) => {
105
+ const connection = this.client.listen.live(buildTranscribeConfig(this.engineConfig.config));
106
+ stream.on("data", (chunk) => {
107
+ connection.send(chunk);
108
+ });
109
+ connection.on(LiveTranscriptionEvents.Open, () => {
110
+ connection.on(LiveTranscriptionEvents.Transcript, (data) => {
111
+ if (data.channel.alternatives[0].transcript && data.speech_final) {
112
+ const result = {
113
+ speech: data.channel.alternatives[0].transcript,
114
+ isFinal: true
115
+ };
116
+ resolve(result);
117
+ connection.destroy();
118
+ }
119
+ });
120
+ connection.on(LiveTranscriptionEvents.Error, (err) => {
121
+ logger.warn("error on Deepgram connection", { err });
122
+ reject(err);
123
+ });
124
+ });
125
+ stream.on("end", () => {
126
+ connection.destroy();
127
+ });
128
+ stream.on("error", (err) => {
129
+ connection.destroy();
130
+ reject(err);
131
+ });
132
+ });
133
+ });
134
+ }
135
+ static getConfigValidationSchema() {
136
+ return z.object({
137
+ languageCode: z.nativeEnum(common_1.VoiceLanguage).optional().nullable(),
138
+ model: z.nativeEnum(types_1.DeepgramModel).optional().nullable()
139
+ });
140
+ }
141
+ static getCredentialsValidationSchema() {
142
+ return z.object({
143
+ apiKey: z.string()
144
+ });
145
+ }
146
+ }
147
+ exports.Deepgram = Deepgram;
148
+ function buildTranscribeConfig(config) {
149
+ return {
150
+ model: config.model || types_1.DeepgramModel.NOVA_2_PHONECALL,
151
+ encoding: "linear16",
152
+ sample_rate: 16000,
153
+ language: config.languageCode || common_1.VoiceLanguage.EN_US,
154
+ smart_format: true
155
+ };
156
+ }
@@ -2,16 +2,15 @@ import { Stream } from "stream";
2
2
  import { SpeechClient } from "@google-cloud/speech";
3
3
  import * as z from "zod";
4
4
  import { AbstractSpeechToText } from "./AbstractSpeechToText";
5
- import { GoogleSttConfig, SpeechResult, StreamSpeechResult } from "./types";
5
+ import { GoogleSttConfig, SpeechResult, StreamSpeech } from "./types";
6
+ import { SpeechToText } from "../types";
6
7
  declare const ENGINE_NAME = "stt.google";
7
- declare class Google extends AbstractSpeechToText<typeof ENGINE_NAME> {
8
+ declare class Google extends AbstractSpeechToText<typeof ENGINE_NAME> implements SpeechToText {
8
9
  client: SpeechClient;
9
- config: GoogleSttConfig;
10
+ engineConfig: GoogleSttConfig;
10
11
  readonly engineName = "stt.google";
11
- protected readonly AUDIO_ENCODING = "LINEAR16";
12
- protected readonly SAMPLE_RATE_HERTZ = 16000;
13
12
  constructor(config: GoogleSttConfig);
14
- streamTranscribe(_: Stream): StreamSpeechResult;
13
+ streamTranscribe(_: Stream): StreamSpeech;
15
14
  transcribe(stream: Stream): Promise<SpeechResult>;
16
15
  static getConfigValidationSchema(): z.Schema;
17
16
  static getCredentialsValidationSchema(): z.Schema;
@@ -39,32 +39,32 @@ const z = __importStar(require("zod"));
39
39
  const AbstractSpeechToText_1 = require("./AbstractSpeechToText");
40
40
  const ENGINE_NAME = "stt.google";
41
41
  exports.ENGINE_NAME = ENGINE_NAME;
42
- const AUDIO_ENCODING = "LINEAR16";
43
- const SAMPLE_RATE_HERTZ = 16000;
44
42
  class Google extends AbstractSpeechToText_1.AbstractSpeechToText {
45
43
  constructor(config) {
46
44
  super(config);
47
45
  this.engineName = ENGINE_NAME;
48
- this.AUDIO_ENCODING = AUDIO_ENCODING;
49
- this.SAMPLE_RATE_HERTZ = SAMPLE_RATE_HERTZ;
50
46
  this.client = new speech_1.SpeechClient(config);
51
- this.config = Object.assign(Object.assign({}, config), { config: {
52
- encoding: AUDIO_ENCODING,
53
- sampleRateHertz: SAMPLE_RATE_HERTZ,
54
- interimResults: false,
55
- languageCode: config.languageCode
56
- } });
47
+ this.engineConfig = config;
57
48
  }
58
49
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
59
50
  streamTranscribe(_) {
60
51
  // Not implemented
61
- return null;
52
+ throw new Error("Stream Transcribe not implemented for Google Engine");
62
53
  }
63
54
  transcribe(stream) {
64
55
  return __awaiter(this, void 0, void 0, function* () {
56
+ const languageCode = this.engineConfig.config.languageCode || common_1.VoiceLanguage.EN_US;
57
+ const audioConfig = {
58
+ interimResults: false,
59
+ config: {
60
+ encoding: "LINEAR16",
61
+ sampleRateHertz: 16000,
62
+ languageCode
63
+ }
64
+ };
65
65
  return new Promise((resolve, reject) => {
66
66
  const recognizeStream = this.client
67
- .streamingRecognize(this.config)
67
+ .streamingRecognize(audioConfig)
68
68
  .on("error", (e) => reject(e))
69
69
  .on("data", (data) => {
70
70
  var _a;
@@ -86,7 +86,7 @@ class Google extends AbstractSpeechToText_1.AbstractSpeechToText {
86
86
  }
87
87
  static getConfigValidationSchema() {
88
88
  return z.object({
89
- languageCode: z.nativeEnum(common_1.VoiceLanguage)
89
+ languageCode: z.nativeEnum(common_1.VoiceLanguage).optional().nullable()
90
90
  });
91
91
  }
92
92
  static getCredentialsValidationSchema() {
@@ -20,6 +20,7 @@ exports.SpeechToTextFactory = void 0;
20
20
  * limitations under the License.
21
21
  */
22
22
  const logger_1 = require("@fonoster/logger");
23
+ const Deepgram_1 = require("./Deepgram");
23
24
  const Google_1 = require("./Google");
24
25
  const logger = (0, logger_1.getLogger)({ service: "apiserver", filePath: __filename });
25
26
  class SpeechToTextFactory {
@@ -39,3 +40,4 @@ exports.SpeechToTextFactory = SpeechToTextFactory;
39
40
  SpeechToTextFactory.engines = new Map();
40
41
  // Register engines
41
42
  SpeechToTextFactory.registerEngine(Google_1.ENGINE_NAME, Google_1.Google);
43
+ SpeechToTextFactory.registerEngine(Deepgram_1.ENGINE_NAME, Deepgram_1.Deepgram);
@@ -1,20 +1,23 @@
1
1
  import { VoiceLanguage } from "@fonoster/common/src/tts/types";
2
- type SttConfig = {
3
- languageCode: VoiceLanguage;
4
- };
2
+ declare enum DeepgramModel {
3
+ NOVA_2 = "nova-2",
4
+ NOVA_2_PHONECALL = "nova-2-phonecall",
5
+ NOVA_2_CONVERSATIONALAI = "nova-2-conversationalai"
6
+ }
5
7
  type SpeechResult = {
6
8
  speech: string;
7
9
  isFinal: boolean;
8
10
  };
9
- type StreamSpeechResult = {
11
+ type StreamSpeech = {
10
12
  on(events: string, callback: (result: SpeechResult) => void): void;
11
- close: () => void;
12
13
  };
13
- type GoogleSttConfig = SttConfig & {
14
+ type SttConfig = {
15
+ config: {
16
+ languageCode: VoiceLanguage;
17
+ };
18
+ };
19
+ type GoogleSttConfig = {
14
20
  config: {
15
- encoding: "LINEAR16";
16
- sampleRateHertz: 16000;
17
- interimResults: boolean;
18
21
  languageCode: VoiceLanguage;
19
22
  };
20
23
  credentials: {
@@ -22,4 +25,13 @@ type GoogleSttConfig = SttConfig & {
22
25
  private_key: string;
23
26
  };
24
27
  };
25
- export { SttConfig, SpeechResult, StreamSpeechResult, GoogleSttConfig };
28
+ type DeepgramSttConfig = {
29
+ config: {
30
+ languageCode: VoiceLanguage;
31
+ model: DeepgramModel;
32
+ };
33
+ credentials: {
34
+ apiKey: string;
35
+ };
36
+ };
37
+ export { SpeechResult, StreamSpeech, SttConfig, GoogleSttConfig, DeepgramSttConfig, DeepgramModel };
@@ -1,2 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DeepgramModel = void 0;
4
+ var DeepgramModel;
5
+ (function (DeepgramModel) {
6
+ DeepgramModel["NOVA_2"] = "nova-2";
7
+ DeepgramModel["NOVA_2_PHONECALL"] = "nova-2-phonecall";
8
+ DeepgramModel["NOVA_2_CONVERSATIONALAI"] = "nova-2-conversationalai";
9
+ })(DeepgramModel || (exports.DeepgramModel = DeepgramModel = {}));
@@ -0,0 +1,25 @@
1
+ import * as z from "zod";
2
+ import { AbstractTextToSpeech } from "./AbstractTextToSpeech";
3
+ import { SynthOptions, TtsConfig } from "./types";
4
+ declare const DeepgramClient: any;
5
+ declare const ENGINE_NAME = "tts.deepgram";
6
+ type DeepgramTtsConfig = TtsConfig & {
7
+ [key: string]: Record<string, string>;
8
+ credentials: {
9
+ apiKey: string;
10
+ };
11
+ };
12
+ declare class Deepgram extends AbstractTextToSpeech<typeof ENGINE_NAME> {
13
+ client: typeof DeepgramClient;
14
+ engineConfig: DeepgramTtsConfig;
15
+ readonly engineName = "tts.deepgram";
16
+ protected readonly OUTPUT_FORMAT = "sln16";
17
+ protected readonly CACHING_FIELDS: string[];
18
+ protected readonly AUDIO_ENCODING: "linear16";
19
+ protected readonly SAMPLE_RATE_HERTZ = 16000;
20
+ constructor(config: DeepgramTtsConfig);
21
+ synthesize(text: string, options: SynthOptions): Promise<string>;
22
+ static getConfigValidationSchema(): z.Schema;
23
+ static getCredentialsValidationSchema(): z.Schema;
24
+ }
25
+ export { Deepgram, ENGINE_NAME };