@ssml-builder-js/azure-tts-client 2.11.0 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/index.d.mts +123 -1
- package/dist/index.d.ts +123 -1
- package/dist/index.js +177 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +172 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
- package/src/client.ts +38 -2
- package/src/index.ts +25 -1
- package/src/safe.ts +72 -0
- package/src/synthesis.ts +139 -4
- package/src/types.ts +59 -0
- package/test/synthesis.test.ts +40 -1
- package/test/v213-pipeline.test.ts +68 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/synthesis.ts","../src/speechConfig.ts","../src/outputFormats.ts","../src/client.ts","../src/voiceCatalog.ts"],"sourcesContent":["/**\n * azure-tts-client: Azure Text-to-Speech client for SSML playback.\n */\n\nexport type { AzureTtsClientOptions, AzureTtsLogger, TtsConfig } from \"./types.ts\";\nexport { AzureTtsError, AzureTtsSdkError } from \"./errors.ts\";\nexport { AzureTtsClient } from \"./client.ts\";\nexport { synthesizeSpeech } from \"./synthesis.ts\";\nexport { fetchAzureVoiceCatalog } from \"./voiceCatalog.ts\";\nexport type {\n AzureVoiceCatalog,\n AzureVoiceCatalogVoice,\n FetchedAzureVoiceCatalogMetadata,\n FetchAzureVoiceCatalogOptions,\n} from \"./voiceCatalog.ts\";\n","export class AzureTtsError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly responseBody: string;\n readonly requestId: string | null;\n\n constructor(status: number, statusText: string, responseBody: string, requestId: string | null) {\n super(`Azure TTS request failed: ${status} ${statusText}`);\n this.name = \"AzureTtsError\";\n this.status = status;\n this.statusText = statusText;\n this.responseBody = responseBody;\n this.requestId = requestId;\n }\n}\n\nexport class AzureTtsSdkError extends AzureTtsError {\n readonly errorDetails: string;\n\n constructor(errorDetails: string) {\n super(0, \"Speech SDK\", errorDetails, null);\n this.name = \"AzureTtsSdkError\";\n this.message = `Azure TTS synthesis failed: ${errorDetails}`;\n this.errorDetails = errorDetails;\n }\n}\n\nexport function createSpeechSdkError(error: unknown): AzureTtsSdkError {\n const message = error instanceof Error ? error.message : String(error);\n return new AzureTtsSdkError(message);\n}\n","import * as SpeechSDK from \"microsoft-cognitiveservices-speech-sdk\";\nimport { createSpeechSdkError } from \"./errors.ts\";\nimport { createSpeechConfig } from \"./speechConfig.ts\";\nimport type { TtsConfig } from \"./types.ts\";\n\nfunction closeSpeechResources(speechConfig: SpeechSDK.SpeechConfig, synthesizer: SpeechSDK.SpeechSynthesizer): void {\n try {\n synthesizer.close();\n } catch {}\n\n try {\n speechConfig.close();\n } catch {}\n}\n\nexport async function synthesizeSpeech(ssml: string, config: TtsConfig): Promise<ArrayBuffer> {\n if (config.signal?.aborted) {\n throw createSpeechSdkError(\"Speech synthesis was cancelled.\");\n }\n\n const speechConfig = createSpeechConfig(config);\n const synthesizer = new SpeechSDK.SpeechSynthesizer(speechConfig, null);\n\n return await new Promise<ArrayBuffer>((resolve, reject) => {\n let resourcesClosed = false;\n let settled = false;\n let timeout: ReturnType<typeof setTimeout> | undefined;\n let abortHandler: (() => void) | undefined;\n const cleanup = () => {\n if (timeout) clearTimeout(timeout);\n if (abortHandler) config.signal?.removeEventListener(\"abort\", abortHandler);\n };\n const closeResources = () => {\n if (resourcesClosed) return;\n resourcesClosed = true;\n closeSpeechResources(speechConfig, synthesizer);\n };\n const rejectWithError = (error: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n closeResources();\n reject(createSpeechSdkError(error));\n };\n\n const cb = (result: SpeechSDK.SpeechSynthesisResult) => {\n if (settled) return;\n const { reason, errorDetails } = result;\n if (reason !== SpeechSDK.ResultReason.SynthesizingAudioCompleted) {\n const err = errorDetails || `Speech synthesis failed with reason ${reason}.`;\n rejectWithError(err);\n return;\n }\n settled = true;\n cleanup();\n closeResources();\n resolve(result.audioData);\n };\n\n try {\n if (config.signal) {\n abortHandler = () => rejectWithError(\"Speech synthesis was cancelled.\");\n config.signal.addEventListener(\"abort\", abortHandler, { once: true });\n }\n if (config.timeoutMs !== undefined && config.timeoutMs > 0) {\n timeout = setTimeout(\n () => rejectWithError(`Speech synthesis timed out after ${config.timeoutMs} ms.`),\n config.timeoutMs,\n );\n }\n synthesizer.speakSsmlAsync(ssml, cb, rejectWithError);\n } catch (error) {\n rejectWithError(error);\n }\n });\n}\n","import { SpeechConfig } from \"microsoft-cognitiveservices-speech-sdk\";\nimport { DEFAULT_OUTPUT_FORMAT, resolveOutputFormat } from \"./outputFormats.ts\";\nimport type { TtsConfig } from \"./types.ts\";\n\nexport function resolveEndpoint(config: TtsConfig): string {\n const endpoint = config.endpoint?.trim() || \"https://{region}.tts.speech.microsoft.com/cognitiveservices/v1\";\n return endpoint.replace(/\\{region\\}/g, encodeURIComponent(config.region));\n}\n\nexport function createSpeechConfig(config: TtsConfig): SpeechConfig {\n const { outputFormat = DEFAULT_OUTPUT_FORMAT, subscriptionKey } = config;\n\n const endpoint = new URL(resolveEndpoint(config));\n const speechConfig = SpeechConfig.fromEndpoint(endpoint, subscriptionKey);\n speechConfig.speechSynthesisOutputFormat = resolveOutputFormat(outputFormat);\n return speechConfig;\n}\n","import * as SpeechSDK from \"microsoft-cognitiveservices-speech-sdk\";\n\nexport const DEFAULT_OUTPUT_FORMAT = \"audio-16khz-128kbitrate-mono-mp3\";\n\nconst OUTPUT_FORMATS: Record<string, SpeechSDK.SpeechSynthesisOutputFormat> = {\n \"raw-8khz-8bit-mono-mulaw\": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz8BitMonoMULaw,\n \"riff-16khz-16kbps-mono-siren\": SpeechSDK.SpeechSynthesisOutputFormat.Riff16Khz16KbpsMonoSiren,\n \"audio-16khz-16kbps-mono-siren\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz16KbpsMonoSiren,\n \"audio-16khz-32kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz32KBitRateMonoMp3,\n \"audio-16khz-128kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz128KBitRateMonoMp3,\n \"audio-16khz-64kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz64KBitRateMonoMp3,\n \"audio-24khz-48kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz48KBitRateMonoMp3,\n \"audio-24khz-96kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz96KBitRateMonoMp3,\n \"audio-24khz-160kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz160KBitRateMonoMp3,\n \"raw-16khz-16bit-mono-truesilk\": SpeechSDK.SpeechSynthesisOutputFormat.Raw16Khz16BitMonoTrueSilk,\n \"riff-16khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff16Khz16BitMonoPcm,\n \"riff-8khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz16BitMonoPcm,\n \"riff-24khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm,\n \"riff-8khz-8bit-mono-mulaw\": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz8BitMonoMULaw,\n \"raw-16khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw16Khz16BitMonoPcm,\n \"raw-24khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoPcm,\n \"raw-8khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz16BitMonoPcm,\n \"ogg-16khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Ogg16Khz16BitMonoOpus,\n \"ogg-24khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Ogg24Khz16BitMonoOpus,\n \"raw-48khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw48Khz16BitMonoPcm,\n \"riff-48khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff48Khz16BitMonoPcm,\n \"audio-48khz-96kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio48Khz96KBitRateMonoMp3,\n \"audio-48khz-192kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio48Khz192KBitRateMonoMp3,\n \"ogg-48khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Ogg48Khz16BitMonoOpus,\n \"webm-16khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Webm16Khz16BitMonoOpus,\n \"webm-24khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Webm24Khz16BitMonoOpus,\n \"webm-24khz-16bit-24kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Webm24Khz16Bit24KbpsMonoOpus,\n \"raw-24khz-16bit-mono-truesilk\": SpeechSDK.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoTrueSilk,\n \"raw-8khz-8bit-mono-alaw\": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz8BitMonoALaw,\n \"riff-8khz-8bit-mono-alaw\": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz8BitMonoALaw,\n \"audio-16khz-16bit-32kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz16Bit32KbpsMonoOpus,\n \"audio-24khz-16bit-48kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz16Bit48KbpsMonoOpus,\n \"audio-24khz-16bit-24kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz16Bit24KbpsMonoOpus,\n \"raw-22050hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw22050Hz16BitMonoPcm,\n \"riff-22050hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff22050Hz16BitMonoPcm,\n \"raw-44100hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw44100Hz16BitMonoPcm,\n \"riff-44100hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff44100Hz16BitMonoPcm,\n \"amr-wb-16000hz\": SpeechSDK.SpeechSynthesisOutputFormat.AmrWb16000Hz,\n \"g722-16khz-64kbps\": SpeechSDK.SpeechSynthesisOutputFormat.G72216Khz64Kbps,\n};\n\nexport function resolveOutputFormat(outputFormat: string): SpeechSDK.SpeechSynthesisOutputFormat {\n const resolvedFormat = OUTPUT_FORMATS[outputFormat];\n if (resolvedFormat === undefined) {\n throw new Error(`Unsupported Azure Speech output format: ${outputFormat}`);\n }\n\n return resolvedFormat;\n}\n","import { synthesizeSpeech } from \"./synthesis.ts\";\nimport type { AzureTtsClientOptions } from \"./types.ts\";\n\nconst ENDPOINT_TEMPLATE = \"https://{region}.tts.speech.microsoft.com/cognitiveservices/v1\";\n\nexport class AzureTtsClient {\n readonly #options: AzureTtsClientOptions;\n\n constructor(options: AzureTtsClientOptions) {\n this.#options = options;\n }\n\n async synthesize(ssml: string): Promise<ArrayBuffer> {\n const { region, subscriptionKey, outputFormat, signal, timeoutMs } = this.#options;\n const endpoint = this.#options.endpoint?.trim() || ENDPOINT_TEMPLATE.replace(\"{region}\", region);\n this.#options.logger?.debug?.(\"Using Azure TTS endpoint:\", endpoint);\n\n const config = { endpoint, region, subscriptionKey, outputFormat, signal, timeoutMs };\n return synthesizeSpeech(ssml, config);\n }\n}\n","const AZURE_VOICE_API_VERSION = \"2025-10-01\";\n\nexport interface FetchAzureVoiceCatalogOptions {\n apiKey: string;\n region: string | string[];\n}\n\nexport interface AzureVoiceCatalogVoice {\n name: string;\n locale: string;\n secondaryLocales?: readonly string[];\n styles?: readonly string[];\n regions: readonly string[];\n status?: \"ga\" | \"preview\" | \"deprecated\";\n}\n\nexport interface FetchedAzureVoiceCatalogMetadata {\n voiceCount: number;\n generatedAt: string;\n apiVersion: string;\n regions: readonly string[];\n}\n\nexport interface AzureVoiceCatalog {\n voices: readonly AzureVoiceCatalogVoice[];\n metadata: FetchedAzureVoiceCatalogMetadata;\n}\n\ninterface AzureVoiceApiRecord {\n Locale?: unknown;\n Name?: unknown;\n SecondaryLocaleList?: unknown;\n ShortName?: unknown;\n Status?: unknown;\n StyleList?: unknown;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction stringList(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return [...new Set(value.map(stringValue).filter((item): item is string => item !== undefined))];\n}\n\nfunction normalizeStatus(value: unknown): AzureVoiceCatalogVoice[\"status\"] {\n const status = stringValue(value)?.toLowerCase();\n if (status === \"preview\" || status === \"deprecated\" || status === \"ga\") return status;\n return undefined;\n}\n\nfunction normalizeRegions(region: string | string[]): string[] {\n const regions = Array.isArray(region) ? region : [region];\n const result = [...new Set(regions.map((item) => item.trim()).filter(Boolean))];\n if (result.length === 0) throw new TypeError(\"At least one Azure Speech region is required.\");\n return result;\n}\n\nasync function fetchRegionVoices(region: string, apiKey: string): Promise<AzureVoiceApiRecord[]> {\n const endpoint = `https://${encodeURIComponent(region)}.tts.speech.microsoft.com/cognitiveservices/voices/list`;\n const response = await fetch(endpoint, {\n headers: {\n Accept: \"application/json\",\n \"Ocp-Apim-Subscription-Key\": apiKey,\n },\n });\n if (!response.ok) {\n throw new Error(`Azure List Voices API request failed for region \"${region}\" with HTTP ${response.status}.`);\n }\n const payload: unknown = await response.json();\n if (!Array.isArray(payload)) throw new Error(`Azure List Voices API returned an invalid response for \"${region}\".`);\n return payload.filter((item): item is AzureVoiceApiRecord => Boolean(item && typeof item === \"object\"));\n}\n\n/** Fetches and deduplicates the current Azure Speech voice catalog for one or more regions. */\nexport async function fetchAzureVoiceCatalog(options: FetchAzureVoiceCatalogOptions): Promise<AzureVoiceCatalog> {\n if (!options || typeof options.apiKey !== \"string\" || !options.apiKey.trim())\n throw new TypeError(\"An Azure Speech API key is required.\");\n const regions = normalizeRegions(options.region);\n const payloads = await Promise.all(regions.map((region) => fetchRegionVoices(region, options.apiKey)));\n const voices = new Map<string, AzureVoiceCatalogVoice>();\n\n for (let regionIndex = 0; regionIndex < payloads.length; regionIndex += 1) {\n const region = regions[regionIndex];\n for (const record of payloads[regionIndex]) {\n const name = stringValue(record.ShortName) ?? stringValue(record.Name);\n const locale = stringValue(record.Locale);\n if (!name || !locale) continue;\n const key = name.toLowerCase();\n const existing = voices.get(key);\n const secondaryLocales = stringList(record.SecondaryLocaleList);\n const styles = stringList(record.StyleList);\n const status = normalizeStatus(record.Status);\n const merged: AzureVoiceCatalogVoice = {\n name: existing?.name ?? name,\n locale: existing?.locale ?? locale,\n regions: [...new Set([...(existing?.regions ?? []), region])],\n };\n const mergedSecondaryLocales = [...new Set([...(existing?.secondaryLocales ?? []), ...secondaryLocales])];\n if (mergedSecondaryLocales.length > 0) merged.secondaryLocales = mergedSecondaryLocales;\n const mergedStyles = [...new Set([...(existing?.styles ?? []), ...styles])];\n if (mergedStyles.length > 0) merged.styles = mergedStyles;\n if (status) merged.status = status;\n else if (existing?.status) merged.status = existing.status;\n voices.set(key, merged);\n }\n }\n\n const sortedVoices = [...voices.values()].sort((first, second) => first.name.localeCompare(second.name));\n return {\n voices: sortedVoices,\n metadata: {\n voiceCount: sortedVoices.length,\n generatedAt: new Date().toISOString(),\n apiVersion: AZURE_VOICE_API_VERSION,\n regions,\n },\n };\n}\n"],"mappings":"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","names":["SpeechSDK"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/synthesis.ts","../src/speechConfig.ts","../src/outputFormats.ts","../src/safe.ts","../src/client.ts","../src/voiceCatalog.ts"],"sourcesContent":["/**\n * azure-tts-client: Azure Text-to-Speech client for SSML playback.\n */\n\nexport type {\n AzureTtsClientOptions,\n AzureTtsLogger,\n SsmlSynthesisBookmark,\n SsmlSynthesisBoundary,\n SsmlSynthesisResult,\n SsmlSynthesisViseme,\n SsmlSynthesisChunk,\n SynthesisProgressEvent,\n SynthesizeChunksOptions,\n TtsConfig,\n} from \"./types.ts\";\nexport { AzureTtsError, AzureTtsSdkError } from \"./errors.ts\";\nexport { AzureTtsClient } from \"./client.ts\";\nexport { synthesizeSpeech } from \"./synthesis.ts\";\nexport { synthesizeSsml } from \"./synthesis.ts\";\nexport { mergeSynthesisResults, synthesizeSsmlChunks } from \"./synthesis.ts\";\nexport { synthesizeSsmlSafe } from \"./safe.ts\";\nexport type {\n AzureApiErrorResult,\n Result,\n SsmlSynthesisSafeResult,\n SsmlValidationError as AzureSsmlValidationError,\n Success,\n SynthesisResult,\n SynthesizeSsmlSafeOptions,\n ValidationErrorResult,\n} from \"./safe.ts\";\nexport { fetchAzureVoiceCatalog } from \"./voiceCatalog.ts\";\nexport type {\n AzureVoiceCatalog,\n AzureVoiceCatalogVoice,\n FetchedAzureVoiceCatalogMetadata,\n FetchAzureVoiceCatalogOptions,\n} from \"./voiceCatalog.ts\";\n","export class AzureTtsError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly responseBody: string;\n readonly requestId: string | null;\n\n constructor(status: number, statusText: string, responseBody: string, requestId: string | null) {\n super(`Azure TTS request failed: ${status} ${statusText}`);\n this.name = \"AzureTtsError\";\n this.status = status;\n this.statusText = statusText;\n this.responseBody = responseBody;\n this.requestId = requestId;\n }\n}\n\nexport class AzureTtsSdkError extends AzureTtsError {\n readonly errorDetails: string;\n\n constructor(errorDetails: string) {\n super(0, \"Speech SDK\", errorDetails, null);\n this.name = \"AzureTtsSdkError\";\n this.message = `Azure TTS synthesis failed: ${errorDetails}`;\n this.errorDetails = errorDetails;\n }\n}\n\nexport function createSpeechSdkError(error: unknown): AzureTtsSdkError {\n const message = error instanceof Error ? error.message : String(error);\n return new AzureTtsSdkError(message);\n}\n","import * as SpeechSDK from \"microsoft-cognitiveservices-speech-sdk\";\nimport { createSpeechSdkError } from \"./errors.ts\";\nimport { createSpeechConfig } from \"./speechConfig.ts\";\nimport type { SsmlSynthesisChunk, SsmlSynthesisResult, TtsConfig } from \"./types.ts\";\n\nfunction closeSpeechResources(speechConfig: SpeechSDK.SpeechConfig, synthesizer: SpeechSDK.SpeechSynthesizer): void {\n try {\n synthesizer.close();\n } catch {}\n\n try {\n speechConfig.close();\n } catch {}\n}\n\nconst ticksToMilliseconds = (ticks: number): number => Math.max(0, ticks) / 10_000;\n\nexport async function synthesizeSsml(ssml: string, config: TtsConfig): Promise<SsmlSynthesisResult> {\n if (config.signal?.aborted) {\n throw createSpeechSdkError(\"Speech synthesis was cancelled.\");\n }\n\n const speechConfig = createSpeechConfig(config);\n const synthesizer = new SpeechSDK.SpeechSynthesizer(speechConfig, null);\n\n return await new Promise<SsmlSynthesisResult>((resolve, reject) => {\n let resourcesClosed = false;\n let settled = false;\n let timeout: ReturnType<typeof setTimeout> | undefined;\n let abortHandler: (() => void) | undefined;\n const cleanup = () => {\n if (timeout) clearTimeout(timeout);\n if (abortHandler) config.signal?.removeEventListener(\"abort\", abortHandler);\n };\n const closeResources = () => {\n if (resourcesClosed) return;\n resourcesClosed = true;\n closeSpeechResources(speechConfig, synthesizer);\n };\n const rejectWithError = (error: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n closeResources();\n reject(createSpeechSdkError(error));\n };\n\n const boundaries: SsmlSynthesisResult[\"boundaries\"] = [];\n const visemes: SsmlSynthesisResult[\"visemes\"] = [];\n const bookmarks: SsmlSynthesisResult[\"bookmarks\"] = [];\n synthesizer.wordBoundary = (_sender, event) => {\n boundaries.push({\n text: event.text,\n audioOffsetMs: ticksToMilliseconds(event.audioOffset),\n durationMs: ticksToMilliseconds(event.duration),\n });\n };\n synthesizer.visemeReceived = (_sender, event) => {\n visemes.push({ visemeId: event.visemeId, audioOffsetMs: ticksToMilliseconds(event.audioOffset) });\n };\n synthesizer.bookmarkReached = (_sender, event) => {\n bookmarks.push({ name: event.text, audioOffsetMs: ticksToMilliseconds(event.audioOffset) });\n };\n\n const cb = (result: SpeechSDK.SpeechSynthesisResult) => {\n if (settled) return;\n const { reason, errorDetails } = result;\n if (reason !== SpeechSDK.ResultReason.SynthesizingAudioCompleted) {\n const err = errorDetails || `Speech synthesis failed with reason ${reason}.`;\n rejectWithError(err);\n return;\n }\n settled = true;\n cleanup();\n closeResources();\n const eventDurationMs = Math.max(\n 0,\n ...(boundaries ?? []).map((boundary) => boundary.audioOffsetMs + boundary.durationMs),\n ...(visemes ?? []).map((viseme) => viseme.audioOffsetMs),\n ...(bookmarks ?? []).map((bookmark) => bookmark.audioOffsetMs),\n );\n const durationMs = result.audioDuration ? ticksToMilliseconds(result.audioDuration) : eventDurationMs;\n const requestId = (result as SpeechSDK.SpeechSynthesisResult & { resultId?: string }).resultId;\n const addSourceMetadata = <T extends { audioOffsetMs: number }>(event: T): T => ({\n ...event,\n ...(config.sourceTextRange ? { textRange: { ...config.sourceTextRange } } : {}),\n ...(requestId ? { requestId } : {}),\n });\n const sourceBoundaries = boundaries.map((boundary) => addSourceMetadata(boundary));\n const sourceVisemes = visemes.map((viseme) => addSourceMetadata(viseme));\n const sourceBookmarks = bookmarks.map((bookmark) => addSourceMetadata(bookmark));\n resolve({\n audioData: result.audioData,\n durationMs,\n ...(config.sourceTextRange ? { textRange: { ...config.sourceTextRange } } : {}),\n ...(requestId ? { requestId } : {}),\n ...(sourceBoundaries.length > 0\n ? { boundaries: sourceBoundaries, wordBoundary: sourceBoundaries, wordBoundaries: sourceBoundaries }\n : {}),\n ...(sourceVisemes.length > 0 ? { visemes: sourceVisemes } : {}),\n ...(sourceBookmarks.length > 0 ? { bookmarks: sourceBookmarks } : {}),\n });\n };\n\n try {\n if (config.signal) {\n abortHandler = () => rejectWithError(\"Speech synthesis was cancelled.\");\n config.signal.addEventListener(\"abort\", abortHandler, { once: true });\n }\n if (config.timeoutMs !== undefined && config.timeoutMs > 0) {\n timeout = setTimeout(\n () => rejectWithError(`Speech synthesis timed out after ${config.timeoutMs} ms.`),\n config.timeoutMs,\n );\n }\n synthesizer.speakSsmlAsync(ssml, cb, rejectWithError);\n } catch (error) {\n rejectWithError(error);\n }\n });\n}\n\n/** Synthesizes chunks sequentially, annotates synchronization events, and merges the results. */\nexport async function synthesizeSsmlChunks(\n chunks: readonly (SsmlSynthesisChunk | string)[],\n config: TtsConfig,\n): Promise<SsmlSynthesisResult> {\n const results: SsmlSynthesisResult[] = [];\n const totalChunks = chunks.length;\n for (const [index, chunk] of chunks.entries()) {\n const input = typeof chunk === \"string\" ? { ssml: chunk } : chunk;\n const result = await synthesizeSsml(input.ssml, {\n ...config,\n ...(input.originalTextRange ? { sourceTextRange: input.originalTextRange } : {}),\n onProgress: undefined,\n });\n results.push(result);\n config.onProgress?.({\n currentChunk: index + 1,\n totalChunks,\n percent: totalChunks === 0 ? 100 : Math.round(((index + 1) / totalChunks) * 100),\n });\n }\n return mergeSynthesisResults(results);\n}\n\n/** Concatenates audio buffers and shifts all synchronization events by prior chunk durations. */\nexport function mergeSynthesisResults(results: readonly SsmlSynthesisResult[]): SsmlSynthesisResult {\n const audioLength = results.reduce((total, result) => total + result.audioData.byteLength, 0);\n const audioData = new Uint8Array(audioLength);\n const boundaries: NonNullable<SsmlSynthesisResult[\"boundaries\"]> = [];\n const visemes: NonNullable<SsmlSynthesisResult[\"visemes\"]> = [];\n const bookmarks: NonNullable<SsmlSynthesisResult[\"bookmarks\"]> = [];\n let byteOffset = 0;\n let durationOffset = 0;\n\n for (const result of results) {\n audioData.set(new Uint8Array(result.audioData), byteOffset);\n byteOffset += result.audioData.byteLength;\n const chunkBoundaries =\n result.boundaries && result.boundaries.length > 0\n ? result.boundaries\n : (result.wordBoundary ?? result.wordBoundaries ?? []);\n for (const boundary of chunkBoundaries) {\n const textRange = boundary.textRange ?? result.textRange;\n const requestId = boundary.requestId ?? result.requestId;\n boundaries.push({\n ...boundary,\n audioOffsetMs: boundary.audioOffsetMs + durationOffset,\n ...(textRange ? { textRange: { ...textRange } } : {}),\n ...(requestId ? { requestId } : {}),\n });\n }\n for (const viseme of result.visemes ?? []) {\n const textRange = viseme.textRange ?? result.textRange;\n const requestId = viseme.requestId ?? result.requestId;\n visemes.push({\n ...viseme,\n audioOffsetMs: viseme.audioOffsetMs + durationOffset,\n ...(textRange ? { textRange: { ...textRange } } : {}),\n ...(requestId ? { requestId } : {}),\n });\n }\n for (const bookmark of result.bookmarks ?? []) {\n const textRange = bookmark.textRange ?? result.textRange;\n const requestId = bookmark.requestId ?? result.requestId;\n bookmarks.push({\n ...bookmark,\n audioOffsetMs: bookmark.audioOffsetMs + durationOffset,\n ...(textRange ? { textRange: { ...textRange } } : {}),\n ...(requestId ? { requestId } : {}),\n });\n }\n durationOffset += Math.max(0, result.durationMs);\n }\n\n return {\n audioData: audioData.buffer,\n durationMs: durationOffset,\n ...(boundaries.length > 0 ? { boundaries, wordBoundary: boundaries, wordBoundaries: boundaries } : {}),\n ...(visemes.length > 0 ? { visemes } : {}),\n ...(bookmarks.length > 0 ? { bookmarks } : {}),\n ...(results.length === 1 && results[0]?.requestId ? { requestId: results[0].requestId } : {}),\n ...(results.length === 1 && results[0]?.textRange ? { textRange: { ...results[0].textRange } } : {}),\n };\n}\n\n/** Backward-compatible audio-only synthesis helper. */\nexport async function synthesizeSpeech(ssml: string, config: TtsConfig): Promise<ArrayBuffer> {\n return (await synthesizeSsml(ssml, config)).audioData;\n}\n","import { SpeechConfig } from \"microsoft-cognitiveservices-speech-sdk\";\nimport { DEFAULT_OUTPUT_FORMAT, resolveOutputFormat } from \"./outputFormats.ts\";\nimport type { TtsConfig } from \"./types.ts\";\n\nexport function resolveEndpoint(config: TtsConfig): string {\n const endpoint = config.endpoint?.trim() || \"https://{region}.tts.speech.microsoft.com/cognitiveservices/v1\";\n return endpoint.replace(/\\{region\\}/g, encodeURIComponent(config.region));\n}\n\nexport function createSpeechConfig(config: TtsConfig): SpeechConfig {\n const { outputFormat = DEFAULT_OUTPUT_FORMAT, subscriptionKey } = config;\n\n const endpoint = new URL(resolveEndpoint(config));\n const speechConfig = SpeechConfig.fromEndpoint(endpoint, subscriptionKey);\n speechConfig.speechSynthesisOutputFormat = resolveOutputFormat(outputFormat);\n return speechConfig;\n}\n","import * as SpeechSDK from \"microsoft-cognitiveservices-speech-sdk\";\n\nexport const DEFAULT_OUTPUT_FORMAT = \"audio-16khz-128kbitrate-mono-mp3\";\n\nconst OUTPUT_FORMATS: Record<string, SpeechSDK.SpeechSynthesisOutputFormat> = {\n \"raw-8khz-8bit-mono-mulaw\": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz8BitMonoMULaw,\n \"riff-16khz-16kbps-mono-siren\": SpeechSDK.SpeechSynthesisOutputFormat.Riff16Khz16KbpsMonoSiren,\n \"audio-16khz-16kbps-mono-siren\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz16KbpsMonoSiren,\n \"audio-16khz-32kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz32KBitRateMonoMp3,\n \"audio-16khz-128kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz128KBitRateMonoMp3,\n \"audio-16khz-64kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz64KBitRateMonoMp3,\n \"audio-24khz-48kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz48KBitRateMonoMp3,\n \"audio-24khz-96kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz96KBitRateMonoMp3,\n \"audio-24khz-160kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz160KBitRateMonoMp3,\n \"raw-16khz-16bit-mono-truesilk\": SpeechSDK.SpeechSynthesisOutputFormat.Raw16Khz16BitMonoTrueSilk,\n \"riff-16khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff16Khz16BitMonoPcm,\n \"riff-8khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz16BitMonoPcm,\n \"riff-24khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm,\n \"riff-8khz-8bit-mono-mulaw\": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz8BitMonoMULaw,\n \"raw-16khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw16Khz16BitMonoPcm,\n \"raw-24khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoPcm,\n \"raw-8khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz16BitMonoPcm,\n \"ogg-16khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Ogg16Khz16BitMonoOpus,\n \"ogg-24khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Ogg24Khz16BitMonoOpus,\n \"raw-48khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw48Khz16BitMonoPcm,\n \"riff-48khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff48Khz16BitMonoPcm,\n \"audio-48khz-96kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio48Khz96KBitRateMonoMp3,\n \"audio-48khz-192kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio48Khz192KBitRateMonoMp3,\n \"ogg-48khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Ogg48Khz16BitMonoOpus,\n \"webm-16khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Webm16Khz16BitMonoOpus,\n \"webm-24khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Webm24Khz16BitMonoOpus,\n \"webm-24khz-16bit-24kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Webm24Khz16Bit24KbpsMonoOpus,\n \"raw-24khz-16bit-mono-truesilk\": SpeechSDK.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoTrueSilk,\n \"raw-8khz-8bit-mono-alaw\": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz8BitMonoALaw,\n \"riff-8khz-8bit-mono-alaw\": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz8BitMonoALaw,\n \"audio-16khz-16bit-32kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz16Bit32KbpsMonoOpus,\n \"audio-24khz-16bit-48kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz16Bit48KbpsMonoOpus,\n \"audio-24khz-16bit-24kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz16Bit24KbpsMonoOpus,\n \"raw-22050hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw22050Hz16BitMonoPcm,\n \"riff-22050hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff22050Hz16BitMonoPcm,\n \"raw-44100hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw44100Hz16BitMonoPcm,\n \"riff-44100hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff44100Hz16BitMonoPcm,\n \"amr-wb-16000hz\": SpeechSDK.SpeechSynthesisOutputFormat.AmrWb16000Hz,\n \"g722-16khz-64kbps\": SpeechSDK.SpeechSynthesisOutputFormat.G72216Khz64Kbps,\n};\n\nexport function resolveOutputFormat(outputFormat: string): SpeechSDK.SpeechSynthesisOutputFormat {\n const resolvedFormat = OUTPUT_FORMATS[outputFormat];\n if (resolvedFormat === undefined) {\n throw new Error(`Unsupported Azure Speech output format: ${outputFormat}`);\n }\n\n return resolvedFormat;\n}\n","import { validateAzureSsml, type AzureValidationOptions, type SsmlDiagnostic } from \"@ssml-builder-js/ssml-core\";\nimport { AzureTtsError, createSpeechSdkError } from \"./errors.ts\";\nimport type { AzureTtsClient } from \"./client.ts\";\nimport type { SsmlSynthesisResult } from \"./types.ts\";\n\nexport interface SsmlValidationError {\n readonly kind: \"validation\";\n readonly message: string;\n readonly diagnostics: readonly SsmlDiagnostic[];\n}\n\nexport type Result<T, E> =\n | { readonly ok: true; readonly success: true; readonly status: \"success\"; readonly value: T }\n | {\n readonly ok: false;\n readonly success: false;\n readonly status: \"validation-error\" | \"azure-api-error\";\n readonly error: E;\n };\n\nexport type SynthesisResult<T, E> = Result<T, E>;\n\nexport type Success<T> = Extract<Result<T, never>, { readonly ok: true }>;\nexport type ValidationErrorResult = Extract<\n Result<never, SsmlValidationError>,\n { readonly status: \"validation-error\" }\n>;\nexport type AzureApiErrorResult = Extract<Result<never, AzureTtsError>, { readonly status: \"azure-api-error\" }>;\n\nexport type SsmlSynthesisSafeResult =\n | Result<SsmlSynthesisResult, never>\n | Result<never, SsmlValidationError>\n | Result<never, AzureTtsError>;\n\nexport interface SynthesizeSsmlSafeOptions extends AzureValidationOptions {\n /** Optional nested form for callers that want to keep validation settings grouped. */\n validation?: AzureValidationOptions;\n}\n\ninterface SynthesisClient {\n synthesizeSsml(ssml: string): Promise<SsmlSynthesisResult>;\n}\n\n/** Validates SSML before invoking Azure and converts validation/API failures to one result shape. */\nexport async function synthesizeSsmlSafe(\n client: Pick<AzureTtsClient, \"synthesizeSsml\"> | SynthesisClient,\n ssml: string,\n options: SynthesizeSsmlSafeOptions = {},\n): Promise<SsmlSynthesisSafeResult> {\n const validationOptions = options.validation ?? options;\n const diagnostics = await Promise.resolve(validateAzureSsml(ssml, validationOptions));\n const errors = diagnostics.filter((diagnostic) => diagnostic.severity === \"error\");\n if (errors.length > 0) {\n return {\n ok: false,\n success: false,\n status: \"validation-error\",\n error: {\n kind: \"validation\",\n message: \"SSML validation failed; the Azure Speech API was not called.\",\n diagnostics: errors,\n },\n };\n }\n\n try {\n return { ok: true, success: true, status: \"success\", value: await client.synthesizeSsml(ssml) };\n } catch (error) {\n const azureError = error instanceof AzureTtsError ? error : createSpeechSdkError(error);\n return { ok: false, success: false, status: \"azure-api-error\", error: azureError };\n }\n}\n","import { synthesizeSpeech, synthesizeSsml, synthesizeSsmlChunks } from \"./synthesis.ts\";\nimport { synthesizeSsmlSafe } from \"./safe.ts\";\nimport type { SynthesizeSsmlSafeOptions } from \"./safe.ts\";\nimport type {\n AzureTtsClientOptions,\n SsmlSynthesisChunk,\n SsmlSynthesisResult,\n SynthesizeChunksOptions,\n} from \"./types.ts\";\n\nconst ENDPOINT_TEMPLATE = \"https://{region}.tts.speech.microsoft.com/cognitiveservices/v1\";\n\nexport class AzureTtsClient {\n readonly #options: AzureTtsClientOptions;\n\n constructor(options: AzureTtsClientOptions) {\n this.#options = options;\n }\n\n async synthesize(ssml: string): Promise<ArrayBuffer> {\n const { region, subscriptionKey, outputFormat, signal, timeoutMs } = this.#options;\n const endpoint = this.#options.endpoint?.trim() || ENDPOINT_TEMPLATE.replace(\"{region}\", region);\n this.#options.logger?.debug?.(\"Using Azure TTS endpoint:\", endpoint);\n\n const config = { endpoint, region, subscriptionKey, outputFormat, signal, timeoutMs };\n return synthesizeSpeech(ssml, config);\n }\n\n async synthesizeSsml(ssml: string): Promise<SsmlSynthesisResult> {\n const { region, subscriptionKey, outputFormat, signal, timeoutMs } = this.#options;\n const endpoint = this.#options.endpoint?.trim() || ENDPOINT_TEMPLATE.replace(\"{region}\", region);\n this.#options.logger?.debug?.(\"Using Azure TTS endpoint:\", endpoint);\n\n return synthesizeSsml(ssml, { endpoint, region, subscriptionKey, outputFormat, signal, timeoutMs });\n }\n\n async synthesizeChunks(\n chunks: readonly (SsmlSynthesisChunk | string)[],\n options: SynthesizeChunksOptions = {},\n ): Promise<SsmlSynthesisResult> {\n const { region, subscriptionKey, outputFormat, signal, timeoutMs } = this.#options;\n const endpoint = this.#options.endpoint?.trim() || ENDPOINT_TEMPLATE.replace(\"{region}\", region);\n return synthesizeSsmlChunks(chunks, {\n endpoint,\n region,\n subscriptionKey,\n outputFormat,\n signal,\n timeoutMs,\n onProgress: options.onProgress ?? this.#options.onProgress,\n });\n }\n\n async synthesizeSsmlSafe(ssml: string, options: SynthesizeSsmlSafeOptions = {}) {\n return synthesizeSsmlSafe(this, ssml, options);\n }\n}\n","const AZURE_VOICE_API_VERSION = \"2025-10-01\";\n\nexport interface FetchAzureVoiceCatalogOptions {\n apiKey: string;\n region: string | string[];\n}\n\nexport interface AzureVoiceCatalogVoice {\n name: string;\n locale: string;\n secondaryLocales?: readonly string[];\n styles?: readonly string[];\n regions: readonly string[];\n status?: \"ga\" | \"preview\" | \"deprecated\";\n}\n\nexport interface FetchedAzureVoiceCatalogMetadata {\n voiceCount: number;\n generatedAt: string;\n apiVersion: string;\n regions: readonly string[];\n}\n\nexport interface AzureVoiceCatalog {\n voices: readonly AzureVoiceCatalogVoice[];\n metadata: FetchedAzureVoiceCatalogMetadata;\n}\n\ninterface AzureVoiceApiRecord {\n Locale?: unknown;\n Name?: unknown;\n SecondaryLocaleList?: unknown;\n ShortName?: unknown;\n Status?: unknown;\n StyleList?: unknown;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction stringList(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return [...new Set(value.map(stringValue).filter((item): item is string => item !== undefined))];\n}\n\nfunction normalizeStatus(value: unknown): AzureVoiceCatalogVoice[\"status\"] {\n const status = stringValue(value)?.toLowerCase();\n if (status === \"preview\" || status === \"deprecated\" || status === \"ga\") return status;\n return undefined;\n}\n\nfunction normalizeRegions(region: string | string[]): string[] {\n const regions = Array.isArray(region) ? region : [region];\n const result = [...new Set(regions.map((item) => item.trim()).filter(Boolean))];\n if (result.length === 0) throw new TypeError(\"At least one Azure Speech region is required.\");\n return result;\n}\n\nasync function fetchRegionVoices(region: string, apiKey: string): Promise<AzureVoiceApiRecord[]> {\n const endpoint = `https://${encodeURIComponent(region)}.tts.speech.microsoft.com/cognitiveservices/voices/list`;\n const response = await fetch(endpoint, {\n headers: {\n Accept: \"application/json\",\n \"Ocp-Apim-Subscription-Key\": apiKey,\n },\n });\n if (!response.ok) {\n throw new Error(`Azure List Voices API request failed for region \"${region}\" with HTTP ${response.status}.`);\n }\n const payload: unknown = await response.json();\n if (!Array.isArray(payload)) throw new Error(`Azure List Voices API returned an invalid response for \"${region}\".`);\n return payload.filter((item): item is AzureVoiceApiRecord => Boolean(item && typeof item === \"object\"));\n}\n\n/** Fetches and deduplicates the current Azure Speech voice catalog for one or more regions. */\nexport async function fetchAzureVoiceCatalog(options: FetchAzureVoiceCatalogOptions): Promise<AzureVoiceCatalog> {\n if (!options || typeof options.apiKey !== \"string\" || !options.apiKey.trim())\n throw new TypeError(\"An Azure Speech API key is required.\");\n const regions = normalizeRegions(options.region);\n const payloads = await Promise.all(regions.map((region) => fetchRegionVoices(region, options.apiKey)));\n const voices = new Map<string, AzureVoiceCatalogVoice>();\n\n for (let regionIndex = 0; regionIndex < payloads.length; regionIndex += 1) {\n const region = regions[regionIndex];\n for (const record of payloads[regionIndex]) {\n const name = stringValue(record.ShortName) ?? stringValue(record.Name);\n const locale = stringValue(record.Locale);\n if (!name || !locale) continue;\n const key = name.toLowerCase();\n const existing = voices.get(key);\n const secondaryLocales = stringList(record.SecondaryLocaleList);\n const styles = stringList(record.StyleList);\n const status = normalizeStatus(record.Status);\n const merged: AzureVoiceCatalogVoice = {\n name: existing?.name ?? name,\n locale: existing?.locale ?? locale,\n regions: [...new Set([...(existing?.regions ?? []), region])],\n };\n const mergedSecondaryLocales = [...new Set([...(existing?.secondaryLocales ?? []), ...secondaryLocales])];\n if (mergedSecondaryLocales.length > 0) merged.secondaryLocales = mergedSecondaryLocales;\n const mergedStyles = [...new Set([...(existing?.styles ?? []), ...styles])];\n if (mergedStyles.length > 0) merged.styles = mergedStyles;\n if (status) merged.status = status;\n else if (existing?.status) merged.status = existing.status;\n voices.set(key, merged);\n }\n }\n\n const sortedVoices = [...voices.values()].sort((first, second) => first.name.localeCompare(second.name));\n return {\n voices: sortedVoices,\n metadata: {\n voiceCount: sortedVoices.length,\n generatedAt: new Date().toISOString(),\n apiVersion: AZURE_VOICE_API_VERSION,\n regions,\n },\n };\n}\n"],"mappings":"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","names":["SpeechSDK"]}
|
package/dist/index.mjs
CHANGED
|
@@ -112,7 +112,8 @@ function closeSpeechResources(speechConfig, synthesizer) {
|
|
|
112
112
|
} catch {
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
|
|
115
|
+
var ticksToMilliseconds = (ticks) => Math.max(0, ticks) / 1e4;
|
|
116
|
+
async function synthesizeSsml(ssml, config) {
|
|
116
117
|
if (config.signal?.aborted) {
|
|
117
118
|
throw createSpeechSdkError("Speech synthesis was cancelled.");
|
|
118
119
|
}
|
|
@@ -139,6 +140,22 @@ async function synthesizeSpeech(ssml, config) {
|
|
|
139
140
|
closeResources();
|
|
140
141
|
reject(createSpeechSdkError(error));
|
|
141
142
|
};
|
|
143
|
+
const boundaries = [];
|
|
144
|
+
const visemes = [];
|
|
145
|
+
const bookmarks = [];
|
|
146
|
+
synthesizer.wordBoundary = (_sender, event) => {
|
|
147
|
+
boundaries.push({
|
|
148
|
+
text: event.text,
|
|
149
|
+
audioOffsetMs: ticksToMilliseconds(event.audioOffset),
|
|
150
|
+
durationMs: ticksToMilliseconds(event.duration)
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
synthesizer.visemeReceived = (_sender, event) => {
|
|
154
|
+
visemes.push({ visemeId: event.visemeId, audioOffsetMs: ticksToMilliseconds(event.audioOffset) });
|
|
155
|
+
};
|
|
156
|
+
synthesizer.bookmarkReached = (_sender, event) => {
|
|
157
|
+
bookmarks.push({ name: event.text, audioOffsetMs: ticksToMilliseconds(event.audioOffset) });
|
|
158
|
+
};
|
|
142
159
|
const cb = (result) => {
|
|
143
160
|
if (settled) return;
|
|
144
161
|
const { reason, errorDetails } = result;
|
|
@@ -150,7 +167,31 @@ async function synthesizeSpeech(ssml, config) {
|
|
|
150
167
|
settled = true;
|
|
151
168
|
cleanup();
|
|
152
169
|
closeResources();
|
|
153
|
-
|
|
170
|
+
const eventDurationMs = Math.max(
|
|
171
|
+
0,
|
|
172
|
+
...(boundaries ?? []).map((boundary) => boundary.audioOffsetMs + boundary.durationMs),
|
|
173
|
+
...(visemes ?? []).map((viseme) => viseme.audioOffsetMs),
|
|
174
|
+
...(bookmarks ?? []).map((bookmark) => bookmark.audioOffsetMs)
|
|
175
|
+
);
|
|
176
|
+
const durationMs = result.audioDuration ? ticksToMilliseconds(result.audioDuration) : eventDurationMs;
|
|
177
|
+
const requestId = result.resultId;
|
|
178
|
+
const addSourceMetadata = (event) => ({
|
|
179
|
+
...event,
|
|
180
|
+
...config.sourceTextRange ? { textRange: { ...config.sourceTextRange } } : {},
|
|
181
|
+
...requestId ? { requestId } : {}
|
|
182
|
+
});
|
|
183
|
+
const sourceBoundaries = boundaries.map((boundary) => addSourceMetadata(boundary));
|
|
184
|
+
const sourceVisemes = visemes.map((viseme) => addSourceMetadata(viseme));
|
|
185
|
+
const sourceBookmarks = bookmarks.map((bookmark) => addSourceMetadata(bookmark));
|
|
186
|
+
resolve({
|
|
187
|
+
audioData: result.audioData,
|
|
188
|
+
durationMs,
|
|
189
|
+
...config.sourceTextRange ? { textRange: { ...config.sourceTextRange } } : {},
|
|
190
|
+
...requestId ? { requestId } : {},
|
|
191
|
+
...sourceBoundaries.length > 0 ? { boundaries: sourceBoundaries, wordBoundary: sourceBoundaries, wordBoundaries: sourceBoundaries } : {},
|
|
192
|
+
...sourceVisemes.length > 0 ? { visemes: sourceVisemes } : {},
|
|
193
|
+
...sourceBookmarks.length > 0 ? { bookmarks: sourceBookmarks } : {}
|
|
194
|
+
});
|
|
154
195
|
};
|
|
155
196
|
try {
|
|
156
197
|
if (config.signal) {
|
|
@@ -169,6 +210,108 @@ async function synthesizeSpeech(ssml, config) {
|
|
|
169
210
|
}
|
|
170
211
|
});
|
|
171
212
|
}
|
|
213
|
+
async function synthesizeSsmlChunks(chunks, config) {
|
|
214
|
+
const results = [];
|
|
215
|
+
const totalChunks = chunks.length;
|
|
216
|
+
for (const [index, chunk] of chunks.entries()) {
|
|
217
|
+
const input = typeof chunk === "string" ? { ssml: chunk } : chunk;
|
|
218
|
+
const result = await synthesizeSsml(input.ssml, {
|
|
219
|
+
...config,
|
|
220
|
+
...input.originalTextRange ? { sourceTextRange: input.originalTextRange } : {},
|
|
221
|
+
onProgress: void 0
|
|
222
|
+
});
|
|
223
|
+
results.push(result);
|
|
224
|
+
config.onProgress?.({
|
|
225
|
+
currentChunk: index + 1,
|
|
226
|
+
totalChunks,
|
|
227
|
+
percent: totalChunks === 0 ? 100 : Math.round((index + 1) / totalChunks * 100)
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
return mergeSynthesisResults(results);
|
|
231
|
+
}
|
|
232
|
+
function mergeSynthesisResults(results) {
|
|
233
|
+
const audioLength = results.reduce((total, result) => total + result.audioData.byteLength, 0);
|
|
234
|
+
const audioData = new Uint8Array(audioLength);
|
|
235
|
+
const boundaries = [];
|
|
236
|
+
const visemes = [];
|
|
237
|
+
const bookmarks = [];
|
|
238
|
+
let byteOffset = 0;
|
|
239
|
+
let durationOffset = 0;
|
|
240
|
+
for (const result of results) {
|
|
241
|
+
audioData.set(new Uint8Array(result.audioData), byteOffset);
|
|
242
|
+
byteOffset += result.audioData.byteLength;
|
|
243
|
+
const chunkBoundaries = result.boundaries && result.boundaries.length > 0 ? result.boundaries : result.wordBoundary ?? result.wordBoundaries ?? [];
|
|
244
|
+
for (const boundary of chunkBoundaries) {
|
|
245
|
+
const textRange = boundary.textRange ?? result.textRange;
|
|
246
|
+
const requestId = boundary.requestId ?? result.requestId;
|
|
247
|
+
boundaries.push({
|
|
248
|
+
...boundary,
|
|
249
|
+
audioOffsetMs: boundary.audioOffsetMs + durationOffset,
|
|
250
|
+
...textRange ? { textRange: { ...textRange } } : {},
|
|
251
|
+
...requestId ? { requestId } : {}
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
for (const viseme of result.visemes ?? []) {
|
|
255
|
+
const textRange = viseme.textRange ?? result.textRange;
|
|
256
|
+
const requestId = viseme.requestId ?? result.requestId;
|
|
257
|
+
visemes.push({
|
|
258
|
+
...viseme,
|
|
259
|
+
audioOffsetMs: viseme.audioOffsetMs + durationOffset,
|
|
260
|
+
...textRange ? { textRange: { ...textRange } } : {},
|
|
261
|
+
...requestId ? { requestId } : {}
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
for (const bookmark of result.bookmarks ?? []) {
|
|
265
|
+
const textRange = bookmark.textRange ?? result.textRange;
|
|
266
|
+
const requestId = bookmark.requestId ?? result.requestId;
|
|
267
|
+
bookmarks.push({
|
|
268
|
+
...bookmark,
|
|
269
|
+
audioOffsetMs: bookmark.audioOffsetMs + durationOffset,
|
|
270
|
+
...textRange ? { textRange: { ...textRange } } : {},
|
|
271
|
+
...requestId ? { requestId } : {}
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
durationOffset += Math.max(0, result.durationMs);
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
audioData: audioData.buffer,
|
|
278
|
+
durationMs: durationOffset,
|
|
279
|
+
...boundaries.length > 0 ? { boundaries, wordBoundary: boundaries, wordBoundaries: boundaries } : {},
|
|
280
|
+
...visemes.length > 0 ? { visemes } : {},
|
|
281
|
+
...bookmarks.length > 0 ? { bookmarks } : {},
|
|
282
|
+
...results.length === 1 && results[0]?.requestId ? { requestId: results[0].requestId } : {},
|
|
283
|
+
...results.length === 1 && results[0]?.textRange ? { textRange: { ...results[0].textRange } } : {}
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
async function synthesizeSpeech(ssml, config) {
|
|
287
|
+
return (await synthesizeSsml(ssml, config)).audioData;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// src/safe.ts
|
|
291
|
+
import { validateAzureSsml } from "@ssml-builder-js/ssml-core";
|
|
292
|
+
async function synthesizeSsmlSafe(client, ssml, options = {}) {
|
|
293
|
+
const validationOptions = options.validation ?? options;
|
|
294
|
+
const diagnostics = await Promise.resolve(validateAzureSsml(ssml, validationOptions));
|
|
295
|
+
const errors = diagnostics.filter((diagnostic) => diagnostic.severity === "error");
|
|
296
|
+
if (errors.length > 0) {
|
|
297
|
+
return {
|
|
298
|
+
ok: false,
|
|
299
|
+
success: false,
|
|
300
|
+
status: "validation-error",
|
|
301
|
+
error: {
|
|
302
|
+
kind: "validation",
|
|
303
|
+
message: "SSML validation failed; the Azure Speech API was not called.",
|
|
304
|
+
diagnostics: errors
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
try {
|
|
309
|
+
return { ok: true, success: true, status: "success", value: await client.synthesizeSsml(ssml) };
|
|
310
|
+
} catch (error) {
|
|
311
|
+
const azureError = error instanceof AzureTtsError ? error : createSpeechSdkError(error);
|
|
312
|
+
return { ok: false, success: false, status: "azure-api-error", error: azureError };
|
|
313
|
+
}
|
|
314
|
+
}
|
|
172
315
|
|
|
173
316
|
// src/client.ts
|
|
174
317
|
var ENDPOINT_TEMPLATE = "https://{region}.tts.speech.microsoft.com/cognitiveservices/v1";
|
|
@@ -185,6 +328,28 @@ var AzureTtsClient = class {
|
|
|
185
328
|
const config = { endpoint, region, subscriptionKey, outputFormat, signal, timeoutMs };
|
|
186
329
|
return synthesizeSpeech(ssml, config);
|
|
187
330
|
}
|
|
331
|
+
async synthesizeSsml(ssml) {
|
|
332
|
+
const { region, subscriptionKey, outputFormat, signal, timeoutMs } = __privateGet(this, _options);
|
|
333
|
+
const endpoint = __privateGet(this, _options).endpoint?.trim() || ENDPOINT_TEMPLATE.replace("{region}", region);
|
|
334
|
+
__privateGet(this, _options).logger?.debug?.("Using Azure TTS endpoint:", endpoint);
|
|
335
|
+
return synthesizeSsml(ssml, { endpoint, region, subscriptionKey, outputFormat, signal, timeoutMs });
|
|
336
|
+
}
|
|
337
|
+
async synthesizeChunks(chunks, options = {}) {
|
|
338
|
+
const { region, subscriptionKey, outputFormat, signal, timeoutMs } = __privateGet(this, _options);
|
|
339
|
+
const endpoint = __privateGet(this, _options).endpoint?.trim() || ENDPOINT_TEMPLATE.replace("{region}", region);
|
|
340
|
+
return synthesizeSsmlChunks(chunks, {
|
|
341
|
+
endpoint,
|
|
342
|
+
region,
|
|
343
|
+
subscriptionKey,
|
|
344
|
+
outputFormat,
|
|
345
|
+
signal,
|
|
346
|
+
timeoutMs,
|
|
347
|
+
onProgress: options.onProgress ?? __privateGet(this, _options).onProgress
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
async synthesizeSsmlSafe(ssml, options = {}) {
|
|
351
|
+
return synthesizeSsmlSafe(this, ssml, options);
|
|
352
|
+
}
|
|
188
353
|
};
|
|
189
354
|
_options = new WeakMap();
|
|
190
355
|
|
|
@@ -270,6 +435,10 @@ export {
|
|
|
270
435
|
AzureTtsError,
|
|
271
436
|
AzureTtsSdkError,
|
|
272
437
|
fetchAzureVoiceCatalog,
|
|
273
|
-
|
|
438
|
+
mergeSynthesisResults,
|
|
439
|
+
synthesizeSpeech,
|
|
440
|
+
synthesizeSsml,
|
|
441
|
+
synthesizeSsmlChunks,
|
|
442
|
+
synthesizeSsmlSafe
|
|
274
443
|
};
|
|
275
444
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/synthesis.ts","../src/speechConfig.ts","../src/outputFormats.ts","../src/client.ts","../src/voiceCatalog.ts"],"sourcesContent":["export class AzureTtsError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly responseBody: string;\n readonly requestId: string | null;\n\n constructor(status: number, statusText: string, responseBody: string, requestId: string | null) {\n super(`Azure TTS request failed: ${status} ${statusText}`);\n this.name = \"AzureTtsError\";\n this.status = status;\n this.statusText = statusText;\n this.responseBody = responseBody;\n this.requestId = requestId;\n }\n}\n\nexport class AzureTtsSdkError extends AzureTtsError {\n readonly errorDetails: string;\n\n constructor(errorDetails: string) {\n super(0, \"Speech SDK\", errorDetails, null);\n this.name = \"AzureTtsSdkError\";\n this.message = `Azure TTS synthesis failed: ${errorDetails}`;\n this.errorDetails = errorDetails;\n }\n}\n\nexport function createSpeechSdkError(error: unknown): AzureTtsSdkError {\n const message = error instanceof Error ? error.message : String(error);\n return new AzureTtsSdkError(message);\n}\n","import * as SpeechSDK from \"microsoft-cognitiveservices-speech-sdk\";\nimport { createSpeechSdkError } from \"./errors.ts\";\nimport { createSpeechConfig } from \"./speechConfig.ts\";\nimport type { TtsConfig } from \"./types.ts\";\n\nfunction closeSpeechResources(speechConfig: SpeechSDK.SpeechConfig, synthesizer: SpeechSDK.SpeechSynthesizer): void {\n try {\n synthesizer.close();\n } catch {}\n\n try {\n speechConfig.close();\n } catch {}\n}\n\nexport async function synthesizeSpeech(ssml: string, config: TtsConfig): Promise<ArrayBuffer> {\n if (config.signal?.aborted) {\n throw createSpeechSdkError(\"Speech synthesis was cancelled.\");\n }\n\n const speechConfig = createSpeechConfig(config);\n const synthesizer = new SpeechSDK.SpeechSynthesizer(speechConfig, null);\n\n return await new Promise<ArrayBuffer>((resolve, reject) => {\n let resourcesClosed = false;\n let settled = false;\n let timeout: ReturnType<typeof setTimeout> | undefined;\n let abortHandler: (() => void) | undefined;\n const cleanup = () => {\n if (timeout) clearTimeout(timeout);\n if (abortHandler) config.signal?.removeEventListener(\"abort\", abortHandler);\n };\n const closeResources = () => {\n if (resourcesClosed) return;\n resourcesClosed = true;\n closeSpeechResources(speechConfig, synthesizer);\n };\n const rejectWithError = (error: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n closeResources();\n reject(createSpeechSdkError(error));\n };\n\n const cb = (result: SpeechSDK.SpeechSynthesisResult) => {\n if (settled) return;\n const { reason, errorDetails } = result;\n if (reason !== SpeechSDK.ResultReason.SynthesizingAudioCompleted) {\n const err = errorDetails || `Speech synthesis failed with reason ${reason}.`;\n rejectWithError(err);\n return;\n }\n settled = true;\n cleanup();\n closeResources();\n resolve(result.audioData);\n };\n\n try {\n if (config.signal) {\n abortHandler = () => rejectWithError(\"Speech synthesis was cancelled.\");\n config.signal.addEventListener(\"abort\", abortHandler, { once: true });\n }\n if (config.timeoutMs !== undefined && config.timeoutMs > 0) {\n timeout = setTimeout(\n () => rejectWithError(`Speech synthesis timed out after ${config.timeoutMs} ms.`),\n config.timeoutMs,\n );\n }\n synthesizer.speakSsmlAsync(ssml, cb, rejectWithError);\n } catch (error) {\n rejectWithError(error);\n }\n });\n}\n","import { SpeechConfig } from \"microsoft-cognitiveservices-speech-sdk\";\nimport { DEFAULT_OUTPUT_FORMAT, resolveOutputFormat } from \"./outputFormats.ts\";\nimport type { TtsConfig } from \"./types.ts\";\n\nexport function resolveEndpoint(config: TtsConfig): string {\n const endpoint = config.endpoint?.trim() || \"https://{region}.tts.speech.microsoft.com/cognitiveservices/v1\";\n return endpoint.replace(/\\{region\\}/g, encodeURIComponent(config.region));\n}\n\nexport function createSpeechConfig(config: TtsConfig): SpeechConfig {\n const { outputFormat = DEFAULT_OUTPUT_FORMAT, subscriptionKey } = config;\n\n const endpoint = new URL(resolveEndpoint(config));\n const speechConfig = SpeechConfig.fromEndpoint(endpoint, subscriptionKey);\n speechConfig.speechSynthesisOutputFormat = resolveOutputFormat(outputFormat);\n return speechConfig;\n}\n","import * as SpeechSDK from \"microsoft-cognitiveservices-speech-sdk\";\n\nexport const DEFAULT_OUTPUT_FORMAT = \"audio-16khz-128kbitrate-mono-mp3\";\n\nconst OUTPUT_FORMATS: Record<string, SpeechSDK.SpeechSynthesisOutputFormat> = {\n \"raw-8khz-8bit-mono-mulaw\": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz8BitMonoMULaw,\n \"riff-16khz-16kbps-mono-siren\": SpeechSDK.SpeechSynthesisOutputFormat.Riff16Khz16KbpsMonoSiren,\n \"audio-16khz-16kbps-mono-siren\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz16KbpsMonoSiren,\n \"audio-16khz-32kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz32KBitRateMonoMp3,\n \"audio-16khz-128kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz128KBitRateMonoMp3,\n \"audio-16khz-64kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz64KBitRateMonoMp3,\n \"audio-24khz-48kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz48KBitRateMonoMp3,\n \"audio-24khz-96kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz96KBitRateMonoMp3,\n \"audio-24khz-160kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz160KBitRateMonoMp3,\n \"raw-16khz-16bit-mono-truesilk\": SpeechSDK.SpeechSynthesisOutputFormat.Raw16Khz16BitMonoTrueSilk,\n \"riff-16khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff16Khz16BitMonoPcm,\n \"riff-8khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz16BitMonoPcm,\n \"riff-24khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm,\n \"riff-8khz-8bit-mono-mulaw\": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz8BitMonoMULaw,\n \"raw-16khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw16Khz16BitMonoPcm,\n \"raw-24khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoPcm,\n \"raw-8khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz16BitMonoPcm,\n \"ogg-16khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Ogg16Khz16BitMonoOpus,\n \"ogg-24khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Ogg24Khz16BitMonoOpus,\n \"raw-48khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw48Khz16BitMonoPcm,\n \"riff-48khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff48Khz16BitMonoPcm,\n \"audio-48khz-96kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio48Khz96KBitRateMonoMp3,\n \"audio-48khz-192kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio48Khz192KBitRateMonoMp3,\n \"ogg-48khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Ogg48Khz16BitMonoOpus,\n \"webm-16khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Webm16Khz16BitMonoOpus,\n \"webm-24khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Webm24Khz16BitMonoOpus,\n \"webm-24khz-16bit-24kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Webm24Khz16Bit24KbpsMonoOpus,\n \"raw-24khz-16bit-mono-truesilk\": SpeechSDK.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoTrueSilk,\n \"raw-8khz-8bit-mono-alaw\": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz8BitMonoALaw,\n \"riff-8khz-8bit-mono-alaw\": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz8BitMonoALaw,\n \"audio-16khz-16bit-32kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz16Bit32KbpsMonoOpus,\n \"audio-24khz-16bit-48kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz16Bit48KbpsMonoOpus,\n \"audio-24khz-16bit-24kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz16Bit24KbpsMonoOpus,\n \"raw-22050hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw22050Hz16BitMonoPcm,\n \"riff-22050hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff22050Hz16BitMonoPcm,\n \"raw-44100hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw44100Hz16BitMonoPcm,\n \"riff-44100hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff44100Hz16BitMonoPcm,\n \"amr-wb-16000hz\": SpeechSDK.SpeechSynthesisOutputFormat.AmrWb16000Hz,\n \"g722-16khz-64kbps\": SpeechSDK.SpeechSynthesisOutputFormat.G72216Khz64Kbps,\n};\n\nexport function resolveOutputFormat(outputFormat: string): SpeechSDK.SpeechSynthesisOutputFormat {\n const resolvedFormat = OUTPUT_FORMATS[outputFormat];\n if (resolvedFormat === undefined) {\n throw new Error(`Unsupported Azure Speech output format: ${outputFormat}`);\n }\n\n return resolvedFormat;\n}\n","import { synthesizeSpeech } from \"./synthesis.ts\";\nimport type { AzureTtsClientOptions } from \"./types.ts\";\n\nconst ENDPOINT_TEMPLATE = \"https://{region}.tts.speech.microsoft.com/cognitiveservices/v1\";\n\nexport class AzureTtsClient {\n readonly #options: AzureTtsClientOptions;\n\n constructor(options: AzureTtsClientOptions) {\n this.#options = options;\n }\n\n async synthesize(ssml: string): Promise<ArrayBuffer> {\n const { region, subscriptionKey, outputFormat, signal, timeoutMs } = this.#options;\n const endpoint = this.#options.endpoint?.trim() || ENDPOINT_TEMPLATE.replace(\"{region}\", region);\n this.#options.logger?.debug?.(\"Using Azure TTS endpoint:\", endpoint);\n\n const config = { endpoint, region, subscriptionKey, outputFormat, signal, timeoutMs };\n return synthesizeSpeech(ssml, config);\n }\n}\n","const AZURE_VOICE_API_VERSION = \"2025-10-01\";\n\nexport interface FetchAzureVoiceCatalogOptions {\n apiKey: string;\n region: string | string[];\n}\n\nexport interface AzureVoiceCatalogVoice {\n name: string;\n locale: string;\n secondaryLocales?: readonly string[];\n styles?: readonly string[];\n regions: readonly string[];\n status?: \"ga\" | \"preview\" | \"deprecated\";\n}\n\nexport interface FetchedAzureVoiceCatalogMetadata {\n voiceCount: number;\n generatedAt: string;\n apiVersion: string;\n regions: readonly string[];\n}\n\nexport interface AzureVoiceCatalog {\n voices: readonly AzureVoiceCatalogVoice[];\n metadata: FetchedAzureVoiceCatalogMetadata;\n}\n\ninterface AzureVoiceApiRecord {\n Locale?: unknown;\n Name?: unknown;\n SecondaryLocaleList?: unknown;\n ShortName?: unknown;\n Status?: unknown;\n StyleList?: unknown;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction stringList(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return [...new Set(value.map(stringValue).filter((item): item is string => item !== undefined))];\n}\n\nfunction normalizeStatus(value: unknown): AzureVoiceCatalogVoice[\"status\"] {\n const status = stringValue(value)?.toLowerCase();\n if (status === \"preview\" || status === \"deprecated\" || status === \"ga\") return status;\n return undefined;\n}\n\nfunction normalizeRegions(region: string | string[]): string[] {\n const regions = Array.isArray(region) ? region : [region];\n const result = [...new Set(regions.map((item) => item.trim()).filter(Boolean))];\n if (result.length === 0) throw new TypeError(\"At least one Azure Speech region is required.\");\n return result;\n}\n\nasync function fetchRegionVoices(region: string, apiKey: string): Promise<AzureVoiceApiRecord[]> {\n const endpoint = `https://${encodeURIComponent(region)}.tts.speech.microsoft.com/cognitiveservices/voices/list`;\n const response = await fetch(endpoint, {\n headers: {\n Accept: \"application/json\",\n \"Ocp-Apim-Subscription-Key\": apiKey,\n },\n });\n if (!response.ok) {\n throw new Error(`Azure List Voices API request failed for region \"${region}\" with HTTP ${response.status}.`);\n }\n const payload: unknown = await response.json();\n if (!Array.isArray(payload)) throw new Error(`Azure List Voices API returned an invalid response for \"${region}\".`);\n return payload.filter((item): item is AzureVoiceApiRecord => Boolean(item && typeof item === \"object\"));\n}\n\n/** Fetches and deduplicates the current Azure Speech voice catalog for one or more regions. */\nexport async function fetchAzureVoiceCatalog(options: FetchAzureVoiceCatalogOptions): Promise<AzureVoiceCatalog> {\n if (!options || typeof options.apiKey !== \"string\" || !options.apiKey.trim())\n throw new TypeError(\"An Azure Speech API key is required.\");\n const regions = normalizeRegions(options.region);\n const payloads = await Promise.all(regions.map((region) => fetchRegionVoices(region, options.apiKey)));\n const voices = new Map<string, AzureVoiceCatalogVoice>();\n\n for (let regionIndex = 0; regionIndex < payloads.length; regionIndex += 1) {\n const region = regions[regionIndex];\n for (const record of payloads[regionIndex]) {\n const name = stringValue(record.ShortName) ?? stringValue(record.Name);\n const locale = stringValue(record.Locale);\n if (!name || !locale) continue;\n const key = name.toLowerCase();\n const existing = voices.get(key);\n const secondaryLocales = stringList(record.SecondaryLocaleList);\n const styles = stringList(record.StyleList);\n const status = normalizeStatus(record.Status);\n const merged: AzureVoiceCatalogVoice = {\n name: existing?.name ?? name,\n locale: existing?.locale ?? locale,\n regions: [...new Set([...(existing?.regions ?? []), region])],\n };\n const mergedSecondaryLocales = [...new Set([...(existing?.secondaryLocales ?? []), ...secondaryLocales])];\n if (mergedSecondaryLocales.length > 0) merged.secondaryLocales = mergedSecondaryLocales;\n const mergedStyles = [...new Set([...(existing?.styles ?? []), ...styles])];\n if (mergedStyles.length > 0) merged.styles = mergedStyles;\n if (status) merged.status = status;\n else if (existing?.status) merged.status = existing.status;\n voices.set(key, merged);\n }\n }\n\n const sortedVoices = [...voices.values()].sort((first, second) => first.name.localeCompare(second.name));\n return {\n voices: sortedVoices,\n metadata: {\n voiceCount: sortedVoices.length,\n generatedAt: new Date().toISOString(),\n apiVersion: AZURE_VOICE_API_VERSION,\n regions,\n },\n };\n}\n"],"mappings":"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","names":["SpeechSDK"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/synthesis.ts","../src/speechConfig.ts","../src/outputFormats.ts","../src/safe.ts","../src/client.ts","../src/voiceCatalog.ts"],"sourcesContent":["export class AzureTtsError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly responseBody: string;\n readonly requestId: string | null;\n\n constructor(status: number, statusText: string, responseBody: string, requestId: string | null) {\n super(`Azure TTS request failed: ${status} ${statusText}`);\n this.name = \"AzureTtsError\";\n this.status = status;\n this.statusText = statusText;\n this.responseBody = responseBody;\n this.requestId = requestId;\n }\n}\n\nexport class AzureTtsSdkError extends AzureTtsError {\n readonly errorDetails: string;\n\n constructor(errorDetails: string) {\n super(0, \"Speech SDK\", errorDetails, null);\n this.name = \"AzureTtsSdkError\";\n this.message = `Azure TTS synthesis failed: ${errorDetails}`;\n this.errorDetails = errorDetails;\n }\n}\n\nexport function createSpeechSdkError(error: unknown): AzureTtsSdkError {\n const message = error instanceof Error ? error.message : String(error);\n return new AzureTtsSdkError(message);\n}\n","import * as SpeechSDK from \"microsoft-cognitiveservices-speech-sdk\";\nimport { createSpeechSdkError } from \"./errors.ts\";\nimport { createSpeechConfig } from \"./speechConfig.ts\";\nimport type { SsmlSynthesisChunk, SsmlSynthesisResult, TtsConfig } from \"./types.ts\";\n\nfunction closeSpeechResources(speechConfig: SpeechSDK.SpeechConfig, synthesizer: SpeechSDK.SpeechSynthesizer): void {\n try {\n synthesizer.close();\n } catch {}\n\n try {\n speechConfig.close();\n } catch {}\n}\n\nconst ticksToMilliseconds = (ticks: number): number => Math.max(0, ticks) / 10_000;\n\nexport async function synthesizeSsml(ssml: string, config: TtsConfig): Promise<SsmlSynthesisResult> {\n if (config.signal?.aborted) {\n throw createSpeechSdkError(\"Speech synthesis was cancelled.\");\n }\n\n const speechConfig = createSpeechConfig(config);\n const synthesizer = new SpeechSDK.SpeechSynthesizer(speechConfig, null);\n\n return await new Promise<SsmlSynthesisResult>((resolve, reject) => {\n let resourcesClosed = false;\n let settled = false;\n let timeout: ReturnType<typeof setTimeout> | undefined;\n let abortHandler: (() => void) | undefined;\n const cleanup = () => {\n if (timeout) clearTimeout(timeout);\n if (abortHandler) config.signal?.removeEventListener(\"abort\", abortHandler);\n };\n const closeResources = () => {\n if (resourcesClosed) return;\n resourcesClosed = true;\n closeSpeechResources(speechConfig, synthesizer);\n };\n const rejectWithError = (error: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n closeResources();\n reject(createSpeechSdkError(error));\n };\n\n const boundaries: SsmlSynthesisResult[\"boundaries\"] = [];\n const visemes: SsmlSynthesisResult[\"visemes\"] = [];\n const bookmarks: SsmlSynthesisResult[\"bookmarks\"] = [];\n synthesizer.wordBoundary = (_sender, event) => {\n boundaries.push({\n text: event.text,\n audioOffsetMs: ticksToMilliseconds(event.audioOffset),\n durationMs: ticksToMilliseconds(event.duration),\n });\n };\n synthesizer.visemeReceived = (_sender, event) => {\n visemes.push({ visemeId: event.visemeId, audioOffsetMs: ticksToMilliseconds(event.audioOffset) });\n };\n synthesizer.bookmarkReached = (_sender, event) => {\n bookmarks.push({ name: event.text, audioOffsetMs: ticksToMilliseconds(event.audioOffset) });\n };\n\n const cb = (result: SpeechSDK.SpeechSynthesisResult) => {\n if (settled) return;\n const { reason, errorDetails } = result;\n if (reason !== SpeechSDK.ResultReason.SynthesizingAudioCompleted) {\n const err = errorDetails || `Speech synthesis failed with reason ${reason}.`;\n rejectWithError(err);\n return;\n }\n settled = true;\n cleanup();\n closeResources();\n const eventDurationMs = Math.max(\n 0,\n ...(boundaries ?? []).map((boundary) => boundary.audioOffsetMs + boundary.durationMs),\n ...(visemes ?? []).map((viseme) => viseme.audioOffsetMs),\n ...(bookmarks ?? []).map((bookmark) => bookmark.audioOffsetMs),\n );\n const durationMs = result.audioDuration ? ticksToMilliseconds(result.audioDuration) : eventDurationMs;\n const requestId = (result as SpeechSDK.SpeechSynthesisResult & { resultId?: string }).resultId;\n const addSourceMetadata = <T extends { audioOffsetMs: number }>(event: T): T => ({\n ...event,\n ...(config.sourceTextRange ? { textRange: { ...config.sourceTextRange } } : {}),\n ...(requestId ? { requestId } : {}),\n });\n const sourceBoundaries = boundaries.map((boundary) => addSourceMetadata(boundary));\n const sourceVisemes = visemes.map((viseme) => addSourceMetadata(viseme));\n const sourceBookmarks = bookmarks.map((bookmark) => addSourceMetadata(bookmark));\n resolve({\n audioData: result.audioData,\n durationMs,\n ...(config.sourceTextRange ? { textRange: { ...config.sourceTextRange } } : {}),\n ...(requestId ? { requestId } : {}),\n ...(sourceBoundaries.length > 0\n ? { boundaries: sourceBoundaries, wordBoundary: sourceBoundaries, wordBoundaries: sourceBoundaries }\n : {}),\n ...(sourceVisemes.length > 0 ? { visemes: sourceVisemes } : {}),\n ...(sourceBookmarks.length > 0 ? { bookmarks: sourceBookmarks } : {}),\n });\n };\n\n try {\n if (config.signal) {\n abortHandler = () => rejectWithError(\"Speech synthesis was cancelled.\");\n config.signal.addEventListener(\"abort\", abortHandler, { once: true });\n }\n if (config.timeoutMs !== undefined && config.timeoutMs > 0) {\n timeout = setTimeout(\n () => rejectWithError(`Speech synthesis timed out after ${config.timeoutMs} ms.`),\n config.timeoutMs,\n );\n }\n synthesizer.speakSsmlAsync(ssml, cb, rejectWithError);\n } catch (error) {\n rejectWithError(error);\n }\n });\n}\n\n/** Synthesizes chunks sequentially, annotates synchronization events, and merges the results. */\nexport async function synthesizeSsmlChunks(\n chunks: readonly (SsmlSynthesisChunk | string)[],\n config: TtsConfig,\n): Promise<SsmlSynthesisResult> {\n const results: SsmlSynthesisResult[] = [];\n const totalChunks = chunks.length;\n for (const [index, chunk] of chunks.entries()) {\n const input = typeof chunk === \"string\" ? { ssml: chunk } : chunk;\n const result = await synthesizeSsml(input.ssml, {\n ...config,\n ...(input.originalTextRange ? { sourceTextRange: input.originalTextRange } : {}),\n onProgress: undefined,\n });\n results.push(result);\n config.onProgress?.({\n currentChunk: index + 1,\n totalChunks,\n percent: totalChunks === 0 ? 100 : Math.round(((index + 1) / totalChunks) * 100),\n });\n }\n return mergeSynthesisResults(results);\n}\n\n/** Concatenates audio buffers and shifts all synchronization events by prior chunk durations. */\nexport function mergeSynthesisResults(results: readonly SsmlSynthesisResult[]): SsmlSynthesisResult {\n const audioLength = results.reduce((total, result) => total + result.audioData.byteLength, 0);\n const audioData = new Uint8Array(audioLength);\n const boundaries: NonNullable<SsmlSynthesisResult[\"boundaries\"]> = [];\n const visemes: NonNullable<SsmlSynthesisResult[\"visemes\"]> = [];\n const bookmarks: NonNullable<SsmlSynthesisResult[\"bookmarks\"]> = [];\n let byteOffset = 0;\n let durationOffset = 0;\n\n for (const result of results) {\n audioData.set(new Uint8Array(result.audioData), byteOffset);\n byteOffset += result.audioData.byteLength;\n const chunkBoundaries =\n result.boundaries && result.boundaries.length > 0\n ? result.boundaries\n : (result.wordBoundary ?? result.wordBoundaries ?? []);\n for (const boundary of chunkBoundaries) {\n const textRange = boundary.textRange ?? result.textRange;\n const requestId = boundary.requestId ?? result.requestId;\n boundaries.push({\n ...boundary,\n audioOffsetMs: boundary.audioOffsetMs + durationOffset,\n ...(textRange ? { textRange: { ...textRange } } : {}),\n ...(requestId ? { requestId } : {}),\n });\n }\n for (const viseme of result.visemes ?? []) {\n const textRange = viseme.textRange ?? result.textRange;\n const requestId = viseme.requestId ?? result.requestId;\n visemes.push({\n ...viseme,\n audioOffsetMs: viseme.audioOffsetMs + durationOffset,\n ...(textRange ? { textRange: { ...textRange } } : {}),\n ...(requestId ? { requestId } : {}),\n });\n }\n for (const bookmark of result.bookmarks ?? []) {\n const textRange = bookmark.textRange ?? result.textRange;\n const requestId = bookmark.requestId ?? result.requestId;\n bookmarks.push({\n ...bookmark,\n audioOffsetMs: bookmark.audioOffsetMs + durationOffset,\n ...(textRange ? { textRange: { ...textRange } } : {}),\n ...(requestId ? { requestId } : {}),\n });\n }\n durationOffset += Math.max(0, result.durationMs);\n }\n\n return {\n audioData: audioData.buffer,\n durationMs: durationOffset,\n ...(boundaries.length > 0 ? { boundaries, wordBoundary: boundaries, wordBoundaries: boundaries } : {}),\n ...(visemes.length > 0 ? { visemes } : {}),\n ...(bookmarks.length > 0 ? { bookmarks } : {}),\n ...(results.length === 1 && results[0]?.requestId ? { requestId: results[0].requestId } : {}),\n ...(results.length === 1 && results[0]?.textRange ? { textRange: { ...results[0].textRange } } : {}),\n };\n}\n\n/** Backward-compatible audio-only synthesis helper. */\nexport async function synthesizeSpeech(ssml: string, config: TtsConfig): Promise<ArrayBuffer> {\n return (await synthesizeSsml(ssml, config)).audioData;\n}\n","import { SpeechConfig } from \"microsoft-cognitiveservices-speech-sdk\";\nimport { DEFAULT_OUTPUT_FORMAT, resolveOutputFormat } from \"./outputFormats.ts\";\nimport type { TtsConfig } from \"./types.ts\";\n\nexport function resolveEndpoint(config: TtsConfig): string {\n const endpoint = config.endpoint?.trim() || \"https://{region}.tts.speech.microsoft.com/cognitiveservices/v1\";\n return endpoint.replace(/\\{region\\}/g, encodeURIComponent(config.region));\n}\n\nexport function createSpeechConfig(config: TtsConfig): SpeechConfig {\n const { outputFormat = DEFAULT_OUTPUT_FORMAT, subscriptionKey } = config;\n\n const endpoint = new URL(resolveEndpoint(config));\n const speechConfig = SpeechConfig.fromEndpoint(endpoint, subscriptionKey);\n speechConfig.speechSynthesisOutputFormat = resolveOutputFormat(outputFormat);\n return speechConfig;\n}\n","import * as SpeechSDK from \"microsoft-cognitiveservices-speech-sdk\";\n\nexport const DEFAULT_OUTPUT_FORMAT = \"audio-16khz-128kbitrate-mono-mp3\";\n\nconst OUTPUT_FORMATS: Record<string, SpeechSDK.SpeechSynthesisOutputFormat> = {\n \"raw-8khz-8bit-mono-mulaw\": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz8BitMonoMULaw,\n \"riff-16khz-16kbps-mono-siren\": SpeechSDK.SpeechSynthesisOutputFormat.Riff16Khz16KbpsMonoSiren,\n \"audio-16khz-16kbps-mono-siren\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz16KbpsMonoSiren,\n \"audio-16khz-32kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz32KBitRateMonoMp3,\n \"audio-16khz-128kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz128KBitRateMonoMp3,\n \"audio-16khz-64kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz64KBitRateMonoMp3,\n \"audio-24khz-48kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz48KBitRateMonoMp3,\n \"audio-24khz-96kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz96KBitRateMonoMp3,\n \"audio-24khz-160kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz160KBitRateMonoMp3,\n \"raw-16khz-16bit-mono-truesilk\": SpeechSDK.SpeechSynthesisOutputFormat.Raw16Khz16BitMonoTrueSilk,\n \"riff-16khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff16Khz16BitMonoPcm,\n \"riff-8khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz16BitMonoPcm,\n \"riff-24khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm,\n \"riff-8khz-8bit-mono-mulaw\": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz8BitMonoMULaw,\n \"raw-16khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw16Khz16BitMonoPcm,\n \"raw-24khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoPcm,\n \"raw-8khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz16BitMonoPcm,\n \"ogg-16khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Ogg16Khz16BitMonoOpus,\n \"ogg-24khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Ogg24Khz16BitMonoOpus,\n \"raw-48khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw48Khz16BitMonoPcm,\n \"riff-48khz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff48Khz16BitMonoPcm,\n \"audio-48khz-96kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio48Khz96KBitRateMonoMp3,\n \"audio-48khz-192kbitrate-mono-mp3\": SpeechSDK.SpeechSynthesisOutputFormat.Audio48Khz192KBitRateMonoMp3,\n \"ogg-48khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Ogg48Khz16BitMonoOpus,\n \"webm-16khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Webm16Khz16BitMonoOpus,\n \"webm-24khz-16bit-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Webm24Khz16BitMonoOpus,\n \"webm-24khz-16bit-24kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Webm24Khz16Bit24KbpsMonoOpus,\n \"raw-24khz-16bit-mono-truesilk\": SpeechSDK.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoTrueSilk,\n \"raw-8khz-8bit-mono-alaw\": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz8BitMonoALaw,\n \"riff-8khz-8bit-mono-alaw\": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz8BitMonoALaw,\n \"audio-16khz-16bit-32kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz16Bit32KbpsMonoOpus,\n \"audio-24khz-16bit-48kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz16Bit48KbpsMonoOpus,\n \"audio-24khz-16bit-24kbps-mono-opus\": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz16Bit24KbpsMonoOpus,\n \"raw-22050hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw22050Hz16BitMonoPcm,\n \"riff-22050hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff22050Hz16BitMonoPcm,\n \"raw-44100hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Raw44100Hz16BitMonoPcm,\n \"riff-44100hz-16bit-mono-pcm\": SpeechSDK.SpeechSynthesisOutputFormat.Riff44100Hz16BitMonoPcm,\n \"amr-wb-16000hz\": SpeechSDK.SpeechSynthesisOutputFormat.AmrWb16000Hz,\n \"g722-16khz-64kbps\": SpeechSDK.SpeechSynthesisOutputFormat.G72216Khz64Kbps,\n};\n\nexport function resolveOutputFormat(outputFormat: string): SpeechSDK.SpeechSynthesisOutputFormat {\n const resolvedFormat = OUTPUT_FORMATS[outputFormat];\n if (resolvedFormat === undefined) {\n throw new Error(`Unsupported Azure Speech output format: ${outputFormat}`);\n }\n\n return resolvedFormat;\n}\n","import { validateAzureSsml, type AzureValidationOptions, type SsmlDiagnostic } from \"@ssml-builder-js/ssml-core\";\nimport { AzureTtsError, createSpeechSdkError } from \"./errors.ts\";\nimport type { AzureTtsClient } from \"./client.ts\";\nimport type { SsmlSynthesisResult } from \"./types.ts\";\n\nexport interface SsmlValidationError {\n readonly kind: \"validation\";\n readonly message: string;\n readonly diagnostics: readonly SsmlDiagnostic[];\n}\n\nexport type Result<T, E> =\n | { readonly ok: true; readonly success: true; readonly status: \"success\"; readonly value: T }\n | {\n readonly ok: false;\n readonly success: false;\n readonly status: \"validation-error\" | \"azure-api-error\";\n readonly error: E;\n };\n\nexport type SynthesisResult<T, E> = Result<T, E>;\n\nexport type Success<T> = Extract<Result<T, never>, { readonly ok: true }>;\nexport type ValidationErrorResult = Extract<\n Result<never, SsmlValidationError>,\n { readonly status: \"validation-error\" }\n>;\nexport type AzureApiErrorResult = Extract<Result<never, AzureTtsError>, { readonly status: \"azure-api-error\" }>;\n\nexport type SsmlSynthesisSafeResult =\n | Result<SsmlSynthesisResult, never>\n | Result<never, SsmlValidationError>\n | Result<never, AzureTtsError>;\n\nexport interface SynthesizeSsmlSafeOptions extends AzureValidationOptions {\n /** Optional nested form for callers that want to keep validation settings grouped. */\n validation?: AzureValidationOptions;\n}\n\ninterface SynthesisClient {\n synthesizeSsml(ssml: string): Promise<SsmlSynthesisResult>;\n}\n\n/** Validates SSML before invoking Azure and converts validation/API failures to one result shape. */\nexport async function synthesizeSsmlSafe(\n client: Pick<AzureTtsClient, \"synthesizeSsml\"> | SynthesisClient,\n ssml: string,\n options: SynthesizeSsmlSafeOptions = {},\n): Promise<SsmlSynthesisSafeResult> {\n const validationOptions = options.validation ?? options;\n const diagnostics = await Promise.resolve(validateAzureSsml(ssml, validationOptions));\n const errors = diagnostics.filter((diagnostic) => diagnostic.severity === \"error\");\n if (errors.length > 0) {\n return {\n ok: false,\n success: false,\n status: \"validation-error\",\n error: {\n kind: \"validation\",\n message: \"SSML validation failed; the Azure Speech API was not called.\",\n diagnostics: errors,\n },\n };\n }\n\n try {\n return { ok: true, success: true, status: \"success\", value: await client.synthesizeSsml(ssml) };\n } catch (error) {\n const azureError = error instanceof AzureTtsError ? error : createSpeechSdkError(error);\n return { ok: false, success: false, status: \"azure-api-error\", error: azureError };\n }\n}\n","import { synthesizeSpeech, synthesizeSsml, synthesizeSsmlChunks } from \"./synthesis.ts\";\nimport { synthesizeSsmlSafe } from \"./safe.ts\";\nimport type { SynthesizeSsmlSafeOptions } from \"./safe.ts\";\nimport type {\n AzureTtsClientOptions,\n SsmlSynthesisChunk,\n SsmlSynthesisResult,\n SynthesizeChunksOptions,\n} from \"./types.ts\";\n\nconst ENDPOINT_TEMPLATE = \"https://{region}.tts.speech.microsoft.com/cognitiveservices/v1\";\n\nexport class AzureTtsClient {\n readonly #options: AzureTtsClientOptions;\n\n constructor(options: AzureTtsClientOptions) {\n this.#options = options;\n }\n\n async synthesize(ssml: string): Promise<ArrayBuffer> {\n const { region, subscriptionKey, outputFormat, signal, timeoutMs } = this.#options;\n const endpoint = this.#options.endpoint?.trim() || ENDPOINT_TEMPLATE.replace(\"{region}\", region);\n this.#options.logger?.debug?.(\"Using Azure TTS endpoint:\", endpoint);\n\n const config = { endpoint, region, subscriptionKey, outputFormat, signal, timeoutMs };\n return synthesizeSpeech(ssml, config);\n }\n\n async synthesizeSsml(ssml: string): Promise<SsmlSynthesisResult> {\n const { region, subscriptionKey, outputFormat, signal, timeoutMs } = this.#options;\n const endpoint = this.#options.endpoint?.trim() || ENDPOINT_TEMPLATE.replace(\"{region}\", region);\n this.#options.logger?.debug?.(\"Using Azure TTS endpoint:\", endpoint);\n\n return synthesizeSsml(ssml, { endpoint, region, subscriptionKey, outputFormat, signal, timeoutMs });\n }\n\n async synthesizeChunks(\n chunks: readonly (SsmlSynthesisChunk | string)[],\n options: SynthesizeChunksOptions = {},\n ): Promise<SsmlSynthesisResult> {\n const { region, subscriptionKey, outputFormat, signal, timeoutMs } = this.#options;\n const endpoint = this.#options.endpoint?.trim() || ENDPOINT_TEMPLATE.replace(\"{region}\", region);\n return synthesizeSsmlChunks(chunks, {\n endpoint,\n region,\n subscriptionKey,\n outputFormat,\n signal,\n timeoutMs,\n onProgress: options.onProgress ?? this.#options.onProgress,\n });\n }\n\n async synthesizeSsmlSafe(ssml: string, options: SynthesizeSsmlSafeOptions = {}) {\n return synthesizeSsmlSafe(this, ssml, options);\n }\n}\n","const AZURE_VOICE_API_VERSION = \"2025-10-01\";\n\nexport interface FetchAzureVoiceCatalogOptions {\n apiKey: string;\n region: string | string[];\n}\n\nexport interface AzureVoiceCatalogVoice {\n name: string;\n locale: string;\n secondaryLocales?: readonly string[];\n styles?: readonly string[];\n regions: readonly string[];\n status?: \"ga\" | \"preview\" | \"deprecated\";\n}\n\nexport interface FetchedAzureVoiceCatalogMetadata {\n voiceCount: number;\n generatedAt: string;\n apiVersion: string;\n regions: readonly string[];\n}\n\nexport interface AzureVoiceCatalog {\n voices: readonly AzureVoiceCatalogVoice[];\n metadata: FetchedAzureVoiceCatalogMetadata;\n}\n\ninterface AzureVoiceApiRecord {\n Locale?: unknown;\n Name?: unknown;\n SecondaryLocaleList?: unknown;\n ShortName?: unknown;\n Status?: unknown;\n StyleList?: unknown;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction stringList(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return [...new Set(value.map(stringValue).filter((item): item is string => item !== undefined))];\n}\n\nfunction normalizeStatus(value: unknown): AzureVoiceCatalogVoice[\"status\"] {\n const status = stringValue(value)?.toLowerCase();\n if (status === \"preview\" || status === \"deprecated\" || status === \"ga\") return status;\n return undefined;\n}\n\nfunction normalizeRegions(region: string | string[]): string[] {\n const regions = Array.isArray(region) ? region : [region];\n const result = [...new Set(regions.map((item) => item.trim()).filter(Boolean))];\n if (result.length === 0) throw new TypeError(\"At least one Azure Speech region is required.\");\n return result;\n}\n\nasync function fetchRegionVoices(region: string, apiKey: string): Promise<AzureVoiceApiRecord[]> {\n const endpoint = `https://${encodeURIComponent(region)}.tts.speech.microsoft.com/cognitiveservices/voices/list`;\n const response = await fetch(endpoint, {\n headers: {\n Accept: \"application/json\",\n \"Ocp-Apim-Subscription-Key\": apiKey,\n },\n });\n if (!response.ok) {\n throw new Error(`Azure List Voices API request failed for region \"${region}\" with HTTP ${response.status}.`);\n }\n const payload: unknown = await response.json();\n if (!Array.isArray(payload)) throw new Error(`Azure List Voices API returned an invalid response for \"${region}\".`);\n return payload.filter((item): item is AzureVoiceApiRecord => Boolean(item && typeof item === \"object\"));\n}\n\n/** Fetches and deduplicates the current Azure Speech voice catalog for one or more regions. */\nexport async function fetchAzureVoiceCatalog(options: FetchAzureVoiceCatalogOptions): Promise<AzureVoiceCatalog> {\n if (!options || typeof options.apiKey !== \"string\" || !options.apiKey.trim())\n throw new TypeError(\"An Azure Speech API key is required.\");\n const regions = normalizeRegions(options.region);\n const payloads = await Promise.all(regions.map((region) => fetchRegionVoices(region, options.apiKey)));\n const voices = new Map<string, AzureVoiceCatalogVoice>();\n\n for (let regionIndex = 0; regionIndex < payloads.length; regionIndex += 1) {\n const region = regions[regionIndex];\n for (const record of payloads[regionIndex]) {\n const name = stringValue(record.ShortName) ?? stringValue(record.Name);\n const locale = stringValue(record.Locale);\n if (!name || !locale) continue;\n const key = name.toLowerCase();\n const existing = voices.get(key);\n const secondaryLocales = stringList(record.SecondaryLocaleList);\n const styles = stringList(record.StyleList);\n const status = normalizeStatus(record.Status);\n const merged: AzureVoiceCatalogVoice = {\n name: existing?.name ?? name,\n locale: existing?.locale ?? locale,\n regions: [...new Set([...(existing?.regions ?? []), region])],\n };\n const mergedSecondaryLocales = [...new Set([...(existing?.secondaryLocales ?? []), ...secondaryLocales])];\n if (mergedSecondaryLocales.length > 0) merged.secondaryLocales = mergedSecondaryLocales;\n const mergedStyles = [...new Set([...(existing?.styles ?? []), ...styles])];\n if (mergedStyles.length > 0) merged.styles = mergedStyles;\n if (status) merged.status = status;\n else if (existing?.status) merged.status = existing.status;\n voices.set(key, merged);\n }\n }\n\n const sortedVoices = [...voices.values()].sort((first, second) => first.name.localeCompare(second.name));\n return {\n voices: sortedVoices,\n metadata: {\n voiceCount: sortedVoices.length,\n generatedAt: new Date().toISOString(),\n apiVersion: AZURE_VOICE_API_VERSION,\n regions,\n },\n };\n}\n"],"mappings":"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","names":["SpeechSDK"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ssml-builder-js/azure-tts-client",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.0",
|
|
4
4
|
"description": "Azure Text-to-Speech client using the Microsoft Speech SDK",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"typescript": "^6.0.3"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
+
"@ssml-builder-js/ssml-core": "^2.13.0",
|
|
38
39
|
"microsoft-cognitiveservices-speech-sdk": "1.51.0"
|
|
39
40
|
}
|
|
40
41
|
}
|
package/src/client.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import { synthesizeSpeech } from "./synthesis.ts";
|
|
2
|
-
import
|
|
1
|
+
import { synthesizeSpeech, synthesizeSsml, synthesizeSsmlChunks } from "./synthesis.ts";
|
|
2
|
+
import { synthesizeSsmlSafe } from "./safe.ts";
|
|
3
|
+
import type { SynthesizeSsmlSafeOptions } from "./safe.ts";
|
|
4
|
+
import type {
|
|
5
|
+
AzureTtsClientOptions,
|
|
6
|
+
SsmlSynthesisChunk,
|
|
7
|
+
SsmlSynthesisResult,
|
|
8
|
+
SynthesizeChunksOptions,
|
|
9
|
+
} from "./types.ts";
|
|
3
10
|
|
|
4
11
|
const ENDPOINT_TEMPLATE = "https://{region}.tts.speech.microsoft.com/cognitiveservices/v1";
|
|
5
12
|
|
|
@@ -18,4 +25,33 @@ export class AzureTtsClient {
|
|
|
18
25
|
const config = { endpoint, region, subscriptionKey, outputFormat, signal, timeoutMs };
|
|
19
26
|
return synthesizeSpeech(ssml, config);
|
|
20
27
|
}
|
|
28
|
+
|
|
29
|
+
async synthesizeSsml(ssml: string): Promise<SsmlSynthesisResult> {
|
|
30
|
+
const { region, subscriptionKey, outputFormat, signal, timeoutMs } = this.#options;
|
|
31
|
+
const endpoint = this.#options.endpoint?.trim() || ENDPOINT_TEMPLATE.replace("{region}", region);
|
|
32
|
+
this.#options.logger?.debug?.("Using Azure TTS endpoint:", endpoint);
|
|
33
|
+
|
|
34
|
+
return synthesizeSsml(ssml, { endpoint, region, subscriptionKey, outputFormat, signal, timeoutMs });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async synthesizeChunks(
|
|
38
|
+
chunks: readonly (SsmlSynthesisChunk | string)[],
|
|
39
|
+
options: SynthesizeChunksOptions = {},
|
|
40
|
+
): Promise<SsmlSynthesisResult> {
|
|
41
|
+
const { region, subscriptionKey, outputFormat, signal, timeoutMs } = this.#options;
|
|
42
|
+
const endpoint = this.#options.endpoint?.trim() || ENDPOINT_TEMPLATE.replace("{region}", region);
|
|
43
|
+
return synthesizeSsmlChunks(chunks, {
|
|
44
|
+
endpoint,
|
|
45
|
+
region,
|
|
46
|
+
subscriptionKey,
|
|
47
|
+
outputFormat,
|
|
48
|
+
signal,
|
|
49
|
+
timeoutMs,
|
|
50
|
+
onProgress: options.onProgress ?? this.#options.onProgress,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async synthesizeSsmlSafe(ssml: string, options: SynthesizeSsmlSafeOptions = {}) {
|
|
55
|
+
return synthesizeSsmlSafe(this, ssml, options);
|
|
56
|
+
}
|
|
21
57
|
}
|
package/src/index.ts
CHANGED
|
@@ -2,10 +2,34 @@
|
|
|
2
2
|
* azure-tts-client: Azure Text-to-Speech client for SSML playback.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export type {
|
|
5
|
+
export type {
|
|
6
|
+
AzureTtsClientOptions,
|
|
7
|
+
AzureTtsLogger,
|
|
8
|
+
SsmlSynthesisBookmark,
|
|
9
|
+
SsmlSynthesisBoundary,
|
|
10
|
+
SsmlSynthesisResult,
|
|
11
|
+
SsmlSynthesisViseme,
|
|
12
|
+
SsmlSynthesisChunk,
|
|
13
|
+
SynthesisProgressEvent,
|
|
14
|
+
SynthesizeChunksOptions,
|
|
15
|
+
TtsConfig,
|
|
16
|
+
} from "./types.ts";
|
|
6
17
|
export { AzureTtsError, AzureTtsSdkError } from "./errors.ts";
|
|
7
18
|
export { AzureTtsClient } from "./client.ts";
|
|
8
19
|
export { synthesizeSpeech } from "./synthesis.ts";
|
|
20
|
+
export { synthesizeSsml } from "./synthesis.ts";
|
|
21
|
+
export { mergeSynthesisResults, synthesizeSsmlChunks } from "./synthesis.ts";
|
|
22
|
+
export { synthesizeSsmlSafe } from "./safe.ts";
|
|
23
|
+
export type {
|
|
24
|
+
AzureApiErrorResult,
|
|
25
|
+
Result,
|
|
26
|
+
SsmlSynthesisSafeResult,
|
|
27
|
+
SsmlValidationError as AzureSsmlValidationError,
|
|
28
|
+
Success,
|
|
29
|
+
SynthesisResult,
|
|
30
|
+
SynthesizeSsmlSafeOptions,
|
|
31
|
+
ValidationErrorResult,
|
|
32
|
+
} from "./safe.ts";
|
|
9
33
|
export { fetchAzureVoiceCatalog } from "./voiceCatalog.ts";
|
|
10
34
|
export type {
|
|
11
35
|
AzureVoiceCatalog,
|