@pie-players/tts-server-polly 0.3.67 → 0.3.68
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/dist/PollyServerProvider.d.ts +8 -13
- package/dist/PollyServerProvider.js +63 -22
- package/package.json +2 -2
|
@@ -46,19 +46,6 @@ export interface PollyProviderConfig extends TTSServerConfig {
|
|
|
46
46
|
*/
|
|
47
47
|
defaultVoice?: string;
|
|
48
48
|
}
|
|
49
|
-
/**
|
|
50
|
-
* AWS Polly Server Provider
|
|
51
|
-
*
|
|
52
|
-
* Provides high-quality neural text-to-speech with precise word-level timing
|
|
53
|
-
* through AWS Polly speech marks.
|
|
54
|
-
*
|
|
55
|
-
* Features:
|
|
56
|
-
* - Native speech marks support (millisecond precision)
|
|
57
|
-
* - Neural and standard voices
|
|
58
|
-
* - 25+ languages
|
|
59
|
-
* - Full SSML support
|
|
60
|
-
* - Parallel audio + speech marks requests
|
|
61
|
-
*/
|
|
62
49
|
export declare class PollyServerProvider extends BaseTTSProvider {
|
|
63
50
|
readonly providerId = "aws-polly";
|
|
64
51
|
readonly providerName = "AWS Polly";
|
|
@@ -100,6 +87,14 @@ export declare class PollyServerProvider extends BaseTTSProvider {
|
|
|
100
87
|
* Clearly documents what features are W3C-standard vs AWS-specific.
|
|
101
88
|
*/
|
|
102
89
|
getCapabilities(): ServerProviderCapabilities;
|
|
90
|
+
/**
|
|
91
|
+
* Map an AWS SDK error to a TTSError, matching the granularity
|
|
92
|
+
* GoogleCloudTTSProvider gives its own vendor errors: a bare
|
|
93
|
+
* `PROVIDER_ERROR` for everything hides cases callers (Host A maps
|
|
94
|
+
* `RATE_LIMIT_EXCEEDED` / `AUTHENTICATION_ERROR` / `INVALID_REQUEST` /
|
|
95
|
+
* `TEXT_TOO_LONG` onto HTTP status codes) already know how to handle.
|
|
96
|
+
*/
|
|
97
|
+
private mapPollyErrorToTTSError;
|
|
103
98
|
/**
|
|
104
99
|
* Clean up AWS Polly client
|
|
105
100
|
*/
|
|
@@ -17,6 +17,34 @@ import { BaseTTSProvider, TTSError, TTSErrorCode, } from "@pie-players/tts-serve
|
|
|
17
17
|
* - Full SSML support
|
|
18
18
|
* - Parallel audio + speech marks requests
|
|
19
19
|
*/
|
|
20
|
+
/**
|
|
21
|
+
* Polly's own SSML vocabulary, on top of the standard elements the base provider
|
|
22
|
+
* knows. `<amazon:effect>` and the `<aws-*>` family are Polly-only.
|
|
23
|
+
*/
|
|
24
|
+
const POLLY_SSML_TAGS = ["<amazon:", "<aws-"];
|
|
25
|
+
/**
|
|
26
|
+
* AWS SDK exception names (`error.name`) that mean the request itself was
|
|
27
|
+
* invalid or unsupported, as opposed to a transient/provider-side failure.
|
|
28
|
+
* @see https://docs.aws.amazon.com/polly/latest/dg/API_Reference.html
|
|
29
|
+
*/
|
|
30
|
+
const POLLY_INVALID_REQUEST_EXCEPTIONS = new Set([
|
|
31
|
+
"InvalidSampleRateException",
|
|
32
|
+
"InvalidSsmlException",
|
|
33
|
+
"LanguageNotSupportedException",
|
|
34
|
+
"ValidationException",
|
|
35
|
+
"EngineNotSupportedException",
|
|
36
|
+
"MarksNotSupportedForFormatException",
|
|
37
|
+
"SsmlMarksNotSupportedForTextTypeException",
|
|
38
|
+
"UnsupportedPlsAlphabetException",
|
|
39
|
+
"UnsupportedPlsLanguageException",
|
|
40
|
+
"InvalidS3BucketException",
|
|
41
|
+
"InvalidS3KeyException",
|
|
42
|
+
"InvalidSnsTopicArnException",
|
|
43
|
+
]);
|
|
44
|
+
const POLLY_RATE_LIMIT_EXCEPTIONS = new Set([
|
|
45
|
+
"ThrottlingException",
|
|
46
|
+
"ServiceQuotaExceededException",
|
|
47
|
+
]);
|
|
20
48
|
export class PollyServerProvider extends BaseTTSProvider {
|
|
21
49
|
providerId = "aws-polly";
|
|
22
50
|
providerName = "AWS Polly";
|
|
@@ -120,29 +148,22 @@ export class PollyServerProvider extends BaseTTSProvider {
|
|
|
120
148
|
};
|
|
121
149
|
}
|
|
122
150
|
catch (error) {
|
|
123
|
-
throw
|
|
151
|
+
throw this.mapPollyErrorToTTSError(error, { request });
|
|
124
152
|
}
|
|
125
153
|
}
|
|
126
154
|
/**
|
|
127
155
|
* Synthesize audio stream
|
|
128
156
|
*/
|
|
129
157
|
async synthesizeAudio(request, voice) {
|
|
130
|
-
|
|
131
|
-
const isSsml = request.text.includes("<speak") ||
|
|
132
|
-
request.text.includes("<emphasis") ||
|
|
133
|
-
request.text.includes("<break") ||
|
|
134
|
-
request.text.includes("<prosody") ||
|
|
135
|
-
request.text.includes("<phoneme") ||
|
|
136
|
-
request.text.includes("<amazon:") ||
|
|
137
|
-
request.text.includes("<aws-");
|
|
138
|
-
const textType = isSsml ? "ssml" : "text";
|
|
139
|
-
if (isSsml) {
|
|
158
|
+
if (this.detectSSML(request.text, POLLY_SSML_TAGS)) {
|
|
140
159
|
console.log("[PollyServerProvider] Detected SSML content, using TextType: ssml");
|
|
141
160
|
}
|
|
161
|
+
const { text, isSsml } = this.applyProsody(request.text, request, POLLY_SSML_TAGS);
|
|
162
|
+
const textType = isSsml ? "ssml" : "text";
|
|
142
163
|
const command = new SynthesizeSpeechCommand({
|
|
143
164
|
Engine: this.engine === "neural" ? Engine.NEURAL : Engine.STANDARD,
|
|
144
165
|
OutputFormat: this.resolveOutputFormat(request),
|
|
145
|
-
Text:
|
|
166
|
+
Text: text,
|
|
146
167
|
TextType: textType,
|
|
147
168
|
VoiceId: voice,
|
|
148
169
|
SampleRate: String(request.sampleRate || 24000),
|
|
@@ -172,19 +193,12 @@ export class PollyServerProvider extends BaseTTSProvider {
|
|
|
172
193
|
* Synthesize speech marks
|
|
173
194
|
*/
|
|
174
195
|
async synthesizeSpeechMarks(request, voice) {
|
|
175
|
-
|
|
176
|
-
const isSsml = request.text.includes("<speak") ||
|
|
177
|
-
request.text.includes("<emphasis") ||
|
|
178
|
-
request.text.includes("<break") ||
|
|
179
|
-
request.text.includes("<prosody") ||
|
|
180
|
-
request.text.includes("<phoneme") ||
|
|
181
|
-
request.text.includes("<amazon:") ||
|
|
182
|
-
request.text.includes("<aws-");
|
|
196
|
+
const { text, isSsml } = this.applyProsody(request.text, request, POLLY_SSML_TAGS);
|
|
183
197
|
const textType = isSsml ? "ssml" : "text";
|
|
184
198
|
const command = new SynthesizeSpeechCommand({
|
|
185
199
|
Engine: this.engine === "neural" ? Engine.NEURAL : Engine.STANDARD,
|
|
186
200
|
OutputFormat: "json",
|
|
187
|
-
Text:
|
|
201
|
+
Text: text,
|
|
188
202
|
TextType: textType,
|
|
189
203
|
VoiceId: voice,
|
|
190
204
|
SpeechMarkTypes: this.resolveSpeechMarkTypes(request),
|
|
@@ -273,7 +287,7 @@ export class PollyServerProvider extends BaseTTSProvider {
|
|
|
273
287
|
});
|
|
274
288
|
}
|
|
275
289
|
catch (error) {
|
|
276
|
-
throw
|
|
290
|
+
throw this.mapPollyErrorToTTSError(error);
|
|
277
291
|
}
|
|
278
292
|
}
|
|
279
293
|
/**
|
|
@@ -310,6 +324,33 @@ export class PollyServerProvider extends BaseTTSProvider {
|
|
|
310
324
|
},
|
|
311
325
|
};
|
|
312
326
|
}
|
|
327
|
+
/**
|
|
328
|
+
* Map an AWS SDK error to a TTSError, matching the granularity
|
|
329
|
+
* GoogleCloudTTSProvider gives its own vendor errors: a bare
|
|
330
|
+
* `PROVIDER_ERROR` for everything hides cases callers (Host A maps
|
|
331
|
+
* `RATE_LIMIT_EXCEEDED` / `AUTHENTICATION_ERROR` / `INVALID_REQUEST` /
|
|
332
|
+
* `TEXT_TOO_LONG` onto HTTP status codes) already know how to handle.
|
|
333
|
+
*/
|
|
334
|
+
mapPollyErrorToTTSError(error, extraDetails) {
|
|
335
|
+
const err = error;
|
|
336
|
+
const message = err?.message || String(error);
|
|
337
|
+
const statusCode = err?.$metadata?.httpStatusCode;
|
|
338
|
+
const details = { error, ...extraDetails };
|
|
339
|
+
if (err?.name === "TextLengthExceededException") {
|
|
340
|
+
return new TTSError(TTSErrorCode.TEXT_TOO_LONG, `AWS Polly text length exceeded: ${message}`, details, this.providerId);
|
|
341
|
+
}
|
|
342
|
+
if (err?.name && POLLY_INVALID_REQUEST_EXCEPTIONS.has(err.name)) {
|
|
343
|
+
return new TTSError(TTSErrorCode.INVALID_REQUEST, `Invalid request to AWS Polly: ${message}`, details, this.providerId);
|
|
344
|
+
}
|
|
345
|
+
if ((err?.name && POLLY_RATE_LIMIT_EXCEPTIONS.has(err.name)) ||
|
|
346
|
+
statusCode === 429) {
|
|
347
|
+
return new TTSError(TTSErrorCode.RATE_LIMIT_EXCEEDED, `AWS Polly rate limit exceeded: ${message}`, details, this.providerId);
|
|
348
|
+
}
|
|
349
|
+
if (statusCode === 401 || statusCode === 403) {
|
|
350
|
+
return new TTSError(TTSErrorCode.AUTHENTICATION_ERROR, `AWS Polly authentication failed: ${message}`, details, this.providerId);
|
|
351
|
+
}
|
|
352
|
+
return new TTSError(TTSErrorCode.PROVIDER_ERROR, `AWS Polly error: ${message}`, details, this.providerId);
|
|
353
|
+
}
|
|
313
354
|
/**
|
|
314
355
|
* Clean up AWS Polly client
|
|
315
356
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-players/tts-server-polly",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.68",
|
|
4
4
|
"description": "AWS Polly provider for server-side TTS with speech marks support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@aws-sdk/client-polly": "^3.1033.0",
|
|
42
|
-
"@pie-players/tts-server-core": "0.3.
|
|
42
|
+
"@pie-players/tts-server-core": "0.3.68"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"typescript": "^5.9.3",
|