@pie-players/pie-tool-ruler 0.3.20 → 0.3.21

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.
@@ -19,18 +19,34 @@ var b = (t) => {
19
19
  const i = t.split(`
20
20
  `).map((o) => o.trim()).filter(Boolean);
21
21
  for (const o of i) try {
22
- const s = JSON.parse(o), d = typeof s.type == "string" ? s.type : "word", n = typeof s.time == "number" && Number.isFinite(s.time) ? s.time : 0, a = typeof s.value == "string" ? s.value : "", c = typeof s.start == "number" && Number.isFinite(s.start) ? s.start : null, y = typeof s.end == "number" && Number.isFinite(s.end) ? s.end : null, g = c ?? r, l = y ?? g + Math.max(1, a.length || String(s.value || "").length);
22
+ const s = JSON.parse(o), a = typeof s.type == "string" ? s.type : "word", d = typeof s.time == "number" && Number.isFinite(s.time) ? s.time : 0, n = typeof s.value == "string" ? s.value : "", c = typeof s.start == "number" && Number.isFinite(s.start) ? s.start : null, u = typeof s.end == "number" && Number.isFinite(s.end) ? s.end : null, y = c ?? r, l = u ?? y + Math.max(1, n.length || String(s.value || "").length);
23
23
  r = Math.max(l + 1, r), e.push({
24
- time: n,
25
- type: d,
26
- start: g,
24
+ time: d,
25
+ type: a,
26
+ start: y,
27
27
  end: l,
28
- value: a
28
+ value: n
29
29
  });
30
30
  } catch {
31
31
  }
32
32
  return e;
33
- }, M = {
33
+ }, M = (t) => {
34
+ if (!Array.isArray(t)) return [];
35
+ const e = [];
36
+ let r = 0;
37
+ for (const i of t) {
38
+ if (!i || typeof i != "object") continue;
39
+ const o = typeof i.type == "string" ? i.type : "word", s = typeof i.time == "number" && Number.isFinite(i.time) ? i.time : 0, a = typeof i.value == "string" ? i.value : "", d = typeof i.start == "number" && Number.isFinite(i.start) ? i.start : null, n = typeof i.end == "number" && Number.isFinite(i.end) ? i.end : null, c = d ?? r, u = n ?? c + Math.max(1, a.length || 1);
40
+ r = Math.max(r, u + 1), e.push({
41
+ time: s,
42
+ type: o,
43
+ start: c,
44
+ end: u,
45
+ value: a
46
+ });
47
+ }
48
+ return e.sort((i, o) => i.time !== o.time ? i.time - o.time : i.start !== o.start ? i.start - o.start : i.end - o.end);
49
+ }, E = {
34
50
  pie: {
35
51
  id: "pie",
36
52
  resolveSynthesisUrl: (t) => {
@@ -38,7 +54,7 @@ var b = (t) => {
38
54
  return e === "rootPost" ? r : `${r}/synthesize`;
39
55
  },
40
56
  buildRequestBody: (t, e) => {
41
- const r = e.providerOptions || {}, i = typeof e.engine == "string" ? e.engine : typeof r.engine == "string" ? r.engine : void 0, o = typeof r.sampleRate == "number" && Number.isFinite(r.sampleRate) ? r.sampleRate : void 0, s = r.format === "mp3" || r.format === "ogg" || r.format === "pcm" ? r.format : void 0, d = Array.isArray(r.speechMarkTypes) ? r.speechMarkTypes.filter((n) => n === "word" || n === "sentence" || n === "ssml") : void 0;
57
+ const r = e.providerOptions || {}, i = typeof e.engine == "string" ? e.engine : typeof r.engine == "string" ? r.engine : void 0, o = typeof r.sampleRate == "number" && Number.isFinite(r.sampleRate) ? r.sampleRate : void 0, s = r.format === "mp3" || r.format === "ogg" || r.format === "pcm" ? r.format : void 0, a = Array.isArray(r.speechMarkTypes) ? r.speechMarkTypes.filter((d) => d === "word" || d === "sentence" || d === "ssml") : void 0;
42
58
  return {
43
59
  text: t,
44
60
  provider: e.provider || "polly",
@@ -48,7 +64,7 @@ var b = (t) => {
48
64
  engine: i,
49
65
  sampleRate: o,
50
66
  format: s,
51
- speechMarkTypes: d,
67
+ speechMarkTypes: a,
52
68
  includeSpeechMarks: !0
53
69
  };
54
70
  },
@@ -82,25 +98,27 @@ var b = (t) => {
82
98
  parseResponse: async (t, e, r, i) => {
83
99
  const o = await t.json(), s = {};
84
100
  if (e.includeAuthOnAssetFetch)
85
- for (const [n, a] of Object.entries(r)) n.toLowerCase() === "authorization" && (s[n] = a);
86
- let d = [];
87
- if (typeof o.word == "string" && o.word.length > 0) {
101
+ for (const [n, c] of Object.entries(r)) n.toLowerCase() === "authorization" && (s[n] = c);
102
+ let a = [];
103
+ const d = M(o.speechMarks);
104
+ if (d.length > 0) a = d;
105
+ else if (typeof o.word == "string" && o.word.length > 0) {
88
106
  const n = await fetch(o.word, {
89
107
  headers: s,
90
108
  signal: i
91
109
  });
92
- n.ok && (d = I(await n.text()));
110
+ n.ok && (a = I(await n.text()));
93
111
  }
94
112
  return {
95
113
  audio: {
96
114
  kind: "url",
97
115
  url: o.audioContent
98
116
  },
99
- speechMarks: d
117
+ speechMarks: a
100
118
  };
101
119
  }
102
120
  }
103
- }, E = class {
121
+ }, P = class {
104
122
  constructor(t, e) {
105
123
  h(this, "config", void 0), h(this, "adapter", void 0), h(this, "currentAudio", null), h(this, "pausedState", !1), h(this, "wordTimings", []), h(this, "highlightInterval", null), h(this, "intentionallyStopped", !1), h(this, "activeSynthesisController", null), h(this, "synthesisRunId", 0), h(this, "telemetryReporter", void 0), h(this, "onWordBoundary", void 0), this.config = t, this.adapter = e, this.telemetryReporter = b(t);
106
124
  }
@@ -121,20 +139,20 @@ var b = (t) => {
121
139
  return;
122
140
  }
123
141
  const s = this.config.rate || 1;
124
- return this.wordTimings = o.map((d) => ({
125
- ...d,
126
- time: d.time / s
127
- })), new Promise((d, n) => {
128
- const a = new Audio(i);
129
- this.currentAudio = a, this.config.rate && (a.playbackRate = Math.max(0.25, Math.min(4, this.config.rate))), this.config.volume !== void 0 && (a.volume = Math.max(0, Math.min(1, this.config.volume))), a.onplay = () => {
142
+ return this.wordTimings = o.map((a) => ({
143
+ ...a,
144
+ time: a.time / s
145
+ })), new Promise((a, d) => {
146
+ const n = new Audio(i);
147
+ this.currentAudio = n, this.config.rate && (n.playbackRate = Math.max(0.25, Math.min(4, this.config.rate))), this.config.volume !== void 0 && (n.volume = Math.max(0, Math.min(1, this.config.volume))), n.onplay = () => {
130
148
  this.pausedState = !1, this.onWordBoundary && this.wordTimings.length > 0 && this.startWordHighlighting();
131
- }, a.onended = () => {
132
- this.stopWordHighlighting(), URL.revokeObjectURL(i), this.currentAudio = null, this.wordTimings = [], d();
133
- }, a.onerror = (c) => {
134
- this.stopWordHighlighting(), URL.revokeObjectURL(i), this.currentAudio = null, this.wordTimings = [], this.intentionallyStopped ? d() : n(/* @__PURE__ */ new Error("Failed to play audio from server"));
135
- }, a.onpause = () => {
149
+ }, n.onended = () => {
150
+ this.stopWordHighlighting(), URL.revokeObjectURL(i), this.currentAudio = null, this.wordTimings = [], a();
151
+ }, n.onerror = (c) => {
152
+ this.stopWordHighlighting(), URL.revokeObjectURL(i), this.currentAudio = null, this.wordTimings = [], this.intentionallyStopped ? a() : d(/* @__PURE__ */ new Error("Failed to play audio from server"));
153
+ }, n.onpause = () => {
136
154
  this.stopWordHighlighting(), this.pausedState = !0;
137
- }, a.play().catch(n);
155
+ }, n.play().catch(d);
138
156
  });
139
157
  }
140
158
  async synthesizeSpeech(t, e, r) {
@@ -149,12 +167,12 @@ var b = (t) => {
149
167
  ...this.config.headers
150
168
  };
151
169
  this.config.authToken && (o.Authorization = `Bearer ${this.config.authToken}`);
152
- const s = this.adapter.resolveSynthesisUrl(this.config), d = this.adapter.buildRequestBody(t, this.config), n = await (async () => {
170
+ const s = this.adapter.resolveSynthesisUrl(this.config), a = this.adapter.buildRequestBody(t, this.config), d = await (async () => {
153
171
  try {
154
172
  return await fetch(s, {
155
173
  method: "POST",
156
174
  headers: o,
157
- body: JSON.stringify(d),
175
+ body: JSON.stringify(a),
158
176
  signal: e
159
177
  });
160
178
  } catch (l) {
@@ -168,24 +186,24 @@ var b = (t) => {
168
186
  }), l;
169
187
  }
170
188
  })();
171
- if (!n.ok) {
172
- const l = await n.json().catch(() => ({})), u = l.message || l.error?.message || `Server returned ${n.status}`;
189
+ if (!d.ok) {
190
+ const l = await d.json().catch(() => ({})), p = l.message || l.error?.message || `Server returned ${d.status}`;
173
191
  throw await this.emitTelemetry("pie-tool-backend-call-error", {
174
192
  toolId: "tts",
175
193
  backend: this.config.provider || "server",
176
194
  operation: "synthesize-speech",
177
195
  duration: Date.now() - i,
178
- statusCode: n.status,
196
+ statusCode: d.status,
179
197
  errorType: "TTSBackendRequestError",
180
- message: u
181
- }), new Error(u);
198
+ message: p
199
+ }), new Error(p);
182
200
  }
183
- const a = await this.adapter.parseResponse(n, this.config, o, e);
201
+ const n = await this.adapter.parseResponse(d, this.config, o, e);
184
202
  if (r !== this.synthesisRunId || e.aborted) throw new Error("Synthesis superseded by a newer request");
185
203
  let c;
186
- if (a.audio.kind === "base64") c = this.base64ToBlob(a.audio.data, a.audio.contentType);
204
+ if (n.audio.kind === "base64") c = this.base64ToBlob(n.audio.data, n.audio.contentType);
187
205
  else {
188
- const l = a.audio.url, u = Date.now();
206
+ const l = n.audio.url, p = Date.now();
189
207
  await this.emitTelemetry("pie-tool-backend-call-start", {
190
208
  toolId: "tts",
191
209
  backend: this.config.provider || "server",
@@ -193,49 +211,49 @@ var b = (t) => {
193
211
  });
194
212
  const f = {};
195
213
  this.config.includeAuthOnAssetFetch && this.config.authToken && (f.Authorization = `Bearer ${this.config.authToken}`);
196
- const p = await (async () => {
214
+ const m = await (async () => {
197
215
  try {
198
216
  return await fetch(l, {
199
217
  headers: f,
200
218
  signal: e
201
219
  });
202
- } catch (m) {
220
+ } catch (g) {
203
221
  throw await this.emitTelemetry("pie-tool-backend-call-error", {
204
222
  toolId: "tts",
205
223
  backend: this.config.provider || "server",
206
224
  operation: "fetch-synthesized-audio-asset",
207
- duration: Date.now() - u,
225
+ duration: Date.now() - p,
208
226
  errorType: "TTSAssetNetworkError",
209
- message: m instanceof Error ? m.message : String(m)
210
- }), m;
227
+ message: g instanceof Error ? g.message : String(g)
228
+ }), g;
211
229
  }
212
230
  })();
213
- if (!p.ok)
231
+ if (!m.ok)
214
232
  throw await this.emitTelemetry("pie-tool-backend-call-error", {
215
233
  toolId: "tts",
216
234
  backend: this.config.provider || "server",
217
235
  operation: "fetch-synthesized-audio-asset",
218
- duration: Date.now() - u,
219
- statusCode: p.status,
236
+ duration: Date.now() - p,
237
+ statusCode: m.status,
220
238
  errorType: "TTSAssetFetchError",
221
- message: `Failed to download synthesized audio (${p.status})`
222
- }), new Error(`Failed to download synthesized audio (${p.status})`);
223
- c = await p.blob(), await this.emitTelemetry("pie-tool-backend-call-success", {
239
+ message: `Failed to download synthesized audio (${m.status})`
240
+ }), new Error(`Failed to download synthesized audio (${m.status})`);
241
+ c = await m.blob(), await this.emitTelemetry("pie-tool-backend-call-success", {
224
242
  toolId: "tts",
225
243
  backend: this.config.provider || "server",
226
244
  operation: "fetch-synthesized-audio-asset",
227
- duration: Date.now() - u
245
+ duration: Date.now() - p
228
246
  });
229
247
  }
230
- const y = URL.createObjectURL(c), g = this.parseSpeechMarks(a.speechMarks);
248
+ const u = URL.createObjectURL(c), y = this.parseSpeechMarks(n.speechMarks);
231
249
  return await this.emitTelemetry("pie-tool-backend-call-success", {
232
250
  toolId: "tts",
233
251
  backend: this.config.provider || "server",
234
252
  operation: "synthesize-speech",
235
253
  duration: Date.now() - i
236
254
  }), {
237
- audioUrl: y,
238
- wordTimings: g
255
+ audioUrl: u,
256
+ wordTimings: y
239
257
  };
240
258
  }
241
259
  base64ToBlob(t, e) {
@@ -298,7 +316,7 @@ var b = (t) => {
298
316
  updateSettings(t) {
299
317
  t.rate !== void 0 && (this.config.rate = t.rate, this.currentAudio && (this.currentAudio.playbackRate = Math.max(0.25, Math.min(4, t.rate)))), t.pitch !== void 0 && (this.config.pitch = t.pitch), t.voice !== void 0 && (this.config.voice = t.voice);
300
318
  }
301
- }, C = class {
319
+ }, B = class {
302
320
  constructor() {
303
321
  h(this, "providerId", "server-tts"), h(this, "providerName", "Server TTS"), h(this, "version", "1.0.0"), h(this, "config", null), h(this, "adapter", null), h(this, "telemetryReporter", void 0);
304
322
  }
@@ -312,7 +330,7 @@ var b = (t) => {
312
330
  async initialize(t) {
313
331
  const e = t;
314
332
  if (!e.apiEndpoint) throw new Error("apiEndpoint is required for ServerTTSProvider");
315
- if (this.config = e, this.telemetryReporter = b(e), this.adapter = M[T(e)], e.validateEndpoint) {
333
+ if (this.config = e, this.telemetryReporter = b(e), this.adapter = E[T(e)], e.validateEndpoint) {
316
334
  const r = Date.now();
317
335
  if (await this.emitTelemetry("pie-tool-backend-call-start", {
318
336
  toolId: "tts",
@@ -334,7 +352,7 @@ var b = (t) => {
334
352
  duration: Date.now() - r
335
353
  });
336
354
  }
337
- return new E(e, this.adapter);
355
+ return new P(e, this.adapter);
338
356
  }
339
357
  async testAPIAvailability() {
340
358
  if (!this.config || !this.adapter) return !1;
@@ -346,12 +364,12 @@ var b = (t) => {
346
364
  return clearTimeout(r), !0;
347
365
  const o = i === "voices" ? k(this.config) : this.adapter.resolveSynthesisUrl(this.config), s = i === "voices" ? "GET" : "OPTIONS";
348
366
  try {
349
- const d = await fetch(o, {
367
+ const a = await fetch(o, {
350
368
  method: s,
351
369
  headers: t,
352
370
  signal: e.signal
353
371
  });
354
- return clearTimeout(r), d.ok || d.status === 405;
372
+ return clearTimeout(r), a.ok || a.status === 405;
355
373
  } catch {
356
374
  return clearTimeout(r), !1;
357
375
  }
@@ -389,5 +407,5 @@ var b = (t) => {
389
407
  }
390
408
  };
391
409
  export {
392
- C as ServerTTSProvider
410
+ B as ServerTTSProvider
393
411
  };