@loonylabs/tts-middleware 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +201 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/services/tts/index.d.ts +30 -0
- package/dist/middleware/services/tts/index.d.ts.map +1 -0
- package/dist/middleware/services/tts/index.js +69 -0
- package/dist/middleware/services/tts/index.js.map +1 -0
- package/dist/middleware/services/tts/providers/azure-provider.d.ts +131 -0
- package/dist/middleware/services/tts/providers/azure-provider.d.ts.map +1 -0
- package/dist/middleware/services/tts/providers/azure-provider.js +375 -0
- package/dist/middleware/services/tts/providers/azure-provider.js.map +1 -0
- package/dist/middleware/services/tts/providers/base-tts-provider.d.ts +204 -0
- package/dist/middleware/services/tts/providers/base-tts-provider.d.ts.map +1 -0
- package/dist/middleware/services/tts/providers/base-tts-provider.js +267 -0
- package/dist/middleware/services/tts/providers/base-tts-provider.js.map +1 -0
- package/dist/middleware/services/tts/providers/edenai-provider.d.ts +112 -0
- package/dist/middleware/services/tts/providers/edenai-provider.d.ts.map +1 -0
- package/dist/middleware/services/tts/providers/edenai-provider.js +289 -0
- package/dist/middleware/services/tts/providers/edenai-provider.js.map +1 -0
- package/dist/middleware/services/tts/providers/index.d.ts +9 -0
- package/dist/middleware/services/tts/providers/index.d.ts.map +1 -0
- package/dist/middleware/services/tts/providers/index.js +29 -0
- package/dist/middleware/services/tts/providers/index.js.map +1 -0
- package/dist/middleware/services/tts/tts.service.d.ts +175 -0
- package/dist/middleware/services/tts/tts.service.d.ts.map +1 -0
- package/dist/middleware/services/tts/tts.service.js +287 -0
- package/dist/middleware/services/tts/tts.service.js.map +1 -0
- package/dist/middleware/services/tts/types/common.types.d.ts +303 -0
- package/dist/middleware/services/tts/types/common.types.d.ts.map +1 -0
- package/dist/middleware/services/tts/types/common.types.js +42 -0
- package/dist/middleware/services/tts/types/common.types.js.map +1 -0
- package/dist/middleware/services/tts/types/index.d.ts +22 -0
- package/dist/middleware/services/tts/types/index.d.ts.map +1 -0
- package/dist/middleware/services/tts/types/index.js +46 -0
- package/dist/middleware/services/tts/types/index.js.map +1 -0
- package/dist/middleware/services/tts/types/provider-options.types.d.ts +414 -0
- package/dist/middleware/services/tts/types/provider-options.types.d.ts.map +1 -0
- package/dist/middleware/services/tts/types/provider-options.types.js +71 -0
- package/dist/middleware/services/tts/types/provider-options.types.js.map +1 -0
- package/dist/middleware/services/tts/utils/character-counter.utils.d.ts +160 -0
- package/dist/middleware/services/tts/utils/character-counter.utils.d.ts.map +1 -0
- package/dist/middleware/services/tts/utils/character-counter.utils.js +205 -0
- package/dist/middleware/services/tts/utils/character-counter.utils.js.map +1 -0
- package/dist/middleware/services/tts/utils/index.d.ts +9 -0
- package/dist/middleware/services/tts/utils/index.d.ts.map +1 -0
- package/dist/middleware/services/tts/utils/index.js +25 -0
- package/dist/middleware/services/tts/utils/index.js.map +1 -0
- package/dist/middleware/services/tts/utils/logger.utils.d.ts +116 -0
- package/dist/middleware/services/tts/utils/logger.utils.d.ts.map +1 -0
- package/dist/middleware/services/tts/utils/logger.utils.js +186 -0
- package/dist/middleware/services/tts/utils/logger.utils.js.map +1 -0
- package/dist/middleware/shared/config/tts.config.d.ts +147 -0
- package/dist/middleware/shared/config/tts.config.d.ts.map +1 -0
- package/dist/middleware/shared/config/tts.config.js +162 -0
- package/dist/middleware/shared/config/tts.config.js.map +1 -0
- package/package.json +94 -0
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Azure Speech Services TTS Provider
|
|
4
|
+
*
|
|
5
|
+
* @description Implementation of TTS provider for Microsoft Azure Speech Services.
|
|
6
|
+
* This is the MVP provider for EU-compliant TTS synthesis.
|
|
7
|
+
*
|
|
8
|
+
* @see https://learn.microsoft.com/en-us/azure/ai-services/speech-service/
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.AzureProvider = void 0;
|
|
45
|
+
const sdk = __importStar(require("microsoft-cognitiveservices-speech-sdk"));
|
|
46
|
+
const types_1 = require("../types");
|
|
47
|
+
const base_tts_provider_1 = require("./base-tts-provider");
|
|
48
|
+
/**
|
|
49
|
+
* Azure Speech Services provider implementation
|
|
50
|
+
*
|
|
51
|
+
* @description Provides TTS synthesis using Microsoft Azure Speech Services.
|
|
52
|
+
* Supports emotion, style, and multiple audio formats.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const provider = new AzureProvider();
|
|
57
|
+
* const response = await provider.synthesize(
|
|
58
|
+
* "Hello World",
|
|
59
|
+
* "en-US-JennyNeural",
|
|
60
|
+
* {
|
|
61
|
+
* text: "Hello World",
|
|
62
|
+
* voice: { id: "en-US-JennyNeural" },
|
|
63
|
+
* audio: { speed: 1.0, format: "mp3" },
|
|
64
|
+
* providerOptions: { emotion: "cheerful" }
|
|
65
|
+
* }
|
|
66
|
+
* );
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
class AzureProvider extends base_tts_provider_1.BaseTTSProvider {
|
|
70
|
+
/**
|
|
71
|
+
* Creates a new Azure TTS provider
|
|
72
|
+
*
|
|
73
|
+
* @param config - Optional Azure configuration (uses env vars if not provided)
|
|
74
|
+
* @throws {InvalidConfigError} If required configuration is missing
|
|
75
|
+
*/
|
|
76
|
+
constructor(config) {
|
|
77
|
+
super(types_1.TTSProvider.AZURE);
|
|
78
|
+
this.speechConfig = null;
|
|
79
|
+
// Load configuration from environment or provided config
|
|
80
|
+
this.config = {
|
|
81
|
+
subscriptionKey: config?.subscriptionKey || process.env.AZURE_SPEECH_KEY || '',
|
|
82
|
+
region: config?.region || process.env.AZURE_SPEECH_REGION || '',
|
|
83
|
+
endpoint: config?.endpoint || process.env.AZURE_SPEECH_ENDPOINT,
|
|
84
|
+
};
|
|
85
|
+
// Validate configuration
|
|
86
|
+
this.validateAzureConfig();
|
|
87
|
+
// Initialize speech config
|
|
88
|
+
this.initializeSpeechConfig();
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Validate Azure-specific configuration
|
|
92
|
+
*
|
|
93
|
+
* @private
|
|
94
|
+
* @throws {InvalidConfigError} If configuration is invalid
|
|
95
|
+
*/
|
|
96
|
+
validateAzureConfig() {
|
|
97
|
+
if (!this.config.subscriptionKey) {
|
|
98
|
+
throw new base_tts_provider_1.InvalidConfigError(this.providerName, 'Azure Speech subscription key is required (AZURE_SPEECH_KEY)');
|
|
99
|
+
}
|
|
100
|
+
if (!this.config.region) {
|
|
101
|
+
throw new base_tts_provider_1.InvalidConfigError(this.providerName, 'Azure Speech region is required (AZURE_SPEECH_REGION)');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Initialize Azure Speech SDK configuration
|
|
106
|
+
*
|
|
107
|
+
* @private
|
|
108
|
+
*/
|
|
109
|
+
initializeSpeechConfig() {
|
|
110
|
+
try {
|
|
111
|
+
if (this.config.endpoint) {
|
|
112
|
+
this.speechConfig = sdk.SpeechConfig.fromEndpoint(new URL(this.config.endpoint), this.config.subscriptionKey);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
this.speechConfig = sdk.SpeechConfig.fromSubscription(this.config.subscriptionKey, this.config.region);
|
|
116
|
+
}
|
|
117
|
+
this.log('info', 'Azure Speech SDK initialized', {
|
|
118
|
+
region: this.config.region,
|
|
119
|
+
hasEndpoint: !!this.config.endpoint,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
throw new base_tts_provider_1.InvalidConfigError(this.providerName, `Failed to initialize Azure Speech SDK: ${error.message}`, error);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Synthesize text to speech using Azure Speech Services
|
|
128
|
+
*
|
|
129
|
+
* @param text - The input text to synthesize
|
|
130
|
+
* @param voiceId - The voice identifier (e.g., "en-US-JennyNeural")
|
|
131
|
+
* @param request - The full synthesis request with options
|
|
132
|
+
* @returns Promise resolving to the synthesis response
|
|
133
|
+
* @throws {InvalidConfigError} If configuration is invalid
|
|
134
|
+
* @throws {InvalidVoiceError} If voice is not found
|
|
135
|
+
* @throws {SynthesisFailedError} If synthesis fails
|
|
136
|
+
*/
|
|
137
|
+
async synthesize(text, voiceId, request) {
|
|
138
|
+
// Validate configuration
|
|
139
|
+
this.validateConfig(request);
|
|
140
|
+
if (!this.speechConfig) {
|
|
141
|
+
throw new base_tts_provider_1.InvalidConfigError(this.providerName, 'Speech configuration not initialized');
|
|
142
|
+
}
|
|
143
|
+
const startTime = Date.now();
|
|
144
|
+
try {
|
|
145
|
+
// Extract options
|
|
146
|
+
const audioFormat = request.audio?.format || 'mp3';
|
|
147
|
+
const speed = request.audio?.speed || 1.0;
|
|
148
|
+
const sampleRate = request.audio?.sampleRate || 24000;
|
|
149
|
+
// Set audio output format
|
|
150
|
+
this.setAudioFormat(audioFormat, sampleRate);
|
|
151
|
+
// Generate SSML
|
|
152
|
+
const ssml = this.generateSSML(text, voiceId, request);
|
|
153
|
+
this.log('debug', 'Synthesizing with Azure', {
|
|
154
|
+
voiceId,
|
|
155
|
+
audioFormat,
|
|
156
|
+
speed,
|
|
157
|
+
sampleRate,
|
|
158
|
+
ssmlLength: ssml.length,
|
|
159
|
+
});
|
|
160
|
+
// Create synthesizer
|
|
161
|
+
const synthesizer = new sdk.SpeechSynthesizer(this.speechConfig);
|
|
162
|
+
// Synthesize speech
|
|
163
|
+
const audioBuffer = await this.synthesizeSSML(synthesizer, ssml);
|
|
164
|
+
// Calculate duration (estimated)
|
|
165
|
+
const duration = Date.now() - startTime;
|
|
166
|
+
// Count billable characters (original text, not SSML)
|
|
167
|
+
const characters = this.countCharacters(text);
|
|
168
|
+
this.log('info', 'Synthesis successful', {
|
|
169
|
+
voiceId,
|
|
170
|
+
characters,
|
|
171
|
+
duration,
|
|
172
|
+
audioSize: audioBuffer.length,
|
|
173
|
+
});
|
|
174
|
+
// Return response
|
|
175
|
+
return {
|
|
176
|
+
audio: audioBuffer,
|
|
177
|
+
metadata: {
|
|
178
|
+
provider: this.providerName,
|
|
179
|
+
voice: voiceId,
|
|
180
|
+
duration,
|
|
181
|
+
audioFormat,
|
|
182
|
+
sampleRate,
|
|
183
|
+
},
|
|
184
|
+
billing: {
|
|
185
|
+
characters,
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
this.log('error', 'Synthesis failed', {
|
|
191
|
+
voiceId,
|
|
192
|
+
error: error.message,
|
|
193
|
+
});
|
|
194
|
+
throw this.handleError(error, 'during synthesis');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Set audio output format for Azure Speech SDK
|
|
199
|
+
*
|
|
200
|
+
* @private
|
|
201
|
+
* @param format - The audio format (mp3, wav, opus)
|
|
202
|
+
* @param sampleRate - The sample rate in Hz
|
|
203
|
+
*/
|
|
204
|
+
setAudioFormat(format, sampleRate) {
|
|
205
|
+
if (!this.speechConfig) {
|
|
206
|
+
throw new base_tts_provider_1.InvalidConfigError(this.providerName, 'Speech configuration not initialized');
|
|
207
|
+
}
|
|
208
|
+
// Map format and sample rate to Azure format strings
|
|
209
|
+
const azureFormat = this.getAzureAudioFormat(format, sampleRate);
|
|
210
|
+
this.speechConfig.speechSynthesisOutputFormat = azureFormat;
|
|
211
|
+
this.log('debug', 'Audio format set', {
|
|
212
|
+
format,
|
|
213
|
+
sampleRate,
|
|
214
|
+
azureFormat: sdk.SpeechSynthesisOutputFormat[azureFormat],
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Map audio format and sample rate to Azure format enum
|
|
219
|
+
*
|
|
220
|
+
* @private
|
|
221
|
+
* @param format - The audio format
|
|
222
|
+
* @param sampleRate - The sample rate in Hz
|
|
223
|
+
* @returns Azure audio format enum value
|
|
224
|
+
*/
|
|
225
|
+
getAzureAudioFormat(format, sampleRate) {
|
|
226
|
+
const formatKey = `${format}_${sampleRate}`;
|
|
227
|
+
const formatMap = {
|
|
228
|
+
// MP3 formats
|
|
229
|
+
mp3_8000: sdk.SpeechSynthesisOutputFormat.Audio16Khz32KBitRateMonoMp3,
|
|
230
|
+
mp3_16000: sdk.SpeechSynthesisOutputFormat.Audio16Khz128KBitRateMonoMp3,
|
|
231
|
+
mp3_24000: sdk.SpeechSynthesisOutputFormat.Audio24Khz160KBitRateMonoMp3,
|
|
232
|
+
mp3_48000: sdk.SpeechSynthesisOutputFormat.Audio48Khz192KBitRateMonoMp3,
|
|
233
|
+
// WAV formats
|
|
234
|
+
wav_8000: sdk.SpeechSynthesisOutputFormat.Riff8Khz16BitMonoPcm,
|
|
235
|
+
wav_16000: sdk.SpeechSynthesisOutputFormat.Riff16Khz16BitMonoPcm,
|
|
236
|
+
wav_24000: sdk.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm,
|
|
237
|
+
wav_48000: sdk.SpeechSynthesisOutputFormat.Riff48Khz16BitMonoPcm,
|
|
238
|
+
// Opus formats
|
|
239
|
+
opus_8000: sdk.SpeechSynthesisOutputFormat.Ogg16Khz16BitMonoOpus,
|
|
240
|
+
opus_16000: sdk.SpeechSynthesisOutputFormat.Ogg16Khz16BitMonoOpus,
|
|
241
|
+
opus_24000: sdk.SpeechSynthesisOutputFormat.Ogg24Khz16BitMonoOpus,
|
|
242
|
+
opus_48000: sdk.SpeechSynthesisOutputFormat.Ogg48Khz16BitMonoOpus,
|
|
243
|
+
};
|
|
244
|
+
// Default formats if exact match not found
|
|
245
|
+
const defaultFormats = {
|
|
246
|
+
mp3: sdk.SpeechSynthesisOutputFormat.Audio24Khz160KBitRateMonoMp3,
|
|
247
|
+
wav: sdk.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm,
|
|
248
|
+
opus: sdk.SpeechSynthesisOutputFormat.Ogg24Khz16BitMonoOpus,
|
|
249
|
+
aac: sdk.SpeechSynthesisOutputFormat.Audio24Khz160KBitRateMonoMp3, // Fallback to MP3
|
|
250
|
+
flac: sdk.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm, // Fallback to WAV
|
|
251
|
+
};
|
|
252
|
+
return (formatMap[formatKey] ||
|
|
253
|
+
defaultFormats[format] ||
|
|
254
|
+
sdk.SpeechSynthesisOutputFormat.Audio24Khz160KBitRateMonoMp3);
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Generate SSML from plain text and options
|
|
258
|
+
*
|
|
259
|
+
* @private
|
|
260
|
+
* @param text - The input text
|
|
261
|
+
* @param voiceId - The voice identifier
|
|
262
|
+
* @param request - The synthesis request with options
|
|
263
|
+
* @returns SSML string
|
|
264
|
+
*/
|
|
265
|
+
generateSSML(text, voiceId, request) {
|
|
266
|
+
// Extract language from voice ID (e.g., "en-US-JennyNeural" -> "en-US")
|
|
267
|
+
const language = voiceId.split('-').slice(0, 2).join('-');
|
|
268
|
+
// Extract provider options
|
|
269
|
+
const emotion = request.providerOptions?.emotion || null;
|
|
270
|
+
const style = request.providerOptions?.style || null;
|
|
271
|
+
const speed = request.audio?.speed || 1.0;
|
|
272
|
+
// Escape XML special characters
|
|
273
|
+
const escapedText = this.escapeXML(text);
|
|
274
|
+
// Build SSML
|
|
275
|
+
let ssml = `<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="https://www.w3.org/2001/mstts" xml:lang="${language}">`;
|
|
276
|
+
ssml += `<voice name="${voiceId}">`;
|
|
277
|
+
// Add style/emotion if provided (Azure-specific)
|
|
278
|
+
if (style || emotion) {
|
|
279
|
+
const expressAs = style || emotion;
|
|
280
|
+
ssml += `<mstts:express-as style="${expressAs}">`;
|
|
281
|
+
}
|
|
282
|
+
// Add prosody for speed control
|
|
283
|
+
const rateValue = this.speedToProsodyRate(speed);
|
|
284
|
+
ssml += `<prosody rate="${rateValue}">`;
|
|
285
|
+
// Add text
|
|
286
|
+
ssml += escapedText;
|
|
287
|
+
// Close prosody
|
|
288
|
+
ssml += `</prosody>`;
|
|
289
|
+
// Close express-as if used
|
|
290
|
+
if (style || emotion) {
|
|
291
|
+
ssml += `</mstts:express-as>`;
|
|
292
|
+
}
|
|
293
|
+
// Close voice and speak
|
|
294
|
+
ssml += `</voice>`;
|
|
295
|
+
ssml += `</speak>`;
|
|
296
|
+
return ssml;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Convert speed multiplier to SSML prosody rate value
|
|
300
|
+
*
|
|
301
|
+
* @private
|
|
302
|
+
* @param speed - Speed multiplier (0.5 - 2.0)
|
|
303
|
+
* @returns SSML rate value
|
|
304
|
+
*/
|
|
305
|
+
speedToProsodyRate(speed) {
|
|
306
|
+
// Azure accepts percentage values: "50%" = half speed, "200%" = double speed
|
|
307
|
+
// Or relative values: "x-slow", "slow", "medium", "fast", "x-fast"
|
|
308
|
+
if (speed === 1.0) {
|
|
309
|
+
return 'medium';
|
|
310
|
+
}
|
|
311
|
+
// Convert to percentage (1.0 = 100%, 0.5 = 50%, 2.0 = 200%)
|
|
312
|
+
const percentage = Math.round(speed * 100);
|
|
313
|
+
return `${percentage}%`;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Escape XML special characters
|
|
317
|
+
*
|
|
318
|
+
* @private
|
|
319
|
+
* @param text - The text to escape
|
|
320
|
+
* @returns Escaped text
|
|
321
|
+
*/
|
|
322
|
+
escapeXML(text) {
|
|
323
|
+
return text
|
|
324
|
+
.replace(/&/g, '&')
|
|
325
|
+
.replace(/</g, '<')
|
|
326
|
+
.replace(/>/g, '>')
|
|
327
|
+
.replace(/"/g, '"')
|
|
328
|
+
.replace(/'/g, ''');
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Synthesize SSML using Azure Speech SDK
|
|
332
|
+
*
|
|
333
|
+
* @private
|
|
334
|
+
* @param synthesizer - The speech synthesizer
|
|
335
|
+
* @param ssml - The SSML to synthesize
|
|
336
|
+
* @returns Promise resolving to audio buffer
|
|
337
|
+
* @throws {InvalidVoiceError} If voice is not found
|
|
338
|
+
* @throws {SynthesisFailedError} If synthesis fails
|
|
339
|
+
*/
|
|
340
|
+
async synthesizeSSML(synthesizer, ssml) {
|
|
341
|
+
return new Promise((resolve, reject) => {
|
|
342
|
+
synthesizer.speakSsmlAsync(ssml, (result) => {
|
|
343
|
+
if (result.reason === sdk.ResultReason.SynthesizingAudioCompleted) {
|
|
344
|
+
// Convert ArrayBuffer to Buffer
|
|
345
|
+
const audioBuffer = Buffer.from(result.audioData);
|
|
346
|
+
synthesizer.close();
|
|
347
|
+
resolve(audioBuffer);
|
|
348
|
+
}
|
|
349
|
+
else if (result.reason === sdk.ResultReason.Canceled) {
|
|
350
|
+
const cancellation = sdk.CancellationDetails.fromResult(result);
|
|
351
|
+
synthesizer.close();
|
|
352
|
+
// Check error type
|
|
353
|
+
if (cancellation.ErrorCode === sdk.CancellationErrorCode.AuthenticationFailure) {
|
|
354
|
+
reject(new base_tts_provider_1.InvalidConfigError(this.providerName, `Authentication failed: ${cancellation.errorDetails}`));
|
|
355
|
+
}
|
|
356
|
+
else if (cancellation.errorDetails?.includes('voice')) {
|
|
357
|
+
reject(new base_tts_provider_1.InvalidVoiceError(this.providerName, 'unknown', `Voice not found: ${cancellation.errorDetails}`));
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
reject(new base_tts_provider_1.SynthesisFailedError(this.providerName, `Synthesis canceled: ${cancellation.errorDetails || 'Unknown error'}`));
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
synthesizer.close();
|
|
365
|
+
reject(new base_tts_provider_1.SynthesisFailedError(this.providerName, `Unexpected result reason: ${sdk.ResultReason[result.reason]}`));
|
|
366
|
+
}
|
|
367
|
+
}, (error) => {
|
|
368
|
+
synthesizer.close();
|
|
369
|
+
reject(this.handleError(new Error(error), 'during Azure SDK call'));
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
exports.AzureProvider = AzureProvider;
|
|
375
|
+
//# sourceMappingURL=azure-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azure-provider.js","sourceRoot":"","sources":["../../../../../src/middleware/services/tts/providers/azure-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base TTS Provider Abstract Class
|
|
3
|
+
*
|
|
4
|
+
* All TTS providers must extend this class and implement the abstract methods.
|
|
5
|
+
* This ensures consistency across all providers.
|
|
6
|
+
*
|
|
7
|
+
* @abstract
|
|
8
|
+
*/
|
|
9
|
+
import type { TTSProvider, TTSSynthesizeRequest, TTSResponse, TTSErrorCode } from '../types';
|
|
10
|
+
/**
|
|
11
|
+
* Base error class for all TTS errors
|
|
12
|
+
*/
|
|
13
|
+
export declare class TTSError extends Error {
|
|
14
|
+
readonly provider: string;
|
|
15
|
+
readonly code: TTSErrorCode;
|
|
16
|
+
readonly cause?: Error | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Creates a new TTS error
|
|
19
|
+
*
|
|
20
|
+
* @param provider - The provider that threw the error
|
|
21
|
+
* @param code - Error code for categorization
|
|
22
|
+
* @param message - Human-readable error message
|
|
23
|
+
* @param cause - Optional underlying error that caused this error
|
|
24
|
+
*/
|
|
25
|
+
constructor(provider: string, code: TTSErrorCode, message: string, cause?: Error | undefined);
|
|
26
|
+
/**
|
|
27
|
+
* Returns a formatted error message with context
|
|
28
|
+
*/
|
|
29
|
+
toString(): string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Error thrown when TTS configuration is invalid or missing
|
|
33
|
+
*/
|
|
34
|
+
export declare class InvalidConfigError extends TTSError {
|
|
35
|
+
constructor(provider: string, message: string, cause?: Error);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Error thrown when voice ID is invalid or not found
|
|
39
|
+
*/
|
|
40
|
+
export declare class InvalidVoiceError extends TTSError {
|
|
41
|
+
constructor(provider: string, voiceId: string, message?: string, cause?: Error);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Error thrown when provider quota/rate limit is exceeded
|
|
45
|
+
*/
|
|
46
|
+
export declare class QuotaExceededError extends TTSError {
|
|
47
|
+
constructor(provider: string, message?: string, cause?: Error);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Error thrown when provider service is unavailable
|
|
51
|
+
*/
|
|
52
|
+
export declare class ProviderUnavailableError extends TTSError {
|
|
53
|
+
constructor(provider: string, message?: string, cause?: Error);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Error thrown when synthesis fails for unknown reasons
|
|
57
|
+
*/
|
|
58
|
+
export declare class SynthesisFailedError extends TTSError {
|
|
59
|
+
constructor(provider: string, message: string, cause?: Error);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Error thrown when network operation fails
|
|
63
|
+
*/
|
|
64
|
+
export declare class NetworkError extends TTSError {
|
|
65
|
+
constructor(provider: string, message: string, cause?: Error);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Abstract base class for all TTS providers
|
|
69
|
+
*
|
|
70
|
+
* @abstract
|
|
71
|
+
*
|
|
72
|
+
* @description All provider implementations must:
|
|
73
|
+
* - Extend this class
|
|
74
|
+
* - Implement the abstract synthesize() method
|
|
75
|
+
* - Call super() in constructor with the provider name
|
|
76
|
+
* - Use the provided error classes for consistent error handling
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* class AzureProvider extends BaseTTSProvider {
|
|
81
|
+
* constructor() {
|
|
82
|
+
* super(TTSProvider.AZURE);
|
|
83
|
+
* }
|
|
84
|
+
*
|
|
85
|
+
* async synthesize(text: string, voiceId: string, request: TTSSynthesizeRequest): Promise<TTSResponse> {
|
|
86
|
+
* this.validateConfig(request);
|
|
87
|
+
* // ... implementation
|
|
88
|
+
* }
|
|
89
|
+
* }
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export declare abstract class BaseTTSProvider {
|
|
93
|
+
/**
|
|
94
|
+
* The provider name (e.g., 'azure', 'openai')
|
|
95
|
+
*/
|
|
96
|
+
protected readonly providerName: TTSProvider;
|
|
97
|
+
/**
|
|
98
|
+
* Creates a new TTS provider
|
|
99
|
+
*
|
|
100
|
+
* @param providerName - The provider identifier
|
|
101
|
+
*/
|
|
102
|
+
constructor(providerName: TTSProvider);
|
|
103
|
+
/**
|
|
104
|
+
* Synthesize text to speech
|
|
105
|
+
*
|
|
106
|
+
* @abstract
|
|
107
|
+
* @param text - The input text to synthesize
|
|
108
|
+
* @param voiceId - The voice identifier (provider-specific)
|
|
109
|
+
* @param request - The full synthesis request with options
|
|
110
|
+
* @returns Promise resolving to the synthesis response with audio buffer
|
|
111
|
+
* @throws {InvalidConfigError} If provider configuration is invalid
|
|
112
|
+
* @throws {InvalidVoiceError} If voice ID is not found
|
|
113
|
+
* @throws {QuotaExceededError} If provider quota is exceeded
|
|
114
|
+
* @throws {ProviderUnavailableError} If provider service is unavailable
|
|
115
|
+
* @throws {SynthesisFailedError} If synthesis fails for other reasons
|
|
116
|
+
*/
|
|
117
|
+
abstract synthesize(text: string, voiceId: string, request: TTSSynthesizeRequest): Promise<TTSResponse>;
|
|
118
|
+
/**
|
|
119
|
+
* Get the provider name
|
|
120
|
+
*
|
|
121
|
+
* @returns The provider identifier
|
|
122
|
+
*/
|
|
123
|
+
getProviderName(): TTSProvider;
|
|
124
|
+
/**
|
|
125
|
+
* Validate provider configuration
|
|
126
|
+
*
|
|
127
|
+
* @protected
|
|
128
|
+
* @param request - The synthesis request to validate
|
|
129
|
+
* @throws {InvalidConfigError} If configuration is invalid
|
|
130
|
+
*
|
|
131
|
+
* @description Subclasses should override this to validate provider-specific
|
|
132
|
+
* configuration (e.g., API keys, region settings)
|
|
133
|
+
*/
|
|
134
|
+
protected validateConfig(request: TTSSynthesizeRequest): void;
|
|
135
|
+
/**
|
|
136
|
+
* Count characters in text for billing purposes
|
|
137
|
+
*
|
|
138
|
+
* @protected
|
|
139
|
+
* @param text - The input text to count
|
|
140
|
+
* @returns The number of characters (including spaces and punctuation)
|
|
141
|
+
*
|
|
142
|
+
* @description This is the base implementation that counts all characters.
|
|
143
|
+
* Providers that use SSML or have special character counting rules
|
|
144
|
+
* should override this method.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* const count = this.countCharacters("Hello World!"); // returns 12
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
protected countCharacters(text: string): number;
|
|
152
|
+
/**
|
|
153
|
+
* Validate that a voice exists
|
|
154
|
+
*
|
|
155
|
+
* @protected
|
|
156
|
+
* @param _voiceId - The voice identifier to validate (unused in base implementation)
|
|
157
|
+
* @returns Promise resolving to true if voice exists
|
|
158
|
+
* @throws {InvalidVoiceError} If voice does not exist
|
|
159
|
+
*
|
|
160
|
+
* @description Base implementation always returns true. Providers should
|
|
161
|
+
* override this to validate voice IDs against their voice catalogs.
|
|
162
|
+
*/
|
|
163
|
+
protected validateVoiceExists(_voiceId: string): Promise<boolean>;
|
|
164
|
+
/**
|
|
165
|
+
* Create a standardized error from a provider-specific error
|
|
166
|
+
*
|
|
167
|
+
* @protected
|
|
168
|
+
* @param error - The original error
|
|
169
|
+
* @param context - Additional context for debugging
|
|
170
|
+
* @returns A standardized TTS error
|
|
171
|
+
*
|
|
172
|
+
* @description Wraps provider-specific errors in our error classes
|
|
173
|
+
* for consistent error handling across providers.
|
|
174
|
+
*/
|
|
175
|
+
protected handleError(error: Error, context?: string): TTSError;
|
|
176
|
+
/**
|
|
177
|
+
* Log a message using the pluggable logger
|
|
178
|
+
*
|
|
179
|
+
* @protected
|
|
180
|
+
* @param level - Log level
|
|
181
|
+
* @param message - Log message
|
|
182
|
+
* @param meta - Optional metadata
|
|
183
|
+
*
|
|
184
|
+
* @description Uses the global TTS logger which can be customized via setLogger().
|
|
185
|
+
* By default uses console logging, but can be replaced with any logger (Winston, Pino, etc.)
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```typescript
|
|
189
|
+
* // In application code:
|
|
190
|
+
* import { setLogger, silentLogger } from '@loonylabs/tts-middleware';
|
|
191
|
+
*
|
|
192
|
+
* // Disable all logging
|
|
193
|
+
* setLogger(silentLogger);
|
|
194
|
+
*
|
|
195
|
+
* // Use custom logger
|
|
196
|
+
* setLogger({
|
|
197
|
+
* info: (msg, meta) => myLogger.info(msg, meta),
|
|
198
|
+
* // ...
|
|
199
|
+
* });
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
protected log(level: 'info' | 'warn' | 'error' | 'debug', message: string, meta?: Record<string, unknown>): void;
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=base-tts-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-tts-provider.d.ts","sourceRoot":"","sources":["../../../../../src/middleware/services/tts/providers/base-tts-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,oBAAoB,EACpB,WAAW,EACX,YAAY,EACb,MAAM,UAAU,CAAC;AAGlB;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;aAUf,QAAQ,EAAE,MAAM;aAChB,IAAI,EAAE,YAAY;aAElB,KAAK,CAAC,EAAE,KAAK;IAZ/B;;;;;;;OAOG;gBAEe,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,YAAY,EAClC,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,KAAK,YAAA;IAW/B;;OAEG;IACH,QAAQ,IAAI,MAAM;CAKnB;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,QAAQ;gBAClC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAI7D;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,QAAQ;gBAE3C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,KAAK;CAUhB;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,QAAQ;gBAClC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAS9D;AAED;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,QAAQ;gBACxC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAS9D;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,QAAQ;gBACpC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAI7D;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,QAAQ;gBAC5B,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAI7D;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,8BAAsB,eAAe;IACnC;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC;IAE7C;;;;OAIG;gBACS,YAAY,EAAE,WAAW;IAIrC;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,UAAU,CACjB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,WAAW,CAAC;IAEvB;;;;OAIG;IACI,eAAe,IAAI,WAAW;IAIrC;;;;;;;;;OASG;IACH,SAAS,CAAC,cAAc,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAgB7D;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAI/C;;;;;;;;;;OAUG;cACa,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMvE;;;;;;;;;;OAUG;IACH,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ;IAyD/D;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,SAAS,CAAC,GAAG,CACX,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,EAC1C,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,IAAI;CAGR"}
|