@ssml-builder-js/azure-tts-client 2.13.0 → 2.15.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.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add strict audio merge formats, discriminated synthesis errors, per-event source mappings, abortable URL validation, external audio muxers, and live Visual Editor voice capability warnings.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+ - @ssml-builder-js/ssml-core@2.15.0
13
+
14
+ ## 2.14.0
15
+
16
+ ### Minor Changes
17
+
18
+ - Add safe container-aware audio merging, preflight-validated SSML chunk synthesis with structured progress events, source mapping metadata, controlled URL validation, and voice capability details in the Visual Editor.
19
+
20
+ ### Patch Changes
21
+
22
+ - Updated dependencies
23
+ - @ssml-builder-js/ssml-core@2.14.0
24
+
3
25
  ## 2.13.0
4
26
 
5
27
  ### Minor Changes
package/dist/index.d.mts CHANGED
@@ -1,4 +1,50 @@
1
- import { SsmlDiagnostic, AzureValidationOptions } from '@ssml-builder-js/ssml-core';
1
+ import { SsmlTextRange, SsmlSourceTextSegment, SsmlSourceMarker, SsmlDiagnostic, AzureValidationOptions } from '@ssml-builder-js/ssml-core';
2
+ import * as SpeechSDK from 'microsoft-cognitiveservices-speech-sdk';
3
+
4
+ declare const DEFAULT_OUTPUT_FORMAT = "audio-16khz-128kbitrate-mono-mp3";
5
+ declare const OUTPUT_FORMATS: {
6
+ "raw-8khz-8bit-mono-mulaw": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz8BitMonoMULaw;
7
+ "riff-16khz-16kbps-mono-siren": SpeechSDK.SpeechSynthesisOutputFormat.Riff16Khz16KbpsMonoSiren;
8
+ "audio-16khz-16kbps-mono-siren": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz16KbpsMonoSiren;
9
+ "audio-16khz-32kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz32KBitRateMonoMp3;
10
+ "audio-16khz-128kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz128KBitRateMonoMp3;
11
+ "audio-16khz-64kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz64KBitRateMonoMp3;
12
+ "audio-24khz-48kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz48KBitRateMonoMp3;
13
+ "audio-24khz-96kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz96KBitRateMonoMp3;
14
+ "audio-24khz-160kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz160KBitRateMonoMp3;
15
+ "raw-16khz-16bit-mono-truesilk": SpeechSDK.SpeechSynthesisOutputFormat.Raw16Khz16BitMonoTrueSilk;
16
+ "riff-16khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Riff16Khz16BitMonoPcm;
17
+ "riff-8khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz16BitMonoPcm;
18
+ "riff-24khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm;
19
+ "riff-8khz-8bit-mono-mulaw": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz8BitMonoMULaw;
20
+ "raw-16khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Raw16Khz16BitMonoPcm;
21
+ "raw-24khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoPcm;
22
+ "raw-8khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz16BitMonoPcm;
23
+ "ogg-16khz-16bit-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Ogg16Khz16BitMonoOpus;
24
+ "ogg-24khz-16bit-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Ogg24Khz16BitMonoOpus;
25
+ "raw-48khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Raw48Khz16BitMonoPcm;
26
+ "riff-48khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Riff48Khz16BitMonoPcm;
27
+ "audio-48khz-96kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio48Khz96KBitRateMonoMp3;
28
+ "audio-48khz-192kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio48Khz192KBitRateMonoMp3;
29
+ "ogg-48khz-16bit-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Ogg48Khz16BitMonoOpus;
30
+ "webm-16khz-16bit-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Webm16Khz16BitMonoOpus;
31
+ "webm-24khz-16bit-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Webm24Khz16BitMonoOpus;
32
+ "webm-24khz-16bit-24kbps-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Webm24Khz16Bit24KbpsMonoOpus;
33
+ "raw-24khz-16bit-mono-truesilk": SpeechSDK.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoTrueSilk;
34
+ "raw-8khz-8bit-mono-alaw": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz8BitMonoALaw;
35
+ "riff-8khz-8bit-mono-alaw": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz8BitMonoALaw;
36
+ "audio-16khz-16bit-32kbps-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz16Bit32KbpsMonoOpus;
37
+ "audio-24khz-16bit-48kbps-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz16Bit48KbpsMonoOpus;
38
+ "audio-24khz-16bit-24kbps-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz16Bit24KbpsMonoOpus;
39
+ "raw-22050hz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Raw22050Hz16BitMonoPcm;
40
+ "riff-22050hz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Riff22050Hz16BitMonoPcm;
41
+ "raw-44100hz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Raw44100Hz16BitMonoPcm;
42
+ "riff-44100hz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Riff44100Hz16BitMonoPcm;
43
+ "amr-wb-16000hz": SpeechSDK.SpeechSynthesisOutputFormat.AmrWb16000Hz;
44
+ "g722-16khz-64kbps": SpeechSDK.SpeechSynthesisOutputFormat.G72216Khz64Kbps;
45
+ };
46
+ type AzureTtsOutputFormat = keyof typeof OUTPUT_FORMATS;
47
+ declare function resolveMimeType(outputFormat: string): string;
2
48
 
3
49
  interface TtsConfig {
4
50
  signal?: AbortSignal;
@@ -12,13 +58,16 @@ interface TtsConfig {
12
58
  start: number;
13
59
  end: number;
14
60
  };
15
- /** Reports completion of a chunk when using synthesizeSsmlChunks. */
16
- onProgress?: (event: {
17
- currentChunk: number;
18
- totalChunks: number;
19
- percent: number;
20
- }) => void;
61
+ /** Reports chunk lifecycle events when using chunk synthesis. */
62
+ onProgress?: (event: SynthesisProgressEvent) => void;
63
+ /** Metadata used to map synchronization events back to the source document. */
64
+ chunkIndex?: number;
65
+ sourceNodePath?: string[];
66
+ /** Exact source text segments used to map individual Azure events. */
67
+ sourceTextSegments?: SsmlSourceTextSegment[];
68
+ sourceMarkers?: SsmlSourceMarker[];
21
69
  }
70
+ type SynthesisChunkStatus = "pending" | "synthesizing" | "success" | "failed";
22
71
  interface SsmlSynthesisBoundary {
23
72
  text: string;
24
73
  audioOffsetMs: number;
@@ -27,6 +76,14 @@ interface SsmlSynthesisBoundary {
27
76
  start: number;
28
77
  end: number;
29
78
  };
79
+ /** Chunk that produced this event. */
80
+ chunkIndex?: number;
81
+ /** Path of the source SSML node, when available. */
82
+ sourceNodePath?: string[];
83
+ /** Original text range represented by this event. */
84
+ originalTextRange?: SsmlTextRange;
85
+ /** Audio offset within the originating chunk before merge. */
86
+ chunkAudioOffsetMs?: number;
30
87
  requestId?: string;
31
88
  }
32
89
  interface SsmlSynthesisViseme {
@@ -36,6 +93,10 @@ interface SsmlSynthesisViseme {
36
93
  start: number;
37
94
  end: number;
38
95
  };
96
+ chunkIndex?: number;
97
+ sourceNodePath?: string[];
98
+ originalTextRange?: SsmlTextRange;
99
+ chunkAudioOffsetMs?: number;
39
100
  requestId?: string;
40
101
  }
41
102
  interface SsmlSynthesisBookmark {
@@ -45,6 +106,10 @@ interface SsmlSynthesisBookmark {
45
106
  start: number;
46
107
  end: number;
47
108
  };
109
+ chunkIndex?: number;
110
+ sourceNodePath?: string[];
111
+ originalTextRange?: SsmlTextRange;
112
+ chunkAudioOffsetMs?: number;
48
113
  requestId?: string;
49
114
  }
50
115
  /** Audio and Azure Speech synchronization events emitted for one SSML request. */
@@ -65,6 +130,11 @@ interface SsmlSynthesisResult {
65
130
  start: number;
66
131
  end: number;
67
132
  };
133
+ /** MIME type of a result produced by an explicit merge operation. */
134
+ mimeType?: string;
135
+ }
136
+ interface MergedSynthesisResult extends SsmlSynthesisResult {
137
+ mimeType: string;
68
138
  }
69
139
  interface SsmlSynthesisChunk {
70
140
  ssml: string;
@@ -72,14 +142,27 @@ interface SsmlSynthesisChunk {
72
142
  start: number;
73
143
  end: number;
74
144
  };
145
+ sourceNodePath?: string[];
146
+ sourceTextSegments?: SsmlSourceTextSegment[];
147
+ sourceMarkers?: SsmlSourceMarker[];
75
148
  }
76
149
  interface SynthesizeChunksOptions {
77
150
  onProgress?: (event: SynthesisProgressEvent) => void;
151
+ outputFormat?: AzureTtsOutputFormat | string;
152
+ signal?: AbortSignal;
153
+ timeoutMs?: number;
154
+ sourceNodePath?: string[];
78
155
  }
79
156
  interface SynthesisProgressEvent {
157
+ /** 1-based completed chunk count retained for backward compatibility. */
80
158
  currentChunk: number;
81
159
  totalChunks: number;
82
160
  percent: number;
161
+ chunkIndex: number;
162
+ originalTextRange?: SsmlTextRange;
163
+ status: SynthesisChunkStatus;
164
+ durationMs: number;
165
+ error?: unknown;
83
166
  }
84
167
  interface AzureTtsLogger {
85
168
  debug?: (...args: unknown[]) => void;
@@ -98,7 +181,9 @@ interface AzureTtsClientOptions {
98
181
  onProgress?: (event: SynthesisProgressEvent) => void;
99
182
  }
100
183
 
184
+ type SynthesisErrorKind = "validation-error" | "azure-api-error" | "merge-error" | "unsupported-format-error" | "cancelled" | "timeout";
101
185
  declare class AzureTtsError extends Error {
186
+ readonly kind: "azure-api-error";
102
187
  readonly status: number;
103
188
  readonly statusText: string;
104
189
  readonly responseBody: string;
@@ -109,23 +194,57 @@ declare class AzureTtsSdkError extends AzureTtsError {
109
194
  readonly errorDetails: string;
110
195
  constructor(errorDetails: string);
111
196
  }
197
+ declare class SynthesisCancelledError extends Error {
198
+ readonly kind: "cancelled";
199
+ constructor(message?: string);
200
+ }
201
+ declare class SynthesisTimeoutError extends Error {
202
+ readonly kind: "timeout";
203
+ constructor(message: string);
204
+ }
205
+ declare class MergeError extends Error {
206
+ readonly kind: "merge-error";
207
+ readonly cause: unknown;
208
+ constructor(message: string, cause?: unknown);
209
+ }
210
+ /** Thrown when audio buffers require container re-multiplexing before they can be merged. */
211
+ declare class UnsupportedMergeFormatError extends Error {
212
+ readonly kind: "unsupported-format-error";
213
+ readonly format: string;
214
+ constructor(format: string);
215
+ }
216
+ type AzureTtsSynthesisError = AzureTtsError | MergeError | UnsupportedMergeFormatError | SynthesisCancelledError | SynthesisTimeoutError;
112
217
 
113
218
  interface SsmlValidationError {
114
- readonly kind: "validation";
219
+ readonly kind: "validation-error";
115
220
  readonly message: string;
116
221
  readonly diagnostics: readonly SsmlDiagnostic[];
117
222
  }
223
+ type SsmlSynthesisError = SsmlValidationError | AzureTtsSynthesisError;
224
+ declare class ChunkValidationError extends Error {
225
+ readonly kind: "validation-error";
226
+ readonly chunkIndex: number;
227
+ readonly diagnostics: readonly SsmlDiagnostic[];
228
+ constructor(chunkIndex: number, diagnostics: readonly SsmlDiagnostic[]);
229
+ }
118
230
  type Result<T, E> = {
119
231
  readonly ok: true;
120
232
  readonly success: true;
121
233
  readonly status: "success";
122
234
  readonly value: T;
123
- } | {
235
+ } | (E extends {
236
+ readonly kind: infer Kind extends SynthesisErrorKind;
237
+ } ? {
124
238
  readonly ok: false;
125
239
  readonly success: false;
126
- readonly status: "validation-error" | "azure-api-error";
240
+ readonly status: Kind;
127
241
  readonly error: E;
128
- };
242
+ } : {
243
+ readonly ok: false;
244
+ readonly success: false;
245
+ readonly status: SynthesisErrorKind;
246
+ readonly error: E;
247
+ });
129
248
  type SynthesisResult<T, E> = Result<T, E>;
130
249
  type Success<T> = Extract<Result<T, never>, {
131
250
  readonly ok: true;
@@ -136,31 +255,61 @@ type ValidationErrorResult = Extract<Result<never, SsmlValidationError>, {
136
255
  type AzureApiErrorResult = Extract<Result<never, AzureTtsError>, {
137
256
  readonly status: "azure-api-error";
138
257
  }>;
139
- type SsmlSynthesisSafeResult = Result<SsmlSynthesisResult, never> | Result<never, SsmlValidationError> | Result<never, AzureTtsError>;
258
+ type SsmlSynthesisSafeResult = Result<SsmlSynthesisResult, never> | Result<never, SsmlValidationError> | Result<never, SsmlSynthesisError>;
140
259
  interface SynthesizeSsmlSafeOptions extends AzureValidationOptions {
141
260
  /** Optional nested form for callers that want to keep validation settings grouped. */
142
261
  validation?: AzureValidationOptions;
262
+ signal?: AbortSignal;
143
263
  }
264
+ interface SynthesizeSsmlChunksSafeOptions extends AzureValidationOptions {
265
+ validation?: AzureValidationOptions;
266
+ outputFormat?: string;
267
+ signal?: AbortSignal;
268
+ timeoutMs?: number;
269
+ sourceNodePath?: string[];
270
+ onProgress?: (event: SynthesisProgressEvent) => void;
271
+ }
272
+ type SsmlSynthesisChunksSafeResult = Result<SsmlSynthesisResult, never> | Result<never, ChunkValidationError> | Result<never, SsmlSynthesisError | ChunkValidationError>;
144
273
  interface SynthesisClient {
145
- synthesizeSsml(ssml: string): Promise<SsmlSynthesisResult>;
274
+ synthesizeSsml(ssml: string, options?: Partial<SynthesizeChunksOptions>): Promise<SsmlSynthesisResult>;
275
+ synthesizeChunks?(chunks: readonly (SsmlSynthesisChunk | string)[], options?: SynthesizeChunksOptions): Promise<SsmlSynthesisResult>;
146
276
  }
147
277
  /** Validates SSML before invoking Azure and converts validation/API failures to one result shape. */
148
278
  declare function synthesizeSsmlSafe(client: Pick<AzureTtsClient, "synthesizeSsml"> | SynthesisClient, ssml: string, options?: SynthesizeSsmlSafeOptions): Promise<SsmlSynthesisSafeResult>;
279
+ /** Validates every chunk before synthesis and returns a chunk-addressable result. */
280
+ declare function synthesizeSsmlChunksSafe(client: Pick<AzureTtsClient, "synthesizeSsml" | "synthesizeChunks"> | SynthesisClient, chunks: readonly (SsmlSynthesisChunk | string)[], options?: SynthesizeSsmlChunksSafeOptions): Promise<SsmlSynthesisChunksSafeResult>;
149
281
 
150
282
  declare class AzureTtsClient {
151
283
  #private;
152
284
  constructor(options: AzureTtsClientOptions);
153
285
  synthesize(ssml: string): Promise<ArrayBuffer>;
154
- synthesizeSsml(ssml: string): Promise<SsmlSynthesisResult>;
286
+ synthesizeSsml(ssml: string, options?: Partial<TtsConfig>): Promise<SsmlSynthesisResult>;
155
287
  synthesizeChunks(chunks: readonly (SsmlSynthesisChunk | string)[], options?: SynthesizeChunksOptions): Promise<SsmlSynthesisResult>;
156
288
  synthesizeSsmlSafe(ssml: string, options?: SynthesizeSsmlSafeOptions): Promise<SsmlSynthesisSafeResult>;
289
+ synthesizeChunksSafe(chunks: readonly (SsmlSynthesisChunk | string)[], options?: SynthesizeSsmlChunksSafeOptions): Promise<SsmlSynthesisChunksSafeResult>;
290
+ synthesizeSsmlChunksSafe(chunks: readonly (SsmlSynthesisChunk | string)[], options?: SynthesizeSsmlChunksSafeOptions): Promise<SsmlSynthesisChunksSafeResult>;
157
291
  }
158
292
 
293
+ type MergeAudioFormat = "wav" | "mp3" | "raw";
294
+ interface MergeAudioOptions {
295
+ format: AzureTtsOutputFormat;
296
+ }
297
+ interface MergeSynthesisOptions extends MergeAudioOptions {
298
+ customMerger?: (buffers: ArrayBuffer[], format: string) => Promise<ArrayBuffer> | ArrayBuffer;
299
+ }
300
+ type AsyncMergeSynthesisOptions = MergeSynthesisOptions & {
301
+ customMerger: NonNullable<MergeSynthesisOptions["customMerger"]>;
302
+ };
303
+ /** Returns whether the named output format can be safely concatenated without re-multiplexing. */
304
+ declare function resolveMergeAudioFormat(format: string): MergeAudioFormat | undefined;
305
+ declare function canMergeAudioFormat(format: string): boolean;
306
+ /** Merges audio buffers while preserving the invariants of supported containers. */
307
+ declare function mergeAudioBuffers(buffers: readonly ArrayBuffer[], options: MergeAudioOptions): ArrayBuffer;
159
308
  declare function synthesizeSsml(ssml: string, config: TtsConfig): Promise<SsmlSynthesisResult>;
160
309
  /** Synthesizes chunks sequentially, annotates synchronization events, and merges the results. */
161
310
  declare function synthesizeSsmlChunks(chunks: readonly (SsmlSynthesisChunk | string)[], config: TtsConfig): Promise<SsmlSynthesisResult>;
162
- /** Concatenates audio buffers and shifts all synchronization events by prior chunk durations. */
163
- declare function mergeSynthesisResults(results: readonly SsmlSynthesisResult[]): SsmlSynthesisResult;
311
+ declare function mergeSynthesisResults(results: readonly SsmlSynthesisResult[], options: AsyncMergeSynthesisOptions): Promise<MergedSynthesisResult>;
312
+ declare function mergeSynthesisResults(results: readonly SsmlSynthesisResult[], options: MergeAudioOptions): MergedSynthesisResult;
164
313
  /** Backward-compatible audio-only synthesis helper. */
165
314
  declare function synthesizeSpeech(ssml: string, config: TtsConfig): Promise<ArrayBuffer>;
166
315
 
@@ -173,6 +322,9 @@ interface AzureVoiceCatalogVoice {
173
322
  locale: string;
174
323
  secondaryLocales?: readonly string[];
175
324
  styles?: readonly string[];
325
+ supportedTags?: readonly string[];
326
+ unsupportedTags?: readonly string[];
327
+ models?: readonly string[];
176
328
  regions: readonly string[];
177
329
  status?: "ga" | "preview" | "deprecated";
178
330
  }
@@ -189,4 +341,4 @@ interface AzureVoiceCatalog {
189
341
  /** Fetches and deduplicates the current Azure Speech voice catalog for one or more regions. */
190
342
  declare function fetchAzureVoiceCatalog(options: FetchAzureVoiceCatalogOptions): Promise<AzureVoiceCatalog>;
191
343
 
192
- export { type AzureApiErrorResult, type SsmlValidationError as AzureSsmlValidationError, AzureTtsClient, type AzureTtsClientOptions, AzureTtsError, type AzureTtsLogger, AzureTtsSdkError, type AzureVoiceCatalog, type AzureVoiceCatalogVoice, type FetchAzureVoiceCatalogOptions, type FetchedAzureVoiceCatalogMetadata, type Result, type SsmlSynthesisBookmark, type SsmlSynthesisBoundary, type SsmlSynthesisChunk, type SsmlSynthesisResult, type SsmlSynthesisSafeResult, type SsmlSynthesisViseme, type Success, type SynthesisProgressEvent, type SynthesisResult, type SynthesizeChunksOptions, type SynthesizeSsmlSafeOptions, type TtsConfig, type ValidationErrorResult, fetchAzureVoiceCatalog, mergeSynthesisResults, synthesizeSpeech, synthesizeSsml, synthesizeSsmlChunks, synthesizeSsmlSafe };
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 };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,50 @@
1
- import { SsmlDiagnostic, AzureValidationOptions } from '@ssml-builder-js/ssml-core';
1
+ import { SsmlTextRange, SsmlSourceTextSegment, SsmlSourceMarker, SsmlDiagnostic, AzureValidationOptions } from '@ssml-builder-js/ssml-core';
2
+ import * as SpeechSDK from 'microsoft-cognitiveservices-speech-sdk';
3
+
4
+ declare const DEFAULT_OUTPUT_FORMAT = "audio-16khz-128kbitrate-mono-mp3";
5
+ declare const OUTPUT_FORMATS: {
6
+ "raw-8khz-8bit-mono-mulaw": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz8BitMonoMULaw;
7
+ "riff-16khz-16kbps-mono-siren": SpeechSDK.SpeechSynthesisOutputFormat.Riff16Khz16KbpsMonoSiren;
8
+ "audio-16khz-16kbps-mono-siren": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz16KbpsMonoSiren;
9
+ "audio-16khz-32kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz32KBitRateMonoMp3;
10
+ "audio-16khz-128kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz128KBitRateMonoMp3;
11
+ "audio-16khz-64kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz64KBitRateMonoMp3;
12
+ "audio-24khz-48kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz48KBitRateMonoMp3;
13
+ "audio-24khz-96kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz96KBitRateMonoMp3;
14
+ "audio-24khz-160kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz160KBitRateMonoMp3;
15
+ "raw-16khz-16bit-mono-truesilk": SpeechSDK.SpeechSynthesisOutputFormat.Raw16Khz16BitMonoTrueSilk;
16
+ "riff-16khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Riff16Khz16BitMonoPcm;
17
+ "riff-8khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz16BitMonoPcm;
18
+ "riff-24khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm;
19
+ "riff-8khz-8bit-mono-mulaw": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz8BitMonoMULaw;
20
+ "raw-16khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Raw16Khz16BitMonoPcm;
21
+ "raw-24khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoPcm;
22
+ "raw-8khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz16BitMonoPcm;
23
+ "ogg-16khz-16bit-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Ogg16Khz16BitMonoOpus;
24
+ "ogg-24khz-16bit-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Ogg24Khz16BitMonoOpus;
25
+ "raw-48khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Raw48Khz16BitMonoPcm;
26
+ "riff-48khz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Riff48Khz16BitMonoPcm;
27
+ "audio-48khz-96kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio48Khz96KBitRateMonoMp3;
28
+ "audio-48khz-192kbitrate-mono-mp3": SpeechSDK.SpeechSynthesisOutputFormat.Audio48Khz192KBitRateMonoMp3;
29
+ "ogg-48khz-16bit-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Ogg48Khz16BitMonoOpus;
30
+ "webm-16khz-16bit-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Webm16Khz16BitMonoOpus;
31
+ "webm-24khz-16bit-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Webm24Khz16BitMonoOpus;
32
+ "webm-24khz-16bit-24kbps-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Webm24Khz16Bit24KbpsMonoOpus;
33
+ "raw-24khz-16bit-mono-truesilk": SpeechSDK.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoTrueSilk;
34
+ "raw-8khz-8bit-mono-alaw": SpeechSDK.SpeechSynthesisOutputFormat.Raw8Khz8BitMonoALaw;
35
+ "riff-8khz-8bit-mono-alaw": SpeechSDK.SpeechSynthesisOutputFormat.Riff8Khz8BitMonoALaw;
36
+ "audio-16khz-16bit-32kbps-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Audio16Khz16Bit32KbpsMonoOpus;
37
+ "audio-24khz-16bit-48kbps-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz16Bit48KbpsMonoOpus;
38
+ "audio-24khz-16bit-24kbps-mono-opus": SpeechSDK.SpeechSynthesisOutputFormat.Audio24Khz16Bit24KbpsMonoOpus;
39
+ "raw-22050hz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Raw22050Hz16BitMonoPcm;
40
+ "riff-22050hz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Riff22050Hz16BitMonoPcm;
41
+ "raw-44100hz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Raw44100Hz16BitMonoPcm;
42
+ "riff-44100hz-16bit-mono-pcm": SpeechSDK.SpeechSynthesisOutputFormat.Riff44100Hz16BitMonoPcm;
43
+ "amr-wb-16000hz": SpeechSDK.SpeechSynthesisOutputFormat.AmrWb16000Hz;
44
+ "g722-16khz-64kbps": SpeechSDK.SpeechSynthesisOutputFormat.G72216Khz64Kbps;
45
+ };
46
+ type AzureTtsOutputFormat = keyof typeof OUTPUT_FORMATS;
47
+ declare function resolveMimeType(outputFormat: string): string;
2
48
 
3
49
  interface TtsConfig {
4
50
  signal?: AbortSignal;
@@ -12,13 +58,16 @@ interface TtsConfig {
12
58
  start: number;
13
59
  end: number;
14
60
  };
15
- /** Reports completion of a chunk when using synthesizeSsmlChunks. */
16
- onProgress?: (event: {
17
- currentChunk: number;
18
- totalChunks: number;
19
- percent: number;
20
- }) => void;
61
+ /** Reports chunk lifecycle events when using chunk synthesis. */
62
+ onProgress?: (event: SynthesisProgressEvent) => void;
63
+ /** Metadata used to map synchronization events back to the source document. */
64
+ chunkIndex?: number;
65
+ sourceNodePath?: string[];
66
+ /** Exact source text segments used to map individual Azure events. */
67
+ sourceTextSegments?: SsmlSourceTextSegment[];
68
+ sourceMarkers?: SsmlSourceMarker[];
21
69
  }
70
+ type SynthesisChunkStatus = "pending" | "synthesizing" | "success" | "failed";
22
71
  interface SsmlSynthesisBoundary {
23
72
  text: string;
24
73
  audioOffsetMs: number;
@@ -27,6 +76,14 @@ interface SsmlSynthesisBoundary {
27
76
  start: number;
28
77
  end: number;
29
78
  };
79
+ /** Chunk that produced this event. */
80
+ chunkIndex?: number;
81
+ /** Path of the source SSML node, when available. */
82
+ sourceNodePath?: string[];
83
+ /** Original text range represented by this event. */
84
+ originalTextRange?: SsmlTextRange;
85
+ /** Audio offset within the originating chunk before merge. */
86
+ chunkAudioOffsetMs?: number;
30
87
  requestId?: string;
31
88
  }
32
89
  interface SsmlSynthesisViseme {
@@ -36,6 +93,10 @@ interface SsmlSynthesisViseme {
36
93
  start: number;
37
94
  end: number;
38
95
  };
96
+ chunkIndex?: number;
97
+ sourceNodePath?: string[];
98
+ originalTextRange?: SsmlTextRange;
99
+ chunkAudioOffsetMs?: number;
39
100
  requestId?: string;
40
101
  }
41
102
  interface SsmlSynthesisBookmark {
@@ -45,6 +106,10 @@ interface SsmlSynthesisBookmark {
45
106
  start: number;
46
107
  end: number;
47
108
  };
109
+ chunkIndex?: number;
110
+ sourceNodePath?: string[];
111
+ originalTextRange?: SsmlTextRange;
112
+ chunkAudioOffsetMs?: number;
48
113
  requestId?: string;
49
114
  }
50
115
  /** Audio and Azure Speech synchronization events emitted for one SSML request. */
@@ -65,6 +130,11 @@ interface SsmlSynthesisResult {
65
130
  start: number;
66
131
  end: number;
67
132
  };
133
+ /** MIME type of a result produced by an explicit merge operation. */
134
+ mimeType?: string;
135
+ }
136
+ interface MergedSynthesisResult extends SsmlSynthesisResult {
137
+ mimeType: string;
68
138
  }
69
139
  interface SsmlSynthesisChunk {
70
140
  ssml: string;
@@ -72,14 +142,27 @@ interface SsmlSynthesisChunk {
72
142
  start: number;
73
143
  end: number;
74
144
  };
145
+ sourceNodePath?: string[];
146
+ sourceTextSegments?: SsmlSourceTextSegment[];
147
+ sourceMarkers?: SsmlSourceMarker[];
75
148
  }
76
149
  interface SynthesizeChunksOptions {
77
150
  onProgress?: (event: SynthesisProgressEvent) => void;
151
+ outputFormat?: AzureTtsOutputFormat | string;
152
+ signal?: AbortSignal;
153
+ timeoutMs?: number;
154
+ sourceNodePath?: string[];
78
155
  }
79
156
  interface SynthesisProgressEvent {
157
+ /** 1-based completed chunk count retained for backward compatibility. */
80
158
  currentChunk: number;
81
159
  totalChunks: number;
82
160
  percent: number;
161
+ chunkIndex: number;
162
+ originalTextRange?: SsmlTextRange;
163
+ status: SynthesisChunkStatus;
164
+ durationMs: number;
165
+ error?: unknown;
83
166
  }
84
167
  interface AzureTtsLogger {
85
168
  debug?: (...args: unknown[]) => void;
@@ -98,7 +181,9 @@ interface AzureTtsClientOptions {
98
181
  onProgress?: (event: SynthesisProgressEvent) => void;
99
182
  }
100
183
 
184
+ type SynthesisErrorKind = "validation-error" | "azure-api-error" | "merge-error" | "unsupported-format-error" | "cancelled" | "timeout";
101
185
  declare class AzureTtsError extends Error {
186
+ readonly kind: "azure-api-error";
102
187
  readonly status: number;
103
188
  readonly statusText: string;
104
189
  readonly responseBody: string;
@@ -109,23 +194,57 @@ declare class AzureTtsSdkError extends AzureTtsError {
109
194
  readonly errorDetails: string;
110
195
  constructor(errorDetails: string);
111
196
  }
197
+ declare class SynthesisCancelledError extends Error {
198
+ readonly kind: "cancelled";
199
+ constructor(message?: string);
200
+ }
201
+ declare class SynthesisTimeoutError extends Error {
202
+ readonly kind: "timeout";
203
+ constructor(message: string);
204
+ }
205
+ declare class MergeError extends Error {
206
+ readonly kind: "merge-error";
207
+ readonly cause: unknown;
208
+ constructor(message: string, cause?: unknown);
209
+ }
210
+ /** Thrown when audio buffers require container re-multiplexing before they can be merged. */
211
+ declare class UnsupportedMergeFormatError extends Error {
212
+ readonly kind: "unsupported-format-error";
213
+ readonly format: string;
214
+ constructor(format: string);
215
+ }
216
+ type AzureTtsSynthesisError = AzureTtsError | MergeError | UnsupportedMergeFormatError | SynthesisCancelledError | SynthesisTimeoutError;
112
217
 
113
218
  interface SsmlValidationError {
114
- readonly kind: "validation";
219
+ readonly kind: "validation-error";
115
220
  readonly message: string;
116
221
  readonly diagnostics: readonly SsmlDiagnostic[];
117
222
  }
223
+ type SsmlSynthesisError = SsmlValidationError | AzureTtsSynthesisError;
224
+ declare class ChunkValidationError extends Error {
225
+ readonly kind: "validation-error";
226
+ readonly chunkIndex: number;
227
+ readonly diagnostics: readonly SsmlDiagnostic[];
228
+ constructor(chunkIndex: number, diagnostics: readonly SsmlDiagnostic[]);
229
+ }
118
230
  type Result<T, E> = {
119
231
  readonly ok: true;
120
232
  readonly success: true;
121
233
  readonly status: "success";
122
234
  readonly value: T;
123
- } | {
235
+ } | (E extends {
236
+ readonly kind: infer Kind extends SynthesisErrorKind;
237
+ } ? {
124
238
  readonly ok: false;
125
239
  readonly success: false;
126
- readonly status: "validation-error" | "azure-api-error";
240
+ readonly status: Kind;
127
241
  readonly error: E;
128
- };
242
+ } : {
243
+ readonly ok: false;
244
+ readonly success: false;
245
+ readonly status: SynthesisErrorKind;
246
+ readonly error: E;
247
+ });
129
248
  type SynthesisResult<T, E> = Result<T, E>;
130
249
  type Success<T> = Extract<Result<T, never>, {
131
250
  readonly ok: true;
@@ -136,31 +255,61 @@ type ValidationErrorResult = Extract<Result<never, SsmlValidationError>, {
136
255
  type AzureApiErrorResult = Extract<Result<never, AzureTtsError>, {
137
256
  readonly status: "azure-api-error";
138
257
  }>;
139
- type SsmlSynthesisSafeResult = Result<SsmlSynthesisResult, never> | Result<never, SsmlValidationError> | Result<never, AzureTtsError>;
258
+ type SsmlSynthesisSafeResult = Result<SsmlSynthesisResult, never> | Result<never, SsmlValidationError> | Result<never, SsmlSynthesisError>;
140
259
  interface SynthesizeSsmlSafeOptions extends AzureValidationOptions {
141
260
  /** Optional nested form for callers that want to keep validation settings grouped. */
142
261
  validation?: AzureValidationOptions;
262
+ signal?: AbortSignal;
143
263
  }
264
+ interface SynthesizeSsmlChunksSafeOptions extends AzureValidationOptions {
265
+ validation?: AzureValidationOptions;
266
+ outputFormat?: string;
267
+ signal?: AbortSignal;
268
+ timeoutMs?: number;
269
+ sourceNodePath?: string[];
270
+ onProgress?: (event: SynthesisProgressEvent) => void;
271
+ }
272
+ type SsmlSynthesisChunksSafeResult = Result<SsmlSynthesisResult, never> | Result<never, ChunkValidationError> | Result<never, SsmlSynthesisError | ChunkValidationError>;
144
273
  interface SynthesisClient {
145
- synthesizeSsml(ssml: string): Promise<SsmlSynthesisResult>;
274
+ synthesizeSsml(ssml: string, options?: Partial<SynthesizeChunksOptions>): Promise<SsmlSynthesisResult>;
275
+ synthesizeChunks?(chunks: readonly (SsmlSynthesisChunk | string)[], options?: SynthesizeChunksOptions): Promise<SsmlSynthesisResult>;
146
276
  }
147
277
  /** Validates SSML before invoking Azure and converts validation/API failures to one result shape. */
148
278
  declare function synthesizeSsmlSafe(client: Pick<AzureTtsClient, "synthesizeSsml"> | SynthesisClient, ssml: string, options?: SynthesizeSsmlSafeOptions): Promise<SsmlSynthesisSafeResult>;
279
+ /** Validates every chunk before synthesis and returns a chunk-addressable result. */
280
+ declare function synthesizeSsmlChunksSafe(client: Pick<AzureTtsClient, "synthesizeSsml" | "synthesizeChunks"> | SynthesisClient, chunks: readonly (SsmlSynthesisChunk | string)[], options?: SynthesizeSsmlChunksSafeOptions): Promise<SsmlSynthesisChunksSafeResult>;
149
281
 
150
282
  declare class AzureTtsClient {
151
283
  #private;
152
284
  constructor(options: AzureTtsClientOptions);
153
285
  synthesize(ssml: string): Promise<ArrayBuffer>;
154
- synthesizeSsml(ssml: string): Promise<SsmlSynthesisResult>;
286
+ synthesizeSsml(ssml: string, options?: Partial<TtsConfig>): Promise<SsmlSynthesisResult>;
155
287
  synthesizeChunks(chunks: readonly (SsmlSynthesisChunk | string)[], options?: SynthesizeChunksOptions): Promise<SsmlSynthesisResult>;
156
288
  synthesizeSsmlSafe(ssml: string, options?: SynthesizeSsmlSafeOptions): Promise<SsmlSynthesisSafeResult>;
289
+ synthesizeChunksSafe(chunks: readonly (SsmlSynthesisChunk | string)[], options?: SynthesizeSsmlChunksSafeOptions): Promise<SsmlSynthesisChunksSafeResult>;
290
+ synthesizeSsmlChunksSafe(chunks: readonly (SsmlSynthesisChunk | string)[], options?: SynthesizeSsmlChunksSafeOptions): Promise<SsmlSynthesisChunksSafeResult>;
157
291
  }
158
292
 
293
+ type MergeAudioFormat = "wav" | "mp3" | "raw";
294
+ interface MergeAudioOptions {
295
+ format: AzureTtsOutputFormat;
296
+ }
297
+ interface MergeSynthesisOptions extends MergeAudioOptions {
298
+ customMerger?: (buffers: ArrayBuffer[], format: string) => Promise<ArrayBuffer> | ArrayBuffer;
299
+ }
300
+ type AsyncMergeSynthesisOptions = MergeSynthesisOptions & {
301
+ customMerger: NonNullable<MergeSynthesisOptions["customMerger"]>;
302
+ };
303
+ /** Returns whether the named output format can be safely concatenated without re-multiplexing. */
304
+ declare function resolveMergeAudioFormat(format: string): MergeAudioFormat | undefined;
305
+ declare function canMergeAudioFormat(format: string): boolean;
306
+ /** Merges audio buffers while preserving the invariants of supported containers. */
307
+ declare function mergeAudioBuffers(buffers: readonly ArrayBuffer[], options: MergeAudioOptions): ArrayBuffer;
159
308
  declare function synthesizeSsml(ssml: string, config: TtsConfig): Promise<SsmlSynthesisResult>;
160
309
  /** Synthesizes chunks sequentially, annotates synchronization events, and merges the results. */
161
310
  declare function synthesizeSsmlChunks(chunks: readonly (SsmlSynthesisChunk | string)[], config: TtsConfig): Promise<SsmlSynthesisResult>;
162
- /** Concatenates audio buffers and shifts all synchronization events by prior chunk durations. */
163
- declare function mergeSynthesisResults(results: readonly SsmlSynthesisResult[]): SsmlSynthesisResult;
311
+ declare function mergeSynthesisResults(results: readonly SsmlSynthesisResult[], options: AsyncMergeSynthesisOptions): Promise<MergedSynthesisResult>;
312
+ declare function mergeSynthesisResults(results: readonly SsmlSynthesisResult[], options: MergeAudioOptions): MergedSynthesisResult;
164
313
  /** Backward-compatible audio-only synthesis helper. */
165
314
  declare function synthesizeSpeech(ssml: string, config: TtsConfig): Promise<ArrayBuffer>;
166
315
 
@@ -173,6 +322,9 @@ interface AzureVoiceCatalogVoice {
173
322
  locale: string;
174
323
  secondaryLocales?: readonly string[];
175
324
  styles?: readonly string[];
325
+ supportedTags?: readonly string[];
326
+ unsupportedTags?: readonly string[];
327
+ models?: readonly string[];
176
328
  regions: readonly string[];
177
329
  status?: "ga" | "preview" | "deprecated";
178
330
  }
@@ -189,4 +341,4 @@ interface AzureVoiceCatalog {
189
341
  /** Fetches and deduplicates the current Azure Speech voice catalog for one or more regions. */
190
342
  declare function fetchAzureVoiceCatalog(options: FetchAzureVoiceCatalogOptions): Promise<AzureVoiceCatalog>;
191
343
 
192
- export { type AzureApiErrorResult, type SsmlValidationError as AzureSsmlValidationError, AzureTtsClient, type AzureTtsClientOptions, AzureTtsError, type AzureTtsLogger, AzureTtsSdkError, type AzureVoiceCatalog, type AzureVoiceCatalogVoice, type FetchAzureVoiceCatalogOptions, type FetchedAzureVoiceCatalogMetadata, type Result, type SsmlSynthesisBookmark, type SsmlSynthesisBoundary, type SsmlSynthesisChunk, type SsmlSynthesisResult, type SsmlSynthesisSafeResult, type SsmlSynthesisViseme, type Success, type SynthesisProgressEvent, type SynthesisResult, type SynthesizeChunksOptions, type SynthesizeSsmlSafeOptions, type TtsConfig, type ValidationErrorResult, fetchAzureVoiceCatalog, mergeSynthesisResults, synthesizeSpeech, synthesizeSsml, synthesizeSsmlChunks, synthesizeSsmlSafe };
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 };