ssml-builder-js 2.16.0 → 2.17.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 +6 -2
- package/dist/{chunk-NKLZGITR.mjs → chunk-2SYLELUT.mjs} +4 -2
- package/dist/{chunk-NKLZGITR.mjs.map → chunk-2SYLELUT.mjs.map} +1 -1
- package/dist/{chunk-HI74FTKY.mjs → chunk-5AZWURHW.mjs} +4 -2
- package/dist/{chunk-HI74FTKY.mjs.map → chunk-5AZWURHW.mjs.map} +1 -1
- package/dist/{chunk-F2EMU3HM.mjs → chunk-SLZ7PE6W.mjs} +2 -2
- package/dist/core.d.mts +4 -0
- package/dist/core.d.ts +4 -0
- package/dist/core.js +3 -1
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +1 -1
- package/dist/elements.js +3 -1
- package/dist/elements.js.map +1 -1
- package/dist/elements.mjs +2 -2
- package/dist/{index.d-DR5Qz43p.d.mts → index.d-tpKoP1jl.d.mts} +12 -1
- package/dist/{index.d-DR5Qz43p.d.ts → index.d-tpKoP1jl.d.ts} +12 -1
- package/dist/index.d.mts +78 -11
- package/dist/index.d.ts +78 -11
- package/dist/index.js +336 -72
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +330 -72
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +5 -2
- package/dist/react.d.ts +5 -2
- package/dist/react.js +111 -25
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +110 -26
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
- /package/dist/{chunk-F2EMU3HM.mjs.map → chunk-SLZ7PE6W.mjs.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -41,6 +41,7 @@ __export(src_exports, {
|
|
|
41
41
|
AzureTtsClient: () => AzureTtsClient,
|
|
42
42
|
AzureTtsError: () => AzureTtsError,
|
|
43
43
|
AzureTtsSdkError: () => AzureTtsSdkError,
|
|
44
|
+
BatchChunkValidationError: () => BatchChunkValidationError,
|
|
44
45
|
ChunkValidationError: () => ChunkValidationError,
|
|
45
46
|
DEFAULT_OUTPUT_FORMAT: () => DEFAULT_OUTPUT_FORMAT,
|
|
46
47
|
MergeError: () => MergeError,
|
|
@@ -58,6 +59,7 @@ __export(src_exports, {
|
|
|
58
59
|
fromPlainTextToSsml: () => fromPlainTextToSsml,
|
|
59
60
|
getAzureVoiceCatalogMetadata: () => getAzureVoiceCatalogMetadata,
|
|
60
61
|
getBuiltInVoiceCatalogMetadata: () => getBuiltInVoiceCatalogMetadata,
|
|
62
|
+
getRetryAfterDelayMs: () => getRetryAfterDelayMs,
|
|
61
63
|
getSsmlSourceMap: () => getSsmlSourceMap,
|
|
62
64
|
inspectAudioSpecification: () => inspectAudioSpecification,
|
|
63
65
|
isValidAzureAudioDuration: () => isValidAzureAudioDuration,
|
|
@@ -2723,7 +2725,9 @@ var AZURE_VOICE_CATALOG_METADATA = {
|
|
|
2723
2725
|
apiVersion: "2025-10-01",
|
|
2724
2726
|
generatedAt: "2026-08-28T00:00:00.000Z",
|
|
2725
2727
|
regions: [],
|
|
2726
|
-
voiceCount: AZURE_VOICE_DEFINITIONS.length
|
|
2728
|
+
voiceCount: AZURE_VOICE_DEFINITIONS.length,
|
|
2729
|
+
expiresAt: "2026-09-04T00:00:00.000Z",
|
|
2730
|
+
regionDiffs: {}
|
|
2727
2731
|
};
|
|
2728
2732
|
|
|
2729
2733
|
// packages/ssml-core/src/voiceCatalog.ts
|
|
@@ -2737,7 +2741,7 @@ var getBuiltInVoiceCatalogMetadata = getAzureVoiceCatalogMetadata;
|
|
|
2737
2741
|
|
|
2738
2742
|
// packages/azure-tts-client/src/errors.ts
|
|
2739
2743
|
var AzureTtsError = class extends Error {
|
|
2740
|
-
constructor(status, statusText, responseBody, requestId) {
|
|
2744
|
+
constructor(status, statusText, responseBody, requestId, responseHeaders) {
|
|
2741
2745
|
super(`Azure TTS request failed: ${status} ${statusText}`);
|
|
2742
2746
|
this.kind = "azure-api-error";
|
|
2743
2747
|
this.name = "AzureTtsError";
|
|
@@ -2745,8 +2749,37 @@ var AzureTtsError = class extends Error {
|
|
|
2745
2749
|
this.statusText = statusText;
|
|
2746
2750
|
this.responseBody = responseBody;
|
|
2747
2751
|
this.requestId = requestId;
|
|
2752
|
+
const value = responseHeaders instanceof Headers ? responseHeaders.get("retry-after") : responseHeaders?.["retry-after"] ?? responseHeaders?.["Retry-After"];
|
|
2753
|
+
const seconds = value ? Number(value.trim()) : NaN;
|
|
2754
|
+
const date = value ? Date.parse(value) : NaN;
|
|
2755
|
+
if (Number.isFinite(seconds) && seconds >= 0) this.retryAfterMs = seconds * 1e3;
|
|
2756
|
+
else if (Number.isFinite(date)) this.retryAfterMs = Math.max(0, date - Date.now());
|
|
2748
2757
|
}
|
|
2749
2758
|
};
|
|
2759
|
+
function getRetryAfterDelayMs(error) {
|
|
2760
|
+
if (error instanceof AzureTtsError && error.retryAfterMs !== void 0) return error.retryAfterMs;
|
|
2761
|
+
if (!error || typeof error !== "object") return void 0;
|
|
2762
|
+
const candidate = error;
|
|
2763
|
+
if (typeof candidate.retryAfterMs === "number" && candidate.retryAfterMs >= 0) return candidate.retryAfterMs;
|
|
2764
|
+
const headers = candidate.headers ?? candidate.response?.headers;
|
|
2765
|
+
if (headers instanceof Headers) {
|
|
2766
|
+
const value = headers.get("retry-after");
|
|
2767
|
+
if (!value) return void 0;
|
|
2768
|
+
const seconds = Number(value.trim());
|
|
2769
|
+
if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
|
|
2770
|
+
const date = Date.parse(value);
|
|
2771
|
+
return Number.isFinite(date) ? Math.max(0, date - Date.now()) : void 0;
|
|
2772
|
+
}
|
|
2773
|
+
if (headers && typeof headers === "object") {
|
|
2774
|
+
const value = headers["retry-after"] ?? headers["Retry-After"];
|
|
2775
|
+
if (typeof value !== "string") return void 0;
|
|
2776
|
+
const seconds = Number(value.trim());
|
|
2777
|
+
if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
|
|
2778
|
+
const date = Date.parse(value);
|
|
2779
|
+
return Number.isFinite(date) ? Math.max(0, date - Date.now()) : void 0;
|
|
2780
|
+
}
|
|
2781
|
+
return void 0;
|
|
2782
|
+
}
|
|
2750
2783
|
var AzureTtsSdkError = class extends AzureTtsError {
|
|
2751
2784
|
constructor(errorDetails) {
|
|
2752
2785
|
super(0, "Speech SDK", errorDetails, null);
|
|
@@ -4498,7 +4531,9 @@ var AZURE_VOICE_CATALOG_METADATA2 = {
|
|
|
4498
4531
|
apiVersion: "2025-10-01",
|
|
4499
4532
|
generatedAt: "2026-08-28T00:00:00.000Z",
|
|
4500
4533
|
regions: [],
|
|
4501
|
-
voiceCount: AZURE_VOICE_DEFINITIONS2.length
|
|
4534
|
+
voiceCount: AZURE_VOICE_DEFINITIONS2.length,
|
|
4535
|
+
expiresAt: "2026-09-04T00:00:00.000Z",
|
|
4536
|
+
regionDiffs: {}
|
|
4502
4537
|
};
|
|
4503
4538
|
|
|
4504
4539
|
// packages/azure-tts-client/src/outputFormats.ts
|
|
@@ -4630,6 +4665,8 @@ function formatAudioSpecification(format) {
|
|
|
4630
4665
|
const bitrateMatch = /(\d+)(?:kbitrate|kbps|kbits?)/i.exec(format);
|
|
4631
4666
|
const bitrate = bitrateMatch?.[1] ? Number(bitrateMatch[1]) * 1e3 : void 0;
|
|
4632
4667
|
const codec = /mp3|mpeg/i.test(format) ? "mp3" : /opus/i.test(format) ? "opus" : /silk/i.test(format) ? "silk" : /pcm|mulaw|alaw|siren/i.test(format) ? "pcm" : "unknown";
|
|
4668
|
+
const bitDepthMatch = /(\d+)bit/i.exec(format);
|
|
4669
|
+
const container = /(?:wav|wave|riff)/i.test(format) ? "riff-wave" : /mp3|mpeg/i.test(format) ? "mp3-raw" : /ogg/i.test(format) ? "ogg" : /webm/i.test(format) ? "webm" : /raw/i.test(format) ? "raw" : void 0;
|
|
4633
4670
|
return {
|
|
4634
4671
|
format,
|
|
4635
4672
|
mimeType: resolveMimeType(format),
|
|
@@ -4637,6 +4674,9 @@ function formatAudioSpecification(format) {
|
|
|
4637
4674
|
sampleRate,
|
|
4638
4675
|
channels,
|
|
4639
4676
|
...bitrate ? { bitrate } : {},
|
|
4677
|
+
...bitDepthMatch?.[1] ? { bitDepth: Number(bitDepthMatch[1]) } : {},
|
|
4678
|
+
...container ? { container } : {},
|
|
4679
|
+
isVbr: /vbr/i.test(format),
|
|
4640
4680
|
isCompressed: codec === "mp3" || codec === "opus" || codec === "silk"
|
|
4641
4681
|
};
|
|
4642
4682
|
}
|
|
@@ -4672,6 +4712,8 @@ function parseMp3Specification(buffer, format) {
|
|
|
4672
4712
|
sampleRate,
|
|
4673
4713
|
channels: (bytes[index + 3] ?? 0) >> 6 === 3 ? 1 : 2,
|
|
4674
4714
|
bitrate: bitrateKbps * 1e3,
|
|
4715
|
+
container: "mp3-raw",
|
|
4716
|
+
isVbr: false,
|
|
4675
4717
|
isCompressed: true
|
|
4676
4718
|
};
|
|
4677
4719
|
}
|
|
@@ -4693,6 +4735,9 @@ function inspectAudioSpecification(buffer, format) {
|
|
|
4693
4735
|
sampleRate,
|
|
4694
4736
|
channels,
|
|
4695
4737
|
...sampleRate && channels && bitsPerSample ? { bitrate: sampleRate * channels * bitsPerSample } : {},
|
|
4738
|
+
bitDepth: bitsPerSample,
|
|
4739
|
+
container: "riff-wave",
|
|
4740
|
+
isVbr: false,
|
|
4696
4741
|
isCompressed: formatCode !== 1
|
|
4697
4742
|
};
|
|
4698
4743
|
}
|
|
@@ -4703,7 +4748,7 @@ function validateAudioSpecifications(specs) {
|
|
|
4703
4748
|
const first = specs[0];
|
|
4704
4749
|
if (!first) return;
|
|
4705
4750
|
const mismatch = specs.find(
|
|
4706
|
-
(spec) => spec.sampleRate !== first.sampleRate || spec.channels !== first.channels || first.bitrate !== void 0 && spec.bitrate !== void 0 && spec.bitrate !== first.bitrate
|
|
4751
|
+
(spec) => spec.sampleRate !== first.sampleRate || spec.channels !== first.channels || first.bitrate !== void 0 && spec.bitrate !== void 0 && spec.bitrate !== first.bitrate || first.bitDepth !== void 0 && spec.bitDepth !== void 0 && spec.bitDepth !== first.bitDepth || first.container !== void 0 && spec.container !== void 0 && spec.container !== first.container || first.isVbr !== void 0 && spec.isVbr !== void 0 && spec.isVbr !== first.isVbr
|
|
4707
4752
|
);
|
|
4708
4753
|
if (mismatch)
|
|
4709
4754
|
throw new AudioFormatMismatchError(
|
|
@@ -4906,9 +4951,7 @@ async function synthesizeSsml(ssml, config) {
|
|
|
4906
4951
|
};
|
|
4907
4952
|
}
|
|
4908
4953
|
if (sourceSegments.length === 0 && !config.sourceTextRange && !config.sourceNodePath) {
|
|
4909
|
-
|
|
4910
|
-
Object.defineProperty(unmapped, "mappingStatus", { value: "unmapped", enumerable: false });
|
|
4911
|
-
return unmapped;
|
|
4954
|
+
return { mappingStatus: "unmapped" };
|
|
4912
4955
|
}
|
|
4913
4956
|
const value = text ?? "";
|
|
4914
4957
|
let localStart = Number.isFinite(offsetHint) && (offsetHint ?? 0) >= 0 ? offsetHint : -1;
|
|
@@ -4990,8 +5033,13 @@ async function synthesizeSsml(ssml, config) {
|
|
|
4990
5033
|
...config.sourceNodePath ? { sourceNodePath: [...config.sourceNodePath] } : {},
|
|
4991
5034
|
...requestId ? { requestId } : {}
|
|
4992
5035
|
};
|
|
4993
|
-
if (event.mappingStatus === "unmapped")
|
|
5036
|
+
if (event.mappingStatus === "unmapped") {
|
|
4994
5037
|
Object.defineProperty(mapped, "mappingStatus", { value: "unmapped", enumerable: false });
|
|
5038
|
+
Object.defineProperty(mapped, "toJSON", {
|
|
5039
|
+
value: () => ({ ...mapped, mappingStatus: "unmapped" }),
|
|
5040
|
+
enumerable: false
|
|
5041
|
+
});
|
|
5042
|
+
}
|
|
4995
5043
|
return mapped;
|
|
4996
5044
|
};
|
|
4997
5045
|
const sourceBoundaries = boundaries.map((boundary) => addSourceMetadata(boundary));
|
|
@@ -5014,10 +5062,11 @@ async function synthesizeSsml(ssml, config) {
|
|
|
5014
5062
|
abortHandler = () => rejectWithError(new SynthesisCancelledError());
|
|
5015
5063
|
config.signal.addEventListener("abort", abortHandler, { once: true });
|
|
5016
5064
|
}
|
|
5017
|
-
|
|
5065
|
+
const timeoutMs = config.timeouts?.perChunkMs ?? config.timeoutMs;
|
|
5066
|
+
if (timeoutMs !== void 0 && timeoutMs > 0) {
|
|
5018
5067
|
timeout = setTimeout(
|
|
5019
|
-
() => rejectWithError(new SynthesisTimeoutError(`Speech synthesis timed out after ${
|
|
5020
|
-
|
|
5068
|
+
() => rejectWithError(new SynthesisTimeoutError(`Speech synthesis timed out after ${timeoutMs} ms.`)),
|
|
5069
|
+
timeoutMs
|
|
5021
5070
|
);
|
|
5022
5071
|
}
|
|
5023
5072
|
synthesizer.speakSsmlAsync(ssml, cb, rejectWithError);
|
|
@@ -5036,7 +5085,9 @@ function isRetryableSynthesisError(error) {
|
|
|
5036
5085
|
if (typeof status === "number") return status === 429 || status >= 500 && status < 600;
|
|
5037
5086
|
return /network|connection|connect|socket|fetch failed|econn|etimedout|temporar|transient|unavailable/i.test(message);
|
|
5038
5087
|
}
|
|
5039
|
-
function retryDelay(options, retryAttempt) {
|
|
5088
|
+
function retryDelay(options, retryAttempt, error) {
|
|
5089
|
+
const retryAfterMs = getRetryAfterDelayMs(error);
|
|
5090
|
+
if (retryAfterMs !== void 0) return retryAfterMs;
|
|
5040
5091
|
const base = Math.min(options.maxDelayMs, options.initialDelayMs * 2 ** Math.max(0, retryAttempt - 1));
|
|
5041
5092
|
return Math.floor(Math.random() * (base + 1));
|
|
5042
5093
|
}
|
|
@@ -5068,7 +5119,8 @@ async function synthesizeWithRetry(ssml, config, retryOptions, onRetry) {
|
|
|
5068
5119
|
const options = retryOptions ? {
|
|
5069
5120
|
maxRetries: Math.max(0, Math.floor(retryOptions.maxRetries)),
|
|
5070
5121
|
initialDelayMs: Math.max(0, retryOptions.initialDelayMs),
|
|
5071
|
-
maxDelayMs: Math.max(0, retryOptions.maxDelayMs)
|
|
5122
|
+
maxDelayMs: Math.max(0, retryOptions.maxDelayMs),
|
|
5123
|
+
shouldRetry: retryOptions.shouldRetry
|
|
5072
5124
|
} : void 0;
|
|
5073
5125
|
let attempt = 0;
|
|
5074
5126
|
while (true) {
|
|
@@ -5076,17 +5128,56 @@ async function synthesizeWithRetry(ssml, config, retryOptions, onRetry) {
|
|
|
5076
5128
|
try {
|
|
5077
5129
|
return await synthesizeSsml(ssml, config);
|
|
5078
5130
|
} catch (error) {
|
|
5079
|
-
if (!options || attempt >= options.maxRetries || !
|
|
5131
|
+
if (!options || attempt >= options.maxRetries || !(options.shouldRetry?.(error, attempt + 1) ?? isRetryableSynthesisError(error)))
|
|
5132
|
+
throw error;
|
|
5080
5133
|
attempt += 1;
|
|
5081
|
-
const delayMs = retryDelay(options, attempt);
|
|
5134
|
+
const delayMs = retryDelay(options, attempt, error);
|
|
5082
5135
|
onRetry(attempt, delayMs);
|
|
5083
5136
|
await waitForRetry(delayMs, config.signal);
|
|
5084
5137
|
}
|
|
5085
5138
|
}
|
|
5086
5139
|
}
|
|
5140
|
+
function createAbortScope(parent, timeoutMs) {
|
|
5141
|
+
const controller = new AbortController();
|
|
5142
|
+
let didTimeout = false;
|
|
5143
|
+
const onAbort = () => controller.abort();
|
|
5144
|
+
if (parent?.aborted) controller.abort();
|
|
5145
|
+
parent?.addEventListener("abort", onAbort, { once: true });
|
|
5146
|
+
const timer = timeoutMs !== void 0 && timeoutMs > 0 ? setTimeout(() => {
|
|
5147
|
+
didTimeout = true;
|
|
5148
|
+
controller.abort();
|
|
5149
|
+
}, timeoutMs) : void 0;
|
|
5150
|
+
return {
|
|
5151
|
+
signal: controller.signal,
|
|
5152
|
+
timedOut: () => didTimeout,
|
|
5153
|
+
dispose: () => {
|
|
5154
|
+
if (timer) clearTimeout(timer);
|
|
5155
|
+
parent?.removeEventListener("abort", onAbort);
|
|
5156
|
+
},
|
|
5157
|
+
abort: () => controller.abort()
|
|
5158
|
+
};
|
|
5159
|
+
}
|
|
5160
|
+
async function synthesizeChunkWithTimeout(ssml, config, retryOptions, timeoutMs, onRetry) {
|
|
5161
|
+
const scope = createAbortScope(config.signal, timeoutMs);
|
|
5162
|
+
try {
|
|
5163
|
+
return await synthesizeWithRetry(ssml, { ...config, signal: scope.signal }, retryOptions, onRetry);
|
|
5164
|
+
} catch (error) {
|
|
5165
|
+
if (scope.timedOut()) throw new SynthesisTimeoutError(`Speech synthesis timed out after ${timeoutMs} ms.`);
|
|
5166
|
+
throw error;
|
|
5167
|
+
} finally {
|
|
5168
|
+
scope.dispose();
|
|
5169
|
+
}
|
|
5170
|
+
}
|
|
5087
5171
|
async function synthesizeSsmlChunks(chunks, config) {
|
|
5088
5172
|
const results = new Array(chunks.length);
|
|
5089
5173
|
const totalChunks = chunks.length;
|
|
5174
|
+
const cachedChunks = new Map((config.resumeChunks ?? []).map((chunk) => [chunk.chunkIndex, chunk]));
|
|
5175
|
+
for (const [index, cached] of cachedChunks) {
|
|
5176
|
+
if (index >= 0 && index < totalChunks) results[index] = cached;
|
|
5177
|
+
}
|
|
5178
|
+
const requestedIndices = config.resumeChunkIndices ? new Set(config.resumeChunkIndices.filter((index) => index >= 0 && index < totalChunks)) : void 0;
|
|
5179
|
+
const shouldSynthesize = (index) => !cachedChunks.has(index) && (requestedIndices === void 0 || requestedIndices.has(index));
|
|
5180
|
+
const scope = createAbortScope(config.signal, config.timeouts?.totalJobMs);
|
|
5090
5181
|
const report = (event) => config.onProgress?.(event);
|
|
5091
5182
|
for (const [index, chunk] of chunks.entries()) {
|
|
5092
5183
|
const input = typeof chunk === "string" ? { ssml: chunk } : chunk;
|
|
@@ -5100,13 +5191,17 @@ async function synthesizeSsmlChunks(chunks, config) {
|
|
|
5100
5191
|
durationMs: 0
|
|
5101
5192
|
});
|
|
5102
5193
|
}
|
|
5103
|
-
let completed = 0;
|
|
5194
|
+
let completed = [...results].filter((result) => result !== void 0).length;
|
|
5104
5195
|
let nextIndex = 0;
|
|
5105
5196
|
const concurrency = resolveConcurrency(config.concurrency, chunks.length);
|
|
5197
|
+
let firstError;
|
|
5198
|
+
const failedIndices = /* @__PURE__ */ new Set();
|
|
5106
5199
|
const worker = async () => {
|
|
5107
5200
|
while (true) {
|
|
5108
5201
|
const index = nextIndex++;
|
|
5109
5202
|
if (index >= chunks.length) return;
|
|
5203
|
+
if (!shouldSynthesize(index)) continue;
|
|
5204
|
+
if (firstError && config.cancelOnFailure !== false) return;
|
|
5110
5205
|
const chunk = chunks[index];
|
|
5111
5206
|
const input = typeof chunk === "string" ? { ssml: chunk } : chunk;
|
|
5112
5207
|
report({
|
|
@@ -5120,10 +5215,11 @@ async function synthesizeSsmlChunks(chunks, config) {
|
|
|
5120
5215
|
});
|
|
5121
5216
|
const startedAt = Date.now();
|
|
5122
5217
|
try {
|
|
5123
|
-
const result = await
|
|
5218
|
+
const result = await synthesizeChunkWithTimeout(
|
|
5124
5219
|
input.ssml,
|
|
5125
5220
|
{
|
|
5126
5221
|
...config,
|
|
5222
|
+
signal: scope.signal,
|
|
5127
5223
|
...input.originalTextRange ? { sourceTextRange: input.originalTextRange } : {},
|
|
5128
5224
|
...input.sourceNodePath ?? config.sourceNodePath ? { sourceNodePath: [...input.sourceNodePath ?? config.sourceNodePath ?? []] } : {},
|
|
5129
5225
|
...input.sourceTextSegments ? { sourceTextSegments: input.sourceTextSegments } : {},
|
|
@@ -5132,6 +5228,7 @@ async function synthesizeSsmlChunks(chunks, config) {
|
|
|
5132
5228
|
onProgress: void 0
|
|
5133
5229
|
},
|
|
5134
5230
|
config.retryOptions,
|
|
5231
|
+
config.timeouts?.chunkWithRetriesMs ?? config.timeouts?.perChunkMs ?? config.timeoutMs,
|
|
5135
5232
|
(retryAttempt, nextRetryDelayMs) => report({
|
|
5136
5233
|
currentChunk: completed,
|
|
5137
5234
|
totalChunks,
|
|
@@ -5157,6 +5254,7 @@ async function synthesizeSsmlChunks(chunks, config) {
|
|
|
5157
5254
|
durationMs: Date.now() - startedAt
|
|
5158
5255
|
});
|
|
5159
5256
|
} catch (error) {
|
|
5257
|
+
failedIndices.add(index);
|
|
5160
5258
|
report({
|
|
5161
5259
|
currentChunk: completed,
|
|
5162
5260
|
totalChunks,
|
|
@@ -5167,16 +5265,36 @@ async function synthesizeSsmlChunks(chunks, config) {
|
|
|
5167
5265
|
durationMs: Date.now() - startedAt,
|
|
5168
5266
|
error
|
|
5169
5267
|
});
|
|
5170
|
-
|
|
5268
|
+
firstError ?? (firstError = scope.timedOut() ? new SynthesisTimeoutError(`Speech synthesis timed out after ${config.timeouts?.totalJobMs} ms.`) : error);
|
|
5269
|
+
if (config.cancelOnFailure !== false) scope.abort();
|
|
5270
|
+
return;
|
|
5171
5271
|
}
|
|
5172
5272
|
}
|
|
5173
5273
|
};
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5274
|
+
try {
|
|
5275
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, chunks.length) }, () => worker()));
|
|
5276
|
+
if (firstError) throw firstError;
|
|
5277
|
+
const orderedResults = results.filter((result) => result !== void 0);
|
|
5278
|
+
return await mergeSynthesisResults(orderedResults, {
|
|
5279
|
+
format: config.outputFormat ?? DEFAULT_OUTPUT_FORMAT,
|
|
5280
|
+
signal: scope.signal,
|
|
5281
|
+
customMerger: config.customMerger,
|
|
5282
|
+
outputMimeType: config.outputMimeType,
|
|
5283
|
+
postMergeValidator: config.postMergeValidator
|
|
5284
|
+
});
|
|
5285
|
+
} catch (error) {
|
|
5286
|
+
const partial = {
|
|
5287
|
+
synthesizedChunks: results.flatMap((result, chunkIndex) => result ? [{ ...result, chunkIndex }] : []),
|
|
5288
|
+
completedChunks: results.flatMap((result, chunkIndex) => result ? [{ ...result, chunkIndex }] : []),
|
|
5289
|
+
pendingChunkIndices: chunks.flatMap((_chunk, chunkIndex) => results[chunkIndex] ? [] : [chunkIndex]),
|
|
5290
|
+
failedChunkIndices: [...failedIndices],
|
|
5291
|
+
totalChunks
|
|
5292
|
+
};
|
|
5293
|
+
if (error && typeof error === "object") error.partialResult = partial;
|
|
5294
|
+
throw error;
|
|
5295
|
+
} finally {
|
|
5296
|
+
scope.dispose();
|
|
5297
|
+
}
|
|
5180
5298
|
}
|
|
5181
5299
|
function createMergedResult(results, audioData, format, audioSpec, outputMimeType) {
|
|
5182
5300
|
const boundaries = [];
|
|
@@ -5270,13 +5388,24 @@ function mergeSynthesisResults(results, options) {
|
|
|
5270
5388
|
if (!(merged instanceof ArrayBuffer) || buffers.some((buffer) => buffer.byteLength > 0) && merged.byteLength === 0)
|
|
5271
5389
|
throw new MergeError("The custom audio merger returned an invalid audio buffer.");
|
|
5272
5390
|
if (signal.aborted) throw new SynthesisCancelledError();
|
|
5273
|
-
|
|
5391
|
+
const result = createMergedResult(
|
|
5274
5392
|
results,
|
|
5275
5393
|
merged,
|
|
5276
5394
|
format,
|
|
5277
5395
|
inspectAudioSpecification(merged, format),
|
|
5278
5396
|
resolvedOptions.outputMimeType
|
|
5279
5397
|
);
|
|
5398
|
+
return Promise.resolve(
|
|
5399
|
+
resolvedOptions.postMergeValidator?.(result, {
|
|
5400
|
+
format,
|
|
5401
|
+
outputMimeType: resolvedOptions.outputMimeType ?? resolveMimeType(format),
|
|
5402
|
+
inputSpecs,
|
|
5403
|
+
signal
|
|
5404
|
+
})
|
|
5405
|
+
).then((valid) => {
|
|
5406
|
+
if (valid === false) throw new MergeError("The post-merge validator rejected the merged audio.");
|
|
5407
|
+
return result;
|
|
5408
|
+
});
|
|
5280
5409
|
}).catch((error) => {
|
|
5281
5410
|
if (error instanceof UnsupportedMergeFormatError || isAudioFormatMismatch(error) || error instanceof MergeError)
|
|
5282
5411
|
throw error;
|
|
@@ -5284,13 +5413,28 @@ function mergeSynthesisResults(results, options) {
|
|
|
5284
5413
|
});
|
|
5285
5414
|
}
|
|
5286
5415
|
try {
|
|
5287
|
-
|
|
5416
|
+
const result = createMergedResult(
|
|
5288
5417
|
results,
|
|
5289
5418
|
mergeAudioBuffers(buffers, { format }),
|
|
5290
5419
|
format,
|
|
5291
5420
|
inputSpecs[0],
|
|
5292
5421
|
resolvedOptions.outputMimeType
|
|
5293
5422
|
);
|
|
5423
|
+
if (resolvedOptions.postMergeValidator) {
|
|
5424
|
+
const validation = resolvedOptions.postMergeValidator(result, {
|
|
5425
|
+
format,
|
|
5426
|
+
outputMimeType: resolvedOptions.outputMimeType ?? resolveMimeType(format),
|
|
5427
|
+
inputSpecs,
|
|
5428
|
+
signal
|
|
5429
|
+
});
|
|
5430
|
+
if (validation instanceof Promise)
|
|
5431
|
+
return validation.then((valid) => {
|
|
5432
|
+
if (valid === false) throw new MergeError("The post-merge validator rejected the merged audio.");
|
|
5433
|
+
return result;
|
|
5434
|
+
});
|
|
5435
|
+
if (validation === false) throw new MergeError("The post-merge validator rejected the merged audio.");
|
|
5436
|
+
}
|
|
5437
|
+
return result;
|
|
5294
5438
|
} catch (error) {
|
|
5295
5439
|
if (error instanceof UnsupportedMergeFormatError || isAudioFormatMismatch(error) || error instanceof MergeError)
|
|
5296
5440
|
throw error;
|
|
@@ -5311,8 +5455,52 @@ var ChunkValidationError = class extends Error {
|
|
|
5311
5455
|
this.diagnostics = diagnostics;
|
|
5312
5456
|
}
|
|
5313
5457
|
};
|
|
5314
|
-
|
|
5315
|
-
|
|
5458
|
+
var BatchChunkValidationError = class extends ChunkValidationError {
|
|
5459
|
+
constructor(chunkDiagnostics) {
|
|
5460
|
+
const first = chunkDiagnostics[0];
|
|
5461
|
+
super(first?.chunkIndex ?? -1, first?.diagnostics ?? []);
|
|
5462
|
+
this.name = "BatchChunkValidationError";
|
|
5463
|
+
this.message = `SSML validation failed for ${chunkDiagnostics.length} chunk(s); the Azure Speech API was not called.`;
|
|
5464
|
+
this.chunkDiagnostics = chunkDiagnostics;
|
|
5465
|
+
this.totalErrorCount = chunkDiagnostics.reduce((total, chunk) => total + chunk.diagnostics.length, 0);
|
|
5466
|
+
this.errorCount = this.totalErrorCount;
|
|
5467
|
+
this.totalErrors = this.totalErrorCount;
|
|
5468
|
+
}
|
|
5469
|
+
};
|
|
5470
|
+
function failure(error, partialResult) {
|
|
5471
|
+
return {
|
|
5472
|
+
ok: false,
|
|
5473
|
+
success: false,
|
|
5474
|
+
status: error.kind,
|
|
5475
|
+
error,
|
|
5476
|
+
...partialResult ? { partialResult } : {}
|
|
5477
|
+
};
|
|
5478
|
+
}
|
|
5479
|
+
function partialResultFrom(error) {
|
|
5480
|
+
if (!error || typeof error !== "object") return void 0;
|
|
5481
|
+
const partial = error.partialResult;
|
|
5482
|
+
if (!partial || typeof partial !== "object") return void 0;
|
|
5483
|
+
return partial;
|
|
5484
|
+
}
|
|
5485
|
+
function createSafeAbortScope(parent, timeoutMs) {
|
|
5486
|
+
const controller = new AbortController();
|
|
5487
|
+
let didTimeout = false;
|
|
5488
|
+
const onAbort = () => controller.abort();
|
|
5489
|
+
if (parent?.aborted) controller.abort();
|
|
5490
|
+
parent?.addEventListener("abort", onAbort, { once: true });
|
|
5491
|
+
const timer = timeoutMs !== void 0 && timeoutMs > 0 ? setTimeout(() => {
|
|
5492
|
+
didTimeout = true;
|
|
5493
|
+
controller.abort();
|
|
5494
|
+
}, timeoutMs) : void 0;
|
|
5495
|
+
return {
|
|
5496
|
+
signal: controller.signal,
|
|
5497
|
+
timedOut: () => didTimeout,
|
|
5498
|
+
dispose: () => {
|
|
5499
|
+
if (timer) clearTimeout(timer);
|
|
5500
|
+
parent?.removeEventListener("abort", onAbort);
|
|
5501
|
+
},
|
|
5502
|
+
abort: () => controller.abort()
|
|
5503
|
+
};
|
|
5316
5504
|
}
|
|
5317
5505
|
function isRetryable(error) {
|
|
5318
5506
|
if (error instanceof Error && /cancel|abort|tim(?:e|ed) ?out/i.test(error.message)) return false;
|
|
@@ -5327,6 +5515,9 @@ function delayForRetry(options, attempt) {
|
|
|
5327
5515
|
const base = Math.min(maxDelay, Math.max(0, options.initialDelayMs) * 2 ** Math.max(0, attempt - 1));
|
|
5328
5516
|
return Math.floor(Math.random() * (base + 1));
|
|
5329
5517
|
}
|
|
5518
|
+
function retryDelayForError(options, attempt, error) {
|
|
5519
|
+
return getRetryAfterDelayMs(error) ?? delayForRetry(options, attempt);
|
|
5520
|
+
}
|
|
5330
5521
|
function resolveConcurrency2(value, total) {
|
|
5331
5522
|
if (value === void 0) return 1;
|
|
5332
5523
|
if (value === Infinity) return Math.max(1, total);
|
|
@@ -5336,7 +5527,8 @@ async function retryableSynthesis(synthesize, options, signal, onRetry) {
|
|
|
5336
5527
|
const retry = options ? {
|
|
5337
5528
|
maxRetries: Math.max(0, Math.floor(options.maxRetries)),
|
|
5338
5529
|
initialDelayMs: options.initialDelayMs,
|
|
5339
|
-
maxDelayMs: options.maxDelayMs
|
|
5530
|
+
maxDelayMs: options.maxDelayMs,
|
|
5531
|
+
shouldRetry: options.shouldRetry
|
|
5340
5532
|
} : void 0;
|
|
5341
5533
|
let attempt = 0;
|
|
5342
5534
|
while (true) {
|
|
@@ -5344,9 +5536,10 @@ async function retryableSynthesis(synthesize, options, signal, onRetry) {
|
|
|
5344
5536
|
try {
|
|
5345
5537
|
return await synthesize();
|
|
5346
5538
|
} catch (error) {
|
|
5347
|
-
if (!retry || attempt >= retry.maxRetries || !
|
|
5539
|
+
if (!retry || attempt >= retry.maxRetries || !(retry.shouldRetry?.(error, attempt + 1) ?? isRetryable(error)))
|
|
5540
|
+
throw error;
|
|
5348
5541
|
attempt += 1;
|
|
5349
|
-
const delayMs =
|
|
5542
|
+
const delayMs = retryDelayForError(retry, attempt, error);
|
|
5350
5543
|
onRetry(attempt, delayMs);
|
|
5351
5544
|
if (delayMs > 0)
|
|
5352
5545
|
await new Promise((resolve, reject) => {
|
|
@@ -5370,7 +5563,7 @@ function sharedValidationOptions(options, signal) {
|
|
|
5370
5563
|
const runner = createAzureUrlValidatorRunner2(validator, {
|
|
5371
5564
|
...options.urlValidation ?? {},
|
|
5372
5565
|
...options.urlValidatorConcurrency !== void 0 ? { concurrency: options.urlValidatorConcurrency } : {},
|
|
5373
|
-
...options.urlValidatorTimeoutMs !== void 0 ? { timeoutMs: options.urlValidatorTimeoutMs } : {},
|
|
5566
|
+
...options.timeouts?.urlValidationMs !== void 0 ? { timeoutMs: options.timeouts.urlValidationMs } : options.urlValidatorTimeoutMs !== void 0 ? { timeoutMs: options.urlValidatorTimeoutMs } : {},
|
|
5374
5567
|
...signal ? { signal } : {},
|
|
5375
5568
|
...options.urlValidatorCache ? { cache: options.urlValidatorCache } : {}
|
|
5376
5569
|
});
|
|
@@ -5399,7 +5592,11 @@ async function synthesizeSsmlSafe(client, ssml, options = {}) {
|
|
|
5399
5592
|
ok: true,
|
|
5400
5593
|
success: true,
|
|
5401
5594
|
status: "success",
|
|
5402
|
-
value: await client.synthesizeSsml(ssml, {
|
|
5595
|
+
value: await client.synthesizeSsml(ssml, {
|
|
5596
|
+
signal: options.signal,
|
|
5597
|
+
timeoutMs: options.timeouts?.perChunkMs,
|
|
5598
|
+
timeouts: options.timeouts
|
|
5599
|
+
})
|
|
5403
5600
|
};
|
|
5404
5601
|
} catch (error) {
|
|
5405
5602
|
const synthesisError = toSynthesisError(error);
|
|
@@ -5407,7 +5604,10 @@ async function synthesizeSsmlSafe(client, ssml, options = {}) {
|
|
|
5407
5604
|
}
|
|
5408
5605
|
}
|
|
5409
5606
|
async function synthesizeSsmlChunksSafe(client, chunks, options = {}) {
|
|
5410
|
-
const validationOptions = sharedValidationOptions(
|
|
5607
|
+
const validationOptions = sharedValidationOptions(
|
|
5608
|
+
{ ...options.validation ?? options, timeouts: options.timeouts },
|
|
5609
|
+
options.signal
|
|
5610
|
+
);
|
|
5411
5611
|
if (options.signal?.aborted) {
|
|
5412
5612
|
const error = toSynthesisError(new Error("Speech synthesis was cancelled."));
|
|
5413
5613
|
return failure(error);
|
|
@@ -5441,16 +5641,17 @@ async function synthesizeSsmlChunksSafe(client, chunks, options = {}) {
|
|
|
5441
5641
|
return diagnostics.filter((diagnostic) => diagnostic.severity === "error");
|
|
5442
5642
|
})
|
|
5443
5643
|
);
|
|
5444
|
-
const firstInvalidIndex = validations.findIndex((diagnostics) => diagnostics.length > 0);
|
|
5445
5644
|
if (options.signal?.aborted) {
|
|
5446
5645
|
const error = toSynthesisError(new Error("Speech synthesis was cancelled."));
|
|
5447
5646
|
return failure(error);
|
|
5448
5647
|
}
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5648
|
+
const chunkDiagnostics = validations.map((diagnostics, chunkIndex) => ({ chunkIndex, diagnostics })).filter((entry) => entry.diagnostics.length > 0);
|
|
5649
|
+
if (chunkDiagnostics.length > 0) {
|
|
5650
|
+
const error = new BatchChunkValidationError(chunkDiagnostics);
|
|
5651
|
+
for (const entry of chunkDiagnostics) pending(entry.chunkIndex, "failed", error);
|
|
5452
5652
|
return failure(error);
|
|
5453
5653
|
}
|
|
5654
|
+
let fallbackJobScope;
|
|
5454
5655
|
try {
|
|
5455
5656
|
if (client.synthesizeChunks) {
|
|
5456
5657
|
const normalizedChunks = chunks.map((chunk) => {
|
|
@@ -5462,20 +5663,39 @@ async function synthesizeSsmlChunksSafe(client, chunks, options = {}) {
|
|
|
5462
5663
|
outputFormat: options.outputFormat,
|
|
5463
5664
|
signal: options.signal,
|
|
5464
5665
|
timeoutMs: options.timeoutMs,
|
|
5666
|
+
timeouts: options.timeouts,
|
|
5465
5667
|
sourceNodePath: options.sourceNodePath,
|
|
5466
5668
|
concurrency: options.concurrency,
|
|
5467
|
-
retryOptions: options.retryOptions
|
|
5669
|
+
retryOptions: options.retryOptions,
|
|
5670
|
+
cancelOnFailure: options.cancelOnFailure,
|
|
5671
|
+
resumeChunks: options.resumeChunks,
|
|
5672
|
+
resumeChunkIndices: options.resumeChunkIndices,
|
|
5673
|
+
customMerger: options.customMerger,
|
|
5674
|
+
outputMimeType: options.outputMimeType,
|
|
5675
|
+
postMergeValidator: options.postMergeValidator
|
|
5468
5676
|
});
|
|
5469
5677
|
return { ok: true, success: true, status: "success", value };
|
|
5470
5678
|
}
|
|
5471
5679
|
const results = new Array(chunks.length);
|
|
5472
|
-
|
|
5680
|
+
const cachedChunks = new Map((options.resumeChunks ?? []).map((chunk) => [chunk.chunkIndex, chunk]));
|
|
5681
|
+
for (const [index, cached] of cachedChunks) {
|
|
5682
|
+
if (index >= 0 && index < chunks.length) results[index] = cached;
|
|
5683
|
+
}
|
|
5684
|
+
const requestedIndices = options.resumeChunkIndices ? new Set(options.resumeChunkIndices.filter((index) => index >= 0 && index < chunks.length)) : void 0;
|
|
5685
|
+
const shouldSynthesize = (index) => !cachedChunks.has(index) && (requestedIndices === void 0 || requestedIndices.has(index));
|
|
5686
|
+
const jobScope = chunks.length > 1 || options.timeouts?.totalJobMs !== void 0 ? createSafeAbortScope(options.signal, options.timeouts?.totalJobMs) : void 0;
|
|
5687
|
+
fallbackJobScope = jobScope;
|
|
5688
|
+
const failedIndices = /* @__PURE__ */ new Set();
|
|
5689
|
+
let firstError;
|
|
5690
|
+
let completed = [...results].filter((result) => result !== void 0).length;
|
|
5473
5691
|
let nextIndex = 0;
|
|
5474
5692
|
const concurrency = resolveConcurrency2(options.concurrency, chunks.length);
|
|
5475
5693
|
const worker = async () => {
|
|
5476
5694
|
while (true) {
|
|
5477
5695
|
const index = nextIndex++;
|
|
5478
5696
|
if (index >= chunks.length) return;
|
|
5697
|
+
if (!shouldSynthesize(index)) continue;
|
|
5698
|
+
if (failedIndices.size > 0 && options.cancelOnFailure !== false) return;
|
|
5479
5699
|
const chunk = chunks[index];
|
|
5480
5700
|
const input = typeof chunk === "string" ? { ssml: chunk } : chunk;
|
|
5481
5701
|
const sourceNodePath = input.sourceNodePath;
|
|
@@ -5483,28 +5703,40 @@ async function synthesizeSsmlChunksSafe(client, chunks, options = {}) {
|
|
|
5483
5703
|
pending(index, "synthesizing");
|
|
5484
5704
|
const startedAt = Date.now();
|
|
5485
5705
|
try {
|
|
5486
|
-
const
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5706
|
+
const chunkTimeout = options.timeouts?.chunkWithRetriesMs ?? options.timeouts?.perChunkMs;
|
|
5707
|
+
const chunkScope = chunkTimeout !== void 0 || jobScope ? createSafeAbortScope(jobScope?.signal ?? options.signal, chunkTimeout ?? options.timeoutMs) : void 0;
|
|
5708
|
+
const chunkSignal = chunkScope?.signal ?? options.signal;
|
|
5709
|
+
let result;
|
|
5710
|
+
try {
|
|
5711
|
+
result = await retryableSynthesis(
|
|
5712
|
+
() => client.synthesizeSsml(input.ssml, {
|
|
5713
|
+
outputFormat: options.outputFormat,
|
|
5714
|
+
signal: chunkSignal,
|
|
5715
|
+
timeoutMs: options.timeouts?.perChunkMs ?? options.timeoutMs,
|
|
5716
|
+
sourceNodePath: input.sourceNodePath ?? options.sourceNodePath
|
|
5717
|
+
}),
|
|
5718
|
+
options.retryOptions,
|
|
5719
|
+
chunkSignal,
|
|
5720
|
+
(retryAttempt, nextRetryDelayMs) => options.onProgress?.({
|
|
5721
|
+
currentChunk: completed,
|
|
5722
|
+
totalChunks: chunks.length,
|
|
5723
|
+
percent: chunks.length === 0 ? 100 : Math.round(completed / chunks.length * 100),
|
|
5724
|
+
chunkIndex: index,
|
|
5725
|
+
originalTextRange: input.originalTextRange,
|
|
5726
|
+
status: "synthesizing",
|
|
5727
|
+
durationMs: Date.now() - startedAt,
|
|
5728
|
+
retryAttempt,
|
|
5729
|
+
nextRetryDelayMs,
|
|
5730
|
+
isRetrying: true
|
|
5731
|
+
})
|
|
5732
|
+
);
|
|
5733
|
+
} catch (error) {
|
|
5734
|
+
if (chunkScope?.timedOut())
|
|
5735
|
+
throw new Error(`Speech synthesis timed out after ${chunkTimeout ?? options.timeoutMs} ms.`);
|
|
5736
|
+
throw error;
|
|
5737
|
+
} finally {
|
|
5738
|
+
chunkScope?.dispose();
|
|
5739
|
+
}
|
|
5508
5740
|
results[index] = {
|
|
5509
5741
|
...result,
|
|
5510
5742
|
...input.originalTextRange ? { textRange: { ...input.originalTextRange } } : {},
|
|
@@ -5559,6 +5791,7 @@ async function synthesizeSsmlChunksSafe(client, chunks, options = {}) {
|
|
|
5559
5791
|
durationMs: Date.now() - startedAt
|
|
5560
5792
|
});
|
|
5561
5793
|
} catch (error) {
|
|
5794
|
+
failedIndices.add(index);
|
|
5562
5795
|
options.onProgress?.({
|
|
5563
5796
|
currentChunk: completed,
|
|
5564
5797
|
totalChunks: chunks.length,
|
|
@@ -5569,24 +5802,42 @@ async function synthesizeSsmlChunksSafe(client, chunks, options = {}) {
|
|
|
5569
5802
|
durationMs: Date.now() - startedAt,
|
|
5570
5803
|
error
|
|
5571
5804
|
});
|
|
5572
|
-
|
|
5805
|
+
if (options.cancelOnFailure !== false) jobScope?.abort();
|
|
5806
|
+
firstError ?? (firstError = error);
|
|
5807
|
+
return;
|
|
5573
5808
|
}
|
|
5574
5809
|
}
|
|
5575
5810
|
};
|
|
5576
5811
|
await Promise.all(Array.from({ length: Math.min(concurrency, chunks.length) }, () => worker()));
|
|
5812
|
+
if (failedIndices.size > 0) {
|
|
5813
|
+
const error = firstError ?? new Error("One or more SSML chunks failed to synthesize.");
|
|
5814
|
+
error.partialResult = {
|
|
5815
|
+
synthesizedChunks: results.flatMap((result, chunkIndex) => result ? [{ ...result, chunkIndex }] : []),
|
|
5816
|
+
completedChunks: results.flatMap((result, chunkIndex) => result ? [{ ...result, chunkIndex }] : []),
|
|
5817
|
+
pendingChunkIndices: chunks.flatMap((_chunk, chunkIndex) => results[chunkIndex] ? [] : [chunkIndex]),
|
|
5818
|
+
failedChunkIndices: [...failedIndices],
|
|
5819
|
+
totalChunks: chunks.length
|
|
5820
|
+
};
|
|
5821
|
+
throw error;
|
|
5822
|
+
}
|
|
5577
5823
|
const orderedResults = results.filter((result) => result !== void 0);
|
|
5578
5824
|
return {
|
|
5579
5825
|
ok: true,
|
|
5580
5826
|
success: true,
|
|
5581
5827
|
status: "success",
|
|
5582
|
-
value: mergeSynthesisResults(orderedResults, {
|
|
5828
|
+
value: await mergeSynthesisResults(orderedResults, {
|
|
5583
5829
|
format: options.outputFormat ?? "audio-16khz-128kbitrate-mono-mp3",
|
|
5584
|
-
signal: options.signal
|
|
5830
|
+
signal: jobScope?.signal ?? options.signal,
|
|
5831
|
+
customMerger: options.customMerger,
|
|
5832
|
+
outputMimeType: options.outputMimeType,
|
|
5833
|
+
postMergeValidator: options.postMergeValidator
|
|
5585
5834
|
})
|
|
5586
5835
|
};
|
|
5587
5836
|
} catch (error) {
|
|
5588
5837
|
const synthesisError = toSynthesisError(error);
|
|
5589
|
-
return failure(synthesisError);
|
|
5838
|
+
return failure(synthesisError, partialResultFrom(error));
|
|
5839
|
+
} finally {
|
|
5840
|
+
fallbackJobScope?.dispose();
|
|
5590
5841
|
}
|
|
5591
5842
|
}
|
|
5592
5843
|
function withValidationSignal(options, signal) {
|
|
@@ -5607,14 +5858,14 @@ var AzureTtsClient = class {
|
|
|
5607
5858
|
__privateSet(this, _options, options);
|
|
5608
5859
|
}
|
|
5609
5860
|
async synthesize(ssml) {
|
|
5610
|
-
const { region, subscriptionKey, outputFormat, signal, timeoutMs } = __privateGet(this, _options);
|
|
5861
|
+
const { region, subscriptionKey, outputFormat, signal, timeoutMs, timeouts } = __privateGet(this, _options);
|
|
5611
5862
|
const endpoint = __privateGet(this, _options).endpoint?.trim() || ENDPOINT_TEMPLATE.replace("{region}", region);
|
|
5612
5863
|
__privateGet(this, _options).logger?.debug?.("Using Azure TTS endpoint:", endpoint);
|
|
5613
|
-
const config = { endpoint, region, subscriptionKey, outputFormat, signal, timeoutMs };
|
|
5864
|
+
const config = { endpoint, region, subscriptionKey, outputFormat, signal, timeoutMs, timeouts };
|
|
5614
5865
|
return synthesizeSpeech(ssml, config);
|
|
5615
5866
|
}
|
|
5616
5867
|
async synthesizeSsml(ssml, options = {}) {
|
|
5617
|
-
const { region, subscriptionKey, outputFormat, signal, timeoutMs } = __privateGet(this, _options);
|
|
5868
|
+
const { region, subscriptionKey, outputFormat, signal, timeoutMs, timeouts } = __privateGet(this, _options);
|
|
5618
5869
|
const endpoint = __privateGet(this, _options).endpoint?.trim() || ENDPOINT_TEMPLATE.replace("{region}", region);
|
|
5619
5870
|
__privateGet(this, _options).logger?.debug?.("Using Azure TTS endpoint:", endpoint);
|
|
5620
5871
|
return synthesizeSsml(ssml, {
|
|
@@ -5624,13 +5875,14 @@ var AzureTtsClient = class {
|
|
|
5624
5875
|
outputFormat: options.outputFormat ?? outputFormat,
|
|
5625
5876
|
signal: options.signal ?? signal,
|
|
5626
5877
|
timeoutMs: options.timeoutMs ?? timeoutMs,
|
|
5878
|
+
timeouts: options.timeouts ?? timeouts,
|
|
5627
5879
|
sourceNodePath: options.sourceNodePath,
|
|
5628
5880
|
sourceTextSegments: options.sourceTextSegments,
|
|
5629
5881
|
sourceMarkers: options.sourceMarkers
|
|
5630
5882
|
});
|
|
5631
5883
|
}
|
|
5632
5884
|
async synthesizeChunks(chunks, options = {}) {
|
|
5633
|
-
const { region, subscriptionKey, outputFormat, signal, timeoutMs } = __privateGet(this, _options);
|
|
5885
|
+
const { region, subscriptionKey, outputFormat, signal, timeoutMs, timeouts } = __privateGet(this, _options);
|
|
5634
5886
|
const endpoint = __privateGet(this, _options).endpoint?.trim() || ENDPOINT_TEMPLATE.replace("{region}", region);
|
|
5635
5887
|
return synthesizeSsmlChunks(chunks, {
|
|
5636
5888
|
endpoint,
|
|
@@ -5639,10 +5891,17 @@ var AzureTtsClient = class {
|
|
|
5639
5891
|
outputFormat: options.outputFormat ?? outputFormat,
|
|
5640
5892
|
signal: options.signal ?? signal,
|
|
5641
5893
|
timeoutMs: options.timeoutMs ?? timeoutMs,
|
|
5894
|
+
timeouts: options.timeouts ?? timeouts,
|
|
5642
5895
|
sourceNodePath: options.sourceNodePath,
|
|
5643
5896
|
onProgress: options.onProgress ?? __privateGet(this, _options).onProgress,
|
|
5644
5897
|
concurrency: options.concurrency ?? __privateGet(this, _options).concurrency,
|
|
5645
|
-
retryOptions: options.retryOptions ?? __privateGet(this, _options).retryOptions
|
|
5898
|
+
retryOptions: options.retryOptions ?? __privateGet(this, _options).retryOptions,
|
|
5899
|
+
cancelOnFailure: options.cancelOnFailure,
|
|
5900
|
+
resumeChunks: options.resumeChunks,
|
|
5901
|
+
resumeChunkIndices: options.resumeChunkIndices,
|
|
5902
|
+
customMerger: options.customMerger,
|
|
5903
|
+
outputMimeType: options.outputMimeType,
|
|
5904
|
+
postMergeValidator: options.postMergeValidator
|
|
5646
5905
|
});
|
|
5647
5906
|
}
|
|
5648
5907
|
async synthesizeSsmlSafe(ssml, options = {}) {
|
|
@@ -5654,6 +5913,7 @@ var AzureTtsClient = class {
|
|
|
5654
5913
|
outputFormat: options.outputFormat ?? __privateGet(this, _options).outputFormat,
|
|
5655
5914
|
signal: options.signal ?? __privateGet(this, _options).signal,
|
|
5656
5915
|
timeoutMs: options.timeoutMs ?? __privateGet(this, _options).timeoutMs,
|
|
5916
|
+
timeouts: options.timeouts ?? __privateGet(this, _options).timeouts,
|
|
5657
5917
|
onProgress: options.onProgress ?? __privateGet(this, _options).onProgress,
|
|
5658
5918
|
concurrency: options.concurrency ?? __privateGet(this, _options).concurrency,
|
|
5659
5919
|
retryOptions: options.retryOptions ?? __privateGet(this, _options).retryOptions
|
|
@@ -5747,7 +6007,9 @@ async function fetchAzureVoiceCatalog(options) {
|
|
|
5747
6007
|
voiceCount: sortedVoices.length,
|
|
5748
6008
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5749
6009
|
apiVersion: AZURE_VOICE_API_VERSION,
|
|
5750
|
-
regions
|
|
6010
|
+
regions,
|
|
6011
|
+
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1e3).toISOString(),
|
|
6012
|
+
regionDiffs: {}
|
|
5751
6013
|
}
|
|
5752
6014
|
};
|
|
5753
6015
|
}
|
|
@@ -5757,6 +6019,7 @@ async function fetchAzureVoiceCatalog(options) {
|
|
|
5757
6019
|
AzureTtsClient,
|
|
5758
6020
|
AzureTtsError,
|
|
5759
6021
|
AzureTtsSdkError,
|
|
6022
|
+
BatchChunkValidationError,
|
|
5760
6023
|
ChunkValidationError,
|
|
5761
6024
|
DEFAULT_OUTPUT_FORMAT,
|
|
5762
6025
|
MergeError,
|
|
@@ -5774,6 +6037,7 @@ async function fetchAzureVoiceCatalog(options) {
|
|
|
5774
6037
|
fromPlainTextToSsml,
|
|
5775
6038
|
getAzureVoiceCatalogMetadata,
|
|
5776
6039
|
getBuiltInVoiceCatalogMetadata,
|
|
6040
|
+
getRetryAfterDelayMs,
|
|
5777
6041
|
getSsmlSourceMap,
|
|
5778
6042
|
inspectAudioSpecification,
|
|
5779
6043
|
isValidAzureAudioDuration,
|