@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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LoonyLabs Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# @loonylabs/tts-middleware
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@loonylabs/tts-middleware)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[]()
|
|
6
|
+
[]()
|
|
7
|
+
|
|
8
|
+
**Provider-agnostic Text-to-Speech (TTS) middleware infrastructure.**
|
|
9
|
+
|
|
10
|
+
Build voice-enabled applications that switch seamlessly between Azure, EdenAI, OpenAI, ElevenLabs, and more without changing your application logic. Includes standardized error handling, accurate character counting for billing, and uniform audio output.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## ✨ Key Features
|
|
15
|
+
|
|
16
|
+
- **🔌 Provider Agnostic:** Unified API for all TTS providers. Switch providers by changing one config parameter.
|
|
17
|
+
- **☁️ Multi-Provider Support:**
|
|
18
|
+
- **Azure Speech Services:** Full support for Neural voices, emotions, and speaking styles.
|
|
19
|
+
- **EdenAI:** Access to 6+ providers (Google, OpenAI, Amazon, IBM, etc.) via a single aggregator API.
|
|
20
|
+
- **Ready for:** OpenAI, ElevenLabs, Google, Deepgram (interfaces prepared).
|
|
21
|
+
- **📝 SSML Abstraction:** Auto-generates provider-specific SSML markup (e.g., for Azure prosody/styles) from simple JSON options.
|
|
22
|
+
- **💰 Character Counting:** Precise character counting logic for billing estimation.
|
|
23
|
+
- **🛡️ Robust Error Handling:** Standardized error types (`InvalidConfigError`, `QuotaExceededError`, `NetworkError`) across all providers.
|
|
24
|
+
- **📐 TypeScript First:** Fully typed request/response objects and provider options.
|
|
25
|
+
- **🇪🇺 GDPR/DSGVO Ready:** Configurable region support (e.g., Azure Germany/Europe regions).
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 📦 Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install @loonylabs/tts-middleware
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 🚀 Quick Start
|
|
36
|
+
|
|
37
|
+
### 1. Configure Environment
|
|
38
|
+
|
|
39
|
+
Create a `.env` file in your project root:
|
|
40
|
+
|
|
41
|
+
```env
|
|
42
|
+
# Default Provider
|
|
43
|
+
TTS_DEFAULT_PROVIDER=azure
|
|
44
|
+
|
|
45
|
+
# Azure Speech Services
|
|
46
|
+
AZURE_SPEECH_KEY=your_azure_key
|
|
47
|
+
AZURE_SPEECH_REGION=germanywestcentral
|
|
48
|
+
|
|
49
|
+
# EdenAI (Optional)
|
|
50
|
+
EDENAI_API_KEY=your_edenai_key
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 2. Basic Usage
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { ttsService, TTSProvider } from '@loonylabs/tts-middleware';
|
|
57
|
+
import fs from 'fs';
|
|
58
|
+
|
|
59
|
+
async function generateSpeech() {
|
|
60
|
+
try {
|
|
61
|
+
// Synthesize speech
|
|
62
|
+
const response = await ttsService.synthesize({
|
|
63
|
+
text: "Hello! This is a test of the LoonyLabs TTS middleware.",
|
|
64
|
+
voice: { id: "en-US-JennyNeural" }, // Provider-specific voice ID
|
|
65
|
+
audio: {
|
|
66
|
+
format: "mp3",
|
|
67
|
+
speed: 1.0
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Save to file
|
|
72
|
+
fs.writeFileSync('output.mp3', response.audio);
|
|
73
|
+
|
|
74
|
+
console.log(`Generated audio: ${response.metadata.duration}ms`);
|
|
75
|
+
console.log(`Billed characters: ${response.billing.characters}`);
|
|
76
|
+
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error("Synthesis failed:", error);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
generateSpeech();
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 🛠️ Advanced Usage
|
|
88
|
+
|
|
89
|
+
### Using Provider-Specific Features (e.g., Azure Emotions)
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
const response = await ttsService.synthesize({
|
|
93
|
+
text: "I am so excited to tell you this!",
|
|
94
|
+
provider: TTSProvider.AZURE,
|
|
95
|
+
voice: { id: "en-US-JennyNeural" },
|
|
96
|
+
providerOptions: {
|
|
97
|
+
emotion: "cheerful", // Azure-specific
|
|
98
|
+
style: "chat", // Azure-specific
|
|
99
|
+
styleDegree: 1.5
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Switching Providers Dynamically
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
// Use EdenAI to access Google's TTS engine
|
|
108
|
+
const response = await ttsService.synthesize({
|
|
109
|
+
text: "Hello from Google via EdenAI",
|
|
110
|
+
provider: TTSProvider.EDENAI,
|
|
111
|
+
voice: { id: "en-US" },
|
|
112
|
+
providerOptions: {
|
|
113
|
+
provider: "google" // Select underlying provider
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 🏗️ Architecture
|
|
121
|
+
|
|
122
|
+
The middleware uses a singleton orchestrator pattern to manage provider instances.
|
|
123
|
+
|
|
124
|
+
```mermaid
|
|
125
|
+
graph TD
|
|
126
|
+
App[Your Application] -->|synthesize()| Service[TTSService]
|
|
127
|
+
Service -->|getProvider()| Registry{Provider Registry}
|
|
128
|
+
|
|
129
|
+
Registry -->|Select| Azure[AzureProvider]
|
|
130
|
+
Registry -->|Select| Eden[EdenAIProvider]
|
|
131
|
+
|
|
132
|
+
Azure -->|SSML/SDK| AzureAPI[Azure Speech API]
|
|
133
|
+
Eden -->|REST| EdenAPI[EdenAI API]
|
|
134
|
+
|
|
135
|
+
EdenAPI -.-> Google[Google TTS]
|
|
136
|
+
EdenAPI -.-> OpenAI[OpenAI TTS]
|
|
137
|
+
EdenAPI -.-> Amazon[Amazon Polly]
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 🧩 Supported Providers
|
|
143
|
+
|
|
144
|
+
| Provider | Status | Key Features |
|
|
145
|
+
|----------|--------|--------------|
|
|
146
|
+
| **Azure** | ✅ Stable | Neural Voices, Emotions, Styles, SSML, Visemes (planned) |
|
|
147
|
+
| **EdenAI** | ✅ Stable | Aggregator for Google, OpenAI, Amazon, IBM, Microsoft |
|
|
148
|
+
| **OpenAI** | 🔮 Planned | HD Audio, Simple API |
|
|
149
|
+
| **ElevenLabs** | 🔮 Planned | Voice Cloning, High Expressivity |
|
|
150
|
+
| **Google** | 🔮 Planned | WaveNet Voices, Pitch/Volume control |
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 🔧 Logging Configuration
|
|
155
|
+
|
|
156
|
+
The middleware includes a pluggable logger interface. By default, it uses `console`, but you can replace it with any logger (Winston, Pino, etc.).
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import { setLogger, silentLogger, setLogLevel } from '@loonylabs/tts-middleware';
|
|
160
|
+
|
|
161
|
+
// Disable all logging (useful for tests)
|
|
162
|
+
setLogger(silentLogger);
|
|
163
|
+
|
|
164
|
+
// Set minimum log level (debug, info, warn, error)
|
|
165
|
+
setLogLevel('warn'); // Only show warnings and errors
|
|
166
|
+
|
|
167
|
+
// Use custom logger (e.g., Winston)
|
|
168
|
+
setLogger({
|
|
169
|
+
info: (msg, meta) => winston.info(msg, meta),
|
|
170
|
+
warn: (msg, meta) => winston.warn(msg, meta),
|
|
171
|
+
error: (msg, meta) => winston.error(msg, meta),
|
|
172
|
+
debug: (msg, meta) => winston.debug(msg, meta),
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 🧪 Testing
|
|
179
|
+
|
|
180
|
+
The project maintains high code coverage (>94%) using Jest.
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Run unit & integration tests
|
|
184
|
+
npm test
|
|
185
|
+
|
|
186
|
+
# Run manual verification script (requires .env)
|
|
187
|
+
npx ts-node scripts/manual-test-edenai.ts
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## 🤝 Contributing
|
|
191
|
+
|
|
192
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines.
|
|
193
|
+
|
|
194
|
+
Contributions are welcome! Please ensure:
|
|
195
|
+
1. **Tests:** Add tests for new features.
|
|
196
|
+
2. **Linting:** Run `npm run lint` before committing.
|
|
197
|
+
3. **Conventions:** Follow the existing project structure.
|
|
198
|
+
|
|
199
|
+
## 📄 License
|
|
200
|
+
|
|
201
|
+
[MIT](LICENSE) © 2026 LoonyLabs Team
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @loonylabs/tts-middleware
|
|
3
|
+
*
|
|
4
|
+
* Provider-agnostic Text-to-Speech middleware for Azure, EdenAI, OpenAI,
|
|
5
|
+
* ElevenLabs, Google Cloud, and Deepgram.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { ttsService, TTSProvider } from '@loonylabs/tts-middleware';
|
|
10
|
+
*
|
|
11
|
+
* const response = await ttsService.synthesize({
|
|
12
|
+
* text: "Hello World",
|
|
13
|
+
* provider: TTSProvider.AZURE,
|
|
14
|
+
* voice: { id: "en-US-JennyNeural" },
|
|
15
|
+
* audio: { speed: 1.0, format: "mp3" }
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @packageDocumentation
|
|
20
|
+
*/
|
|
21
|
+
export * from './middleware/services/tts';
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,cAAc,2BAA2B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @loonylabs/tts-middleware
|
|
4
|
+
*
|
|
5
|
+
* Provider-agnostic Text-to-Speech middleware for Azure, EdenAI, OpenAI,
|
|
6
|
+
* ElevenLabs, Google Cloud, and Deepgram.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { ttsService, TTSProvider } from '@loonylabs/tts-middleware';
|
|
11
|
+
*
|
|
12
|
+
* const response = await ttsService.synthesize({
|
|
13
|
+
* text: "Hello World",
|
|
14
|
+
* provider: TTSProvider.AZURE,
|
|
15
|
+
* voice: { id: "en-US-JennyNeural" },
|
|
16
|
+
* audio: { speed: 1.0, format: "mp3" }
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @packageDocumentation
|
|
21
|
+
*/
|
|
22
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
25
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
26
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
27
|
+
}
|
|
28
|
+
Object.defineProperty(o, k2, desc);
|
|
29
|
+
}) : (function(o, m, k, k2) {
|
|
30
|
+
if (k2 === undefined) k2 = k;
|
|
31
|
+
o[k2] = m[k];
|
|
32
|
+
}));
|
|
33
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
34
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
35
|
+
};
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
// Re-export everything from the TTS middleware
|
|
38
|
+
__exportStar(require("./middleware/services/tts"), exports);
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;;;;;;;;;;;;;;;;AAEH,+CAA+C;AAC/C,4DAA0C"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TTS Middleware - Public API
|
|
3
|
+
*
|
|
4
|
+
* @description Main entry point for the TTS middleware.
|
|
5
|
+
* Exports all public types, providers, and the main service.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { ttsService, TTSProvider } from '@loonylabs/tts-middleware';
|
|
10
|
+
*
|
|
11
|
+
* const response = await ttsService.synthesize({
|
|
12
|
+
* text: "Hello World",
|
|
13
|
+
* provider: TTSProvider.AZURE,
|
|
14
|
+
* voice: { id: "en-US-JennyNeural" },
|
|
15
|
+
* audio: { speed: 1.0, format: "mp3" }
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @module @loonylabs/tts-middleware
|
|
20
|
+
*/
|
|
21
|
+
export { TTSService, ttsService } from './tts.service';
|
|
22
|
+
export { TTSProvider, TTSErrorCode, AudioFormat, } from './types';
|
|
23
|
+
export type { AudioOptions, VoiceConfig, TTSSynthesizeRequest, TTSResponse, TTSResponseMetadata, TTSBillingInfo, TTSVoice, TTSVoiceMetadata, AzureProviderOptions, OpenAIProviderOptions, ElevenLabsProviderOptions, GoogleCloudProviderOptions, DeepgramProviderOptions, EdenAIProviderOptions, ProviderOptions, } from './types';
|
|
24
|
+
export { isAzureOptions, isOpenAIOptions, isElevenLabsOptions, isGoogleCloudOptions, isDeepgramOptions, isEdenAIOptions, } from './types';
|
|
25
|
+
export { BaseTTSProvider, AzureProvider, EdenAIProvider, } from './providers';
|
|
26
|
+
export { TTSError, InvalidConfigError, InvalidVoiceError, QuotaExceededError, ProviderUnavailableError, SynthesisFailedError, NetworkError, } from './providers';
|
|
27
|
+
export { countCharacters, countCharactersWithoutSSML, validateCharacterCount, countBillableCharacters, estimateAudioDuration, formatCharacterCount, } from './utils';
|
|
28
|
+
export { setLogger, getLogger, resetLogger, setLogLevel, getLogLevel, silentLogger, } from './utils';
|
|
29
|
+
export type { TTSLogger, LogLevel } from './utils';
|
|
30
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/middleware/services/tts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGvD,OAAO,EACL,WAAW,EACX,YAAY,EACZ,WAAW,GACZ,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,0BAA0B,EAC1B,uBAAuB,EACvB,qBAAqB,EACrB,eAAe,GAChB,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,GAChB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,eAAe,EACf,aAAa,EACb,cAAc,GACf,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,QAAQ,EACR,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,oBAAoB,EACpB,YAAY,GACb,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,eAAe,EACf,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,SAAS,EACT,SAAS,EACT,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,GACb,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TTS Middleware - Public API
|
|
4
|
+
*
|
|
5
|
+
* @description Main entry point for the TTS middleware.
|
|
6
|
+
* Exports all public types, providers, and the main service.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { ttsService, TTSProvider } from '@loonylabs/tts-middleware';
|
|
11
|
+
*
|
|
12
|
+
* const response = await ttsService.synthesize({
|
|
13
|
+
* text: "Hello World",
|
|
14
|
+
* provider: TTSProvider.AZURE,
|
|
15
|
+
* voice: { id: "en-US-JennyNeural" },
|
|
16
|
+
* audio: { speed: 1.0, format: "mp3" }
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @module @loonylabs/tts-middleware
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.silentLogger = exports.getLogLevel = exports.setLogLevel = exports.resetLogger = exports.getLogger = exports.setLogger = exports.formatCharacterCount = exports.estimateAudioDuration = exports.countBillableCharacters = exports.validateCharacterCount = exports.countCharactersWithoutSSML = exports.countCharacters = exports.NetworkError = exports.SynthesisFailedError = exports.ProviderUnavailableError = exports.QuotaExceededError = exports.InvalidVoiceError = exports.InvalidConfigError = exports.TTSError = exports.EdenAIProvider = exports.AzureProvider = exports.BaseTTSProvider = exports.isEdenAIOptions = exports.isDeepgramOptions = exports.isGoogleCloudOptions = exports.isElevenLabsOptions = exports.isOpenAIOptions = exports.isAzureOptions = exports.TTSErrorCode = exports.TTSProvider = exports.ttsService = exports.TTSService = void 0;
|
|
24
|
+
// ===== Main Service =====
|
|
25
|
+
var tts_service_1 = require("./tts.service");
|
|
26
|
+
Object.defineProperty(exports, "TTSService", { enumerable: true, get: function () { return tts_service_1.TTSService; } });
|
|
27
|
+
Object.defineProperty(exports, "ttsService", { enumerable: true, get: function () { return tts_service_1.ttsService; } });
|
|
28
|
+
// ===== Types =====
|
|
29
|
+
var types_1 = require("./types");
|
|
30
|
+
Object.defineProperty(exports, "TTSProvider", { enumerable: true, get: function () { return types_1.TTSProvider; } });
|
|
31
|
+
Object.defineProperty(exports, "TTSErrorCode", { enumerable: true, get: function () { return types_1.TTSErrorCode; } });
|
|
32
|
+
var types_2 = require("./types");
|
|
33
|
+
Object.defineProperty(exports, "isAzureOptions", { enumerable: true, get: function () { return types_2.isAzureOptions; } });
|
|
34
|
+
Object.defineProperty(exports, "isOpenAIOptions", { enumerable: true, get: function () { return types_2.isOpenAIOptions; } });
|
|
35
|
+
Object.defineProperty(exports, "isElevenLabsOptions", { enumerable: true, get: function () { return types_2.isElevenLabsOptions; } });
|
|
36
|
+
Object.defineProperty(exports, "isGoogleCloudOptions", { enumerable: true, get: function () { return types_2.isGoogleCloudOptions; } });
|
|
37
|
+
Object.defineProperty(exports, "isDeepgramOptions", { enumerable: true, get: function () { return types_2.isDeepgramOptions; } });
|
|
38
|
+
Object.defineProperty(exports, "isEdenAIOptions", { enumerable: true, get: function () { return types_2.isEdenAIOptions; } });
|
|
39
|
+
// ===== Providers =====
|
|
40
|
+
var providers_1 = require("./providers");
|
|
41
|
+
Object.defineProperty(exports, "BaseTTSProvider", { enumerable: true, get: function () { return providers_1.BaseTTSProvider; } });
|
|
42
|
+
Object.defineProperty(exports, "AzureProvider", { enumerable: true, get: function () { return providers_1.AzureProvider; } });
|
|
43
|
+
Object.defineProperty(exports, "EdenAIProvider", { enumerable: true, get: function () { return providers_1.EdenAIProvider; } });
|
|
44
|
+
// ===== Errors =====
|
|
45
|
+
var providers_2 = require("./providers");
|
|
46
|
+
Object.defineProperty(exports, "TTSError", { enumerable: true, get: function () { return providers_2.TTSError; } });
|
|
47
|
+
Object.defineProperty(exports, "InvalidConfigError", { enumerable: true, get: function () { return providers_2.InvalidConfigError; } });
|
|
48
|
+
Object.defineProperty(exports, "InvalidVoiceError", { enumerable: true, get: function () { return providers_2.InvalidVoiceError; } });
|
|
49
|
+
Object.defineProperty(exports, "QuotaExceededError", { enumerable: true, get: function () { return providers_2.QuotaExceededError; } });
|
|
50
|
+
Object.defineProperty(exports, "ProviderUnavailableError", { enumerable: true, get: function () { return providers_2.ProviderUnavailableError; } });
|
|
51
|
+
Object.defineProperty(exports, "SynthesisFailedError", { enumerable: true, get: function () { return providers_2.SynthesisFailedError; } });
|
|
52
|
+
Object.defineProperty(exports, "NetworkError", { enumerable: true, get: function () { return providers_2.NetworkError; } });
|
|
53
|
+
// ===== Utilities =====
|
|
54
|
+
var utils_1 = require("./utils");
|
|
55
|
+
Object.defineProperty(exports, "countCharacters", { enumerable: true, get: function () { return utils_1.countCharacters; } });
|
|
56
|
+
Object.defineProperty(exports, "countCharactersWithoutSSML", { enumerable: true, get: function () { return utils_1.countCharactersWithoutSSML; } });
|
|
57
|
+
Object.defineProperty(exports, "validateCharacterCount", { enumerable: true, get: function () { return utils_1.validateCharacterCount; } });
|
|
58
|
+
Object.defineProperty(exports, "countBillableCharacters", { enumerable: true, get: function () { return utils_1.countBillableCharacters; } });
|
|
59
|
+
Object.defineProperty(exports, "estimateAudioDuration", { enumerable: true, get: function () { return utils_1.estimateAudioDuration; } });
|
|
60
|
+
Object.defineProperty(exports, "formatCharacterCount", { enumerable: true, get: function () { return utils_1.formatCharacterCount; } });
|
|
61
|
+
// ===== Logger =====
|
|
62
|
+
var utils_2 = require("./utils");
|
|
63
|
+
Object.defineProperty(exports, "setLogger", { enumerable: true, get: function () { return utils_2.setLogger; } });
|
|
64
|
+
Object.defineProperty(exports, "getLogger", { enumerable: true, get: function () { return utils_2.getLogger; } });
|
|
65
|
+
Object.defineProperty(exports, "resetLogger", { enumerable: true, get: function () { return utils_2.resetLogger; } });
|
|
66
|
+
Object.defineProperty(exports, "setLogLevel", { enumerable: true, get: function () { return utils_2.setLogLevel; } });
|
|
67
|
+
Object.defineProperty(exports, "getLogLevel", { enumerable: true, get: function () { return utils_2.getLogLevel; } });
|
|
68
|
+
Object.defineProperty(exports, "silentLogger", { enumerable: true, get: function () { return utils_2.silentLogger; } });
|
|
69
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/middleware/services/tts/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;;;AAEH,2BAA2B;AAC3B,6CAAuD;AAA9C,yGAAA,UAAU,OAAA;AAAE,yGAAA,UAAU,OAAA;AAE/B,oBAAoB;AACpB,iCAIiB;AAHf,oGAAA,WAAW,OAAA;AACX,qGAAA,YAAY,OAAA;AAsBd,iCAOiB;AANf,uGAAA,cAAc,OAAA;AACd,wGAAA,eAAe,OAAA;AACf,4GAAA,mBAAmB,OAAA;AACnB,6GAAA,oBAAoB,OAAA;AACpB,0GAAA,iBAAiB,OAAA;AACjB,wGAAA,eAAe,OAAA;AAGjB,wBAAwB;AACxB,yCAIqB;AAHnB,4GAAA,eAAe,OAAA;AACf,0GAAA,aAAa,OAAA;AACb,2GAAA,cAAc,OAAA;AAGhB,qBAAqB;AACrB,yCAQqB;AAPnB,qGAAA,QAAQ,OAAA;AACR,+GAAA,kBAAkB,OAAA;AAClB,8GAAA,iBAAiB,OAAA;AACjB,+GAAA,kBAAkB,OAAA;AAClB,qHAAA,wBAAwB,OAAA;AACxB,iHAAA,oBAAoB,OAAA;AACpB,yGAAA,YAAY,OAAA;AAGd,wBAAwB;AACxB,iCAOiB;AANf,wGAAA,eAAe,OAAA;AACf,mHAAA,0BAA0B,OAAA;AAC1B,+GAAA,sBAAsB,OAAA;AACtB,gHAAA,uBAAuB,OAAA;AACvB,8GAAA,qBAAqB,OAAA;AACrB,6GAAA,oBAAoB,OAAA;AAGtB,qBAAqB;AACrB,iCAOiB;AANf,kGAAA,SAAS,OAAA;AACT,kGAAA,SAAS,OAAA;AACT,oGAAA,WAAW,OAAA;AACX,oGAAA,WAAW,OAAA;AACX,oGAAA,WAAW,OAAA;AACX,qGAAA,YAAY,OAAA"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Azure Speech Services TTS Provider
|
|
3
|
+
*
|
|
4
|
+
* @description Implementation of TTS provider for Microsoft Azure Speech Services.
|
|
5
|
+
* This is the MVP provider for EU-compliant TTS synthesis.
|
|
6
|
+
*
|
|
7
|
+
* @see https://learn.microsoft.com/en-us/azure/ai-services/speech-service/
|
|
8
|
+
*/
|
|
9
|
+
import type { TTSSynthesizeRequest, TTSResponse } from '../types';
|
|
10
|
+
import { BaseTTSProvider } from './base-tts-provider';
|
|
11
|
+
/**
|
|
12
|
+
* Azure-specific configuration
|
|
13
|
+
*/
|
|
14
|
+
interface AzureConfig {
|
|
15
|
+
subscriptionKey: string;
|
|
16
|
+
region: string;
|
|
17
|
+
endpoint?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Azure Speech Services provider implementation
|
|
21
|
+
*
|
|
22
|
+
* @description Provides TTS synthesis using Microsoft Azure Speech Services.
|
|
23
|
+
* Supports emotion, style, and multiple audio formats.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const provider = new AzureProvider();
|
|
28
|
+
* const response = await provider.synthesize(
|
|
29
|
+
* "Hello World",
|
|
30
|
+
* "en-US-JennyNeural",
|
|
31
|
+
* {
|
|
32
|
+
* text: "Hello World",
|
|
33
|
+
* voice: { id: "en-US-JennyNeural" },
|
|
34
|
+
* audio: { speed: 1.0, format: "mp3" },
|
|
35
|
+
* providerOptions: { emotion: "cheerful" }
|
|
36
|
+
* }
|
|
37
|
+
* );
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare class AzureProvider extends BaseTTSProvider {
|
|
41
|
+
private config;
|
|
42
|
+
private speechConfig;
|
|
43
|
+
/**
|
|
44
|
+
* Creates a new Azure TTS provider
|
|
45
|
+
*
|
|
46
|
+
* @param config - Optional Azure configuration (uses env vars if not provided)
|
|
47
|
+
* @throws {InvalidConfigError} If required configuration is missing
|
|
48
|
+
*/
|
|
49
|
+
constructor(config?: Partial<AzureConfig>);
|
|
50
|
+
/**
|
|
51
|
+
* Validate Azure-specific configuration
|
|
52
|
+
*
|
|
53
|
+
* @private
|
|
54
|
+
* @throws {InvalidConfigError} If configuration is invalid
|
|
55
|
+
*/
|
|
56
|
+
private validateAzureConfig;
|
|
57
|
+
/**
|
|
58
|
+
* Initialize Azure Speech SDK configuration
|
|
59
|
+
*
|
|
60
|
+
* @private
|
|
61
|
+
*/
|
|
62
|
+
private initializeSpeechConfig;
|
|
63
|
+
/**
|
|
64
|
+
* Synthesize text to speech using Azure Speech Services
|
|
65
|
+
*
|
|
66
|
+
* @param text - The input text to synthesize
|
|
67
|
+
* @param voiceId - The voice identifier (e.g., "en-US-JennyNeural")
|
|
68
|
+
* @param request - The full synthesis request with options
|
|
69
|
+
* @returns Promise resolving to the synthesis response
|
|
70
|
+
* @throws {InvalidConfigError} If configuration is invalid
|
|
71
|
+
* @throws {InvalidVoiceError} If voice is not found
|
|
72
|
+
* @throws {SynthesisFailedError} If synthesis fails
|
|
73
|
+
*/
|
|
74
|
+
synthesize(text: string, voiceId: string, request: TTSSynthesizeRequest): Promise<TTSResponse>;
|
|
75
|
+
/**
|
|
76
|
+
* Set audio output format for Azure Speech SDK
|
|
77
|
+
*
|
|
78
|
+
* @private
|
|
79
|
+
* @param format - The audio format (mp3, wav, opus)
|
|
80
|
+
* @param sampleRate - The sample rate in Hz
|
|
81
|
+
*/
|
|
82
|
+
private setAudioFormat;
|
|
83
|
+
/**
|
|
84
|
+
* Map audio format and sample rate to Azure format enum
|
|
85
|
+
*
|
|
86
|
+
* @private
|
|
87
|
+
* @param format - The audio format
|
|
88
|
+
* @param sampleRate - The sample rate in Hz
|
|
89
|
+
* @returns Azure audio format enum value
|
|
90
|
+
*/
|
|
91
|
+
private getAzureAudioFormat;
|
|
92
|
+
/**
|
|
93
|
+
* Generate SSML from plain text and options
|
|
94
|
+
*
|
|
95
|
+
* @private
|
|
96
|
+
* @param text - The input text
|
|
97
|
+
* @param voiceId - The voice identifier
|
|
98
|
+
* @param request - The synthesis request with options
|
|
99
|
+
* @returns SSML string
|
|
100
|
+
*/
|
|
101
|
+
private generateSSML;
|
|
102
|
+
/**
|
|
103
|
+
* Convert speed multiplier to SSML prosody rate value
|
|
104
|
+
*
|
|
105
|
+
* @private
|
|
106
|
+
* @param speed - Speed multiplier (0.5 - 2.0)
|
|
107
|
+
* @returns SSML rate value
|
|
108
|
+
*/
|
|
109
|
+
private speedToProsodyRate;
|
|
110
|
+
/**
|
|
111
|
+
* Escape XML special characters
|
|
112
|
+
*
|
|
113
|
+
* @private
|
|
114
|
+
* @param text - The text to escape
|
|
115
|
+
* @returns Escaped text
|
|
116
|
+
*/
|
|
117
|
+
private escapeXML;
|
|
118
|
+
/**
|
|
119
|
+
* Synthesize SSML using Azure Speech SDK
|
|
120
|
+
*
|
|
121
|
+
* @private
|
|
122
|
+
* @param synthesizer - The speech synthesizer
|
|
123
|
+
* @param ssml - The SSML to synthesize
|
|
124
|
+
* @returns Promise resolving to audio buffer
|
|
125
|
+
* @throws {InvalidVoiceError} If voice is not found
|
|
126
|
+
* @throws {SynthesisFailedError} If synthesis fails
|
|
127
|
+
*/
|
|
128
|
+
private synthesizeSSML;
|
|
129
|
+
}
|
|
130
|
+
export {};
|
|
131
|
+
//# sourceMappingURL=azure-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azure-provider.d.ts","sourceRoot":"","sources":["../../../../../src/middleware/services/tts/providers/azure-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAe,MAAM,UAAU,CAAC;AAE/E,OAAO,EACL,eAAe,EAIhB,MAAM,qBAAqB,CAAC;AAE7B;;GAEG;AACH,UAAU,WAAW;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,aAAc,SAAQ,eAAe;IAChD,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,YAAY,CAAiC;IAErD;;;;;OAKG;gBACS,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC;IAkBzC;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAgB3B;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IA2B9B;;;;;;;;;;OAUG;IACG,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,WAAW,CAAC;IA4EvB;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAoBtB;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IA0C3B;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;IAgDpB;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;;;;;OAMG;IACH,OAAO,CAAC,SAAS;IASjB;;;;;;;;;OASG;YACW,cAAc;CA0D7B"}
|