@juspay/neurolink 8.12.0 → 8.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/CHANGELOG.md +6 -0
- package/dist/lib/types/ttsTypes.d.ts +0 -29
- package/dist/lib/utils/ttsProcessor.d.ts +112 -1
- package/dist/lib/utils/ttsProcessor.js +182 -0
- package/dist/types/ttsTypes.d.ts +0 -29
- package/dist/utils/ttsProcessor.d.ts +112 -1
- package/dist/utils/ttsProcessor.js +182 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [8.13.0](https://github.com/juspay/neurolink/compare/v8.12.0...v8.13.0) (2025-12-13)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
- **(tts):** Implement TTSProcessor.synthesize() method ([d6f3567](https://github.com/juspay/neurolink/commit/d6f3567dda26191f0ca9fd82a8cd7ccff5c9f819))
|
|
6
|
+
|
|
1
7
|
## [8.12.0](https://github.com/juspay/neurolink/compare/v8.11.0...v8.12.0) (2025-12-13)
|
|
2
8
|
|
|
3
9
|
### Features
|
|
@@ -85,35 +85,6 @@ export declare const VALID_TTS_QUALITIES: readonly TTSQuality[];
|
|
|
85
85
|
* Type guard to check if an object is a TTSResult
|
|
86
86
|
*/
|
|
87
87
|
export declare function isTTSResult(value: unknown): value is TTSResult;
|
|
88
|
-
/**
|
|
89
|
-
* TTS Handler type for provider-specific implementations
|
|
90
|
-
*
|
|
91
|
-
* Each provider (Google AI, OpenAI, etc.) implements this type
|
|
92
|
-
* to provide TTS generation capabilities using their respective APIs.
|
|
93
|
-
*/
|
|
94
|
-
export type TTSHandler = {
|
|
95
|
-
/**
|
|
96
|
-
* Generate audio from text using provider-specific TTS API
|
|
97
|
-
*
|
|
98
|
-
* @param text - Text to convert to speech
|
|
99
|
-
* @param options - TTS configuration options
|
|
100
|
-
* @returns Audio buffer with metadata
|
|
101
|
-
*/
|
|
102
|
-
synthesize(text: string, options: TTSOptions): Promise<TTSResult>;
|
|
103
|
-
/**
|
|
104
|
-
* Get available voices for the provider
|
|
105
|
-
*
|
|
106
|
-
* @param languageCode - Optional language filter (e.g., "en-US")
|
|
107
|
-
* @returns List of available voices
|
|
108
|
-
*/
|
|
109
|
-
getVoices(languageCode?: string): Promise<TTSVoice[]>;
|
|
110
|
-
/**
|
|
111
|
-
* Validate that the provider is properly configured
|
|
112
|
-
*
|
|
113
|
-
* @returns True if provider can generate TTS
|
|
114
|
-
*/
|
|
115
|
-
isConfigured(): boolean;
|
|
116
|
-
};
|
|
117
88
|
/**
|
|
118
89
|
* Type guard to check if TTSOptions are valid
|
|
119
90
|
*/
|
|
@@ -6,7 +6,69 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module utils/ttsProcessor
|
|
8
8
|
*/
|
|
9
|
-
import type {
|
|
9
|
+
import type { TTSOptions, TTSResult, TTSVoice } from "../types/ttsTypes.js";
|
|
10
|
+
import { ErrorCategory, ErrorSeverity } from "../constants/enums.js";
|
|
11
|
+
import { NeuroLinkError } from "./errorHandling.js";
|
|
12
|
+
/**
|
|
13
|
+
* TTS-specific error codes
|
|
14
|
+
*/
|
|
15
|
+
export declare const TTS_ERROR_CODES: {
|
|
16
|
+
readonly EMPTY_TEXT: "TTS_EMPTY_TEXT";
|
|
17
|
+
readonly TEXT_TOO_LONG: "TTS_TEXT_TOO_LONG";
|
|
18
|
+
readonly PROVIDER_NOT_SUPPORTED: "TTS_PROVIDER_NOT_SUPPORTED";
|
|
19
|
+
readonly PROVIDER_NOT_CONFIGURED: "TTS_PROVIDER_NOT_CONFIGURED";
|
|
20
|
+
readonly SYNTHESIS_FAILED: "TTS_SYNTHESIS_FAILED";
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* TTS Error class for text-to-speech specific errors
|
|
24
|
+
*/
|
|
25
|
+
export declare class TTSError extends NeuroLinkError {
|
|
26
|
+
constructor(options: {
|
|
27
|
+
code: string;
|
|
28
|
+
message: string;
|
|
29
|
+
category?: ErrorCategory;
|
|
30
|
+
severity?: ErrorSeverity;
|
|
31
|
+
retriable?: boolean;
|
|
32
|
+
context?: Record<string, unknown>;
|
|
33
|
+
originalError?: Error;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* TTS Handler interface for provider-specific implementations
|
|
38
|
+
*
|
|
39
|
+
* Each provider (Google AI, OpenAI, etc.) implements this interface
|
|
40
|
+
* to provide TTS generation capabilities using their respective APIs.
|
|
41
|
+
*/
|
|
42
|
+
export interface TTSHandler {
|
|
43
|
+
/**
|
|
44
|
+
* Generate audio from text using provider-specific TTS API
|
|
45
|
+
*
|
|
46
|
+
* @param text - Text to convert to speech
|
|
47
|
+
* @param options - TTS configuration options
|
|
48
|
+
* @returns Audio buffer with metadata
|
|
49
|
+
*/
|
|
50
|
+
synthesize(text: string, options: TTSOptions): Promise<TTSResult>;
|
|
51
|
+
/**
|
|
52
|
+
* Get available voices for the provider
|
|
53
|
+
*
|
|
54
|
+
* @param languageCode - Optional language filter (e.g., "en-US")
|
|
55
|
+
* @returns List of available voices
|
|
56
|
+
*/
|
|
57
|
+
getVoices?(languageCode?: string): Promise<TTSVoice[]>;
|
|
58
|
+
/**
|
|
59
|
+
* Validate that the provider is properly configured
|
|
60
|
+
*
|
|
61
|
+
* @returns True if provider can generate TTS
|
|
62
|
+
*/
|
|
63
|
+
isConfigured(): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Maximum text length supported by this provider (in characters)
|
|
66
|
+
* Different providers have different limits
|
|
67
|
+
*
|
|
68
|
+
* @default 3000 if not specified
|
|
69
|
+
*/
|
|
70
|
+
maxTextLength?: number;
|
|
71
|
+
}
|
|
10
72
|
/**
|
|
11
73
|
* TTS processor class for orchestrating text-to-speech operations
|
|
12
74
|
*
|
|
@@ -32,6 +94,26 @@ export declare class TTSProcessor {
|
|
|
32
94
|
* @private
|
|
33
95
|
*/
|
|
34
96
|
private static readonly handlers;
|
|
97
|
+
/**
|
|
98
|
+
* Default maximum text length for TTS synthesis (characters)
|
|
99
|
+
*
|
|
100
|
+
* Providers can override this value by specifying the `maxTextLength` property
|
|
101
|
+
* in their respective `TTSHandler` implementation. If not specified, this default
|
|
102
|
+
* value will be used.
|
|
103
|
+
*
|
|
104
|
+
* @private
|
|
105
|
+
*/
|
|
106
|
+
private static readonly DEFAULT_MAX_TEXT_LENGTH;
|
|
107
|
+
/**
|
|
108
|
+
* Default timeout for TTS synthesis operations (milliseconds)
|
|
109
|
+
*
|
|
110
|
+
* This timeout prevents indefinite hangs in provider API calls and serves as
|
|
111
|
+
* a safety net for all TTS operations. Individual handlers may implement
|
|
112
|
+
* shorter provider-specific timeouts.
|
|
113
|
+
*
|
|
114
|
+
* @private
|
|
115
|
+
*/
|
|
116
|
+
private static readonly DEFAULT_SYNTHESIS_TIMEOUT_MS;
|
|
35
117
|
/**
|
|
36
118
|
* Register a TTS handler for a specific provider
|
|
37
119
|
*
|
|
@@ -74,4 +156,33 @@ export declare class TTSProcessor {
|
|
|
74
156
|
* ```
|
|
75
157
|
*/
|
|
76
158
|
static supports(providerName: string): boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Synthesize speech from text using a registered TTS provider
|
|
161
|
+
*
|
|
162
|
+
* Orchestrates the text-to-speech generation process:
|
|
163
|
+
* 1. Validates input text (not empty, within length limits)
|
|
164
|
+
* 2. Looks up the provider handler
|
|
165
|
+
* 3. Verifies provider configuration
|
|
166
|
+
* 4. Delegates synthesis to the provider
|
|
167
|
+
* 5. Enriches result with metadata
|
|
168
|
+
*
|
|
169
|
+
* @param text - Text to convert to speech
|
|
170
|
+
* @param provider - Provider identifier
|
|
171
|
+
* @param options - TTS configuration options
|
|
172
|
+
* @returns Audio result with buffer and metadata
|
|
173
|
+
* @throws TTSError if validation fails, provider not supported/configured, or synthesis times out
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* const result = await TTSProcessor.synthesize("Hello, world!", "google-ai", {
|
|
178
|
+
* voice: "en-US-Neural2-C",
|
|
179
|
+
* format: "mp3",
|
|
180
|
+
* speed: 1.0
|
|
181
|
+
* });
|
|
182
|
+
*
|
|
183
|
+
* console.log(`Generated ${result.size} bytes of ${result.format} audio`);
|
|
184
|
+
* // Save to file or play the audio buffer
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
static synthesize(text: string, provider: string, options: TTSOptions): Promise<TTSResult>;
|
|
77
188
|
}
|
|
@@ -7,6 +7,35 @@
|
|
|
7
7
|
* @module utils/ttsProcessor
|
|
8
8
|
*/
|
|
9
9
|
import { logger } from "./logger.js";
|
|
10
|
+
import { ErrorCategory, ErrorSeverity } from "../constants/enums.js";
|
|
11
|
+
import { NeuroLinkError, withTimeout } from "./errorHandling.js";
|
|
12
|
+
/**
|
|
13
|
+
* TTS-specific error codes
|
|
14
|
+
*/
|
|
15
|
+
export const TTS_ERROR_CODES = {
|
|
16
|
+
EMPTY_TEXT: "TTS_EMPTY_TEXT",
|
|
17
|
+
TEXT_TOO_LONG: "TTS_TEXT_TOO_LONG",
|
|
18
|
+
PROVIDER_NOT_SUPPORTED: "TTS_PROVIDER_NOT_SUPPORTED",
|
|
19
|
+
PROVIDER_NOT_CONFIGURED: "TTS_PROVIDER_NOT_CONFIGURED",
|
|
20
|
+
SYNTHESIS_FAILED: "TTS_SYNTHESIS_FAILED",
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* TTS Error class for text-to-speech specific errors
|
|
24
|
+
*/
|
|
25
|
+
export class TTSError extends NeuroLinkError {
|
|
26
|
+
constructor(options) {
|
|
27
|
+
super({
|
|
28
|
+
code: options.code,
|
|
29
|
+
message: options.message,
|
|
30
|
+
category: options.category ?? ErrorCategory.VALIDATION,
|
|
31
|
+
severity: options.severity ?? ErrorSeverity.MEDIUM,
|
|
32
|
+
retriable: options.retriable ?? false,
|
|
33
|
+
context: options.context,
|
|
34
|
+
originalError: options.originalError,
|
|
35
|
+
});
|
|
36
|
+
this.name = "TTSError";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
10
39
|
/**
|
|
11
40
|
* TTS processor class for orchestrating text-to-speech operations
|
|
12
41
|
*
|
|
@@ -32,6 +61,26 @@ export class TTSProcessor {
|
|
|
32
61
|
* @private
|
|
33
62
|
*/
|
|
34
63
|
static handlers = new Map();
|
|
64
|
+
/**
|
|
65
|
+
* Default maximum text length for TTS synthesis (characters)
|
|
66
|
+
*
|
|
67
|
+
* Providers can override this value by specifying the `maxTextLength` property
|
|
68
|
+
* in their respective `TTSHandler` implementation. If not specified, this default
|
|
69
|
+
* value will be used.
|
|
70
|
+
*
|
|
71
|
+
* @private
|
|
72
|
+
*/
|
|
73
|
+
static DEFAULT_MAX_TEXT_LENGTH = 3000;
|
|
74
|
+
/**
|
|
75
|
+
* Default timeout for TTS synthesis operations (milliseconds)
|
|
76
|
+
*
|
|
77
|
+
* This timeout prevents indefinite hangs in provider API calls and serves as
|
|
78
|
+
* a safety net for all TTS operations. Individual handlers may implement
|
|
79
|
+
* shorter provider-specific timeouts.
|
|
80
|
+
*
|
|
81
|
+
* @private
|
|
82
|
+
*/
|
|
83
|
+
static DEFAULT_SYNTHESIS_TIMEOUT_MS = 60000;
|
|
35
84
|
/**
|
|
36
85
|
* Register a TTS handler for a specific provider
|
|
37
86
|
*
|
|
@@ -101,5 +150,138 @@ export class TTSProcessor {
|
|
|
101
150
|
}
|
|
102
151
|
return isSupported;
|
|
103
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Synthesize speech from text using a registered TTS provider
|
|
155
|
+
*
|
|
156
|
+
* Orchestrates the text-to-speech generation process:
|
|
157
|
+
* 1. Validates input text (not empty, within length limits)
|
|
158
|
+
* 2. Looks up the provider handler
|
|
159
|
+
* 3. Verifies provider configuration
|
|
160
|
+
* 4. Delegates synthesis to the provider
|
|
161
|
+
* 5. Enriches result with metadata
|
|
162
|
+
*
|
|
163
|
+
* @param text - Text to convert to speech
|
|
164
|
+
* @param provider - Provider identifier
|
|
165
|
+
* @param options - TTS configuration options
|
|
166
|
+
* @returns Audio result with buffer and metadata
|
|
167
|
+
* @throws TTSError if validation fails, provider not supported/configured, or synthesis times out
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const result = await TTSProcessor.synthesize("Hello, world!", "google-ai", {
|
|
172
|
+
* voice: "en-US-Neural2-C",
|
|
173
|
+
* format: "mp3",
|
|
174
|
+
* speed: 1.0
|
|
175
|
+
* });
|
|
176
|
+
*
|
|
177
|
+
* console.log(`Generated ${result.size} bytes of ${result.format} audio`);
|
|
178
|
+
* // Save to file or play the audio buffer
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
static async synthesize(text, provider, options) {
|
|
182
|
+
// Trim the text once at the start
|
|
183
|
+
const trimmedText = text.trim();
|
|
184
|
+
// 1. Text validation: reject empty text
|
|
185
|
+
if (!trimmedText) {
|
|
186
|
+
logger.error("[TTSProcessor] Text is required for synthesis");
|
|
187
|
+
throw new TTSError({
|
|
188
|
+
code: TTS_ERROR_CODES.EMPTY_TEXT,
|
|
189
|
+
message: "Text is required for TTS synthesis",
|
|
190
|
+
severity: ErrorSeverity.LOW,
|
|
191
|
+
retriable: false,
|
|
192
|
+
context: { provider },
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// 2. Handler lookup and error if provider not supported
|
|
196
|
+
const handler = this.getHandler(provider);
|
|
197
|
+
if (!handler) {
|
|
198
|
+
logger.error(`[TTSProcessor] Provider "${provider}" is not registered`);
|
|
199
|
+
throw new TTSError({
|
|
200
|
+
code: TTS_ERROR_CODES.PROVIDER_NOT_SUPPORTED,
|
|
201
|
+
message: `TTS provider "${provider}" is not supported. Use TTSProcessor.registerHandler() to register it.`,
|
|
202
|
+
severity: ErrorSeverity.HIGH,
|
|
203
|
+
retriable: false,
|
|
204
|
+
context: {
|
|
205
|
+
provider,
|
|
206
|
+
availableProviders: Array.from(this.handlers.keys()),
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
// 3. Text validation: reject text exceeding provider-specific max length
|
|
211
|
+
const maxTextLength = handler.maxTextLength ?? this.DEFAULT_MAX_TEXT_LENGTH;
|
|
212
|
+
if (trimmedText.length > maxTextLength) {
|
|
213
|
+
logger.error(`[TTSProcessor] Text exceeds maximum length of ${maxTextLength} characters for provider "${provider}"`);
|
|
214
|
+
throw new TTSError({
|
|
215
|
+
code: TTS_ERROR_CODES.TEXT_TOO_LONG,
|
|
216
|
+
message: `Text length (${trimmedText.length}) exceeds maximum allowed length (${maxTextLength} characters) for provider "${provider}"`,
|
|
217
|
+
severity: ErrorSeverity.MEDIUM,
|
|
218
|
+
retriable: false,
|
|
219
|
+
context: {
|
|
220
|
+
provider,
|
|
221
|
+
textLength: trimmedText.length,
|
|
222
|
+
maxLength: maxTextLength,
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
// 4. Configuration check
|
|
227
|
+
if (!handler.isConfigured()) {
|
|
228
|
+
logger.warn(`[TTSProcessor] Provider "${provider}" is not properly configured`);
|
|
229
|
+
throw new TTSError({
|
|
230
|
+
code: TTS_ERROR_CODES.PROVIDER_NOT_CONFIGURED,
|
|
231
|
+
message: `TTS provider "${provider}" is not configured. Please set the required API keys.`,
|
|
232
|
+
category: ErrorCategory.CONFIGURATION,
|
|
233
|
+
severity: ErrorSeverity.HIGH,
|
|
234
|
+
retriable: false,
|
|
235
|
+
context: { provider },
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
try {
|
|
239
|
+
logger.debug(`[TTSProcessor] Starting synthesis with provider: ${provider}`);
|
|
240
|
+
// 5. Call handler.synthesize() with timeout protection (60 second safety net)
|
|
241
|
+
const result = await withTimeout(handler.synthesize(trimmedText, options), this.DEFAULT_SYNTHESIS_TIMEOUT_MS, new TTSError({
|
|
242
|
+
code: TTS_ERROR_CODES.SYNTHESIS_FAILED,
|
|
243
|
+
message: `TTS synthesis timeout for provider "${provider}" after ${this.DEFAULT_SYNTHESIS_TIMEOUT_MS}ms`,
|
|
244
|
+
category: ErrorCategory.EXECUTION,
|
|
245
|
+
severity: ErrorSeverity.HIGH,
|
|
246
|
+
retriable: true,
|
|
247
|
+
context: {
|
|
248
|
+
provider,
|
|
249
|
+
timeoutMs: this.DEFAULT_SYNTHESIS_TIMEOUT_MS,
|
|
250
|
+
textLength: trimmedText.length,
|
|
251
|
+
},
|
|
252
|
+
}));
|
|
253
|
+
// 6. Post-processing: add metadata
|
|
254
|
+
const enrichedResult = {
|
|
255
|
+
...result,
|
|
256
|
+
voice: result.voice ?? options.voice,
|
|
257
|
+
};
|
|
258
|
+
logger.info(`[TTSProcessor] Successfully synthesized ${result.size} bytes of audio`);
|
|
259
|
+
// 7. Returns TTSResult with buffer, format, metadata
|
|
260
|
+
return enrichedResult;
|
|
261
|
+
}
|
|
262
|
+
catch (err) {
|
|
263
|
+
// 8. Comprehensive error handling
|
|
264
|
+
// Re-throw TTSError as-is
|
|
265
|
+
if (err instanceof TTSError) {
|
|
266
|
+
throw err;
|
|
267
|
+
}
|
|
268
|
+
// Wrap other errors in TTSError
|
|
269
|
+
const errorMessage = err instanceof Error ? err.message : String(err || "Unknown error");
|
|
270
|
+
logger.error(`[TTSProcessor] Synthesis failed for provider "${provider}": ${errorMessage}`);
|
|
271
|
+
throw new TTSError({
|
|
272
|
+
code: TTS_ERROR_CODES.SYNTHESIS_FAILED,
|
|
273
|
+
message: `TTS synthesis failed for provider "${provider}": ${errorMessage}`,
|
|
274
|
+
category: ErrorCategory.EXECUTION,
|
|
275
|
+
severity: ErrorSeverity.HIGH,
|
|
276
|
+
retriable: true,
|
|
277
|
+
context: {
|
|
278
|
+
provider,
|
|
279
|
+
textLength: trimmedText.length,
|
|
280
|
+
options,
|
|
281
|
+
},
|
|
282
|
+
originalError: err instanceof Error ? err : undefined,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
104
286
|
}
|
|
105
287
|
//# sourceMappingURL=ttsProcessor.js.map
|
package/dist/types/ttsTypes.d.ts
CHANGED
|
@@ -85,35 +85,6 @@ export declare const VALID_TTS_QUALITIES: readonly TTSQuality[];
|
|
|
85
85
|
* Type guard to check if an object is a TTSResult
|
|
86
86
|
*/
|
|
87
87
|
export declare function isTTSResult(value: unknown): value is TTSResult;
|
|
88
|
-
/**
|
|
89
|
-
* TTS Handler type for provider-specific implementations
|
|
90
|
-
*
|
|
91
|
-
* Each provider (Google AI, OpenAI, etc.) implements this type
|
|
92
|
-
* to provide TTS generation capabilities using their respective APIs.
|
|
93
|
-
*/
|
|
94
|
-
export type TTSHandler = {
|
|
95
|
-
/**
|
|
96
|
-
* Generate audio from text using provider-specific TTS API
|
|
97
|
-
*
|
|
98
|
-
* @param text - Text to convert to speech
|
|
99
|
-
* @param options - TTS configuration options
|
|
100
|
-
* @returns Audio buffer with metadata
|
|
101
|
-
*/
|
|
102
|
-
synthesize(text: string, options: TTSOptions): Promise<TTSResult>;
|
|
103
|
-
/**
|
|
104
|
-
* Get available voices for the provider
|
|
105
|
-
*
|
|
106
|
-
* @param languageCode - Optional language filter (e.g., "en-US")
|
|
107
|
-
* @returns List of available voices
|
|
108
|
-
*/
|
|
109
|
-
getVoices(languageCode?: string): Promise<TTSVoice[]>;
|
|
110
|
-
/**
|
|
111
|
-
* Validate that the provider is properly configured
|
|
112
|
-
*
|
|
113
|
-
* @returns True if provider can generate TTS
|
|
114
|
-
*/
|
|
115
|
-
isConfigured(): boolean;
|
|
116
|
-
};
|
|
117
88
|
/**
|
|
118
89
|
* Type guard to check if TTSOptions are valid
|
|
119
90
|
*/
|
|
@@ -6,7 +6,69 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module utils/ttsProcessor
|
|
8
8
|
*/
|
|
9
|
-
import type {
|
|
9
|
+
import type { TTSOptions, TTSResult, TTSVoice } from "../types/ttsTypes.js";
|
|
10
|
+
import { ErrorCategory, ErrorSeverity } from "../constants/enums.js";
|
|
11
|
+
import { NeuroLinkError } from "./errorHandling.js";
|
|
12
|
+
/**
|
|
13
|
+
* TTS-specific error codes
|
|
14
|
+
*/
|
|
15
|
+
export declare const TTS_ERROR_CODES: {
|
|
16
|
+
readonly EMPTY_TEXT: "TTS_EMPTY_TEXT";
|
|
17
|
+
readonly TEXT_TOO_LONG: "TTS_TEXT_TOO_LONG";
|
|
18
|
+
readonly PROVIDER_NOT_SUPPORTED: "TTS_PROVIDER_NOT_SUPPORTED";
|
|
19
|
+
readonly PROVIDER_NOT_CONFIGURED: "TTS_PROVIDER_NOT_CONFIGURED";
|
|
20
|
+
readonly SYNTHESIS_FAILED: "TTS_SYNTHESIS_FAILED";
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* TTS Error class for text-to-speech specific errors
|
|
24
|
+
*/
|
|
25
|
+
export declare class TTSError extends NeuroLinkError {
|
|
26
|
+
constructor(options: {
|
|
27
|
+
code: string;
|
|
28
|
+
message: string;
|
|
29
|
+
category?: ErrorCategory;
|
|
30
|
+
severity?: ErrorSeverity;
|
|
31
|
+
retriable?: boolean;
|
|
32
|
+
context?: Record<string, unknown>;
|
|
33
|
+
originalError?: Error;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* TTS Handler interface for provider-specific implementations
|
|
38
|
+
*
|
|
39
|
+
* Each provider (Google AI, OpenAI, etc.) implements this interface
|
|
40
|
+
* to provide TTS generation capabilities using their respective APIs.
|
|
41
|
+
*/
|
|
42
|
+
export interface TTSHandler {
|
|
43
|
+
/**
|
|
44
|
+
* Generate audio from text using provider-specific TTS API
|
|
45
|
+
*
|
|
46
|
+
* @param text - Text to convert to speech
|
|
47
|
+
* @param options - TTS configuration options
|
|
48
|
+
* @returns Audio buffer with metadata
|
|
49
|
+
*/
|
|
50
|
+
synthesize(text: string, options: TTSOptions): Promise<TTSResult>;
|
|
51
|
+
/**
|
|
52
|
+
* Get available voices for the provider
|
|
53
|
+
*
|
|
54
|
+
* @param languageCode - Optional language filter (e.g., "en-US")
|
|
55
|
+
* @returns List of available voices
|
|
56
|
+
*/
|
|
57
|
+
getVoices?(languageCode?: string): Promise<TTSVoice[]>;
|
|
58
|
+
/**
|
|
59
|
+
* Validate that the provider is properly configured
|
|
60
|
+
*
|
|
61
|
+
* @returns True if provider can generate TTS
|
|
62
|
+
*/
|
|
63
|
+
isConfigured(): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Maximum text length supported by this provider (in characters)
|
|
66
|
+
* Different providers have different limits
|
|
67
|
+
*
|
|
68
|
+
* @default 3000 if not specified
|
|
69
|
+
*/
|
|
70
|
+
maxTextLength?: number;
|
|
71
|
+
}
|
|
10
72
|
/**
|
|
11
73
|
* TTS processor class for orchestrating text-to-speech operations
|
|
12
74
|
*
|
|
@@ -32,6 +94,26 @@ export declare class TTSProcessor {
|
|
|
32
94
|
* @private
|
|
33
95
|
*/
|
|
34
96
|
private static readonly handlers;
|
|
97
|
+
/**
|
|
98
|
+
* Default maximum text length for TTS synthesis (characters)
|
|
99
|
+
*
|
|
100
|
+
* Providers can override this value by specifying the `maxTextLength` property
|
|
101
|
+
* in their respective `TTSHandler` implementation. If not specified, this default
|
|
102
|
+
* value will be used.
|
|
103
|
+
*
|
|
104
|
+
* @private
|
|
105
|
+
*/
|
|
106
|
+
private static readonly DEFAULT_MAX_TEXT_LENGTH;
|
|
107
|
+
/**
|
|
108
|
+
* Default timeout for TTS synthesis operations (milliseconds)
|
|
109
|
+
*
|
|
110
|
+
* This timeout prevents indefinite hangs in provider API calls and serves as
|
|
111
|
+
* a safety net for all TTS operations. Individual handlers may implement
|
|
112
|
+
* shorter provider-specific timeouts.
|
|
113
|
+
*
|
|
114
|
+
* @private
|
|
115
|
+
*/
|
|
116
|
+
private static readonly DEFAULT_SYNTHESIS_TIMEOUT_MS;
|
|
35
117
|
/**
|
|
36
118
|
* Register a TTS handler for a specific provider
|
|
37
119
|
*
|
|
@@ -74,4 +156,33 @@ export declare class TTSProcessor {
|
|
|
74
156
|
* ```
|
|
75
157
|
*/
|
|
76
158
|
static supports(providerName: string): boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Synthesize speech from text using a registered TTS provider
|
|
161
|
+
*
|
|
162
|
+
* Orchestrates the text-to-speech generation process:
|
|
163
|
+
* 1. Validates input text (not empty, within length limits)
|
|
164
|
+
* 2. Looks up the provider handler
|
|
165
|
+
* 3. Verifies provider configuration
|
|
166
|
+
* 4. Delegates synthesis to the provider
|
|
167
|
+
* 5. Enriches result with metadata
|
|
168
|
+
*
|
|
169
|
+
* @param text - Text to convert to speech
|
|
170
|
+
* @param provider - Provider identifier
|
|
171
|
+
* @param options - TTS configuration options
|
|
172
|
+
* @returns Audio result with buffer and metadata
|
|
173
|
+
* @throws TTSError if validation fails, provider not supported/configured, or synthesis times out
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* const result = await TTSProcessor.synthesize("Hello, world!", "google-ai", {
|
|
178
|
+
* voice: "en-US-Neural2-C",
|
|
179
|
+
* format: "mp3",
|
|
180
|
+
* speed: 1.0
|
|
181
|
+
* });
|
|
182
|
+
*
|
|
183
|
+
* console.log(`Generated ${result.size} bytes of ${result.format} audio`);
|
|
184
|
+
* // Save to file or play the audio buffer
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
static synthesize(text: string, provider: string, options: TTSOptions): Promise<TTSResult>;
|
|
77
188
|
}
|
|
@@ -7,6 +7,35 @@
|
|
|
7
7
|
* @module utils/ttsProcessor
|
|
8
8
|
*/
|
|
9
9
|
import { logger } from "./logger.js";
|
|
10
|
+
import { ErrorCategory, ErrorSeverity } from "../constants/enums.js";
|
|
11
|
+
import { NeuroLinkError, withTimeout } from "./errorHandling.js";
|
|
12
|
+
/**
|
|
13
|
+
* TTS-specific error codes
|
|
14
|
+
*/
|
|
15
|
+
export const TTS_ERROR_CODES = {
|
|
16
|
+
EMPTY_TEXT: "TTS_EMPTY_TEXT",
|
|
17
|
+
TEXT_TOO_LONG: "TTS_TEXT_TOO_LONG",
|
|
18
|
+
PROVIDER_NOT_SUPPORTED: "TTS_PROVIDER_NOT_SUPPORTED",
|
|
19
|
+
PROVIDER_NOT_CONFIGURED: "TTS_PROVIDER_NOT_CONFIGURED",
|
|
20
|
+
SYNTHESIS_FAILED: "TTS_SYNTHESIS_FAILED",
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* TTS Error class for text-to-speech specific errors
|
|
24
|
+
*/
|
|
25
|
+
export class TTSError extends NeuroLinkError {
|
|
26
|
+
constructor(options) {
|
|
27
|
+
super({
|
|
28
|
+
code: options.code,
|
|
29
|
+
message: options.message,
|
|
30
|
+
category: options.category ?? ErrorCategory.VALIDATION,
|
|
31
|
+
severity: options.severity ?? ErrorSeverity.MEDIUM,
|
|
32
|
+
retriable: options.retriable ?? false,
|
|
33
|
+
context: options.context,
|
|
34
|
+
originalError: options.originalError,
|
|
35
|
+
});
|
|
36
|
+
this.name = "TTSError";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
10
39
|
/**
|
|
11
40
|
* TTS processor class for orchestrating text-to-speech operations
|
|
12
41
|
*
|
|
@@ -32,6 +61,26 @@ export class TTSProcessor {
|
|
|
32
61
|
* @private
|
|
33
62
|
*/
|
|
34
63
|
static handlers = new Map();
|
|
64
|
+
/**
|
|
65
|
+
* Default maximum text length for TTS synthesis (characters)
|
|
66
|
+
*
|
|
67
|
+
* Providers can override this value by specifying the `maxTextLength` property
|
|
68
|
+
* in their respective `TTSHandler` implementation. If not specified, this default
|
|
69
|
+
* value will be used.
|
|
70
|
+
*
|
|
71
|
+
* @private
|
|
72
|
+
*/
|
|
73
|
+
static DEFAULT_MAX_TEXT_LENGTH = 3000;
|
|
74
|
+
/**
|
|
75
|
+
* Default timeout for TTS synthesis operations (milliseconds)
|
|
76
|
+
*
|
|
77
|
+
* This timeout prevents indefinite hangs in provider API calls and serves as
|
|
78
|
+
* a safety net for all TTS operations. Individual handlers may implement
|
|
79
|
+
* shorter provider-specific timeouts.
|
|
80
|
+
*
|
|
81
|
+
* @private
|
|
82
|
+
*/
|
|
83
|
+
static DEFAULT_SYNTHESIS_TIMEOUT_MS = 60000;
|
|
35
84
|
/**
|
|
36
85
|
* Register a TTS handler for a specific provider
|
|
37
86
|
*
|
|
@@ -101,4 +150,137 @@ export class TTSProcessor {
|
|
|
101
150
|
}
|
|
102
151
|
return isSupported;
|
|
103
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Synthesize speech from text using a registered TTS provider
|
|
155
|
+
*
|
|
156
|
+
* Orchestrates the text-to-speech generation process:
|
|
157
|
+
* 1. Validates input text (not empty, within length limits)
|
|
158
|
+
* 2. Looks up the provider handler
|
|
159
|
+
* 3. Verifies provider configuration
|
|
160
|
+
* 4. Delegates synthesis to the provider
|
|
161
|
+
* 5. Enriches result with metadata
|
|
162
|
+
*
|
|
163
|
+
* @param text - Text to convert to speech
|
|
164
|
+
* @param provider - Provider identifier
|
|
165
|
+
* @param options - TTS configuration options
|
|
166
|
+
* @returns Audio result with buffer and metadata
|
|
167
|
+
* @throws TTSError if validation fails, provider not supported/configured, or synthesis times out
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const result = await TTSProcessor.synthesize("Hello, world!", "google-ai", {
|
|
172
|
+
* voice: "en-US-Neural2-C",
|
|
173
|
+
* format: "mp3",
|
|
174
|
+
* speed: 1.0
|
|
175
|
+
* });
|
|
176
|
+
*
|
|
177
|
+
* console.log(`Generated ${result.size} bytes of ${result.format} audio`);
|
|
178
|
+
* // Save to file or play the audio buffer
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
static async synthesize(text, provider, options) {
|
|
182
|
+
// Trim the text once at the start
|
|
183
|
+
const trimmedText = text.trim();
|
|
184
|
+
// 1. Text validation: reject empty text
|
|
185
|
+
if (!trimmedText) {
|
|
186
|
+
logger.error("[TTSProcessor] Text is required for synthesis");
|
|
187
|
+
throw new TTSError({
|
|
188
|
+
code: TTS_ERROR_CODES.EMPTY_TEXT,
|
|
189
|
+
message: "Text is required for TTS synthesis",
|
|
190
|
+
severity: ErrorSeverity.LOW,
|
|
191
|
+
retriable: false,
|
|
192
|
+
context: { provider },
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// 2. Handler lookup and error if provider not supported
|
|
196
|
+
const handler = this.getHandler(provider);
|
|
197
|
+
if (!handler) {
|
|
198
|
+
logger.error(`[TTSProcessor] Provider "${provider}" is not registered`);
|
|
199
|
+
throw new TTSError({
|
|
200
|
+
code: TTS_ERROR_CODES.PROVIDER_NOT_SUPPORTED,
|
|
201
|
+
message: `TTS provider "${provider}" is not supported. Use TTSProcessor.registerHandler() to register it.`,
|
|
202
|
+
severity: ErrorSeverity.HIGH,
|
|
203
|
+
retriable: false,
|
|
204
|
+
context: {
|
|
205
|
+
provider,
|
|
206
|
+
availableProviders: Array.from(this.handlers.keys()),
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
// 3. Text validation: reject text exceeding provider-specific max length
|
|
211
|
+
const maxTextLength = handler.maxTextLength ?? this.DEFAULT_MAX_TEXT_LENGTH;
|
|
212
|
+
if (trimmedText.length > maxTextLength) {
|
|
213
|
+
logger.error(`[TTSProcessor] Text exceeds maximum length of ${maxTextLength} characters for provider "${provider}"`);
|
|
214
|
+
throw new TTSError({
|
|
215
|
+
code: TTS_ERROR_CODES.TEXT_TOO_LONG,
|
|
216
|
+
message: `Text length (${trimmedText.length}) exceeds maximum allowed length (${maxTextLength} characters) for provider "${provider}"`,
|
|
217
|
+
severity: ErrorSeverity.MEDIUM,
|
|
218
|
+
retriable: false,
|
|
219
|
+
context: {
|
|
220
|
+
provider,
|
|
221
|
+
textLength: trimmedText.length,
|
|
222
|
+
maxLength: maxTextLength,
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
// 4. Configuration check
|
|
227
|
+
if (!handler.isConfigured()) {
|
|
228
|
+
logger.warn(`[TTSProcessor] Provider "${provider}" is not properly configured`);
|
|
229
|
+
throw new TTSError({
|
|
230
|
+
code: TTS_ERROR_CODES.PROVIDER_NOT_CONFIGURED,
|
|
231
|
+
message: `TTS provider "${provider}" is not configured. Please set the required API keys.`,
|
|
232
|
+
category: ErrorCategory.CONFIGURATION,
|
|
233
|
+
severity: ErrorSeverity.HIGH,
|
|
234
|
+
retriable: false,
|
|
235
|
+
context: { provider },
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
try {
|
|
239
|
+
logger.debug(`[TTSProcessor] Starting synthesis with provider: ${provider}`);
|
|
240
|
+
// 5. Call handler.synthesize() with timeout protection (60 second safety net)
|
|
241
|
+
const result = await withTimeout(handler.synthesize(trimmedText, options), this.DEFAULT_SYNTHESIS_TIMEOUT_MS, new TTSError({
|
|
242
|
+
code: TTS_ERROR_CODES.SYNTHESIS_FAILED,
|
|
243
|
+
message: `TTS synthesis timeout for provider "${provider}" after ${this.DEFAULT_SYNTHESIS_TIMEOUT_MS}ms`,
|
|
244
|
+
category: ErrorCategory.EXECUTION,
|
|
245
|
+
severity: ErrorSeverity.HIGH,
|
|
246
|
+
retriable: true,
|
|
247
|
+
context: {
|
|
248
|
+
provider,
|
|
249
|
+
timeoutMs: this.DEFAULT_SYNTHESIS_TIMEOUT_MS,
|
|
250
|
+
textLength: trimmedText.length,
|
|
251
|
+
},
|
|
252
|
+
}));
|
|
253
|
+
// 6. Post-processing: add metadata
|
|
254
|
+
const enrichedResult = {
|
|
255
|
+
...result,
|
|
256
|
+
voice: result.voice ?? options.voice,
|
|
257
|
+
};
|
|
258
|
+
logger.info(`[TTSProcessor] Successfully synthesized ${result.size} bytes of audio`);
|
|
259
|
+
// 7. Returns TTSResult with buffer, format, metadata
|
|
260
|
+
return enrichedResult;
|
|
261
|
+
}
|
|
262
|
+
catch (err) {
|
|
263
|
+
// 8. Comprehensive error handling
|
|
264
|
+
// Re-throw TTSError as-is
|
|
265
|
+
if (err instanceof TTSError) {
|
|
266
|
+
throw err;
|
|
267
|
+
}
|
|
268
|
+
// Wrap other errors in TTSError
|
|
269
|
+
const errorMessage = err instanceof Error ? err.message : String(err || "Unknown error");
|
|
270
|
+
logger.error(`[TTSProcessor] Synthesis failed for provider "${provider}": ${errorMessage}`);
|
|
271
|
+
throw new TTSError({
|
|
272
|
+
code: TTS_ERROR_CODES.SYNTHESIS_FAILED,
|
|
273
|
+
message: `TTS synthesis failed for provider "${provider}": ${errorMessage}`,
|
|
274
|
+
category: ErrorCategory.EXECUTION,
|
|
275
|
+
severity: ErrorSeverity.HIGH,
|
|
276
|
+
retriable: true,
|
|
277
|
+
context: {
|
|
278
|
+
provider,
|
|
279
|
+
textLength: trimmedText.length,
|
|
280
|
+
options,
|
|
281
|
+
},
|
|
282
|
+
originalError: err instanceof Error ? err : undefined,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
104
286
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.13.0",
|
|
4
4
|
"description": "Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and deploy AI applications with 9 major providers: OpenAI, Anthropic, Google AI, AWS Bedrock, Azure, Hugging Face, Ollama, and Mistral AI.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Juspay Technologies",
|