@pie-players/tts-server-google 0.3.66 → 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.
@@ -119,10 +119,6 @@ export declare class GoogleCloudTTSProvider extends BaseTTSProvider {
119
119
  * Extract words from existing SSML (simplified version for v1)
120
120
  */
121
121
  private extractWordsFromSSML;
122
- /**
123
- * Escape special XML characters for SSML
124
- */
125
- private escapeSSML;
126
122
  /**
127
123
  * Extract speech marks from Google's timepoints
128
124
  */
@@ -130,7 +126,6 @@ export declare class GoogleCloudTTSProvider extends BaseTTSProvider {
130
126
  /**
131
127
  * Detect if text contains SSML markup
132
128
  */
133
- private detectSSML;
134
129
  /**
135
130
  * Get available voices from Google Cloud TTS
136
131
  */
@@ -164,11 +164,10 @@ export class GoogleCloudTTSProvider extends BaseTTSProvider {
164
164
  * Synthesize audio stream only (no speech marks)
165
165
  */
166
166
  async synthesizeAudio(request, voice) {
167
- // Detect if text contains SSML tags
168
- const isSsml = this.detectSSML(request.text);
169
- if (isSsml && this.enableLogging) {
167
+ if (this.detectSSML(request.text) && this.enableLogging) {
170
168
  console.log("[GoogleCloudTTS] Detected SSML content");
171
169
  }
170
+ const { text, isSsml } = this.applyProsody(request.text, request);
172
171
  // Parse voice name to extract language code
173
172
  const languageCode = voice.split("-").slice(0, 2).join("-"); // e.g., "en-US" from "en-US-Wavenet-A"
174
173
  // Map our audio encoding to Google's enum
@@ -178,7 +177,7 @@ export class GoogleCloudTTSProvider extends BaseTTSProvider {
178
177
  OGG_OPUS: "OGG_OPUS",
179
178
  };
180
179
  const [response] = await this.client.synthesizeSpeech({
181
- input: isSsml ? { ssml: request.text } : { text: request.text },
180
+ input: isSsml ? { ssml: text } : { text },
182
181
  voice: {
183
182
  languageCode,
184
183
  name: voice,
@@ -210,10 +209,12 @@ export class GoogleCloudTTSProvider extends BaseTTSProvider {
210
209
  // Check if the text is already SSML
211
210
  const isUserSSML = this.detectSSML(request.text);
212
211
  // If user provided SSML, we need to inject marks within the existing SSML
213
- // For simplicity in v1, we'll inject marks for plain text only
212
+ // For simplicity in v1, we'll inject marks for plain text only. Already-SSML
213
+ // input skips prosody wrapping too: injecting <prosody> into markup the
214
+ // caller authored themselves would require parsing it.
214
215
  const { ssml, wordMap } = isUserSSML
215
216
  ? this.extractWordsFromSSML(request.text)
216
- : this.injectSSMLMarks(request.text);
217
+ : this.injectSSMLMarks(request.text, this.buildProsodyAttrs(request));
217
218
  if (this.enableLogging) {
218
219
  console.log(`[GoogleCloudTTS] Injected ${wordMap.length} SSML marks`);
219
220
  }
@@ -266,7 +267,7 @@ export class GoogleCloudTTSProvider extends BaseTTSProvider {
266
267
  /**
267
268
  * Inject SSML marks before each word in plain text
268
269
  */
269
- injectSSMLMarks(text) {
270
+ injectSSMLMarks(text, prosodyAttrs = "") {
270
271
  const words = [];
271
272
  const wordRegex = /\b[\w']+\b/g;
272
273
  let match;
@@ -279,7 +280,7 @@ export class GoogleCloudTTSProvider extends BaseTTSProvider {
279
280
  words.push({ word, start, end, markName });
280
281
  }
281
282
  // Build SSML with marks
282
- let ssml = "<speak>";
283
+ let ssml = prosodyAttrs ? `<speak><prosody ${prosodyAttrs}>` : "<speak>";
283
284
  let lastEnd = 0;
284
285
  for (const { word, start, end, markName } of words) {
285
286
  // Add text before word (including whitespace and punctuation)
@@ -289,7 +290,10 @@ export class GoogleCloudTTSProvider extends BaseTTSProvider {
289
290
  lastEnd = end;
290
291
  }
291
292
  // Add remaining text
292
- ssml += this.escapeSSML(text.slice(lastEnd)) + "</speak>";
293
+ ssml +=
294
+ this.escapeSSML(text.slice(lastEnd)) +
295
+ (prosodyAttrs ? "</prosody>" : "") +
296
+ "</speak>";
293
297
  return { ssml, wordMap: words };
294
298
  }
295
299
  /**
@@ -304,17 +308,6 @@ export class GoogleCloudTTSProvider extends BaseTTSProvider {
304
308
  .trim();
305
309
  return this.injectSSMLMarks(plainText);
306
310
  }
307
- /**
308
- * Escape special XML characters for SSML
309
- */
310
- escapeSSML(text) {
311
- return text
312
- .replace(/&/g, "&amp;")
313
- .replace(/</g, "&lt;")
314
- .replace(/>/g, "&gt;")
315
- .replace(/"/g, "&quot;")
316
- .replace(/'/g, "&apos;");
317
- }
318
311
  /**
319
312
  * Extract speech marks from Google's timepoints
320
313
  */
@@ -344,15 +337,6 @@ export class GoogleCloudTTSProvider extends BaseTTSProvider {
344
337
  /**
345
338
  * Detect if text contains SSML markup
346
339
  */
347
- detectSSML(text) {
348
- return (text.includes("<speak") ||
349
- text.includes("<prosody") ||
350
- text.includes("<emphasis") ||
351
- text.includes("<break") ||
352
- text.includes("<phoneme") ||
353
- text.includes("<say-as") ||
354
- text.includes("<mark"));
355
- }
356
340
  /**
357
341
  * Get available voices from Google Cloud TTS
358
342
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pie-players/tts-server-google",
3
- "version": "0.3.66",
3
+ "version": "0.3.68",
4
4
  "description": "Google Cloud Text-to-Speech provider for server-side TTS with speech marks support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@google-cloud/text-to-speech": "^6.4.0",
43
- "@pie-players/tts-server-core": "0.3.66"
43
+ "@pie-players/tts-server-core": "0.3.68"
44
44
  },
45
45
  "devDependencies": {
46
46
  "typescript": "^5.9.3",