@andresaya/edge-tts 1.8.1 → 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.
@@ -30,11 +30,12 @@ var EdgeTTSModule = (() => {
30
30
  var Constants = {
31
31
  TRUSTED_CLIENT_TOKEN: "6A5AA1D4EAFF4E9FB37E23D68491D6F4",
32
32
  BASE_URL: "https://speech.platform.bing.com/consumer/speech/synthesize/readaloud",
33
- WSS_URL: "wss://speech.platform.bing.com/consumer/speech/synthesize/readaloud/edge/v1",
33
+ // NOTE: token goes as Ocp-Apim-Subscription-Key here; Edge user agents only.
34
+ WSS_URL: "wss://api.msedgeservices.com/tts/cognitiveservices/websocket/v1",
34
35
  VOICES_URL: "https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list",
35
- CHROMIUM_FULL_VERSION: "143.0.3650.75",
36
- CHROMIUM_MAJOR_VERSION: "143",
37
- VERSION_MS_GEC: "1-143.0.3650",
36
+ CHROMIUM_FULL_VERSION: "155.0.0.0",
37
+ CHROMIUM_MAJOR_VERSION: "155",
38
+ VERSION_MS_GEC: "1-155.0.4283.45",
38
39
  token32() {
39
40
  const bytes = new Uint8Array(16);
40
41
  crypto.getRandomValues(bytes);
@@ -42,7 +43,7 @@ var EdgeTTSModule = (() => {
42
43
  },
43
44
  getBaseHeaders() {
44
45
  return {
45
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0",
46
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36 Edg/155.0.0.0",
46
47
  "Accept-Encoding": "gzip, deflate, br, zstd",
47
48
  "Accept-Language": "en-US,en;q=0.9",
48
49
  "Cookie": "MUID=" + this.token32()
@@ -52,13 +53,12 @@ var EdgeTTSModule = (() => {
52
53
  "Pragma": "no-cache",
53
54
  "Cache-Control": "no-cache",
54
55
  "Origin": "chrome-extension://jdiccldimpdaibmpdkjnbmckianbfold",
55
- "Sec-WebSocket-Protocol": "synthesize",
56
- "Sec-WebSocket-Version": "13",
57
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.3650.75 Safari/537.36 Edg/143.0.3650.75"
56
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36 Edg/155.0.0.0"
58
57
  },
59
58
  VOICE_HEADERS: {
60
- "Sec-CH-UA": '" Not;A Brand";v="99", "Microsoft Edge";v="143", "Chromium";v="143"',
59
+ "Sec-CH-UA": '"Microsoft Edge";v="155", "Chromium";v="155", "Not(A:Brand";v="24"',
61
60
  "Sec-CH-UA-Mobile": "?0",
61
+ "Sec-CH-UA-Platform": '"Windows"',
62
62
  "Accept": "*/*",
63
63
  "Sec-Fetch-Site": "none",
64
64
  "Sec-Fetch-Mode": "cors",
@@ -123,7 +123,8 @@ var EdgeTTSModule = (() => {
123
123
  { headers: Constants.getBaseHeaders() }
124
124
  );
125
125
  const data = await response.json();
126
- return this.normalizeVoices(data.voices || []);
126
+ const voices = Array.isArray(data) ? data : data?.voices || [];
127
+ return this.normalizeVoices(voices);
127
128
  }
128
129
  async getVoicesByLanguage(locale) {
129
130
  const voices = await this.getVoices();
@@ -199,8 +200,9 @@ Path:speech.config\r
199
200
  return new Promise((resolve, reject) => {
200
201
  this.audio_stream = [];
201
202
  const reqId = this.generateUUID();
202
- const url = `${Constants.WSS_URL}?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}&ConnectionId=${reqId}`;
203
+ const url = `${Constants.WSS_URL}?Ocp-Apim-Subscription-Key=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}&ConnectionId=${reqId}`;
203
204
  this.ws = new WebSocket(url);
205
+ this.ws.binaryType = "arraybuffer";
204
206
  const SSML_text = this.getSSML(text, voice, options);
205
207
  let timedOut = false;
206
208
  let inactivityTimeout;
@@ -234,13 +236,7 @@ ${SSML_text}`;
234
236
  this.ws?.close();
235
237
  }
236
238
  } else {
237
- const reader = new FileReader();
238
- reader.onload = () => {
239
- const arrayBuffer = reader.result;
240
- const uint8Array = new Uint8Array(arrayBuffer);
241
- this.processAudioData(uint8Array);
242
- };
243
- reader.readAsArrayBuffer(event.data);
239
+ this.processAudioData(new Uint8Array(event.data));
244
240
  }
245
241
  };
246
242
  this.ws.onerror = (err) => {
@@ -262,8 +258,9 @@ ${SSML_text}`;
262
258
  this.audio_stream = [];
263
259
  const reqId = this.generateUUID();
264
260
  const secMsGEC = await this.generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN);
265
- const url = `${Constants.WSS_URL}?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}&ConnectionId=${reqId}`;
261
+ const url = `${Constants.WSS_URL}?Ocp-Apim-Subscription-Key=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}&ConnectionId=${reqId}`;
266
262
  this.ws = new WebSocket(url);
263
+ this.ws.binaryType = "arraybuffer";
267
264
  const SSML_text = this.getSSML(text, voice, options);
268
265
  const queue = [];
269
266
  let done = false;
@@ -313,19 +310,14 @@ ${SSML_text}`;
313
310
  this.ws?.close();
314
311
  }
315
312
  } else {
316
- const reader = new FileReader();
317
- reader.onload = () => {
318
- const arrayBuffer = reader.result;
319
- const uint8Array = new Uint8Array(arrayBuffer);
320
- const needle = new TextEncoder().encode("Path:audio\r\n");
321
- const audioStartIndex = this.indexOf(uint8Array, needle);
322
- if (audioStartIndex !== -1) {
323
- const audioChunk = uint8Array.slice(audioStartIndex + needle.length);
324
- this.audio_stream.push(audioChunk);
325
- push(audioChunk);
326
- }
327
- };
328
- reader.readAsArrayBuffer(event.data);
313
+ const uint8Array = new Uint8Array(event.data);
314
+ const needle = new TextEncoder().encode("Path:audio\r\n");
315
+ const audioStartIndex = this.indexOf(uint8Array, needle);
316
+ if (audioStartIndex !== -1) {
317
+ const audioChunk = uint8Array.slice(audioStartIndex + needle.length);
318
+ this.audio_stream.push(audioChunk);
319
+ push(audioChunk);
320
+ }
329
321
  }
330
322
  };
331
323
  this.ws.onerror = (err) => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/browser/EdgeTTS.browser.ts", "../../src/config/constants.ts"],
4
- "sourcesContent": ["import { Constants } from '../config/constants';\n\nexport interface Voice {\n Name: string;\n ShortName: string;\n Gender: string;\n Locale: string;\n FriendlyName: string;\n LocalName: string;\n}\n\nexport interface SynthesisOptions {\n pitch?: string | number;\n rate?: string | number;\n volume?: string | number;\n}\n\nexport class EdgeTTS {\n private audio_stream: Uint8Array[] = [];\n private ws?: WebSocket;\n\n\n async normalizeVoices(data: any[]): Promise<Voice[]> {\n const out = [];\n for (const v of data || []) {\n const short = v?.ShortName || \"\";\n const locale = v?.Locale || \"\";\n\n // base: remove locale prefix and Neural/NeuralHD suffix\n let base = short.replace(/^[a-z]{2}-[A-Z]{2}-/, \"\");\n base = base.replace(/NeuralHD$/, \"\").replace(/Neural$/, \"\").trim();\n\n // VoiceType: if NeuralHD/Neural in Name or ShortName\n const mix = `${v?.Name || \"\"} ${short}`;\n const voiceType =\n v?.VoiceType || (/NeuralHD/i.test(mix) ? \"NeuralHD\" : \"Neural\");\n\n // LocaleName: prefer LocaleName -> LanguageName -> locale\n const localeName = v?.LocaleName || (locale || null);\n\n // DisplayName: prefer DisplayName -> FriendlyName -> base -> short\n let display = v?.DisplayName || v?.FriendlyName || base || short;\n display = display.replace(/^Microsoft\\s+/i, \"\");\n display = display.split(\" - \")[0].trim();\n\n display = display.replace(/\\s*Online\\s*\\(Natural\\)\\s*/i, \" \");\n display = display.replace(/\\s*Online\\s*/i, \" \");\n display = display.replace(/\\s+/g, \" \").trim();\n\n // VoiceTag parsing\n const tag = (v?.VoiceTag && typeof v.VoiceTag === \"object\") ? v.VoiceTag : {};\n const tailored = Array.isArray(tag.TailoredScenarios)\n ? tag.TailoredScenarios\n : (Array.isArray(tag.ContentCategories) ? tag.ContentCategories : []);\n const personalities = Array.isArray(tag.VoicePersonalities)\n ? tag.VoicePersonalities\n : [];\n\n out.push({\n Name: short || (v?.Name || \"\"),\n DisplayName: display,\n LocalName: display,\n ShortName: short || (v?.Name || \"\"),\n Gender: v?.Gender ?? null,\n Locale: locale || null,\n LocaleName: localeName,\n SecondaryLocaleList: Array.isArray(v?.SecondaryLocaleList) ? v.SecondaryLocaleList : [],\n VoiceType: voiceType,\n VoiceTag: {\n TailoredScenarios: tailored,\n VoicePersonalities: personalities,\n },\n FriendlyName: `${display} (${voiceType}) - ${localeName}`,\n });\n }\n\n return out;\n }\n\n async getVoices(): Promise<Voice[]> {\n const secMsGEC = await this.generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN);\n\n const response = await fetch(\n `${Constants.VOICES_URL}?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}`,\n { headers: Constants.getBaseHeaders() }\n );\n\n const data = await response.json();\n return this.normalizeVoices(data.voices || []);\n }\n\n async getVoicesByLanguage(locale: string): Promise<Voice[]> {\n const voices = await this.getVoices();\n return voices.filter(voice => voice.Locale.startsWith(locale));\n }\n\n async getVoicesByGender(gender: 'Male' | 'Female'): Promise<Voice[]> {\n const voices = await this.getVoices();\n return voices.filter(voice => voice.Gender === gender);\n }\n\n private generateUUID(): string {\n return 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n }\n\n private validatePitch(pitch: string | number): string {\n if (typeof pitch === 'number') {\n return (pitch >= 0 ? `+${pitch}Hz` : `${pitch}Hz`);\n }\n return pitch;\n }\n\n private validateRate(rate: string | number): string {\n let rateValue: number;\n if (typeof rate === 'string') {\n rateValue = parseFloat(rate.replace('%', ''));\n } else {\n rateValue = rate;\n }\n return rateValue >= 0 ? `+${rateValue}%` : `${rateValue}%`;\n }\n\n private validateVolume(volume: string | number): string {\n let volumeValue: number;\n if (typeof volume === 'string') {\n volumeValue = parseInt(volume.replace('%', ''), 10);\n } else {\n volumeValue = volume;\n }\n return `${volumeValue}%`;\n }\n\n private escapeXML(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n }\n\n private getSSML(content: string, voice: string, options: SynthesisOptions = {}): string { \n const pitch = this.validatePitch(options.pitch ?? 0);\n const rate = this.validateRate(options.rate ?? 0);\n const volume = this.validateVolume(options.volume ?? 0);\n const escapedText = this.escapeXML(content);\n\n return `<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xmlns:mstts=\"https://www.w3.org/2001/mstts\" xml:lang=\"en-US\">\n <voice name=\"${voice}\">\n <prosody pitch=\"${pitch}\" rate=\"${rate}\" volume=\"${volume}\">\n ${escapedText}\n </prosody>\n </voice>\n </speak>`;\n }\n\n private nowRFC1123(): string {\n return new Date().toUTCString();\n }\n\n private parseRFC1123(rfcStr: string): Date {\n return new Date(rfcStr);\n }\n\n private buildTTSConfigMessage(): string {\n const timestamp = this.nowRFC1123();\n return `X-Timestamp:${timestamp}\\r\\nContent-Type:application/json; charset=utf-8\\r\\nPath:speech.config\\r\\n\\r\\n` +\n `{\"context\":{\"synthesis\":{\"audio\":{\"metadataoptions\":{\"sentenceBoundaryEnabled\":false,\"wordBoundaryEnabled\":true},\"outputFormat\":\"audio-24khz-48kbitrate-mono-mp3\"}}}}`;\n }\n\n async synthesize(text: string, voice: string = 'en-US-JennyNeural', options: SynthesisOptions = {}): Promise<void> {\n const secMsGEC = await this.generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN);\n\n return new Promise((resolve, reject) => {\n this.audio_stream = [];\n const reqId = this.generateUUID();\n const url = `${Constants.WSS_URL}?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}&ConnectionId=${reqId}`;\n\n this.ws = new WebSocket(url);\n\n const SSML_text = this.getSSML(text, voice, options);\n\n let timedOut = false;\n let inactivityTimeout: number;\n\n const resetInactivityTimeout = () => {\n clearTimeout(inactivityTimeout);\n inactivityTimeout = window.setTimeout(() => {\n timedOut = true;\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close();\n }\n reject(new Error(\"WebSocket inactivity timeout - no response from server\"));\n }, 30000); // 30 seconds of inactivity\n };\n\n this.ws.onopen = () => {\n resetInactivityTimeout(); // start the inactivity timeout\n const message = this.buildTTSConfigMessage();\n this.ws!.send(message);\n const timestamp = this.nowRFC1123();\n const speechMessage = `X-RequestId:${reqId}\\r\\nContent-Type:application/ssml+xml\\r\\nX-Timestamp:${timestamp}\\r\\nPath:ssml\\r\\n\\r\\n${SSML_text}`;\n this.ws!.send(speechMessage);\n };\n\n this.ws.onmessage = (event) => {\n resetInactivityTimeout(); // restart inactivity timeout \n if (typeof event.data === 'string') {\n if (event.data.includes('Path:turn.end')) {\n this.ws?.close();\n }\n } else {\n const reader = new FileReader();\n reader.onload = () => {\n const arrayBuffer = reader.result as ArrayBuffer;\n const uint8Array = new Uint8Array(arrayBuffer);\n this.processAudioData(uint8Array);\n };\n reader.readAsArrayBuffer(event.data);\n }\n };\n\n this.ws.onerror = (err: any) => {\n clearTimeout(inactivityTimeout);\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close();\n }\n reject(new Error('WebSocket error'));\n };\n\n this.ws.onclose = () => {\n clearTimeout(inactivityTimeout);\n if (!timedOut) {\n resolve();\n }\n };\n });\n }\n\n async *synthesizeStream(text: string, voice: string = 'en-US-JennyNeural', options: SynthesisOptions = {}): AsyncGenerator<Uint8Array, void, unknown> {\n this.audio_stream = [];\n\n const reqId = this.generateUUID();\n const secMsGEC = await this.generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN);\n\n const url = `${Constants.WSS_URL}?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}&ConnectionId=${reqId}`;\n\n this.ws = new WebSocket(url);\n\n const SSML_text = this.getSSML(text, voice, options);\n\n const queue: Uint8Array[] = [];\n let done = false;\n let error: Error | null = null;\n let notify: (() => void) | null = null;\n\n const push = (chunk: Uint8Array) => {\n queue.push(chunk);\n if (notify) {\n notify();\n notify = null;\n }\n };\n\n let timedOut = false;\n let inactivityTimeout: number;\n\n const resetInactivityTimeout = () => {\n clearTimeout(inactivityTimeout);\n inactivityTimeout = window.setTimeout(() => {\n timedOut = true;\n error = new Error(\"WebSocket inactivity timeout - no response from server\");\n done = true;\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close();\n }\n if (notify) {\n notify();\n notify = null;\n }\n }, 30000); // 30 seconds of inactivity\n };\n\n this.ws.onopen = () => {\n resetInactivityTimeout(); // start the inactivity timeout\n const message = this.buildTTSConfigMessage();\n this.ws!.send(message);\n\n const timestamp = this.nowRFC1123();\n const speechMessage = `X-RequestId:${reqId}\\r\\nContent-Type:application/ssml+xml\\r\\nX-Timestamp:${timestamp}\\r\\nPath:ssml\\r\\n\\r\\n${SSML_text}`;\n this.ws!.send(speechMessage);\n };\n\n this.ws.onmessage = (event) => {\n resetInactivityTimeout(); // restart inactivity timeout\n if (typeof event.data === 'string') {\n if (event.data.includes('Path:turn.end')) {\n this.ws?.close();\n }\n } else {\n const reader = new FileReader();\n reader.onload = () => {\n const arrayBuffer = reader.result as ArrayBuffer;\n const uint8Array = new Uint8Array(arrayBuffer);\n\n const needle = new TextEncoder().encode(\"Path:audio\\r\\n\");\n const audioStartIndex = this.indexOf(uint8Array, needle);\n\n if (audioStartIndex !== -1) {\n const audioChunk = uint8Array.slice(audioStartIndex + needle.length);\n this.audio_stream.push(audioChunk);\n push(audioChunk);\n }\n };\n reader.readAsArrayBuffer(event.data);\n }\n };\n\n this.ws.onerror = (err: any) => {\n clearTimeout(inactivityTimeout);\n error = new Error('WebSocket error');\n done = true;\n if (notify) {\n notify();\n notify = null;\n }\n };\n\n this.ws.onclose = () => {\n clearTimeout(inactivityTimeout);\n done = true;\n if (notify) {\n notify();\n notify = null;\n }\n };\n\n while (!done || queue.length > 0) {\n if (queue.length === 0) {\n await new Promise<void>(resolve => (notify = resolve));\n continue;\n }\n const chunk = queue.shift();\n if (chunk) {\n yield chunk;\n }\n }\n\n if (error) {\n throw error;\n }\n }\n\n private processAudioData(buffer: Uint8Array): void {\n const needle = new TextEncoder().encode(\"Path:audio\\r\\n\");\n const audioStartIndex = this.indexOf(buffer, needle);\n\n if (audioStartIndex !== -1) {\n const audioChunk = buffer.slice(audioStartIndex + needle.length);\n this.audio_stream.push(audioChunk);\n }\n }\n\n private indexOf(arr: Uint8Array, subarr: Uint8Array): number {\n for (let i = 0; i <= arr.length - subarr.length; i++) {\n let match = true;\n for (let j = 0; j < subarr.length; j++) {\n if (arr[i + j] !== subarr[j]) {\n match = false;\n break;\n }\n }\n if (match) return i;\n }\n return -1;\n }\n\n private async generateSecMsGec(trustedClientToken: string): Promise<string> {\n const now = this.nowRFC1123();\n const fixedDate = this.parseRFC1123(now);\n const ticks = Math.floor(fixedDate.getTime() / 1000) + 11644473600;\n const rounded = ticks - (ticks % 300);\n const windowsTicks = rounded * 10_000_000;\n\n const encoder = new TextEncoder();\n const data = encoder.encode(`${windowsTicks}${trustedClientToken}`);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n\n return Array.from(new Uint8Array(hashBuffer))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n .toUpperCase();\n }\n\n getAudioData(): Uint8Array {\n if (this.audio_stream.length === 0) {\n throw new Error(\"No audio data available\");\n }\n // When the service cannot speak the text it answers with a single empty\n // chunk, so the stream is not empty but the audio is. Checking the byte\n // count rather than the chunk count is what catches that.\n const totalLength = this.audio_stream.reduce((acc, chunk) => acc + chunk.length, 0);\n if (totalLength === 0) {\n throw new Error(\n \"The service returned no audio. Voices are locale specific, so a voice cannot \" +\n \"read text written in another script. Check that the voice matches the language \" +\n \"of the text.\"\n );\n }\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of this.audio_stream) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n }\n}\n", "export const Constants = {\n TRUSTED_CLIENT_TOKEN: '6A5AA1D4EAFF4E9FB37E23D68491D6F4',\n BASE_URL: 'https://speech.platform.bing.com/consumer/speech/synthesize/readaloud',\n WSS_URL: 'wss://speech.platform.bing.com/consumer/speech/synthesize/readaloud/edge/v1',\n VOICES_URL: 'https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list',\n\n CHROMIUM_FULL_VERSION: '143.0.3650.75',\n CHROMIUM_MAJOR_VERSION: '143',\n VERSION_MS_GEC: '1-143.0.3650',\n\n token32() {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n .toUpperCase();\n },\n\n getBaseHeaders() {\n return {\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0',\n 'Accept-Encoding': 'gzip, deflate, br, zstd',\n 'Accept-Language': 'en-US,en;q=0.9',\n 'Cookie': 'MUID=' + this.token32()\n };\n },\n\n WSS_HEADERS: {\n 'Pragma': 'no-cache',\n 'Cache-Control': 'no-cache',\n 'Origin': 'chrome-extension://jdiccldimpdaibmpdkjnbmckianbfold',\n 'Sec-WebSocket-Protocol': 'synthesize',\n 'Sec-WebSocket-Version': '13',\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.3650.75 Safari/537.36 Edg/143.0.3650.75'\n },\n\n VOICE_HEADERS: {\n 'Sec-CH-UA': '\" Not;A Brand\";v=\"99\", \"Microsoft Edge\";v=\"143\", \"Chromium\";v=\"143\"',\n 'Sec-CH-UA-Mobile': '?0',\n 'Accept': '*/*',\n 'Sec-Fetch-Site': 'none',\n 'Sec-Fetch-Mode': 'cors',\n 'Sec-Fetch-Dest': 'empty'\n },\n\n // https://learn.microsoft.com/en-us/azure/ai-services/speech-service/rest-text-to-speech?tabs=nonstreaming\n OUTPUT_FORMAT: {\n 'AUDIO_24KHZ_48KBITRATE_MONO_MP3': 'audio-24khz-48kbitrate-mono-mp3',\n 'AUDIO_24KHZ_96KBITRATE_MONO_MP3': 'audio-24khz-96kbitrate-mono-mp3',\n 'WEBM_24KHZ_16BIT_MONO_OPUS': 'webm-24khz-16bit-mono-opus',\n }\n\n\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;;;ACAO,MAAM,YAAY;AAAA,IACrB,sBAAsB;AAAA,IACtB,UAAU;AAAA,IACV,SAAS;AAAA,IACT,YAAY;AAAA,IAEZ,uBAAuB;AAAA,IACvB,wBAAwB;AAAA,IACxB,gBAAgB;AAAA,IAEhB,UAAU;AACN,YAAM,QAAQ,IAAI,WAAW,EAAE;AAC/B,aAAO,gBAAgB,KAAK;AAE5B,aAAO,MAAM,KAAK,KAAK,EAClB,IAAI,OAAK,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EACxC,KAAK,EAAE,EACP,YAAY;AAAA,IACrB;AAAA,IAEA,iBAAiB;AACb,aAAO;AAAA,QACH,cAAc;AAAA,QACd,mBAAmB;AAAA,QACnB,mBAAmB;AAAA,QACnB,UAAU,UAAU,KAAK,QAAQ;AAAA,MACrC;AAAA,IACJ;AAAA,IAEA,aAAa;AAAA,MACT,UAAU;AAAA,MACV,iBAAiB;AAAA,MACjB,UAAU;AAAA,MACV,0BAA0B;AAAA,MAC1B,yBAAyB;AAAA,MACzB,cAAc;AAAA,IAClB;AAAA,IAEA,eAAe;AAAA,MACX,aAAa;AAAA,MACb,oBAAoB;AAAA,MACpB,UAAU;AAAA,MACV,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,IACtB;AAAA;AAAA,IAGA,eAAe;AAAA,MACX,mCAAmC;AAAA,MACnC,mCAAmC;AAAA,MACnC,8BAA8B;AAAA,IAClC;AAAA,EAGJ;;;ADtCO,MAAM,UAAN,MAAc;AAAA,IAAd;AACH,0BAAQ,gBAA6B,CAAC;AACtC,0BAAQ;AAAA;AAAA,IAGR,MAAM,gBAAgB,MAA+B;AACjD,YAAM,MAAM,CAAC;AACb,iBAAW,KAAK,QAAQ,CAAC,GAAG;AACxB,cAAM,QAAQ,GAAG,aAAa;AAC9B,cAAM,SAAS,GAAG,UAAU;AAG5B,YAAI,OAAO,MAAM,QAAQ,uBAAuB,EAAE;AAClD,eAAO,KAAK,QAAQ,aAAa,EAAE,EAAE,QAAQ,WAAW,EAAE,EAAE,KAAK;AAGjE,cAAM,MAAM,GAAG,GAAG,QAAQ,EAAE,IAAI,KAAK;AACrC,cAAM,YACF,GAAG,cAAc,YAAY,KAAK,GAAG,IAAI,aAAa;AAG1D,cAAM,aAAa,GAAG,eAAe,UAAU;AAG/C,YAAI,UAAU,GAAG,eAAe,GAAG,gBAAgB,QAAQ;AAC3D,kBAAU,QAAQ,QAAQ,kBAAkB,EAAE;AAC9C,kBAAU,QAAQ,MAAM,KAAK,EAAE,CAAC,EAAE,KAAK;AAEvC,kBAAU,QAAQ,QAAQ,+BAA+B,GAAG;AAC5D,kBAAU,QAAQ,QAAQ,iBAAiB,GAAG;AAC9C,kBAAU,QAAQ,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAG5C,cAAM,MAAO,GAAG,YAAY,OAAO,EAAE,aAAa,WAAY,EAAE,WAAW,CAAC;AAC5E,cAAM,WAAW,MAAM,QAAQ,IAAI,iBAAiB,IAC9C,IAAI,oBACH,MAAM,QAAQ,IAAI,iBAAiB,IAAI,IAAI,oBAAoB,CAAC;AACvE,cAAM,gBAAgB,MAAM,QAAQ,IAAI,kBAAkB,IACpD,IAAI,qBACJ,CAAC;AAEP,YAAI,KAAK;AAAA,UACL,MAAM,UAAU,GAAG,QAAQ;AAAA,UAC3B,aAAa;AAAA,UACb,WAAW;AAAA,UACX,WAAW,UAAU,GAAG,QAAQ;AAAA,UAChC,QAAQ,GAAG,UAAU;AAAA,UACrB,QAAQ,UAAU;AAAA,UAClB,YAAY;AAAA,UACZ,qBAAqB,MAAM,QAAQ,GAAG,mBAAmB,IAAI,EAAE,sBAAsB,CAAC;AAAA,UACtF,WAAW;AAAA,UACX,UAAU;AAAA,YACN,mBAAmB;AAAA,YACnB,oBAAoB;AAAA,UACxB;AAAA,UACA,cAAc,GAAG,OAAO,KAAK,SAAS,OAAO,UAAU;AAAA,QAC3D,CAAC;AAAA,MACL;AAEA,aAAO;AAAA,IACX;AAAA,IAEA,MAAM,YAA8B;AAChC,YAAM,WAAW,MAAM,KAAK,iBAAiB,UAAU,oBAAoB;AAE3E,YAAM,WAAW,MAAM;AAAA,QACnB,GAAG,UAAU,UAAU,uBAAuB,UAAU,oBAAoB,eAAe,QAAQ,uBAAuB,UAAU,cAAc;AAAA,QAClJ,EAAE,SAAS,UAAU,eAAe,EAAE;AAAA,MAC1C;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,aAAO,KAAK,gBAAgB,KAAK,UAAU,CAAC,CAAC;AAAA,IACjD;AAAA,IAEA,MAAM,oBAAoB,QAAkC;AACxD,YAAM,SAAS,MAAM,KAAK,UAAU;AACpC,aAAO,OAAO,OAAO,WAAS,MAAM,OAAO,WAAW,MAAM,CAAC;AAAA,IACjE;AAAA,IAEA,MAAM,kBAAkB,QAA6C;AACjE,YAAM,SAAS,MAAM,KAAK,UAAU;AACpC,aAAO,OAAO,OAAO,WAAS,MAAM,WAAW,MAAM;AAAA,IACzD;AAAA,IAEQ,eAAuB;AAC3B,aAAO,uCAAuC,QAAQ,SAAS,SAAU,GAAG;AACxE,cAAM,IAAI,KAAK,OAAO,IAAI,KAAK;AAC/B,cAAM,IAAI,MAAM,MAAM,IAAK,IAAI,IAAM;AACrC,eAAO,EAAE,SAAS,EAAE;AAAA,MACxB,CAAC;AAAA,IACL;AAAA,IAEQ,cAAc,OAAgC;AAClD,UAAI,OAAO,UAAU,UAAU;AAC3B,eAAQ,SAAS,IAAI,IAAI,KAAK,OAAO,GAAG,KAAK;AAAA,MACjD;AACA,aAAO;AAAA,IACX;AAAA,IAEQ,aAAa,MAA+B;AAChD,UAAI;AACJ,UAAI,OAAO,SAAS,UAAU;AAC1B,oBAAY,WAAW,KAAK,QAAQ,KAAK,EAAE,CAAC;AAAA,MAChD,OAAO;AACH,oBAAY;AAAA,MAChB;AACA,aAAO,aAAa,IAAI,IAAI,SAAS,MAAM,GAAG,SAAS;AAAA,IAC3D;AAAA,IAEQ,eAAe,QAAiC;AACpD,UAAI;AACJ,UAAI,OAAO,WAAW,UAAU;AAC5B,sBAAc,SAAS,OAAO,QAAQ,KAAK,EAAE,GAAG,EAAE;AAAA,MACtD,OAAO;AACH,sBAAc;AAAA,MAClB;AACA,aAAO,GAAG,WAAW;AAAA,IACzB;AAAA,IAEQ,UAAU,MAAsB;AACpC,aAAO,KACF,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,QAAQ;AAAA,IAC/B;AAAA,IAEQ,QAAQ,SAAiB,OAAe,UAA4B,CAAC,GAAW;AACpF,YAAM,QAAQ,KAAK,cAAc,QAAQ,SAAS,CAAC;AACnD,YAAM,OAAO,KAAK,aAAa,QAAQ,QAAQ,CAAC;AAChD,YAAM,SAAS,KAAK,eAAe,QAAQ,UAAU,CAAC;AACtD,YAAM,cAAc,KAAK,UAAU,OAAO;AAE1C,aAAO;AAAA,mCACoB,KAAK;AAAA,0CACE,KAAK,WAAW,IAAI,aAAa,MAAM;AAAA,8BACnD,WAAW;AAAA;AAAA;AAAA;AAAA,IAIrC;AAAA,IAEQ,aAAqB;AACzB,cAAO,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC;AAAA,IAEQ,aAAa,QAAsB;AACvC,aAAO,IAAI,KAAK,MAAM;AAAA,IAC1B;AAAA,IAEQ,wBAAgC;AACpC,YAAM,YAAY,KAAK,WAAW;AAClC,aAAO,eAAe,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,IAEnC;AAAA,IAEA,MAAM,WAAW,MAAc,QAAgB,qBAAqB,UAA4B,CAAC,GAAkB;AAC/G,YAAM,WAAW,MAAM,KAAK,iBAAiB,UAAU,oBAAoB;AAE3E,aAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,aAAK,eAAe,CAAC;AACrB,cAAM,QAAQ,KAAK,aAAa;AAChC,cAAM,MAAM,GAAG,UAAU,OAAO,uBAAuB,UAAU,oBAAoB,eAAe,QAAQ,uBAAuB,UAAU,cAAc,iBAAiB,KAAK;AAEjL,aAAK,KAAK,IAAI,UAAU,GAAG;AAE3B,cAAM,YAAY,KAAK,QAAQ,MAAM,OAAO,OAAO;AAEnD,YAAI,WAAW;AACf,YAAI;AAEJ,cAAM,yBAAyB,MAAM;AACjC,uBAAa,iBAAiB;AAC9B,8BAAoB,OAAO,WAAW,MAAM;AACxC,uBAAW;AACX,gBAAI,KAAK,MAAM,KAAK,GAAG,eAAe,UAAU,MAAM;AAClD,mBAAK,GAAG,MAAM;AAAA,YAClB;AACA,mBAAO,IAAI,MAAM,wDAAwD,CAAC;AAAA,UAC9E,GAAG,GAAK;AAAA,QACZ;AAEA,aAAK,GAAG,SAAS,MAAM;AACnB,iCAAuB;AACvB,gBAAM,UAAU,KAAK,sBAAsB;AAC3C,eAAK,GAAI,KAAK,OAAO;AACrB,gBAAM,YAAY,KAAK,WAAW;AAClC,gBAAM,gBAAgB,eAAe,KAAK;AAAA;AAAA,cAAwD,SAAS;AAAA;AAAA;AAAA,EAAwB,SAAS;AAC5I,eAAK,GAAI,KAAK,aAAa;AAAA,QAC/B;AAEA,aAAK,GAAG,YAAY,CAAC,UAAU;AAC3B,iCAAuB;AACvB,cAAI,OAAO,MAAM,SAAS,UAAU;AAChC,gBAAI,MAAM,KAAK,SAAS,eAAe,GAAG;AACtC,mBAAK,IAAI,MAAM;AAAA,YACnB;AAAA,UACJ,OAAO;AACH,kBAAM,SAAS,IAAI,WAAW;AAC9B,mBAAO,SAAS,MAAM;AAClB,oBAAM,cAAc,OAAO;AAC3B,oBAAM,aAAa,IAAI,WAAW,WAAW;AAC7C,mBAAK,iBAAiB,UAAU;AAAA,YACpC;AACA,mBAAO,kBAAkB,MAAM,IAAI;AAAA,UACvC;AAAA,QACJ;AAEA,aAAK,GAAG,UAAU,CAAC,QAAa;AAC5B,uBAAa,iBAAiB;AAC9B,cAAI,KAAK,MAAM,KAAK,GAAG,eAAe,UAAU,MAAM;AAClD,iBAAK,GAAG,MAAM;AAAA,UAClB;AACA,iBAAO,IAAI,MAAM,iBAAiB,CAAC;AAAA,QACvC;AAEA,aAAK,GAAG,UAAU,MAAM;AACpB,uBAAa,iBAAiB;AAC9B,cAAI,CAAC,UAAU;AACX,oBAAQ;AAAA,UACZ;AAAA,QACJ;AAAA,MACJ,CAAC;AAAA,IACL;AAAA,IAEA,OAAO,iBAAiB,MAAc,QAAgB,qBAAqB,UAA4B,CAAC,GAA8C;AAClJ,WAAK,eAAe,CAAC;AAErB,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,WAAW,MAAM,KAAK,iBAAiB,UAAU,oBAAoB;AAE3E,YAAM,MAAM,GAAG,UAAU,OAAO,uBAAuB,UAAU,oBAAoB,eAAe,QAAQ,uBAAuB,UAAU,cAAc,iBAAiB,KAAK;AAEjL,WAAK,KAAK,IAAI,UAAU,GAAG;AAE3B,YAAM,YAAY,KAAK,QAAQ,MAAM,OAAO,OAAO;AAEnD,YAAM,QAAsB,CAAC;AAC7B,UAAI,OAAO;AACX,UAAI,QAAsB;AAC1B,UAAI,SAA8B;AAElC,YAAM,OAAO,CAAC,UAAsB;AAChC,cAAM,KAAK,KAAK;AAChB,YAAI,QAAQ;AACR,iBAAO;AACP,mBAAS;AAAA,QACb;AAAA,MACJ;AAEA,UAAI,WAAW;AACf,UAAI;AAEJ,YAAM,yBAAyB,MAAM;AACjC,qBAAa,iBAAiB;AAC9B,4BAAoB,OAAO,WAAW,MAAM;AACxC,qBAAW;AACX,kBAAQ,IAAI,MAAM,wDAAwD;AAC1E,iBAAO;AACP,cAAI,KAAK,MAAM,KAAK,GAAG,eAAe,UAAU,MAAM;AAClD,iBAAK,GAAG,MAAM;AAAA,UAClB;AACA,cAAI,QAAQ;AACR,mBAAO;AACP,qBAAS;AAAA,UACb;AAAA,QACJ,GAAG,GAAK;AAAA,MACZ;AAEA,WAAK,GAAG,SAAS,MAAM;AACnB,+BAAuB;AACvB,cAAM,UAAU,KAAK,sBAAsB;AAC3C,aAAK,GAAI,KAAK,OAAO;AAErB,cAAM,YAAY,KAAK,WAAW;AAClC,cAAM,gBAAgB,eAAe,KAAK;AAAA;AAAA,cAAwD,SAAS;AAAA;AAAA;AAAA,EAAwB,SAAS;AAC5I,aAAK,GAAI,KAAK,aAAa;AAAA,MAC/B;AAEA,WAAK,GAAG,YAAY,CAAC,UAAU;AAC3B,+BAAuB;AACvB,YAAI,OAAO,MAAM,SAAS,UAAU;AAChC,cAAI,MAAM,KAAK,SAAS,eAAe,GAAG;AACtC,iBAAK,IAAI,MAAM;AAAA,UACnB;AAAA,QACJ,OAAO;AACH,gBAAM,SAAS,IAAI,WAAW;AAC9B,iBAAO,SAAS,MAAM;AAClB,kBAAM,cAAc,OAAO;AAC3B,kBAAM,aAAa,IAAI,WAAW,WAAW;AAE7C,kBAAM,SAAS,IAAI,YAAY,EAAE,OAAO,gBAAgB;AACxD,kBAAM,kBAAkB,KAAK,QAAQ,YAAY,MAAM;AAEvD,gBAAI,oBAAoB,IAAI;AACxB,oBAAM,aAAa,WAAW,MAAM,kBAAkB,OAAO,MAAM;AACnE,mBAAK,aAAa,KAAK,UAAU;AACjC,mBAAK,UAAU;AAAA,YACnB;AAAA,UACJ;AACA,iBAAO,kBAAkB,MAAM,IAAI;AAAA,QACvC;AAAA,MACJ;AAEA,WAAK,GAAG,UAAU,CAAC,QAAa;AAC5B,qBAAa,iBAAiB;AAC9B,gBAAQ,IAAI,MAAM,iBAAiB;AACnC,eAAO;AACP,YAAI,QAAQ;AACR,iBAAO;AACP,mBAAS;AAAA,QACb;AAAA,MACJ;AAEA,WAAK,GAAG,UAAU,MAAM;AACpB,qBAAa,iBAAiB;AAC9B,eAAO;AACP,YAAI,QAAQ;AACR,iBAAO;AACP,mBAAS;AAAA,QACb;AAAA,MACJ;AAEA,aAAO,CAAC,QAAQ,MAAM,SAAS,GAAG;AAC9B,YAAI,MAAM,WAAW,GAAG;AACpB,gBAAM,IAAI,QAAc,aAAY,SAAS,OAAQ;AACrD;AAAA,QACJ;AACA,cAAM,QAAQ,MAAM,MAAM;AAC1B,YAAI,OAAO;AACP,gBAAM;AAAA,QACV;AAAA,MACJ;AAEA,UAAI,OAAO;AACP,cAAM;AAAA,MACV;AAAA,IACJ;AAAA,IAEQ,iBAAiB,QAA0B;AAC/C,YAAM,SAAS,IAAI,YAAY,EAAE,OAAO,gBAAgB;AACxD,YAAM,kBAAkB,KAAK,QAAQ,QAAQ,MAAM;AAEnD,UAAI,oBAAoB,IAAI;AACxB,cAAM,aAAa,OAAO,MAAM,kBAAkB,OAAO,MAAM;AAC/D,aAAK,aAAa,KAAK,UAAU;AAAA,MACrC;AAAA,IACJ;AAAA,IAEQ,QAAQ,KAAiB,QAA4B;AACzD,eAAS,IAAI,GAAG,KAAK,IAAI,SAAS,OAAO,QAAQ,KAAK;AAClD,YAAI,QAAQ;AACZ,iBAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACpC,cAAI,IAAI,IAAI,CAAC,MAAM,OAAO,CAAC,GAAG;AAC1B,oBAAQ;AACR;AAAA,UACJ;AAAA,QACJ;AACA,YAAI,MAAO,QAAO;AAAA,MACtB;AACA,aAAO;AAAA,IACX;AAAA,IAEA,MAAc,iBAAiB,oBAA6C;AACxE,YAAM,MAAM,KAAK,WAAW;AAC5B,YAAM,YAAY,KAAK,aAAa,GAAG;AACvC,YAAM,QAAQ,KAAK,MAAM,UAAU,QAAQ,IAAI,GAAI,IAAI;AACvD,YAAM,UAAU,QAAS,QAAQ;AACjC,YAAM,eAAe,UAAU;AAE/B,YAAM,UAAU,IAAI,YAAY;AAChC,YAAM,OAAO,QAAQ,OAAO,GAAG,YAAY,GAAG,kBAAkB,EAAE;AAClE,YAAM,aAAa,MAAM,OAAO,OAAO,OAAO,WAAW,IAAI;AAE7D,aAAO,MAAM,KAAK,IAAI,WAAW,UAAU,CAAC,EACvC,IAAI,OAAK,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EACxC,KAAK,EAAE,EACP,YAAY;AAAA,IACrB;AAAA,IAEA,eAA2B;AACvB,UAAI,KAAK,aAAa,WAAW,GAAG;AAChC,cAAM,IAAI,MAAM,yBAAyB;AAAA,MAC7C;AAIA,YAAM,cAAc,KAAK,aAAa,OAAO,CAAC,KAAK,UAAU,MAAM,MAAM,QAAQ,CAAC;AAClF,UAAI,gBAAgB,GAAG;AACnB,cAAM,IAAI;AAAA,UACN;AAAA,QAGJ;AAAA,MACJ;AACA,YAAM,SAAS,IAAI,WAAW,WAAW;AACzC,UAAI,SAAS;AACb,iBAAW,SAAS,KAAK,cAAc;AACnC,eAAO,IAAI,OAAO,MAAM;AACxB,kBAAU,MAAM;AAAA,MACpB;AACA,aAAO;AAAA,IACX;AAAA,EACJ;",
4
+ "sourcesContent": ["import { Constants } from '../config/constants';\n\nexport interface Voice {\n Name: string;\n ShortName: string;\n Gender: string;\n Locale: string;\n FriendlyName: string;\n LocalName: string;\n}\n\nexport interface SynthesisOptions {\n pitch?: string | number;\n rate?: string | number;\n volume?: string | number;\n}\n\nexport class EdgeTTS {\n private audio_stream: Uint8Array[] = [];\n private ws?: WebSocket;\n\n\n async normalizeVoices(data: any[]): Promise<Voice[]> {\n const out = [];\n for (const v of data || []) {\n const short = v?.ShortName || \"\";\n const locale = v?.Locale || \"\";\n\n // base: remove locale prefix and Neural/NeuralHD suffix\n let base = short.replace(/^[a-z]{2}-[A-Z]{2}-/, \"\");\n base = base.replace(/NeuralHD$/, \"\").replace(/Neural$/, \"\").trim();\n\n // VoiceType: if NeuralHD/Neural in Name or ShortName\n const mix = `${v?.Name || \"\"} ${short}`;\n const voiceType =\n v?.VoiceType || (/NeuralHD/i.test(mix) ? \"NeuralHD\" : \"Neural\");\n\n // LocaleName: prefer LocaleName -> LanguageName -> locale\n const localeName = v?.LocaleName || (locale || null);\n\n // DisplayName: prefer DisplayName -> FriendlyName -> base -> short\n let display = v?.DisplayName || v?.FriendlyName || base || short;\n display = display.replace(/^Microsoft\\s+/i, \"\");\n display = display.split(\" - \")[0].trim();\n\n display = display.replace(/\\s*Online\\s*\\(Natural\\)\\s*/i, \" \");\n display = display.replace(/\\s*Online\\s*/i, \" \");\n display = display.replace(/\\s+/g, \" \").trim();\n\n // VoiceTag parsing\n const tag = (v?.VoiceTag && typeof v.VoiceTag === \"object\") ? v.VoiceTag : {};\n const tailored = Array.isArray(tag.TailoredScenarios)\n ? tag.TailoredScenarios\n : (Array.isArray(tag.ContentCategories) ? tag.ContentCategories : []);\n const personalities = Array.isArray(tag.VoicePersonalities)\n ? tag.VoicePersonalities\n : [];\n\n out.push({\n Name: short || (v?.Name || \"\"),\n DisplayName: display,\n LocalName: display,\n ShortName: short || (v?.Name || \"\"),\n Gender: v?.Gender ?? null,\n Locale: locale || null,\n LocaleName: localeName,\n SecondaryLocaleList: Array.isArray(v?.SecondaryLocaleList) ? v.SecondaryLocaleList : [],\n VoiceType: voiceType,\n VoiceTag: {\n TailoredScenarios: tailored,\n VoicePersonalities: personalities,\n },\n FriendlyName: `${display} (${voiceType}) - ${localeName}`,\n });\n }\n\n return out;\n }\n\n async getVoices(): Promise<Voice[]> {\n const secMsGEC = await this.generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN);\n\n const response = await fetch(\n `${Constants.VOICES_URL}?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}`,\n { headers: Constants.getBaseHeaders() }\n );\n\n const data = await response.json();\n // The readaloud endpoint returns a bare array, not { voices: [...] }.\n // Reading `data.voices` unconditionally yielded zero voices even on a\n // successful 200 response. Both shapes are accepted now.\n const voices = Array.isArray(data) ? data : (data?.voices || []);\n return this.normalizeVoices(voices);\n }\n\n async getVoicesByLanguage(locale: string): Promise<Voice[]> {\n const voices = await this.getVoices();\n return voices.filter(voice => voice.Locale.startsWith(locale));\n }\n\n async getVoicesByGender(gender: 'Male' | 'Female'): Promise<Voice[]> {\n const voices = await this.getVoices();\n return voices.filter(voice => voice.Gender === gender);\n }\n\n private generateUUID(): string {\n return 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n }\n\n private validatePitch(pitch: string | number): string {\n if (typeof pitch === 'number') {\n return (pitch >= 0 ? `+${pitch}Hz` : `${pitch}Hz`);\n }\n return pitch;\n }\n\n private validateRate(rate: string | number): string {\n let rateValue: number;\n if (typeof rate === 'string') {\n rateValue = parseFloat(rate.replace('%', ''));\n } else {\n rateValue = rate;\n }\n return rateValue >= 0 ? `+${rateValue}%` : `${rateValue}%`;\n }\n\n private validateVolume(volume: string | number): string {\n let volumeValue: number;\n if (typeof volume === 'string') {\n volumeValue = parseInt(volume.replace('%', ''), 10);\n } else {\n volumeValue = volume;\n }\n return `${volumeValue}%`;\n }\n\n private escapeXML(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n }\n\n private getSSML(content: string, voice: string, options: SynthesisOptions = {}): string { \n const pitch = this.validatePitch(options.pitch ?? 0);\n const rate = this.validateRate(options.rate ?? 0);\n const volume = this.validateVolume(options.volume ?? 0);\n const escapedText = this.escapeXML(content);\n\n return `<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xmlns:mstts=\"https://www.w3.org/2001/mstts\" xml:lang=\"en-US\">\n <voice name=\"${voice}\">\n <prosody pitch=\"${pitch}\" rate=\"${rate}\" volume=\"${volume}\">\n ${escapedText}\n </prosody>\n </voice>\n </speak>`;\n }\n\n private nowRFC1123(): string {\n return new Date().toUTCString();\n }\n\n private parseRFC1123(rfcStr: string): Date {\n return new Date(rfcStr);\n }\n\n private buildTTSConfigMessage(): string {\n const timestamp = this.nowRFC1123();\n return `X-Timestamp:${timestamp}\\r\\nContent-Type:application/json; charset=utf-8\\r\\nPath:speech.config\\r\\n\\r\\n` +\n `{\"context\":{\"synthesis\":{\"audio\":{\"metadataoptions\":{\"sentenceBoundaryEnabled\":false,\"wordBoundaryEnabled\":true},\"outputFormat\":\"audio-24khz-48kbitrate-mono-mp3\"}}}}`;\n }\n\n async synthesize(text: string, voice: string = 'en-US-JennyNeural', options: SynthesisOptions = {}): Promise<void> {\n const secMsGEC = await this.generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN);\n\n return new Promise((resolve, reject) => {\n this.audio_stream = [];\n const reqId = this.generateUUID();\n const url = `${Constants.WSS_URL}?Ocp-Apim-Subscription-Key=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}&ConnectionId=${reqId}`;\n\n this.ws = new WebSocket(url);\n this.ws.binaryType = 'arraybuffer';\n\n const SSML_text = this.getSSML(text, voice, options);\n\n let timedOut = false;\n let inactivityTimeout: number;\n\n const resetInactivityTimeout = () => {\n clearTimeout(inactivityTimeout);\n inactivityTimeout = window.setTimeout(() => {\n timedOut = true;\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close();\n }\n reject(new Error(\"WebSocket inactivity timeout - no response from server\"));\n }, 30000); // 30 seconds of inactivity\n };\n\n this.ws.onopen = () => {\n resetInactivityTimeout(); // start the inactivity timeout\n const message = this.buildTTSConfigMessage();\n this.ws!.send(message);\n const timestamp = this.nowRFC1123();\n const speechMessage = `X-RequestId:${reqId}\\r\\nContent-Type:application/ssml+xml\\r\\nX-Timestamp:${timestamp}\\r\\nPath:ssml\\r\\n\\r\\n${SSML_text}`;\n this.ws!.send(speechMessage);\n };\n\n this.ws.onmessage = (event) => {\n resetInactivityTimeout(); // restart inactivity timeout \n if (typeof event.data === 'string') {\n if (event.data.includes('Path:turn.end')) {\n this.ws?.close();\n }\n } else {\n this.processAudioData(new Uint8Array(event.data));\n }\n };\n\n this.ws.onerror = (err: any) => {\n clearTimeout(inactivityTimeout);\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close();\n }\n reject(new Error('WebSocket error'));\n };\n\n this.ws.onclose = () => {\n clearTimeout(inactivityTimeout);\n if (!timedOut) {\n resolve();\n }\n };\n });\n }\n\n async *synthesizeStream(text: string, voice: string = 'en-US-JennyNeural', options: SynthesisOptions = {}): AsyncGenerator<Uint8Array, void, unknown> {\n this.audio_stream = [];\n\n const reqId = this.generateUUID();\n const secMsGEC = await this.generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN);\n\n const url = `${Constants.WSS_URL}?Ocp-Apim-Subscription-Key=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}&ConnectionId=${reqId}`;\n\n this.ws = new WebSocket(url);\n this.ws.binaryType = 'arraybuffer';\n\n const SSML_text = this.getSSML(text, voice, options);\n\n const queue: Uint8Array[] = [];\n let done = false;\n let error: Error | null = null;\n let notify: (() => void) | null = null;\n\n const push = (chunk: Uint8Array) => {\n queue.push(chunk);\n if (notify) {\n notify();\n notify = null;\n }\n };\n\n let timedOut = false;\n let inactivityTimeout: number;\n\n const resetInactivityTimeout = () => {\n clearTimeout(inactivityTimeout);\n inactivityTimeout = window.setTimeout(() => {\n timedOut = true;\n error = new Error(\"WebSocket inactivity timeout - no response from server\");\n done = true;\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close();\n }\n if (notify) {\n notify();\n notify = null;\n }\n }, 30000); // 30 seconds of inactivity\n };\n\n this.ws.onopen = () => {\n resetInactivityTimeout(); // start the inactivity timeout\n const message = this.buildTTSConfigMessage();\n this.ws!.send(message);\n\n const timestamp = this.nowRFC1123();\n const speechMessage = `X-RequestId:${reqId}\\r\\nContent-Type:application/ssml+xml\\r\\nX-Timestamp:${timestamp}\\r\\nPath:ssml\\r\\n\\r\\n${SSML_text}`;\n this.ws!.send(speechMessage);\n };\n\n this.ws.onmessage = (event) => {\n resetInactivityTimeout(); // restart inactivity timeout\n if (typeof event.data === 'string') {\n if (event.data.includes('Path:turn.end')) {\n this.ws?.close();\n }\n } else {\n const uint8Array = new Uint8Array(event.data);\n\n const needle = new TextEncoder().encode(\"Path:audio\\r\\n\");\n const audioStartIndex = this.indexOf(uint8Array, needle);\n\n if (audioStartIndex !== -1) {\n const audioChunk = uint8Array.slice(audioStartIndex + needle.length);\n this.audio_stream.push(audioChunk);\n push(audioChunk);\n }\n }\n };\n\n this.ws.onerror = (err: any) => {\n clearTimeout(inactivityTimeout);\n error = new Error('WebSocket error');\n done = true;\n if (notify) {\n notify();\n notify = null;\n }\n };\n\n this.ws.onclose = () => {\n clearTimeout(inactivityTimeout);\n done = true;\n if (notify) {\n notify();\n notify = null;\n }\n };\n\n while (!done || queue.length > 0) {\n if (queue.length === 0) {\n await new Promise<void>(resolve => (notify = resolve));\n continue;\n }\n const chunk = queue.shift();\n if (chunk) {\n yield chunk;\n }\n }\n\n if (error) {\n throw error;\n }\n }\n\n private processAudioData(buffer: Uint8Array): void {\n const needle = new TextEncoder().encode(\"Path:audio\\r\\n\");\n const audioStartIndex = this.indexOf(buffer, needle);\n\n if (audioStartIndex !== -1) {\n const audioChunk = buffer.slice(audioStartIndex + needle.length);\n this.audio_stream.push(audioChunk);\n }\n }\n\n private indexOf(arr: Uint8Array, subarr: Uint8Array): number {\n for (let i = 0; i <= arr.length - subarr.length; i++) {\n let match = true;\n for (let j = 0; j < subarr.length; j++) {\n if (arr[i + j] !== subarr[j]) {\n match = false;\n break;\n }\n }\n if (match) return i;\n }\n return -1;\n }\n\n private async generateSecMsGec(trustedClientToken: string): Promise<string> {\n const now = this.nowRFC1123();\n const fixedDate = this.parseRFC1123(now);\n const ticks = Math.floor(fixedDate.getTime() / 1000) + 11644473600;\n const rounded = ticks - (ticks % 300);\n const windowsTicks = rounded * 10_000_000;\n\n const encoder = new TextEncoder();\n const data = encoder.encode(`${windowsTicks}${trustedClientToken}`);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n\n return Array.from(new Uint8Array(hashBuffer))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n .toUpperCase();\n }\n\n getAudioData(): Uint8Array {\n if (this.audio_stream.length === 0) {\n throw new Error(\"No audio data available\");\n }\n // When the service cannot speak the text it answers with a single empty\n // chunk, so the stream is not empty but the audio is. Checking the byte\n // count rather than the chunk count is what catches that.\n const totalLength = this.audio_stream.reduce((acc, chunk) => acc + chunk.length, 0);\n if (totalLength === 0) {\n throw new Error(\n \"The service returned no audio. Voices are locale specific, so a voice cannot \" +\n \"read text written in another script. Check that the voice matches the language \" +\n \"of the text.\"\n );\n }\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of this.audio_stream) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n }\n}\n", "export const Constants = {\n TRUSTED_CLIENT_TOKEN: '6A5AA1D4EAFF4E9FB37E23D68491D6F4',\n BASE_URL: 'https://speech.platform.bing.com/consumer/speech/synthesize/readaloud',\n // NOTE: token goes as Ocp-Apim-Subscription-Key here; Edge user agents only.\n WSS_URL: 'wss://api.msedgeservices.com/tts/cognitiveservices/websocket/v1',\n VOICES_URL: 'https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list',\n\n CHROMIUM_FULL_VERSION: '155.0.0.0',\n CHROMIUM_MAJOR_VERSION: '155',\n VERSION_MS_GEC: '1-155.0.4283.45',\n\n token32() {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n .toUpperCase();\n },\n\n getBaseHeaders() {\n return {\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36 Edg/155.0.0.0',\n 'Accept-Encoding': 'gzip, deflate, br, zstd',\n 'Accept-Language': 'en-US,en;q=0.9',\n 'Cookie': 'MUID=' + this.token32()\n };\n },\n\n WSS_HEADERS: {\n 'Pragma': 'no-cache',\n 'Cache-Control': 'no-cache',\n 'Origin': 'chrome-extension://jdiccldimpdaibmpdkjnbmckianbfold',\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36 Edg/155.0.0.0'\n },\n\n VOICE_HEADERS: {\n 'Sec-CH-UA': '\"Microsoft Edge\";v=\"155\", \"Chromium\";v=\"155\", \"Not(A:Brand\";v=\"24\"',\n 'Sec-CH-UA-Mobile': '?0',\n 'Sec-CH-UA-Platform': '\"Windows\"',\n 'Accept': '*/*',\n 'Sec-Fetch-Site': 'none',\n 'Sec-Fetch-Mode': 'cors',\n 'Sec-Fetch-Dest': 'empty'\n },\n\n // https://learn.microsoft.com/en-us/azure/ai-services/speech-service/rest-text-to-speech?tabs=nonstreaming\n OUTPUT_FORMAT: {\n 'AUDIO_24KHZ_48KBITRATE_MONO_MP3': 'audio-24khz-48kbitrate-mono-mp3',\n 'AUDIO_24KHZ_96KBITRATE_MONO_MP3': 'audio-24khz-96kbitrate-mono-mp3',\n 'WEBM_24KHZ_16BIT_MONO_OPUS': 'webm-24khz-16bit-mono-opus',\n }\n\n\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,25 +1,25 @@
1
- "use strict";var EdgeTTSModule=(()=>{var w=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var b=(o,e,t)=>e in o?w(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var O=(o,e)=>{for(var t in e)w(o,t,{get:e[t],enumerable:!0})},k=(o,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of M(e))!U.call(o,r)&&r!==t&&w(o,r,{get:()=>e[r],enumerable:!(s=v(e,r))||s.enumerable});return o};var L=o=>k(w({},"__esModule",{value:!0}),o);var E=(o,e,t)=>b(o,typeof e!="symbol"?e+"":e,t);var R={};O(R,{EdgeTTS:()=>x});var c={TRUSTED_CLIENT_TOKEN:"6A5AA1D4EAFF4E9FB37E23D68491D6F4",BASE_URL:"https://speech.platform.bing.com/consumer/speech/synthesize/readaloud",WSS_URL:"wss://speech.platform.bing.com/consumer/speech/synthesize/readaloud/edge/v1",VOICES_URL:"https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list",CHROMIUM_FULL_VERSION:"143.0.3650.75",CHROMIUM_MAJOR_VERSION:"143",VERSION_MS_GEC:"1-143.0.3650",token32(){let o=new Uint8Array(16);return crypto.getRandomValues(o),Array.from(o).map(e=>e.toString(16).padStart(2,"0")).join("").toUpperCase()},getBaseHeaders(){return{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0","Accept-Encoding":"gzip, deflate, br, zstd","Accept-Language":"en-US,en;q=0.9",Cookie:"MUID="+this.token32()}},WSS_HEADERS:{Pragma:"no-cache","Cache-Control":"no-cache",Origin:"chrome-extension://jdiccldimpdaibmpdkjnbmckianbfold","Sec-WebSocket-Protocol":"synthesize","Sec-WebSocket-Version":"13","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.3650.75 Safari/537.36 Edg/143.0.3650.75"},VOICE_HEADERS:{"Sec-CH-UA":'" Not;A Brand";v="99", "Microsoft Edge";v="143", "Chromium";v="143"',"Sec-CH-UA-Mobile":"?0",Accept:"*/*","Sec-Fetch-Site":"none","Sec-Fetch-Mode":"cors","Sec-Fetch-Dest":"empty"},OUTPUT_FORMAT:{AUDIO_24KHZ_48KBITRATE_MONO_MP3:"audio-24khz-48kbitrate-mono-mp3",AUDIO_24KHZ_96KBITRATE_MONO_MP3:"audio-24khz-96kbitrate-mono-mp3",WEBM_24KHZ_16BIT_MONO_OPUS:"webm-24khz-16bit-mono-opus"}};var x=class{constructor(){E(this,"audio_stream",[]);E(this,"ws")}async normalizeVoices(e){let t=[];for(let s of e||[]){let r=s?.ShortName||"",a=s?.Locale||"",u=r.replace(/^[a-z]{2}-[A-Z]{2}-/,"");u=u.replace(/NeuralHD$/,"").replace(/Neural$/,"").trim();let g=`${s?.Name||""} ${r}`,d=s?.VoiceType||(/NeuralHD/i.test(g)?"NeuralHD":"Neural"),h=s?.LocaleName||a||null,i=s?.DisplayName||s?.FriendlyName||u||r;i=i.replace(/^Microsoft\s+/i,""),i=i.split(" - ")[0].trim(),i=i.replace(/\s*Online\s*\(Natural\)\s*/i," "),i=i.replace(/\s*Online\s*/i," "),i=i.replace(/\s+/g," ").trim();let n=s?.VoiceTag&&typeof s.VoiceTag=="object"?s.VoiceTag:{},y=Array.isArray(n.TailoredScenarios)?n.TailoredScenarios:Array.isArray(n.ContentCategories)?n.ContentCategories:[],m=Array.isArray(n.VoicePersonalities)?n.VoicePersonalities:[];t.push({Name:r||s?.Name||"",DisplayName:i,LocalName:i,ShortName:r||s?.Name||"",Gender:s?.Gender??null,Locale:a||null,LocaleName:h,SecondaryLocaleList:Array.isArray(s?.SecondaryLocaleList)?s.SecondaryLocaleList:[],VoiceType:d,VoiceTag:{TailoredScenarios:y,VoicePersonalities:m},FriendlyName:`${i} (${d}) - ${h}`})}return t}async getVoices(){let e=await this.generateSecMsGec(c.TRUSTED_CLIENT_TOKEN),s=await(await fetch(`${c.VOICES_URL}?TrustedClientToken=${c.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${e}&Sec-MS-GEC-Version=${c.VERSION_MS_GEC}`,{headers:c.getBaseHeaders()})).json();return this.normalizeVoices(s.voices||[])}async getVoicesByLanguage(e){return(await this.getVoices()).filter(s=>s.Locale.startsWith(e))}async getVoicesByGender(e){return(await this.getVoices()).filter(s=>s.Gender===e)}generateUUID(){return"xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}validatePitch(e){return typeof e=="number"?e>=0?`+${e}Hz`:`${e}Hz`:e}validateRate(e){let t;return typeof e=="string"?t=parseFloat(e.replace("%","")):t=e,t>=0?`+${t}%`:`${t}%`}validateVolume(e){let t;return typeof e=="string"?t=parseInt(e.replace("%",""),10):t=e,`${t}%`}escapeXML(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}getSSML(e,t,s={}){let r=this.validatePitch(s.pitch??0),a=this.validateRate(s.rate??0),u=this.validateVolume(s.volume??0),g=this.escapeXML(e);return`<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="https://www.w3.org/2001/mstts" xml:lang="en-US">
2
- <voice name="${t}">
3
- <prosody pitch="${r}" rate="${a}" volume="${u}">
4
- ${g}
1
+ "use strict";var EdgeTTSModule=(()=>{var f=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var M=(o,e,s)=>e in o?f(o,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):o[e]=s;var U=(o,e)=>{for(var s in e)f(o,s,{get:e[s],enumerable:!0})},b=(o,e,s,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of v(e))!N.call(o,r)&&r!==s&&f(o,r,{get:()=>e[r],enumerable:!(t=A(e,r))||t.enumerable});return o};var O=o=>b(f({},"__esModule",{value:!0}),o);var E=(o,e,s)=>M(o,typeof e!="symbol"?e+"":e,s);var L={};U(L,{EdgeTTS:()=>x});var c={TRUSTED_CLIENT_TOKEN:"6A5AA1D4EAFF4E9FB37E23D68491D6F4",BASE_URL:"https://speech.platform.bing.com/consumer/speech/synthesize/readaloud",WSS_URL:"wss://api.msedgeservices.com/tts/cognitiveservices/websocket/v1",VOICES_URL:"https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list",CHROMIUM_FULL_VERSION:"155.0.0.0",CHROMIUM_MAJOR_VERSION:"155",VERSION_MS_GEC:"1-155.0.4283.45",token32(){let o=new Uint8Array(16);return crypto.getRandomValues(o),Array.from(o).map(e=>e.toString(16).padStart(2,"0")).join("").toUpperCase()},getBaseHeaders(){return{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36 Edg/155.0.0.0","Accept-Encoding":"gzip, deflate, br, zstd","Accept-Language":"en-US,en;q=0.9",Cookie:"MUID="+this.token32()}},WSS_HEADERS:{Pragma:"no-cache","Cache-Control":"no-cache",Origin:"chrome-extension://jdiccldimpdaibmpdkjnbmckianbfold","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36 Edg/155.0.0.0"},VOICE_HEADERS:{"Sec-CH-UA":'"Microsoft Edge";v="155", "Chromium";v="155", "Not(A:Brand";v="24"',"Sec-CH-UA-Mobile":"?0","Sec-CH-UA-Platform":'"Windows"',Accept:"*/*","Sec-Fetch-Site":"none","Sec-Fetch-Mode":"cors","Sec-Fetch-Dest":"empty"},OUTPUT_FORMAT:{AUDIO_24KHZ_48KBITRATE_MONO_MP3:"audio-24khz-48kbitrate-mono-mp3",AUDIO_24KHZ_96KBITRATE_MONO_MP3:"audio-24khz-96kbitrate-mono-mp3",WEBM_24KHZ_16BIT_MONO_OPUS:"webm-24khz-16bit-mono-opus"}};var x=class{constructor(){E(this,"audio_stream",[]);E(this,"ws")}async normalizeVoices(e){let s=[];for(let t of e||[]){let r=t?.ShortName||"",a=t?.Locale||"",l=r.replace(/^[a-z]{2}-[A-Z]{2}-/,"");l=l.replace(/NeuralHD$/,"").replace(/Neural$/,"").trim();let p=`${t?.Name||""} ${r}`,u=t?.VoiceType||(/NeuralHD/i.test(p)?"NeuralHD":"Neural"),m=t?.LocaleName||a||null,n=t?.DisplayName||t?.FriendlyName||l||r;n=n.replace(/^Microsoft\s+/i,""),n=n.split(" - ")[0].trim(),n=n.replace(/\s*Online\s*\(Natural\)\s*/i," "),n=n.replace(/\s*Online\s*/i," "),n=n.replace(/\s+/g," ").trim();let i=t?.VoiceTag&&typeof t.VoiceTag=="object"?t.VoiceTag:{},g=Array.isArray(i.TailoredScenarios)?i.TailoredScenarios:Array.isArray(i.ContentCategories)?i.ContentCategories:[],d=Array.isArray(i.VoicePersonalities)?i.VoicePersonalities:[];s.push({Name:r||t?.Name||"",DisplayName:n,LocalName:n,ShortName:r||t?.Name||"",Gender:t?.Gender??null,Locale:a||null,LocaleName:m,SecondaryLocaleList:Array.isArray(t?.SecondaryLocaleList)?t.SecondaryLocaleList:[],VoiceType:u,VoiceTag:{TailoredScenarios:g,VoicePersonalities:d},FriendlyName:`${n} (${u}) - ${m}`})}return s}async getVoices(){let e=await this.generateSecMsGec(c.TRUSTED_CLIENT_TOKEN),t=await(await fetch(`${c.VOICES_URL}?TrustedClientToken=${c.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${e}&Sec-MS-GEC-Version=${c.VERSION_MS_GEC}`,{headers:c.getBaseHeaders()})).json(),r=Array.isArray(t)?t:t?.voices||[];return this.normalizeVoices(r)}async getVoicesByLanguage(e){return(await this.getVoices()).filter(t=>t.Locale.startsWith(e))}async getVoicesByGender(e){return(await this.getVoices()).filter(t=>t.Gender===e)}generateUUID(){return"xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){let s=Math.random()*16|0;return(e==="x"?s:s&3|8).toString(16)})}validatePitch(e){return typeof e=="number"?e>=0?`+${e}Hz`:`${e}Hz`:e}validateRate(e){let s;return typeof e=="string"?s=parseFloat(e.replace("%","")):s=e,s>=0?`+${s}%`:`${s}%`}validateVolume(e){let s;return typeof e=="string"?s=parseInt(e.replace("%",""),10):s=e,`${s}%`}escapeXML(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}getSSML(e,s,t={}){let r=this.validatePitch(t.pitch??0),a=this.validateRate(t.rate??0),l=this.validateVolume(t.volume??0),p=this.escapeXML(e);return`<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="https://www.w3.org/2001/mstts" xml:lang="en-US">
2
+ <voice name="${s}">
3
+ <prosody pitch="${r}" rate="${a}" volume="${l}">
4
+ ${p}
5
5
  </prosody>
6
6
  </voice>
7
7
  </speak>`}nowRFC1123(){return new Date().toUTCString()}parseRFC1123(e){return new Date(e)}buildTTSConfigMessage(){return`X-Timestamp:${this.nowRFC1123()}\r
8
8
  Content-Type:application/json; charset=utf-8\r
9
9
  Path:speech.config\r
10
10
  \r
11
- {"context":{"synthesis":{"audio":{"metadataoptions":{"sentenceBoundaryEnabled":false,"wordBoundaryEnabled":true},"outputFormat":"audio-24khz-48kbitrate-mono-mp3"}}}}`}async synthesize(e,t="en-US-JennyNeural",s={}){let r=await this.generateSecMsGec(c.TRUSTED_CLIENT_TOKEN);return new Promise((a,u)=>{this.audio_stream=[];let g=this.generateUUID(),d=`${c.WSS_URL}?TrustedClientToken=${c.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${r}&Sec-MS-GEC-Version=${c.VERSION_MS_GEC}&ConnectionId=${g}`;this.ws=new WebSocket(d);let h=this.getSSML(e,t,s),i=!1,n,y=()=>{clearTimeout(n),n=window.setTimeout(()=>{i=!0,this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.close(),u(new Error("WebSocket inactivity timeout - no response from server"))},3e4)};this.ws.onopen=()=>{y();let m=this.buildTTSConfigMessage();this.ws.send(m);let p=this.nowRFC1123(),f=`X-RequestId:${g}\r
11
+ {"context":{"synthesis":{"audio":{"metadataoptions":{"sentenceBoundaryEnabled":false,"wordBoundaryEnabled":true},"outputFormat":"audio-24khz-48kbitrate-mono-mp3"}}}}`}async synthesize(e,s="en-US-JennyNeural",t={}){let r=await this.generateSecMsGec(c.TRUSTED_CLIENT_TOKEN);return new Promise((a,l)=>{this.audio_stream=[];let p=this.generateUUID(),u=`${c.WSS_URL}?Ocp-Apim-Subscription-Key=${c.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${r}&Sec-MS-GEC-Version=${c.VERSION_MS_GEC}&ConnectionId=${p}`;this.ws=new WebSocket(u),this.ws.binaryType="arraybuffer";let m=this.getSSML(e,s,t),n=!1,i,g=()=>{clearTimeout(i),i=window.setTimeout(()=>{n=!0,this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.close(),l(new Error("WebSocket inactivity timeout - no response from server"))},3e4)};this.ws.onopen=()=>{g();let d=this.buildTTSConfigMessage();this.ws.send(d);let S=this.nowRFC1123(),w=`X-RequestId:${p}\r
12
12
  Content-Type:application/ssml+xml\r
13
- X-Timestamp:${p}\r
13
+ X-Timestamp:${S}\r
14
14
  Path:ssml\r
15
15
  \r
16
- ${h}`;this.ws.send(f)},this.ws.onmessage=m=>{if(y(),typeof m.data=="string")m.data.includes("Path:turn.end")&&this.ws?.close();else{let p=new FileReader;p.onload=()=>{let f=p.result,l=new Uint8Array(f);this.processAudioData(l)},p.readAsArrayBuffer(m.data)}},this.ws.onerror=m=>{clearTimeout(n),this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.close(),u(new Error("WebSocket error"))},this.ws.onclose=()=>{clearTimeout(n),i||a()}})}async*synthesizeStream(e,t="en-US-JennyNeural",s={}){this.audio_stream=[];let r=this.generateUUID(),a=await this.generateSecMsGec(c.TRUSTED_CLIENT_TOKEN),u=`${c.WSS_URL}?TrustedClientToken=${c.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${a}&Sec-MS-GEC-Version=${c.VERSION_MS_GEC}&ConnectionId=${r}`;this.ws=new WebSocket(u);let g=this.getSSML(e,t,s),d=[],h=!1,i=null,n=null,y=l=>{d.push(l),n&&(n(),n=null)},m=!1,p,f=()=>{clearTimeout(p),p=window.setTimeout(()=>{m=!0,i=new Error("WebSocket inactivity timeout - no response from server"),h=!0,this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.close(),n&&(n(),n=null)},3e4)};for(this.ws.onopen=()=>{f();let l=this.buildTTSConfigMessage();this.ws.send(l);let S=this.nowRFC1123(),T=`X-RequestId:${r}\r
16
+ ${m}`;this.ws.send(w)},this.ws.onmessage=d=>{g(),typeof d.data=="string"?d.data.includes("Path:turn.end")&&this.ws?.close():this.processAudioData(new Uint8Array(d.data))},this.ws.onerror=d=>{clearTimeout(i),this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.close(),l(new Error("WebSocket error"))},this.ws.onclose=()=>{clearTimeout(i),n||a()}})}async*synthesizeStream(e,s="en-US-JennyNeural",t={}){this.audio_stream=[];let r=this.generateUUID(),a=await this.generateSecMsGec(c.TRUSTED_CLIENT_TOKEN),l=`${c.WSS_URL}?Ocp-Apim-Subscription-Key=${c.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${a}&Sec-MS-GEC-Version=${c.VERSION_MS_GEC}&ConnectionId=${r}`;this.ws=new WebSocket(l),this.ws.binaryType="arraybuffer";let p=this.getSSML(e,s,t),u=[],m=!1,n=null,i=null,g=h=>{u.push(h),i&&(i(),i=null)},d=!1,S,w=()=>{clearTimeout(S),S=window.setTimeout(()=>{d=!0,n=new Error("WebSocket inactivity timeout - no response from server"),m=!0,this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.close(),i&&(i(),i=null)},3e4)};for(this.ws.onopen=()=>{w();let h=this.buildTTSConfigMessage();this.ws.send(h);let y=this.nowRFC1123(),T=`X-RequestId:${r}\r
17
17
  Content-Type:application/ssml+xml\r
18
- X-Timestamp:${S}\r
18
+ X-Timestamp:${y}\r
19
19
  Path:ssml\r
20
20
  \r
21
- ${g}`;this.ws.send(T)},this.ws.onmessage=l=>{if(f(),typeof l.data=="string")l.data.includes("Path:turn.end")&&this.ws?.close();else{let S=new FileReader;S.onload=()=>{let T=S.result,C=new Uint8Array(T),A=new TextEncoder().encode(`Path:audio\r
22
- `),_=this.indexOf(C,A);if(_!==-1){let N=C.slice(_+A.length);this.audio_stream.push(N),y(N)}},S.readAsArrayBuffer(l.data)}},this.ws.onerror=l=>{clearTimeout(p),i=new Error("WebSocket error"),h=!0,n&&(n(),n=null)},this.ws.onclose=()=>{clearTimeout(p),h=!0,n&&(n(),n=null)};!h||d.length>0;){if(d.length===0){await new Promise(S=>n=S);continue}let l=d.shift();l&&(yield l)}if(i)throw i}processAudioData(e){let t=new TextEncoder().encode(`Path:audio\r
23
- `),s=this.indexOf(e,t);if(s!==-1){let r=e.slice(s+t.length);this.audio_stream.push(r)}}indexOf(e,t){for(let s=0;s<=e.length-t.length;s++){let r=!0;for(let a=0;a<t.length;a++)if(e[s+a]!==t[a]){r=!1;break}if(r)return s}return-1}async generateSecMsGec(e){let t=this.nowRFC1123(),s=this.parseRFC1123(t),r=Math.floor(s.getTime()/1e3)+11644473600,u=(r-r%300)*1e7,d=new TextEncoder().encode(`${u}${e}`),h=await crypto.subtle.digest("SHA-256",d);return Array.from(new Uint8Array(h)).map(i=>i.toString(16).padStart(2,"0")).join("").toUpperCase()}getAudioData(){if(this.audio_stream.length===0)throw new Error("No audio data available");let e=this.audio_stream.reduce((r,a)=>r+a.length,0);if(e===0)throw new Error("The service returned no audio. Voices are locale specific, so a voice cannot read text written in another script. Check that the voice matches the language of the text.");let t=new Uint8Array(e),s=0;for(let r of this.audio_stream)t.set(r,s),s+=r.length;return t}};return L(R);})();
21
+ ${p}`;this.ws.send(T)},this.ws.onmessage=h=>{if(w(),typeof h.data=="string")h.data.includes("Path:turn.end")&&this.ws?.close();else{let y=new Uint8Array(h.data),T=new TextEncoder().encode(`Path:audio\r
22
+ `),C=this.indexOf(y,T);if(C!==-1){let _=y.slice(C+T.length);this.audio_stream.push(_),g(_)}}},this.ws.onerror=h=>{clearTimeout(S),n=new Error("WebSocket error"),m=!0,i&&(i(),i=null)},this.ws.onclose=()=>{clearTimeout(S),m=!0,i&&(i(),i=null)};!m||u.length>0;){if(u.length===0){await new Promise(y=>i=y);continue}let h=u.shift();h&&(yield h)}if(n)throw n}processAudioData(e){let s=new TextEncoder().encode(`Path:audio\r
23
+ `),t=this.indexOf(e,s);if(t!==-1){let r=e.slice(t+s.length);this.audio_stream.push(r)}}indexOf(e,s){for(let t=0;t<=e.length-s.length;t++){let r=!0;for(let a=0;a<s.length;a++)if(e[t+a]!==s[a]){r=!1;break}if(r)return t}return-1}async generateSecMsGec(e){let s=this.nowRFC1123(),t=this.parseRFC1123(s),r=Math.floor(t.getTime()/1e3)+11644473600,l=(r-r%300)*1e7,u=new TextEncoder().encode(`${l}${e}`),m=await crypto.subtle.digest("SHA-256",u);return Array.from(new Uint8Array(m)).map(n=>n.toString(16).padStart(2,"0")).join("").toUpperCase()}getAudioData(){if(this.audio_stream.length===0)throw new Error("No audio data available");let e=this.audio_stream.reduce((r,a)=>r+a.length,0);if(e===0)throw new Error("The service returned no audio. Voices are locale specific, so a voice cannot read text written in another script. Check that the voice matches the language of the text.");let s=new Uint8Array(e),t=0;for(let r of this.audio_stream)s.set(r,t),t+=r.length;return s}};return O(L);})();
24
24
  window.EdgeTTS = EdgeTTSModule.EdgeTTS; window.EdgeTTSVoice = EdgeTTSModule.Voice;
25
25
  //# sourceMappingURL=edge-tts.umd.min.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/browser/EdgeTTS.browser.ts", "../../src/config/constants.ts"],
4
- "sourcesContent": ["import { Constants } from '../config/constants';\n\nexport interface Voice {\n Name: string;\n ShortName: string;\n Gender: string;\n Locale: string;\n FriendlyName: string;\n LocalName: string;\n}\n\nexport interface SynthesisOptions {\n pitch?: string | number;\n rate?: string | number;\n volume?: string | number;\n}\n\nexport class EdgeTTS {\n private audio_stream: Uint8Array[] = [];\n private ws?: WebSocket;\n\n\n async normalizeVoices(data: any[]): Promise<Voice[]> {\n const out = [];\n for (const v of data || []) {\n const short = v?.ShortName || \"\";\n const locale = v?.Locale || \"\";\n\n // base: remove locale prefix and Neural/NeuralHD suffix\n let base = short.replace(/^[a-z]{2}-[A-Z]{2}-/, \"\");\n base = base.replace(/NeuralHD$/, \"\").replace(/Neural$/, \"\").trim();\n\n // VoiceType: if NeuralHD/Neural in Name or ShortName\n const mix = `${v?.Name || \"\"} ${short}`;\n const voiceType =\n v?.VoiceType || (/NeuralHD/i.test(mix) ? \"NeuralHD\" : \"Neural\");\n\n // LocaleName: prefer LocaleName -> LanguageName -> locale\n const localeName = v?.LocaleName || (locale || null);\n\n // DisplayName: prefer DisplayName -> FriendlyName -> base -> short\n let display = v?.DisplayName || v?.FriendlyName || base || short;\n display = display.replace(/^Microsoft\\s+/i, \"\");\n display = display.split(\" - \")[0].trim();\n\n display = display.replace(/\\s*Online\\s*\\(Natural\\)\\s*/i, \" \");\n display = display.replace(/\\s*Online\\s*/i, \" \");\n display = display.replace(/\\s+/g, \" \").trim();\n\n // VoiceTag parsing\n const tag = (v?.VoiceTag && typeof v.VoiceTag === \"object\") ? v.VoiceTag : {};\n const tailored = Array.isArray(tag.TailoredScenarios)\n ? tag.TailoredScenarios\n : (Array.isArray(tag.ContentCategories) ? tag.ContentCategories : []);\n const personalities = Array.isArray(tag.VoicePersonalities)\n ? tag.VoicePersonalities\n : [];\n\n out.push({\n Name: short || (v?.Name || \"\"),\n DisplayName: display,\n LocalName: display,\n ShortName: short || (v?.Name || \"\"),\n Gender: v?.Gender ?? null,\n Locale: locale || null,\n LocaleName: localeName,\n SecondaryLocaleList: Array.isArray(v?.SecondaryLocaleList) ? v.SecondaryLocaleList : [],\n VoiceType: voiceType,\n VoiceTag: {\n TailoredScenarios: tailored,\n VoicePersonalities: personalities,\n },\n FriendlyName: `${display} (${voiceType}) - ${localeName}`,\n });\n }\n\n return out;\n }\n\n async getVoices(): Promise<Voice[]> {\n const secMsGEC = await this.generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN);\n\n const response = await fetch(\n `${Constants.VOICES_URL}?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}`,\n { headers: Constants.getBaseHeaders() }\n );\n\n const data = await response.json();\n return this.normalizeVoices(data.voices || []);\n }\n\n async getVoicesByLanguage(locale: string): Promise<Voice[]> {\n const voices = await this.getVoices();\n return voices.filter(voice => voice.Locale.startsWith(locale));\n }\n\n async getVoicesByGender(gender: 'Male' | 'Female'): Promise<Voice[]> {\n const voices = await this.getVoices();\n return voices.filter(voice => voice.Gender === gender);\n }\n\n private generateUUID(): string {\n return 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n }\n\n private validatePitch(pitch: string | number): string {\n if (typeof pitch === 'number') {\n return (pitch >= 0 ? `+${pitch}Hz` : `${pitch}Hz`);\n }\n return pitch;\n }\n\n private validateRate(rate: string | number): string {\n let rateValue: number;\n if (typeof rate === 'string') {\n rateValue = parseFloat(rate.replace('%', ''));\n } else {\n rateValue = rate;\n }\n return rateValue >= 0 ? `+${rateValue}%` : `${rateValue}%`;\n }\n\n private validateVolume(volume: string | number): string {\n let volumeValue: number;\n if (typeof volume === 'string') {\n volumeValue = parseInt(volume.replace('%', ''), 10);\n } else {\n volumeValue = volume;\n }\n return `${volumeValue}%`;\n }\n\n private escapeXML(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n }\n\n private getSSML(content: string, voice: string, options: SynthesisOptions = {}): string { \n const pitch = this.validatePitch(options.pitch ?? 0);\n const rate = this.validateRate(options.rate ?? 0);\n const volume = this.validateVolume(options.volume ?? 0);\n const escapedText = this.escapeXML(content);\n\n return `<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xmlns:mstts=\"https://www.w3.org/2001/mstts\" xml:lang=\"en-US\">\n <voice name=\"${voice}\">\n <prosody pitch=\"${pitch}\" rate=\"${rate}\" volume=\"${volume}\">\n ${escapedText}\n </prosody>\n </voice>\n </speak>`;\n }\n\n private nowRFC1123(): string {\n return new Date().toUTCString();\n }\n\n private parseRFC1123(rfcStr: string): Date {\n return new Date(rfcStr);\n }\n\n private buildTTSConfigMessage(): string {\n const timestamp = this.nowRFC1123();\n return `X-Timestamp:${timestamp}\\r\\nContent-Type:application/json; charset=utf-8\\r\\nPath:speech.config\\r\\n\\r\\n` +\n `{\"context\":{\"synthesis\":{\"audio\":{\"metadataoptions\":{\"sentenceBoundaryEnabled\":false,\"wordBoundaryEnabled\":true},\"outputFormat\":\"audio-24khz-48kbitrate-mono-mp3\"}}}}`;\n }\n\n async synthesize(text: string, voice: string = 'en-US-JennyNeural', options: SynthesisOptions = {}): Promise<void> {\n const secMsGEC = await this.generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN);\n\n return new Promise((resolve, reject) => {\n this.audio_stream = [];\n const reqId = this.generateUUID();\n const url = `${Constants.WSS_URL}?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}&ConnectionId=${reqId}`;\n\n this.ws = new WebSocket(url);\n\n const SSML_text = this.getSSML(text, voice, options);\n\n let timedOut = false;\n let inactivityTimeout: number;\n\n const resetInactivityTimeout = () => {\n clearTimeout(inactivityTimeout);\n inactivityTimeout = window.setTimeout(() => {\n timedOut = true;\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close();\n }\n reject(new Error(\"WebSocket inactivity timeout - no response from server\"));\n }, 30000); // 30 seconds of inactivity\n };\n\n this.ws.onopen = () => {\n resetInactivityTimeout(); // start the inactivity timeout\n const message = this.buildTTSConfigMessage();\n this.ws!.send(message);\n const timestamp = this.nowRFC1123();\n const speechMessage = `X-RequestId:${reqId}\\r\\nContent-Type:application/ssml+xml\\r\\nX-Timestamp:${timestamp}\\r\\nPath:ssml\\r\\n\\r\\n${SSML_text}`;\n this.ws!.send(speechMessage);\n };\n\n this.ws.onmessage = (event) => {\n resetInactivityTimeout(); // restart inactivity timeout \n if (typeof event.data === 'string') {\n if (event.data.includes('Path:turn.end')) {\n this.ws?.close();\n }\n } else {\n const reader = new FileReader();\n reader.onload = () => {\n const arrayBuffer = reader.result as ArrayBuffer;\n const uint8Array = new Uint8Array(arrayBuffer);\n this.processAudioData(uint8Array);\n };\n reader.readAsArrayBuffer(event.data);\n }\n };\n\n this.ws.onerror = (err: any) => {\n clearTimeout(inactivityTimeout);\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close();\n }\n reject(new Error('WebSocket error'));\n };\n\n this.ws.onclose = () => {\n clearTimeout(inactivityTimeout);\n if (!timedOut) {\n resolve();\n }\n };\n });\n }\n\n async *synthesizeStream(text: string, voice: string = 'en-US-JennyNeural', options: SynthesisOptions = {}): AsyncGenerator<Uint8Array, void, unknown> {\n this.audio_stream = [];\n\n const reqId = this.generateUUID();\n const secMsGEC = await this.generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN);\n\n const url = `${Constants.WSS_URL}?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}&ConnectionId=${reqId}`;\n\n this.ws = new WebSocket(url);\n\n const SSML_text = this.getSSML(text, voice, options);\n\n const queue: Uint8Array[] = [];\n let done = false;\n let error: Error | null = null;\n let notify: (() => void) | null = null;\n\n const push = (chunk: Uint8Array) => {\n queue.push(chunk);\n if (notify) {\n notify();\n notify = null;\n }\n };\n\n let timedOut = false;\n let inactivityTimeout: number;\n\n const resetInactivityTimeout = () => {\n clearTimeout(inactivityTimeout);\n inactivityTimeout = window.setTimeout(() => {\n timedOut = true;\n error = new Error(\"WebSocket inactivity timeout - no response from server\");\n done = true;\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close();\n }\n if (notify) {\n notify();\n notify = null;\n }\n }, 30000); // 30 seconds of inactivity\n };\n\n this.ws.onopen = () => {\n resetInactivityTimeout(); // start the inactivity timeout\n const message = this.buildTTSConfigMessage();\n this.ws!.send(message);\n\n const timestamp = this.nowRFC1123();\n const speechMessage = `X-RequestId:${reqId}\\r\\nContent-Type:application/ssml+xml\\r\\nX-Timestamp:${timestamp}\\r\\nPath:ssml\\r\\n\\r\\n${SSML_text}`;\n this.ws!.send(speechMessage);\n };\n\n this.ws.onmessage = (event) => {\n resetInactivityTimeout(); // restart inactivity timeout\n if (typeof event.data === 'string') {\n if (event.data.includes('Path:turn.end')) {\n this.ws?.close();\n }\n } else {\n const reader = new FileReader();\n reader.onload = () => {\n const arrayBuffer = reader.result as ArrayBuffer;\n const uint8Array = new Uint8Array(arrayBuffer);\n\n const needle = new TextEncoder().encode(\"Path:audio\\r\\n\");\n const audioStartIndex = this.indexOf(uint8Array, needle);\n\n if (audioStartIndex !== -1) {\n const audioChunk = uint8Array.slice(audioStartIndex + needle.length);\n this.audio_stream.push(audioChunk);\n push(audioChunk);\n }\n };\n reader.readAsArrayBuffer(event.data);\n }\n };\n\n this.ws.onerror = (err: any) => {\n clearTimeout(inactivityTimeout);\n error = new Error('WebSocket error');\n done = true;\n if (notify) {\n notify();\n notify = null;\n }\n };\n\n this.ws.onclose = () => {\n clearTimeout(inactivityTimeout);\n done = true;\n if (notify) {\n notify();\n notify = null;\n }\n };\n\n while (!done || queue.length > 0) {\n if (queue.length === 0) {\n await new Promise<void>(resolve => (notify = resolve));\n continue;\n }\n const chunk = queue.shift();\n if (chunk) {\n yield chunk;\n }\n }\n\n if (error) {\n throw error;\n }\n }\n\n private processAudioData(buffer: Uint8Array): void {\n const needle = new TextEncoder().encode(\"Path:audio\\r\\n\");\n const audioStartIndex = this.indexOf(buffer, needle);\n\n if (audioStartIndex !== -1) {\n const audioChunk = buffer.slice(audioStartIndex + needle.length);\n this.audio_stream.push(audioChunk);\n }\n }\n\n private indexOf(arr: Uint8Array, subarr: Uint8Array): number {\n for (let i = 0; i <= arr.length - subarr.length; i++) {\n let match = true;\n for (let j = 0; j < subarr.length; j++) {\n if (arr[i + j] !== subarr[j]) {\n match = false;\n break;\n }\n }\n if (match) return i;\n }\n return -1;\n }\n\n private async generateSecMsGec(trustedClientToken: string): Promise<string> {\n const now = this.nowRFC1123();\n const fixedDate = this.parseRFC1123(now);\n const ticks = Math.floor(fixedDate.getTime() / 1000) + 11644473600;\n const rounded = ticks - (ticks % 300);\n const windowsTicks = rounded * 10_000_000;\n\n const encoder = new TextEncoder();\n const data = encoder.encode(`${windowsTicks}${trustedClientToken}`);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n\n return Array.from(new Uint8Array(hashBuffer))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n .toUpperCase();\n }\n\n getAudioData(): Uint8Array {\n if (this.audio_stream.length === 0) {\n throw new Error(\"No audio data available\");\n }\n // When the service cannot speak the text it answers with a single empty\n // chunk, so the stream is not empty but the audio is. Checking the byte\n // count rather than the chunk count is what catches that.\n const totalLength = this.audio_stream.reduce((acc, chunk) => acc + chunk.length, 0);\n if (totalLength === 0) {\n throw new Error(\n \"The service returned no audio. Voices are locale specific, so a voice cannot \" +\n \"read text written in another script. Check that the voice matches the language \" +\n \"of the text.\"\n );\n }\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of this.audio_stream) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n }\n}\n", "export const Constants = {\n TRUSTED_CLIENT_TOKEN: '6A5AA1D4EAFF4E9FB37E23D68491D6F4',\n BASE_URL: 'https://speech.platform.bing.com/consumer/speech/synthesize/readaloud',\n WSS_URL: 'wss://speech.platform.bing.com/consumer/speech/synthesize/readaloud/edge/v1',\n VOICES_URL: 'https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list',\n\n CHROMIUM_FULL_VERSION: '143.0.3650.75',\n CHROMIUM_MAJOR_VERSION: '143',\n VERSION_MS_GEC: '1-143.0.3650',\n\n token32() {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n .toUpperCase();\n },\n\n getBaseHeaders() {\n return {\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0',\n 'Accept-Encoding': 'gzip, deflate, br, zstd',\n 'Accept-Language': 'en-US,en;q=0.9',\n 'Cookie': 'MUID=' + this.token32()\n };\n },\n\n WSS_HEADERS: {\n 'Pragma': 'no-cache',\n 'Cache-Control': 'no-cache',\n 'Origin': 'chrome-extension://jdiccldimpdaibmpdkjnbmckianbfold',\n 'Sec-WebSocket-Protocol': 'synthesize',\n 'Sec-WebSocket-Version': '13',\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.3650.75 Safari/537.36 Edg/143.0.3650.75'\n },\n\n VOICE_HEADERS: {\n 'Sec-CH-UA': '\" Not;A Brand\";v=\"99\", \"Microsoft Edge\";v=\"143\", \"Chromium\";v=\"143\"',\n 'Sec-CH-UA-Mobile': '?0',\n 'Accept': '*/*',\n 'Sec-Fetch-Site': 'none',\n 'Sec-Fetch-Mode': 'cors',\n 'Sec-Fetch-Dest': 'empty'\n },\n\n // https://learn.microsoft.com/en-us/azure/ai-services/speech-service/rest-text-to-speech?tabs=nonstreaming\n OUTPUT_FORMAT: {\n 'AUDIO_24KHZ_48KBITRATE_MONO_MP3': 'audio-24khz-48kbitrate-mono-mp3',\n 'AUDIO_24KHZ_96KBITRATE_MONO_MP3': 'audio-24khz-96kbitrate-mono-mp3',\n 'WEBM_24KHZ_16BIT_MONO_OPUS': 'webm-24khz-16bit-mono-opus',\n }\n\n\n};\n"],
5
- "mappings": "ykBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,ICAO,IAAMC,EAAY,CACrB,qBAAsB,mCACtB,SAAU,wEACV,QAAS,8EACT,WAAY,oFAEZ,sBAAuB,gBACvB,uBAAwB,MACxB,eAAgB,eAEhB,SAAU,CACN,IAAMC,EAAQ,IAAI,WAAW,EAAE,EAC/B,cAAO,gBAAgBA,CAAK,EAErB,MAAM,KAAKA,CAAK,EAClB,IAAIC,GAAKA,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EACxC,KAAK,EAAE,EACP,YAAY,CACrB,EAEA,gBAAiB,CACb,MAAO,CACH,aAAc,gIACd,kBAAmB,0BACnB,kBAAmB,iBACnB,OAAU,QAAU,KAAK,QAAQ,CACrC,CACJ,EAEA,YAAa,CACT,OAAU,WACV,gBAAiB,WACjB,OAAU,sDACV,yBAA0B,aAC1B,wBAAyB,KACzB,aAAc,uIAClB,EAEA,cAAe,CACX,YAAa,sEACb,mBAAoB,KACpB,OAAU,MACV,iBAAkB,OAClB,iBAAkB,OAClB,iBAAkB,OACtB,EAGA,cAAe,CACX,gCAAmC,kCACnC,gCAAmC,kCACnC,2BAA8B,4BAClC,CAGJ,EDtCO,IAAMC,EAAN,KAAc,CAAd,cACHC,EAAA,KAAQ,eAA6B,CAAC,GACtCA,EAAA,KAAQ,MAGR,MAAM,gBAAgBC,EAA+B,CACjD,IAAMC,EAAM,CAAC,EACb,QAAWC,KAAKF,GAAQ,CAAC,EAAG,CACxB,IAAMG,EAAQD,GAAG,WAAa,GACxBE,EAASF,GAAG,QAAU,GAGxBG,EAAOF,EAAM,QAAQ,sBAAuB,EAAE,EAClDE,EAAOA,EAAK,QAAQ,YAAa,EAAE,EAAE,QAAQ,UAAW,EAAE,EAAE,KAAK,EAGjE,IAAMC,EAAM,GAAGJ,GAAG,MAAQ,EAAE,IAAIC,CAAK,GAC/BI,EACFL,GAAG,YAAc,YAAY,KAAKI,CAAG,EAAI,WAAa,UAGpDE,EAAaN,GAAG,YAAeE,GAAU,KAG3CK,EAAUP,GAAG,aAAeA,GAAG,cAAgBG,GAAQF,EAC3DM,EAAUA,EAAQ,QAAQ,iBAAkB,EAAE,EAC9CA,EAAUA,EAAQ,MAAM,KAAK,EAAE,CAAC,EAAE,KAAK,EAEvCA,EAAUA,EAAQ,QAAQ,8BAA+B,GAAG,EAC5DA,EAAUA,EAAQ,QAAQ,gBAAiB,GAAG,EAC9CA,EAAUA,EAAQ,QAAQ,OAAQ,GAAG,EAAE,KAAK,EAG5C,IAAMC,EAAOR,GAAG,UAAY,OAAOA,EAAE,UAAa,SAAYA,EAAE,SAAW,CAAC,EACtES,EAAW,MAAM,QAAQD,EAAI,iBAAiB,EAC9CA,EAAI,kBACH,MAAM,QAAQA,EAAI,iBAAiB,EAAIA,EAAI,kBAAoB,CAAC,EACjEE,EAAgB,MAAM,QAAQF,EAAI,kBAAkB,EACpDA,EAAI,mBACJ,CAAC,EAEPT,EAAI,KAAK,CACL,KAAME,GAAUD,GAAG,MAAQ,GAC3B,YAAaO,EACb,UAAWA,EACX,UAAWN,GAAUD,GAAG,MAAQ,GAChC,OAAQA,GAAG,QAAU,KACrB,OAAQE,GAAU,KAClB,WAAYI,EACZ,oBAAqB,MAAM,QAAQN,GAAG,mBAAmB,EAAIA,EAAE,oBAAsB,CAAC,EACtF,UAAWK,EACX,SAAU,CACN,kBAAmBI,EACnB,mBAAoBC,CACxB,EACA,aAAc,GAAGH,CAAO,KAAKF,CAAS,OAAOC,CAAU,EAC3D,CAAC,CACL,CAEA,OAAOP,CACX,CAEA,MAAM,WAA8B,CAChC,IAAMY,EAAW,MAAM,KAAK,iBAAiBC,EAAU,oBAAoB,EAOrEd,EAAO,MALI,MAAM,MACnB,GAAGc,EAAU,UAAU,uBAAuBA,EAAU,oBAAoB,eAAeD,CAAQ,uBAAuBC,EAAU,cAAc,GAClJ,CAAE,QAASA,EAAU,eAAe,CAAE,CAC1C,GAE4B,KAAK,EACjC,OAAO,KAAK,gBAAgBd,EAAK,QAAU,CAAC,CAAC,CACjD,CAEA,MAAM,oBAAoBI,EAAkC,CAExD,OADe,MAAM,KAAK,UAAU,GACtB,OAAOW,GAASA,EAAM,OAAO,WAAWX,CAAM,CAAC,CACjE,CAEA,MAAM,kBAAkBY,EAA6C,CAEjE,OADe,MAAM,KAAK,UAAU,GACtB,OAAOD,GAASA,EAAM,SAAWC,CAAM,CACzD,CAEQ,cAAuB,CAC3B,MAAO,uCAAuC,QAAQ,QAAS,SAAUC,EAAG,CACxE,IAAMC,EAAI,KAAK,OAAO,EAAI,GAAK,EAE/B,OADUD,IAAM,IAAMC,EAAKA,EAAI,EAAM,GAC5B,SAAS,EAAE,CACxB,CAAC,CACL,CAEQ,cAAcC,EAAgC,CAClD,OAAI,OAAOA,GAAU,SACTA,GAAS,EAAI,IAAIA,CAAK,KAAO,GAAGA,CAAK,KAE1CA,CACX,CAEQ,aAAaC,EAA+B,CAChD,IAAIC,EACJ,OAAI,OAAOD,GAAS,SAChBC,EAAY,WAAWD,EAAK,QAAQ,IAAK,EAAE,CAAC,EAE5CC,EAAYD,EAETC,GAAa,EAAI,IAAIA,CAAS,IAAM,GAAGA,CAAS,GAC3D,CAEQ,eAAeC,EAAiC,CACpD,IAAIC,EACJ,OAAI,OAAOD,GAAW,SAClBC,EAAc,SAASD,EAAO,QAAQ,IAAK,EAAE,EAAG,EAAE,EAElDC,EAAcD,EAEX,GAAGC,CAAW,GACzB,CAEQ,UAAUC,EAAsB,CACpC,OAAOA,EACF,QAAQ,KAAM,OAAO,EACrB,QAAQ,KAAM,MAAM,EACpB,QAAQ,KAAM,MAAM,EACpB,QAAQ,KAAM,QAAQ,EACtB,QAAQ,KAAM,QAAQ,CAC/B,CAEQ,QAAQC,EAAiBV,EAAeW,EAA4B,CAAC,EAAW,CACpF,IAAMP,EAAQ,KAAK,cAAcO,EAAQ,OAAS,CAAC,EAC7CN,EAAO,KAAK,aAAaM,EAAQ,MAAQ,CAAC,EAC1CJ,EAAS,KAAK,eAAeI,EAAQ,QAAU,CAAC,EAChDC,EAAc,KAAK,UAAUF,CAAO,EAE1C,MAAO;AAAA,mCACoBV,CAAK;AAAA,0CACEI,CAAK,WAAWC,CAAI,aAAaE,CAAM;AAAA,8BACnDK,CAAW;AAAA;AAAA;AAAA,yBAIrC,CAEQ,YAAqB,CACzB,OAAO,IAAI,KAAK,EAAE,YAAY,CAClC,CAEQ,aAAaC,EAAsB,CACvC,OAAO,IAAI,KAAKA,CAAM,CAC1B,CAEQ,uBAAgC,CAEpC,MAAO,eADW,KAAK,WAAW,CACH;AAAA;AAAA;AAAA;AAAA,sKAEnC,CAEA,MAAM,WAAWJ,EAAcT,EAAgB,oBAAqBW,EAA4B,CAAC,EAAkB,CAC/G,IAAMb,EAAW,MAAM,KAAK,iBAAiBC,EAAU,oBAAoB,EAE3E,OAAO,IAAI,QAAQ,CAACe,EAASC,IAAW,CACpC,KAAK,aAAe,CAAC,EACrB,IAAMC,EAAQ,KAAK,aAAa,EAC1BC,EAAM,GAAGlB,EAAU,OAAO,uBAAuBA,EAAU,oBAAoB,eAAeD,CAAQ,uBAAuBC,EAAU,cAAc,iBAAiBiB,CAAK,GAEjL,KAAK,GAAK,IAAI,UAAUC,CAAG,EAE3B,IAAMC,EAAY,KAAK,QAAQT,EAAMT,EAAOW,CAAO,EAE/CQ,EAAW,GACXC,EAEEC,EAAyB,IAAM,CACjC,aAAaD,CAAiB,EAC9BA,EAAoB,OAAO,WAAW,IAAM,CACxCD,EAAW,GACP,KAAK,IAAM,KAAK,GAAG,aAAe,UAAU,MAC5C,KAAK,GAAG,MAAM,EAElBJ,EAAO,IAAI,MAAM,wDAAwD,CAAC,CAC9E,EAAG,GAAK,CACZ,EAEA,KAAK,GAAG,OAAS,IAAM,CACnBM,EAAuB,EACvB,IAAMC,EAAU,KAAK,sBAAsB,EAC3C,KAAK,GAAI,KAAKA,CAAO,EACrB,IAAMC,EAAY,KAAK,WAAW,EAC5BC,EAAgB,eAAeR,CAAK;AAAA;AAAA,cAAwDO,CAAS;AAAA;AAAA;AAAA,EAAwBL,CAAS,GAC5I,KAAK,GAAI,KAAKM,CAAa,CAC/B,EAEA,KAAK,GAAG,UAAaC,GAAU,CAE3B,GADAJ,EAAuB,EACnB,OAAOI,EAAM,MAAS,SAClBA,EAAM,KAAK,SAAS,eAAe,GACnC,KAAK,IAAI,MAAM,MAEhB,CACH,IAAMC,EAAS,IAAI,WACnBA,EAAO,OAAS,IAAM,CAClB,IAAMC,EAAcD,EAAO,OACrBE,EAAa,IAAI,WAAWD,CAAW,EAC7C,KAAK,iBAAiBC,CAAU,CACpC,EACAF,EAAO,kBAAkBD,EAAM,IAAI,CACvC,CACJ,EAEA,KAAK,GAAG,QAAWI,GAAa,CAC5B,aAAaT,CAAiB,EAC1B,KAAK,IAAM,KAAK,GAAG,aAAe,UAAU,MAC5C,KAAK,GAAG,MAAM,EAElBL,EAAO,IAAI,MAAM,iBAAiB,CAAC,CACvC,EAEA,KAAK,GAAG,QAAU,IAAM,CACpB,aAAaK,CAAiB,EACzBD,GACDL,EAAQ,CAEhB,CACJ,CAAC,CACL,CAEA,MAAO,iBAAiBL,EAAcT,EAAgB,oBAAqBW,EAA4B,CAAC,EAA8C,CAClJ,KAAK,aAAe,CAAC,EAErB,IAAMK,EAAQ,KAAK,aAAa,EAC1BlB,EAAW,MAAM,KAAK,iBAAiBC,EAAU,oBAAoB,EAErEkB,EAAM,GAAGlB,EAAU,OAAO,uBAAuBA,EAAU,oBAAoB,eAAeD,CAAQ,uBAAuBC,EAAU,cAAc,iBAAiBiB,CAAK,GAEjL,KAAK,GAAK,IAAI,UAAUC,CAAG,EAE3B,IAAMC,EAAY,KAAK,QAAQT,EAAMT,EAAOW,CAAO,EAE7CmB,EAAsB,CAAC,EACzBC,EAAO,GACPC,EAAsB,KACtBC,EAA8B,KAE5BC,EAAQC,GAAsB,CAChCL,EAAM,KAAKK,CAAK,EACZF,IACAA,EAAO,EACPA,EAAS,KAEjB,EAEId,EAAW,GACXC,EAEEC,EAAyB,IAAM,CACjC,aAAaD,CAAiB,EAC9BA,EAAoB,OAAO,WAAW,IAAM,CACxCD,EAAW,GACXa,EAAQ,IAAI,MAAM,wDAAwD,EAC1ED,EAAO,GACH,KAAK,IAAM,KAAK,GAAG,aAAe,UAAU,MAC5C,KAAK,GAAG,MAAM,EAEdE,IACAA,EAAO,EACPA,EAAS,KAEjB,EAAG,GAAK,CACZ,EAwDA,IAtDA,KAAK,GAAG,OAAS,IAAM,CACnBZ,EAAuB,EACvB,IAAMC,EAAU,KAAK,sBAAsB,EAC3C,KAAK,GAAI,KAAKA,CAAO,EAErB,IAAMC,EAAY,KAAK,WAAW,EAC5BC,EAAgB,eAAeR,CAAK;AAAA;AAAA,cAAwDO,CAAS;AAAA;AAAA;AAAA,EAAwBL,CAAS,GAC5I,KAAK,GAAI,KAAKM,CAAa,CAC/B,EAEA,KAAK,GAAG,UAAaC,GAAU,CAE3B,GADAJ,EAAuB,EACnB,OAAOI,EAAM,MAAS,SAClBA,EAAM,KAAK,SAAS,eAAe,GACnC,KAAK,IAAI,MAAM,MAEhB,CACH,IAAMC,EAAS,IAAI,WACnBA,EAAO,OAAS,IAAM,CAClB,IAAMC,EAAcD,EAAO,OACrBE,EAAa,IAAI,WAAWD,CAAW,EAEvCS,EAAS,IAAI,YAAY,EAAE,OAAO;AAAA,CAAgB,EAClDC,EAAkB,KAAK,QAAQT,EAAYQ,CAAM,EAEvD,GAAIC,IAAoB,GAAI,CACxB,IAAMC,EAAaV,EAAW,MAAMS,EAAkBD,EAAO,MAAM,EACnE,KAAK,aAAa,KAAKE,CAAU,EACjCJ,EAAKI,CAAU,CACnB,CACJ,EACAZ,EAAO,kBAAkBD,EAAM,IAAI,CACvC,CACJ,EAEA,KAAK,GAAG,QAAWI,GAAa,CAC5B,aAAaT,CAAiB,EAC9BY,EAAQ,IAAI,MAAM,iBAAiB,EACnCD,EAAO,GACHE,IACAA,EAAO,EACPA,EAAS,KAEjB,EAEA,KAAK,GAAG,QAAU,IAAM,CACpB,aAAab,CAAiB,EAC9BW,EAAO,GACHE,IACAA,EAAO,EACPA,EAAS,KAEjB,EAEO,CAACF,GAAQD,EAAM,OAAS,GAAG,CAC9B,GAAIA,EAAM,SAAW,EAAG,CACpB,MAAM,IAAI,QAAchB,GAAYmB,EAASnB,CAAQ,EACrD,QACJ,CACA,IAAMqB,EAAQL,EAAM,MAAM,EACtBK,IACA,MAAMA,EAEd,CAEA,GAAIH,EACA,MAAMA,CAEd,CAEQ,iBAAiBO,EAA0B,CAC/C,IAAMH,EAAS,IAAI,YAAY,EAAE,OAAO;AAAA,CAAgB,EAClDC,EAAkB,KAAK,QAAQE,EAAQH,CAAM,EAEnD,GAAIC,IAAoB,GAAI,CACxB,IAAMC,EAAaC,EAAO,MAAMF,EAAkBD,EAAO,MAAM,EAC/D,KAAK,aAAa,KAAKE,CAAU,CACrC,CACJ,CAEQ,QAAQE,EAAiBC,EAA4B,CACzD,QAASC,EAAI,EAAGA,GAAKF,EAAI,OAASC,EAAO,OAAQC,IAAK,CAClD,IAAIC,EAAQ,GACZ,QAASC,EAAI,EAAGA,EAAIH,EAAO,OAAQG,IAC/B,GAAIJ,EAAIE,EAAIE,CAAC,IAAMH,EAAOG,CAAC,EAAG,CAC1BD,EAAQ,GACR,KACJ,CAEJ,GAAIA,EAAO,OAAOD,CACtB,CACA,MAAO,EACX,CAEA,MAAc,iBAAiBG,EAA6C,CACxE,IAAMC,EAAM,KAAK,WAAW,EACtBC,EAAY,KAAK,aAAaD,CAAG,EACjCE,EAAQ,KAAK,MAAMD,EAAU,QAAQ,EAAI,GAAI,EAAI,YAEjDE,GADUD,EAASA,EAAQ,KACF,IAGzB/D,EADU,IAAI,YAAY,EACX,OAAO,GAAGgE,CAAY,GAAGJ,CAAkB,EAAE,EAC5DK,EAAa,MAAM,OAAO,OAAO,OAAO,UAAWjE,CAAI,EAE7D,OAAO,MAAM,KAAK,IAAI,WAAWiE,CAAU,CAAC,EACvC,IAAIC,GAAKA,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EACxC,KAAK,EAAE,EACP,YAAY,CACrB,CAEA,cAA2B,CACvB,GAAI,KAAK,aAAa,SAAW,EAC7B,MAAM,IAAI,MAAM,yBAAyB,EAK7C,IAAMC,EAAc,KAAK,aAAa,OAAO,CAACC,EAAKlB,IAAUkB,EAAMlB,EAAM,OAAQ,CAAC,EAClF,GAAIiB,IAAgB,EAChB,MAAM,IAAI,MACN,0KAGJ,EAEJ,IAAME,EAAS,IAAI,WAAWF,CAAW,EACrCG,EAAS,EACb,QAAWpB,KAAS,KAAK,aACrBmB,EAAO,IAAInB,EAAOoB,CAAM,EACxBA,GAAUpB,EAAM,OAEpB,OAAOmB,CACX,CACJ",
6
- "names": ["EdgeTTS_browser_exports", "__export", "EdgeTTS", "Constants", "bytes", "b", "EdgeTTS", "__publicField", "data", "out", "v", "short", "locale", "base", "mix", "voiceType", "localeName", "display", "tag", "tailored", "personalities", "secMsGEC", "Constants", "voice", "gender", "c", "r", "pitch", "rate", "rateValue", "volume", "volumeValue", "text", "content", "options", "escapedText", "rfcStr", "resolve", "reject", "reqId", "url", "SSML_text", "timedOut", "inactivityTimeout", "resetInactivityTimeout", "message", "timestamp", "speechMessage", "event", "reader", "arrayBuffer", "uint8Array", "err", "queue", "done", "error", "notify", "push", "chunk", "needle", "audioStartIndex", "audioChunk", "buffer", "arr", "subarr", "i", "match", "j", "trustedClientToken", "now", "fixedDate", "ticks", "windowsTicks", "hashBuffer", "b", "totalLength", "acc", "result", "offset"]
4
+ "sourcesContent": ["import { Constants } from '../config/constants';\n\nexport interface Voice {\n Name: string;\n ShortName: string;\n Gender: string;\n Locale: string;\n FriendlyName: string;\n LocalName: string;\n}\n\nexport interface SynthesisOptions {\n pitch?: string | number;\n rate?: string | number;\n volume?: string | number;\n}\n\nexport class EdgeTTS {\n private audio_stream: Uint8Array[] = [];\n private ws?: WebSocket;\n\n\n async normalizeVoices(data: any[]): Promise<Voice[]> {\n const out = [];\n for (const v of data || []) {\n const short = v?.ShortName || \"\";\n const locale = v?.Locale || \"\";\n\n // base: remove locale prefix and Neural/NeuralHD suffix\n let base = short.replace(/^[a-z]{2}-[A-Z]{2}-/, \"\");\n base = base.replace(/NeuralHD$/, \"\").replace(/Neural$/, \"\").trim();\n\n // VoiceType: if NeuralHD/Neural in Name or ShortName\n const mix = `${v?.Name || \"\"} ${short}`;\n const voiceType =\n v?.VoiceType || (/NeuralHD/i.test(mix) ? \"NeuralHD\" : \"Neural\");\n\n // LocaleName: prefer LocaleName -> LanguageName -> locale\n const localeName = v?.LocaleName || (locale || null);\n\n // DisplayName: prefer DisplayName -> FriendlyName -> base -> short\n let display = v?.DisplayName || v?.FriendlyName || base || short;\n display = display.replace(/^Microsoft\\s+/i, \"\");\n display = display.split(\" - \")[0].trim();\n\n display = display.replace(/\\s*Online\\s*\\(Natural\\)\\s*/i, \" \");\n display = display.replace(/\\s*Online\\s*/i, \" \");\n display = display.replace(/\\s+/g, \" \").trim();\n\n // VoiceTag parsing\n const tag = (v?.VoiceTag && typeof v.VoiceTag === \"object\") ? v.VoiceTag : {};\n const tailored = Array.isArray(tag.TailoredScenarios)\n ? tag.TailoredScenarios\n : (Array.isArray(tag.ContentCategories) ? tag.ContentCategories : []);\n const personalities = Array.isArray(tag.VoicePersonalities)\n ? tag.VoicePersonalities\n : [];\n\n out.push({\n Name: short || (v?.Name || \"\"),\n DisplayName: display,\n LocalName: display,\n ShortName: short || (v?.Name || \"\"),\n Gender: v?.Gender ?? null,\n Locale: locale || null,\n LocaleName: localeName,\n SecondaryLocaleList: Array.isArray(v?.SecondaryLocaleList) ? v.SecondaryLocaleList : [],\n VoiceType: voiceType,\n VoiceTag: {\n TailoredScenarios: tailored,\n VoicePersonalities: personalities,\n },\n FriendlyName: `${display} (${voiceType}) - ${localeName}`,\n });\n }\n\n return out;\n }\n\n async getVoices(): Promise<Voice[]> {\n const secMsGEC = await this.generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN);\n\n const response = await fetch(\n `${Constants.VOICES_URL}?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}`,\n { headers: Constants.getBaseHeaders() }\n );\n\n const data = await response.json();\n // The readaloud endpoint returns a bare array, not { voices: [...] }.\n // Reading `data.voices` unconditionally yielded zero voices even on a\n // successful 200 response. Both shapes are accepted now.\n const voices = Array.isArray(data) ? data : (data?.voices || []);\n return this.normalizeVoices(voices);\n }\n\n async getVoicesByLanguage(locale: string): Promise<Voice[]> {\n const voices = await this.getVoices();\n return voices.filter(voice => voice.Locale.startsWith(locale));\n }\n\n async getVoicesByGender(gender: 'Male' | 'Female'): Promise<Voice[]> {\n const voices = await this.getVoices();\n return voices.filter(voice => voice.Gender === gender);\n }\n\n private generateUUID(): string {\n return 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n }\n\n private validatePitch(pitch: string | number): string {\n if (typeof pitch === 'number') {\n return (pitch >= 0 ? `+${pitch}Hz` : `${pitch}Hz`);\n }\n return pitch;\n }\n\n private validateRate(rate: string | number): string {\n let rateValue: number;\n if (typeof rate === 'string') {\n rateValue = parseFloat(rate.replace('%', ''));\n } else {\n rateValue = rate;\n }\n return rateValue >= 0 ? `+${rateValue}%` : `${rateValue}%`;\n }\n\n private validateVolume(volume: string | number): string {\n let volumeValue: number;\n if (typeof volume === 'string') {\n volumeValue = parseInt(volume.replace('%', ''), 10);\n } else {\n volumeValue = volume;\n }\n return `${volumeValue}%`;\n }\n\n private escapeXML(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n }\n\n private getSSML(content: string, voice: string, options: SynthesisOptions = {}): string { \n const pitch = this.validatePitch(options.pitch ?? 0);\n const rate = this.validateRate(options.rate ?? 0);\n const volume = this.validateVolume(options.volume ?? 0);\n const escapedText = this.escapeXML(content);\n\n return `<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xmlns:mstts=\"https://www.w3.org/2001/mstts\" xml:lang=\"en-US\">\n <voice name=\"${voice}\">\n <prosody pitch=\"${pitch}\" rate=\"${rate}\" volume=\"${volume}\">\n ${escapedText}\n </prosody>\n </voice>\n </speak>`;\n }\n\n private nowRFC1123(): string {\n return new Date().toUTCString();\n }\n\n private parseRFC1123(rfcStr: string): Date {\n return new Date(rfcStr);\n }\n\n private buildTTSConfigMessage(): string {\n const timestamp = this.nowRFC1123();\n return `X-Timestamp:${timestamp}\\r\\nContent-Type:application/json; charset=utf-8\\r\\nPath:speech.config\\r\\n\\r\\n` +\n `{\"context\":{\"synthesis\":{\"audio\":{\"metadataoptions\":{\"sentenceBoundaryEnabled\":false,\"wordBoundaryEnabled\":true},\"outputFormat\":\"audio-24khz-48kbitrate-mono-mp3\"}}}}`;\n }\n\n async synthesize(text: string, voice: string = 'en-US-JennyNeural', options: SynthesisOptions = {}): Promise<void> {\n const secMsGEC = await this.generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN);\n\n return new Promise((resolve, reject) => {\n this.audio_stream = [];\n const reqId = this.generateUUID();\n const url = `${Constants.WSS_URL}?Ocp-Apim-Subscription-Key=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}&ConnectionId=${reqId}`;\n\n this.ws = new WebSocket(url);\n this.ws.binaryType = 'arraybuffer';\n\n const SSML_text = this.getSSML(text, voice, options);\n\n let timedOut = false;\n let inactivityTimeout: number;\n\n const resetInactivityTimeout = () => {\n clearTimeout(inactivityTimeout);\n inactivityTimeout = window.setTimeout(() => {\n timedOut = true;\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close();\n }\n reject(new Error(\"WebSocket inactivity timeout - no response from server\"));\n }, 30000); // 30 seconds of inactivity\n };\n\n this.ws.onopen = () => {\n resetInactivityTimeout(); // start the inactivity timeout\n const message = this.buildTTSConfigMessage();\n this.ws!.send(message);\n const timestamp = this.nowRFC1123();\n const speechMessage = `X-RequestId:${reqId}\\r\\nContent-Type:application/ssml+xml\\r\\nX-Timestamp:${timestamp}\\r\\nPath:ssml\\r\\n\\r\\n${SSML_text}`;\n this.ws!.send(speechMessage);\n };\n\n this.ws.onmessage = (event) => {\n resetInactivityTimeout(); // restart inactivity timeout \n if (typeof event.data === 'string') {\n if (event.data.includes('Path:turn.end')) {\n this.ws?.close();\n }\n } else {\n this.processAudioData(new Uint8Array(event.data));\n }\n };\n\n this.ws.onerror = (err: any) => {\n clearTimeout(inactivityTimeout);\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close();\n }\n reject(new Error('WebSocket error'));\n };\n\n this.ws.onclose = () => {\n clearTimeout(inactivityTimeout);\n if (!timedOut) {\n resolve();\n }\n };\n });\n }\n\n async *synthesizeStream(text: string, voice: string = 'en-US-JennyNeural', options: SynthesisOptions = {}): AsyncGenerator<Uint8Array, void, unknown> {\n this.audio_stream = [];\n\n const reqId = this.generateUUID();\n const secMsGEC = await this.generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN);\n\n const url = `${Constants.WSS_URL}?Ocp-Apim-Subscription-Key=${Constants.TRUSTED_CLIENT_TOKEN}&Sec-MS-GEC=${secMsGEC}&Sec-MS-GEC-Version=${Constants.VERSION_MS_GEC}&ConnectionId=${reqId}`;\n\n this.ws = new WebSocket(url);\n this.ws.binaryType = 'arraybuffer';\n\n const SSML_text = this.getSSML(text, voice, options);\n\n const queue: Uint8Array[] = [];\n let done = false;\n let error: Error | null = null;\n let notify: (() => void) | null = null;\n\n const push = (chunk: Uint8Array) => {\n queue.push(chunk);\n if (notify) {\n notify();\n notify = null;\n }\n };\n\n let timedOut = false;\n let inactivityTimeout: number;\n\n const resetInactivityTimeout = () => {\n clearTimeout(inactivityTimeout);\n inactivityTimeout = window.setTimeout(() => {\n timedOut = true;\n error = new Error(\"WebSocket inactivity timeout - no response from server\");\n done = true;\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close();\n }\n if (notify) {\n notify();\n notify = null;\n }\n }, 30000); // 30 seconds of inactivity\n };\n\n this.ws.onopen = () => {\n resetInactivityTimeout(); // start the inactivity timeout\n const message = this.buildTTSConfigMessage();\n this.ws!.send(message);\n\n const timestamp = this.nowRFC1123();\n const speechMessage = `X-RequestId:${reqId}\\r\\nContent-Type:application/ssml+xml\\r\\nX-Timestamp:${timestamp}\\r\\nPath:ssml\\r\\n\\r\\n${SSML_text}`;\n this.ws!.send(speechMessage);\n };\n\n this.ws.onmessage = (event) => {\n resetInactivityTimeout(); // restart inactivity timeout\n if (typeof event.data === 'string') {\n if (event.data.includes('Path:turn.end')) {\n this.ws?.close();\n }\n } else {\n const uint8Array = new Uint8Array(event.data);\n\n const needle = new TextEncoder().encode(\"Path:audio\\r\\n\");\n const audioStartIndex = this.indexOf(uint8Array, needle);\n\n if (audioStartIndex !== -1) {\n const audioChunk = uint8Array.slice(audioStartIndex + needle.length);\n this.audio_stream.push(audioChunk);\n push(audioChunk);\n }\n }\n };\n\n this.ws.onerror = (err: any) => {\n clearTimeout(inactivityTimeout);\n error = new Error('WebSocket error');\n done = true;\n if (notify) {\n notify();\n notify = null;\n }\n };\n\n this.ws.onclose = () => {\n clearTimeout(inactivityTimeout);\n done = true;\n if (notify) {\n notify();\n notify = null;\n }\n };\n\n while (!done || queue.length > 0) {\n if (queue.length === 0) {\n await new Promise<void>(resolve => (notify = resolve));\n continue;\n }\n const chunk = queue.shift();\n if (chunk) {\n yield chunk;\n }\n }\n\n if (error) {\n throw error;\n }\n }\n\n private processAudioData(buffer: Uint8Array): void {\n const needle = new TextEncoder().encode(\"Path:audio\\r\\n\");\n const audioStartIndex = this.indexOf(buffer, needle);\n\n if (audioStartIndex !== -1) {\n const audioChunk = buffer.slice(audioStartIndex + needle.length);\n this.audio_stream.push(audioChunk);\n }\n }\n\n private indexOf(arr: Uint8Array, subarr: Uint8Array): number {\n for (let i = 0; i <= arr.length - subarr.length; i++) {\n let match = true;\n for (let j = 0; j < subarr.length; j++) {\n if (arr[i + j] !== subarr[j]) {\n match = false;\n break;\n }\n }\n if (match) return i;\n }\n return -1;\n }\n\n private async generateSecMsGec(trustedClientToken: string): Promise<string> {\n const now = this.nowRFC1123();\n const fixedDate = this.parseRFC1123(now);\n const ticks = Math.floor(fixedDate.getTime() / 1000) + 11644473600;\n const rounded = ticks - (ticks % 300);\n const windowsTicks = rounded * 10_000_000;\n\n const encoder = new TextEncoder();\n const data = encoder.encode(`${windowsTicks}${trustedClientToken}`);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n\n return Array.from(new Uint8Array(hashBuffer))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n .toUpperCase();\n }\n\n getAudioData(): Uint8Array {\n if (this.audio_stream.length === 0) {\n throw new Error(\"No audio data available\");\n }\n // When the service cannot speak the text it answers with a single empty\n // chunk, so the stream is not empty but the audio is. Checking the byte\n // count rather than the chunk count is what catches that.\n const totalLength = this.audio_stream.reduce((acc, chunk) => acc + chunk.length, 0);\n if (totalLength === 0) {\n throw new Error(\n \"The service returned no audio. Voices are locale specific, so a voice cannot \" +\n \"read text written in another script. Check that the voice matches the language \" +\n \"of the text.\"\n );\n }\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of this.audio_stream) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n }\n}\n", "export const Constants = {\n TRUSTED_CLIENT_TOKEN: '6A5AA1D4EAFF4E9FB37E23D68491D6F4',\n BASE_URL: 'https://speech.platform.bing.com/consumer/speech/synthesize/readaloud',\n // NOTE: token goes as Ocp-Apim-Subscription-Key here; Edge user agents only.\n WSS_URL: 'wss://api.msedgeservices.com/tts/cognitiveservices/websocket/v1',\n VOICES_URL: 'https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list',\n\n CHROMIUM_FULL_VERSION: '155.0.0.0',\n CHROMIUM_MAJOR_VERSION: '155',\n VERSION_MS_GEC: '1-155.0.4283.45',\n\n token32() {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n .toUpperCase();\n },\n\n getBaseHeaders() {\n return {\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36 Edg/155.0.0.0',\n 'Accept-Encoding': 'gzip, deflate, br, zstd',\n 'Accept-Language': 'en-US,en;q=0.9',\n 'Cookie': 'MUID=' + this.token32()\n };\n },\n\n WSS_HEADERS: {\n 'Pragma': 'no-cache',\n 'Cache-Control': 'no-cache',\n 'Origin': 'chrome-extension://jdiccldimpdaibmpdkjnbmckianbfold',\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36 Edg/155.0.0.0'\n },\n\n VOICE_HEADERS: {\n 'Sec-CH-UA': '\"Microsoft Edge\";v=\"155\", \"Chromium\";v=\"155\", \"Not(A:Brand\";v=\"24\"',\n 'Sec-CH-UA-Mobile': '?0',\n 'Sec-CH-UA-Platform': '\"Windows\"',\n 'Accept': '*/*',\n 'Sec-Fetch-Site': 'none',\n 'Sec-Fetch-Mode': 'cors',\n 'Sec-Fetch-Dest': 'empty'\n },\n\n // https://learn.microsoft.com/en-us/azure/ai-services/speech-service/rest-text-to-speech?tabs=nonstreaming\n OUTPUT_FORMAT: {\n 'AUDIO_24KHZ_48KBITRATE_MONO_MP3': 'audio-24khz-48kbitrate-mono-mp3',\n 'AUDIO_24KHZ_96KBITRATE_MONO_MP3': 'audio-24khz-96kbitrate-mono-mp3',\n 'WEBM_24KHZ_16BIT_MONO_OPUS': 'webm-24khz-16bit-mono-opus',\n }\n\n\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["EdgeTTS_browser_exports", "__export", "EdgeTTS", "Constants", "bytes", "b", "EdgeTTS", "__publicField", "data", "out", "v", "short", "locale", "base", "mix", "voiceType", "localeName", "display", "tag", "tailored", "personalities", "secMsGEC", "Constants", "voices", "voice", "gender", "c", "r", "pitch", "rate", "rateValue", "volume", "volumeValue", "text", "content", "options", "escapedText", "rfcStr", "resolve", "reject", "reqId", "url", "SSML_text", "timedOut", "inactivityTimeout", "resetInactivityTimeout", "message", "timestamp", "speechMessage", "event", "err", "queue", "done", "error", "notify", "push", "chunk", "uint8Array", "needle", "audioStartIndex", "audioChunk", "buffer", "arr", "subarr", "i", "match", "j", "trustedClientToken", "now", "fixedDate", "ticks", "windowsTicks", "hashBuffer", "b", "totalLength", "acc", "result", "offset"]
7
7
  }
@@ -6,13 +6,10 @@ 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.8.1')
9
+ .version('1.8.3')
10
10
  .addCommand(SynthesizeCommand_1.SynthesizeCommand)
11
11
  .addCommand(VoiceListCommand_1.VoiceListCommand);
12
- try {
13
- program.parse();
14
- }
15
- catch (error) {
12
+ program.parseAsync().catch((error) => {
16
13
  console.error(`Error: ${error.message}`);
17
14
  process.exit(1);
18
- }
15
+ });
@@ -8,7 +8,7 @@ exports.VoiceListCommand = new commander_1.Command('voice-list')
8
8
  .action(async () => {
9
9
  const tts = new EdgeTTS_1.EdgeTTS();
10
10
  const voices = await tts.getVoices();
11
- console.log('Lista de voces disponibles:');
11
+ console.log('Available voices:');
12
12
  voices.forEach((voice) => {
13
13
  console.log(` - ${voice.ShortName}`);
14
14
  });
@@ -17,13 +17,12 @@ export declare const Constants: {
17
17
  Pragma: string;
18
18
  'Cache-Control': string;
19
19
  Origin: string;
20
- 'Sec-WebSocket-Protocol': string;
21
- 'Sec-WebSocket-Version': string;
22
20
  'User-Agent': string;
23
21
  };
24
22
  VOICE_HEADERS: {
25
23
  'Sec-CH-UA': string;
26
24
  'Sec-CH-UA-Mobile': string;
25
+ 'Sec-CH-UA-Platform': string;
27
26
  Accept: string;
28
27
  'Sec-Fetch-Site': string;
29
28
  'Sec-Fetch-Mode': string;
@@ -4,11 +4,12 @@ exports.Constants = void 0;
4
4
  exports.Constants = {
5
5
  TRUSTED_CLIENT_TOKEN: '6A5AA1D4EAFF4E9FB37E23D68491D6F4',
6
6
  BASE_URL: 'https://speech.platform.bing.com/consumer/speech/synthesize/readaloud',
7
- WSS_URL: 'wss://speech.platform.bing.com/consumer/speech/synthesize/readaloud/edge/v1',
7
+ // NOTE: token goes as Ocp-Apim-Subscription-Key here; Edge user agents only.
8
+ WSS_URL: 'wss://api.msedgeservices.com/tts/cognitiveservices/websocket/v1',
8
9
  VOICES_URL: 'https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list',
9
- CHROMIUM_FULL_VERSION: '143.0.3650.75',
10
- CHROMIUM_MAJOR_VERSION: '143',
11
- VERSION_MS_GEC: '1-143.0.3650',
10
+ CHROMIUM_FULL_VERSION: '155.0.0.0',
11
+ CHROMIUM_MAJOR_VERSION: '155',
12
+ VERSION_MS_GEC: '1-155.0.4283.45',
12
13
  token32() {
13
14
  const bytes = new Uint8Array(16);
14
15
  crypto.getRandomValues(bytes);
@@ -19,7 +20,7 @@ exports.Constants = {
19
20
  },
20
21
  getBaseHeaders() {
21
22
  return {
22
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0',
23
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36 Edg/155.0.0.0',
23
24
  'Accept-Encoding': 'gzip, deflate, br, zstd',
24
25
  'Accept-Language': 'en-US,en;q=0.9',
25
26
  'Cookie': 'MUID=' + this.token32()
@@ -29,13 +30,12 @@ exports.Constants = {
29
30
  'Pragma': 'no-cache',
30
31
  'Cache-Control': 'no-cache',
31
32
  'Origin': 'chrome-extension://jdiccldimpdaibmpdkjnbmckianbfold',
32
- 'Sec-WebSocket-Protocol': 'synthesize',
33
- 'Sec-WebSocket-Version': '13',
34
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.3650.75 Safari/537.36 Edg/143.0.3650.75'
33
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36 Edg/155.0.0.0'
35
34
  },
36
35
  VOICE_HEADERS: {
37
- 'Sec-CH-UA': '" Not;A Brand";v="99", "Microsoft Edge";v="143", "Chromium";v="143"',
36
+ 'Sec-CH-UA': '"Microsoft Edge";v="155", "Chromium";v="155", "Not(A:Brand";v="24"',
38
37
  'Sec-CH-UA-Mobile': '?0',
38
+ 'Sec-CH-UA-Platform': '"Windows"',
39
39
  'Accept': '*/*',
40
40
  'Sec-Fetch-Site': 'none',
41
41
  'Sec-Fetch-Mode': 'cors',