@andresaya/edge-tts 1.9.0 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/core/crypto.ts", "../../src/config/constants.ts", "../../src/core/clock.ts", "../../src/core/errors.ts", "../../src/core/protocol.ts", "../../src/core/session.ts", "../../src/core/subtitles.ts", "../../src/core/base.ts", "../../src/browser/EdgeTTS.browser.ts"],
4
- "sourcesContent": ["export interface WebCrypto {\n getRandomValues<T extends Uint8Array>(array: T): T;\n subtle: { digest(algorithm: string, data: Uint8Array): Promise<ArrayBuffer> };\n}\n\nlet impl: WebCrypto | undefined;\n\nexport function setWebCrypto(crypto: WebCrypto): void {\n impl = crypto;\n}\n\nexport function webCrypto(): WebCrypto {\n const crypto = impl ?? (globalThis as { crypto?: WebCrypto }).crypto;\n if (!crypto) throw new Error('Web Crypto is not available in this environment');\n return crypto;\n}\n", "import { webCrypto } from '../core/crypto';\n\nexport 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 webCrypto().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", "let skewMs = 0;\n\nexport function now(): number {\n return Date.now() + skewMs;\n}\n\n// NOTE: the Date header has one-second resolution, so smaller differences are noise.\nexport function adjustClock(serverTimeMs: number): boolean {\n const delta = serverTimeMs - now();\n if (!Number.isFinite(delta) || Math.abs(delta) < 2000) return false;\n skewMs += delta;\n return true;\n}\n\nexport function resetClock(): void {\n skewMs = 0;\n}\n", "export type EdgeTTSErrorCode =\n | 'NO_AUDIO'\n | 'TIMEOUT'\n | 'HANDSHAKE'\n | 'NETWORK'\n | 'INVALID_OPTION'\n | 'VOICES';\n\nexport class EdgeTTSError extends Error {\n readonly code: EdgeTTSErrorCode;\n readonly status?: number;\n\n constructor(message: string, code: EdgeTTSErrorCode, options: { status?: number; cause?: unknown } = {}) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = 'EdgeTTSError';\n this.code = code;\n if (options.status !== undefined) this.status = options.status;\n }\n}\n", "import { webCrypto } from './crypto';\nimport type { SentenceBoundary, Voice, WordBoundary } from './types';\n\nexport const DEFAULT_OUTPUT_FORMAT = 'audio-24khz-48kbitrate-mono-mp3';\n\nconst decoder = new TextDecoder();\n\nexport function buildSynthesisUrl(base: string, token: string, secMsGec: string, version: string, connectionId: string): string {\n return `${base}?Ocp-Apim-Subscription-Key=${token}&Sec-MS-GEC=${secMsGec}&Sec-MS-GEC-Version=${version}&ConnectionId=${connectionId}`;\n}\n\nexport function buildConfigMessage(timestamp: string, outputFormat: string): string {\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\":true,\"wordBoundaryEnabled\":true},\"outputFormat\":\"${outputFormat}\"}}}}`;\n}\n\nexport function buildSSMLMessage(requestId: string, timestamp: string, ssml: string): string {\n return `X-RequestId:${requestId}\\r\\nContent-Type:application/ssml+xml\\r\\nX-Timestamp:${timestamp}\\r\\nPath:ssml\\r\\n\\r\\n${ssml}`;\n}\n\nexport function 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\nexport function buildSSML(text: string, voice: string, pitch: string, rate: string, volume: string): string {\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 ${escapeXML(text)}\n </prosody>\n </voice>\n </speak>`;\n}\n\nfunction headerPath(head: string): string {\n return /Path:([^\\r\\n]*)/i.exec(head)?.[1]?.trim() ?? '';\n}\n\nexport function parseTextFrame(text: string): { path: string; body: string } {\n const split = text.indexOf('\\r\\n\\r\\n');\n if (split === -1) return { path: headerPath(text), body: '' };\n return { path: headerPath(text.slice(0, split)), body: text.slice(split + 4) };\n}\n\nexport function parseBinaryFrame(data: Uint8Array): { path: string; body: Uint8Array } {\n if (data.length < 2) return { path: '', body: new Uint8Array(0) };\n const headerLength = (data[0] << 8) | data[1];\n return {\n path: headerPath(decoder.decode(data.subarray(2, 2 + headerLength))),\n body: data.slice(2 + headerLength),\n };\n}\n\nexport function parseMetadata(body: string): (WordBoundary | SentenceBoundary)[] {\n let metadata: any;\n try {\n metadata = JSON.parse(body);\n } catch {\n return [];\n }\n if (!Array.isArray(metadata?.Metadata)) return [];\n\n const boundaries: (WordBoundary | SentenceBoundary)[] = [];\n for (const item of metadata.Metadata) {\n if (item?.Type !== 'WordBoundary' && item?.Type !== 'SentenceBoundary') continue;\n boundaries.push({\n type: item.Type,\n offset: item.Data.Offset,\n duration: item.Data.Duration,\n text: item.Data.text?.Text,\n });\n }\n return boundaries;\n}\n\nconst OPENING_PUNCTUATION = '\u00BF\u00A1\u00AB\"\\'\u201C\u2018([';\n\n// NOTE: the service drops opening punctuation such as \u00BF and \u00A1 from sentence text.\nexport function sentenceTextRestorer(source: string): (text: string) => string {\n let cursor = 0;\n return (text) => {\n const index = text ? source.indexOf(text, cursor) : -1;\n if (index === -1) return text;\n let start = index;\n while (start > cursor && OPENING_PUNCTUATION.includes(source[start - 1])) start--;\n cursor = index + text.length;\n return source.slice(start, cursor);\n };\n}\n\nexport async function generateSecMsGec(trustedClientToken: string, nowMs: number): Promise<string> {\n const ticks = Math.floor(nowMs / 1000) + 11644473600;\n const rounded = ticks - (ticks % 300);\n const windowsTicks = rounded * 10_000_000;\n\n const data = new TextEncoder().encode(`${windowsTicks}${trustedClientToken}`);\n const hashBuffer = await webCrypto().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\nexport function 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\nexport function fileExtension(format: string): string {\n if (format.includes('mp3')) return 'mp3';\n if (format.includes('opus') && format.includes('webm')) return 'webm';\n if (format.includes('opus') && format.includes('ogg')) return 'ogg';\n if (format.includes('wav') || format.includes('riff')) return 'wav';\n if (format.includes('pcm') && format.includes('raw')) return 'pcm';\n if (format.includes('alaw')) return 'alaw';\n if (format.includes('mulaw')) return 'mulaw';\n if (format.includes('truesilk')) return 'silk';\n if (format.includes('g722')) return 'g722';\n if (format.includes('amr')) return 'amr';\n return 'audio';\n}\n\n// NOTE: MP3 is CBR; formats without a bitrate (opus) assume 48 kbit/s.\nexport function estimateDuration(bytes: number, outputFormat: string): number {\n const kbps = Number(/(\\d+)kbitrate/.exec(outputFormat)?.[1] ?? 48);\n return (bytes * 8) / (kbps * 1000);\n}\n\nexport function concatChunks(chunks: Uint8Array[]): Uint8Array {\n const result = new Uint8Array(chunks.reduce((total, chunk) => total + chunk.length, 0));\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n}\n\nexport function normalizeVoices(data: any[]): 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", "import { EdgeTTSError } from './errors';\nimport { parseBinaryFrame, parseMetadata, parseTextFrame } from './protocol';\nimport type { SentenceBoundary, WordBoundary } from './types';\n\nexport interface SocketLike {\n binaryType: string;\n readonly readyState: number;\n onopen: ((event: any) => void) | null;\n onmessage: ((event: { data: unknown }) => void) | null;\n onerror: ((event: any) => void) | null;\n onclose: ((event: any) => void) | null;\n send(data: string): void;\n close(): void;\n}\n\nexport interface SessionOptions {\n configMessage: string;\n ssmlMessage: string;\n timeout: number;\n signal?: AbortSignal;\n onAudio(chunk: Uint8Array): void;\n onBoundary(boundary: WordBoundary | SentenceBoundary): void;\n toError(event: unknown, opened: boolean): Error;\n}\n\nconst CONNECTING = 0;\nconst OPEN = 1;\n\nexport function abortReason(signal: AbortSignal): unknown {\n if (signal.reason !== undefined) return signal.reason;\n const error = new Error('This operation was aborted');\n error.name = 'AbortError';\n return error;\n}\n\nfunction toBytes(data: unknown): Uint8Array {\n if (data instanceof ArrayBuffer) return new Uint8Array(data);\n if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n return new Uint8Array(0);\n}\n\nexport function runSession(open: () => SocketLike, options: SessionOptions): Promise<void> {\n return new Promise((resolve, reject) => {\n if (options.signal?.aborted) {\n reject(abortReason(options.signal));\n return;\n }\n\n const socket = open();\n socket.binaryType = 'arraybuffer';\n\n let settled = false;\n let opened = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const finish = (error?: unknown) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n options.signal?.removeEventListener('abort', onAbort);\n if (error === undefined) {\n resolve();\n return;\n }\n if (socket.readyState === CONNECTING || socket.readyState === OPEN) socket.close();\n reject(error);\n };\n\n const arm = () => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n finish(new EdgeTTSError('WebSocket inactivity timeout - no response from server', 'TIMEOUT'));\n }, options.timeout);\n };\n\n const onAbort = () => finish(abortReason(options.signal!));\n options.signal?.addEventListener('abort', onAbort, { once: true });\n arm();\n\n socket.onopen = () => {\n if (settled) return;\n opened = true;\n arm();\n socket.send(options.configMessage);\n socket.send(options.ssmlMessage);\n };\n\n socket.onmessage = (event) => {\n if (settled) return;\n arm();\n if (typeof event.data === 'string') {\n const frame = parseTextFrame(event.data);\n if (frame.path === 'audio.metadata') {\n for (const boundary of parseMetadata(frame.body)) options.onBoundary(boundary);\n } else if (frame.path === 'turn.end') {\n socket.close();\n }\n return;\n }\n const frame = parseBinaryFrame(toBytes(event.data));\n if (frame.path === 'audio') options.onAudio(frame.body);\n };\n\n socket.onerror = (event) => finish(options.toError(event, opened));\n socket.onclose = () => finish();\n });\n}\n", "export interface Cue {\n offset: number;\n duration: number;\n text: string;\n}\n\nfunction timestamp(ticks: number, separator: string): string {\n const total = Math.max(0, Math.round(ticks / 10_000));\n const ms = total % 1000;\n const s = Math.floor(total / 1000) % 60;\n const m = Math.floor(total / 60_000) % 60;\n const h = Math.floor(total / 3_600_000);\n const pad = (n: number, width = 2) => String(n).padStart(width, '0');\n return `${pad(h)}:${pad(m)}:${pad(s)}${separator}${pad(ms, 3)}`;\n}\n\nexport function toSRT(cues: Cue[]): string {\n return cues\n .map((cue, i) => `${i + 1}\\n${timestamp(cue.offset, ',')} --> ${timestamp(cue.offset + cue.duration, ',')}\\n${cue.text}\\n`)\n .join('\\n');\n}\n\nexport function toVTT(cues: Cue[]): string {\n const body = cues\n .map(cue => `${timestamp(cue.offset, '.')} --> ${timestamp(cue.offset + cue.duration, '.')}\\n${cue.text}\\n`)\n .join('\\n');\n return `WEBVTT\\n\\n${body}`;\n}\n", "import { Constants } from '../config/constants';\nimport { now } from './clock';\nimport { EdgeTTSError } from './errors';\nimport {\n buildConfigMessage,\n buildSSMLMessage,\n buildSynthesisUrl,\n concatChunks,\n DEFAULT_OUTPUT_FORMAT,\n estimateDuration,\n fileExtension,\n generateSecMsGec,\n generateUUID,\n normalizeVoices,\n sentenceTextRestorer,\n} from './protocol';\nimport { abortReason, runSession, type SocketLike } from './session';\nimport { toSRT as formatSRT, toVTT as formatVTT } from './subtitles';\nimport type {\n EdgeTTSOptions,\n SentenceBoundary,\n SynthesisOptions,\n SynthesisResult,\n Voice,\n WordBoundary,\n} from './types';\n\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_VOICES_CACHE_TTL = 10 * 60_000;\n\nexport const NO_AUDIO_MESSAGE =\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\nexport function noAudioMessage(outputFormat: string): string {\n const supported: string[] = Object.values(Constants.OUTPUT_FORMAT);\n if (supported.includes(outputFormat)) return NO_AUDIO_MESSAGE;\n return `${NO_AUDIO_MESSAGE} The output format \"${outputFormat}\" may also be the cause: ` +\n `the service is known to support ${supported.join(', ')}.`;\n}\n\ntype Boundary = WordBoundary | SentenceBoundary;\n\nfunction collect(text: string, words: WordBoundary[], sentences: SentenceBoundary[]) {\n const restore = sentenceTextRestorer(text);\n return (boundary: Boundary) => {\n if (boundary.type === 'WordBoundary') words.push(boundary);\n else sentences.push({ ...boundary, text: restore(boundary.text) });\n };\n}\n\nexport abstract class EdgeTTSCore {\n protected audio_stream: Uint8Array[] = [];\n protected output_format: string = DEFAULT_OUTPUT_FORMAT;\n protected word_boundaries: WordBoundary[] = [];\n protected sentence_boundaries: SentenceBoundary[] = [];\n protected readonly options: EdgeTTSOptions;\n private voicesCache?: { expires: number; voices: Voice[] };\n\n protected abstract readonly defaultVoice: string;\n\n constructor(options: EdgeTTSOptions = {}) {\n this.options = { ...options };\n }\n\n protected abstract openSocket(url: string): SocketLike;\n protected abstract requestVoices(url: string): Promise<any[]>;\n protected abstract buildSSML(text: string, voice: string, options: SynthesisOptions): string;\n protected abstract timestamp(): string;\n protected abstract socketError(event: unknown, opened: boolean): Error;\n\n protected async recoverHandshake(): Promise<boolean> {\n return false;\n }\n\n protected signature(): Promise<string> {\n return generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN, now());\n }\n\n async normalizeVoices(data: any[]): Promise<Voice[]> {\n return normalizeVoices(data);\n }\n\n async getVoices(): Promise<Voice[]> {\n if (this.voicesCache && this.voicesCache.expires > Date.now()) {\n return JSON.parse(JSON.stringify(this.voicesCache.voices));\n }\n\n const secMsGEC = await this.signature();\n const url =\n `${this.options.voicesUrl ?? Constants.VOICES_URL}` +\n `?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}` +\n `&Sec-MS-GEC=${secMsGEC}` +\n `&Sec-MS-GEC-Version=${this.options.secMsGecVersion ?? Constants.VERSION_MS_GEC}`;\n\n const voices = await this.normalizeVoices(await this.requestVoices(url));\n\n const ttl = this.options.voicesCacheTtl ?? DEFAULT_VOICES_CACHE_TTL;\n if (ttl > 0) {\n this.voicesCache = { expires: Date.now() + ttl, voices: JSON.parse(JSON.stringify(voices)) };\n }\n return 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 async synthesize(text: string, voice: string = this.defaultVoice, options: SynthesisOptions = {}): Promise<void> {\n const audio: Uint8Array[] = [];\n const words: WordBoundary[] = [];\n const sentences: SentenceBoundary[] = [];\n this.audio_stream = audio;\n this.word_boundaries = words;\n this.sentence_boundaries = sentences;\n this.output_format = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n\n await this.run(text, voice, options, chunk => audio.push(chunk), collect(text, words, sentences));\n }\n\n async *synthesizeStream(text: string, voice: string = this.defaultVoice, options: SynthesisOptions = {}): AsyncGenerator<Uint8Array, void, unknown> {\n const audio: Uint8Array[] = [];\n const words: WordBoundary[] = [];\n const sentences: SentenceBoundary[] = [];\n this.audio_stream = audio;\n this.word_boundaries = words;\n this.sentence_boundaries = sentences;\n this.output_format = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n\n const controller = new AbortController();\n const forwardAbort = () => controller.abort(abortReason(options.signal!));\n if (options.signal?.aborted) forwardAbort();\n else options.signal?.addEventListener('abort', forwardAbort, { once: true });\n\n const queue: Uint8Array[] = [];\n let wake: (() => void) | null = null;\n let done = false;\n let failure: unknown;\n const notify = () => {\n wake?.();\n wake = null;\n };\n\n this.run(text, voice, { ...options, signal: controller.signal }, chunk => {\n audio.push(chunk);\n queue.push(chunk);\n notify();\n }, collect(text, words, sentences)).then(\n () => { done = true; notify(); },\n error => { failure = error; done = true; notify(); },\n );\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length === 0) {\n await new Promise<void>(resolve => (wake = resolve));\n continue;\n }\n yield queue.shift()!;\n }\n if (failure !== undefined) throw failure;\n } finally {\n options.signal?.removeEventListener('abort', forwardAbort);\n if (!done) controller.abort();\n }\n }\n\n async generate(text: string, voice: string = this.defaultVoice, options: SynthesisOptions = {}): Promise<SynthesisResult> {\n const chunks: Uint8Array[] = [];\n const words: WordBoundary[] = [];\n const sentences: SentenceBoundary[] = [];\n await this.run(text, voice, options, chunk => chunks.push(chunk), collect(text, words, sentences));\n\n const audio = concatChunks(chunks);\n const outputFormat = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n if (audio.length === 0) throw new EdgeTTSError(noAudioMessage(outputFormat), 'NO_AUDIO');\n\n return {\n audio,\n format: fileExtension(outputFormat),\n outputFormat,\n wordBoundaries: words,\n sentenceBoundaries: sentences,\n duration: estimateDuration(audio.length, outputFormat),\n };\n }\n\n getWordBoundaries(): WordBoundary[] {\n return this.word_boundaries;\n }\n\n getSentenceBoundaries(): SentenceBoundary[] {\n return this.sentence_boundaries;\n }\n\n toSRT(): string {\n return formatSRT(this.sentence_boundaries.length > 0 ? this.sentence_boundaries : this.word_boundaries);\n }\n\n toVTT(): string {\n return formatVTT(this.sentence_boundaries.length > 0 ? this.sentence_boundaries : this.word_boundaries);\n }\n\n private async run(\n text: string,\n voice: string,\n options: SynthesisOptions,\n onAudio: (chunk: Uint8Array) => void,\n onBoundary: (boundary: Boundary) => void,\n ): Promise<void> {\n const ssml = this.buildSSML(text, voice, options);\n const outputFormat = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n\n const attempt = async () => {\n const requestId = generateUUID();\n const url = buildSynthesisUrl(\n this.options.wssUrl ?? Constants.WSS_URL,\n Constants.TRUSTED_CLIENT_TOKEN,\n await this.signature(),\n this.options.secMsGecVersion ?? Constants.VERSION_MS_GEC,\n requestId,\n );\n await runSession(() => this.openSocket(url), {\n configMessage: buildConfigMessage(this.timestamp(), outputFormat),\n ssmlMessage: buildSSMLMessage(requestId, this.timestamp(), ssml),\n timeout: options.timeout ?? this.options.timeout ?? DEFAULT_TIMEOUT,\n signal: options.signal,\n onAudio,\n onBoundary,\n toError: (event, opened) => this.socketError(event, opened),\n });\n };\n\n try {\n await attempt();\n } catch (error) {\n if (!(error instanceof EdgeTTSError && error.code === 'HANDSHAKE')) throw error;\n if (!(await this.recoverHandshake())) throw error;\n await attempt();\n }\n }\n}\n", "import { Constants } from '../config/constants';\nimport { EdgeTTSCore, noAudioMessage } from '../core/base';\nimport { EdgeTTSError } from '../core/errors';\nimport { buildSSML, concatChunks } from '../core/protocol';\nimport type { SocketLike } from '../core/session';\nimport type { EdgeTTSOptions, SynthesisOptions } from '../core/types';\n\nexport type { Voice, SynthesisOptions, WordBoundary, SentenceBoundary, EdgeTTSOptions, SynthesisResult } from '../core/types';\nexport { EdgeTTSError, type EdgeTTSErrorCode } from '../core/errors';\nexport { toSRT, toVTT } from '../core/subtitles';\n\nexport class EdgeTTS extends EdgeTTSCore {\n protected readonly defaultVoice = 'en-US-JennyNeural';\n private ws?: WebSocket;\n\n constructor(options: EdgeTTSOptions = {}) {\n super(options);\n }\n\n protected openSocket(url: string): SocketLike {\n this.ws = new WebSocket(url);\n return this.ws as unknown as SocketLike;\n }\n\n protected async requestVoices(url: string): Promise<any[]> {\n const response = await fetch(url, { headers: Constants.getBaseHeaders() });\n if (!response.ok) {\n throw new EdgeTTSError(`Voice list request failed with status ${response.status}`, 'VOICES', { status: response.status });\n }\n const data = await response.json();\n // The readaloud endpoint returns a bare array, not { voices: [...] }.\n return Array.isArray(data) ? data : (data?.voices || []);\n }\n\n protected buildSSML(text: 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 return buildSSML(text, voice, pitch, rate, volume);\n }\n\n protected timestamp(): string {\n return new Date().toUTCString();\n }\n\n protected socketError(_event: unknown, opened: boolean): Error {\n return new EdgeTTSError('WebSocket error', opened ? 'NETWORK' : 'HANDSHAKE');\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 getAudioData(): Uint8Array {\n if (this.audio_stream.length === 0) {\n throw new EdgeTTSError(\"No audio data available\", 'NO_AUDIO');\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 result = concatChunks(this.audio_stream);\n if (result.length === 0) {\n throw new EdgeTTSError(noAudioMessage(this.output_format), 'NO_AUDIO');\n }\n return result;\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["impl", "webCrypto", "crypto", "impl", "Constants", "bytes", "webCrypto", "b", "skewMs", "now", "EdgeTTSError", "message", "code", "options", "__publicField", "DEFAULT_OUTPUT_FORMAT", "decoder", "buildSynthesisUrl", "base", "token", "secMsGec", "version", "connectionId", "buildConfigMessage", "timestamp", "outputFormat", "buildSSMLMessage", "requestId", "ssml", "escapeXML", "text", "buildSSML", "voice", "pitch", "rate", "volume", "headerPath", "head", "parseTextFrame", "split", "parseBinaryFrame", "data", "headerLength", "parseMetadata", "body", "metadata", "boundaries", "item", "OPENING_PUNCTUATION", "sentenceTextRestorer", "source", "cursor", "index", "start", "generateSecMsGec", "trustedClientToken", "nowMs", "ticks", "windowsTicks", "hashBuffer", "webCrypto", "b", "generateUUID", "c", "r", "fileExtension", "format", "estimateDuration", "bytes", "kbps", "concatChunks", "chunks", "result", "total", "chunk", "offset", "normalizeVoices", "out", "v", "short", "locale", "mix", "voiceType", "localeName", "display", "tag", "tailored", "personalities", "CONNECTING", "OPEN", "abortReason", "signal", "error", "toBytes", "data", "runSession", "open", "options", "resolve", "reject", "socket", "settled", "opened", "timer", "finish", "onAbort", "arm", "EdgeTTSError", "event", "frame", "parseTextFrame", "boundary", "parseMetadata", "parseBinaryFrame", "timestamp", "ticks", "separator", "total", "ms", "s", "m", "h", "pad", "n", "width", "toSRT", "cues", "cue", "i", "toVTT", "DEFAULT_TIMEOUT", "DEFAULT_VOICES_CACHE_TTL", "NO_AUDIO_MESSAGE", "noAudioMessage", "outputFormat", "supported", "Constants", "collect", "text", "words", "sentences", "restore", "sentenceTextRestorer", "boundary", "EdgeTTSCore", "options", "__publicField", "DEFAULT_OUTPUT_FORMAT", "generateSecMsGec", "now", "data", "normalizeVoices", "secMsGEC", "url", "voices", "ttl", "locale", "voice", "gender", "audio", "chunk", "controller", "forwardAbort", "abortReason", "queue", "wake", "done", "failure", "notify", "error", "resolve", "chunks", "concatChunks", "EdgeTTSError", "fileExtension", "estimateDuration", "toSRT", "toVTT", "onAudio", "onBoundary", "ssml", "attempt", "requestId", "generateUUID", "buildSynthesisUrl", "runSession", "buildConfigMessage", "buildSSMLMessage", "event", "opened", "EdgeTTS", "EdgeTTSCore", "options", "__publicField", "url", "response", "Constants", "EdgeTTSError", "data", "text", "voice", "pitch", "rate", "volume", "buildSSML", "_event", "opened", "rateValue", "volumeValue", "result", "concatChunks", "noAudioMessage"]
4
+ "sourcesContent": ["export interface WebCrypto {\n getRandomValues<T extends Uint8Array>(array: T): T;\n subtle: { digest(algorithm: string, data: Uint8Array): Promise<ArrayBuffer> };\n}\n\nlet impl: WebCrypto | undefined;\n\nexport function setWebCrypto(crypto: WebCrypto): void {\n impl = crypto;\n}\n\nexport function webCrypto(): WebCrypto {\n const crypto = impl ?? (globalThis as { crypto?: WebCrypto }).crypto;\n if (!crypto) throw new Error('Web Crypto is not available in this environment');\n return crypto;\n}\n", "import { webCrypto } from '../core/crypto';\n\nexport 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 webCrypto().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", "let skewMs = 0;\n\nexport function now(): number {\n return Date.now() + skewMs;\n}\n\n// NOTE: the Date header has one-second resolution, so smaller differences are noise.\nexport function adjustClock(serverTimeMs: number): boolean {\n const delta = serverTimeMs - now();\n if (!Number.isFinite(delta) || Math.abs(delta) < 2000) return false;\n skewMs += delta;\n return true;\n}\n\nexport function resetClock(): void {\n skewMs = 0;\n}\n", "export type EdgeTTSErrorCode =\n | 'NO_AUDIO'\n | 'TIMEOUT'\n | 'HANDSHAKE'\n | 'NETWORK'\n | 'INVALID_OPTION'\n | 'REFUSED'\n | 'VOICES';\n\nexport class EdgeTTSError extends Error {\n readonly code: EdgeTTSErrorCode;\n readonly status?: number;\n\n constructor(message: string, code: EdgeTTSErrorCode, options: { status?: number; cause?: unknown } = {}) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = 'EdgeTTSError';\n this.code = code;\n if (options.status !== undefined) this.status = options.status;\n }\n}\n", "import { webCrypto } from './crypto';\nimport type { SentenceBoundary, Voice, WordBoundary } from './types';\n\nexport const DEFAULT_OUTPUT_FORMAT = 'audio-24khz-48kbitrate-mono-mp3';\n\nconst decoder = new TextDecoder();\n\nexport function buildSynthesisUrl(base: string, token: string, secMsGec: string, version: string, connectionId: string): string {\n return `${base}?Ocp-Apim-Subscription-Key=${token}&Sec-MS-GEC=${secMsGec}&Sec-MS-GEC-Version=${version}&ConnectionId=${connectionId}`;\n}\n\nexport function buildConfigMessage(timestamp: string, outputFormat: string): string {\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\":true,\"wordBoundaryEnabled\":true},\"outputFormat\":\"${outputFormat}\"}}}}`;\n}\n\nexport function buildSSMLMessage(requestId: string, timestamp: string, ssml: string): string {\n return `X-RequestId:${requestId}\\r\\nContent-Type:application/ssml+xml\\r\\nX-Timestamp:${timestamp}\\r\\nPath:ssml\\r\\n\\r\\n${ssml}`;\n}\n\nexport function 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\nexport function buildSSML(text: string, voice: string, pitch: string, rate: string, volume: string): string {\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 ${escapeXML(text)}\n </prosody>\n </voice>\n </speak>`;\n}\n\nfunction headerPath(head: string): string {\n return /Path:([^\\r\\n]*)/i.exec(head)?.[1]?.trim() ?? '';\n}\n\nexport function parseTextFrame(text: string): { path: string; body: string } {\n const split = text.indexOf('\\r\\n\\r\\n');\n if (split === -1) return { path: headerPath(text), body: '' };\n return { path: headerPath(text.slice(0, split)), body: text.slice(split + 4) };\n}\n\nexport function parseBinaryFrame(data: Uint8Array): { path: string; body: Uint8Array } {\n if (data.length < 2) return { path: '', body: new Uint8Array(0) };\n const headerLength = (data[0] << 8) | data[1];\n return {\n path: headerPath(decoder.decode(data.subarray(2, 2 + headerLength))),\n body: data.slice(2 + headerLength),\n };\n}\n\nexport function parseMetadata(body: string): (WordBoundary | SentenceBoundary)[] {\n let metadata: any;\n try {\n metadata = JSON.parse(body);\n } catch {\n return [];\n }\n if (!Array.isArray(metadata?.Metadata)) return [];\n\n const boundaries: (WordBoundary | SentenceBoundary)[] = [];\n for (const item of metadata.Metadata) {\n if (item?.Type !== 'WordBoundary' && item?.Type !== 'SentenceBoundary') continue;\n boundaries.push({\n type: item.Type,\n offset: item.Data.Offset,\n duration: item.Data.Duration,\n text: item.Data.text?.Text,\n });\n }\n return boundaries;\n}\n\nconst OPENING_PUNCTUATION = '\u00BF\u00A1\u00AB\"\\'\u201C\u2018([';\n\n// NOTE: the service drops opening punctuation such as \u00BF and \u00A1 from sentence text.\nexport function sentenceTextRestorer(source: string): (text: string) => string {\n let cursor = 0;\n return (text) => {\n const index = text ? source.indexOf(text, cursor) : -1;\n if (index === -1) return text;\n let start = index;\n while (start > cursor && OPENING_PUNCTUATION.includes(source[start - 1])) start--;\n cursor = index + text.length;\n return source.slice(start, cursor);\n };\n}\n\nexport async function generateSecMsGec(trustedClientToken: string, nowMs: number): Promise<string> {\n const ticks = Math.floor(nowMs / 1000) + 11644473600;\n const rounded = ticks - (ticks % 300);\n const windowsTicks = rounded * 10_000_000;\n\n const data = new TextEncoder().encode(`${windowsTicks}${trustedClientToken}`);\n const hashBuffer = await webCrypto().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\nexport function 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\nexport function fileExtension(format: string): string {\n if (format.includes('mp3')) return 'mp3';\n if (format.includes('opus') && format.includes('webm')) return 'webm';\n if (format.includes('opus') && format.includes('ogg')) return 'ogg';\n if (format.includes('wav') || format.includes('riff')) return 'wav';\n if (format.includes('pcm') && format.includes('raw')) return 'pcm';\n if (format.includes('alaw')) return 'alaw';\n if (format.includes('mulaw')) return 'mulaw';\n if (format.includes('truesilk')) return 'silk';\n if (format.includes('g722')) return 'g722';\n if (format.includes('amr')) return 'amr';\n return 'audio';\n}\n\n// NOTE: MP3 is CBR; formats without a bitrate (opus) assume 48 kbit/s.\nexport function estimateDuration(bytes: number, outputFormat: string): number {\n const kbps = Number(/(\\d+)kbitrate/.exec(outputFormat)?.[1] ?? 48);\n return (bytes * 8) / (kbps * 1000);\n}\n\nexport function concatChunks(chunks: Uint8Array[]): Uint8Array {\n const result = new Uint8Array(chunks.reduce((total, chunk) => total + chunk.length, 0));\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n}\n\nexport function normalizeVoices(data: any[]): 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", "import { EdgeTTSError } from './errors';\nimport { parseBinaryFrame, parseMetadata, parseTextFrame } from './protocol';\nimport type { SentenceBoundary, WordBoundary } from './types';\n\nexport interface SocketLike {\n binaryType: string;\n readonly readyState: number;\n onopen: ((event: any) => void) | null;\n onmessage: ((event: { data: unknown }) => void) | null;\n onerror: ((event: any) => void) | null;\n onclose: ((event: any) => void) | null;\n send(data: string): void;\n close(): void;\n}\n\nexport interface SessionOptions {\n configMessage: string;\n ssmlMessage: string;\n timeout: number;\n signal?: AbortSignal;\n onAudio(chunk: Uint8Array): void;\n onBoundary(boundary: WordBoundary | SentenceBoundary): void;\n toError(event: unknown, opened: boolean): Error;\n}\n\nconst CONNECTING = 0;\nconst OPEN = 1;\n\n// Close codes that end a session without an error: a normal close, a close\n// without a code (as when the client closes after turn.end) and a dropped\n// connection, which the missing audio reports afterwards.\nconst CLEAN_CLOSE_CODES = [1000, 1005, 1006];\n\n/**\n * The error for a close the service started to refuse the request. It\n * sends code 1007 with a reason such as \"Unsupported voice xx-XX-Nobody.\"\n */\nexport function closeError(event: { code?: number; reason?: unknown } | undefined): EdgeTTSError | undefined {\n const code = event?.code;\n if (typeof code !== 'number' || CLEAN_CLOSE_CODES.includes(code)) return undefined;\n const reason = typeof event?.reason === 'string' && event.reason !== '' ? event.reason : `close code ${code}`;\n return new EdgeTTSError(`The service refused the request: ${reason}`, 'REFUSED', { status: code });\n}\n\nexport function abortReason(signal: AbortSignal): unknown {\n if (signal.reason !== undefined) return signal.reason;\n const error = new Error('This operation was aborted');\n error.name = 'AbortError';\n return error;\n}\n\nfunction toBytes(data: unknown): Uint8Array {\n if (data instanceof ArrayBuffer) return new Uint8Array(data);\n if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n return new Uint8Array(0);\n}\n\nexport function runSession(open: () => SocketLike, options: SessionOptions): Promise<void> {\n return new Promise((resolve, reject) => {\n if (options.signal?.aborted) {\n reject(abortReason(options.signal));\n return;\n }\n\n const socket = open();\n socket.binaryType = 'arraybuffer';\n\n let settled = false;\n let opened = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const finish = (error?: unknown) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n options.signal?.removeEventListener('abort', onAbort);\n if (error === undefined) {\n resolve();\n return;\n }\n if (socket.readyState === CONNECTING || socket.readyState === OPEN) socket.close();\n reject(error);\n };\n\n const arm = () => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n finish(new EdgeTTSError('WebSocket inactivity timeout - no response from server', 'TIMEOUT'));\n }, options.timeout);\n };\n\n const onAbort = () => finish(abortReason(options.signal!));\n options.signal?.addEventListener('abort', onAbort, { once: true });\n arm();\n\n socket.onopen = () => {\n if (settled) return;\n opened = true;\n arm();\n socket.send(options.configMessage);\n socket.send(options.ssmlMessage);\n };\n\n socket.onmessage = (event) => {\n if (settled) return;\n arm();\n if (typeof event.data === 'string') {\n const frame = parseTextFrame(event.data);\n if (frame.path === 'audio.metadata') {\n for (const boundary of parseMetadata(frame.body)) options.onBoundary(boundary);\n } else if (frame.path === 'turn.end') {\n socket.close();\n }\n return;\n }\n const frame = parseBinaryFrame(toBytes(event.data));\n if (frame.path === 'audio') options.onAudio(frame.body);\n };\n\n socket.onerror = (event) => finish(options.toError(event, opened));\n socket.onclose = (event) => finish(closeError(event));\n });\n}\n", "export interface Cue {\n offset: number;\n duration: number;\n text: string;\n}\n\nfunction timestamp(ticks: number, separator: string): string {\n const total = Math.max(0, Math.round(ticks / 10_000));\n const ms = total % 1000;\n const s = Math.floor(total / 1000) % 60;\n const m = Math.floor(total / 60_000) % 60;\n const h = Math.floor(total / 3_600_000);\n const pad = (n: number, width = 2) => String(n).padStart(width, '0');\n return `${pad(h)}:${pad(m)}:${pad(s)}${separator}${pad(ms, 3)}`;\n}\n\nexport function toSRT(cues: Cue[]): string {\n return cues\n .map((cue, i) => `${i + 1}\\n${timestamp(cue.offset, ',')} --> ${timestamp(cue.offset + cue.duration, ',')}\\n${cue.text}\\n`)\n .join('\\n');\n}\n\nexport function toVTT(cues: Cue[]): string {\n const body = cues\n .map(cue => `${timestamp(cue.offset, '.')} --> ${timestamp(cue.offset + cue.duration, '.')}\\n${cue.text}\\n`)\n .join('\\n');\n return `WEBVTT\\n\\n${body}`;\n}\n", "import { Constants } from '../config/constants';\nimport { now } from './clock';\nimport { EdgeTTSError } from './errors';\nimport {\n buildConfigMessage,\n buildSSMLMessage,\n buildSynthesisUrl,\n concatChunks,\n DEFAULT_OUTPUT_FORMAT,\n estimateDuration,\n fileExtension,\n generateSecMsGec,\n generateUUID,\n normalizeVoices,\n sentenceTextRestorer,\n} from './protocol';\nimport { abortReason, runSession, type SocketLike } from './session';\nimport { toSRT as formatSRT, toVTT as formatVTT } from './subtitles';\nimport type {\n EdgeTTSOptions,\n SentenceBoundary,\n SynthesisOptions,\n SynthesisResult,\n Voice,\n WordBoundary,\n} from './types';\n\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_VOICES_CACHE_TTL = 10 * 60_000;\n\nexport const NO_AUDIO_MESSAGE =\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\nexport function noAudioMessage(outputFormat: string): string {\n const supported: string[] = Object.values(Constants.OUTPUT_FORMAT);\n if (supported.includes(outputFormat)) return NO_AUDIO_MESSAGE;\n return `${NO_AUDIO_MESSAGE} The output format \"${outputFormat}\" may also be the cause: ` +\n `the service is known to support ${supported.join(', ')}.`;\n}\n\ntype Boundary = WordBoundary | SentenceBoundary;\n\nfunction collect(text: string, words: WordBoundary[], sentences: SentenceBoundary[]) {\n const restore = sentenceTextRestorer(text);\n return (boundary: Boundary) => {\n if (boundary.type === 'WordBoundary') words.push(boundary);\n else sentences.push({ ...boundary, text: restore(boundary.text) });\n };\n}\n\nexport abstract class EdgeTTSCore {\n protected audio_stream: Uint8Array[] = [];\n protected output_format: string = DEFAULT_OUTPUT_FORMAT;\n protected word_boundaries: WordBoundary[] = [];\n protected sentence_boundaries: SentenceBoundary[] = [];\n protected readonly options: EdgeTTSOptions;\n private voicesCache?: { expires: number; voices: Voice[] };\n\n protected abstract readonly defaultVoice: string;\n\n constructor(options: EdgeTTSOptions = {}) {\n this.options = { ...options };\n }\n\n protected abstract openSocket(url: string): SocketLike;\n protected abstract requestVoices(url: string): Promise<any[]>;\n protected abstract buildSSML(text: string, voice: string, options: SynthesisOptions): string;\n protected abstract timestamp(): string;\n protected abstract socketError(event: unknown, opened: boolean): Error;\n\n protected async recoverHandshake(): Promise<boolean> {\n return false;\n }\n\n protected signature(): Promise<string> {\n return generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN, now());\n }\n\n async normalizeVoices(data: any[]): Promise<Voice[]> {\n return normalizeVoices(data);\n }\n\n async getVoices(): Promise<Voice[]> {\n if (this.voicesCache && this.voicesCache.expires > Date.now()) {\n return JSON.parse(JSON.stringify(this.voicesCache.voices));\n }\n\n const secMsGEC = await this.signature();\n const url =\n `${this.options.voicesUrl ?? Constants.VOICES_URL}` +\n `?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}` +\n `&Sec-MS-GEC=${secMsGEC}` +\n `&Sec-MS-GEC-Version=${this.options.secMsGecVersion ?? Constants.VERSION_MS_GEC}`;\n\n const voices = await this.normalizeVoices(await this.requestVoices(url));\n\n const ttl = this.options.voicesCacheTtl ?? DEFAULT_VOICES_CACHE_TTL;\n if (ttl > 0) {\n this.voicesCache = { expires: Date.now() + ttl, voices: JSON.parse(JSON.stringify(voices)) };\n }\n return 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 async synthesize(text: string, voice: string = this.defaultVoice, options: SynthesisOptions = {}): Promise<void> {\n const audio: Uint8Array[] = [];\n const words: WordBoundary[] = [];\n const sentences: SentenceBoundary[] = [];\n this.audio_stream = audio;\n this.word_boundaries = words;\n this.sentence_boundaries = sentences;\n this.output_format = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n\n await this.run(text, voice, options, chunk => audio.push(chunk), collect(text, words, sentences));\n }\n\n async *synthesizeStream(text: string, voice: string = this.defaultVoice, options: SynthesisOptions = {}): AsyncGenerator<Uint8Array, void, unknown> {\n const audio: Uint8Array[] = [];\n const words: WordBoundary[] = [];\n const sentences: SentenceBoundary[] = [];\n this.audio_stream = audio;\n this.word_boundaries = words;\n this.sentence_boundaries = sentences;\n this.output_format = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n\n const controller = new AbortController();\n const forwardAbort = () => controller.abort(abortReason(options.signal!));\n if (options.signal?.aborted) forwardAbort();\n else options.signal?.addEventListener('abort', forwardAbort, { once: true });\n\n const queue: Uint8Array[] = [];\n let wake: (() => void) | null = null;\n let done = false;\n let failure: unknown;\n const notify = () => {\n wake?.();\n wake = null;\n };\n\n this.run(text, voice, { ...options, signal: controller.signal }, chunk => {\n audio.push(chunk);\n queue.push(chunk);\n notify();\n }, collect(text, words, sentences)).then(\n () => { done = true; notify(); },\n error => { failure = error; done = true; notify(); },\n );\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length === 0) {\n await new Promise<void>(resolve => (wake = resolve));\n continue;\n }\n yield queue.shift()!;\n }\n if (failure !== undefined) throw failure;\n } finally {\n options.signal?.removeEventListener('abort', forwardAbort);\n if (!done) controller.abort();\n }\n }\n\n async generate(text: string, voice: string = this.defaultVoice, options: SynthesisOptions = {}): Promise<SynthesisResult> {\n const chunks: Uint8Array[] = [];\n const words: WordBoundary[] = [];\n const sentences: SentenceBoundary[] = [];\n await this.run(text, voice, options, chunk => chunks.push(chunk), collect(text, words, sentences));\n\n const audio = concatChunks(chunks);\n const outputFormat = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n if (audio.length === 0) throw new EdgeTTSError(noAudioMessage(outputFormat), 'NO_AUDIO');\n\n return {\n audio,\n format: fileExtension(outputFormat),\n outputFormat,\n wordBoundaries: words,\n sentenceBoundaries: sentences,\n duration: estimateDuration(audio.length, outputFormat),\n };\n }\n\n getWordBoundaries(): WordBoundary[] {\n return this.word_boundaries;\n }\n\n getSentenceBoundaries(): SentenceBoundary[] {\n return this.sentence_boundaries;\n }\n\n toSRT(): string {\n return formatSRT(this.sentence_boundaries.length > 0 ? this.sentence_boundaries : this.word_boundaries);\n }\n\n toVTT(): string {\n return formatVTT(this.sentence_boundaries.length > 0 ? this.sentence_boundaries : this.word_boundaries);\n }\n\n private async run(\n text: string,\n voice: string,\n options: SynthesisOptions,\n onAudio: (chunk: Uint8Array) => void,\n onBoundary: (boundary: Boundary) => void,\n ): Promise<void> {\n if (text.trim() === '') throw new EdgeTTSError('The text is empty.', 'INVALID_OPTION');\n const ssml = this.buildSSML(text, voice, options);\n const outputFormat = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n\n const attempt = async () => {\n const requestId = generateUUID();\n const url = buildSynthesisUrl(\n this.options.wssUrl ?? Constants.WSS_URL,\n Constants.TRUSTED_CLIENT_TOKEN,\n await this.signature(),\n this.options.secMsGecVersion ?? Constants.VERSION_MS_GEC,\n requestId,\n );\n await runSession(() => this.openSocket(url), {\n configMessage: buildConfigMessage(this.timestamp(), outputFormat),\n ssmlMessage: buildSSMLMessage(requestId, this.timestamp(), ssml),\n timeout: options.timeout ?? this.options.timeout ?? DEFAULT_TIMEOUT,\n signal: options.signal,\n onAudio,\n onBoundary,\n toError: (event, opened) => this.socketError(event, opened),\n });\n };\n\n try {\n await attempt();\n } catch (error) {\n if (!(error instanceof EdgeTTSError && error.code === 'HANDSHAKE')) throw error;\n if (!(await this.recoverHandshake())) throw error;\n await attempt();\n }\n }\n}\n", "import { Constants } from '../config/constants';\nimport { EdgeTTSCore, noAudioMessage } from '../core/base';\nimport { EdgeTTSError } from '../core/errors';\nimport { buildSSML, concatChunks } from '../core/protocol';\nimport type { SocketLike } from '../core/session';\nimport type { EdgeTTSOptions, SynthesisOptions } from '../core/types';\n\nexport type { Voice, SynthesisOptions, WordBoundary, SentenceBoundary, EdgeTTSOptions, SynthesisResult } from '../core/types';\nexport { EdgeTTSError, type EdgeTTSErrorCode } from '../core/errors';\nexport { toSRT, toVTT } from '../core/subtitles';\n\nexport class EdgeTTS extends EdgeTTSCore {\n protected readonly defaultVoice = 'en-US-JennyNeural';\n private ws?: WebSocket;\n\n constructor(options: EdgeTTSOptions = {}) {\n super(options);\n }\n\n protected openSocket(url: string): SocketLike {\n this.ws = new WebSocket(url);\n return this.ws as unknown as SocketLike;\n }\n\n protected async requestVoices(url: string): Promise<any[]> {\n const response = await fetch(url, { headers: Constants.getBaseHeaders() });\n if (!response.ok) {\n throw new EdgeTTSError(`Voice list request failed with status ${response.status}`, 'VOICES', { status: response.status });\n }\n const data = await response.json();\n // The readaloud endpoint returns a bare array, not { voices: [...] }.\n return Array.isArray(data) ? data : (data?.voices || []);\n }\n\n protected buildSSML(text: 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 return buildSSML(text, voice, pitch, rate, volume);\n }\n\n protected timestamp(): string {\n return new Date().toUTCString();\n }\n\n protected socketError(_event: unknown, opened: boolean): Error {\n return new EdgeTTSError('WebSocket error', opened ? 'NETWORK' : 'HANDSHAKE');\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 getAudioData(): Uint8Array {\n if (this.audio_stream.length === 0) {\n throw new EdgeTTSError(\"No audio data available\", 'NO_AUDIO');\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 result = concatChunks(this.audio_stream);\n if (result.length === 0) {\n throw new EdgeTTSError(noAudioMessage(this.output_format), 'NO_AUDIO');\n }\n return result;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["impl", "webCrypto", "crypto", "impl", "Constants", "bytes", "webCrypto", "b", "skewMs", "now", "EdgeTTSError", "message", "code", "options", "__publicField", "DEFAULT_OUTPUT_FORMAT", "decoder", "buildSynthesisUrl", "base", "token", "secMsGec", "version", "connectionId", "buildConfigMessage", "timestamp", "outputFormat", "buildSSMLMessage", "requestId", "ssml", "escapeXML", "text", "buildSSML", "voice", "pitch", "rate", "volume", "headerPath", "head", "parseTextFrame", "split", "parseBinaryFrame", "data", "headerLength", "parseMetadata", "body", "metadata", "boundaries", "item", "OPENING_PUNCTUATION", "sentenceTextRestorer", "source", "cursor", "index", "start", "generateSecMsGec", "trustedClientToken", "nowMs", "ticks", "windowsTicks", "hashBuffer", "webCrypto", "b", "generateUUID", "c", "r", "fileExtension", "format", "estimateDuration", "bytes", "kbps", "concatChunks", "chunks", "result", "total", "chunk", "offset", "normalizeVoices", "out", "v", "short", "locale", "mix", "voiceType", "localeName", "display", "tag", "tailored", "personalities", "CONNECTING", "OPEN", "CLEAN_CLOSE_CODES", "closeError", "event", "code", "reason", "EdgeTTSError", "abortReason", "signal", "error", "toBytes", "data", "runSession", "open", "options", "resolve", "reject", "socket", "settled", "opened", "timer", "finish", "onAbort", "arm", "frame", "parseTextFrame", "boundary", "parseMetadata", "parseBinaryFrame", "timestamp", "ticks", "separator", "total", "ms", "s", "m", "h", "pad", "n", "width", "toSRT", "cues", "cue", "i", "toVTT", "DEFAULT_TIMEOUT", "DEFAULT_VOICES_CACHE_TTL", "NO_AUDIO_MESSAGE", "noAudioMessage", "outputFormat", "supported", "Constants", "collect", "text", "words", "sentences", "restore", "sentenceTextRestorer", "boundary", "EdgeTTSCore", "options", "__publicField", "DEFAULT_OUTPUT_FORMAT", "generateSecMsGec", "now", "data", "normalizeVoices", "secMsGEC", "url", "voices", "ttl", "locale", "voice", "gender", "audio", "chunk", "controller", "forwardAbort", "abortReason", "queue", "wake", "done", "failure", "notify", "error", "resolve", "chunks", "concatChunks", "EdgeTTSError", "fileExtension", "estimateDuration", "toSRT", "toVTT", "onAudio", "onBoundary", "ssml", "attempt", "requestId", "generateUUID", "buildSynthesisUrl", "runSession", "buildConfigMessage", "buildSSMLMessage", "event", "opened", "EdgeTTS", "EdgeTTSCore", "options", "__publicField", "url", "response", "Constants", "EdgeTTSError", "data", "text", "voice", "pitch", "rate", "volume", "buildSSML", "_event", "opened", "rateValue", "volumeValue", "result", "concatChunks", "noAudioMessage"]
7
7
  }
@@ -265,6 +265,13 @@ ${ssml}`;
265
265
  // src/core/session.ts
266
266
  var CONNECTING = 0;
267
267
  var OPEN = 1;
268
+ var CLEAN_CLOSE_CODES = [1e3, 1005, 1006];
269
+ function closeError(event) {
270
+ const code = event?.code;
271
+ if (typeof code !== "number" || CLEAN_CLOSE_CODES.includes(code)) return void 0;
272
+ const reason = typeof event?.reason === "string" && event.reason !== "" ? event.reason : `close code ${code}`;
273
+ return new EdgeTTSError(`The service refused the request: ${reason}`, "REFUSED", { status: code });
274
+ }
268
275
  function abortReason(signal) {
269
276
  if (signal.reason !== void 0) return signal.reason;
270
277
  const error = new Error("This operation was aborted");
@@ -331,7 +338,7 @@ ${ssml}`;
331
338
  if (frame.path === "audio") options.onAudio(frame.body);
332
339
  };
333
340
  socket.onerror = (event) => finish(options.toError(event, opened));
334
- socket.onclose = () => finish();
341
+ socket.onclose = (event) => finish(closeError(event));
335
342
  });
336
343
  }
337
344
 
@@ -505,6 +512,7 @@ ${body}`;
505
512
  return toVTT(this.sentence_boundaries.length > 0 ? this.sentence_boundaries : this.word_boundaries);
506
513
  }
507
514
  async run(text, voice, options, onAudio, onBoundary) {
515
+ if (text.trim() === "") throw new EdgeTTSError("The text is empty.", "INVALID_OPTION");
508
516
  const ssml = this.buildSSML(text, voice, options);
509
517
  const outputFormat = options.outputFormat || DEFAULT_OUTPUT_FORMAT;
510
518
  const attempt = async () => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/browser/EdgeTTS.browser.ts", "../../src/core/crypto.ts", "../../src/config/constants.ts", "../../src/core/clock.ts", "../../src/core/errors.ts", "../../src/core/protocol.ts", "../../src/core/session.ts", "../../src/core/subtitles.ts", "../../src/core/base.ts"],
4
- "sourcesContent": ["import { Constants } from '../config/constants';\nimport { EdgeTTSCore, noAudioMessage } from '../core/base';\nimport { EdgeTTSError } from '../core/errors';\nimport { buildSSML, concatChunks } from '../core/protocol';\nimport type { SocketLike } from '../core/session';\nimport type { EdgeTTSOptions, SynthesisOptions } from '../core/types';\n\nexport type { Voice, SynthesisOptions, WordBoundary, SentenceBoundary, EdgeTTSOptions, SynthesisResult } from '../core/types';\nexport { EdgeTTSError, type EdgeTTSErrorCode } from '../core/errors';\nexport { toSRT, toVTT } from '../core/subtitles';\n\nexport class EdgeTTS extends EdgeTTSCore {\n protected readonly defaultVoice = 'en-US-JennyNeural';\n private ws?: WebSocket;\n\n constructor(options: EdgeTTSOptions = {}) {\n super(options);\n }\n\n protected openSocket(url: string): SocketLike {\n this.ws = new WebSocket(url);\n return this.ws as unknown as SocketLike;\n }\n\n protected async requestVoices(url: string): Promise<any[]> {\n const response = await fetch(url, { headers: Constants.getBaseHeaders() });\n if (!response.ok) {\n throw new EdgeTTSError(`Voice list request failed with status ${response.status}`, 'VOICES', { status: response.status });\n }\n const data = await response.json();\n // The readaloud endpoint returns a bare array, not { voices: [...] }.\n return Array.isArray(data) ? data : (data?.voices || []);\n }\n\n protected buildSSML(text: 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 return buildSSML(text, voice, pitch, rate, volume);\n }\n\n protected timestamp(): string {\n return new Date().toUTCString();\n }\n\n protected socketError(_event: unknown, opened: boolean): Error {\n return new EdgeTTSError('WebSocket error', opened ? 'NETWORK' : 'HANDSHAKE');\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 getAudioData(): Uint8Array {\n if (this.audio_stream.length === 0) {\n throw new EdgeTTSError(\"No audio data available\", 'NO_AUDIO');\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 result = concatChunks(this.audio_stream);\n if (result.length === 0) {\n throw new EdgeTTSError(noAudioMessage(this.output_format), 'NO_AUDIO');\n }\n return result;\n }\n}\n", "export interface WebCrypto {\n getRandomValues<T extends Uint8Array>(array: T): T;\n subtle: { digest(algorithm: string, data: Uint8Array): Promise<ArrayBuffer> };\n}\n\nlet impl: WebCrypto | undefined;\n\nexport function setWebCrypto(crypto: WebCrypto): void {\n impl = crypto;\n}\n\nexport function webCrypto(): WebCrypto {\n const crypto = impl ?? (globalThis as { crypto?: WebCrypto }).crypto;\n if (!crypto) throw new Error('Web Crypto is not available in this environment');\n return crypto;\n}\n", "import { webCrypto } from '../core/crypto';\n\nexport 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 webCrypto().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", "let skewMs = 0;\n\nexport function now(): number {\n return Date.now() + skewMs;\n}\n\n// NOTE: the Date header has one-second resolution, so smaller differences are noise.\nexport function adjustClock(serverTimeMs: number): boolean {\n const delta = serverTimeMs - now();\n if (!Number.isFinite(delta) || Math.abs(delta) < 2000) return false;\n skewMs += delta;\n return true;\n}\n\nexport function resetClock(): void {\n skewMs = 0;\n}\n", "export type EdgeTTSErrorCode =\n | 'NO_AUDIO'\n | 'TIMEOUT'\n | 'HANDSHAKE'\n | 'NETWORK'\n | 'INVALID_OPTION'\n | 'VOICES';\n\nexport class EdgeTTSError extends Error {\n readonly code: EdgeTTSErrorCode;\n readonly status?: number;\n\n constructor(message: string, code: EdgeTTSErrorCode, options: { status?: number; cause?: unknown } = {}) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = 'EdgeTTSError';\n this.code = code;\n if (options.status !== undefined) this.status = options.status;\n }\n}\n", "import { webCrypto } from './crypto';\nimport type { SentenceBoundary, Voice, WordBoundary } from './types';\n\nexport const DEFAULT_OUTPUT_FORMAT = 'audio-24khz-48kbitrate-mono-mp3';\n\nconst decoder = new TextDecoder();\n\nexport function buildSynthesisUrl(base: string, token: string, secMsGec: string, version: string, connectionId: string): string {\n return `${base}?Ocp-Apim-Subscription-Key=${token}&Sec-MS-GEC=${secMsGec}&Sec-MS-GEC-Version=${version}&ConnectionId=${connectionId}`;\n}\n\nexport function buildConfigMessage(timestamp: string, outputFormat: string): string {\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\":true,\"wordBoundaryEnabled\":true},\"outputFormat\":\"${outputFormat}\"}}}}`;\n}\n\nexport function buildSSMLMessage(requestId: string, timestamp: string, ssml: string): string {\n return `X-RequestId:${requestId}\\r\\nContent-Type:application/ssml+xml\\r\\nX-Timestamp:${timestamp}\\r\\nPath:ssml\\r\\n\\r\\n${ssml}`;\n}\n\nexport function 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\nexport function buildSSML(text: string, voice: string, pitch: string, rate: string, volume: string): string {\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 ${escapeXML(text)}\n </prosody>\n </voice>\n </speak>`;\n}\n\nfunction headerPath(head: string): string {\n return /Path:([^\\r\\n]*)/i.exec(head)?.[1]?.trim() ?? '';\n}\n\nexport function parseTextFrame(text: string): { path: string; body: string } {\n const split = text.indexOf('\\r\\n\\r\\n');\n if (split === -1) return { path: headerPath(text), body: '' };\n return { path: headerPath(text.slice(0, split)), body: text.slice(split + 4) };\n}\n\nexport function parseBinaryFrame(data: Uint8Array): { path: string; body: Uint8Array } {\n if (data.length < 2) return { path: '', body: new Uint8Array(0) };\n const headerLength = (data[0] << 8) | data[1];\n return {\n path: headerPath(decoder.decode(data.subarray(2, 2 + headerLength))),\n body: data.slice(2 + headerLength),\n };\n}\n\nexport function parseMetadata(body: string): (WordBoundary | SentenceBoundary)[] {\n let metadata: any;\n try {\n metadata = JSON.parse(body);\n } catch {\n return [];\n }\n if (!Array.isArray(metadata?.Metadata)) return [];\n\n const boundaries: (WordBoundary | SentenceBoundary)[] = [];\n for (const item of metadata.Metadata) {\n if (item?.Type !== 'WordBoundary' && item?.Type !== 'SentenceBoundary') continue;\n boundaries.push({\n type: item.Type,\n offset: item.Data.Offset,\n duration: item.Data.Duration,\n text: item.Data.text?.Text,\n });\n }\n return boundaries;\n}\n\nconst OPENING_PUNCTUATION = '\u00BF\u00A1\u00AB\"\\'\u201C\u2018([';\n\n// NOTE: the service drops opening punctuation such as \u00BF and \u00A1 from sentence text.\nexport function sentenceTextRestorer(source: string): (text: string) => string {\n let cursor = 0;\n return (text) => {\n const index = text ? source.indexOf(text, cursor) : -1;\n if (index === -1) return text;\n let start = index;\n while (start > cursor && OPENING_PUNCTUATION.includes(source[start - 1])) start--;\n cursor = index + text.length;\n return source.slice(start, cursor);\n };\n}\n\nexport async function generateSecMsGec(trustedClientToken: string, nowMs: number): Promise<string> {\n const ticks = Math.floor(nowMs / 1000) + 11644473600;\n const rounded = ticks - (ticks % 300);\n const windowsTicks = rounded * 10_000_000;\n\n const data = new TextEncoder().encode(`${windowsTicks}${trustedClientToken}`);\n const hashBuffer = await webCrypto().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\nexport function 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\nexport function fileExtension(format: string): string {\n if (format.includes('mp3')) return 'mp3';\n if (format.includes('opus') && format.includes('webm')) return 'webm';\n if (format.includes('opus') && format.includes('ogg')) return 'ogg';\n if (format.includes('wav') || format.includes('riff')) return 'wav';\n if (format.includes('pcm') && format.includes('raw')) return 'pcm';\n if (format.includes('alaw')) return 'alaw';\n if (format.includes('mulaw')) return 'mulaw';\n if (format.includes('truesilk')) return 'silk';\n if (format.includes('g722')) return 'g722';\n if (format.includes('amr')) return 'amr';\n return 'audio';\n}\n\n// NOTE: MP3 is CBR; formats without a bitrate (opus) assume 48 kbit/s.\nexport function estimateDuration(bytes: number, outputFormat: string): number {\n const kbps = Number(/(\\d+)kbitrate/.exec(outputFormat)?.[1] ?? 48);\n return (bytes * 8) / (kbps * 1000);\n}\n\nexport function concatChunks(chunks: Uint8Array[]): Uint8Array {\n const result = new Uint8Array(chunks.reduce((total, chunk) => total + chunk.length, 0));\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n}\n\nexport function normalizeVoices(data: any[]): 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", "import { EdgeTTSError } from './errors';\nimport { parseBinaryFrame, parseMetadata, parseTextFrame } from './protocol';\nimport type { SentenceBoundary, WordBoundary } from './types';\n\nexport interface SocketLike {\n binaryType: string;\n readonly readyState: number;\n onopen: ((event: any) => void) | null;\n onmessage: ((event: { data: unknown }) => void) | null;\n onerror: ((event: any) => void) | null;\n onclose: ((event: any) => void) | null;\n send(data: string): void;\n close(): void;\n}\n\nexport interface SessionOptions {\n configMessage: string;\n ssmlMessage: string;\n timeout: number;\n signal?: AbortSignal;\n onAudio(chunk: Uint8Array): void;\n onBoundary(boundary: WordBoundary | SentenceBoundary): void;\n toError(event: unknown, opened: boolean): Error;\n}\n\nconst CONNECTING = 0;\nconst OPEN = 1;\n\nexport function abortReason(signal: AbortSignal): unknown {\n if (signal.reason !== undefined) return signal.reason;\n const error = new Error('This operation was aborted');\n error.name = 'AbortError';\n return error;\n}\n\nfunction toBytes(data: unknown): Uint8Array {\n if (data instanceof ArrayBuffer) return new Uint8Array(data);\n if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n return new Uint8Array(0);\n}\n\nexport function runSession(open: () => SocketLike, options: SessionOptions): Promise<void> {\n return new Promise((resolve, reject) => {\n if (options.signal?.aborted) {\n reject(abortReason(options.signal));\n return;\n }\n\n const socket = open();\n socket.binaryType = 'arraybuffer';\n\n let settled = false;\n let opened = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const finish = (error?: unknown) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n options.signal?.removeEventListener('abort', onAbort);\n if (error === undefined) {\n resolve();\n return;\n }\n if (socket.readyState === CONNECTING || socket.readyState === OPEN) socket.close();\n reject(error);\n };\n\n const arm = () => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n finish(new EdgeTTSError('WebSocket inactivity timeout - no response from server', 'TIMEOUT'));\n }, options.timeout);\n };\n\n const onAbort = () => finish(abortReason(options.signal!));\n options.signal?.addEventListener('abort', onAbort, { once: true });\n arm();\n\n socket.onopen = () => {\n if (settled) return;\n opened = true;\n arm();\n socket.send(options.configMessage);\n socket.send(options.ssmlMessage);\n };\n\n socket.onmessage = (event) => {\n if (settled) return;\n arm();\n if (typeof event.data === 'string') {\n const frame = parseTextFrame(event.data);\n if (frame.path === 'audio.metadata') {\n for (const boundary of parseMetadata(frame.body)) options.onBoundary(boundary);\n } else if (frame.path === 'turn.end') {\n socket.close();\n }\n return;\n }\n const frame = parseBinaryFrame(toBytes(event.data));\n if (frame.path === 'audio') options.onAudio(frame.body);\n };\n\n socket.onerror = (event) => finish(options.toError(event, opened));\n socket.onclose = () => finish();\n });\n}\n", "export interface Cue {\n offset: number;\n duration: number;\n text: string;\n}\n\nfunction timestamp(ticks: number, separator: string): string {\n const total = Math.max(0, Math.round(ticks / 10_000));\n const ms = total % 1000;\n const s = Math.floor(total / 1000) % 60;\n const m = Math.floor(total / 60_000) % 60;\n const h = Math.floor(total / 3_600_000);\n const pad = (n: number, width = 2) => String(n).padStart(width, '0');\n return `${pad(h)}:${pad(m)}:${pad(s)}${separator}${pad(ms, 3)}`;\n}\n\nexport function toSRT(cues: Cue[]): string {\n return cues\n .map((cue, i) => `${i + 1}\\n${timestamp(cue.offset, ',')} --> ${timestamp(cue.offset + cue.duration, ',')}\\n${cue.text}\\n`)\n .join('\\n');\n}\n\nexport function toVTT(cues: Cue[]): string {\n const body = cues\n .map(cue => `${timestamp(cue.offset, '.')} --> ${timestamp(cue.offset + cue.duration, '.')}\\n${cue.text}\\n`)\n .join('\\n');\n return `WEBVTT\\n\\n${body}`;\n}\n", "import { Constants } from '../config/constants';\nimport { now } from './clock';\nimport { EdgeTTSError } from './errors';\nimport {\n buildConfigMessage,\n buildSSMLMessage,\n buildSynthesisUrl,\n concatChunks,\n DEFAULT_OUTPUT_FORMAT,\n estimateDuration,\n fileExtension,\n generateSecMsGec,\n generateUUID,\n normalizeVoices,\n sentenceTextRestorer,\n} from './protocol';\nimport { abortReason, runSession, type SocketLike } from './session';\nimport { toSRT as formatSRT, toVTT as formatVTT } from './subtitles';\nimport type {\n EdgeTTSOptions,\n SentenceBoundary,\n SynthesisOptions,\n SynthesisResult,\n Voice,\n WordBoundary,\n} from './types';\n\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_VOICES_CACHE_TTL = 10 * 60_000;\n\nexport const NO_AUDIO_MESSAGE =\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\nexport function noAudioMessage(outputFormat: string): string {\n const supported: string[] = Object.values(Constants.OUTPUT_FORMAT);\n if (supported.includes(outputFormat)) return NO_AUDIO_MESSAGE;\n return `${NO_AUDIO_MESSAGE} The output format \"${outputFormat}\" may also be the cause: ` +\n `the service is known to support ${supported.join(', ')}.`;\n}\n\ntype Boundary = WordBoundary | SentenceBoundary;\n\nfunction collect(text: string, words: WordBoundary[], sentences: SentenceBoundary[]) {\n const restore = sentenceTextRestorer(text);\n return (boundary: Boundary) => {\n if (boundary.type === 'WordBoundary') words.push(boundary);\n else sentences.push({ ...boundary, text: restore(boundary.text) });\n };\n}\n\nexport abstract class EdgeTTSCore {\n protected audio_stream: Uint8Array[] = [];\n protected output_format: string = DEFAULT_OUTPUT_FORMAT;\n protected word_boundaries: WordBoundary[] = [];\n protected sentence_boundaries: SentenceBoundary[] = [];\n protected readonly options: EdgeTTSOptions;\n private voicesCache?: { expires: number; voices: Voice[] };\n\n protected abstract readonly defaultVoice: string;\n\n constructor(options: EdgeTTSOptions = {}) {\n this.options = { ...options };\n }\n\n protected abstract openSocket(url: string): SocketLike;\n protected abstract requestVoices(url: string): Promise<any[]>;\n protected abstract buildSSML(text: string, voice: string, options: SynthesisOptions): string;\n protected abstract timestamp(): string;\n protected abstract socketError(event: unknown, opened: boolean): Error;\n\n protected async recoverHandshake(): Promise<boolean> {\n return false;\n }\n\n protected signature(): Promise<string> {\n return generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN, now());\n }\n\n async normalizeVoices(data: any[]): Promise<Voice[]> {\n return normalizeVoices(data);\n }\n\n async getVoices(): Promise<Voice[]> {\n if (this.voicesCache && this.voicesCache.expires > Date.now()) {\n return JSON.parse(JSON.stringify(this.voicesCache.voices));\n }\n\n const secMsGEC = await this.signature();\n const url =\n `${this.options.voicesUrl ?? Constants.VOICES_URL}` +\n `?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}` +\n `&Sec-MS-GEC=${secMsGEC}` +\n `&Sec-MS-GEC-Version=${this.options.secMsGecVersion ?? Constants.VERSION_MS_GEC}`;\n\n const voices = await this.normalizeVoices(await this.requestVoices(url));\n\n const ttl = this.options.voicesCacheTtl ?? DEFAULT_VOICES_CACHE_TTL;\n if (ttl > 0) {\n this.voicesCache = { expires: Date.now() + ttl, voices: JSON.parse(JSON.stringify(voices)) };\n }\n return 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 async synthesize(text: string, voice: string = this.defaultVoice, options: SynthesisOptions = {}): Promise<void> {\n const audio: Uint8Array[] = [];\n const words: WordBoundary[] = [];\n const sentences: SentenceBoundary[] = [];\n this.audio_stream = audio;\n this.word_boundaries = words;\n this.sentence_boundaries = sentences;\n this.output_format = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n\n await this.run(text, voice, options, chunk => audio.push(chunk), collect(text, words, sentences));\n }\n\n async *synthesizeStream(text: string, voice: string = this.defaultVoice, options: SynthesisOptions = {}): AsyncGenerator<Uint8Array, void, unknown> {\n const audio: Uint8Array[] = [];\n const words: WordBoundary[] = [];\n const sentences: SentenceBoundary[] = [];\n this.audio_stream = audio;\n this.word_boundaries = words;\n this.sentence_boundaries = sentences;\n this.output_format = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n\n const controller = new AbortController();\n const forwardAbort = () => controller.abort(abortReason(options.signal!));\n if (options.signal?.aborted) forwardAbort();\n else options.signal?.addEventListener('abort', forwardAbort, { once: true });\n\n const queue: Uint8Array[] = [];\n let wake: (() => void) | null = null;\n let done = false;\n let failure: unknown;\n const notify = () => {\n wake?.();\n wake = null;\n };\n\n this.run(text, voice, { ...options, signal: controller.signal }, chunk => {\n audio.push(chunk);\n queue.push(chunk);\n notify();\n }, collect(text, words, sentences)).then(\n () => { done = true; notify(); },\n error => { failure = error; done = true; notify(); },\n );\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length === 0) {\n await new Promise<void>(resolve => (wake = resolve));\n continue;\n }\n yield queue.shift()!;\n }\n if (failure !== undefined) throw failure;\n } finally {\n options.signal?.removeEventListener('abort', forwardAbort);\n if (!done) controller.abort();\n }\n }\n\n async generate(text: string, voice: string = this.defaultVoice, options: SynthesisOptions = {}): Promise<SynthesisResult> {\n const chunks: Uint8Array[] = [];\n const words: WordBoundary[] = [];\n const sentences: SentenceBoundary[] = [];\n await this.run(text, voice, options, chunk => chunks.push(chunk), collect(text, words, sentences));\n\n const audio = concatChunks(chunks);\n const outputFormat = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n if (audio.length === 0) throw new EdgeTTSError(noAudioMessage(outputFormat), 'NO_AUDIO');\n\n return {\n audio,\n format: fileExtension(outputFormat),\n outputFormat,\n wordBoundaries: words,\n sentenceBoundaries: sentences,\n duration: estimateDuration(audio.length, outputFormat),\n };\n }\n\n getWordBoundaries(): WordBoundary[] {\n return this.word_boundaries;\n }\n\n getSentenceBoundaries(): SentenceBoundary[] {\n return this.sentence_boundaries;\n }\n\n toSRT(): string {\n return formatSRT(this.sentence_boundaries.length > 0 ? this.sentence_boundaries : this.word_boundaries);\n }\n\n toVTT(): string {\n return formatVTT(this.sentence_boundaries.length > 0 ? this.sentence_boundaries : this.word_boundaries);\n }\n\n private async run(\n text: string,\n voice: string,\n options: SynthesisOptions,\n onAudio: (chunk: Uint8Array) => void,\n onBoundary: (boundary: Boundary) => void,\n ): Promise<void> {\n const ssml = this.buildSSML(text, voice, options);\n const outputFormat = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n\n const attempt = async () => {\n const requestId = generateUUID();\n const url = buildSynthesisUrl(\n this.options.wssUrl ?? Constants.WSS_URL,\n Constants.TRUSTED_CLIENT_TOKEN,\n await this.signature(),\n this.options.secMsGecVersion ?? Constants.VERSION_MS_GEC,\n requestId,\n );\n await runSession(() => this.openSocket(url), {\n configMessage: buildConfigMessage(this.timestamp(), outputFormat),\n ssmlMessage: buildSSMLMessage(requestId, this.timestamp(), ssml),\n timeout: options.timeout ?? this.options.timeout ?? DEFAULT_TIMEOUT,\n signal: options.signal,\n onAudio,\n onBoundary,\n toError: (event, opened) => this.socketError(event, opened),\n });\n };\n\n try {\n await attempt();\n } catch (error) {\n if (!(error instanceof EdgeTTSError && error.code === 'HANDSHAKE')) throw error;\n if (!(await this.recoverHandshake())) throw error;\n await attempt();\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Constants } from '../config/constants';\nimport { EdgeTTSCore, noAudioMessage } from '../core/base';\nimport { EdgeTTSError } from '../core/errors';\nimport { buildSSML, concatChunks } from '../core/protocol';\nimport type { SocketLike } from '../core/session';\nimport type { EdgeTTSOptions, SynthesisOptions } from '../core/types';\n\nexport type { Voice, SynthesisOptions, WordBoundary, SentenceBoundary, EdgeTTSOptions, SynthesisResult } from '../core/types';\nexport { EdgeTTSError, type EdgeTTSErrorCode } from '../core/errors';\nexport { toSRT, toVTT } from '../core/subtitles';\n\nexport class EdgeTTS extends EdgeTTSCore {\n protected readonly defaultVoice = 'en-US-JennyNeural';\n private ws?: WebSocket;\n\n constructor(options: EdgeTTSOptions = {}) {\n super(options);\n }\n\n protected openSocket(url: string): SocketLike {\n this.ws = new WebSocket(url);\n return this.ws as unknown as SocketLike;\n }\n\n protected async requestVoices(url: string): Promise<any[]> {\n const response = await fetch(url, { headers: Constants.getBaseHeaders() });\n if (!response.ok) {\n throw new EdgeTTSError(`Voice list request failed with status ${response.status}`, 'VOICES', { status: response.status });\n }\n const data = await response.json();\n // The readaloud endpoint returns a bare array, not { voices: [...] }.\n return Array.isArray(data) ? data : (data?.voices || []);\n }\n\n protected buildSSML(text: 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 return buildSSML(text, voice, pitch, rate, volume);\n }\n\n protected timestamp(): string {\n return new Date().toUTCString();\n }\n\n protected socketError(_event: unknown, opened: boolean): Error {\n return new EdgeTTSError('WebSocket error', opened ? 'NETWORK' : 'HANDSHAKE');\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 getAudioData(): Uint8Array {\n if (this.audio_stream.length === 0) {\n throw new EdgeTTSError(\"No audio data available\", 'NO_AUDIO');\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 result = concatChunks(this.audio_stream);\n if (result.length === 0) {\n throw new EdgeTTSError(noAudioMessage(this.output_format), 'NO_AUDIO');\n }\n return result;\n }\n}\n", "export interface WebCrypto {\n getRandomValues<T extends Uint8Array>(array: T): T;\n subtle: { digest(algorithm: string, data: Uint8Array): Promise<ArrayBuffer> };\n}\n\nlet impl: WebCrypto | undefined;\n\nexport function setWebCrypto(crypto: WebCrypto): void {\n impl = crypto;\n}\n\nexport function webCrypto(): WebCrypto {\n const crypto = impl ?? (globalThis as { crypto?: WebCrypto }).crypto;\n if (!crypto) throw new Error('Web Crypto is not available in this environment');\n return crypto;\n}\n", "import { webCrypto } from '../core/crypto';\n\nexport 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 webCrypto().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", "let skewMs = 0;\n\nexport function now(): number {\n return Date.now() + skewMs;\n}\n\n// NOTE: the Date header has one-second resolution, so smaller differences are noise.\nexport function adjustClock(serverTimeMs: number): boolean {\n const delta = serverTimeMs - now();\n if (!Number.isFinite(delta) || Math.abs(delta) < 2000) return false;\n skewMs += delta;\n return true;\n}\n\nexport function resetClock(): void {\n skewMs = 0;\n}\n", "export type EdgeTTSErrorCode =\n | 'NO_AUDIO'\n | 'TIMEOUT'\n | 'HANDSHAKE'\n | 'NETWORK'\n | 'INVALID_OPTION'\n | 'REFUSED'\n | 'VOICES';\n\nexport class EdgeTTSError extends Error {\n readonly code: EdgeTTSErrorCode;\n readonly status?: number;\n\n constructor(message: string, code: EdgeTTSErrorCode, options: { status?: number; cause?: unknown } = {}) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = 'EdgeTTSError';\n this.code = code;\n if (options.status !== undefined) this.status = options.status;\n }\n}\n", "import { webCrypto } from './crypto';\nimport type { SentenceBoundary, Voice, WordBoundary } from './types';\n\nexport const DEFAULT_OUTPUT_FORMAT = 'audio-24khz-48kbitrate-mono-mp3';\n\nconst decoder = new TextDecoder();\n\nexport function buildSynthesisUrl(base: string, token: string, secMsGec: string, version: string, connectionId: string): string {\n return `${base}?Ocp-Apim-Subscription-Key=${token}&Sec-MS-GEC=${secMsGec}&Sec-MS-GEC-Version=${version}&ConnectionId=${connectionId}`;\n}\n\nexport function buildConfigMessage(timestamp: string, outputFormat: string): string {\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\":true,\"wordBoundaryEnabled\":true},\"outputFormat\":\"${outputFormat}\"}}}}`;\n}\n\nexport function buildSSMLMessage(requestId: string, timestamp: string, ssml: string): string {\n return `X-RequestId:${requestId}\\r\\nContent-Type:application/ssml+xml\\r\\nX-Timestamp:${timestamp}\\r\\nPath:ssml\\r\\n\\r\\n${ssml}`;\n}\n\nexport function 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\nexport function buildSSML(text: string, voice: string, pitch: string, rate: string, volume: string): string {\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 ${escapeXML(text)}\n </prosody>\n </voice>\n </speak>`;\n}\n\nfunction headerPath(head: string): string {\n return /Path:([^\\r\\n]*)/i.exec(head)?.[1]?.trim() ?? '';\n}\n\nexport function parseTextFrame(text: string): { path: string; body: string } {\n const split = text.indexOf('\\r\\n\\r\\n');\n if (split === -1) return { path: headerPath(text), body: '' };\n return { path: headerPath(text.slice(0, split)), body: text.slice(split + 4) };\n}\n\nexport function parseBinaryFrame(data: Uint8Array): { path: string; body: Uint8Array } {\n if (data.length < 2) return { path: '', body: new Uint8Array(0) };\n const headerLength = (data[0] << 8) | data[1];\n return {\n path: headerPath(decoder.decode(data.subarray(2, 2 + headerLength))),\n body: data.slice(2 + headerLength),\n };\n}\n\nexport function parseMetadata(body: string): (WordBoundary | SentenceBoundary)[] {\n let metadata: any;\n try {\n metadata = JSON.parse(body);\n } catch {\n return [];\n }\n if (!Array.isArray(metadata?.Metadata)) return [];\n\n const boundaries: (WordBoundary | SentenceBoundary)[] = [];\n for (const item of metadata.Metadata) {\n if (item?.Type !== 'WordBoundary' && item?.Type !== 'SentenceBoundary') continue;\n boundaries.push({\n type: item.Type,\n offset: item.Data.Offset,\n duration: item.Data.Duration,\n text: item.Data.text?.Text,\n });\n }\n return boundaries;\n}\n\nconst OPENING_PUNCTUATION = '\u00BF\u00A1\u00AB\"\\'\u201C\u2018([';\n\n// NOTE: the service drops opening punctuation such as \u00BF and \u00A1 from sentence text.\nexport function sentenceTextRestorer(source: string): (text: string) => string {\n let cursor = 0;\n return (text) => {\n const index = text ? source.indexOf(text, cursor) : -1;\n if (index === -1) return text;\n let start = index;\n while (start > cursor && OPENING_PUNCTUATION.includes(source[start - 1])) start--;\n cursor = index + text.length;\n return source.slice(start, cursor);\n };\n}\n\nexport async function generateSecMsGec(trustedClientToken: string, nowMs: number): Promise<string> {\n const ticks = Math.floor(nowMs / 1000) + 11644473600;\n const rounded = ticks - (ticks % 300);\n const windowsTicks = rounded * 10_000_000;\n\n const data = new TextEncoder().encode(`${windowsTicks}${trustedClientToken}`);\n const hashBuffer = await webCrypto().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\nexport function 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\nexport function fileExtension(format: string): string {\n if (format.includes('mp3')) return 'mp3';\n if (format.includes('opus') && format.includes('webm')) return 'webm';\n if (format.includes('opus') && format.includes('ogg')) return 'ogg';\n if (format.includes('wav') || format.includes('riff')) return 'wav';\n if (format.includes('pcm') && format.includes('raw')) return 'pcm';\n if (format.includes('alaw')) return 'alaw';\n if (format.includes('mulaw')) return 'mulaw';\n if (format.includes('truesilk')) return 'silk';\n if (format.includes('g722')) return 'g722';\n if (format.includes('amr')) return 'amr';\n return 'audio';\n}\n\n// NOTE: MP3 is CBR; formats without a bitrate (opus) assume 48 kbit/s.\nexport function estimateDuration(bytes: number, outputFormat: string): number {\n const kbps = Number(/(\\d+)kbitrate/.exec(outputFormat)?.[1] ?? 48);\n return (bytes * 8) / (kbps * 1000);\n}\n\nexport function concatChunks(chunks: Uint8Array[]): Uint8Array {\n const result = new Uint8Array(chunks.reduce((total, chunk) => total + chunk.length, 0));\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n}\n\nexport function normalizeVoices(data: any[]): 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", "import { EdgeTTSError } from './errors';\nimport { parseBinaryFrame, parseMetadata, parseTextFrame } from './protocol';\nimport type { SentenceBoundary, WordBoundary } from './types';\n\nexport interface SocketLike {\n binaryType: string;\n readonly readyState: number;\n onopen: ((event: any) => void) | null;\n onmessage: ((event: { data: unknown }) => void) | null;\n onerror: ((event: any) => void) | null;\n onclose: ((event: any) => void) | null;\n send(data: string): void;\n close(): void;\n}\n\nexport interface SessionOptions {\n configMessage: string;\n ssmlMessage: string;\n timeout: number;\n signal?: AbortSignal;\n onAudio(chunk: Uint8Array): void;\n onBoundary(boundary: WordBoundary | SentenceBoundary): void;\n toError(event: unknown, opened: boolean): Error;\n}\n\nconst CONNECTING = 0;\nconst OPEN = 1;\n\n// Close codes that end a session without an error: a normal close, a close\n// without a code (as when the client closes after turn.end) and a dropped\n// connection, which the missing audio reports afterwards.\nconst CLEAN_CLOSE_CODES = [1000, 1005, 1006];\n\n/**\n * The error for a close the service started to refuse the request. It\n * sends code 1007 with a reason such as \"Unsupported voice xx-XX-Nobody.\"\n */\nexport function closeError(event: { code?: number; reason?: unknown } | undefined): EdgeTTSError | undefined {\n const code = event?.code;\n if (typeof code !== 'number' || CLEAN_CLOSE_CODES.includes(code)) return undefined;\n const reason = typeof event?.reason === 'string' && event.reason !== '' ? event.reason : `close code ${code}`;\n return new EdgeTTSError(`The service refused the request: ${reason}`, 'REFUSED', { status: code });\n}\n\nexport function abortReason(signal: AbortSignal): unknown {\n if (signal.reason !== undefined) return signal.reason;\n const error = new Error('This operation was aborted');\n error.name = 'AbortError';\n return error;\n}\n\nfunction toBytes(data: unknown): Uint8Array {\n if (data instanceof ArrayBuffer) return new Uint8Array(data);\n if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n return new Uint8Array(0);\n}\n\nexport function runSession(open: () => SocketLike, options: SessionOptions): Promise<void> {\n return new Promise((resolve, reject) => {\n if (options.signal?.aborted) {\n reject(abortReason(options.signal));\n return;\n }\n\n const socket = open();\n socket.binaryType = 'arraybuffer';\n\n let settled = false;\n let opened = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const finish = (error?: unknown) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n options.signal?.removeEventListener('abort', onAbort);\n if (error === undefined) {\n resolve();\n return;\n }\n if (socket.readyState === CONNECTING || socket.readyState === OPEN) socket.close();\n reject(error);\n };\n\n const arm = () => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n finish(new EdgeTTSError('WebSocket inactivity timeout - no response from server', 'TIMEOUT'));\n }, options.timeout);\n };\n\n const onAbort = () => finish(abortReason(options.signal!));\n options.signal?.addEventListener('abort', onAbort, { once: true });\n arm();\n\n socket.onopen = () => {\n if (settled) return;\n opened = true;\n arm();\n socket.send(options.configMessage);\n socket.send(options.ssmlMessage);\n };\n\n socket.onmessage = (event) => {\n if (settled) return;\n arm();\n if (typeof event.data === 'string') {\n const frame = parseTextFrame(event.data);\n if (frame.path === 'audio.metadata') {\n for (const boundary of parseMetadata(frame.body)) options.onBoundary(boundary);\n } else if (frame.path === 'turn.end') {\n socket.close();\n }\n return;\n }\n const frame = parseBinaryFrame(toBytes(event.data));\n if (frame.path === 'audio') options.onAudio(frame.body);\n };\n\n socket.onerror = (event) => finish(options.toError(event, opened));\n socket.onclose = (event) => finish(closeError(event));\n });\n}\n", "export interface Cue {\n offset: number;\n duration: number;\n text: string;\n}\n\nfunction timestamp(ticks: number, separator: string): string {\n const total = Math.max(0, Math.round(ticks / 10_000));\n const ms = total % 1000;\n const s = Math.floor(total / 1000) % 60;\n const m = Math.floor(total / 60_000) % 60;\n const h = Math.floor(total / 3_600_000);\n const pad = (n: number, width = 2) => String(n).padStart(width, '0');\n return `${pad(h)}:${pad(m)}:${pad(s)}${separator}${pad(ms, 3)}`;\n}\n\nexport function toSRT(cues: Cue[]): string {\n return cues\n .map((cue, i) => `${i + 1}\\n${timestamp(cue.offset, ',')} --> ${timestamp(cue.offset + cue.duration, ',')}\\n${cue.text}\\n`)\n .join('\\n');\n}\n\nexport function toVTT(cues: Cue[]): string {\n const body = cues\n .map(cue => `${timestamp(cue.offset, '.')} --> ${timestamp(cue.offset + cue.duration, '.')}\\n${cue.text}\\n`)\n .join('\\n');\n return `WEBVTT\\n\\n${body}`;\n}\n", "import { Constants } from '../config/constants';\nimport { now } from './clock';\nimport { EdgeTTSError } from './errors';\nimport {\n buildConfigMessage,\n buildSSMLMessage,\n buildSynthesisUrl,\n concatChunks,\n DEFAULT_OUTPUT_FORMAT,\n estimateDuration,\n fileExtension,\n generateSecMsGec,\n generateUUID,\n normalizeVoices,\n sentenceTextRestorer,\n} from './protocol';\nimport { abortReason, runSession, type SocketLike } from './session';\nimport { toSRT as formatSRT, toVTT as formatVTT } from './subtitles';\nimport type {\n EdgeTTSOptions,\n SentenceBoundary,\n SynthesisOptions,\n SynthesisResult,\n Voice,\n WordBoundary,\n} from './types';\n\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_VOICES_CACHE_TTL = 10 * 60_000;\n\nexport const NO_AUDIO_MESSAGE =\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\nexport function noAudioMessage(outputFormat: string): string {\n const supported: string[] = Object.values(Constants.OUTPUT_FORMAT);\n if (supported.includes(outputFormat)) return NO_AUDIO_MESSAGE;\n return `${NO_AUDIO_MESSAGE} The output format \"${outputFormat}\" may also be the cause: ` +\n `the service is known to support ${supported.join(', ')}.`;\n}\n\ntype Boundary = WordBoundary | SentenceBoundary;\n\nfunction collect(text: string, words: WordBoundary[], sentences: SentenceBoundary[]) {\n const restore = sentenceTextRestorer(text);\n return (boundary: Boundary) => {\n if (boundary.type === 'WordBoundary') words.push(boundary);\n else sentences.push({ ...boundary, text: restore(boundary.text) });\n };\n}\n\nexport abstract class EdgeTTSCore {\n protected audio_stream: Uint8Array[] = [];\n protected output_format: string = DEFAULT_OUTPUT_FORMAT;\n protected word_boundaries: WordBoundary[] = [];\n protected sentence_boundaries: SentenceBoundary[] = [];\n protected readonly options: EdgeTTSOptions;\n private voicesCache?: { expires: number; voices: Voice[] };\n\n protected abstract readonly defaultVoice: string;\n\n constructor(options: EdgeTTSOptions = {}) {\n this.options = { ...options };\n }\n\n protected abstract openSocket(url: string): SocketLike;\n protected abstract requestVoices(url: string): Promise<any[]>;\n protected abstract buildSSML(text: string, voice: string, options: SynthesisOptions): string;\n protected abstract timestamp(): string;\n protected abstract socketError(event: unknown, opened: boolean): Error;\n\n protected async recoverHandshake(): Promise<boolean> {\n return false;\n }\n\n protected signature(): Promise<string> {\n return generateSecMsGec(Constants.TRUSTED_CLIENT_TOKEN, now());\n }\n\n async normalizeVoices(data: any[]): Promise<Voice[]> {\n return normalizeVoices(data);\n }\n\n async getVoices(): Promise<Voice[]> {\n if (this.voicesCache && this.voicesCache.expires > Date.now()) {\n return JSON.parse(JSON.stringify(this.voicesCache.voices));\n }\n\n const secMsGEC = await this.signature();\n const url =\n `${this.options.voicesUrl ?? Constants.VOICES_URL}` +\n `?TrustedClientToken=${Constants.TRUSTED_CLIENT_TOKEN}` +\n `&Sec-MS-GEC=${secMsGEC}` +\n `&Sec-MS-GEC-Version=${this.options.secMsGecVersion ?? Constants.VERSION_MS_GEC}`;\n\n const voices = await this.normalizeVoices(await this.requestVoices(url));\n\n const ttl = this.options.voicesCacheTtl ?? DEFAULT_VOICES_CACHE_TTL;\n if (ttl > 0) {\n this.voicesCache = { expires: Date.now() + ttl, voices: JSON.parse(JSON.stringify(voices)) };\n }\n return 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 async synthesize(text: string, voice: string = this.defaultVoice, options: SynthesisOptions = {}): Promise<void> {\n const audio: Uint8Array[] = [];\n const words: WordBoundary[] = [];\n const sentences: SentenceBoundary[] = [];\n this.audio_stream = audio;\n this.word_boundaries = words;\n this.sentence_boundaries = sentences;\n this.output_format = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n\n await this.run(text, voice, options, chunk => audio.push(chunk), collect(text, words, sentences));\n }\n\n async *synthesizeStream(text: string, voice: string = this.defaultVoice, options: SynthesisOptions = {}): AsyncGenerator<Uint8Array, void, unknown> {\n const audio: Uint8Array[] = [];\n const words: WordBoundary[] = [];\n const sentences: SentenceBoundary[] = [];\n this.audio_stream = audio;\n this.word_boundaries = words;\n this.sentence_boundaries = sentences;\n this.output_format = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n\n const controller = new AbortController();\n const forwardAbort = () => controller.abort(abortReason(options.signal!));\n if (options.signal?.aborted) forwardAbort();\n else options.signal?.addEventListener('abort', forwardAbort, { once: true });\n\n const queue: Uint8Array[] = [];\n let wake: (() => void) | null = null;\n let done = false;\n let failure: unknown;\n const notify = () => {\n wake?.();\n wake = null;\n };\n\n this.run(text, voice, { ...options, signal: controller.signal }, chunk => {\n audio.push(chunk);\n queue.push(chunk);\n notify();\n }, collect(text, words, sentences)).then(\n () => { done = true; notify(); },\n error => { failure = error; done = true; notify(); },\n );\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length === 0) {\n await new Promise<void>(resolve => (wake = resolve));\n continue;\n }\n yield queue.shift()!;\n }\n if (failure !== undefined) throw failure;\n } finally {\n options.signal?.removeEventListener('abort', forwardAbort);\n if (!done) controller.abort();\n }\n }\n\n async generate(text: string, voice: string = this.defaultVoice, options: SynthesisOptions = {}): Promise<SynthesisResult> {\n const chunks: Uint8Array[] = [];\n const words: WordBoundary[] = [];\n const sentences: SentenceBoundary[] = [];\n await this.run(text, voice, options, chunk => chunks.push(chunk), collect(text, words, sentences));\n\n const audio = concatChunks(chunks);\n const outputFormat = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n if (audio.length === 0) throw new EdgeTTSError(noAudioMessage(outputFormat), 'NO_AUDIO');\n\n return {\n audio,\n format: fileExtension(outputFormat),\n outputFormat,\n wordBoundaries: words,\n sentenceBoundaries: sentences,\n duration: estimateDuration(audio.length, outputFormat),\n };\n }\n\n getWordBoundaries(): WordBoundary[] {\n return this.word_boundaries;\n }\n\n getSentenceBoundaries(): SentenceBoundary[] {\n return this.sentence_boundaries;\n }\n\n toSRT(): string {\n return formatSRT(this.sentence_boundaries.length > 0 ? this.sentence_boundaries : this.word_boundaries);\n }\n\n toVTT(): string {\n return formatVTT(this.sentence_boundaries.length > 0 ? this.sentence_boundaries : this.word_boundaries);\n }\n\n private async run(\n text: string,\n voice: string,\n options: SynthesisOptions,\n onAudio: (chunk: Uint8Array) => void,\n onBoundary: (boundary: Boundary) => void,\n ): Promise<void> {\n if (text.trim() === '') throw new EdgeTTSError('The text is empty.', 'INVALID_OPTION');\n const ssml = this.buildSSML(text, voice, options);\n const outputFormat = options.outputFormat || DEFAULT_OUTPUT_FORMAT;\n\n const attempt = async () => {\n const requestId = generateUUID();\n const url = buildSynthesisUrl(\n this.options.wssUrl ?? Constants.WSS_URL,\n Constants.TRUSTED_CLIENT_TOKEN,\n await this.signature(),\n this.options.secMsGecVersion ?? Constants.VERSION_MS_GEC,\n requestId,\n );\n await runSession(() => this.openSocket(url), {\n configMessage: buildConfigMessage(this.timestamp(), outputFormat),\n ssmlMessage: buildSSMLMessage(requestId, this.timestamp(), ssml),\n timeout: options.timeout ?? this.options.timeout ?? DEFAULT_TIMEOUT,\n signal: options.signal,\n onAudio,\n onBoundary,\n toError: (event, opened) => this.socketError(event, opened),\n });\n };\n\n try {\n await attempt();\n } catch (error) {\n if (!(error instanceof EdgeTTSError && error.code === 'HANDSHAKE')) throw error;\n if (!(await this.recoverHandshake())) throw error;\n await attempt();\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["timestamp", "frame"]
7
7
  }