@andresaya/edge-tts 1.8.0 → 1.8.3
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/README.md +543 -525
- package/dist/browser/edge-tts.esm.js +29 -32
- package/dist/browser/edge-tts.esm.js.map +2 -2
- package/dist/browser/edge-tts.esm.min.js +10 -10
- package/dist/browser/edge-tts.esm.min.js.map +3 -3
- package/dist/browser/edge-tts.umd.js +29 -32
- package/dist/browser/edge-tts.umd.js.map +2 -2
- package/dist/browser/edge-tts.umd.min.js +11 -11
- package/dist/browser/edge-tts.umd.min.js.map +3 -3
- package/dist/cli/edge-tts.js +3 -6
- package/dist/commands/VoiceListCommand.js +1 -1
- package/dist/config/constants.d.ts +1 -2
- package/dist/config/constants.js +9 -9
- package/dist/services/EdgeTTS.js +34 -21
- package/package.json +48 -54
package/README.md
CHANGED
|
@@ -1,525 +1,543 @@
|
|
|
1
|
-
# Edge TTS
|
|
2
|
-
[](https://deepwiki.com/andresayac/edge-tts)
|
|
3
|
-
|
|
4
|
-
**Edge TTS** is a powerful Text-to-Speech (TTS) package that leverages Microsoft's Edge capabilities. This package allows you to synthesize speech from text and manage voice options easily through a command-line interface (CLI).
|
|
5
|
-
|
|
6
|
-
## Features
|
|
7
|
-
|
|
8
|
-
- **Text-to-Speech**: Convert text into natural-sounding speech using Microsoft Edge's TTS capabilities.
|
|
9
|
-
- **TypeScript Support**: Full TypeScript support with comprehensive type definitions included.
|
|
10
|
-
- **Multiple Audio Formats**: Support for 36+ audio formats (MP3, WebM, OGG, WAV, PCM, and more).
|
|
11
|
-
- **Multiple Voices**: Access a variety of voices to suit your project's needs.
|
|
12
|
-
- **Voice Filtering**: Filter voices by language and gender for better selection.
|
|
13
|
-
- **Audio Information**: Get detailed information about generated audio (size, duration, format).
|
|
14
|
-
- **Audio Export Options**: Export synthesized audio in different formats (raw, base64, or directly to a file).
|
|
15
|
-
- **Streaming Support**: Stream audio data in real-time for better performance.
|
|
16
|
-
- **Word Boundaries Metadata**: Get word boundary information with precise timestamps.
|
|
17
|
-
- **Command-Line Interface**: Use a simple CLI for easy access to functionality.
|
|
18
|
-
- **Easy Integration**: Modular structure allows for easy inclusion in existing projects.
|
|
19
|
-
|
|
20
|
-
## Installation
|
|
21
|
-
|
|
22
|
-
You can install Edge TTS via npm or bun:
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
bun add @andresaya/edge-tts
|
|
26
|
-
```
|
|
27
|
-
```bash
|
|
28
|
-
npm install @andresaya/edge-tts
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## TypeScript Support
|
|
32
|
-
|
|
33
|
-
Edge TTS is written in **TypeScript** and includes full type definitions. No additional `@types` packages are needed.
|
|
34
|
-
|
|
35
|
-
### Available Types
|
|
36
|
-
|
|
37
|
-
```typescript
|
|
38
|
-
import {
|
|
39
|
-
EdgeTTS,
|
|
40
|
-
Constants,
|
|
41
|
-
Voice,
|
|
42
|
-
SynthesisOptions,
|
|
43
|
-
WordBoundary
|
|
44
|
-
} from '@andresaya/edge-tts';
|
|
45
|
-
|
|
46
|
-
// Voice interface
|
|
47
|
-
interface Voice {
|
|
48
|
-
Name: string;
|
|
49
|
-
ShortName: string;
|
|
50
|
-
Gender: 'Male' | 'Female';
|
|
51
|
-
Locale: string;
|
|
52
|
-
FriendlyName: string;
|
|
53
|
-
LocalName: string;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Synthesis options
|
|
57
|
-
interface SynthesisOptions {
|
|
58
|
-
pitch?: string | number; // e.g., '+20Hz' or 20
|
|
59
|
-
rate?: string | number; // e.g., '50%' or 50
|
|
60
|
-
volume?: string | number; // e.g., '90%' or 90
|
|
61
|
-
outputFormat?: string; // e.g., Constants.OUTPUT_FORMAT.AUDIO_24KHZ_96KBITRATE_MONO_MP3
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Word boundary metadata
|
|
65
|
-
interface WordBoundary {
|
|
66
|
-
type: "WordBoundary";
|
|
67
|
-
offset: number;
|
|
68
|
-
duration: number;
|
|
69
|
-
text: string;
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Type-Safe Usage Example
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
import { EdgeTTS, SynthesisOptions, Constants } from '@andresaya/edge-tts';
|
|
77
|
-
|
|
78
|
-
const tts = new EdgeTTS();
|
|
79
|
-
|
|
80
|
-
const options: SynthesisOptions = {
|
|
81
|
-
pitch: '+10Hz',
|
|
82
|
-
rate: '100%',
|
|
83
|
-
volume: '90%',
|
|
84
|
-
outputFormat: Constants.OUTPUT_FORMAT.WEBM_24KHZ_16BIT_MONO_OPUS
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
await tts.synthesize("TypeScript example", 'en-US-AriaNeural', options);
|
|
88
|
-
|
|
89
|
-
const info = tts.getAudioInfo(); // Returns: { size: number; format: string; estimatedDuration: number }
|
|
90
|
-
const boundaries = tts.getWordBoundaries(); // Returns: WordBoundary[]
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
## Usage
|
|
94
|
-
|
|
95
|
-
### Command-Line Interface
|
|
96
|
-
|
|
97
|
-
Install globally to use the CLI:
|
|
98
|
-
|
|
99
|
-
```bash
|
|
100
|
-
npm install -g @andresaya/edge-tts
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
To synthesize speech from text:
|
|
104
|
-
```bash
|
|
105
|
-
edge-tts synthesize -t "Hello, world!" -o hello_world_audio
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
To list available voices:
|
|
109
|
-
```bash
|
|
110
|
-
edge-tts voice-list
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### Integration into Your Project
|
|
114
|
-
|
|
115
|
-
```js
|
|
116
|
-
import { EdgeTTS } from '@andresaya/edge-tts';
|
|
117
|
-
|
|
118
|
-
// Initialize the EdgeTTS service
|
|
119
|
-
const tts = new EdgeTTS();
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## API Reference
|
|
123
|
-
|
|
124
|
-
### Voice Management
|
|
125
|
-
|
|
126
|
-
#### Get All Voices
|
|
127
|
-
```js
|
|
128
|
-
const voices = await tts.getVoices();
|
|
129
|
-
console.log(`Found ${voices.length} voices`);
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
#### Filter Voices by Language
|
|
133
|
-
```js
|
|
134
|
-
// Get all English voices
|
|
135
|
-
const englishVoices = await tts.getVoicesByLanguage('en');
|
|
136
|
-
|
|
137
|
-
// Get specific locale voices
|
|
138
|
-
const usEnglishVoices = await tts.getVoicesByLanguage('en-US');
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
#### Filter Voices by Gender
|
|
142
|
-
```js
|
|
143
|
-
// Get all female voices
|
|
144
|
-
const femaleVoices = await tts.getVoicesByGender('Female');
|
|
145
|
-
|
|
146
|
-
// Get all male voices
|
|
147
|
-
const maleVoices = await tts.getVoicesByGender('Male');
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### Text Synthesis
|
|
151
|
-
|
|
152
|
-
#### Basic Synthesis
|
|
153
|
-
```js
|
|
154
|
-
// Simple synthesis with default voice
|
|
155
|
-
await tts.synthesize("Hello, world!");
|
|
156
|
-
|
|
157
|
-
// Synthesis with specific voice
|
|
158
|
-
await tts.synthesize("Hello, world!", 'en-US-AriaNeural');
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
####
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
await tts.synthesize("Hello!", 'en-US-AriaNeural', {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
###
|
|
243
|
-
|
|
244
|
-
####
|
|
245
|
-
```js
|
|
246
|
-
await tts.synthesize("Hello, world!");
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
const
|
|
450
|
-
const
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
1
|
+
# Edge TTS
|
|
2
|
+
[](https://deepwiki.com/andresayac/edge-tts)
|
|
3
|
+
|
|
4
|
+
**Edge TTS** is a powerful Text-to-Speech (TTS) package that leverages Microsoft's Edge capabilities. This package allows you to synthesize speech from text and manage voice options easily through a command-line interface (CLI).
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- **Text-to-Speech**: Convert text into natural-sounding speech using Microsoft Edge's TTS capabilities.
|
|
9
|
+
- **TypeScript Support**: Full TypeScript support with comprehensive type definitions included.
|
|
10
|
+
- **Multiple Audio Formats**: Support for 36+ audio formats (MP3, WebM, OGG, WAV, PCM, and more).
|
|
11
|
+
- **Multiple Voices**: Access a variety of voices to suit your project's needs.
|
|
12
|
+
- **Voice Filtering**: Filter voices by language and gender for better selection.
|
|
13
|
+
- **Audio Information**: Get detailed information about generated audio (size, duration, format).
|
|
14
|
+
- **Audio Export Options**: Export synthesized audio in different formats (raw, base64, or directly to a file).
|
|
15
|
+
- **Streaming Support**: Stream audio data in real-time for better performance.
|
|
16
|
+
- **Word Boundaries Metadata**: Get word boundary information with precise timestamps.
|
|
17
|
+
- **Command-Line Interface**: Use a simple CLI for easy access to functionality.
|
|
18
|
+
- **Easy Integration**: Modular structure allows for easy inclusion in existing projects.
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
You can install Edge TTS via npm or bun:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
bun add @andresaya/edge-tts
|
|
26
|
+
```
|
|
27
|
+
```bash
|
|
28
|
+
npm install @andresaya/edge-tts
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## TypeScript Support
|
|
32
|
+
|
|
33
|
+
Edge TTS is written in **TypeScript** and includes full type definitions. No additional `@types` packages are needed.
|
|
34
|
+
|
|
35
|
+
### Available Types
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import {
|
|
39
|
+
EdgeTTS,
|
|
40
|
+
Constants,
|
|
41
|
+
Voice,
|
|
42
|
+
SynthesisOptions,
|
|
43
|
+
WordBoundary
|
|
44
|
+
} from '@andresaya/edge-tts';
|
|
45
|
+
|
|
46
|
+
// Voice interface
|
|
47
|
+
interface Voice {
|
|
48
|
+
Name: string;
|
|
49
|
+
ShortName: string;
|
|
50
|
+
Gender: 'Male' | 'Female';
|
|
51
|
+
Locale: string;
|
|
52
|
+
FriendlyName: string;
|
|
53
|
+
LocalName: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Synthesis options
|
|
57
|
+
interface SynthesisOptions {
|
|
58
|
+
pitch?: string | number; // e.g., '+20Hz' or 20
|
|
59
|
+
rate?: string | number; // e.g., '50%' or 50
|
|
60
|
+
volume?: string | number; // e.g., '90%' or 90
|
|
61
|
+
outputFormat?: string; // e.g., Constants.OUTPUT_FORMAT.AUDIO_24KHZ_96KBITRATE_MONO_MP3
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Word boundary metadata
|
|
65
|
+
interface WordBoundary {
|
|
66
|
+
type: "WordBoundary";
|
|
67
|
+
offset: number;
|
|
68
|
+
duration: number;
|
|
69
|
+
text: string;
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Type-Safe Usage Example
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { EdgeTTS, SynthesisOptions, Constants } from '@andresaya/edge-tts';
|
|
77
|
+
|
|
78
|
+
const tts = new EdgeTTS();
|
|
79
|
+
|
|
80
|
+
const options: SynthesisOptions = {
|
|
81
|
+
pitch: '+10Hz',
|
|
82
|
+
rate: '100%',
|
|
83
|
+
volume: '90%',
|
|
84
|
+
outputFormat: Constants.OUTPUT_FORMAT.WEBM_24KHZ_16BIT_MONO_OPUS
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
await tts.synthesize("TypeScript example", 'en-US-AriaNeural', options);
|
|
88
|
+
|
|
89
|
+
const info = tts.getAudioInfo(); // Returns: { size: number; format: string; estimatedDuration: number }
|
|
90
|
+
const boundaries = tts.getWordBoundaries(); // Returns: WordBoundary[]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Usage
|
|
94
|
+
|
|
95
|
+
### Command-Line Interface
|
|
96
|
+
|
|
97
|
+
Install globally to use the CLI:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npm install -g @andresaya/edge-tts
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
To synthesize speech from text:
|
|
104
|
+
```bash
|
|
105
|
+
edge-tts synthesize -t "Hello, world!" -o hello_world_audio
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
To list available voices:
|
|
109
|
+
```bash
|
|
110
|
+
edge-tts voice-list
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Integration into Your Project
|
|
114
|
+
|
|
115
|
+
```js
|
|
116
|
+
import { EdgeTTS } from '@andresaya/edge-tts';
|
|
117
|
+
|
|
118
|
+
// Initialize the EdgeTTS service
|
|
119
|
+
const tts = new EdgeTTS();
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## API Reference
|
|
123
|
+
|
|
124
|
+
### Voice Management
|
|
125
|
+
|
|
126
|
+
#### Get All Voices
|
|
127
|
+
```js
|
|
128
|
+
const voices = await tts.getVoices();
|
|
129
|
+
console.log(`Found ${voices.length} voices`);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### Filter Voices by Language
|
|
133
|
+
```js
|
|
134
|
+
// Get all English voices
|
|
135
|
+
const englishVoices = await tts.getVoicesByLanguage('en');
|
|
136
|
+
|
|
137
|
+
// Get specific locale voices
|
|
138
|
+
const usEnglishVoices = await tts.getVoicesByLanguage('en-US');
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
#### Filter Voices by Gender
|
|
142
|
+
```js
|
|
143
|
+
// Get all female voices
|
|
144
|
+
const femaleVoices = await tts.getVoicesByGender('Female');
|
|
145
|
+
|
|
146
|
+
// Get all male voices
|
|
147
|
+
const maleVoices = await tts.getVoicesByGender('Male');
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Text Synthesis
|
|
151
|
+
|
|
152
|
+
#### Basic Synthesis
|
|
153
|
+
```js
|
|
154
|
+
// Simple synthesis with default voice
|
|
155
|
+
await tts.synthesize("Hello, world!");
|
|
156
|
+
|
|
157
|
+
// Synthesis with specific voice
|
|
158
|
+
await tts.synthesize("Hello, world!", 'en-US-AriaNeural');
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### Matching the voice to the text
|
|
162
|
+
|
|
163
|
+
Voices are locale specific. A voice can only read text written in the script of
|
|
164
|
+
its own language, so passing Chinese, Cyrillic, Arabic or Devanagari text to an
|
|
165
|
+
English voice returns no audio at all:
|
|
166
|
+
|
|
167
|
+
```js
|
|
168
|
+
// Nothing to play: an English voice cannot read this.
|
|
169
|
+
await tts.synthesize("这是一个测试", 'en-US-AriaNeural');
|
|
170
|
+
|
|
171
|
+
// Works.
|
|
172
|
+
await tts.synthesize("这是一个测试", 'zh-CN-XiaoxiaoNeural');
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
A few foreign words inside an otherwise English sentence are fine; the problem
|
|
176
|
+
only appears when the other script is most of the text. `toBuffer()` throws in
|
|
177
|
+
this case rather than handing back an empty buffer.
|
|
178
|
+
|
|
179
|
+
#### Advanced Synthesis with Options
|
|
180
|
+
```js
|
|
181
|
+
await tts.synthesize("Hello, world!", 'en-US-AriaNeural', {
|
|
182
|
+
rate: '50%', // Speech rate: -100% to +200% (or number)
|
|
183
|
+
volume: '90%', // Speech volume: -100% to +100% (or number)
|
|
184
|
+
pitch: '+20Hz', // Voice pitch: -100Hz to +100Hz (or number)
|
|
185
|
+
outputFormat: 'audio-24khz-96kbitrate-mono-mp3' // Audio output format
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### Audio Output Formats
|
|
190
|
+
|
|
191
|
+
Edge TTS supports multiple audio formats. You can specify the format using the `outputFormat` option:
|
|
192
|
+
|
|
193
|
+
```js
|
|
194
|
+
import { EdgeTTS, Constants } from '@andresaya/edge-tts';
|
|
195
|
+
|
|
196
|
+
const tts = new EdgeTTS();
|
|
197
|
+
|
|
198
|
+
// High quality MP3
|
|
199
|
+
await tts.synthesize("Hello!", 'en-US-AriaNeural', {
|
|
200
|
+
outputFormat: Constants.OUTPUT_FORMAT.AUDIO_24KHZ_96KBITRATE_MONO_MP3
|
|
201
|
+
});
|
|
202
|
+
await tts.toFile('./output/audio'); // Automatically saved as .mp3
|
|
203
|
+
|
|
204
|
+
// WebM/Opus for web
|
|
205
|
+
await tts.synthesize("Hello!", 'en-US-AriaNeural', {
|
|
206
|
+
outputFormat: Constants.OUTPUT_FORMAT.WEBM_24KHZ_16BIT_MONO_OPUS
|
|
207
|
+
});
|
|
208
|
+
await tts.toFile('./output/audio'); // Automatically saved as .webm
|
|
209
|
+
|
|
210
|
+
// Lossless WAV
|
|
211
|
+
await tts.synthesize("Hello!", 'en-US-AriaNeural', {
|
|
212
|
+
outputFormat: Constants.OUTPUT_FORMAT.RIFF_24KHZ_16BIT_MONO_PCM
|
|
213
|
+
});
|
|
214
|
+
await tts.toFile('./output/audio'); // Automatically saved as .wav
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Available formats (all 36 tested and compatible):**
|
|
218
|
+
|
|
219
|
+
- **MP3 Formats** (Streaming): 16kHz, 24kHz, 48kHz with various bitrates (32-192 kbps)
|
|
220
|
+
- **Opus Formats** (Streaming): Audio, WebM, and OGG containers
|
|
221
|
+
- **WAV/PCM Formats** (Non-streaming): RIFF (8-48 kHz) and RAW variants
|
|
222
|
+
- **Specialized Codecs**: AMR-WB, G.722, TrueSilk, A-law, μ-law
|
|
223
|
+
|
|
224
|
+
See `Constants.OUTPUT_FORMAT` for the complete list. The file extension is automatically detected based on the format.
|
|
225
|
+
|
|
226
|
+
**Format recommendations:**
|
|
227
|
+
- 🌐 **Web streaming**: `WEBM_24KHZ_16BIT_MONO_OPUS` or `AUDIO_24KHZ_96KBITRATE_MONO_MP3`
|
|
228
|
+
- 📱 **Mobile apps**: `AUDIO_24KHZ_48KBITRATE_MONO_MP3`
|
|
229
|
+
- 💾 **High quality**: `AUDIO_48KHZ_192KBITRATE_MONO_MP3` or `RIFF_48KHZ_16BIT_MONO_PCM`
|
|
230
|
+
- ⚡ **Low bandwidth**: `AUDIO_16KHZ_32KBITRATE_MONO_MP3`
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
#### Streaming Synthesis
|
|
234
|
+
```js
|
|
235
|
+
// Stream audio data in real-time
|
|
236
|
+
for await (const chunk of tts.synthesizeStream("Long text to stream...", 'en-US-AriaNeural')) {
|
|
237
|
+
// Process each audio chunk as it arrives
|
|
238
|
+
console.log(`Received chunk: ${chunk.length} bytes`);
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Audio Information
|
|
243
|
+
|
|
244
|
+
#### Get Audio Details
|
|
245
|
+
```js
|
|
246
|
+
await tts.synthesize("Hello, world!");
|
|
247
|
+
|
|
248
|
+
const audioInfo = tts.getAudioInfo();
|
|
249
|
+
console.log(`Size: ${audioInfo.size} bytes`);
|
|
250
|
+
console.log(`Format: ${audioInfo.format}`);
|
|
251
|
+
console.log(`Duration: ${audioInfo.estimatedDuration} seconds`);
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
#### Get Duration Only
|
|
255
|
+
```js
|
|
256
|
+
const duration = tts.getDuration();
|
|
257
|
+
console.log(`Audio duration: ${duration} seconds`);
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Export Options
|
|
261
|
+
|
|
262
|
+
#### Export as Base64
|
|
263
|
+
```js
|
|
264
|
+
await tts.synthesize("Hello, world!");
|
|
265
|
+
const base64Audio = tts.toBase64();
|
|
266
|
+
console.log(`Base64 length: ${base64Audio.length}`);
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
#### Export as Raw Buffer
|
|
270
|
+
```js
|
|
271
|
+
const rawAudio = tts.toRaw(); // Alias for toBase64()
|
|
272
|
+
const buffer = tts.toBuffer(); // Get as Buffer object
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
#### Export to File
|
|
276
|
+
```js
|
|
277
|
+
const filePath = await tts.toFile("output_audio");
|
|
278
|
+
console.log(`Audio saved to: ${filePath}`);
|
|
279
|
+
// Creates: output_audio.mp3
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Word Boundaries Metadata
|
|
283
|
+
|
|
284
|
+
```php
|
|
285
|
+
// Get word boundaries with timestamps
|
|
286
|
+
$boundaries = $tts->getWordBoundaries();
|
|
287
|
+
|
|
288
|
+
// Save metadata to file
|
|
289
|
+
$tts->saveMetadata('metadata.json');
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
## Examples
|
|
294
|
+
|
|
295
|
+
### Complete Example with Voice Selection
|
|
296
|
+
```js
|
|
297
|
+
import { EdgeTTS } from '@andresaya/edge-tts';
|
|
298
|
+
|
|
299
|
+
async function textToSpeechExample() {
|
|
300
|
+
const tts = new EdgeTTS();
|
|
301
|
+
|
|
302
|
+
// Get available English voices
|
|
303
|
+
const englishVoices = await tts.getVoicesByLanguage('en-US');
|
|
304
|
+
console.log(`Available English voices: ${englishVoices.length}`);
|
|
305
|
+
|
|
306
|
+
// Use the first available voice
|
|
307
|
+
const voice = englishVoices[0];
|
|
308
|
+
console.log(`Using voice: ${voice.FriendlyName}`);
|
|
309
|
+
|
|
310
|
+
// Synthesize with custom options
|
|
311
|
+
await tts.synthesize(
|
|
312
|
+
"This is a test of the Edge TTS system with custom voice parameters.",
|
|
313
|
+
voice.ShortName,
|
|
314
|
+
{
|
|
315
|
+
pitch: '+10Hz',
|
|
316
|
+
rate: '-10%',
|
|
317
|
+
volume: '90%'
|
|
318
|
+
}
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
// Get audio information
|
|
322
|
+
const info = tts.getAudioInfo();
|
|
323
|
+
console.log(`Generated audio: ${info.size} bytes, ${info.estimatedDuration.toFixed(2)}s`);
|
|
324
|
+
|
|
325
|
+
// Save to file
|
|
326
|
+
const outputPath = await tts.toFile('./output/speech');
|
|
327
|
+
console.log(`Audio saved to: ${outputPath}`);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
textToSpeechExample().catch(console.error);
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Streaming Example
|
|
334
|
+
```js
|
|
335
|
+
import { EdgeTTS } from '@andresaya/edge-tts';
|
|
336
|
+
import { createWriteStream } from 'fs';
|
|
337
|
+
|
|
338
|
+
async function streamingExample() {
|
|
339
|
+
const tts = new EdgeTTS();
|
|
340
|
+
const writeStream = createWriteStream('streaming_output.mp3');
|
|
341
|
+
|
|
342
|
+
const longText = "This is a very long text that will be streamed...";
|
|
343
|
+
|
|
344
|
+
for await (const chunk of tts.synthesizeStream(longText, 'en-US-AriaNeural')) {
|
|
345
|
+
writeStream.write(chunk);
|
|
346
|
+
console.log(`Streamed ${chunk.length} bytes`);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
writeStream.end();
|
|
350
|
+
console.log('Streaming completed!');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
streamingExample().catch(console.error);
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Voice Exploration Example
|
|
357
|
+
```js
|
|
358
|
+
import { EdgeTTS } from '@andresaya/edge-tts';
|
|
359
|
+
|
|
360
|
+
async function exploreVoices() {
|
|
361
|
+
const tts = new EdgeTTS();
|
|
362
|
+
|
|
363
|
+
// Get all voices
|
|
364
|
+
const allVoices = await tts.getVoices();
|
|
365
|
+
console.log(`Total voices available: ${allVoices.length}`);
|
|
366
|
+
|
|
367
|
+
// Group by language
|
|
368
|
+
const languages = [...new Set(allVoices.map(v => v.Locale.split('-')[0]))];
|
|
369
|
+
console.log(`Languages available: ${languages.join(', ')}`);
|
|
370
|
+
|
|
371
|
+
// Get Spanish voices
|
|
372
|
+
const spanishVoices = await tts.getVoicesByLanguage('es');
|
|
373
|
+
console.log(`Spanish voices: ${spanishVoices.length}`);
|
|
374
|
+
|
|
375
|
+
// Get female voices
|
|
376
|
+
const femaleVoices = await tts.getVoicesByGender('Female');
|
|
377
|
+
console.log(`Female voices: ${femaleVoices.length}`);
|
|
378
|
+
|
|
379
|
+
// Test different voices
|
|
380
|
+
const testText = "Hola, este es un ejemplo de síntesis de voz.";
|
|
381
|
+
|
|
382
|
+
for (const voice of spanishVoices.slice(0, 3)) {
|
|
383
|
+
console.log(`Testing voice: ${voice.FriendlyName}`);
|
|
384
|
+
|
|
385
|
+
await tts.synthesize(testText, voice.ShortName);
|
|
386
|
+
const filePath = await tts.toFile(`./voices/${voice.ShortName}`);
|
|
387
|
+
|
|
388
|
+
console.log(`Saved: ${filePath}`);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
exploreVoices().catch(console.error);
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## Browser Support
|
|
396
|
+
|
|
397
|
+
This library can be used directly in web browsers via CDN or ES modules.
|
|
398
|
+
|
|
399
|
+
**⚠️ Important:** In the browser, synthesis only works in **Microsoft Edge**. The speech service refuses connections whose user agent is not Edge, and a web page cannot change the user agent its browser sends. Chrome, Firefox and Safari get a 403 when synthesizing. The Node.js version is not affected.
|
|
400
|
+
|
|
401
|
+
### CDN Usage (UMD)
|
|
402
|
+
|
|
403
|
+
```html
|
|
404
|
+
<!-- Load from CDN -->
|
|
405
|
+
<script src="https://unpkg.com/@andresaya/edge-tts@latest/dist/browser/edge-tts.umd.min.js"></script>
|
|
406
|
+
|
|
407
|
+
<script>
|
|
408
|
+
const tts = new EdgeTTS();
|
|
409
|
+
|
|
410
|
+
// Get available voices
|
|
411
|
+
tts.getVoices().then(voices => {
|
|
412
|
+
console.log('Available voices:', voices.length);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
// Synthesize speech
|
|
416
|
+
async function speak() {
|
|
417
|
+
await tts.synthesize("Hello from the browser!", 'en-US-AriaNeural');
|
|
418
|
+
const audioData = tts.getAudioData();
|
|
419
|
+
|
|
420
|
+
// Play audio
|
|
421
|
+
const audioBlob = new Blob([audioData], { type: 'audio/mp3' });
|
|
422
|
+
const audioUrl = URL.createObjectURL(audioBlob);
|
|
423
|
+
const audio = new Audio(audioUrl);
|
|
424
|
+
audio.play();
|
|
425
|
+
}
|
|
426
|
+
</script>
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### ES Module Import
|
|
430
|
+
|
|
431
|
+
```html
|
|
432
|
+
<script type="module">
|
|
433
|
+
import { EdgeTTS } from 'https://unpkg.com/@andresaya/edge-tts@latest/dist/browser/edge-tts.esm.min.js';
|
|
434
|
+
|
|
435
|
+
const tts = new EdgeTTS();
|
|
436
|
+
|
|
437
|
+
// Use the library
|
|
438
|
+
const voices = await tts.getVoices();
|
|
439
|
+
console.log(voices);
|
|
440
|
+
</script>
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Streaming Support in Browser
|
|
444
|
+
|
|
445
|
+
```html
|
|
446
|
+
<script type="module">
|
|
447
|
+
import { EdgeTTS } from 'https://unpkg.com/@andresaya/edge-tts@latest/dist/browser/edge-tts.esm.min.js';
|
|
448
|
+
|
|
449
|
+
const tts = new EdgeTTS();
|
|
450
|
+
const chunks = [];
|
|
451
|
+
|
|
452
|
+
// Stream audio chunks in real-time
|
|
453
|
+
for await (const chunk of tts.synthesizeStream("Long text to stream...", 'en-US-AriaNeural')) {
|
|
454
|
+
chunks.push(chunk);
|
|
455
|
+
console.log(`Received chunk: ${chunk.length} bytes`);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Combine and play all chunks
|
|
459
|
+
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
|
|
460
|
+
const audioData = new Uint8Array(totalLength);
|
|
461
|
+
let offset = 0;
|
|
462
|
+
for (const chunk of chunks) {
|
|
463
|
+
audioData.set(chunk, offset);
|
|
464
|
+
offset += chunk.length;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
const blob = new Blob([audioData], { type: 'audio/mp3' });
|
|
468
|
+
const audio = new Audio(URL.createObjectURL(blob));
|
|
469
|
+
audio.play();
|
|
470
|
+
</script>
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### Complete Browser Example
|
|
474
|
+
|
|
475
|
+
For a full working example with voice selection and synthesis, see [`examples/browser-standalone.html`](examples/browser-standalone.html).
|
|
476
|
+
|
|
477
|
+
## Voice Options
|
|
478
|
+
|
|
479
|
+
### Synthesis Parameters
|
|
480
|
+
|
|
481
|
+
| Parameter | Type | Range | Description |
|
|
482
|
+
|-----------|------|-------|-------------|
|
|
483
|
+
| `pitch` | `string \| number` | `-100Hz` to `+100Hz` | Voice pitch adjustment |
|
|
484
|
+
| `rate` | `string \| number` | `-100%` to `+200%` | Speech rate adjustment |
|
|
485
|
+
| `volume` | `string \| number` | `-100%` to `+100%` | Volume adjustment |
|
|
486
|
+
|
|
487
|
+
### Parameter Examples
|
|
488
|
+
```js
|
|
489
|
+
|
|
490
|
+
// Using numbers (recommended)
|
|
491
|
+
{ pitch: 20, rate: -10, volume: 90 }
|
|
492
|
+
|
|
493
|
+
// Using strings
|
|
494
|
+
{ pitch: '+20Hz', rate: '-10%', volume: '90%' }
|
|
495
|
+
|
|
496
|
+
// Mixed usage
|
|
497
|
+
{ pitch: 15, rate: '25%', volume: 85 }
|
|
498
|
+
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
## Error Handling
|
|
502
|
+
|
|
503
|
+
```js
|
|
504
|
+
import { EdgeTTS } from '@andresaya/edge-tts';
|
|
505
|
+
|
|
506
|
+
async function handleErrors() {
|
|
507
|
+
const tts = new EdgeTTS();
|
|
508
|
+
|
|
509
|
+
try {
|
|
510
|
+
await tts.synthesize("Test text", 'invalid-voice-name');
|
|
511
|
+
} catch (error) {
|
|
512
|
+
console.error('Synthesis failed:', error.message);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
try {
|
|
516
|
+
// This will throw an error - no audio data
|
|
517
|
+
const duration = tts.getDuration();
|
|
518
|
+
} catch (error) {
|
|
519
|
+
console.error('No audio data available:', error.message);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
try {
|
|
523
|
+
// Invalid volume range
|
|
524
|
+
await tts.synthesize("Test", 'en-US-AriaNeural', { volume: -150 });
|
|
525
|
+
} catch (error) {
|
|
526
|
+
console.error('Invalid parameter:', error.message);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
## PHP Version
|
|
532
|
+
If you want to use Edge TTS with PHP, you can check out the PHP version of this package: [Edge TTS PHP](https://github.com/andresayac/edge-tts-php)
|
|
533
|
+
|
|
534
|
+
## License
|
|
535
|
+
This project is licensed under the GNU General Public License v3 (GPLv3).
|
|
536
|
+
|
|
537
|
+
## Acknowledgments
|
|
538
|
+
|
|
539
|
+
We would like to extend our gratitude to the developers and contributors of the following projects for their inspiration and groundwork:
|
|
540
|
+
|
|
541
|
+
* https://github.com/rany2/edge-tts/tree/master/examples
|
|
542
|
+
* https://github.com/rany2/edge-tts/blob/master/src/edge_tts/util.py
|
|
543
|
+
* https://github.com/hasscc/hass-edge-tts/blob/main/custom_components/edge_tts/tts.py
|