ssml-builder-js 2.13.0 → 2.14.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/README.md +8 -0
- package/dist/{chunk-25LOR4AJ.mjs → chunk-AQ55MOPU.mjs} +115 -14
- package/dist/chunk-AQ55MOPU.mjs.map +1 -0
- package/dist/{chunk-CZ2F3TET.mjs → chunk-QFIBPCO4.mjs} +80 -9
- package/dist/chunk-QFIBPCO4.mjs.map +1 -0
- package/dist/{chunk-LCTE26LS.mjs → chunk-UZSCXPC5.mjs} +2 -2
- package/dist/core.d.mts +18 -1
- package/dist/core.d.ts +18 -1
- package/dist/core.js +115 -13
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +3 -1
- package/dist/elements.js +79 -8
- package/dist/elements.js.map +1 -1
- package/dist/elements.mjs +2 -2
- package/dist/{index.d-Xbr6ZWnK.d.mts → index.d-CUXRwSw0.d.mts} +19 -1
- package/dist/{index.d-Xbr6ZWnK.d.ts → index.d-CUXRwSw0.d.ts} +19 -1
- package/dist/index.d.mts +66 -10
- package/dist/index.d.ts +66 -10
- package/dist/index.js +557 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +361 -17
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +5 -1
- package/dist/react.d.ts +5 -1
- package/dist/react.js +106 -12
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +29 -6
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-25LOR4AJ.mjs.map +0 -1
- package/dist/chunk-CZ2F3TET.mjs.map +0 -1
- /package/dist/{chunk-LCTE26LS.mjs.map → chunk-UZSCXPC5.mjs.map} +0 -0
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../packages/azure-tts-client/src/errors.ts","../packages/azure-tts-client/src/synthesis.ts","../packages/azure-tts-client/src/speechConfig.ts","../packages/azure-tts-client/src/outputFormats.ts","../packages/azure-tts-client/src/safe.ts","../packages/azure-tts-client/src/client.ts","../packages/azure-tts-client/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","validateAzureSsml"]}
|
|
1
|
+
{"version":3,"sources":["../packages/azure-tts-client/src/errors.ts","../packages/azure-tts-client/src/synthesis.ts","../packages/azure-tts-client/src/speechConfig.ts","../packages/azure-tts-client/src/outputFormats.ts","../packages/azure-tts-client/src/safe.ts","../packages/azure-tts-client/src/client.ts","../packages/azure-tts-client/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\n/** Thrown when audio buffers require container re-multiplexing before they can be merged. */\nexport class UnsupportedMergeFormatError extends Error {\n readonly format: string;\n\n constructor(format: string) {\n super(`Audio format \"${format}\" cannot be safely concatenated; container re-multiplexing is required.`);\n this.name = \"UnsupportedMergeFormatError\";\n this.format = format;\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, UnsupportedMergeFormatError } from \"./errors.ts\";\nimport { createSpeechConfig } from \"./speechConfig.ts\";\nimport type { SsmlSynthesisChunk, SsmlSynthesisResult, SynthesisProgressEvent, TtsConfig } from \"./types.ts\";\n\nexport type MergeAudioFormat = \"wav\" | \"mp3\" | \"raw\";\n\nfunction ascii(bytes: Uint8Array, offset: number, value: string): boolean {\n return [...value].every((character, index) => bytes[offset + index] === character.charCodeAt(0));\n}\n\nfunction readUint32(bytes: Uint8Array, offset: number): number {\n return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(offset, true);\n}\n\ninterface RiffChunk {\n id: string;\n data: Uint8Array;\n}\n\ninterface ParsedWav {\n chunks: RiffChunk[];\n data: Uint8Array;\n format: Uint8Array;\n}\n\nfunction parseWav(buffer: ArrayBuffer): ParsedWav {\n const bytes = new Uint8Array(buffer);\n if (bytes.byteLength < 12 || !ascii(bytes, 0, \"RIFF\") || !ascii(bytes, 8, \"WAVE\")) {\n throw new Error(\"Invalid WAV/RIFF audio buffer.\");\n }\n const chunks: RiffChunk[] = [];\n const dataParts: Uint8Array[] = [];\n let format: Uint8Array | undefined;\n let offset = 12;\n while (offset < bytes.byteLength) {\n if (offset + 8 > bytes.byteLength) throw new Error(\"Invalid WAV chunk header.\");\n const id = String.fromCharCode(...bytes.slice(offset, offset + 4));\n const size = readUint32(bytes, offset + 4);\n const dataStart = offset + 8;\n const dataEnd = dataStart + size;\n if (dataEnd > bytes.byteLength) throw new Error(`WAV chunk \"${id}\" exceeds the audio buffer.`);\n const data = bytes.slice(dataStart, dataEnd);\n chunks.push({ id, data });\n if (id === \"fmt \") format ??= data;\n if (id === \"data\") dataParts.push(data);\n offset = dataEnd + (size & 1);\n if (offset > bytes.byteLength) throw new Error(\"Invalid WAV chunk padding.\");\n }\n if (!format || dataParts.length === 0) throw new Error(\"WAV audio must contain fmt and data chunks.\");\n const dataLength = dataParts.reduce((total, part) => total + part.byteLength, 0);\n const data = new Uint8Array(dataLength);\n let dataOffset = 0;\n for (const part of dataParts) {\n data.set(part, dataOffset);\n dataOffset += part.byteLength;\n }\n return { chunks, data, format };\n}\n\nfunction writeUint32(target: Uint8Array, offset: number, value: number): void {\n new DataView(target.buffer).setUint32(offset, value, true);\n}\n\nfunction writeChunk(target: Uint8Array, offset: number, id: string, data: Uint8Array): number {\n for (let index = 0; index < 4; index += 1) target[offset + index] = id.charCodeAt(index) ?? 0;\n writeUint32(target, offset + 4, data.byteLength);\n target.set(data, offset + 8);\n const end = offset + 8 + data.byteLength;\n if (data.byteLength & 1) target[end] = 0;\n return end + (data.byteLength & 1);\n}\n\nfunction mergeWavBuffers(buffers: readonly ArrayBuffer[]): ArrayBuffer {\n if (buffers.length === 0) return new ArrayBuffer(0);\n const parsed = buffers.map(parseWav);\n const first = parsed[0];\n if (!first) throw new Error(\"At least one WAV buffer is required.\");\n if (\n parsed.some(\n (item) => item.format.length !== first.format.length || item.format.some((value, i) => value !== first.format[i]),\n )\n )\n throw new Error(\"WAV buffers have incompatible fmt chunks.\");\n const dataLength = parsed.reduce((total, item) => total + item.data.byteLength, 0);\n const nonDataLength = first.chunks.reduce(\n (total, chunk) => (chunk.id === \"data\" ? total : total + 8 + chunk.data.byteLength + (chunk.data.byteLength & 1)),\n 0,\n );\n const outputLength = 12 + nonDataLength + 8 + dataLength + (dataLength & 1);\n if (outputLength - 8 > 0xffffffff) throw new RangeError(\"Merged WAV exceeds the RIFF format size limit.\");\n const output = new Uint8Array(outputLength);\n output.set(Uint8Array.from([0x52, 0x49, 0x46, 0x46]), 0);\n writeUint32(output, 4, outputLength - 8);\n output.set(Uint8Array.from([0x57, 0x41, 0x56, 0x45]), 8);\n let outputOffset = 12;\n let dataWritten = false;\n for (const chunk of first.chunks) {\n if (chunk.id === \"data\") {\n if (dataWritten) continue;\n const data = new Uint8Array(dataLength);\n let dataOffset = 0;\n for (const item of parsed) {\n data.set(item.data, dataOffset);\n dataOffset += item.data.byteLength;\n }\n outputOffset = writeChunk(output, outputOffset, \"data\", data);\n dataWritten = true;\n } else {\n outputOffset = writeChunk(output, outputOffset, chunk.id, chunk.data);\n }\n }\n if (!dataWritten) throw new Error(\"WAV audio must contain a data chunk.\");\n return output.buffer;\n}\n\nfunction skipId3v2(bytes: Uint8Array): number {\n if (!ascii(bytes, 0, \"ID3\") || bytes.byteLength < 10) return 0;\n const size = [bytes[6], bytes[7], bytes[8], bytes[9]].reduce((total, value) => (total << 7) | (value & 0x7f), 0);\n const hasFooter = (bytes[5] & 0x10) !== 0;\n return Math.min(bytes.byteLength, 10 + size + (hasFooter ? 10 : 0));\n}\n\nfunction stripMp3Tags(buffer: ArrayBuffer): Uint8Array {\n const bytes = new Uint8Array(buffer);\n const start = skipId3v2(bytes);\n const end =\n bytes.byteLength >= 128 && ascii(bytes, bytes.byteLength - 128, \"TAG\") ? bytes.byteLength - 128 : bytes.byteLength;\n return bytes.slice(Math.min(start, end), end);\n}\n\nfunction isMp3Format(format: string): boolean {\n return /(?:mp3|mpeg)/i.test(format);\n}\n\nfunction isWavFormat(format: string): boolean {\n return /(?:wav|wave|riff)/i.test(format);\n}\n\nfunction isRawFormat(format: string): boolean {\n return /^raw(?:-|$)/i.test(format);\n}\n\n/** Returns whether the named output format can be safely concatenated without re-multiplexing. */\nexport function resolveMergeAudioFormat(format: string): MergeAudioFormat | undefined {\n if (isWavFormat(format)) return \"wav\";\n if (isMp3Format(format)) return \"mp3\";\n if (isRawFormat(format)) return \"raw\";\n return undefined;\n}\n\nexport function canMergeAudioFormat(format: string): boolean {\n return resolveMergeAudioFormat(format) !== undefined;\n}\n\n/** Merges audio buffers while preserving the invariants of supported containers. */\nexport function mergeAudioBuffers(buffers: readonly ArrayBuffer[], format: string): ArrayBuffer {\n if (isWavFormat(format)) return mergeWavBuffers(buffers);\n if (isMp3Format(format)) {\n const parts = buffers.map(stripMp3Tags);\n const output = new Uint8Array(parts.reduce((total, part) => total + part.byteLength, 0));\n let offset = 0;\n for (const part of parts) {\n output.set(part, offset);\n offset += part.byteLength;\n }\n return output.buffer;\n }\n if (isRawFormat(format)) {\n const output = new Uint8Array(buffers.reduce((total, buffer) => total + buffer.byteLength, 0));\n let offset = 0;\n for (const buffer of buffers) {\n output.set(new Uint8Array(buffer), offset);\n offset += buffer.byteLength;\n }\n return output.buffer;\n }\n throw new UnsupportedMergeFormatError(format);\n}\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 ...(config.sourceTextRange ? { originalTextRange: { ...config.sourceTextRange } } : {}),\n ...(config.chunkIndex !== undefined ? { chunkIndex: config.chunkIndex } : {}),\n ...(config.sourceNodePath ? { sourceNodePath: [...config.sourceNodePath] } : {}),\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 const report = (event: SynthesisProgressEvent): void => config.onProgress?.(event);\n for (const [index, chunk] of chunks.entries()) {\n const input = typeof chunk === \"string\" ? { ssml: chunk } : chunk;\n report({\n currentChunk: index,\n totalChunks,\n percent: totalChunks === 0 ? 100 : Math.round((index / totalChunks) * 100),\n chunkIndex: index,\n originalTextRange: input.originalTextRange,\n status: \"pending\",\n durationMs: 0,\n });\n }\n for (const [index, chunk] of chunks.entries()) {\n const input = typeof chunk === \"string\" ? { ssml: chunk } : chunk;\n report({\n currentChunk: index,\n totalChunks,\n percent: totalChunks === 0 ? 100 : Math.round((index / totalChunks) * 100),\n chunkIndex: index,\n originalTextRange: input.originalTextRange,\n status: \"synthesizing\",\n durationMs: 0,\n });\n const startedAt = Date.now();\n try {\n const result = await synthesizeSsml(input.ssml, {\n ...config,\n ...(input.originalTextRange ? { sourceTextRange: input.originalTextRange } : {}),\n ...(input.sourceNodePath ? { sourceNodePath: input.sourceNodePath } : {}),\n chunkIndex: index,\n onProgress: undefined,\n });\n results.push(result);\n report({\n currentChunk: index + 1,\n totalChunks,\n percent: totalChunks === 0 ? 100 : Math.round(((index + 1) / totalChunks) * 100),\n chunkIndex: index,\n originalTextRange: input.originalTextRange,\n status: \"success\",\n durationMs: Date.now() - startedAt,\n });\n } catch (error) {\n report({\n currentChunk: index,\n totalChunks,\n percent: totalChunks === 0 ? 100 : Math.round((index / totalChunks) * 100),\n chunkIndex: index,\n originalTextRange: input.originalTextRange,\n status: \"failed\",\n durationMs: Date.now() - startedAt,\n error,\n });\n throw error;\n }\n }\n return mergeSynthesisResults(results, config.outputFormat ?? \"audio-16khz-128kbitrate-mono-mp3\");\n}\n\n/** Concatenates audio buffers and shifts all synchronization events by prior chunk durations. */\nexport function mergeSynthesisResults(results: readonly SsmlSynthesisResult[], format?: string): SsmlSynthesisResult {\n const audioData = format\n ? new Uint8Array(\n mergeAudioBuffers(\n results.map((result) => result.audioData),\n format,\n ),\n )\n : new Uint8Array(results.reduce((total, result) => total + result.audioData.byteLength, 0));\n if (!format) {\n let offset = 0;\n for (const result of results) {\n audioData.set(new Uint8Array(result.audioData), offset);\n offset += result.audioData.byteLength;\n }\n }\n const boundaries: NonNullable<SsmlSynthesisResult[\"boundaries\"]> = [];\n const visemes: NonNullable<SsmlSynthesisResult[\"visemes\"]> = [];\n const bookmarks: NonNullable<SsmlSynthesisResult[\"bookmarks\"]> = [];\n let durationOffset = 0;\n\n for (const result of results) {\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 originalTextRange = boundary.originalTextRange ?? textRange;\n const requestId = boundary.requestId ?? result.requestId;\n boundaries.push({\n ...boundary,\n audioOffsetMs: boundary.audioOffsetMs + durationOffset,\n chunkAudioOffsetMs: boundary.chunkAudioOffsetMs ?? boundary.audioOffsetMs,\n ...(boundary.chunkIndex === undefined ? { chunkIndex: results.indexOf(result) } : {}),\n ...(boundary.sourceNodePath ? { sourceNodePath: [...boundary.sourceNodePath] } : {}),\n ...(originalTextRange ? { originalTextRange: { ...originalTextRange } } : {}),\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 originalTextRange = viseme.originalTextRange ?? textRange;\n const requestId = viseme.requestId ?? result.requestId;\n visemes.push({\n ...viseme,\n audioOffsetMs: viseme.audioOffsetMs + durationOffset,\n chunkAudioOffsetMs: viseme.chunkAudioOffsetMs ?? viseme.audioOffsetMs,\n ...(viseme.chunkIndex === undefined ? { chunkIndex: results.indexOf(result) } : {}),\n ...(viseme.sourceNodePath ? { sourceNodePath: [...viseme.sourceNodePath] } : {}),\n ...(originalTextRange ? { originalTextRange: { ...originalTextRange } } : {}),\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 originalTextRange = bookmark.originalTextRange ?? textRange;\n const requestId = bookmark.requestId ?? result.requestId;\n bookmarks.push({\n ...bookmark,\n audioOffsetMs: bookmark.audioOffsetMs + durationOffset,\n chunkAudioOffsetMs: bookmark.chunkAudioOffsetMs ?? bookmark.audioOffsetMs,\n ...(bookmark.chunkIndex === undefined ? { chunkIndex: results.indexOf(result) } : {}),\n ...(bookmark.sourceNodePath ? { sourceNodePath: [...bookmark.sourceNodePath] } : {}),\n ...(originalTextRange ? { originalTextRange: { ...originalTextRange } } : {}),\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 { mergeSynthesisResults } from \"./synthesis.ts\";\nimport type { SsmlSynthesisChunk, SsmlSynthesisResult, SynthesisProgressEvent } from \"./types.ts\";\n\nexport interface SsmlValidationError {\n readonly kind: \"validation\";\n readonly message: string;\n readonly diagnostics: readonly SsmlDiagnostic[];\n}\n\nexport class ChunkValidationError extends Error {\n readonly kind = \"chunk-validation\" as const;\n readonly chunkIndex: number;\n readonly diagnostics: readonly SsmlDiagnostic[];\n\n constructor(chunkIndex: number, diagnostics: readonly SsmlDiagnostic[]) {\n super(`SSML validation failed for chunk ${chunkIndex}; the Azure Speech API was not called.`);\n this.name = \"ChunkValidationError\";\n this.chunkIndex = chunkIndex;\n this.diagnostics = diagnostics;\n }\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\nexport interface SynthesizeSsmlChunksSafeOptions extends AzureValidationOptions {\n validation?: AzureValidationOptions;\n outputFormat?: string;\n onProgress?: (event: SynthesisProgressEvent) => void;\n}\n\nexport type SsmlSynthesisChunksSafeResult =\n | Result<SsmlSynthesisResult, never>\n | Result<never, ChunkValidationError>\n | Result<never, AzureTtsError>;\n\ninterface SynthesisClient {\n synthesizeSsml(ssml: string): Promise<SsmlSynthesisResult>;\n synthesizeChunks?(\n chunks: readonly (SsmlSynthesisChunk | string)[],\n options?: { onProgress?: (event: SynthesisProgressEvent) => void },\n ): 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\n/** Validates every chunk before synthesis and returns a chunk-addressable result. */\nexport async function synthesizeSsmlChunksSafe(\n client: Pick<AzureTtsClient, \"synthesizeSsml\" | \"synthesizeChunks\"> | SynthesisClient,\n chunks: readonly (SsmlSynthesisChunk | string)[],\n options: SynthesizeSsmlChunksSafeOptions = {},\n): Promise<SsmlSynthesisChunksSafeResult> {\n const validationOptions = options.validation ?? options;\n const pending = (index: number, status: SynthesisProgressEvent[\"status\"], error?: unknown): void => {\n options.onProgress?.({\n currentChunk: status === \"success\" ? index + 1 : index,\n totalChunks: chunks.length,\n percent:\n chunks.length === 0 ? 100 : Math.round(((status === \"success\" ? index + 1 : index) / chunks.length) * 100),\n chunkIndex: index,\n originalTextRange: typeof chunks[index] === \"string\" ? undefined : chunks[index]?.originalTextRange,\n status,\n durationMs: 0,\n ...(error ? { error } : {}),\n });\n };\n chunks.forEach((_chunk, index) => {\n pending(index, \"pending\");\n });\n const validations = await Promise.all(\n chunks.map(async (chunk) => {\n const ssml = typeof chunk === \"string\" ? chunk : chunk.ssml;\n const diagnostics = await Promise.resolve(validateAzureSsml(ssml, validationOptions));\n return diagnostics.filter((diagnostic) => diagnostic.severity === \"error\");\n }),\n );\n const firstInvalidIndex = validations.findIndex((diagnostics) => diagnostics.length > 0);\n if (firstInvalidIndex >= 0) {\n const error = new ChunkValidationError(firstInvalidIndex, validations[firstInvalidIndex] ?? []);\n pending(firstInvalidIndex, \"failed\", error);\n return { ok: false, success: false, status: \"validation-error\", error };\n }\n\n try {\n if (client.synthesizeChunks) {\n const value = await client.synthesizeChunks(chunks, { onProgress: options.onProgress });\n return { ok: true, success: true, status: \"success\", value };\n }\n const results: SsmlSynthesisResult[] = [];\n for (const [index, chunk] of chunks.entries()) {\n const input = typeof chunk === \"string\" ? { ssml: chunk } : chunk;\n const sourceNodePath = input.sourceNodePath;\n pending(index, \"synthesizing\");\n const startedAt = Date.now();\n try {\n const result = await client.synthesizeSsml(input.ssml);\n results.push({\n ...result,\n ...(input.originalTextRange ? { textRange: { ...input.originalTextRange } } : {}),\n ...(sourceNodePath\n ? {\n boundaries: result.boundaries?.map((event) => ({\n ...event,\n sourceNodePath: [...sourceNodePath],\n })),\n visemes: result.visemes?.map((event) => ({ ...event, sourceNodePath: [...sourceNodePath] })),\n bookmarks: result.bookmarks?.map((event) => ({ ...event, sourceNodePath: [...sourceNodePath] })),\n }\n : {}),\n });\n options.onProgress?.({\n currentChunk: index + 1,\n totalChunks: chunks.length,\n percent: chunks.length === 0 ? 100 : Math.round(((index + 1) / chunks.length) * 100),\n chunkIndex: index,\n originalTextRange: input.originalTextRange,\n status: \"success\",\n durationMs: Date.now() - startedAt,\n });\n } catch (error) {\n options.onProgress?.({\n currentChunk: index,\n totalChunks: chunks.length,\n percent: chunks.length === 0 ? 100 : Math.round((index / chunks.length) * 100),\n chunkIndex: index,\n originalTextRange: input.originalTextRange,\n status: \"failed\",\n durationMs: Date.now() - startedAt,\n error,\n });\n throw error;\n }\n }\n return {\n ok: true,\n success: true,\n status: \"success\",\n value: mergeSynthesisResults(results, options.outputFormat),\n };\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 { synthesizeSsmlChunksSafe, synthesizeSsmlSafe } from \"./safe.ts\";\nimport type { SynthesizeSsmlChunksSafeOptions, 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 async synthesizeChunksSafe(\n chunks: readonly (SsmlSynthesisChunk | string)[],\n options: SynthesizeSsmlChunksSafeOptions = {},\n ) {\n return synthesizeSsmlChunksSafe(this, chunks, {\n ...options,\n outputFormat: options.outputFormat ?? this.#options.outputFormat,\n onProgress: options.onProgress ?? this.#options.onProgress,\n });\n }\n\n async synthesizeSsmlChunksSafe(\n chunks: readonly (SsmlSynthesisChunk | string)[],\n options: SynthesizeSsmlChunksSafeOptions = {},\n ) {\n return this.synthesizeChunksSafe(chunks, 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 supportedTags?: readonly string[];\n unsupportedTags?: readonly string[];\n models?: 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 SupportedTags?: unknown;\n UnsupportedTags?: unknown;\n Models?: 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 supportedTags = stringList(record.SupportedTags);\n const unsupportedTags = stringList(record.UnsupportedTags);\n const models = stringList(record.Models);\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 const mergedSupportedTags = [...new Set([...(existing?.supportedTags ?? []), ...supportedTags])];\n if (mergedSupportedTags.length > 0) merged.supportedTags = mergedSupportedTags;\n const mergedUnsupportedTags = [...new Set([...(existing?.unsupportedTags ?? []), ...unsupportedTags])];\n if (mergedUnsupportedTags.length > 0) merged.unsupportedTags = mergedUnsupportedTags;\n const mergedModels = [...new Set([...(existing?.models ?? []), ...models])];\n if (mergedModels.length > 0) merged.models = mergedModels;\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","data","validateAzureSsml"]}
|
package/dist/react.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ReactElement, CSSProperties } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { b as SsmlDocument, c as SsmlElement } from './index.d-CUXRwSw0.mjs';
|
|
4
4
|
import { OnMount, Monaco } from '@monaco-editor/react';
|
|
5
5
|
|
|
6
6
|
type SsmlEditorInsertionButton = "break" | "emphasis" | "rate" | "pitch" | "volume" | "emotion" | "say-as" | "phoneme" | "audio" | "sub" | "lang" | "mark" | "bookmark" | "mstts:silence" | "mstts:audioduration" | "mstts:viseme" | (string & {});
|
|
@@ -78,13 +78,17 @@ interface VisualVoiceCatalogEntry {
|
|
|
78
78
|
name: string;
|
|
79
79
|
locale: string;
|
|
80
80
|
region?: string;
|
|
81
|
+
regions?: readonly string[];
|
|
81
82
|
styles?: readonly string[];
|
|
83
|
+
supportedTags?: readonly string[];
|
|
84
|
+
unsupportedTags?: readonly string[];
|
|
82
85
|
preview?: boolean;
|
|
83
86
|
status?: "ga" | "preview" | "deprecated";
|
|
84
87
|
}
|
|
85
88
|
interface VoiceSelectorRenderProps {
|
|
86
89
|
value: string;
|
|
87
90
|
voices: readonly VisualVoiceCatalogEntry[];
|
|
91
|
+
selectedVoice?: VisualVoiceCatalogEntry;
|
|
88
92
|
readOnly: boolean;
|
|
89
93
|
locale: SsmlEditorLocale;
|
|
90
94
|
onChange: (voice: string) => void;
|
package/dist/react.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ReactElement, CSSProperties } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { b as SsmlDocument, c as SsmlElement } from './index.d-CUXRwSw0.js';
|
|
4
4
|
import { OnMount, Monaco } from '@monaco-editor/react';
|
|
5
5
|
|
|
6
6
|
type SsmlEditorInsertionButton = "break" | "emphasis" | "rate" | "pitch" | "volume" | "emotion" | "say-as" | "phoneme" | "audio" | "sub" | "lang" | "mark" | "bookmark" | "mstts:silence" | "mstts:audioduration" | "mstts:viseme" | (string & {});
|
|
@@ -78,13 +78,17 @@ interface VisualVoiceCatalogEntry {
|
|
|
78
78
|
name: string;
|
|
79
79
|
locale: string;
|
|
80
80
|
region?: string;
|
|
81
|
+
regions?: readonly string[];
|
|
81
82
|
styles?: readonly string[];
|
|
83
|
+
supportedTags?: readonly string[];
|
|
84
|
+
unsupportedTags?: readonly string[];
|
|
82
85
|
preview?: boolean;
|
|
83
86
|
status?: "ga" | "preview" | "deprecated";
|
|
84
87
|
}
|
|
85
88
|
interface VoiceSelectorRenderProps {
|
|
86
89
|
value: string;
|
|
87
90
|
voices: readonly VisualVoiceCatalogEntry[];
|
|
91
|
+
selectedVoice?: VisualVoiceCatalogEntry;
|
|
88
92
|
readOnly: boolean;
|
|
89
93
|
locale: SsmlEditorLocale;
|
|
90
94
|
onChange: (voice: string) => void;
|
package/dist/react.js
CHANGED
|
@@ -2953,6 +2953,69 @@ var AZURE_VOICE_DEFINITIONS = [
|
|
|
2953
2953
|
},
|
|
2954
2954
|
{ name: "zh-TW-HsiaoChenNeural", locale: "zh-TW" }
|
|
2955
2955
|
];
|
|
2956
|
+
function createAzureUrlValidatorRunner(validator, options = {}) {
|
|
2957
|
+
if (typeof validator !== "function") throw new TypeError("A URL validator function is required.");
|
|
2958
|
+
const concurrency = options.concurrency === void 0 ? Infinity : Number.isFinite(options.concurrency) ? Math.max(1, Math.floor(options.concurrency)) : Infinity;
|
|
2959
|
+
const cache = options.cache ?? /* @__PURE__ */ new Map();
|
|
2960
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
2961
|
+
const waiters = [];
|
|
2962
|
+
let active = 0;
|
|
2963
|
+
const acquire = async () => {
|
|
2964
|
+
if (active < concurrency) {
|
|
2965
|
+
active += 1;
|
|
2966
|
+
return;
|
|
2967
|
+
}
|
|
2968
|
+
await new Promise((resolve) => waiters.push(resolve));
|
|
2969
|
+
active += 1;
|
|
2970
|
+
};
|
|
2971
|
+
const release = () => {
|
|
2972
|
+
active -= 1;
|
|
2973
|
+
waiters.shift()?.();
|
|
2974
|
+
};
|
|
2975
|
+
const check = async (url, context) => {
|
|
2976
|
+
if (options.signal?.aborted) throw new Error("URL validation was aborted.");
|
|
2977
|
+
const cached = cache.get(url);
|
|
2978
|
+
if (cached !== void 0) return cached;
|
|
2979
|
+
const existing = inFlight.get(url);
|
|
2980
|
+
if (existing) return existing;
|
|
2981
|
+
const promise = (async () => {
|
|
2982
|
+
await acquire();
|
|
2983
|
+
try {
|
|
2984
|
+
if (options.signal?.aborted) throw new Error("URL validation was aborted.");
|
|
2985
|
+
const validation = Promise.resolve(validator(url, context));
|
|
2986
|
+
let timer;
|
|
2987
|
+
let abortHandler;
|
|
2988
|
+
const cancellation = new Promise((_resolve, reject) => {
|
|
2989
|
+
abortHandler = () => reject(new Error("URL validation was aborted."));
|
|
2990
|
+
options.signal?.addEventListener("abort", abortHandler, { once: true });
|
|
2991
|
+
if (options.timeoutMs !== void 0 && options.timeoutMs > 0) {
|
|
2992
|
+
timer = setTimeout(
|
|
2993
|
+
() => reject(new Error(`URL validation timed out after ${options.timeoutMs} ms.`)),
|
|
2994
|
+
options.timeoutMs
|
|
2995
|
+
);
|
|
2996
|
+
}
|
|
2997
|
+
});
|
|
2998
|
+
try {
|
|
2999
|
+
const result = await (timer || abortHandler ? Promise.race([validation, cancellation]) : validation);
|
|
3000
|
+
cache.set(url, result);
|
|
3001
|
+
return result;
|
|
3002
|
+
} finally {
|
|
3003
|
+
if (timer) clearTimeout(timer);
|
|
3004
|
+
if (abortHandler) options.signal?.removeEventListener("abort", abortHandler);
|
|
3005
|
+
}
|
|
3006
|
+
} finally {
|
|
3007
|
+
release();
|
|
3008
|
+
}
|
|
3009
|
+
})();
|
|
3010
|
+
inFlight.set(url, promise);
|
|
3011
|
+
try {
|
|
3012
|
+
return await promise;
|
|
3013
|
+
} finally {
|
|
3014
|
+
inFlight.delete(url);
|
|
3015
|
+
}
|
|
3016
|
+
};
|
|
3017
|
+
return (url, context) => check(url, context);
|
|
3018
|
+
}
|
|
2956
3019
|
var ALLOWED_BREAK_STRENGTHS = /* @__PURE__ */ new Set(["none", "x-weak", "weak", "medium", "strong", "x-strong"]);
|
|
2957
3020
|
var ALLOWED_SAY_AS = /* @__PURE__ */ new Set([
|
|
2958
3021
|
"characters",
|
|
@@ -3237,23 +3300,23 @@ function validateVoiceFeatureMatrix(token, source, diagnostics, voiceName, defin
|
|
|
3237
3300
|
);
|
|
3238
3301
|
}
|
|
3239
3302
|
}
|
|
3240
|
-
function validateAudioSource(token, source, diagnostics, options,
|
|
3303
|
+
function validateAudioSource(token, source, diagnostics, options, elementName3) {
|
|
3241
3304
|
const src = attr(token, "src");
|
|
3242
3305
|
if (!src) {
|
|
3243
|
-
addDiagnostic(diagnostics, source, token.start, `<${
|
|
3306
|
+
addDiagnostic(diagnostics, source, token.start, `<${elementName3}> requires a "src" attribute.`);
|
|
3244
3307
|
return;
|
|
3245
3308
|
}
|
|
3246
3309
|
let parsed;
|
|
3247
3310
|
try {
|
|
3248
3311
|
parsed = new URL(src);
|
|
3249
3312
|
} catch {
|
|
3250
|
-
addDiagnostic(diagnostics, source, token.start, `<${
|
|
3313
|
+
addDiagnostic(diagnostics, source, token.start, `<${elementName3} src> must be an absolute HTTP(S) URL.`);
|
|
3251
3314
|
return;
|
|
3252
3315
|
}
|
|
3253
3316
|
if (parsed.username || parsed.password)
|
|
3254
|
-
addDiagnostic(diagnostics, source, token.start, `<${
|
|
3317
|
+
addDiagnostic(diagnostics, source, token.start, `<${elementName3} src> must not contain URL credentials.`);
|
|
3255
3318
|
if (parsed.protocol !== "https:" && !(options.allowHttpAudio && parsed.protocol === "http:"))
|
|
3256
|
-
addDiagnostic(diagnostics, source, token.start, `<${
|
|
3319
|
+
addDiagnostic(diagnostics, source, token.start, `<${elementName3} src> must use HTTPS.`);
|
|
3257
3320
|
const isAllowedOrigin = options.allowedAudioOrigins?.some((allowedOrigin) => {
|
|
3258
3321
|
try {
|
|
3259
3322
|
const configured = new URL(allowedOrigin);
|
|
@@ -3265,13 +3328,13 @@ function validateAudioSource(token, source, diagnostics, options, elementName2)
|
|
|
3265
3328
|
}
|
|
3266
3329
|
}) ?? false;
|
|
3267
3330
|
if (options.allowedAudioOrigins && !isAllowedOrigin)
|
|
3268
|
-
addDiagnostic(diagnostics, source, token.start, `<${
|
|
3331
|
+
addDiagnostic(diagnostics, source, token.start, `<${elementName3} src> origin "${parsed.origin}" is not allowed.`);
|
|
3269
3332
|
else if (!isAllowedOrigin && !options.allowExternalAudio)
|
|
3270
3333
|
addDiagnostic(
|
|
3271
3334
|
diagnostics,
|
|
3272
3335
|
source,
|
|
3273
3336
|
token.start,
|
|
3274
|
-
`<${
|
|
3337
|
+
`<${elementName3} src> external origin "${parsed.origin}" is blocked by default; set allowExternalAudio to true or provide allowedAudioOrigins.`
|
|
3275
3338
|
);
|
|
3276
3339
|
}
|
|
3277
3340
|
function validateElement(token, source, diagnostics, voiceName, options, voiceCatalog) {
|
|
@@ -3589,6 +3652,14 @@ function validateAzureSsml(ssml, options = {}) {
|
|
|
3589
3652
|
const diagnostics = validateAzureSsmlStatic(ssml, options);
|
|
3590
3653
|
const validator = options.urlValidator ?? options.customUrlValidator;
|
|
3591
3654
|
if (!validator || typeof ssml !== "string") return diagnostics;
|
|
3655
|
+
const runnerOptions = options.urlValidation ?? {};
|
|
3656
|
+
const boundedValidator = createAzureUrlValidatorRunner(validator, {
|
|
3657
|
+
...runnerOptions,
|
|
3658
|
+
...options.urlValidatorConcurrency !== void 0 ? { concurrency: options.urlValidatorConcurrency } : {},
|
|
3659
|
+
...options.urlValidatorTimeoutMs !== void 0 ? { timeoutMs: options.urlValidatorTimeoutMs } : {},
|
|
3660
|
+
...options.urlValidatorSignal ? { signal: options.urlValidatorSignal } : {},
|
|
3661
|
+
...options.urlValidatorCache ? { cache: options.urlValidatorCache } : {}
|
|
3662
|
+
});
|
|
3592
3663
|
let tokens;
|
|
3593
3664
|
try {
|
|
3594
3665
|
tokens = tokenizeElements(ssml);
|
|
@@ -3598,7 +3669,7 @@ function validateAzureSsml(ssml, options = {}) {
|
|
|
3598
3669
|
const checks = tokens.flatMap(
|
|
3599
3670
|
(token) => urlAttributes(token).map(async ({ attribute, value }) => {
|
|
3600
3671
|
try {
|
|
3601
|
-
const result = await
|
|
3672
|
+
const result = await boundedValidator(value, { tag: token.name, attribute });
|
|
3602
3673
|
const valid = typeof result === "boolean" ? result : result.valid;
|
|
3603
3674
|
if (!valid) {
|
|
3604
3675
|
const reason = typeof result === "boolean" ? void 0 : result.reason;
|
|
@@ -6754,13 +6825,31 @@ function localizedElementLabel(element, locale) {
|
|
|
6754
6825
|
function filteredVoices(voiceCatalog, locale, region, style) {
|
|
6755
6826
|
return (voiceCatalog ?? []).filter((voice) => {
|
|
6756
6827
|
if (locale && voice.locale.toLowerCase() !== locale.toLowerCase()) return false;
|
|
6757
|
-
|
|
6828
|
+
const regions = [voice.region, ...voice.regions ?? []].filter(
|
|
6829
|
+
(candidate) => Boolean(candidate)
|
|
6830
|
+
);
|
|
6831
|
+
if (region && regions.length > 0 && !regions.some((candidate) => candidate.toLowerCase() === region.toLowerCase()))
|
|
6832
|
+
return false;
|
|
6758
6833
|
if (style && !voice.styles?.some((candidate) => candidate.toLowerCase() === style.toLowerCase())) return false;
|
|
6759
6834
|
return true;
|
|
6760
6835
|
});
|
|
6761
6836
|
}
|
|
6762
|
-
function
|
|
6763
|
-
|
|
6837
|
+
function VoiceCapabilityMatrix({
|
|
6838
|
+
voice,
|
|
6839
|
+
locale
|
|
6840
|
+
}) {
|
|
6841
|
+
const status = voice.status ?? (voice.preview ? "preview" : void 0);
|
|
6842
|
+
return /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-voice-capabilities", "data-voice-capabilities": "" }, /* @__PURE__ */ React.createElement("div", null, locale === "ja" ? "\u30B9\u30C6\u30FC\u30BF\u30B9" : "Status", ": ", status?.toUpperCase() ?? (locale === "ja" ? "GA" : "GA"), status === "preview" || status === "deprecated" ? /* @__PURE__ */ React.createElement("span", { role: "status", "aria-label": status, className: "ssml-editor-voice-warning-badge" }, status === "preview" ? "\u26A0 Preview" : "\u26A0 Deprecated") : null), (voice.regions?.length || voice.region) && /* @__PURE__ */ React.createElement("div", null, locale === "ja" ? "\u30EA\u30FC\u30B8\u30E7\u30F3" : "Regions", ":", " ", [...voice.regions ?? [], ...voice.region ? [voice.region] : []].filter((region, index, all) => all.indexOf(region) === index).join(", ")), voice.supportedTags && voice.supportedTags.length > 0 && /* @__PURE__ */ React.createElement("div", null, locale === "ja" ? "\u5BFE\u5FDC\u30BF\u30B0" : "Supported tags", ": ", voice.supportedTags.join(", ")), voice.unsupportedTags && voice.unsupportedTags.length > 0 && /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-voice-unsupported" }, locale === "ja" ? "\u975E\u5BFE\u5FDC\u30BF\u30B0" : "Unsupported tags", ": ", voice.unsupportedTags.join(", ")));
|
|
6843
|
+
}
|
|
6844
|
+
function DefaultVoiceSelector({
|
|
6845
|
+
value,
|
|
6846
|
+
voices,
|
|
6847
|
+
selectedVoice,
|
|
6848
|
+
readOnly,
|
|
6849
|
+
locale,
|
|
6850
|
+
onChange
|
|
6851
|
+
}) {
|
|
6852
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
6764
6853
|
"select",
|
|
6765
6854
|
{
|
|
6766
6855
|
"aria-label": locale === "ja" ? "\u97F3\u58F0" : "Voice",
|
|
@@ -6770,7 +6859,7 @@ function DefaultVoiceSelector({ value, voices, readOnly, locale, onChange }) {
|
|
|
6770
6859
|
},
|
|
6771
6860
|
/* @__PURE__ */ React.createElement("option", { value: "" }, locale === "ja" ? "\u97F3\u58F0\u3092\u9078\u629E" : "Select a voice"),
|
|
6772
6861
|
voices.map((voice) => /* @__PURE__ */ React.createElement("option", { key: voice.name, value: voice.name }, voice.name, voice.preview || voice.status === "preview" ? " (preview)" : ""))
|
|
6773
|
-
);
|
|
6862
|
+
), selectedVoice ? /* @__PURE__ */ React.createElement(VoiceCapabilityMatrix, { voice: selectedVoice, locale }) : null);
|
|
6774
6863
|
}
|
|
6775
6864
|
function VisualElementInspector({
|
|
6776
6865
|
document: document2,
|
|
@@ -6791,6 +6880,9 @@ function VisualElementInspector({
|
|
|
6791
6880
|
}
|
|
6792
6881
|
const fields = getElementFields(element);
|
|
6793
6882
|
const availableVoices = filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle);
|
|
6883
|
+
const selectedVoice = voiceCatalog?.find(
|
|
6884
|
+
(voice) => voice.name === (element.type === "voice" ? element.name : void 0)
|
|
6885
|
+
);
|
|
6794
6886
|
const renderSelector = renderVoiceSelector ?? DefaultVoiceSelector;
|
|
6795
6887
|
return /* @__PURE__ */ React.createElement("fieldset", null, /* @__PURE__ */ React.createElement("legend", null, `<${elementLabel(element)}>`), fields.length === 0 ? /* @__PURE__ */ React.createElement("p", null, "This element is preserved in the visual tree. Edit its attributes in Code mode.") : fields.map((field) => {
|
|
6796
6888
|
const value = element[field.key];
|
|
@@ -6832,6 +6924,7 @@ function VisualElementInspector({
|
|
|
6832
6924
|
}[field.key] ?? field.label : field.label, field.key === "name" && elementLabel(element) === "voice" && voiceCatalog ? renderSelector({
|
|
6833
6925
|
value: inputValue,
|
|
6834
6926
|
voices: availableVoices,
|
|
6927
|
+
selectedVoice,
|
|
6835
6928
|
readOnly,
|
|
6836
6929
|
locale,
|
|
6837
6930
|
onChange: (value2) => commit(updateOptionalElementProperty(document2, path, field.key, value2))
|
|
@@ -6976,6 +7069,7 @@ function VisualSsmlEditor({
|
|
|
6976
7069
|
)) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:turn" ? /* @__PURE__ */ React.createElement("fieldset", null, /* @__PURE__ */ React.createElement("legend", null, localizedElementLabel(selectedElement, locale)), /* @__PURE__ */ React.createElement("label", { htmlFor: "ssml-visual-turn-voice" }, locale === "ja" ? "\u97F3\u58F0" : "Voice", voiceCatalog ? (renderVoiceSelector ?? DefaultVoiceSelector)({
|
|
6977
7070
|
value: selectedElement.voice ?? "",
|
|
6978
7071
|
voices: filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle),
|
|
7072
|
+
selectedVoice: voiceCatalog?.find((voice) => voice.name === selectedElement.voice),
|
|
6979
7073
|
readOnly,
|
|
6980
7074
|
locale,
|
|
6981
7075
|
onChange: (value) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "voice", value))
|