@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 +1 -0
- package/dist/cli/edge-tts.js +1 -1
- package/dist/config/constants.d.ts +1 -0
- package/dist/config/constants.js +1 -0
- package/dist/config/formats.d.ts +81 -0
- package/dist/config/formats.js +54 -0
- package/dist/services/EdgeTTS.d.ts +1 -0
- package/dist/services/EdgeTTS.js +27 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Edge TTS
|
|
2
|
+
[](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
|
|
package/dist/cli/edge-tts.js
CHANGED
|
@@ -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.
|
|
9
|
+
.version('1.3.2')
|
|
10
10
|
.addCommand(SynthesizeCommand_1.SynthesizeCommand)
|
|
11
11
|
.addCommand(VoiceListCommand_1.VoiceListCommand);
|
|
12
12
|
try {
|
package/dist/config/constants.js
CHANGED
|
@@ -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;
|
package/dist/services/EdgeTTS.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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.
|
|
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": [
|