@pie-players/tts-client-server 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.
@@ -5,6 +5,7 @@
5
5
  * providers like AWS Polly, Google Cloud TTS, etc.
6
6
  * Returns audio with precise word-level timing (speech marks).
7
7
  */
8
+ import { normalizeSpeechMarks, resolveSpeedRateBucket, } from "@pie-players/tts-server-core";
8
9
  /**
9
10
  * Parse a TTS asset URL (speech marks or audio). Rejects anything that is
10
11
  * not an absolute http(s) URL; relative URLs are resolved against
@@ -139,61 +140,12 @@ const resolveValidationMode = (config, mode) => {
139
140
  return config.endpointValidationMode;
140
141
  return mode === "custom" ? "none" : "voices";
141
142
  };
142
- const speedRateFromRate = (rate) => {
143
- if (!Number.isFinite(rate))
144
- return "medium";
145
- if (rate < 1)
146
- return "slow";
147
- if (rate > 1)
148
- return "fast";
149
- return "medium";
150
- };
151
143
  const resolveSpeedRate = (config) => {
152
144
  const providerOptions = (config.providerOptions || {});
153
145
  if (typeof providerOptions.speedRate === "string") {
154
146
  return providerOptions.speedRate;
155
147
  }
156
- const rate = Number(config.rate ?? 1);
157
- return speedRateFromRate(rate);
158
- };
159
- const parseJSONLSpeechMarks = (raw) => {
160
- const marks = [];
161
- let fallbackIndex = 0;
162
- const lines = raw
163
- .split("\n")
164
- .map((line) => line.trim())
165
- .filter(Boolean);
166
- for (const line of lines) {
167
- try {
168
- const parsed = JSON.parse(line);
169
- const type = typeof parsed.type === "string" ? parsed.type : "word";
170
- const time = typeof parsed.time === "number" && Number.isFinite(parsed.time)
171
- ? parsed.time
172
- : 0;
173
- const value = typeof parsed.value === "string" ? parsed.value : "";
174
- const explicitStart = typeof parsed.start === "number" && Number.isFinite(parsed.start)
175
- ? parsed.start
176
- : null;
177
- const explicitEnd = typeof parsed.end === "number" && Number.isFinite(parsed.end)
178
- ? parsed.end
179
- : null;
180
- const start = explicitStart ?? fallbackIndex;
181
- const computedEnd = explicitEnd ??
182
- start + Math.max(1, value.length || String(parsed.value || "").length);
183
- fallbackIndex = Math.max(computedEnd + 1, fallbackIndex);
184
- marks.push({
185
- time,
186
- type,
187
- start,
188
- end: computedEnd,
189
- value,
190
- });
191
- }
192
- catch {
193
- // Ignore malformed lines and keep parsing valid marks.
194
- }
195
- }
196
- return marks;
148
+ return resolveSpeedRateBucket(config.rate);
197
149
  };
198
150
  const parseInlineSpeechMarks = (input) => {
199
151
  if (!Array.isArray(input))
@@ -266,7 +218,7 @@ const pieAdapter = {
266
218
  includeSpeechMarks: true,
267
219
  };
268
220
  },
269
- parseResponse: async (response) => {
221
+ parseResponse: async (response, _config, _headers, _signal, _text) => {
270
222
  const data = await response.json();
271
223
  return {
272
224
  audio: {
@@ -298,7 +250,7 @@ const customAdapter = {
298
250
  cache,
299
251
  };
300
252
  },
301
- parseResponse: async (response, config, headers, signal) => {
253
+ parseResponse: async (response, config, headers, signal, text) => {
302
254
  const data = await response.json();
303
255
  const marksHeaders = {};
304
256
  if (config.includeAuthOnAssetFetch) {
@@ -329,7 +281,7 @@ const customAdapter = {
329
281
  });
330
282
  if (marksResponse.ok) {
331
283
  const marksRaw = await marksResponse.text();
332
- speechMarks = parseJSONLSpeechMarks(marksRaw);
284
+ speechMarks = normalizeSpeechMarks(marksRaw, text);
333
285
  }
334
286
  }
335
287
  }
@@ -534,7 +486,7 @@ class ServerTTSProviderImpl {
534
486
  });
535
487
  throw new Error(errorMessage);
536
488
  }
537
- const normalized = await this.adapter.parseResponse(response, this.config, headers, signal);
489
+ const normalized = await this.adapter.parseResponse(response, this.config, headers, signal, text);
538
490
  if (runId !== this.synthesisRunId || signal.aborted) {
539
491
  throw new Error("Synthesis superseded by a newer request");
540
492
  }
@@ -754,7 +706,7 @@ class ServerTTSProviderImpl {
754
706
  this.config.rate = settings.rate;
755
707
  this.config.providerOptions = {
756
708
  ...(this.config.providerOptions || {}),
757
- speedRate: speedRateFromRate(Number(settings.rate)),
709
+ speedRate: resolveSpeedRateBucket(settings.rate),
758
710
  };
759
711
  }
760
712
  if (settings.pitch !== undefined) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pie-players/tts-client-server",
3
- "version": "0.3.66",
3
+ "version": "0.3.68",
4
4
  "description": "Client-side TTS provider that calls server API for synthesis",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -38,7 +38,8 @@
38
38
  "access": "public"
39
39
  },
40
40
  "dependencies": {
41
- "@pie-players/pie-tts": "0.3.66"
41
+ "@pie-players/pie-tts": "0.3.68",
42
+ "@pie-players/tts-server-core": "0.3.68"
42
43
  },
43
44
  "devDependencies": {
44
45
  "typescript": "^5.9.3",