@andresaya/edge-tts 1.3.1 → 1.3.2

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
@@ -1,4 +1,5 @@
1
1
  # Edge TTS
2
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/andresayac/edge-tts)
2
3
 
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).
4
5
 
@@ -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.3.0')
9
+ .version('1.3.2')
10
10
  .addCommand(SynthesizeCommand_1.SynthesizeCommand)
11
11
  .addCommand(VoiceListCommand_1.VoiceListCommand);
12
12
  try {
@@ -2,4 +2,5 @@ export declare const Constants: {
2
2
  TRUSTED_CLIENT_TOKEN: string;
3
3
  WSS_URL: string;
4
4
  VOICES_URL: string;
5
+ USER_AGENT: string;
5
6
  };
@@ -5,4 +5,5 @@ exports.Constants = {
5
5
  TRUSTED_CLIENT_TOKEN: '6A5AA1D4EAFF4E9FB37E23D68491D6F4',
6
6
  WSS_URL: 'wss://speech.platform.bing.com/consumer/speech/synthesize/readaloud/edge/v1',
7
7
  VOICES_URL: 'https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list',
8
+ USER_AGENT: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0'
8
9
  };
@@ -0,0 +1,81 @@
1
+ export declare const AUDIO_FORMATS_STREAM: {
2
+ readonly 'raw-8khz-8bit-mono-alaw': "audio/basic";
3
+ readonly 'raw-8khz-8bit-mono-mulaw': "audio/basic";
4
+ readonly 'raw-8khz-16bit-mono-pcm': "audio/basic";
5
+ readonly 'raw-16khz-16bit-mono-pcm': "audio/basic";
6
+ readonly 'raw-22050hz-16bit-mono-pcm': "audio/basic";
7
+ readonly 'raw-24khz-16bit-mono-pcm': "audio/basic";
8
+ readonly 'raw-44100hz-16bit-mono-pcm': "audio/basic";
9
+ readonly 'raw-48khz-16bit-mono-pcm': "audio/basic";
10
+ readonly 'raw-16khz-16bit-mono-truesilk': "audio/SILK";
11
+ readonly 'raw-24khz-16bit-mono-truesilk': "audio/SILK";
12
+ readonly 'audio-16khz-32kbitrate-mono-mp3': "audio/mpeg";
13
+ readonly 'audio-16khz-64kbitrate-mono-mp3': "audio/mpeg";
14
+ readonly 'audio-16khz-128kbitrate-mono-mp3': "audio/mpeg";
15
+ readonly 'audio-24khz-48kbitrate-mono-mp3': "audio/mpeg";
16
+ readonly 'audio-24khz-96kbitrate-mono-mp3': "audio/mpeg";
17
+ readonly 'audio-24khz-160kbitrate-mono-mp3': "audio/mpeg";
18
+ readonly 'audio-48khz-96kbitrate-mono-mp3': "audio/mpeg";
19
+ readonly 'audio-48khz-192kbitrate-mono-mp3': "audio/mpeg";
20
+ readonly 'audio-16khz-16bit-32kbps-mono-opus': "audio/opus";
21
+ readonly 'audio-24khz-16bit-24kbps-mono-opus': "audio/opus";
22
+ readonly 'audio-24khz-16bit-48kbps-mono-opus': "audio/opus";
23
+ readonly 'ogg-16khz-16bit-mono-opus': "audio/ogg; codecs=opus; rate=16000";
24
+ readonly 'ogg-24khz-16bit-mono-opus': "audio/ogg; codecs=opus; rate=24000";
25
+ readonly 'ogg-48khz-16bit-mono-opus': "audio/ogg; codecs=opus; rate=48000";
26
+ readonly 'webm-16khz-16bit-mono-opus': "audio/webm; codec=opus";
27
+ readonly 'webm-24khz-16bit-mono-opus': "audio/webm; codec=opus";
28
+ readonly 'webm-24khz-16bit-24kbps-mono-opus': "audio/webm; codec=opus";
29
+ readonly 'amr-wb-16000hz': "audio/amr-wb";
30
+ readonly 'g722-16khz-64kbps': "audio/g722";
31
+ };
32
+ export declare const AUDIO_FORMATS_NON_STREAM: {
33
+ readonly 'riff-8khz-8bit-mono-alaw': "audio/x-wav";
34
+ readonly 'riff-8khz-8bit-mono-mulaw': "audio/x-wav";
35
+ readonly 'riff-8khz-16bit-mono-pcm': "audio/x-wav";
36
+ readonly 'riff-22050hz-16bit-mono-pcm': "audio/x-wav";
37
+ readonly 'riff-24khz-16bit-mono-pcm': "audio/x-wav";
38
+ readonly 'riff-44100hz-16bit-mono-pcm': "audio/x-wav";
39
+ readonly 'riff-48khz-16bit-mono-pcm': "audio/x-wav";
40
+ };
41
+ type AudioOutputFormat = keyof typeof AUDIO_FORMATS_STREAM;
42
+ declare const ALL_AUDIO_FORMATS: {
43
+ 'riff-8khz-8bit-mono-alaw': "audio/x-wav";
44
+ 'riff-8khz-8bit-mono-mulaw': "audio/x-wav";
45
+ 'riff-8khz-16bit-mono-pcm': "audio/x-wav";
46
+ 'riff-22050hz-16bit-mono-pcm': "audio/x-wav";
47
+ 'riff-24khz-16bit-mono-pcm': "audio/x-wav";
48
+ 'riff-44100hz-16bit-mono-pcm': "audio/x-wav";
49
+ 'riff-48khz-16bit-mono-pcm': "audio/x-wav";
50
+ 'raw-8khz-8bit-mono-alaw': "audio/basic";
51
+ 'raw-8khz-8bit-mono-mulaw': "audio/basic";
52
+ 'raw-8khz-16bit-mono-pcm': "audio/basic";
53
+ 'raw-16khz-16bit-mono-pcm': "audio/basic";
54
+ 'raw-22050hz-16bit-mono-pcm': "audio/basic";
55
+ 'raw-24khz-16bit-mono-pcm': "audio/basic";
56
+ 'raw-44100hz-16bit-mono-pcm': "audio/basic";
57
+ 'raw-48khz-16bit-mono-pcm': "audio/basic";
58
+ 'raw-16khz-16bit-mono-truesilk': "audio/SILK";
59
+ 'raw-24khz-16bit-mono-truesilk': "audio/SILK";
60
+ 'audio-16khz-32kbitrate-mono-mp3': "audio/mpeg";
61
+ 'audio-16khz-64kbitrate-mono-mp3': "audio/mpeg";
62
+ 'audio-16khz-128kbitrate-mono-mp3': "audio/mpeg";
63
+ 'audio-24khz-48kbitrate-mono-mp3': "audio/mpeg";
64
+ 'audio-24khz-96kbitrate-mono-mp3': "audio/mpeg";
65
+ 'audio-24khz-160kbitrate-mono-mp3': "audio/mpeg";
66
+ 'audio-48khz-96kbitrate-mono-mp3': "audio/mpeg";
67
+ 'audio-48khz-192kbitrate-mono-mp3': "audio/mpeg";
68
+ 'audio-16khz-16bit-32kbps-mono-opus': "audio/opus";
69
+ 'audio-24khz-16bit-24kbps-mono-opus': "audio/opus";
70
+ 'audio-24khz-16bit-48kbps-mono-opus': "audio/opus";
71
+ 'ogg-16khz-16bit-mono-opus': "audio/ogg; codecs=opus; rate=16000";
72
+ 'ogg-24khz-16bit-mono-opus': "audio/ogg; codecs=opus; rate=24000";
73
+ 'ogg-48khz-16bit-mono-opus': "audio/ogg; codecs=opus; rate=48000";
74
+ 'webm-16khz-16bit-mono-opus': "audio/webm; codec=opus";
75
+ 'webm-24khz-16bit-mono-opus': "audio/webm; codec=opus";
76
+ 'webm-24khz-16bit-24kbps-mono-opus': "audio/webm; codec=opus";
77
+ 'amr-wb-16000hz': "audio/amr-wb";
78
+ 'g722-16khz-64kbps': "audio/g722";
79
+ };
80
+ declare const FORMAT_CONTENT_TYPE: Map<string, "audio/basic" | "audio/SILK" | "audio/mpeg" | "audio/opus" | "audio/ogg; codecs=opus; rate=16000" | "audio/ogg; codecs=opus; rate=24000" | "audio/ogg; codecs=opus; rate=48000" | "audio/webm; codec=opus" | "audio/amr-wb" | "audio/g722" | "audio/x-wav">;
81
+ export { ALL_AUDIO_FORMATS, FORMAT_CONTENT_TYPE, AudioOutputFormat };
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FORMAT_CONTENT_TYPE = exports.ALL_AUDIO_FORMATS = exports.AUDIO_FORMATS_NON_STREAM = exports.AUDIO_FORMATS_STREAM = void 0;
4
+ exports.AUDIO_FORMATS_STREAM = {
5
+ // RAW PCM
6
+ 'raw-8khz-8bit-mono-alaw': 'audio/basic',
7
+ 'raw-8khz-8bit-mono-mulaw': 'audio/basic',
8
+ 'raw-8khz-16bit-mono-pcm': 'audio/basic',
9
+ 'raw-16khz-16bit-mono-pcm': 'audio/basic',
10
+ 'raw-22050hz-16bit-mono-pcm': 'audio/basic',
11
+ 'raw-24khz-16bit-mono-pcm': 'audio/basic',
12
+ 'raw-44100hz-16bit-mono-pcm': 'audio/basic',
13
+ 'raw-48khz-16bit-mono-pcm': 'audio/basic',
14
+ // TRUESILK
15
+ 'raw-16khz-16bit-mono-truesilk': 'audio/SILK',
16
+ 'raw-24khz-16bit-mono-truesilk': 'audio/SILK',
17
+ // MP3
18
+ 'audio-16khz-32kbitrate-mono-mp3': 'audio/mpeg',
19
+ 'audio-16khz-64kbitrate-mono-mp3': 'audio/mpeg',
20
+ 'audio-16khz-128kbitrate-mono-mp3': 'audio/mpeg',
21
+ 'audio-24khz-48kbitrate-mono-mp3': 'audio/mpeg',
22
+ 'audio-24khz-96kbitrate-mono-mp3': 'audio/mpeg',
23
+ 'audio-24khz-160kbitrate-mono-mp3': 'audio/mpeg',
24
+ 'audio-48khz-96kbitrate-mono-mp3': 'audio/mpeg',
25
+ 'audio-48khz-192kbitrate-mono-mp3': 'audio/mpeg',
26
+ // OPUS in container
27
+ 'audio-16khz-16bit-32kbps-mono-opus': 'audio/opus',
28
+ 'audio-24khz-16bit-24kbps-mono-opus': 'audio/opus',
29
+ 'audio-24khz-16bit-48kbps-mono-opus': 'audio/opus',
30
+ // OGG
31
+ 'ogg-16khz-16bit-mono-opus': 'audio/ogg; codecs=opus; rate=16000',
32
+ 'ogg-24khz-16bit-mono-opus': 'audio/ogg; codecs=opus; rate=24000',
33
+ 'ogg-48khz-16bit-mono-opus': 'audio/ogg; codecs=opus; rate=48000',
34
+ // WEBM
35
+ 'webm-16khz-16bit-mono-opus': 'audio/webm; codec=opus',
36
+ 'webm-24khz-16bit-mono-opus': 'audio/webm; codec=opus',
37
+ 'webm-24khz-16bit-24kbps-mono-opus': 'audio/webm; codec=opus',
38
+ 'amr-wb-16000hz': 'audio/amr-wb',
39
+ 'g722-16khz-64kbps': 'audio/g722'
40
+ };
41
+ exports.AUDIO_FORMATS_NON_STREAM = {
42
+ // RIFF (WAV)
43
+ 'riff-8khz-8bit-mono-alaw': 'audio/x-wav',
44
+ 'riff-8khz-8bit-mono-mulaw': 'audio/x-wav',
45
+ 'riff-8khz-16bit-mono-pcm': 'audio/x-wav',
46
+ 'riff-22050hz-16bit-mono-pcm': 'audio/x-wav',
47
+ 'riff-24khz-16bit-mono-pcm': 'audio/x-wav',
48
+ 'riff-44100hz-16bit-mono-pcm': 'audio/x-wav',
49
+ 'riff-48khz-16bit-mono-pcm': 'audio/x-wav',
50
+ };
51
+ const ALL_AUDIO_FORMATS = { ...exports.AUDIO_FORMATS_STREAM, ...exports.AUDIO_FORMATS_NON_STREAM };
52
+ exports.ALL_AUDIO_FORMATS = ALL_AUDIO_FORMATS;
53
+ const FORMAT_CONTENT_TYPE = new Map(Object.entries(ALL_AUDIO_FORMATS));
54
+ exports.FORMAT_CONTENT_TYPE = FORMAT_CONTENT_TYPE;
@@ -27,6 +27,7 @@ export declare class EdgeTTS {
27
27
  private buildTTSConfigMessage;
28
28
  synthesizeStream(text: string, voice?: string, options?: SynthesisOptions): AsyncGenerator<Uint8Array, void, unknown>;
29
29
  private processAudioData;
30
+ private generateSecMsGec;
30
31
  getDuration(): number;
31
32
  getAudioInfo(): {
32
33
  size: number;
@@ -28,7 +28,11 @@ class EdgeTTS {
28
28
  audio_format = 'mp3';
29
29
  ws;
30
30
  async getVoices() {
31
- const response = await fetch(`${constants_1.Constants.VOICES_URL}?trustedclienttoken=${constants_1.Constants.TRUSTED_CLIENT_TOKEN}`);
31
+ const response = await fetch(`${constants_1.Constants.VOICES_URL}?trustedclienttoken=${constants_1.Constants.TRUSTED_CLIENT_TOKEN}`, {
32
+ headers: {
33
+ "User-Agent": constants_1.Constants.USER_AGENT
34
+ },
35
+ });
32
36
  const data = await response.json();
33
37
  return data.map((voice) => {
34
38
  delete voice.VoiceTag;
@@ -92,10 +96,16 @@ class EdgeTTS {
92
96
  return `${volumeValue}%`;
93
97
  }
94
98
  async synthesize(text, voice = 'en-US-AnaNeural', options = {}) {
99
+ const secMsGEC = await this.generateSecMsGec(constants_1.Constants.TRUSTED_CLIENT_TOKEN);
95
100
  return new Promise((resolve, reject) => {
96
101
  this.audio_stream = [];
97
102
  const req_id = this.generateUUID();
98
- this.ws = new ws_1.default(`${constants_1.Constants.WSS_URL}?trustedclienttoken=${constants_1.Constants.TRUSTED_CLIENT_TOKEN}&ConnectionId=${req_id}`);
103
+ const url = `${constants_1.Constants.WSS_URL}?TrustedClientToken=${constants_1.Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=1-130.0.2849.68&ConnectionId=${req_id}`;
104
+ this.ws = new ws_1.default(url, {
105
+ headers: {
106
+ "User-Agent": constants_1.Constants.USER_AGENT
107
+ }
108
+ });
99
109
  const SSML_text = this.getSSML(text, voice, options);
100
110
  const timeout = setTimeout(() => {
101
111
  if (this.ws && this.ws.readyState === ws_1.default.OPEN) {
@@ -141,7 +151,9 @@ class EdgeTTS {
141
151
  async *synthesizeStream(text, voice = 'en-US-AnaNeural', options = {}) {
142
152
  this.audio_stream = [];
143
153
  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}`);
154
+ const secMsGEC = await this.generateSecMsGec(constants_1.Constants.TRUSTED_CLIENT_TOKEN);
155
+ const url = `${constants_1.Constants.WSS_URL}?TrustedClientToken=${constants_1.Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=1-130.0.2849.68&ConnectionId=${req_id}`;
156
+ this.ws = new ws_1.default(url);
145
157
  const SSML_text = this.getSSML(text, voice, options);
146
158
  const queue = [];
147
159
  let done = false;
@@ -221,6 +233,18 @@ class EdgeTTS {
221
233
  this.ws?.close();
222
234
  }
223
235
  }
236
+ async generateSecMsGec(trustedClientToken) {
237
+ const ticks = Math.floor(Date.now() / 1000) + 11644473600;
238
+ const rounded = ticks - (ticks % 300);
239
+ const windowsTicks = rounded * 10000000;
240
+ const encoder = new TextEncoder();
241
+ const data = encoder.encode(`${windowsTicks}${trustedClientToken}`);
242
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
243
+ return Array.from(new Uint8Array(hashBuffer))
244
+ .map(b => b.toString(16).padStart(2, '0'))
245
+ .join('')
246
+ .toUpperCase();
247
+ }
224
248
  getDuration() {
225
249
  if (this.audio_stream.length === 0) {
226
250
  throw new Error("No audio data available");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andresaya/edge-tts",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
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": [