@andresaya/edge-tts 1.2.6 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,13 +6,16 @@
6
6
 
7
7
  - **Text-to-Speech**: Convert text into natural-sounding speech using Microsoft Edge's TTS capabilities.
8
8
  - **Multiple Voices**: Access a variety of voices to suit your project's needs.
9
+ - **Voice Filtering**: Filter voices by language and gender for better selection.
10
+ - **Audio Information**: Get detailed information about generated audio (size, duration, format).
9
11
  - **Audio Export Options**: Export synthesized audio in different formats (raw, base64, or directly to a file).
12
+ - **Streaming Support**: Stream audio data in real-time for better performance.
10
13
  - **Command-Line Interface**: Use a simple CLI for easy access to functionality.
11
14
  - **Easy Integration**: Modular structure allows for easy inclusion in existing projects.
12
15
 
13
16
  ## Installation
14
17
 
15
- You can install Edge TTS via npm. Run the following command in your terminal:
18
+ You can install Edge TTS via npm or bun:
16
19
 
17
20
  ```bash
18
21
  bun add @andresaya/edge-tts
@@ -21,63 +24,288 @@ bun add @andresaya/edge-tts
21
24
  npm install @andresaya/edge-tts
22
25
  ```
23
26
 
24
-
25
27
  ## Usage
26
- Command-Line Interface
27
28
 
28
- You can install Edge TTS via npm. bun Run the following command in your terminal:
29
+ ### Command-Line Interface
30
+
31
+ Install globally to use the CLI:
29
32
 
30
33
  ```bash
31
34
  npm install -g @andresaya/edge-tts
32
35
  ```
33
36
 
34
- To synthesize speech from text, use the following command:
37
+ To synthesize speech from text:
35
38
  ```bash
36
39
  edge-tts synthesize -t "Hello, world!" -o hello_world_audio
37
40
  ```
38
41
 
39
- To list available voices, run:
40
-
42
+ To list available voices:
41
43
  ```bash
42
44
  edge-tts voice-list
43
45
  ```
44
46
 
45
- Integration into Your Project
46
- To use Edge TTS in your Bun project, you can import it like this:
47
+ ### Integration into Your Project
47
48
 
48
49
  ```js
49
50
  import { EdgeTTS } from '@andresaya/edge-tts';
50
51
 
51
52
  // Initialize the EdgeTTS service
52
53
  const tts = new EdgeTTS();
54
+ ```
55
+
56
+ ## API Reference
53
57
 
54
- // Get voices
55
- const voices = await tts.getVoices();
56
- console.log(voices); // Display available voices
58
+ ### Voice Management
59
+
60
+ #### Get All Voices
61
+ ```js
62
+ const voices = await tts.getVoices();
63
+ console.log(`Found ${voices.length} voices`);
64
+ ```
65
+
66
+ #### Filter Voices by Language
67
+ ```js
68
+ // Get all English voices
69
+ const englishVoices = await tts.getVoicesByLanguage('en');
70
+
71
+ // Get specific locale voices
72
+ const usEnglishVoices = await tts.getVoicesByLanguage('en-US');
73
+ ```
74
+
75
+ #### Filter Voices by Gender
76
+ ```js
77
+ // Get all female voices
78
+ const femaleVoices = await tts.getVoicesByGender('Female');
79
+
80
+ // Get all male voices
81
+ const maleVoices = await tts.getVoicesByGender('Male');
82
+ ```
83
+
84
+ ### Text Synthesis
85
+
86
+ #### Basic Synthesis
87
+ ```js
88
+ // Simple synthesis with default voice
89
+ await tts.synthesize("Hello, world!");
57
90
 
58
- // Synthesize text with options for voice, rate, volume, and pitch
91
+ // Synthesis with specific voice
92
+ await tts.synthesize("Hello, world!", 'en-US-AriaNeural');
93
+ ```
94
+
95
+ #### Advanced Synthesis with Options
96
+ ```js
59
97
  await tts.synthesize("Hello, world!", 'en-US-AriaNeural', {
60
- rate: '0%', // Speech rate (range: -100% to 100%)
61
- volume: '0%', // Speech volume (range: -100% to 100%)
62
- pitch: '0Hz' // Voice pitch (range: -100Hz to 100Hz)
98
+ rate: '50%', // Speech rate: -100% to +200% (or number)
99
+ volume: '90%', // Speech volume: -100% to +100% (or number)
100
+ pitch: '+20Hz' // Voice pitch: -100Hz to +100Hz (or number)
63
101
  });
102
+ ```
64
103
 
65
- // Export synthesized audio in different formats
66
- tts.toBase64(); // Get audio as base64
67
- await tts.toFile("output_audio"); // Save audio to file
68
- await tts.toRaw(); // Get raw audio buffer
104
+ #### Streaming Synthesis
105
+ ```js
106
+ // Stream audio data in real-time
107
+ for await (const chunk of tts.synthesizeStream("Long text to stream...", 'en-US-AriaNeural')) {
108
+ // Process each audio chunk as it arrives
109
+ console.log(`Received chunk: ${chunk.length} bytes`);
110
+ }
69
111
  ```
70
112
 
71
- ## Export Options
72
- After synthesizing speech, you can export the audio in various formats:
113
+ ### Audio Information
73
114
 
74
- - `toBase64`: Returns the audio as a Base64 string.
75
- - `toFile`: Saves the audio to a specified file (e.g., "output.wav").
76
- - `toRaw`: Returns the raw audio stream.
115
+ #### Get Audio Details
116
+ ```js
117
+ await tts.synthesize("Hello, world!");
77
118
 
78
- ## PHP Version
79
- 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)
119
+ const audioInfo = tts.getAudioInfo();
120
+ console.log(`Size: ${audioInfo.size} bytes`);
121
+ console.log(`Format: ${audioInfo.format}`);
122
+ console.log(`Duration: ${audioInfo.estimatedDuration} seconds`);
123
+ ```
124
+
125
+ #### Get Duration Only
126
+ ```js
127
+ const duration = tts.getDuration();
128
+ console.log(`Audio duration: ${duration} seconds`);
129
+ ```
130
+
131
+ ### Export Options
132
+
133
+ #### Export as Base64
134
+ ```js
135
+ await tts.synthesize("Hello, world!");
136
+ const base64Audio = tts.toBase64();
137
+ console.log(`Base64 length: ${base64Audio.length}`);
138
+ ```
139
+
140
+ #### Export as Raw Buffer
141
+ ```js
142
+ const rawAudio = tts.toRaw(); // Alias for toBase64()
143
+ const buffer = tts.toBuffer(); // Get as Buffer object
144
+ ```
80
145
 
146
+ #### Export to File
147
+ ```js
148
+ const filePath = await tts.toFile("output_audio");
149
+ console.log(`Audio saved to: ${filePath}`);
150
+ // Creates: output_audio.mp3
151
+ ```
152
+
153
+ ## Examples
154
+
155
+ ### Complete Example with Voice Selection
156
+ ```js
157
+ import { EdgeTTS } from '@andresaya/edge-tts';
158
+
159
+ async function textToSpeechExample() {
160
+ const tts = new EdgeTTS();
161
+
162
+ // Get available English voices
163
+ const englishVoices = await tts.getVoicesByLanguage('en-US');
164
+ console.log(`Available English voices: ${englishVoices.length}`);
165
+
166
+ // Use the first available voice
167
+ const voice = englishVoices[0];
168
+ console.log(`Using voice: ${voice.FriendlyName}`);
169
+
170
+ // Synthesize with custom options
171
+ await tts.synthesize(
172
+ "This is a test of the Edge TTS system with custom voice parameters.",
173
+ voice.ShortName,
174
+ {
175
+ pitch: '+10Hz',
176
+ rate: '-10%',
177
+ volume: '90%'
178
+ }
179
+ );
180
+
181
+ // Get audio information
182
+ const info = tts.getAudioInfo();
183
+ console.log(`Generated audio: ${info.size} bytes, ${info.estimatedDuration.toFixed(2)}s`);
184
+
185
+ // Save to file
186
+ const outputPath = await tts.toFile('./output/speech');
187
+ console.log(`Audio saved to: ${outputPath}`);
188
+ }
189
+
190
+ textToSpeechExample().catch(console.error);
191
+ ```
192
+
193
+ ### Streaming Example
194
+ ```js
195
+ import { EdgeTTS } from '@andresaya/edge-tts';
196
+ import { createWriteStream } from 'fs';
197
+
198
+ async function streamingExample() {
199
+ const tts = new EdgeTTS();
200
+ const writeStream = createWriteStream('streaming_output.mp3');
201
+
202
+ const longText = "This is a very long text that will be streamed...";
203
+
204
+ for await (const chunk of tts.synthesizeStream(longText, 'en-US-AriaNeural')) {
205
+ writeStream.write(chunk);
206
+ console.log(`Streamed ${chunk.length} bytes`);
207
+ }
208
+
209
+ writeStream.end();
210
+ console.log('Streaming completed!');
211
+ }
212
+
213
+ streamingExample().catch(console.error);
214
+ ```
215
+
216
+ ### Voice Exploration Example
217
+ ```js
218
+ import { EdgeTTS } from '@andresaya/edge-tts';
219
+
220
+ async function exploreVoices() {
221
+ const tts = new EdgeTTS();
222
+
223
+ // Get all voices
224
+ const allVoices = await tts.getVoices();
225
+ console.log(`Total voices available: ${allVoices.length}`);
226
+
227
+ // Group by language
228
+ const languages = [...new Set(allVoices.map(v => v.Locale.split('-')[0]))];
229
+ console.log(`Languages available: ${languages.join(', ')}`);
230
+
231
+ // Get Spanish voices
232
+ const spanishVoices = await tts.getVoicesByLanguage('es');
233
+ console.log(`Spanish voices: ${spanishVoices.length}`);
234
+
235
+ // Get female voices
236
+ const femaleVoices = await tts.getVoicesByGender('Female');
237
+ console.log(`Female voices: ${femaleVoices.length}`);
238
+
239
+ // Test different voices
240
+ const testText = "Hola, este es un ejemplo de síntesis de voz.";
241
+
242
+ for (const voice of spanishVoices.slice(0, 3)) {
243
+ console.log(`Testing voice: ${voice.FriendlyName}`);
244
+
245
+ await tts.synthesize(testText, voice.ShortName);
246
+ const filePath = await tts.toFile(`./voices/${voice.ShortName}`);
247
+
248
+ console.log(`Saved: ${filePath}`);
249
+ }
250
+ }
251
+
252
+ exploreVoices().catch(console.error);
253
+ ```
254
+
255
+ ## Voice Options
256
+
257
+ ### Synthesis Parameters
258
+
259
+ | Parameter | Type | Range | Description |
260
+ |-----------|------|-------|-------------|
261
+ | `pitch` | `string \| number` | `-100Hz` to `+100Hz` | Voice pitch adjustment |
262
+ | `rate` | `string \| number` | `-100%` to `+200%` | Speech rate adjustment |
263
+ | `volume` | `string \| number` | `-100%` to `+100%` | Volume adjustment |
264
+
265
+ ### Parameter Examples
266
+ ```js
267
+ // Using numbers (recommended)
268
+ { pitch: 20, rate: -10, volume: 90 }
269
+
270
+ // Using strings
271
+ { pitch: '+20Hz', rate: '-10%', volume: '90%' }
272
+
273
+ // Mixed usage
274
+ { pitch: 15, rate: '25%', volume: 85 }
275
+ ```
276
+
277
+ ## Error Handling
278
+
279
+ ```js
280
+ import { EdgeTTS } from '@andresaya/edge-tts';
281
+
282
+ async function handleErrors() {
283
+ const tts = new EdgeTTS();
284
+
285
+ try {
286
+ await tts.synthesize("Test text", 'invalid-voice-name');
287
+ } catch (error) {
288
+ console.error('Synthesis failed:', error.message);
289
+ }
290
+
291
+ try {
292
+ // This will throw an error - no audio data
293
+ const duration = tts.getDuration();
294
+ } catch (error) {
295
+ console.error('No audio data available:', error.message);
296
+ }
297
+
298
+ try {
299
+ // Invalid volume range
300
+ await tts.synthesize("Test", 'en-US-AriaNeural', { volume: -150 });
301
+ } catch (error) {
302
+ console.error('Invalid parameter:', error.message);
303
+ }
304
+ }
305
+ ```
306
+
307
+ ## PHP Version
308
+ 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)
81
309
 
82
310
  ## License
83
311
  This project is licensed under the GNU General Public License v3 (GPLv3).
@@ -88,4 +316,4 @@ We would like to extend our gratitude to the developers and contributors of the
88
316
 
89
317
  * https://github.com/rany2/edge-tts/tree/master/examples
90
318
  * https://github.com/rany2/edge-tts/blob/master/src/edge_tts/util.py
91
- * https://github.com/hasscc/hass-edge-tts/blob/main/custom_components/edge_tts/tts.py
319
+ * https://github.com/hasscc/hass-edge-tts/blob/main/custom_components/edge_tts/tts.py
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import { SynthesizeCommand } from '../commands/SynthesizeCommand';
3
- import { VoiceListCommand } from '../commands/VoiceListCommand';
4
- import { Command } from 'commander';
5
- const program = new Command();
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const SynthesizeCommand_1 = require("../commands/SynthesizeCommand");
5
+ const VoiceListCommand_1 = require("../commands/VoiceListCommand");
6
+ const commander_1 = require("commander");
7
+ const program = new commander_1.Command();
6
8
  program
7
- .version('1.2.6')
8
- .addCommand(SynthesizeCommand)
9
- .addCommand(VoiceListCommand);
9
+ .version('1.2.7')
10
+ .addCommand(SynthesizeCommand_1.SynthesizeCommand)
11
+ .addCommand(VoiceListCommand_1.VoiceListCommand);
10
12
  try {
11
13
  program.parse();
12
14
  }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const SynthesizeCommand: Command;
@@ -1,6 +1,9 @@
1
- import { Command } from 'commander';
2
- import { EdgeTTS } from '../services/EdgeTTS';
3
- export const SynthesizeCommand = new Command('synthesize')
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SynthesizeCommand = void 0;
4
+ const commander_1 = require("commander");
5
+ const EdgeTTS_1 = require("../services/EdgeTTS");
6
+ exports.SynthesizeCommand = new commander_1.Command('synthesize')
4
7
  .description('Edge TTS: synthesize text to audio')
5
8
  .option('-t, --text <text>', 'Text to convert to audio')
6
9
  .option('-v, --voice [voice]', 'Voice to use for the audio synthesis', 'en-US-AriaNeural')
@@ -14,7 +17,7 @@ export const SynthesizeCommand = new Command('synthesize')
14
17
  console.error('Text is required');
15
18
  process.exit(1);
16
19
  }
17
- const tts = new EdgeTTS();
20
+ const tts = new EdgeTTS_1.EdgeTTS();
18
21
  await tts.synthesize(text, voice, { pitch, rate, volume });
19
22
  await tts.toFile(`${output}`);
20
23
  console.log(`Audio file generated: ${output}.mp3`);
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const VoiceListCommand: Command;
@@ -1,9 +1,12 @@
1
- import { Command } from 'commander';
2
- import { EdgeTTS } from '../services/EdgeTTS';
3
- export const VoiceListCommand = new Command('voice-list')
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VoiceListCommand = void 0;
4
+ const commander_1 = require("commander");
5
+ const EdgeTTS_1 = require("../services/EdgeTTS");
6
+ exports.VoiceListCommand = new commander_1.Command('voice-list')
4
7
  .description('Get the list of available voices')
5
8
  .action(async () => {
6
- const tts = new EdgeTTS();
9
+ const tts = new EdgeTTS_1.EdgeTTS();
7
10
  const voices = await tts.getVoices();
8
11
  console.log('Lista de voces disponibles:');
9
12
  voices.forEach((voice) => {
@@ -0,0 +1,5 @@
1
+ export declare const Constants: {
2
+ TRUSTED_CLIENT_TOKEN: string;
3
+ WSS_URL: string;
4
+ VOICES_URL: string;
5
+ };
@@ -1,4 +1,7 @@
1
- export const Constants = {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Constants = void 0;
4
+ exports.Constants = {
2
5
  TRUSTED_CLIENT_TOKEN: '6A5AA1D4EAFF4E9FB37E23D68491D6F4',
3
6
  WSS_URL: 'wss://speech.platform.bing.com/consumer/speech/synthesize/readaloud/edge/v1',
4
7
  VOICES_URL: 'https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list',
@@ -0,0 +1 @@
1
+ export { EdgeTTS, type Voice, type SynthesisOptions } from './services/EdgeTTS';
package/dist/index.js CHANGED
@@ -1 +1,5 @@
1
- export { EdgeTTS } from './services/EdgeTTS';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EdgeTTS = void 0;
4
+ var EdgeTTS_1 = require("./services/EdgeTTS");
5
+ Object.defineProperty(exports, "EdgeTTS", { enumerable: true, get: function () { return EdgeTTS_1.EdgeTTS; } });
@@ -0,0 +1,31 @@
1
+ import { Buffer } from 'buffer';
2
+ export interface Voice {
3
+ Name: string;
4
+ ShortName: string;
5
+ Gender: string;
6
+ Locale: string;
7
+ FriendlyName: string;
8
+ }
9
+ export interface SynthesisOptions {
10
+ pitch?: string | number;
11
+ rate?: string | number;
12
+ volume?: string | number;
13
+ }
14
+ export declare class EdgeTTS {
15
+ private audio_stream;
16
+ private audio_format;
17
+ private ws;
18
+ getVoices(): Promise<Voice[]>;
19
+ private generateUUID;
20
+ private validatePitch;
21
+ private validateRate;
22
+ private validateVolume;
23
+ synthesize(text: string, voice?: string, options?: SynthesisOptions): Promise<void>;
24
+ private getSSML;
25
+ private buildTTSConfigMessage;
26
+ private processAudioData;
27
+ toFile(outputPath: string): Promise<string>;
28
+ toRaw(): string;
29
+ toBase64(): string;
30
+ toBuffer(): Buffer;
31
+ }
@@ -1,28 +1,34 @@
1
- import WebSocket, {} from 'ws';
2
- import { Constants } from '../config/constants';
3
- import { writeFile } from 'fs/promises';
4
- import { Buffer } from 'buffer';
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.EdgeTTS = void 0;
7
+ const ws_1 = __importDefault(require("ws"));
8
+ const constants_1 = require("../config/constants");
9
+ const promises_1 = require("fs/promises");
10
+ const buffer_1 = require("buffer");
5
11
  function ensureBuffer(data) {
6
- if (Buffer.isBuffer(data)) {
12
+ if (buffer_1.Buffer.isBuffer(data)) {
7
13
  return data;
8
14
  }
9
15
  if (data instanceof ArrayBuffer) {
10
- return Buffer.from(data);
16
+ return buffer_1.Buffer.from(data);
11
17
  }
12
18
  if (Array.isArray(data)) {
13
- return Buffer.concat(data);
19
+ return buffer_1.Buffer.concat(data);
14
20
  }
15
21
  if (typeof data === 'string') {
16
- return Buffer.from(data, 'utf-8');
22
+ return buffer_1.Buffer.from(data, 'utf-8');
17
23
  }
18
24
  throw new Error(`Unsupported RawData type: ${typeof data}`);
19
25
  }
20
- export class EdgeTTS {
26
+ class EdgeTTS {
21
27
  audio_stream = [];
22
28
  audio_format = 'mp3';
23
29
  ws;
24
30
  async getVoices() {
25
- const response = await fetch(`${Constants.VOICES_URL}?trustedclienttoken=${Constants.TRUSTED_CLIENT_TOKEN}`);
31
+ const response = await fetch(`${constants_1.Constants.VOICES_URL}?trustedclienttoken=${constants_1.Constants.TRUSTED_CLIENT_TOKEN}`);
26
32
  const data = await response.json();
27
33
  return data.map((voice) => {
28
34
  delete voice.VoiceTag;
@@ -81,10 +87,10 @@ export class EdgeTTS {
81
87
  return new Promise((resolve, reject) => {
82
88
  this.audio_stream = [];
83
89
  const req_id = this.generateUUID();
84
- this.ws = new WebSocket(`${Constants.WSS_URL}?trustedclienttoken=${Constants.TRUSTED_CLIENT_TOKEN}&ConnectionId=${req_id}`);
90
+ this.ws = new ws_1.default(`${constants_1.Constants.WSS_URL}?trustedclienttoken=${constants_1.Constants.TRUSTED_CLIENT_TOKEN}&ConnectionId=${req_id}`);
85
91
  const SSML_text = this.getSSML(text, voice, options);
86
92
  const timeout = setTimeout(() => {
87
- if (this.ws && this.ws.readyState === WebSocket.OPEN) {
93
+ if (this.ws && this.ws.readyState === ws_1.default.OPEN) {
88
94
  this.ws.close();
89
95
  }
90
96
  reject(new Error("Synthesis timeout"));
@@ -100,7 +106,7 @@ export class EdgeTTS {
100
106
  });
101
107
  this.ws.on('error', (err) => {
102
108
  clearTimeout(timeout);
103
- if (this.ws && this.ws.readyState === WebSocket.OPEN) {
109
+ if (this.ws && this.ws.readyState === ws_1.default.OPEN) {
104
110
  this.ws.close();
105
111
  }
106
112
  reject(err);
@@ -126,7 +132,7 @@ export class EdgeTTS {
126
132
  }
127
133
  processAudioData(data) {
128
134
  const buffer = ensureBuffer(data);
129
- const needle = Buffer.from("Path:audio\r\n");
135
+ const needle = buffer_1.Buffer.from("Path:audio\r\n");
130
136
  const audioStartIndex = buffer.indexOf(new Uint8Array(needle));
131
137
  if (audioStartIndex !== -1) {
132
138
  const audioChunk = buffer.subarray(audioStartIndex + needle.length);
@@ -139,7 +145,7 @@ export class EdgeTTS {
139
145
  async toFile(outputPath) {
140
146
  const audioBuffer = this.toBuffer();
141
147
  const finalPath = `${outputPath}.${this.audio_format}`;
142
- await writeFile(finalPath, new Uint8Array(audioBuffer));
148
+ await (0, promises_1.writeFile)(finalPath, new Uint8Array(audioBuffer));
143
149
  return finalPath;
144
150
  }
145
151
  toRaw() {
@@ -152,6 +158,7 @@ export class EdgeTTS {
152
158
  if (this.audio_stream.length === 0) {
153
159
  throw new Error("No audio data available. Did you run synthesize() first?");
154
160
  }
155
- return Buffer.concat(this.audio_stream);
161
+ return buffer_1.Buffer.concat(this.audio_stream);
156
162
  }
157
163
  }
164
+ exports.EdgeTTS = EdgeTTS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andresaya/edge-tts",
3
- "version": "1.2.6",
3
+ "version": "1.3.0",
4
4
  "description": "Edge TTS is a package that allows access to the online text-to-speech service used by Microsoft Edge without the need for Microsoft Edge, Windows, or an API key.",
5
5
  "main": "dist/index.js",
6
6
  "keywords": [