@ssml-builder-js/azure-tts-client 2.15.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/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @ssml-builder-js/azure-tts-client
2
2
 
3
+ ## 2.17.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add resilient chunk synthesis with aggregate validation diagnostics, custom merge/post-merge hooks, Retry-After-aware retries, structured timeouts, cancellation/resume partial results, expanded audio specifications, and voice-capability-aware Visual Editor controls.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+ - @ssml-builder-js/ssml-core@2.17.0
13
+
14
+ ## 2.16.0
15
+
16
+ ### Minor Changes
17
+
18
+ - Add shared URL validation for SSML chunks, transient retry and bounded parallel synthesis, structured diagnostics and synchronization mapping status, audio header/specification validation, and the stricter custom audio merger context.
19
+
20
+ ### Patch Changes
21
+
22
+ - Updated dependencies
23
+ - @ssml-builder-js/ssml-core@2.16.0
24
+
3
25
  ## 2.15.0
4
26
 
5
27
  ### Minor Changes
package/dist/index.d.mts CHANGED
@@ -49,6 +49,7 @@ declare function resolveMimeType(outputFormat: string): string;
49
49
  interface TtsConfig {
50
50
  signal?: AbortSignal;
51
51
  timeoutMs?: number;
52
+ timeouts?: SynthesisTimeouts;
52
53
  endpoint?: string;
53
54
  subscriptionKey: string;
54
55
  region: string;
@@ -66,6 +67,39 @@ interface TtsConfig {
66
67
  /** Exact source text segments used to map individual Azure events. */
67
68
  sourceTextSegments?: SsmlSourceTextSegment[];
68
69
  sourceMarkers?: SsmlSourceMarker[];
70
+ concurrency?: number;
71
+ retryOptions?: RetryOptions;
72
+ cancelOnFailure?: boolean;
73
+ resumeChunks?: readonly SynthesizedChunk[];
74
+ resumeChunkIndices?: readonly number[];
75
+ customMerger?: CustomAudioMerger;
76
+ outputMimeType?: string;
77
+ postMergeValidator?: PostMergeValidator;
78
+ }
79
+ type MappingStatus = "exact" | "fallback" | "unmapped";
80
+ interface AudioSpecification {
81
+ format: string;
82
+ mimeType: string;
83
+ codec: "pcm" | "mp3" | "opus" | "silk" | "unknown";
84
+ sampleRate: number;
85
+ channels: number;
86
+ bitrate?: number;
87
+ bitDepth?: number;
88
+ container?: string;
89
+ isVbr?: boolean;
90
+ isCompressed: boolean;
91
+ }
92
+ interface SynthesisTimeouts {
93
+ urlValidationMs?: number;
94
+ perChunkMs?: number;
95
+ chunkWithRetriesMs?: number;
96
+ totalJobMs?: number;
97
+ }
98
+ interface RetryOptions {
99
+ maxRetries: number;
100
+ initialDelayMs: number;
101
+ maxDelayMs: number;
102
+ shouldRetry?: (error: unknown, attempt: number) => boolean;
69
103
  }
70
104
  type SynthesisChunkStatus = "pending" | "synthesizing" | "success" | "failed";
71
105
  interface SsmlSynthesisBoundary {
@@ -85,6 +119,7 @@ interface SsmlSynthesisBoundary {
85
119
  /** Audio offset within the originating chunk before merge. */
86
120
  chunkAudioOffsetMs?: number;
87
121
  requestId?: string;
122
+ mappingStatus: MappingStatus;
88
123
  }
89
124
  interface SsmlSynthesisViseme {
90
125
  visemeId: number;
@@ -98,6 +133,7 @@ interface SsmlSynthesisViseme {
98
133
  originalTextRange?: SsmlTextRange;
99
134
  chunkAudioOffsetMs?: number;
100
135
  requestId?: string;
136
+ mappingStatus: MappingStatus;
101
137
  }
102
138
  interface SsmlSynthesisBookmark {
103
139
  name: string;
@@ -111,6 +147,7 @@ interface SsmlSynthesisBookmark {
111
147
  originalTextRange?: SsmlTextRange;
112
148
  chunkAudioOffsetMs?: number;
113
149
  requestId?: string;
150
+ mappingStatus: MappingStatus;
114
151
  }
115
152
  /** Audio and Azure Speech synchronization events emitted for one SSML request. */
116
153
  interface SsmlSynthesisResult {
@@ -132,6 +169,7 @@ interface SsmlSynthesisResult {
132
169
  };
133
170
  /** MIME type of a result produced by an explicit merge operation. */
134
171
  mimeType?: string;
172
+ audioSpec?: AudioSpecification;
135
173
  }
136
174
  interface MergedSynthesisResult extends SsmlSynthesisResult {
137
175
  mimeType: string;
@@ -151,8 +189,37 @@ interface SynthesizeChunksOptions {
151
189
  outputFormat?: AzureTtsOutputFormat | string;
152
190
  signal?: AbortSignal;
153
191
  timeoutMs?: number;
192
+ timeouts?: SynthesisTimeouts;
154
193
  sourceNodePath?: string[];
194
+ concurrency?: number;
195
+ retryOptions?: RetryOptions;
196
+ cancelOnFailure?: boolean;
197
+ resumeChunks?: readonly SynthesizedChunk[];
198
+ resumeChunkIndices?: readonly number[];
199
+ customMerger?: CustomAudioMerger;
200
+ outputMimeType?: string;
201
+ postMergeValidator?: PostMergeValidator;
155
202
  }
203
+ interface CustomMergerContext {
204
+ format: string;
205
+ outputMimeType: string;
206
+ inputSpecs: readonly AudioSpecification[];
207
+ signal: AbortSignal;
208
+ }
209
+ type CustomAudioMerger = (buffers: ArrayBuffer[], context: CustomMergerContext) => Promise<ArrayBuffer> | ArrayBuffer;
210
+ type PostMergeValidator = (result: MergedSynthesisResult, context: CustomMergerContext) => boolean | undefined | Promise<boolean | undefined>;
211
+ interface SynthesizedChunk extends SsmlSynthesisResult {
212
+ chunkIndex: number;
213
+ }
214
+ interface PartialChunkSynthesisResult {
215
+ synthesizedChunks: readonly SynthesizedChunk[];
216
+ completedChunks: readonly SynthesizedChunk[];
217
+ pendingChunkIndices: readonly number[];
218
+ failedChunkIndices: readonly number[];
219
+ totalChunks: number;
220
+ }
221
+ /** Alias for applications that use the shorter result name. */
222
+ type PartialSynthesisResult = PartialChunkSynthesisResult;
156
223
  interface SynthesisProgressEvent {
157
224
  /** 1-based completed chunk count retained for backward compatibility. */
158
225
  currentChunk: number;
@@ -163,6 +230,9 @@ interface SynthesisProgressEvent {
163
230
  status: SynthesisChunkStatus;
164
231
  durationMs: number;
165
232
  error?: unknown;
233
+ retryAttempt?: number;
234
+ nextRetryDelayMs?: number;
235
+ isRetrying?: boolean;
166
236
  }
167
237
  interface AzureTtsLogger {
168
238
  debug?: (...args: unknown[]) => void;
@@ -173,23 +243,29 @@ interface AzureTtsLogger {
173
243
  interface AzureTtsClientOptions {
174
244
  signal?: AbortSignal;
175
245
  timeoutMs?: number;
246
+ timeouts?: SynthesisTimeouts;
176
247
  subscriptionKey: string;
177
248
  region: string;
178
249
  endpoint?: string;
179
250
  outputFormat?: string;
180
251
  logger?: AzureTtsLogger;
181
252
  onProgress?: (event: SynthesisProgressEvent) => void;
253
+ concurrency?: number;
254
+ retryOptions?: RetryOptions;
182
255
  }
183
256
 
184
- type SynthesisErrorKind = "validation-error" | "azure-api-error" | "merge-error" | "unsupported-format-error" | "cancelled" | "timeout";
257
+ type SynthesisErrorKind = "validation-error" | "azure-api-error" | "merge-error" | "audio-format-mismatch" | "unsupported-format-error" | "cancelled" | "timeout";
185
258
  declare class AzureTtsError extends Error {
186
259
  readonly kind: "azure-api-error";
187
260
  readonly status: number;
188
261
  readonly statusText: string;
189
262
  readonly responseBody: string;
190
263
  readonly requestId: string | null;
191
- constructor(status: number, statusText: string, responseBody: string, requestId: string | null);
264
+ readonly retryAfterMs?: number;
265
+ constructor(status: number, statusText: string, responseBody: string, requestId: string | null, responseHeaders?: Headers | Readonly<Record<string, string>>);
192
266
  }
267
+ /** Reads Retry-After from an error-like value, returning milliseconds when present. */
268
+ declare function getRetryAfterDelayMs(error: unknown): number | undefined;
193
269
  declare class AzureTtsSdkError extends AzureTtsError {
194
270
  readonly errorDetails: string;
195
271
  constructor(errorDetails: string);
@@ -207,13 +283,19 @@ declare class MergeError extends Error {
207
283
  readonly cause: unknown;
208
284
  constructor(message: string, cause?: unknown);
209
285
  }
286
+ /** Thrown when chunk headers describe incompatible audio streams. */
287
+ declare class AudioFormatMismatchError extends Error {
288
+ readonly kind: "audio-format-mismatch";
289
+ readonly inputSpecs: readonly AudioSpecification[];
290
+ constructor(message: string, inputSpecs?: readonly AudioSpecification[]);
291
+ }
210
292
  /** Thrown when audio buffers require container re-multiplexing before they can be merged. */
211
293
  declare class UnsupportedMergeFormatError extends Error {
212
294
  readonly kind: "unsupported-format-error";
213
295
  readonly format: string;
214
296
  constructor(format: string);
215
297
  }
216
- type AzureTtsSynthesisError = AzureTtsError | MergeError | UnsupportedMergeFormatError | SynthesisCancelledError | SynthesisTimeoutError;
298
+ type AzureTtsSynthesisError = AzureTtsError | MergeError | AudioFormatMismatchError | UnsupportedMergeFormatError | SynthesisCancelledError | SynthesisTimeoutError;
217
299
 
218
300
  interface SsmlValidationError {
219
301
  readonly kind: "validation-error";
@@ -227,6 +309,17 @@ declare class ChunkValidationError extends Error {
227
309
  readonly diagnostics: readonly SsmlDiagnostic[];
228
310
  constructor(chunkIndex: number, diagnostics: readonly SsmlDiagnostic[]);
229
311
  }
312
+ interface ChunkDiagnostics {
313
+ readonly chunkIndex: number;
314
+ readonly diagnostics: readonly SsmlDiagnostic[];
315
+ }
316
+ declare class BatchChunkValidationError extends ChunkValidationError {
317
+ readonly chunkDiagnostics: readonly ChunkDiagnostics[];
318
+ readonly totalErrorCount: number;
319
+ readonly errorCount: number;
320
+ readonly totalErrors: number;
321
+ constructor(chunkDiagnostics: readonly ChunkDiagnostics[]);
322
+ }
230
323
  type Result<T, E> = {
231
324
  readonly ok: true;
232
325
  readonly success: true;
@@ -239,11 +332,13 @@ type Result<T, E> = {
239
332
  readonly success: false;
240
333
  readonly status: Kind;
241
334
  readonly error: E;
335
+ readonly partialResult?: PartialChunkSynthesisResult;
242
336
  } : {
243
337
  readonly ok: false;
244
338
  readonly success: false;
245
339
  readonly status: SynthesisErrorKind;
246
340
  readonly error: E;
341
+ readonly partialResult?: PartialChunkSynthesisResult;
247
342
  });
248
343
  type SynthesisResult<T, E> = Result<T, E>;
249
344
  type Success<T> = Extract<Result<T, never>, {
@@ -260,16 +355,26 @@ interface SynthesizeSsmlSafeOptions extends AzureValidationOptions {
260
355
  /** Optional nested form for callers that want to keep validation settings grouped. */
261
356
  validation?: AzureValidationOptions;
262
357
  signal?: AbortSignal;
358
+ timeouts?: SynthesisTimeouts;
263
359
  }
264
360
  interface SynthesizeSsmlChunksSafeOptions extends AzureValidationOptions {
265
361
  validation?: AzureValidationOptions;
266
362
  outputFormat?: string;
267
363
  signal?: AbortSignal;
268
364
  timeoutMs?: number;
365
+ timeouts?: SynthesisTimeouts;
269
366
  sourceNodePath?: string[];
270
367
  onProgress?: (event: SynthesisProgressEvent) => void;
368
+ concurrency?: number;
369
+ retryOptions?: RetryOptions;
370
+ cancelOnFailure?: boolean;
371
+ resumeChunks?: readonly SynthesizedChunk[];
372
+ resumeChunkIndices?: readonly number[];
373
+ customMerger?: CustomAudioMerger;
374
+ outputMimeType?: string;
375
+ postMergeValidator?: PostMergeValidator;
271
376
  }
272
- type SsmlSynthesisChunksSafeResult = Result<SsmlSynthesisResult, never> | Result<never, ChunkValidationError> | Result<never, SsmlSynthesisError | ChunkValidationError>;
377
+ type SsmlSynthesisChunksSafeResult = Result<SsmlSynthesisResult, never> | Result<never, ChunkValidationError> | Result<never, BatchChunkValidationError> | Result<never, SsmlSynthesisError | ChunkValidationError>;
273
378
  interface SynthesisClient {
274
379
  synthesizeSsml(ssml: string, options?: Partial<SynthesizeChunksOptions>): Promise<SsmlSynthesisResult>;
275
380
  synthesizeChunks?(chunks: readonly (SsmlSynthesisChunk | string)[], options?: SynthesizeChunksOptions): Promise<SsmlSynthesisResult>;
@@ -293,22 +398,29 @@ declare class AzureTtsClient {
293
398
  type MergeAudioFormat = "wav" | "mp3" | "raw";
294
399
  interface MergeAudioOptions {
295
400
  format: AzureTtsOutputFormat;
401
+ signal?: AbortSignal;
402
+ outputMimeType?: string;
296
403
  }
404
+ type InputAudioSpecs = AudioSpecification[];
297
405
  interface MergeSynthesisOptions extends MergeAudioOptions {
298
- customMerger?: (buffers: ArrayBuffer[], format: string) => Promise<ArrayBuffer> | ArrayBuffer;
406
+ customMerger?: CustomAudioMerger;
407
+ postMergeValidator?: PostMergeValidator;
299
408
  }
300
409
  type AsyncMergeSynthesisOptions = MergeSynthesisOptions & {
301
410
  customMerger: NonNullable<MergeSynthesisOptions["customMerger"]>;
302
411
  };
412
+ /** Extracts the stream specification from a WAV/MP3 header and output-format fallback. */
413
+ declare function inspectAudioSpecification(buffer: ArrayBuffer, format: string): AudioSpecification;
303
414
  /** Returns whether the named output format can be safely concatenated without re-multiplexing. */
304
415
  declare function resolveMergeAudioFormat(format: string): MergeAudioFormat | undefined;
305
416
  declare function canMergeAudioFormat(format: string): boolean;
306
417
  /** Merges audio buffers while preserving the invariants of supported containers. */
307
418
  declare function mergeAudioBuffers(buffers: readonly ArrayBuffer[], options: MergeAudioOptions): ArrayBuffer;
308
419
  declare function synthesizeSsml(ssml: string, config: TtsConfig): Promise<SsmlSynthesisResult>;
309
- /** Synthesizes chunks sequentially, annotates synchronization events, and merges the results. */
420
+ /** Synthesizes chunks with bounded concurrency, retries transient failures, and merges in chunk order. */
310
421
  declare function synthesizeSsmlChunks(chunks: readonly (SsmlSynthesisChunk | string)[], config: TtsConfig): Promise<SsmlSynthesisResult>;
311
422
  declare function mergeSynthesisResults(results: readonly SsmlSynthesisResult[], options: AsyncMergeSynthesisOptions): Promise<MergedSynthesisResult>;
423
+ declare function mergeSynthesisResults(results: readonly SsmlSynthesisResult[], options: MergeSynthesisOptions): MergedSynthesisResult | Promise<MergedSynthesisResult>;
312
424
  declare function mergeSynthesisResults(results: readonly SsmlSynthesisResult[], options: MergeAudioOptions): MergedSynthesisResult;
313
425
  /** Backward-compatible audio-only synthesis helper. */
314
426
  declare function synthesizeSpeech(ssml: string, config: TtsConfig): Promise<ArrayBuffer>;
@@ -333,6 +445,8 @@ interface FetchedAzureVoiceCatalogMetadata {
333
445
  generatedAt: string;
334
446
  apiVersion: string;
335
447
  regions: readonly string[];
448
+ expiresAt?: string;
449
+ regionDiffs?: Readonly<Record<string, readonly string[]>>;
336
450
  }
337
451
  interface AzureVoiceCatalog {
338
452
  voices: readonly AzureVoiceCatalogVoice[];
@@ -341,4 +455,4 @@ interface AzureVoiceCatalog {
341
455
  /** Fetches and deduplicates the current Azure Speech voice catalog for one or more regions. */
342
456
  declare function fetchAzureVoiceCatalog(options: FetchAzureVoiceCatalogOptions): Promise<AzureVoiceCatalog>;
343
457
 
344
- export { type AzureApiErrorResult, type SsmlValidationError as AzureSsmlValidationError, AzureTtsClient, type AzureTtsClientOptions, AzureTtsError, type AzureTtsLogger, type AzureTtsOutputFormat, AzureTtsSdkError, type AzureTtsSynthesisError, type AzureVoiceCatalog, type AzureVoiceCatalogVoice, ChunkValidationError, DEFAULT_OUTPUT_FORMAT, type FetchAzureVoiceCatalogOptions, type FetchedAzureVoiceCatalogMetadata, type MergeAudioFormat, type MergeAudioOptions, MergeError, type MergeSynthesisOptions, type MergedSynthesisResult, type Result, type SsmlSynthesisBookmark, type SsmlSynthesisBoundary, type SsmlSynthesisChunk, type SsmlSynthesisChunksSafeResult, type SsmlSynthesisError, type SsmlSynthesisResult, type SsmlSynthesisSafeResult, type SsmlSynthesisViseme, type Success, SynthesisCancelledError, type SynthesisChunkStatus, type SynthesisErrorKind, type SynthesisProgressEvent, type SynthesisResult, SynthesisTimeoutError, type SynthesizeChunksOptions, type SynthesizeSsmlChunksSafeOptions, type SynthesizeSsmlSafeOptions, type TtsConfig, UnsupportedMergeFormatError, type ValidationErrorResult, canMergeAudioFormat, fetchAzureVoiceCatalog, mergeAudioBuffers, mergeSynthesisResults, resolveMergeAudioFormat, resolveMimeType, synthesizeSpeech, synthesizeSsml, synthesizeSsmlChunks, synthesizeSsmlChunksSafe, synthesizeSsmlSafe };
458
+ export { AudioFormatMismatchError, type AudioSpecification, type AzureApiErrorResult, type SsmlValidationError as AzureSsmlValidationError, AzureTtsClient, type AzureTtsClientOptions, AzureTtsError, type AzureTtsLogger, type AzureTtsOutputFormat, AzureTtsSdkError, type AzureTtsSynthesisError, type AzureVoiceCatalog, type AzureVoiceCatalogVoice, BatchChunkValidationError, type ChunkDiagnostics, ChunkValidationError, type CustomAudioMerger, type CustomMergerContext, DEFAULT_OUTPUT_FORMAT, type FetchAzureVoiceCatalogOptions, type FetchedAzureVoiceCatalogMetadata, type InputAudioSpecs, type MappingStatus, type MergeAudioFormat, type MergeAudioOptions, MergeError, type MergeSynthesisOptions, type MergedSynthesisResult, type PartialChunkSynthesisResult, type PartialSynthesisResult, type PostMergeValidator, type Result, type RetryOptions, type SsmlSynthesisBookmark, type SsmlSynthesisBoundary, type SsmlSynthesisChunk, type SsmlSynthesisChunksSafeResult, type SsmlSynthesisError, type SsmlSynthesisResult, type SsmlSynthesisSafeResult, type SsmlSynthesisViseme, type Success, SynthesisCancelledError, type SynthesisChunkStatus, type SynthesisErrorKind, type SynthesisProgressEvent, type SynthesisResult, SynthesisTimeoutError, type SynthesisTimeouts, type SynthesizeChunksOptions, type SynthesizeSsmlChunksSafeOptions, type SynthesizeSsmlSafeOptions, type SynthesizedChunk, type TtsConfig, UnsupportedMergeFormatError, type ValidationErrorResult, canMergeAudioFormat, fetchAzureVoiceCatalog, getRetryAfterDelayMs, inspectAudioSpecification, mergeAudioBuffers, mergeSynthesisResults, resolveMergeAudioFormat, resolveMimeType, synthesizeSpeech, synthesizeSsml, synthesizeSsmlChunks, synthesizeSsmlChunksSafe, synthesizeSsmlSafe };
package/dist/index.d.ts CHANGED
@@ -49,6 +49,7 @@ declare function resolveMimeType(outputFormat: string): string;
49
49
  interface TtsConfig {
50
50
  signal?: AbortSignal;
51
51
  timeoutMs?: number;
52
+ timeouts?: SynthesisTimeouts;
52
53
  endpoint?: string;
53
54
  subscriptionKey: string;
54
55
  region: string;
@@ -66,6 +67,39 @@ interface TtsConfig {
66
67
  /** Exact source text segments used to map individual Azure events. */
67
68
  sourceTextSegments?: SsmlSourceTextSegment[];
68
69
  sourceMarkers?: SsmlSourceMarker[];
70
+ concurrency?: number;
71
+ retryOptions?: RetryOptions;
72
+ cancelOnFailure?: boolean;
73
+ resumeChunks?: readonly SynthesizedChunk[];
74
+ resumeChunkIndices?: readonly number[];
75
+ customMerger?: CustomAudioMerger;
76
+ outputMimeType?: string;
77
+ postMergeValidator?: PostMergeValidator;
78
+ }
79
+ type MappingStatus = "exact" | "fallback" | "unmapped";
80
+ interface AudioSpecification {
81
+ format: string;
82
+ mimeType: string;
83
+ codec: "pcm" | "mp3" | "opus" | "silk" | "unknown";
84
+ sampleRate: number;
85
+ channels: number;
86
+ bitrate?: number;
87
+ bitDepth?: number;
88
+ container?: string;
89
+ isVbr?: boolean;
90
+ isCompressed: boolean;
91
+ }
92
+ interface SynthesisTimeouts {
93
+ urlValidationMs?: number;
94
+ perChunkMs?: number;
95
+ chunkWithRetriesMs?: number;
96
+ totalJobMs?: number;
97
+ }
98
+ interface RetryOptions {
99
+ maxRetries: number;
100
+ initialDelayMs: number;
101
+ maxDelayMs: number;
102
+ shouldRetry?: (error: unknown, attempt: number) => boolean;
69
103
  }
70
104
  type SynthesisChunkStatus = "pending" | "synthesizing" | "success" | "failed";
71
105
  interface SsmlSynthesisBoundary {
@@ -85,6 +119,7 @@ interface SsmlSynthesisBoundary {
85
119
  /** Audio offset within the originating chunk before merge. */
86
120
  chunkAudioOffsetMs?: number;
87
121
  requestId?: string;
122
+ mappingStatus: MappingStatus;
88
123
  }
89
124
  interface SsmlSynthesisViseme {
90
125
  visemeId: number;
@@ -98,6 +133,7 @@ interface SsmlSynthesisViseme {
98
133
  originalTextRange?: SsmlTextRange;
99
134
  chunkAudioOffsetMs?: number;
100
135
  requestId?: string;
136
+ mappingStatus: MappingStatus;
101
137
  }
102
138
  interface SsmlSynthesisBookmark {
103
139
  name: string;
@@ -111,6 +147,7 @@ interface SsmlSynthesisBookmark {
111
147
  originalTextRange?: SsmlTextRange;
112
148
  chunkAudioOffsetMs?: number;
113
149
  requestId?: string;
150
+ mappingStatus: MappingStatus;
114
151
  }
115
152
  /** Audio and Azure Speech synchronization events emitted for one SSML request. */
116
153
  interface SsmlSynthesisResult {
@@ -132,6 +169,7 @@ interface SsmlSynthesisResult {
132
169
  };
133
170
  /** MIME type of a result produced by an explicit merge operation. */
134
171
  mimeType?: string;
172
+ audioSpec?: AudioSpecification;
135
173
  }
136
174
  interface MergedSynthesisResult extends SsmlSynthesisResult {
137
175
  mimeType: string;
@@ -151,8 +189,37 @@ interface SynthesizeChunksOptions {
151
189
  outputFormat?: AzureTtsOutputFormat | string;
152
190
  signal?: AbortSignal;
153
191
  timeoutMs?: number;
192
+ timeouts?: SynthesisTimeouts;
154
193
  sourceNodePath?: string[];
194
+ concurrency?: number;
195
+ retryOptions?: RetryOptions;
196
+ cancelOnFailure?: boolean;
197
+ resumeChunks?: readonly SynthesizedChunk[];
198
+ resumeChunkIndices?: readonly number[];
199
+ customMerger?: CustomAudioMerger;
200
+ outputMimeType?: string;
201
+ postMergeValidator?: PostMergeValidator;
155
202
  }
203
+ interface CustomMergerContext {
204
+ format: string;
205
+ outputMimeType: string;
206
+ inputSpecs: readonly AudioSpecification[];
207
+ signal: AbortSignal;
208
+ }
209
+ type CustomAudioMerger = (buffers: ArrayBuffer[], context: CustomMergerContext) => Promise<ArrayBuffer> | ArrayBuffer;
210
+ type PostMergeValidator = (result: MergedSynthesisResult, context: CustomMergerContext) => boolean | undefined | Promise<boolean | undefined>;
211
+ interface SynthesizedChunk extends SsmlSynthesisResult {
212
+ chunkIndex: number;
213
+ }
214
+ interface PartialChunkSynthesisResult {
215
+ synthesizedChunks: readonly SynthesizedChunk[];
216
+ completedChunks: readonly SynthesizedChunk[];
217
+ pendingChunkIndices: readonly number[];
218
+ failedChunkIndices: readonly number[];
219
+ totalChunks: number;
220
+ }
221
+ /** Alias for applications that use the shorter result name. */
222
+ type PartialSynthesisResult = PartialChunkSynthesisResult;
156
223
  interface SynthesisProgressEvent {
157
224
  /** 1-based completed chunk count retained for backward compatibility. */
158
225
  currentChunk: number;
@@ -163,6 +230,9 @@ interface SynthesisProgressEvent {
163
230
  status: SynthesisChunkStatus;
164
231
  durationMs: number;
165
232
  error?: unknown;
233
+ retryAttempt?: number;
234
+ nextRetryDelayMs?: number;
235
+ isRetrying?: boolean;
166
236
  }
167
237
  interface AzureTtsLogger {
168
238
  debug?: (...args: unknown[]) => void;
@@ -173,23 +243,29 @@ interface AzureTtsLogger {
173
243
  interface AzureTtsClientOptions {
174
244
  signal?: AbortSignal;
175
245
  timeoutMs?: number;
246
+ timeouts?: SynthesisTimeouts;
176
247
  subscriptionKey: string;
177
248
  region: string;
178
249
  endpoint?: string;
179
250
  outputFormat?: string;
180
251
  logger?: AzureTtsLogger;
181
252
  onProgress?: (event: SynthesisProgressEvent) => void;
253
+ concurrency?: number;
254
+ retryOptions?: RetryOptions;
182
255
  }
183
256
 
184
- type SynthesisErrorKind = "validation-error" | "azure-api-error" | "merge-error" | "unsupported-format-error" | "cancelled" | "timeout";
257
+ type SynthesisErrorKind = "validation-error" | "azure-api-error" | "merge-error" | "audio-format-mismatch" | "unsupported-format-error" | "cancelled" | "timeout";
185
258
  declare class AzureTtsError extends Error {
186
259
  readonly kind: "azure-api-error";
187
260
  readonly status: number;
188
261
  readonly statusText: string;
189
262
  readonly responseBody: string;
190
263
  readonly requestId: string | null;
191
- constructor(status: number, statusText: string, responseBody: string, requestId: string | null);
264
+ readonly retryAfterMs?: number;
265
+ constructor(status: number, statusText: string, responseBody: string, requestId: string | null, responseHeaders?: Headers | Readonly<Record<string, string>>);
192
266
  }
267
+ /** Reads Retry-After from an error-like value, returning milliseconds when present. */
268
+ declare function getRetryAfterDelayMs(error: unknown): number | undefined;
193
269
  declare class AzureTtsSdkError extends AzureTtsError {
194
270
  readonly errorDetails: string;
195
271
  constructor(errorDetails: string);
@@ -207,13 +283,19 @@ declare class MergeError extends Error {
207
283
  readonly cause: unknown;
208
284
  constructor(message: string, cause?: unknown);
209
285
  }
286
+ /** Thrown when chunk headers describe incompatible audio streams. */
287
+ declare class AudioFormatMismatchError extends Error {
288
+ readonly kind: "audio-format-mismatch";
289
+ readonly inputSpecs: readonly AudioSpecification[];
290
+ constructor(message: string, inputSpecs?: readonly AudioSpecification[]);
291
+ }
210
292
  /** Thrown when audio buffers require container re-multiplexing before they can be merged. */
211
293
  declare class UnsupportedMergeFormatError extends Error {
212
294
  readonly kind: "unsupported-format-error";
213
295
  readonly format: string;
214
296
  constructor(format: string);
215
297
  }
216
- type AzureTtsSynthesisError = AzureTtsError | MergeError | UnsupportedMergeFormatError | SynthesisCancelledError | SynthesisTimeoutError;
298
+ type AzureTtsSynthesisError = AzureTtsError | MergeError | AudioFormatMismatchError | UnsupportedMergeFormatError | SynthesisCancelledError | SynthesisTimeoutError;
217
299
 
218
300
  interface SsmlValidationError {
219
301
  readonly kind: "validation-error";
@@ -227,6 +309,17 @@ declare class ChunkValidationError extends Error {
227
309
  readonly diagnostics: readonly SsmlDiagnostic[];
228
310
  constructor(chunkIndex: number, diagnostics: readonly SsmlDiagnostic[]);
229
311
  }
312
+ interface ChunkDiagnostics {
313
+ readonly chunkIndex: number;
314
+ readonly diagnostics: readonly SsmlDiagnostic[];
315
+ }
316
+ declare class BatchChunkValidationError extends ChunkValidationError {
317
+ readonly chunkDiagnostics: readonly ChunkDiagnostics[];
318
+ readonly totalErrorCount: number;
319
+ readonly errorCount: number;
320
+ readonly totalErrors: number;
321
+ constructor(chunkDiagnostics: readonly ChunkDiagnostics[]);
322
+ }
230
323
  type Result<T, E> = {
231
324
  readonly ok: true;
232
325
  readonly success: true;
@@ -239,11 +332,13 @@ type Result<T, E> = {
239
332
  readonly success: false;
240
333
  readonly status: Kind;
241
334
  readonly error: E;
335
+ readonly partialResult?: PartialChunkSynthesisResult;
242
336
  } : {
243
337
  readonly ok: false;
244
338
  readonly success: false;
245
339
  readonly status: SynthesisErrorKind;
246
340
  readonly error: E;
341
+ readonly partialResult?: PartialChunkSynthesisResult;
247
342
  });
248
343
  type SynthesisResult<T, E> = Result<T, E>;
249
344
  type Success<T> = Extract<Result<T, never>, {
@@ -260,16 +355,26 @@ interface SynthesizeSsmlSafeOptions extends AzureValidationOptions {
260
355
  /** Optional nested form for callers that want to keep validation settings grouped. */
261
356
  validation?: AzureValidationOptions;
262
357
  signal?: AbortSignal;
358
+ timeouts?: SynthesisTimeouts;
263
359
  }
264
360
  interface SynthesizeSsmlChunksSafeOptions extends AzureValidationOptions {
265
361
  validation?: AzureValidationOptions;
266
362
  outputFormat?: string;
267
363
  signal?: AbortSignal;
268
364
  timeoutMs?: number;
365
+ timeouts?: SynthesisTimeouts;
269
366
  sourceNodePath?: string[];
270
367
  onProgress?: (event: SynthesisProgressEvent) => void;
368
+ concurrency?: number;
369
+ retryOptions?: RetryOptions;
370
+ cancelOnFailure?: boolean;
371
+ resumeChunks?: readonly SynthesizedChunk[];
372
+ resumeChunkIndices?: readonly number[];
373
+ customMerger?: CustomAudioMerger;
374
+ outputMimeType?: string;
375
+ postMergeValidator?: PostMergeValidator;
271
376
  }
272
- type SsmlSynthesisChunksSafeResult = Result<SsmlSynthesisResult, never> | Result<never, ChunkValidationError> | Result<never, SsmlSynthesisError | ChunkValidationError>;
377
+ type SsmlSynthesisChunksSafeResult = Result<SsmlSynthesisResult, never> | Result<never, ChunkValidationError> | Result<never, BatchChunkValidationError> | Result<never, SsmlSynthesisError | ChunkValidationError>;
273
378
  interface SynthesisClient {
274
379
  synthesizeSsml(ssml: string, options?: Partial<SynthesizeChunksOptions>): Promise<SsmlSynthesisResult>;
275
380
  synthesizeChunks?(chunks: readonly (SsmlSynthesisChunk | string)[], options?: SynthesizeChunksOptions): Promise<SsmlSynthesisResult>;
@@ -293,22 +398,29 @@ declare class AzureTtsClient {
293
398
  type MergeAudioFormat = "wav" | "mp3" | "raw";
294
399
  interface MergeAudioOptions {
295
400
  format: AzureTtsOutputFormat;
401
+ signal?: AbortSignal;
402
+ outputMimeType?: string;
296
403
  }
404
+ type InputAudioSpecs = AudioSpecification[];
297
405
  interface MergeSynthesisOptions extends MergeAudioOptions {
298
- customMerger?: (buffers: ArrayBuffer[], format: string) => Promise<ArrayBuffer> | ArrayBuffer;
406
+ customMerger?: CustomAudioMerger;
407
+ postMergeValidator?: PostMergeValidator;
299
408
  }
300
409
  type AsyncMergeSynthesisOptions = MergeSynthesisOptions & {
301
410
  customMerger: NonNullable<MergeSynthesisOptions["customMerger"]>;
302
411
  };
412
+ /** Extracts the stream specification from a WAV/MP3 header and output-format fallback. */
413
+ declare function inspectAudioSpecification(buffer: ArrayBuffer, format: string): AudioSpecification;
303
414
  /** Returns whether the named output format can be safely concatenated without re-multiplexing. */
304
415
  declare function resolveMergeAudioFormat(format: string): MergeAudioFormat | undefined;
305
416
  declare function canMergeAudioFormat(format: string): boolean;
306
417
  /** Merges audio buffers while preserving the invariants of supported containers. */
307
418
  declare function mergeAudioBuffers(buffers: readonly ArrayBuffer[], options: MergeAudioOptions): ArrayBuffer;
308
419
  declare function synthesizeSsml(ssml: string, config: TtsConfig): Promise<SsmlSynthesisResult>;
309
- /** Synthesizes chunks sequentially, annotates synchronization events, and merges the results. */
420
+ /** Synthesizes chunks with bounded concurrency, retries transient failures, and merges in chunk order. */
310
421
  declare function synthesizeSsmlChunks(chunks: readonly (SsmlSynthesisChunk | string)[], config: TtsConfig): Promise<SsmlSynthesisResult>;
311
422
  declare function mergeSynthesisResults(results: readonly SsmlSynthesisResult[], options: AsyncMergeSynthesisOptions): Promise<MergedSynthesisResult>;
423
+ declare function mergeSynthesisResults(results: readonly SsmlSynthesisResult[], options: MergeSynthesisOptions): MergedSynthesisResult | Promise<MergedSynthesisResult>;
312
424
  declare function mergeSynthesisResults(results: readonly SsmlSynthesisResult[], options: MergeAudioOptions): MergedSynthesisResult;
313
425
  /** Backward-compatible audio-only synthesis helper. */
314
426
  declare function synthesizeSpeech(ssml: string, config: TtsConfig): Promise<ArrayBuffer>;
@@ -333,6 +445,8 @@ interface FetchedAzureVoiceCatalogMetadata {
333
445
  generatedAt: string;
334
446
  apiVersion: string;
335
447
  regions: readonly string[];
448
+ expiresAt?: string;
449
+ regionDiffs?: Readonly<Record<string, readonly string[]>>;
336
450
  }
337
451
  interface AzureVoiceCatalog {
338
452
  voices: readonly AzureVoiceCatalogVoice[];
@@ -341,4 +455,4 @@ interface AzureVoiceCatalog {
341
455
  /** Fetches and deduplicates the current Azure Speech voice catalog for one or more regions. */
342
456
  declare function fetchAzureVoiceCatalog(options: FetchAzureVoiceCatalogOptions): Promise<AzureVoiceCatalog>;
343
457
 
344
- export { type AzureApiErrorResult, type SsmlValidationError as AzureSsmlValidationError, AzureTtsClient, type AzureTtsClientOptions, AzureTtsError, type AzureTtsLogger, type AzureTtsOutputFormat, AzureTtsSdkError, type AzureTtsSynthesisError, type AzureVoiceCatalog, type AzureVoiceCatalogVoice, ChunkValidationError, DEFAULT_OUTPUT_FORMAT, type FetchAzureVoiceCatalogOptions, type FetchedAzureVoiceCatalogMetadata, type MergeAudioFormat, type MergeAudioOptions, MergeError, type MergeSynthesisOptions, type MergedSynthesisResult, type Result, type SsmlSynthesisBookmark, type SsmlSynthesisBoundary, type SsmlSynthesisChunk, type SsmlSynthesisChunksSafeResult, type SsmlSynthesisError, type SsmlSynthesisResult, type SsmlSynthesisSafeResult, type SsmlSynthesisViseme, type Success, SynthesisCancelledError, type SynthesisChunkStatus, type SynthesisErrorKind, type SynthesisProgressEvent, type SynthesisResult, SynthesisTimeoutError, type SynthesizeChunksOptions, type SynthesizeSsmlChunksSafeOptions, type SynthesizeSsmlSafeOptions, type TtsConfig, UnsupportedMergeFormatError, type ValidationErrorResult, canMergeAudioFormat, fetchAzureVoiceCatalog, mergeAudioBuffers, mergeSynthesisResults, resolveMergeAudioFormat, resolveMimeType, synthesizeSpeech, synthesizeSsml, synthesizeSsmlChunks, synthesizeSsmlChunksSafe, synthesizeSsmlSafe };
458
+ export { AudioFormatMismatchError, type AudioSpecification, type AzureApiErrorResult, type SsmlValidationError as AzureSsmlValidationError, AzureTtsClient, type AzureTtsClientOptions, AzureTtsError, type AzureTtsLogger, type AzureTtsOutputFormat, AzureTtsSdkError, type AzureTtsSynthesisError, type AzureVoiceCatalog, type AzureVoiceCatalogVoice, BatchChunkValidationError, type ChunkDiagnostics, ChunkValidationError, type CustomAudioMerger, type CustomMergerContext, DEFAULT_OUTPUT_FORMAT, type FetchAzureVoiceCatalogOptions, type FetchedAzureVoiceCatalogMetadata, type InputAudioSpecs, type MappingStatus, type MergeAudioFormat, type MergeAudioOptions, MergeError, type MergeSynthesisOptions, type MergedSynthesisResult, type PartialChunkSynthesisResult, type PartialSynthesisResult, type PostMergeValidator, type Result, type RetryOptions, type SsmlSynthesisBookmark, type SsmlSynthesisBoundary, type SsmlSynthesisChunk, type SsmlSynthesisChunksSafeResult, type SsmlSynthesisError, type SsmlSynthesisResult, type SsmlSynthesisSafeResult, type SsmlSynthesisViseme, type Success, SynthesisCancelledError, type SynthesisChunkStatus, type SynthesisErrorKind, type SynthesisProgressEvent, type SynthesisResult, SynthesisTimeoutError, type SynthesisTimeouts, type SynthesizeChunksOptions, type SynthesizeSsmlChunksSafeOptions, type SynthesizeSsmlSafeOptions, type SynthesizedChunk, type TtsConfig, UnsupportedMergeFormatError, type ValidationErrorResult, canMergeAudioFormat, fetchAzureVoiceCatalog, getRetryAfterDelayMs, inspectAudioSpecification, mergeAudioBuffers, mergeSynthesisResults, resolveMergeAudioFormat, resolveMimeType, synthesizeSpeech, synthesizeSsml, synthesizeSsmlChunks, synthesizeSsmlChunksSafe, synthesizeSsmlSafe };