@andresaya/edge-tts 1.3.0 → 1.3.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.
@@ -6,7 +6,7 @@ const VoiceListCommand_1 = require("../commands/VoiceListCommand");
6
6
  const commander_1 = require("commander");
7
7
  const program = new commander_1.Command();
8
8
  program
9
- .version('1.2.7')
9
+ .version('1.3.0')
10
10
  .addCommand(SynthesizeCommand_1.SynthesizeCommand)
11
11
  .addCommand(VoiceListCommand_1.VoiceListCommand);
12
12
  try {
@@ -16,6 +16,8 @@ export declare class EdgeTTS {
16
16
  private audio_format;
17
17
  private ws;
18
18
  getVoices(): Promise<Voice[]>;
19
+ getVoicesByLanguage(locale: string): Promise<Voice[]>;
20
+ getVoicesByGender(gender: 'Male' | 'Female'): Promise<Voice[]>;
19
21
  private generateUUID;
20
22
  private validatePitch;
21
23
  private validateRate;
@@ -23,8 +25,15 @@ export declare class EdgeTTS {
23
25
  synthesize(text: string, voice?: string, options?: SynthesisOptions): Promise<void>;
24
26
  private getSSML;
25
27
  private buildTTSConfigMessage;
28
+ synthesizeStream(text: string, voice?: string, options?: SynthesisOptions): AsyncGenerator<Uint8Array, void, unknown>;
26
29
  private processAudioData;
27
- toFile(outputPath: string): Promise<string>;
30
+ getDuration(): number;
31
+ getAudioInfo(): {
32
+ size: number;
33
+ format: string;
34
+ estimatedDuration: number;
35
+ };
36
+ toFile(outputPath: string, format?: string): Promise<string>;
28
37
  toRaw(): string;
29
38
  toBase64(): string;
30
39
  toBuffer(): Buffer;
@@ -37,6 +37,14 @@ class EdgeTTS {
37
37
  return voice;
38
38
  });
39
39
  }
40
+ async getVoicesByLanguage(locale) {
41
+ const voices = await this.getVoices();
42
+ return voices.filter(voice => voice.Locale.startsWith(locale));
43
+ }
44
+ async getVoicesByGender(gender) {
45
+ const voices = await this.getVoices();
46
+ return voices.filter(voice => voice.Gender === gender);
47
+ }
40
48
  generateUUID() {
41
49
  return 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
42
50
  const r = Math.random() * 16 | 0;
@@ -130,6 +138,77 @@ class EdgeTTS {
130
138
  return `X-Timestamp:${new Date().toISOString()}Z\r\nContent-Type:application/json; charset=utf-8\r\nPath:speech.config\r\n\r\n` +
131
139
  `{"context":{"synthesis":{"audio":{"metadataoptions":{"sentenceBoundaryEnabled":false,"wordBoundaryEnabled":true},"outputFormat":"audio-24khz-48kbitrate-mono-mp3"}}}}`;
132
140
  }
141
+ async *synthesizeStream(text, voice = 'en-US-AnaNeural', options = {}) {
142
+ this.audio_stream = [];
143
+ const req_id = this.generateUUID();
144
+ this.ws = new ws_1.default(`${constants_1.Constants.WSS_URL}?trustedclienttoken=${constants_1.Constants.TRUSTED_CLIENT_TOKEN}&ConnectionId=${req_id}`);
145
+ const SSML_text = this.getSSML(text, voice, options);
146
+ const queue = [];
147
+ let done = false;
148
+ let error = null;
149
+ let notify = null;
150
+ const push = (chunk) => {
151
+ queue.push(chunk);
152
+ if (notify) {
153
+ notify();
154
+ notify = null;
155
+ }
156
+ };
157
+ const timeout = setTimeout(() => {
158
+ if (this.ws && this.ws.readyState === ws_1.default.OPEN) {
159
+ this.ws.close();
160
+ }
161
+ }, 30000);
162
+ this.ws.on('open', () => {
163
+ const message = this.buildTTSConfigMessage();
164
+ this.ws.send(message);
165
+ const speechMessage = `X-RequestId:${req_id}\r\nContent-Type:application/ssml+xml\r\nX-Timestamp:${new Date().toISOString()}Z\r\nPath:ssml\r\n\r\n${SSML_text}`;
166
+ this.ws.send(speechMessage);
167
+ });
168
+ this.ws.on('message', (data) => {
169
+ const buffer = ensureBuffer(data);
170
+ const needle = buffer_1.Buffer.from('Path:audio\r\n');
171
+ const audioStartIndex = buffer.indexOf(new Uint8Array(needle));
172
+ if (audioStartIndex !== -1) {
173
+ const audioChunk = buffer.subarray(audioStartIndex + needle.length);
174
+ const chunk = new Uint8Array(audioChunk);
175
+ this.audio_stream.push(chunk);
176
+ push(chunk);
177
+ }
178
+ if (buffer.toString().includes('Path:turn.end')) {
179
+ this.ws?.close();
180
+ }
181
+ });
182
+ this.ws.on('error', (err) => {
183
+ error = err;
184
+ done = true;
185
+ if (notify) {
186
+ notify();
187
+ notify = null;
188
+ }
189
+ });
190
+ this.ws.on('close', () => {
191
+ clearTimeout(timeout);
192
+ done = true;
193
+ if (notify) {
194
+ notify();
195
+ notify = null;
196
+ }
197
+ });
198
+ while (!done || queue.length > 0) {
199
+ if (queue.length === 0) {
200
+ await new Promise(resolve => (notify = resolve));
201
+ continue;
202
+ }
203
+ const chunk = queue.shift();
204
+ if (chunk) {
205
+ yield chunk;
206
+ }
207
+ }
208
+ if (error) {
209
+ throw error;
210
+ }
211
+ }
133
212
  processAudioData(data) {
134
213
  const buffer = ensureBuffer(data);
135
214
  const needle = buffer_1.Buffer.from("Path:audio\r\n");
@@ -142,9 +221,28 @@ class EdgeTTS {
142
221
  this.ws?.close();
143
222
  }
144
223
  }
145
- async toFile(outputPath) {
224
+ getDuration() {
225
+ if (this.audio_stream.length === 0) {
226
+ throw new Error("No audio data available");
227
+ }
228
+ // Estimate duration based on the size of the audio stream
229
+ const bufferSize = this.toBuffer().length;
230
+ const estimatedDuration = bufferSize / (24000 * 3); // 24000 Hz sample rate, 3 bytes per sample (16-bit stereo)
231
+ return estimatedDuration;
232
+ }
233
+ getAudioInfo() {
234
+ const buffer = this.toBuffer();
235
+ return {
236
+ size: buffer.length,
237
+ format: this.audio_format,
238
+ estimatedDuration: this.getDuration()
239
+ };
240
+ }
241
+ async toFile(outputPath, format = this.audio_format) {
242
+ if (!format || typeof format !== 'string')
243
+ format = this.audio_format;
146
244
  const audioBuffer = this.toBuffer();
147
- const finalPath = `${outputPath}.${this.audio_format}`;
245
+ const finalPath = `${outputPath}.${format}`;
148
246
  await (0, promises_1.writeFile)(finalPath, new Uint8Array(audioBuffer));
149
247
  return finalPath;
150
248
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andresaya/edge-tts",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
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": [