retiam 2.0.1 → 2.0.3
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/THIRD_PARTY_NOTICES.md +3 -3
- package/agent/AGENTS.md +70 -0
- package/agent/CLAUDE.md +2 -0
- package/agent/skill/SKILL.md +114 -0
- package/agent/skill/examples/AreaLesson.ts +48 -0
- package/agent/skill/examples/ExplainMotion.ts +32 -0
- package/agent/skill/examples/NarratedMotion.ts +50 -0
- package/agent/skill/examples/SecantToTangent.ts +142 -0
- package/agent/skill/references/api.md +111 -0
- package/agent/skill/references/explainers.md +123 -0
- package/agent/skill/references/quality.md +151 -0
- package/agent/skill/references/styles.md +58 -0
- package/agent/skill/references/tts.md +166 -0
- package/agent/templates/explainer/lesson.json +25 -0
- package/agent/templates/explainer/review.json +6 -0
- package/agent/templates/explainer/styles.json +92 -0
- package/bin/agent-kit.js +26 -0
- package/bin/cli.js +24 -4
- package/bin/context.js +57 -0
- package/bin/init.js +71 -12
- package/bin/lesson-project.js +30 -0
- package/bin/lesson.js +195 -0
- package/bin/lint.js +6 -6
- package/bin/snapshot-runtime.js +185 -0
- package/bin/snapshot.js +32 -225
- package/dist/THIRD_PARTY_NOTICES.md +3 -3
- package/dist/UTIF-D6vx2UEX.min.js +1 -0
- package/dist/{UTIF-2Ear_0Uo.js → UTIF-mkffT70R.js} +1 -1
- package/dist/decompress-D7LzbvPD.min.js +15 -0
- package/dist/{index-B2sJBy4c.js → index-CdBPrYbr.js} +3830 -3795
- package/dist/index-jgFyrc2D.min.js +10472 -0
- package/dist/libs/explainer/example.d.ts +3 -0
- package/dist/libs/explainer/index.d.ts +5 -0
- package/dist/libs/explainer/index.js +135 -0
- package/dist/libs/explainer/plan.d.ts +12 -0
- package/dist/libs/explainer/plan.js +219 -0
- package/dist/libs/explainer/runtime.d.ts +24 -0
- package/dist/libs/explainer/styles.d.ts +3 -0
- package/dist/libs/explainer/types.d.ts +124 -0
- package/dist/libs/explainer/visuals.d.ts +18 -0
- package/dist/libs/tts/animations/Speak.d.ts +13 -7
- package/dist/libs/tts/components/TTSNarrationComponent.d.ts +9 -7
- package/dist/libs/tts/core/TTSCache.d.ts +3 -3
- package/dist/libs/tts/core/TTSClient.d.ts +3 -3
- package/dist/libs/tts/core/types.d.ts +48 -6
- package/dist/libs/tts/index.d.ts +2 -1
- package/dist/libs/tts/index.js +203 -1333
- package/dist/libs/tts/node/index.d.ts +10 -0
- package/dist/libs/tts/node/index.js +791 -0
- package/dist/libs/tts/providers/ElevenLabsTTSProvider.d.ts +30 -0
- package/dist/libs/tts/providers/ITTSProvider.d.ts +2 -2
- package/dist/libs/vite/index.d.ts +28 -0
- package/dist/libs/vite/index.js +158 -0
- package/dist/main-Cc4QQbSK.min.js +5939 -0
- package/dist/{main-D_G4uIju.js → main-DMu_5Qy7.js} +1 -1
- package/dist/msEdgeV2-D3w4Xsn-.js +642 -0
- package/dist/opentype.module-B-1cYAb-.min.js +1 -0
- package/dist/retiam.es.js +1 -1
- package/dist/retiam.es.min.js +1 -0
- package/dist/src/engine/animation/Animation.d.ts +1 -0
- package/dist/src/engine/entities/composites/text/mathjaxInterop.d.ts +6 -0
- package/package.json +15 -8
- package/readme.md +27 -7
package/dist/libs/tts/index.js
CHANGED
|
@@ -1,1170 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TTS as p } from "./node/index.js";
|
|
2
|
+
import { ElevenLabsTTSProvider as W, MsEdgeTTSProvider as A, TTSAudio as D, TTSCache as L, TTSClient as H, encodeWAV as P } from "./node/index.js";
|
|
3
|
+
import { D as I, M as N, f as Y, a as X, g as Z, b as q, p as G, s as U } from "../../msEdgeV2-D3w4Xsn-.js";
|
|
4
|
+
import { Component as x, Color as d, hex as a, VGroup as b, SDFText as m, CENTER as S, Rect as g, Animation as C } from "retiam";
|
|
2
5
|
/*! Retiam: noncommercial use only unless separately licensed. See ../../LICENSE and ../../COMMERCIAL_LICENSE.md. Third-party notices: ../../THIRD_PARTY_NOTICES.md and ../../THIRD_PARTY_LICENSES.txt. */
|
|
3
|
-
|
|
4
|
-
const s = e * 2, n = a.length * 2, l = new ArrayBuffer(44 + n), o = new DataView(l);
|
|
5
|
-
D(o, 0, "RIFF"), o.setUint32(4, 36 + n, !0), D(o, 8, "WAVE"), D(o, 12, "fmt "), o.setUint32(16, 16, !0), o.setUint16(20, 1, !0), o.setUint16(22, 1, !0), o.setUint32(24, e, !0), o.setUint32(28, s, !0), o.setUint16(32, 2, !0), o.setUint16(34, 16, !0), D(o, 36, "data"), o.setUint32(40, n, !0);
|
|
6
|
-
let u = 44;
|
|
7
|
-
for (let d = 0; d < a.length; d++) {
|
|
8
|
-
const c = Math.max(-1, Math.min(1, a[d])), f = c < 0 ? c * 32768 : c * 32767;
|
|
9
|
-
o.setInt16(u, f, !0), u += 2;
|
|
10
|
-
}
|
|
11
|
-
return l;
|
|
12
|
-
}
|
|
13
|
-
function D(a, e, t) {
|
|
14
|
-
for (let i = 0; i < t.length; i++)
|
|
15
|
-
a.setUint8(e + i, t.charCodeAt(i));
|
|
16
|
-
}
|
|
17
|
-
class G {
|
|
18
|
-
text;
|
|
19
|
-
phonemes;
|
|
20
|
-
samples;
|
|
21
|
-
sampleRate;
|
|
22
|
-
duration;
|
|
23
|
-
durationMs;
|
|
24
|
-
voice;
|
|
25
|
-
speed;
|
|
26
|
-
wordBoundaries;
|
|
27
|
-
rawBuffer;
|
|
28
|
-
mimeType;
|
|
29
|
-
_wavBuffer = null;
|
|
30
|
-
_blob = null;
|
|
31
|
-
_objectUrl = null;
|
|
32
|
-
_dataUrl = null;
|
|
33
|
-
constructor(e) {
|
|
34
|
-
this.text = e.text, this.phonemes = e.phonemes || "", this.samples = e.samples ?? new Float32Array(0), this.sampleRate = e.sampleRate ?? 24e3, this.voice = e.voice ?? "af_heart", this.speed = e.speed ?? 1, this.wordBoundaries = e.wordBoundaries, this.rawBuffer = e.rawBuffer, this.mimeType = e.mimeType || (e.rawBuffer ? "audio/mpeg" : "audio/wav"), e.durationMs !== void 0 ? (this.durationMs = e.durationMs, this.duration = e.duration ?? e.durationMs / 1e3) : e.duration !== void 0 ? (this.duration = e.duration, this.durationMs = e.duration * 1e3) : (this.duration = this.samples.length > 0 ? this.samples.length / this.sampleRate : 0, this.durationMs = this.duration * 1e3);
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Converts raw PCM samples or decodes underlying rawBuffer into a Web Audio [[AudioBuffer]].
|
|
38
|
-
*/
|
|
39
|
-
async getOrDecodeAudioBuffer(e) {
|
|
40
|
-
if (this.samples && this.samples.length > 0)
|
|
41
|
-
return this.toAudioBuffer(e);
|
|
42
|
-
if (this.rawBuffer)
|
|
43
|
-
try {
|
|
44
|
-
const t = await e.decodeAudioData(this.rawBuffer.slice(0));
|
|
45
|
-
return this.samples = t.getChannelData(0), this.sampleRate = t.sampleRate, t;
|
|
46
|
-
} catch (t) {
|
|
47
|
-
console.warn("[TTSAudio] Failed to decode rawBuffer via context.decodeAudioData:", t);
|
|
48
|
-
}
|
|
49
|
-
return this.toAudioBuffer(e);
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Converts raw PCM samples to a Web Audio [[AudioBuffer]].
|
|
53
|
-
*/
|
|
54
|
-
toAudioBuffer(e) {
|
|
55
|
-
const t = e || (typeof window < "u" ? window.__retiam_audio_context : null);
|
|
56
|
-
if (t) {
|
|
57
|
-
const r = t.createBuffer(1, Math.max(1, this.samples.length), this.sampleRate);
|
|
58
|
-
return r.getChannelData(0).set(this.samples), r;
|
|
59
|
-
}
|
|
60
|
-
const i = typeof window < "u" ? window.AudioContext || window.webkitAudioContext : null;
|
|
61
|
-
if (i) {
|
|
62
|
-
const s = new i().createBuffer(1, Math.max(1, this.samples.length), this.sampleRate);
|
|
63
|
-
return s.getChannelData(0).set(this.samples), s;
|
|
64
|
-
}
|
|
65
|
-
throw new Error("[TTSAudio] Cannot create AudioBuffer: No AudioContext available in this environment.");
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Returns an ArrayBuffer containing encoded 16-bit PCM WAV audio.
|
|
69
|
-
*/
|
|
70
|
-
toWav() {
|
|
71
|
-
return this._wavBuffer || (this.rawBuffer && this.mimeType.includes("wav") ? this._wavBuffer = this.rawBuffer : this._wavBuffer = oe(this.samples, this.sampleRate)), this._wavBuffer;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Returns a standard WAV or MP3 [[Blob]].
|
|
75
|
-
*/
|
|
76
|
-
toBlob() {
|
|
77
|
-
return this._blob || (this.rawBuffer ? this._blob = new Blob([this.rawBuffer], { type: this.mimeType }) : this._blob = new Blob([this.toWav()], { type: "audio/wav" })), this._blob;
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Generates a base64 Data URL ("data:audio/...;base64,...").
|
|
81
|
-
*/
|
|
82
|
-
toDataUrl() {
|
|
83
|
-
if (!this._dataUrl) {
|
|
84
|
-
const e = this.rawBuffer ? new Uint8Array(this.rawBuffer) : new Uint8Array(this.toWav());
|
|
85
|
-
let t = "";
|
|
86
|
-
const i = e.byteLength;
|
|
87
|
-
for (let s = 0; s < i; s++)
|
|
88
|
-
t += String.fromCharCode(e[s]);
|
|
89
|
-
const r = typeof btoa < "u" ? btoa(t) : Buffer.from(t, "binary").toString("base64");
|
|
90
|
-
this._dataUrl = `data:${this.mimeType};base64,${r}`;
|
|
91
|
-
}
|
|
92
|
-
return this._dataUrl;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Creates or returns a cached Object URL ("blob:...") for this audio.
|
|
96
|
-
*/
|
|
97
|
-
toObjectUrl() {
|
|
98
|
-
if (!this._objectUrl)
|
|
99
|
-
if (typeof URL < "u" && typeof URL.createObjectURL == "function")
|
|
100
|
-
this._objectUrl = URL.createObjectURL(this.toBlob());
|
|
101
|
-
else
|
|
102
|
-
return this.toDataUrl();
|
|
103
|
-
return this._objectUrl;
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Revokes any generated Object URL to release memory.
|
|
107
|
-
*/
|
|
108
|
-
revokeObjectUrl() {
|
|
109
|
-
this._objectUrl && typeof URL < "u" && typeof URL.revokeObjectURL == "function" && (URL.revokeObjectURL(this._objectUrl), this._objectUrl = null);
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Triggers a browser download or writes out the audio file.
|
|
113
|
-
*/
|
|
114
|
-
save(e) {
|
|
115
|
-
const t = this.mimeType.includes("mpeg") || this.mimeType.includes("mp3") ? ".mp3" : ".wav", i = `speech${t}`, r = e ? e.includes(".") ? e : `${e}${t}` : i;
|
|
116
|
-
if (typeof document < "u") {
|
|
117
|
-
const s = this.toObjectUrl(), n = document.createElement("a");
|
|
118
|
-
n.style.display = "none", n.href = s, n.download = r, document.body.appendChild(n), n.click(), setTimeout(() => {
|
|
119
|
-
document.body.removeChild(n);
|
|
120
|
-
}, 100);
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
try {
|
|
124
|
-
const s = globalThis.require ? globalThis.require("fs") : null;
|
|
125
|
-
if (s) {
|
|
126
|
-
const n = this.rawBuffer ? Buffer.from(this.rawBuffer) : Buffer.from(this.toWav());
|
|
127
|
-
s.writeFileSync(r, n);
|
|
128
|
-
}
|
|
129
|
-
} catch (s) {
|
|
130
|
-
console.warn(`[TTSAudio] Unable to save file ${r}:`, s);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Plays the audio through Retiam's [[AudioManager]] on the dedicated voiceover bus
|
|
135
|
-
* with automatic BGM ducking and timeline synchronization.
|
|
136
|
-
*/
|
|
137
|
-
async play(e, t = {}) {
|
|
138
|
-
let i;
|
|
139
|
-
return e && (typeof e.playVoiceover == "function" ? i = e : e.audio && typeof e.audio.playVoiceover == "function" && (i = e.audio)), i ? i.playVoiceover(this, t) : (console.warn("[TTSAudio] No active AudioManager provided to play(). Creating standalone audio playback."), this._playStandalone(t));
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Standalone playback fallback if no Retiam scene/AudioManager is provided.
|
|
143
|
-
*/
|
|
144
|
-
_playStandalone(e) {
|
|
145
|
-
return new Promise((t) => {
|
|
146
|
-
if (typeof Audio > "u") {
|
|
147
|
-
t(this.durationMs);
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
const i = new Audio(this.toObjectUrl());
|
|
151
|
-
i.volume = Math.max(0, Math.min(1, e.volume ?? 1)), i.onended = () => {
|
|
152
|
-
const r = e.padEndMs ?? 100;
|
|
153
|
-
setTimeout(() => t(this.durationMs + r), r);
|
|
154
|
-
}, i.onerror = () => {
|
|
155
|
-
t(this.durationMs);
|
|
156
|
-
}, i.play().catch(() => {
|
|
157
|
-
t(this.durationMs);
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
const le = {
|
|
163
|
-
1: [44100, 48e3, 32e3],
|
|
164
|
-
2: [22050, 24e3, 16e3],
|
|
165
|
-
"2.5": [11025, 12e3, 8e3]
|
|
166
|
-
}, de = {
|
|
167
|
-
V1L3: [0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320],
|
|
168
|
-
V2L3: [0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160]
|
|
169
|
-
};
|
|
170
|
-
function H(a) {
|
|
171
|
-
const e = a instanceof Uint8Array ? a : new Uint8Array(a), t = e.length;
|
|
172
|
-
let i = 0, r = 0, s = 0, n = 24e3, l = 96, o = 1;
|
|
173
|
-
for (t >= 10 && e[0] === 73 && e[1] === 68 && e[2] === 51 && (i = 10 + ((e[6] & 127) << 21 | (e[7] & 127) << 14 | (e[8] & 127) << 7 | e[9] & 127)); i < t - 4; ) {
|
|
174
|
-
if (e[i] === 255 && (e[i + 1] & 224) === 224) {
|
|
175
|
-
const d = e[i + 1], c = e[i + 2], f = e[i + 3], h = d >> 3 & 3, p = h === 3 ? "1" : h === 2 ? "2" : h === 0 ? "2.5" : null, b = d >> 1 & 3, m = c >> 4 & 15, _ = c >> 2 & 3, A = c >> 1 & 1, U = f >> 6 & 3;
|
|
176
|
-
if (p && b === 1 && _ < 3 && m > 0 && m < 15) {
|
|
177
|
-
const x = le[p][_], F = de[p === "1" ? "V1L3" : "V2L3"][m], z = F * 1e3, R = p === "1" ? 1152 : 576, ee = Math.floor(R * (z / 8) / x) + A;
|
|
178
|
-
n = x, l = F, o = U === 3 ? 1 : 2, s += R, r++, i += ee;
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
i++;
|
|
183
|
-
}
|
|
184
|
-
if (r === 0 || n === 0) {
|
|
185
|
-
const d = Math.max(0.1, t / 12e3);
|
|
186
|
-
return {
|
|
187
|
-
sampleRate: 24e3,
|
|
188
|
-
frameCount: 1,
|
|
189
|
-
totalSamples: Math.floor(d * 24e3),
|
|
190
|
-
durationSec: d,
|
|
191
|
-
durationMs: d * 1e3,
|
|
192
|
-
bitrateKbps: 96,
|
|
193
|
-
channels: 1
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
const u = s / n;
|
|
197
|
-
return {
|
|
198
|
-
sampleRate: n,
|
|
199
|
-
frameCount: r,
|
|
200
|
-
totalSamples: s,
|
|
201
|
-
durationSec: u,
|
|
202
|
-
durationMs: u * 1e3,
|
|
203
|
-
bitrateKbps: l,
|
|
204
|
-
channels: o
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
const K = {
|
|
208
|
-
// --- American English (US) ---
|
|
209
|
-
"en-US-JennyNeural": {
|
|
210
|
-
id: "en-US-JennyNeural",
|
|
211
|
-
name: "Jenny",
|
|
212
|
-
language: "en-us",
|
|
213
|
-
gender: "Female",
|
|
214
|
-
traits: "Warm, Conversational, Natural, Clear",
|
|
215
|
-
targetQuality: "A+",
|
|
216
|
-
overallGrade: "A+",
|
|
217
|
-
provider: "msedge"
|
|
218
|
-
},
|
|
219
|
-
"en-US-GuyNeural": {
|
|
220
|
-
id: "en-US-GuyNeural",
|
|
221
|
-
name: "Guy",
|
|
222
|
-
language: "en-us",
|
|
223
|
-
gender: "Male",
|
|
224
|
-
traits: "Confident, Broadcast, Documentary, Instructional",
|
|
225
|
-
targetQuality: "A+",
|
|
226
|
-
overallGrade: "A+",
|
|
227
|
-
provider: "msedge"
|
|
228
|
-
},
|
|
229
|
-
"en-US-AriaNeural": {
|
|
230
|
-
id: "en-US-AriaNeural",
|
|
231
|
-
name: "Aria",
|
|
232
|
-
language: "en-us",
|
|
233
|
-
gender: "Female",
|
|
234
|
-
traits: "Dynamic, Highly Expressive, Conversational",
|
|
235
|
-
targetQuality: "A+",
|
|
236
|
-
overallGrade: "A",
|
|
237
|
-
provider: "msedge"
|
|
238
|
-
},
|
|
239
|
-
"en-US-AndrewNeural": {
|
|
240
|
-
id: "en-US-AndrewNeural",
|
|
241
|
-
name: "Andrew",
|
|
242
|
-
language: "en-us",
|
|
243
|
-
gender: "Male",
|
|
244
|
-
traits: "Warm, Confident, Authentic, Honest",
|
|
245
|
-
targetQuality: "A+",
|
|
246
|
-
overallGrade: "A+",
|
|
247
|
-
provider: "msedge"
|
|
248
|
-
},
|
|
249
|
-
"en-US-AvaNeural": {
|
|
250
|
-
id: "en-US-AvaNeural",
|
|
251
|
-
name: "Ava",
|
|
252
|
-
language: "en-us",
|
|
253
|
-
gender: "Female",
|
|
254
|
-
traits: "Expressive, Natural, Pleasant",
|
|
255
|
-
targetQuality: "A+",
|
|
256
|
-
overallGrade: "A+",
|
|
257
|
-
provider: "msedge"
|
|
258
|
-
},
|
|
259
|
-
"en-US-EmmaNeural": {
|
|
260
|
-
id: "en-US-EmmaNeural",
|
|
261
|
-
name: "Emma",
|
|
262
|
-
language: "en-us",
|
|
263
|
-
gender: "Female",
|
|
264
|
-
traits: "Clear, Friendly, Conversational",
|
|
265
|
-
targetQuality: "A",
|
|
266
|
-
overallGrade: "A",
|
|
267
|
-
provider: "msedge"
|
|
268
|
-
},
|
|
269
|
-
"en-US-BrianNeural": {
|
|
270
|
-
id: "en-US-BrianNeural",
|
|
271
|
-
name: "Brian",
|
|
272
|
-
language: "en-us",
|
|
273
|
-
gender: "Male",
|
|
274
|
-
traits: "Approachable, Articulate, Natural",
|
|
275
|
-
targetQuality: "A",
|
|
276
|
-
overallGrade: "A",
|
|
277
|
-
provider: "msedge"
|
|
278
|
-
},
|
|
279
|
-
"en-US-ChristopherNeural": {
|
|
280
|
-
id: "en-US-ChristopherNeural",
|
|
281
|
-
name: "Christopher",
|
|
282
|
-
language: "en-us",
|
|
283
|
-
gender: "Male",
|
|
284
|
-
traits: "Deep, Authoritative, Cinematic",
|
|
285
|
-
targetQuality: "A",
|
|
286
|
-
overallGrade: "A",
|
|
287
|
-
provider: "msedge"
|
|
288
|
-
},
|
|
289
|
-
"en-US-EricNeural": {
|
|
290
|
-
id: "en-US-EricNeural",
|
|
291
|
-
name: "Eric",
|
|
292
|
-
language: "en-us",
|
|
293
|
-
gender: "Male",
|
|
294
|
-
traits: "Friendly, Casual, Natural",
|
|
295
|
-
targetQuality: "A-",
|
|
296
|
-
overallGrade: "A-",
|
|
297
|
-
provider: "msedge"
|
|
298
|
-
},
|
|
299
|
-
"en-US-MichelleNeural": {
|
|
300
|
-
id: "en-US-MichelleNeural",
|
|
301
|
-
name: "Michelle",
|
|
302
|
-
language: "en-us",
|
|
303
|
-
gender: "Female",
|
|
304
|
-
traits: "Professional, Engaging, Clear",
|
|
305
|
-
targetQuality: "A-",
|
|
306
|
-
overallGrade: "A-",
|
|
307
|
-
provider: "msedge"
|
|
308
|
-
},
|
|
309
|
-
"en-US-AnaNeural": {
|
|
310
|
-
id: "en-US-AnaNeural",
|
|
311
|
-
name: "Ana",
|
|
312
|
-
language: "en-us",
|
|
313
|
-
gender: "Female",
|
|
314
|
-
traits: "Childlike, Cheerful, Animated",
|
|
315
|
-
targetQuality: "B+",
|
|
316
|
-
overallGrade: "B+",
|
|
317
|
-
provider: "msedge"
|
|
318
|
-
},
|
|
319
|
-
"en-US-SteffanNeural": {
|
|
320
|
-
id: "en-US-SteffanNeural",
|
|
321
|
-
name: "Steffan",
|
|
322
|
-
language: "en-us",
|
|
323
|
-
gender: "Male",
|
|
324
|
-
traits: "Warm, Calming, Soft",
|
|
325
|
-
targetQuality: "A-",
|
|
326
|
-
overallGrade: "A-",
|
|
327
|
-
provider: "msedge"
|
|
328
|
-
},
|
|
329
|
-
// --- British English (UK) ---
|
|
330
|
-
"en-GB-SoniaNeural": {
|
|
331
|
-
id: "en-GB-SoniaNeural",
|
|
332
|
-
name: "Sonia",
|
|
333
|
-
language: "en-gb",
|
|
334
|
-
gender: "Female",
|
|
335
|
-
traits: "RP British, Polished, Professional, Clear",
|
|
336
|
-
targetQuality: "A+",
|
|
337
|
-
overallGrade: "A+",
|
|
338
|
-
provider: "msedge"
|
|
339
|
-
},
|
|
340
|
-
"en-GB-RyanNeural": {
|
|
341
|
-
id: "en-GB-RyanNeural",
|
|
342
|
-
name: "Ryan",
|
|
343
|
-
language: "en-gb",
|
|
344
|
-
gender: "Male",
|
|
345
|
-
traits: "Modern British, Natural, Confident",
|
|
346
|
-
targetQuality: "A",
|
|
347
|
-
overallGrade: "A",
|
|
348
|
-
provider: "msedge"
|
|
349
|
-
},
|
|
350
|
-
"en-GB-LibbyNeural": {
|
|
351
|
-
id: "en-GB-LibbyNeural",
|
|
352
|
-
name: "Libby",
|
|
353
|
-
language: "en-gb",
|
|
354
|
-
gender: "Female",
|
|
355
|
-
traits: "Storyteller, Warm British, Engaging",
|
|
356
|
-
targetQuality: "A-",
|
|
357
|
-
overallGrade: "A-",
|
|
358
|
-
provider: "msedge"
|
|
359
|
-
},
|
|
360
|
-
"en-GB-ThomasNeural": {
|
|
361
|
-
id: "en-GB-ThomasNeural",
|
|
362
|
-
name: "Thomas",
|
|
363
|
-
language: "en-gb",
|
|
364
|
-
gender: "Male",
|
|
365
|
-
traits: "Refined RP British, Documentary, Calm",
|
|
366
|
-
targetQuality: "A",
|
|
367
|
-
overallGrade: "A",
|
|
368
|
-
provider: "msedge"
|
|
369
|
-
},
|
|
370
|
-
// --- Australian & Canadian English ---
|
|
371
|
-
"en-AU-NatashaNeural": {
|
|
372
|
-
id: "en-AU-NatashaNeural",
|
|
373
|
-
name: "Natasha",
|
|
374
|
-
language: "en-au",
|
|
375
|
-
gender: "Female",
|
|
376
|
-
traits: "Australian, Friendly, Energetic",
|
|
377
|
-
targetQuality: "A",
|
|
378
|
-
overallGrade: "A",
|
|
379
|
-
provider: "msedge"
|
|
380
|
-
},
|
|
381
|
-
"en-AU-WilliamMultilingualNeural": {
|
|
382
|
-
id: "en-AU-WilliamMultilingualNeural",
|
|
383
|
-
name: "William",
|
|
384
|
-
language: "en-au",
|
|
385
|
-
gender: "Male",
|
|
386
|
-
traits: "Australian Multilingual, Articulate",
|
|
387
|
-
targetQuality: "A-",
|
|
388
|
-
overallGrade: "A-",
|
|
389
|
-
provider: "msedge"
|
|
390
|
-
},
|
|
391
|
-
"en-CA-ClaraNeural": {
|
|
392
|
-
id: "en-CA-ClaraNeural",
|
|
393
|
-
name: "Clara",
|
|
394
|
-
language: "en-ca",
|
|
395
|
-
gender: "Female",
|
|
396
|
-
traits: "Canadian, Clear, Crisp",
|
|
397
|
-
targetQuality: "A-",
|
|
398
|
-
overallGrade: "A-",
|
|
399
|
-
provider: "msedge"
|
|
400
|
-
},
|
|
401
|
-
"en-CA-LiamNeural": {
|
|
402
|
-
id: "en-CA-LiamNeural",
|
|
403
|
-
name: "Liam",
|
|
404
|
-
language: "en-ca",
|
|
405
|
-
gender: "Male",
|
|
406
|
-
traits: "Canadian, Natural, Conversational",
|
|
407
|
-
targetQuality: "A-",
|
|
408
|
-
overallGrade: "A-",
|
|
409
|
-
provider: "msedge"
|
|
410
|
-
},
|
|
411
|
-
// --- Indian English ---
|
|
412
|
-
"en-IN-NeerjaNeural": {
|
|
413
|
-
id: "en-IN-NeerjaNeural",
|
|
414
|
-
name: "Neerja",
|
|
415
|
-
language: "en-in",
|
|
416
|
-
gender: "Female",
|
|
417
|
-
traits: "Indian English, Professional, High Clarity",
|
|
418
|
-
targetQuality: "A",
|
|
419
|
-
overallGrade: "A",
|
|
420
|
-
provider: "msedge"
|
|
421
|
-
},
|
|
422
|
-
"en-IN-PrabhatNeural": {
|
|
423
|
-
id: "en-IN-PrabhatNeural",
|
|
424
|
-
name: "Prabhat",
|
|
425
|
-
language: "en-in",
|
|
426
|
-
gender: "Male",
|
|
427
|
-
traits: "Indian English, Confident, Instructional",
|
|
428
|
-
targetQuality: "A",
|
|
429
|
-
overallGrade: "A",
|
|
430
|
-
provider: "msedge"
|
|
431
|
-
},
|
|
432
|
-
// --- Global Languages ---
|
|
433
|
-
"es-ES-ElviraNeural": {
|
|
434
|
-
id: "es-ES-ElviraNeural",
|
|
435
|
-
name: "Elvira",
|
|
436
|
-
language: "es-es",
|
|
437
|
-
gender: "Female",
|
|
438
|
-
traits: "Spanish (Spain), Natural, Clear",
|
|
439
|
-
targetQuality: "A",
|
|
440
|
-
overallGrade: "A",
|
|
441
|
-
provider: "msedge"
|
|
442
|
-
},
|
|
443
|
-
"fr-FR-DeniseNeural": {
|
|
444
|
-
id: "fr-FR-DeniseNeural",
|
|
445
|
-
name: "Denise",
|
|
446
|
-
language: "fr-fr",
|
|
447
|
-
gender: "Female",
|
|
448
|
-
traits: "French (France), Refined, Elegant",
|
|
449
|
-
targetQuality: "A",
|
|
450
|
-
overallGrade: "A",
|
|
451
|
-
provider: "msedge"
|
|
452
|
-
},
|
|
453
|
-
"fr-FR-HenriNeural": {
|
|
454
|
-
id: "fr-FR-HenriNeural",
|
|
455
|
-
name: "Henri",
|
|
456
|
-
language: "fr-fr",
|
|
457
|
-
gender: "Male",
|
|
458
|
-
traits: "French (France), Documentary, Authoritative",
|
|
459
|
-
targetQuality: "A",
|
|
460
|
-
overallGrade: "A",
|
|
461
|
-
provider: "msedge"
|
|
462
|
-
},
|
|
463
|
-
"de-DE-KatjaNeural": {
|
|
464
|
-
id: "de-DE-KatjaNeural",
|
|
465
|
-
name: "Katja",
|
|
466
|
-
language: "de-de",
|
|
467
|
-
gender: "Female",
|
|
468
|
-
traits: "German (Germany), Precise, Professional",
|
|
469
|
-
targetQuality: "A",
|
|
470
|
-
overallGrade: "A",
|
|
471
|
-
provider: "msedge"
|
|
472
|
-
},
|
|
473
|
-
"de-DE-KillianNeural": {
|
|
474
|
-
id: "de-DE-KillianNeural",
|
|
475
|
-
name: "Killian",
|
|
476
|
-
language: "de-de",
|
|
477
|
-
gender: "Male",
|
|
478
|
-
traits: "German (Germany), Clear, Calm",
|
|
479
|
-
targetQuality: "A",
|
|
480
|
-
overallGrade: "A",
|
|
481
|
-
provider: "msedge"
|
|
482
|
-
},
|
|
483
|
-
"it-IT-ElsaNeural": {
|
|
484
|
-
id: "it-IT-ElsaNeural",
|
|
485
|
-
name: "Elsa",
|
|
486
|
-
language: "it-it",
|
|
487
|
-
gender: "Female",
|
|
488
|
-
traits: "Italian, Melodic, Expressive",
|
|
489
|
-
targetQuality: "A",
|
|
490
|
-
overallGrade: "A",
|
|
491
|
-
provider: "msedge"
|
|
492
|
-
},
|
|
493
|
-
"ja-JP-NanamiNeural": {
|
|
494
|
-
id: "ja-JP-NanamiNeural",
|
|
495
|
-
name: "Nanami",
|
|
496
|
-
language: "ja-jp",
|
|
497
|
-
gender: "Female",
|
|
498
|
-
traits: "Japanese, Crisp, Anime/Modern",
|
|
499
|
-
targetQuality: "A+",
|
|
500
|
-
overallGrade: "A+",
|
|
501
|
-
provider: "msedge"
|
|
502
|
-
},
|
|
503
|
-
"ja-JP-KeitaNeural": {
|
|
504
|
-
id: "ja-JP-KeitaNeural",
|
|
505
|
-
name: "Keita",
|
|
506
|
-
language: "ja-jp",
|
|
507
|
-
gender: "Male",
|
|
508
|
-
traits: "Japanese, Natural, Instructional",
|
|
509
|
-
targetQuality: "A",
|
|
510
|
-
overallGrade: "A",
|
|
511
|
-
provider: "msedge"
|
|
512
|
-
},
|
|
513
|
-
"zh-CN-XiaoxiaoNeural": {
|
|
514
|
-
id: "zh-CN-XiaoxiaoNeural",
|
|
515
|
-
name: "Xiaoxiao",
|
|
516
|
-
language: "zh-cn",
|
|
517
|
-
gender: "Female",
|
|
518
|
-
traits: "Chinese Mandarin, Natural, Expressive, Smooth",
|
|
519
|
-
targetQuality: "A+",
|
|
520
|
-
overallGrade: "A+",
|
|
521
|
-
provider: "msedge"
|
|
522
|
-
},
|
|
523
|
-
"zh-CN-YunxiNeural": {
|
|
524
|
-
id: "zh-CN-YunxiNeural",
|
|
525
|
-
name: "Yunxi",
|
|
526
|
-
language: "zh-cn",
|
|
527
|
-
gender: "Male",
|
|
528
|
-
traits: "Chinese Mandarin, Energetic, Storytelling",
|
|
529
|
-
targetQuality: "A",
|
|
530
|
-
overallGrade: "A",
|
|
531
|
-
provider: "msedge"
|
|
532
|
-
}
|
|
533
|
-
}, L = "en-US-JennyNeural";
|
|
534
|
-
let B = null;
|
|
535
|
-
function W() {
|
|
536
|
-
return B && B.length > 0 ? B : Object.values(K);
|
|
537
|
-
}
|
|
538
|
-
function ce(a) {
|
|
539
|
-
const e = a.toLowerCase().trim();
|
|
540
|
-
return W().find(
|
|
541
|
-
(i) => i.id.toLowerCase() === e || i.name.toLowerCase() === e || i.id.toLowerCase().includes(e) || i.name.toLowerCase().includes(e)
|
|
542
|
-
);
|
|
543
|
-
}
|
|
544
|
-
function Te(a) {
|
|
545
|
-
const e = a.toLowerCase().replace(/_/g, "-");
|
|
546
|
-
return W().filter(
|
|
547
|
-
(t) => t.language.toLowerCase() === e || t.language.toLowerCase().startsWith(e)
|
|
548
|
-
);
|
|
549
|
-
}
|
|
550
|
-
function he(a) {
|
|
551
|
-
B = a;
|
|
552
|
-
}
|
|
553
|
-
async function ue() {
|
|
554
|
-
if (B)
|
|
555
|
-
return B;
|
|
556
|
-
const e = "https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list?trustedclienttoken=6A5AA1D4EAFF4E9FB37E23D68491D6F4";
|
|
557
|
-
try {
|
|
558
|
-
const t = await fetch(e);
|
|
559
|
-
if (!t.ok)
|
|
560
|
-
throw new Error(`HTTP ${t.status} ${t.statusText}`);
|
|
561
|
-
const i = await t.json();
|
|
562
|
-
if (Array.isArray(i)) {
|
|
563
|
-
const r = i.map((s) => ({
|
|
564
|
-
id: s.ShortName || s.Name,
|
|
565
|
-
name: (s.FriendlyName || s.ShortName || "").replace(/^Microsoft\s+/, "").replace(/\s+Online\s+\(Natural\)/, ""),
|
|
566
|
-
language: (s.Locale || "en-US").toLowerCase(),
|
|
567
|
-
gender: s.Gender === "Male" ? "Male" : "Female",
|
|
568
|
-
traits: s.VoiceTag?.VoicePersonalities ? s.VoiceTag.VoicePersonalities.join(", ") : void 0,
|
|
569
|
-
targetQuality: "A",
|
|
570
|
-
overallGrade: "A",
|
|
571
|
-
provider: "msedge"
|
|
572
|
-
}));
|
|
573
|
-
return B = r, r;
|
|
574
|
-
}
|
|
575
|
-
} catch (t) {
|
|
576
|
-
console.warn("[MsEdgeVoices] Unable to fetch remote voices list. Falling back to built-in curated catalog:", t);
|
|
577
|
-
}
|
|
578
|
-
return Object.values(K);
|
|
579
|
-
}
|
|
580
|
-
class T {
|
|
581
|
-
maxSize;
|
|
582
|
-
cache = /* @__PURE__ */ new Map();
|
|
583
|
-
constructor(e = 128) {
|
|
584
|
-
this.maxSize = Math.max(1, e);
|
|
585
|
-
}
|
|
586
|
-
static createKey(e, t, i) {
|
|
587
|
-
return `${t}:${i.toFixed(2)}:${e.trim().toLowerCase()}`;
|
|
588
|
-
}
|
|
589
|
-
get(e, t, i) {
|
|
590
|
-
const r = T.createKey(e, t, i), s = this.cache.get(r);
|
|
591
|
-
if (s)
|
|
592
|
-
return this.cache.delete(r), this.cache.set(r, s), s;
|
|
593
|
-
}
|
|
594
|
-
set(e, t, i, r) {
|
|
595
|
-
const s = T.createKey(e, t, i);
|
|
596
|
-
if (this.cache.has(s))
|
|
597
|
-
this.cache.delete(s);
|
|
598
|
-
else if (this.cache.size >= this.maxSize) {
|
|
599
|
-
const n = this.cache.keys().next().value;
|
|
600
|
-
n && (this.cache.get(n)?.revokeObjectUrl(), this.cache.delete(n));
|
|
601
|
-
}
|
|
602
|
-
this.cache.set(s, r);
|
|
603
|
-
}
|
|
604
|
-
has(e, t, i) {
|
|
605
|
-
return this.cache.has(T.createKey(e, t, i));
|
|
606
|
-
}
|
|
607
|
-
clear() {
|
|
608
|
-
for (const e of this.cache.values())
|
|
609
|
-
e.revokeObjectUrl();
|
|
610
|
-
this.cache.clear();
|
|
611
|
-
}
|
|
612
|
-
get size() {
|
|
613
|
-
return this.cache.size;
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
const J = "6A5AA1D4EAFF4E9FB37E23D68491D6F4", pe = "wss://speech.platform.bing.com/consumer/speech/synthesize/readaloud/edge/v1", fe = "2-155.0.4283.45", me = 11644473600, ge = [
|
|
617
|
-
1779033703,
|
|
618
|
-
3144134277,
|
|
619
|
-
1013904242,
|
|
620
|
-
2773480762,
|
|
621
|
-
1359893119,
|
|
622
|
-
2600822924,
|
|
623
|
-
528734635,
|
|
624
|
-
1541459225
|
|
625
|
-
], ye = [
|
|
626
|
-
4255104674,
|
|
627
|
-
2435071207,
|
|
628
|
-
3192492180,
|
|
629
|
-
3442351626,
|
|
630
|
-
1811967817,
|
|
631
|
-
79508907,
|
|
632
|
-
4272990180,
|
|
633
|
-
66059218
|
|
634
|
-
], _e = [
|
|
635
|
-
3945054110,
|
|
636
|
-
358115615,
|
|
637
|
-
2696978146,
|
|
638
|
-
217723578,
|
|
639
|
-
2787307148,
|
|
640
|
-
3520959633,
|
|
641
|
-
3235718560,
|
|
642
|
-
4192668342,
|
|
643
|
-
4039316851,
|
|
644
|
-
1884868174,
|
|
645
|
-
1904797190,
|
|
646
|
-
15051571,
|
|
647
|
-
3529027680,
|
|
648
|
-
1920361828
|
|
649
|
-
], I = [
|
|
650
|
-
1116352408,
|
|
651
|
-
1899447441,
|
|
652
|
-
3049323471,
|
|
653
|
-
3921009573,
|
|
654
|
-
961987163,
|
|
655
|
-
1508970993,
|
|
656
|
-
2453635748,
|
|
657
|
-
2870763221,
|
|
658
|
-
3624381080,
|
|
659
|
-
310598401,
|
|
660
|
-
607225278,
|
|
661
|
-
1426881987,
|
|
662
|
-
1925078388,
|
|
663
|
-
2162078206,
|
|
664
|
-
2614888103,
|
|
665
|
-
3248222580,
|
|
666
|
-
3835390401,
|
|
667
|
-
4022224774,
|
|
668
|
-
264347078,
|
|
669
|
-
604807628,
|
|
670
|
-
770255983,
|
|
671
|
-
1249150122,
|
|
672
|
-
1555081692,
|
|
673
|
-
1996064986,
|
|
674
|
-
2554220882,
|
|
675
|
-
2821834349,
|
|
676
|
-
2952996808,
|
|
677
|
-
3210313671,
|
|
678
|
-
3336571891,
|
|
679
|
-
3584528711,
|
|
680
|
-
113926993,
|
|
681
|
-
338241895,
|
|
682
|
-
666307205,
|
|
683
|
-
773529912,
|
|
684
|
-
1294757372,
|
|
685
|
-
1396182291,
|
|
686
|
-
1695183700,
|
|
687
|
-
1986661051,
|
|
688
|
-
2177026350,
|
|
689
|
-
2456956037,
|
|
690
|
-
2730485921,
|
|
691
|
-
2820302411,
|
|
692
|
-
3259730800,
|
|
693
|
-
3345764771,
|
|
694
|
-
3516065817,
|
|
695
|
-
3600352804,
|
|
696
|
-
4094571909,
|
|
697
|
-
275423344,
|
|
698
|
-
430227734,
|
|
699
|
-
506948616,
|
|
700
|
-
659060556,
|
|
701
|
-
883997877,
|
|
702
|
-
958139571,
|
|
703
|
-
1322822218,
|
|
704
|
-
1537002063,
|
|
705
|
-
1747873779,
|
|
706
|
-
1955562222,
|
|
707
|
-
2024104815,
|
|
708
|
-
2227730452,
|
|
709
|
-
2361852424,
|
|
710
|
-
2428436474,
|
|
711
|
-
2756734187,
|
|
712
|
-
3204031479,
|
|
713
|
-
3329325298
|
|
714
|
-
], X = [...I];
|
|
715
|
-
X[14] = 3386640039;
|
|
716
|
-
const Q = [
|
|
717
|
-
[3895366065, 3005677776],
|
|
718
|
-
[1155409094, 2296378653],
|
|
719
|
-
[1005282748, 693190712],
|
|
720
|
-
[3365689651, 3005795295],
|
|
721
|
-
[2367603217, 3557143765],
|
|
722
|
-
[827258325, 652566332],
|
|
723
|
-
[3911487921, 1618477510],
|
|
724
|
-
[4037392853, 2192753147],
|
|
725
|
-
[101076211, 4199654362],
|
|
726
|
-
[3665427040, 545047652],
|
|
727
|
-
[3201434976, 1010595059],
|
|
728
|
-
[2314848760, 3536931681],
|
|
729
|
-
[905590982, 3137643201],
|
|
730
|
-
[3410617286, 3311559015]
|
|
731
|
-
], S = (a) => a >>> 0, g = (...a) => S(a.reduce((e, t) => e + t, 0)), y = (a, e) => S(Math.imul(a, e)), v = (a) => S(a << 16 | a >>> 16), N = (a, e) => S(a >>> e | a << 32 - e), P = (a) => S(a >>> 7 ^ a << 25 ^ a >>> 18 ^ a << 14 ^ a >>> 3), V = (a) => S(a >>> 17 ^ a << 15 ^ a >>> 19 ^ a << 13 ^ a >>> 10), Se = (a, e, t) => S(t ^ a & (e ^ t)), be = (a, e, t) => S(a & e | t & (a | e)), we = (a) => S(N(a, 6) ^ N(a, 11) ^ N(a, 25)), ve = (a) => S(N(a, 2) ^ N(a, 13) ^ N(a, 22));
|
|
732
|
-
function Y(a, e, t) {
|
|
733
|
-
let [i, r, s, n, l, o, u, d] = a;
|
|
734
|
-
const c = t === 14 ? X : I;
|
|
735
|
-
for (let f = t; f < 64; f++) {
|
|
736
|
-
const h = g(d, we(l), Se(l, o, u), c[f], e[f]), p = g(ve(i), be(i, r, s));
|
|
737
|
-
[i, r, s, n, l, o, u, d] = [g(h, p), i, r, s, g(n, h), l, o, u];
|
|
738
|
-
}
|
|
739
|
-
return [i, r, s, n, l, o, u, d];
|
|
740
|
-
}
|
|
741
|
-
function q(a, e) {
|
|
742
|
-
for (let t = e; t < 64; t++)
|
|
743
|
-
a.push(g(
|
|
744
|
-
V(a[t - 2]),
|
|
745
|
-
a[t - 7],
|
|
746
|
-
P(a[t - 15]),
|
|
747
|
-
a[t - 16]
|
|
748
|
-
));
|
|
749
|
-
}
|
|
750
|
-
function Ae(a) {
|
|
751
|
-
const e = new Array(16).fill(0);
|
|
752
|
-
e[14] = S(a[0] << 16 | a[1] << 8 | a[2]), e[15] = S(a[3] << 24 | a[4] << 16 | a[5] << 8 | a[6]);
|
|
753
|
-
for (let i = 16; i < 30; i++) {
|
|
754
|
-
let r = _e[i - 16];
|
|
755
|
-
if (i - 2 >= 14) {
|
|
756
|
-
const s = V(e[i - 2]);
|
|
757
|
-
r = g(r, i === 16 ? S(s ^ 758464) : s);
|
|
758
|
-
}
|
|
759
|
-
if (i - 7 >= 14 && (r = g(r, e[i - 7])), i - 15 >= 14) {
|
|
760
|
-
const s = P(e[i - 15]);
|
|
761
|
-
r = g(r, i === 29 ? S(s ^ 94112640) : s);
|
|
762
|
-
}
|
|
763
|
-
e.push(r);
|
|
764
|
-
}
|
|
765
|
-
e.push(g(
|
|
766
|
-
V(e[28]),
|
|
767
|
-
e[23],
|
|
768
|
-
P(e[15]),
|
|
769
|
-
e[14],
|
|
770
|
-
3386640039,
|
|
771
|
-
-I[14]
|
|
772
|
-
)), q(e, 31);
|
|
773
|
-
const t = Y(ye, e, 14);
|
|
774
|
-
return ge.map((i, r) => g(i, t[r]));
|
|
775
|
-
}
|
|
776
|
-
function ke(a) {
|
|
777
|
-
const e = 57 + a.length, t = ((55 - e) % 64 + 64) % 64, i = new Uint8Array(a.length - 7 + 1 + t + 8);
|
|
778
|
-
i.set(a.subarray(7)), i[a.length - 7] = 128;
|
|
779
|
-
const r = e * 8, s = new DataView(i.buffer);
|
|
780
|
-
s.setUint32(i.length - 8, Math.floor(r / 4294967296), !1), s.setUint32(i.length - 4, S(r), !1);
|
|
781
|
-
let n = Ae(a.subarray(0, 7));
|
|
782
|
-
for (let u = 0; u < i.length; u += 64) {
|
|
783
|
-
const d = new DataView(i.buffer, i.byteOffset + u, 64), c = Array.from({ length: 16 }, (h, p) => d.getUint32(p * 4, !1));
|
|
784
|
-
q(c, 16);
|
|
785
|
-
const f = Y(n, c, 0);
|
|
786
|
-
n = n.map((h, p) => g(h, f[p]));
|
|
787
|
-
}
|
|
788
|
-
const l = new Uint8Array(32), o = new DataView(l.buffer);
|
|
789
|
-
return n.forEach((u, d) => o.setUint32(d * 4, u, !1)), l;
|
|
790
|
-
}
|
|
791
|
-
function Ce(a) {
|
|
792
|
-
const e = new Uint8Array(Math.ceil(a.length / 4) * 4);
|
|
793
|
-
e.set(a);
|
|
794
|
-
const t = new DataView(e.buffer), i = Array.from({ length: e.length / 4 }, (r, s) => t.getUint32(s * 4, !0));
|
|
795
|
-
return i.length % 2 !== 0 && i.push(0), i;
|
|
796
|
-
}
|
|
797
|
-
function xe(a, e) {
|
|
798
|
-
const t = new DataView(e.buffer, e.byteOffset, e.byteLength), i = S(t.getUint32(0, !0) | 1), r = S(t.getUint32(4, !0) | 1), s = [y(i, 2190031155), y(r, 2190031155)], n = Q.map(([h], p) => y(h, s[p % 2])), l = Q.map(([, h]) => h), o = new Uint8Array(a.length + 1);
|
|
799
|
-
o.set(a, 1), Ce(o).forEach((h, p) => {
|
|
800
|
-
let b = y(h, p % 2 === 0 ? i : r), m = y(v(h), p % 2 === 0 ? 4010109435 : 3273069531);
|
|
801
|
-
p === 0 && (b = g(b, y(4076407578, s[0])), m = g(m, 186253312)), n.push(b), l.push(m);
|
|
802
|
-
});
|
|
803
|
-
let u = 0, d = 0, c = 0, f = 0;
|
|
804
|
-
for (let h = 0; h < n.length; h += 2) {
|
|
805
|
-
const p = n[h], b = n[h + 1];
|
|
806
|
-
let m = v(g(l[h], p)), _ = y(m, 1995771700);
|
|
807
|
-
u = g(u, y(v(_), 3287280279), _), m = v(g(l[h + 1], b)), _ = y(m, 411160124), d = g(y(v(_), 901586633), _), u = g(u, d), c = g(y(c, i), p), c = y(v(c), 3482890513), c = y(v(c), 2265471903), c = y(v(c), 315537773), c = y(v(c), 629022083), f = g(f, c), m = g(y(c, r), b), m = y(v(m), 2725517045), m = y(v(m), 3548616447), c = y(v(y(v(m), 2090019721)), 3215236969), f = g(f, c);
|
|
808
|
-
}
|
|
809
|
-
return [S(d ^ c), S(u ^ f)];
|
|
810
|
-
}
|
|
811
|
-
function $(a) {
|
|
812
|
-
return Array.from(a, (e) => e.toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
813
|
-
}
|
|
814
|
-
function Ee(a = Date.now() / 1e3) {
|
|
815
|
-
let e = a + me;
|
|
816
|
-
e -= e % 300, e *= 1e7;
|
|
817
|
-
const t = new TextEncoder().encode(`${e.toFixed(0)}${J}`), i = ke(t), r = xe(t, i), s = new Uint8Array(8), n = new DataView(s.buffer);
|
|
818
|
-
return n.setUint32(0, r[0], !0), n.setUint32(4, r[1], !0), `${$(s)}-${$(i)}`;
|
|
819
|
-
}
|
|
820
|
-
function Be(a) {
|
|
821
|
-
const e = a;
|
|
822
|
-
e.__retiamV2Patched || (e.getSynthUrl = async () => {
|
|
823
|
-
const t = Array.from({ length: 32 }, () => Math.floor(Math.random() * 16).toString(16)).join(""), i = Ee();
|
|
824
|
-
return `${pe}?TrustedClientToken=${J}&Sec-MS-GEC=${i}&Sec-MS-GEC-Version=${fe}&ConnectionId=${t}`;
|
|
825
|
-
}, e.__retiamV2Patched = !0);
|
|
826
|
-
}
|
|
827
|
-
class Me {
|
|
828
|
-
name = "msedge-tts";
|
|
829
|
-
_config;
|
|
830
|
-
_cache;
|
|
831
|
-
_isBrowser;
|
|
832
|
-
_nodeClients = [];
|
|
833
|
-
constructor(e = {}) {
|
|
834
|
-
this._isBrowser = typeof window < "u" && typeof window.document < "u", this._config = {
|
|
835
|
-
cacheAudio: e.cacheAudio !== !1,
|
|
836
|
-
maxCacheSize: e.maxCacheSize ?? 128,
|
|
837
|
-
msedgeEndpoint: e.msedgeEndpoint || "/api/tts/msedge"
|
|
838
|
-
}, this._cache = new T(this._config.maxCacheSize);
|
|
839
|
-
}
|
|
840
|
-
/**
|
|
841
|
-
* Microsoft Edge TTS is cloud-hosted and always ready immediately without local weight loading.
|
|
842
|
-
*/
|
|
843
|
-
get isReady() {
|
|
844
|
-
return !0;
|
|
845
|
-
}
|
|
846
|
-
/**
|
|
847
|
-
* Initializes provider configuration. No weight downloading required.
|
|
848
|
-
*/
|
|
849
|
-
async init(e) {
|
|
850
|
-
e?.msedgeEndpoint && (this._config.msedgeEndpoint = e.msedgeEndpoint), e?.cacheAudio !== void 0 && (this._config.cacheAudio = e.cacheAudio);
|
|
851
|
-
}
|
|
852
|
-
/**
|
|
853
|
-
* Synthesizes text into high-fidelity speech audio using Microsoft Edge neural voices.
|
|
854
|
-
*/
|
|
855
|
-
async synthesize(e, t = {}) {
|
|
856
|
-
const i = e.trim(), r = t.voice || L, s = Math.max(0.25, Math.min(4, t.speed ?? 1));
|
|
857
|
-
if (!i)
|
|
858
|
-
return new G({
|
|
859
|
-
text: "",
|
|
860
|
-
samples: new Float32Array(0),
|
|
861
|
-
sampleRate: 24e3,
|
|
862
|
-
voice: r,
|
|
863
|
-
speed: s
|
|
864
|
-
});
|
|
865
|
-
if (this._config.cacheAudio) {
|
|
866
|
-
const l = this._cache.get(i, r, s);
|
|
867
|
-
if (l)
|
|
868
|
-
return l;
|
|
869
|
-
}
|
|
870
|
-
const n = this._isBrowser ? await this._synthesizeBrowser(i, r, s, t) : await this._synthesizeNode(i, r, s, t);
|
|
871
|
-
return this._config.cacheAudio && this._cache.set(i, r, s, n), n;
|
|
872
|
-
}
|
|
873
|
-
/**
|
|
874
|
-
* Node.js execution: directly calls the msedge-tts package in-process.
|
|
875
|
-
*/
|
|
876
|
-
async _synthesizeNode(e, t, i, r) {
|
|
877
|
-
const { MsEdgeTTS: s, OUTPUT_FORMAT: n } = await import("msedge-tts");
|
|
878
|
-
Be(s);
|
|
879
|
-
const l = new s(), o = Math.round((i - 1) * 100), u = o >= 0 ? `+${o}%` : `${o}%`;
|
|
880
|
-
await l.setMetadata(t, n.AUDIO_24KHZ_96KBITRATE_MONO_MP3, {
|
|
881
|
-
wordBoundaryEnabled: !0,
|
|
882
|
-
sentenceBoundaryEnabled: !0
|
|
883
|
-
});
|
|
884
|
-
const d = {
|
|
885
|
-
rate: u
|
|
886
|
-
};
|
|
887
|
-
if (r.pitch !== void 0 && (d.pitch = r.pitch), r.volume !== void 0 && r.volume !== null) {
|
|
888
|
-
if (typeof r.volume == "number")
|
|
889
|
-
d.volume = r.volume <= 1 && r.volume > 0 ? Math.round(r.volume * 100) : Math.round(r.volume);
|
|
890
|
-
else if (typeof r.volume == "string") {
|
|
891
|
-
const A = parseFloat(r.volume);
|
|
892
|
-
!isNaN(A) && !r.volume.includes("%") && !r.volume.startsWith("+") && !r.volume.startsWith("-") ? d.volume = A <= 1 && A > 0 ? Math.round(A * 100) : Math.round(A) : d.volume = r.volume;
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
const { audioStream: c, metadataStream: f } = l.toStream(e, d), h = [], p = [];
|
|
896
|
-
f && f.on("data", (A) => {
|
|
897
|
-
try {
|
|
898
|
-
const U = A.toString(), x = JSON.parse(U);
|
|
899
|
-
if (Array.isArray(x?.Metadata)) {
|
|
900
|
-
for (const M of x.Metadata)
|
|
901
|
-
if (M.Type === "WordBoundary" && M.Data) {
|
|
902
|
-
const F = (M.Data.Offset || 0) / 1e4, z = (M.Data.Duration || 0) / 1e4, R = M.Data.text?.Text || "";
|
|
903
|
-
p.push({
|
|
904
|
-
text: R,
|
|
905
|
-
offsetMs: F,
|
|
906
|
-
durationMs: z,
|
|
907
|
-
boundaryType: "WordBoundary"
|
|
908
|
-
});
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
} catch {
|
|
912
|
-
}
|
|
913
|
-
}), await new Promise((A, U) => {
|
|
914
|
-
c.on("data", (x) => {
|
|
915
|
-
h.push(x);
|
|
916
|
-
}), c.on("end", () => {
|
|
917
|
-
A();
|
|
918
|
-
}), c.on("error", (x) => {
|
|
919
|
-
U(x);
|
|
920
|
-
});
|
|
921
|
-
});
|
|
922
|
-
const b = Buffer.concat(h), m = b.buffer.slice(
|
|
923
|
-
b.byteOffset,
|
|
924
|
-
b.byteOffset + b.byteLength
|
|
925
|
-
), _ = H(new Uint8Array(m));
|
|
926
|
-
return new G({
|
|
927
|
-
text: e,
|
|
928
|
-
rawBuffer: m,
|
|
929
|
-
mimeType: "audio/mpeg",
|
|
930
|
-
samples: new Float32Array(_.totalSamples),
|
|
931
|
-
sampleRate: _.sampleRate,
|
|
932
|
-
duration: _.durationSec,
|
|
933
|
-
durationMs: _.durationMs,
|
|
934
|
-
voice: t,
|
|
935
|
-
speed: i,
|
|
936
|
-
wordBoundaries: p.length > 0 ? p : void 0
|
|
937
|
-
});
|
|
938
|
-
}
|
|
939
|
-
/**
|
|
940
|
-
* Browser execution: invokes the Vite development server proxy endpoint.
|
|
941
|
-
*/
|
|
942
|
-
async _synthesizeBrowser(e, t, i, r) {
|
|
943
|
-
const s = `${this._config.msedgeEndpoint}/synthesize`, n = await fetch(s, {
|
|
944
|
-
method: "POST",
|
|
945
|
-
headers: {
|
|
946
|
-
"Content-Type": "application/json"
|
|
947
|
-
},
|
|
948
|
-
body: JSON.stringify({
|
|
949
|
-
text: e,
|
|
950
|
-
voice: t,
|
|
951
|
-
speed: i,
|
|
952
|
-
pitch: r.pitch,
|
|
953
|
-
volume: r.volume
|
|
954
|
-
})
|
|
955
|
-
});
|
|
956
|
-
if (!n.ok)
|
|
957
|
-
throw new Error(`[MsEdgeTTSProvider] Synthesis failed: HTTP ${n.status} ${n.statusText}`);
|
|
958
|
-
const l = n.headers.get("X-Audio-Duration-Ms"), o = n.headers.get("X-Word-Boundaries");
|
|
959
|
-
let u;
|
|
960
|
-
if (o)
|
|
961
|
-
try {
|
|
962
|
-
u = JSON.parse(decodeURIComponent(o));
|
|
963
|
-
} catch {
|
|
964
|
-
}
|
|
965
|
-
const d = await n.arrayBuffer();
|
|
966
|
-
let c = new Float32Array(0), f = 24e3, h = l ? parseFloat(l) : 0;
|
|
967
|
-
const p = window.AudioContext || window.webkitAudioContext;
|
|
968
|
-
if (p) {
|
|
969
|
-
const b = !!window.__retiam_audio_context, m = window.__retiam_audio_context || new p();
|
|
970
|
-
try {
|
|
971
|
-
const _ = await m.decodeAudioData(d.slice(0));
|
|
972
|
-
c = _.getChannelData(0), f = _.sampleRate, h || (h = _.duration * 1e3);
|
|
973
|
-
} catch (_) {
|
|
974
|
-
console.warn("[MsEdgeTTSProvider] AudioContext decode deferred, using raw MP3 buffer:", _);
|
|
975
|
-
} finally {
|
|
976
|
-
!b && m && typeof m.close == "function" && m.close().catch(() => {
|
|
977
|
-
});
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
if (c.length === 0 || !h) {
|
|
981
|
-
const b = H(new Uint8Array(d));
|
|
982
|
-
f = b.sampleRate, h || (h = b.durationMs);
|
|
983
|
-
}
|
|
984
|
-
return new G({
|
|
985
|
-
text: e,
|
|
986
|
-
rawBuffer: d,
|
|
987
|
-
mimeType: "audio/mpeg",
|
|
988
|
-
samples: c,
|
|
989
|
-
sampleRate: f,
|
|
990
|
-
duration: h / 1e3,
|
|
991
|
-
durationMs: h,
|
|
992
|
-
voice: t,
|
|
993
|
-
speed: i,
|
|
994
|
-
wordBoundaries: u
|
|
995
|
-
});
|
|
996
|
-
}
|
|
997
|
-
/**
|
|
998
|
-
* Progressively streams synthesized speech sentence by sentence.
|
|
999
|
-
*/
|
|
1000
|
-
async *stream(e, t = {}) {
|
|
1001
|
-
const i = t.voice || L, r = Math.max(0.25, Math.min(4, t.speed ?? 1)), s = t.splitPattern || /([.!?;]+(?:\s+|$))/g, n = [], l = e.split(s);
|
|
1002
|
-
for (let d = 0; d < l.length; d += 2) {
|
|
1003
|
-
const c = (l[d] + (l[d + 1] || "")).trim();
|
|
1004
|
-
c.length > 0 && n.push(c);
|
|
1005
|
-
}
|
|
1006
|
-
n.length === 0 && n.push(e.trim());
|
|
1007
|
-
let o = 0, u = 0;
|
|
1008
|
-
for (const d of n) {
|
|
1009
|
-
const c = await this.synthesize(d, {
|
|
1010
|
-
...t,
|
|
1011
|
-
voice: i,
|
|
1012
|
-
speed: r
|
|
1013
|
-
});
|
|
1014
|
-
yield {
|
|
1015
|
-
text: d,
|
|
1016
|
-
phonemes: "",
|
|
1017
|
-
audio: c,
|
|
1018
|
-
chunkIndex: o++,
|
|
1019
|
-
startTimeMs: u
|
|
1020
|
-
}, u += c.durationMs;
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
/**
|
|
1024
|
-
* Returns curated Microsoft Edge neural voices immediately.
|
|
1025
|
-
*/
|
|
1026
|
-
getVoices() {
|
|
1027
|
-
return W();
|
|
1028
|
-
}
|
|
1029
|
-
/**
|
|
1030
|
-
* Fetches the complete live catalog of all 320+ Microsoft Edge neural voices.
|
|
1031
|
-
*/
|
|
1032
|
-
async fetchVoices() {
|
|
1033
|
-
if (this._isBrowser)
|
|
1034
|
-
try {
|
|
1035
|
-
const e = await fetch(`${this._config.msedgeEndpoint}/voices`);
|
|
1036
|
-
if (e.ok) {
|
|
1037
|
-
const t = await e.json();
|
|
1038
|
-
if (Array.isArray(t))
|
|
1039
|
-
return he(t), t;
|
|
1040
|
-
}
|
|
1041
|
-
} catch {
|
|
1042
|
-
}
|
|
1043
|
-
return ue();
|
|
1044
|
-
}
|
|
1045
|
-
/**
|
|
1046
|
-
* Clears cached utterances.
|
|
1047
|
-
*/
|
|
1048
|
-
clearCache() {
|
|
1049
|
-
this._cache.clear();
|
|
1050
|
-
}
|
|
1051
|
-
/**
|
|
1052
|
-
* Disposes resources and releases cache.
|
|
1053
|
-
*/
|
|
1054
|
-
async dispose() {
|
|
1055
|
-
this.clearCache();
|
|
1056
|
-
for (const e of this._nodeClients)
|
|
1057
|
-
try {
|
|
1058
|
-
e.close();
|
|
1059
|
-
} catch {
|
|
1060
|
-
}
|
|
1061
|
-
this._nodeClients = [];
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
class Z {
|
|
1065
|
-
_provider;
|
|
1066
|
-
_config;
|
|
1067
|
-
constructor(e = {}, t) {
|
|
1068
|
-
this._config = e, this._provider = t ?? new Me(e);
|
|
1069
|
-
}
|
|
1070
|
-
/** The active speech provider. */
|
|
1071
|
-
get provider() {
|
|
1072
|
-
return this._provider;
|
|
1073
|
-
}
|
|
1074
|
-
/** Whether the active provider is ready. */
|
|
1075
|
-
get isReady() {
|
|
1076
|
-
return this._provider.isReady;
|
|
1077
|
-
}
|
|
1078
|
-
/** Replaces the active provider instance. */
|
|
1079
|
-
setProvider(e) {
|
|
1080
|
-
this._provider = e;
|
|
1081
|
-
}
|
|
1082
|
-
/** Initializes the active provider. */
|
|
1083
|
-
async init(e) {
|
|
1084
|
-
e && (this._config = e), await this._provider.init(e ?? this._config);
|
|
1085
|
-
}
|
|
1086
|
-
/** Synthesizes text with the active provider. */
|
|
1087
|
-
async synthesize(e, t = {}) {
|
|
1088
|
-
return this._provider.synthesize(e, t);
|
|
1089
|
-
}
|
|
1090
|
-
/** Streams synthesized audio sentence by sentence. */
|
|
1091
|
-
async *stream(e, t = {}) {
|
|
1092
|
-
yield* this._provider.stream(e, t);
|
|
1093
|
-
}
|
|
1094
|
-
/** Synthesizes and plays speech through a Scene or AudioManager. */
|
|
1095
|
-
async speak(e, t, i = {}) {
|
|
1096
|
-
const r = await this.synthesize(t, i), s = await r.play(e, i);
|
|
1097
|
-
return { audio: r, durationMs: s };
|
|
1098
|
-
}
|
|
1099
|
-
/** Returns voices exposed by the active provider. */
|
|
1100
|
-
getVoices() {
|
|
1101
|
-
return this._provider.getVoices();
|
|
1102
|
-
}
|
|
1103
|
-
/** Finds a voice by ID, display name, or partial match. */
|
|
1104
|
-
findVoice(e) {
|
|
1105
|
-
const t = e.toLowerCase();
|
|
1106
|
-
return this._provider.getVoices().find(
|
|
1107
|
-
(i) => i.id.toLowerCase() === t || i.name.toLowerCase() === t || i.id.toLowerCase().includes(t) || i.name.toLowerCase().includes(t)
|
|
1108
|
-
) ?? ce(e);
|
|
1109
|
-
}
|
|
1110
|
-
/** Releases provider resources and cached audio. */
|
|
1111
|
-
async dispose() {
|
|
1112
|
-
await this._provider.dispose();
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
let O = null;
|
|
1116
|
-
function E() {
|
|
1117
|
-
return O || (O = new Z()), O;
|
|
1118
|
-
}
|
|
1119
|
-
class j {
|
|
1120
|
-
/** Replaces the global client configuration and restores the built-in provider. */
|
|
1121
|
-
static configure(e) {
|
|
1122
|
-
O = new Z(e);
|
|
1123
|
-
}
|
|
1124
|
-
/** Initializes the global speech provider. */
|
|
1125
|
-
static async init(e) {
|
|
1126
|
-
e && this.configure(e), await E().init(e);
|
|
1127
|
-
}
|
|
1128
|
-
/** Replaces the global provider instance. */
|
|
1129
|
-
static setProvider(e) {
|
|
1130
|
-
E().setProvider(e);
|
|
1131
|
-
}
|
|
1132
|
-
/** Active global provider. */
|
|
1133
|
-
static get provider() {
|
|
1134
|
-
return E().provider;
|
|
1135
|
-
}
|
|
1136
|
-
/** Synthesizes text to speech. */
|
|
1137
|
-
static async synthesize(e, t) {
|
|
1138
|
-
return E().synthesize(e, t);
|
|
1139
|
-
}
|
|
1140
|
-
/** Explicit alias for Microsoft Edge neural synthesis. */
|
|
1141
|
-
static async msedge(e, t) {
|
|
1142
|
-
return E().synthesize(e, t);
|
|
1143
|
-
}
|
|
1144
|
-
/** Streams synthesized speech sentence by sentence. */
|
|
1145
|
-
static async *stream(e, t) {
|
|
1146
|
-
yield* E().stream(e, t);
|
|
1147
|
-
}
|
|
1148
|
-
/** Synthesizes and plays speech through a Scene or AudioManager. */
|
|
1149
|
-
static async speak(e, t, i) {
|
|
1150
|
-
return E().speak(e, t, i);
|
|
1151
|
-
}
|
|
1152
|
-
/** Returns the active provider's voices. */
|
|
1153
|
-
static getVoices() {
|
|
1154
|
-
return E().getVoices();
|
|
1155
|
-
}
|
|
1156
|
-
/** Finds a Microsoft Edge neural voice. */
|
|
1157
|
-
static findVoice(e) {
|
|
1158
|
-
return E().findVoice(e);
|
|
1159
|
-
}
|
|
1160
|
-
/** Recommended default voice. */
|
|
1161
|
-
static DEFAULT_VOICE = L;
|
|
1162
|
-
/** Explicit provider-specific alias for the recommended default voice. */
|
|
1163
|
-
static DEFAULT_MSEDGE_VOICE = L;
|
|
1164
|
-
}
|
|
1165
|
-
class Fe extends te {
|
|
6
|
+
class F extends x {
|
|
1166
7
|
voice;
|
|
1167
8
|
speed;
|
|
9
|
+
elevenlabs;
|
|
1168
10
|
animateSpeaking;
|
|
1169
11
|
pulseAmplitude;
|
|
1170
12
|
pulseFrequency;
|
|
@@ -1174,13 +16,13 @@ class Fe extends te {
|
|
|
1174
16
|
_baseScaleX = 1;
|
|
1175
17
|
_baseScaleY = 1;
|
|
1176
18
|
_baseScaleZ = 1;
|
|
1177
|
-
constructor(
|
|
1178
|
-
super(), this.voice =
|
|
19
|
+
constructor(t = {}) {
|
|
20
|
+
super(), this.voice = t.voice, this.speed = t.speed, this.elevenlabs = t.elevenlabs, this.animateSpeaking = t.animateSpeaking !== !1, this.pulseAmplitude = t.pulseAmplitude ?? 0.05, this.pulseFrequency = t.pulseFrequency ?? 4, this.onSpeechStart = t.onSpeechStart, this.onSpeechEnd = t.onSpeechEnd;
|
|
1179
21
|
}
|
|
1180
22
|
onInit() {
|
|
1181
23
|
if (this.entity?.transform) {
|
|
1182
|
-
const
|
|
1183
|
-
this._baseScaleX =
|
|
24
|
+
const t = this.entity.transform.getScale();
|
|
25
|
+
this._baseScaleX = t.x, this._baseScaleY = t.y, this._baseScaleZ = t.z;
|
|
1184
26
|
}
|
|
1185
27
|
}
|
|
1186
28
|
/**
|
|
@@ -1196,23 +38,32 @@ class Fe extends te {
|
|
|
1196
38
|
* @param overrides Voice and playback option overrides.
|
|
1197
39
|
* @returns Synthesized [[TTSAudioResult]] and total speech duration in milliseconds.
|
|
1198
40
|
*/
|
|
1199
|
-
async speak(
|
|
1200
|
-
const
|
|
41
|
+
async speak(t, i = {}) {
|
|
42
|
+
const e = this.entity?.scene, s = i.voice ?? this.voice, c = i.speed ?? this.speed;
|
|
1201
43
|
if (this.entity?.transform) {
|
|
1202
|
-
const
|
|
1203
|
-
this._baseScaleX =
|
|
44
|
+
const h = this.entity.transform.getScale();
|
|
45
|
+
this._baseScaleX = h.x, this._baseScaleY = h.y, this._baseScaleZ = h.z;
|
|
1204
46
|
}
|
|
1205
|
-
const
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
47
|
+
const l = await p.synthesize(t, {
|
|
48
|
+
voice: s,
|
|
49
|
+
speed: c,
|
|
50
|
+
...i,
|
|
51
|
+
elevenlabs: {
|
|
52
|
+
...this.elevenlabs,
|
|
53
|
+
...i.elevenlabs,
|
|
54
|
+
voiceSettings: { ...this.elevenlabs?.voiceSettings, ...i.elevenlabs?.voiceSettings }
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
this._isSpeaking = !0, this.onSpeechStart?.(t, l);
|
|
58
|
+
const o = await l.play(e, i);
|
|
59
|
+
return this._isSpeaking = !1, this._restoreBaseScale(), this.onSpeechEnd?.(t), { audio: l, durationMs: o };
|
|
1209
60
|
}
|
|
1210
|
-
update(
|
|
61
|
+
update(t, i) {
|
|
1211
62
|
if (!(!this.enabled || !this.entity?.transform) && this._isSpeaking && this.animateSpeaking) {
|
|
1212
|
-
const
|
|
63
|
+
const e = t / 1e3 * this.pulseFrequency * Math.PI * 2, s = 1 + Math.sin(e) * this.pulseAmplitude;
|
|
1213
64
|
this.entity.transform.setScale([
|
|
1214
|
-
this._baseScaleX *
|
|
1215
|
-
this._baseScaleY *
|
|
65
|
+
this._baseScaleX * s,
|
|
66
|
+
this._baseScaleY * s,
|
|
1216
67
|
this._baseScaleZ
|
|
1217
68
|
]), this.entity.version++;
|
|
1218
69
|
}
|
|
@@ -1228,14 +79,14 @@ class Fe extends te {
|
|
|
1228
79
|
this._isSpeaking = !1, this._restoreBaseScale();
|
|
1229
80
|
}
|
|
1230
81
|
}
|
|
1231
|
-
const
|
|
82
|
+
const v = {
|
|
1232
83
|
obsidian: {
|
|
1233
84
|
fontSize: 0.38,
|
|
1234
|
-
textColor:
|
|
85
|
+
textColor: a("#F8FAFC"),
|
|
1235
86
|
textOpacity: 1,
|
|
1236
|
-
backdropColor:
|
|
87
|
+
backdropColor: a("#060913"),
|
|
1237
88
|
backdropOpacity: 0.85,
|
|
1238
|
-
strokeColor: new
|
|
89
|
+
strokeColor: new d(0.22, 0.74, 0.97, 0.35),
|
|
1239
90
|
strokeWidth: 0.02,
|
|
1240
91
|
cornerRadius: 0.22,
|
|
1241
92
|
pillShape: !1,
|
|
@@ -1246,11 +97,11 @@ const Ne = {
|
|
|
1246
97
|
},
|
|
1247
98
|
pill: {
|
|
1248
99
|
fontSize: 0.38,
|
|
1249
|
-
textColor:
|
|
100
|
+
textColor: a("#FFFFFF"),
|
|
1250
101
|
textOpacity: 1,
|
|
1251
|
-
backdropColor:
|
|
102
|
+
backdropColor: a("#080D1A"),
|
|
1252
103
|
backdropOpacity: 0.88,
|
|
1253
|
-
strokeColor: new
|
|
104
|
+
strokeColor: new d(0.38, 0.52, 0.75, 0.4),
|
|
1254
105
|
strokeWidth: 0.02,
|
|
1255
106
|
pillShape: !0,
|
|
1256
107
|
padding: [0.7, 0.28],
|
|
@@ -1260,11 +111,11 @@ const Ne = {
|
|
|
1260
111
|
},
|
|
1261
112
|
minimal: {
|
|
1262
113
|
fontSize: 0.38,
|
|
1263
|
-
textColor:
|
|
114
|
+
textColor: a("#F1F5F9"),
|
|
1264
115
|
textOpacity: 1,
|
|
1265
|
-
backdropColor:
|
|
116
|
+
backdropColor: a("#090D16"),
|
|
1266
117
|
backdropOpacity: 0.8,
|
|
1267
|
-
strokeColor:
|
|
118
|
+
strokeColor: d.NONE,
|
|
1268
119
|
strokeWidth: 0,
|
|
1269
120
|
cornerRadius: 0.16,
|
|
1270
121
|
pillShape: !1,
|
|
@@ -1275,11 +126,11 @@ const Ne = {
|
|
|
1275
126
|
},
|
|
1276
127
|
broadcast: {
|
|
1277
128
|
fontSize: 0.38,
|
|
1278
|
-
textColor:
|
|
129
|
+
textColor: a("#FFFFFF"),
|
|
1279
130
|
textOpacity: 1,
|
|
1280
|
-
backdropColor:
|
|
131
|
+
backdropColor: a("#000000"),
|
|
1281
132
|
backdropOpacity: 0.92,
|
|
1282
|
-
strokeColor:
|
|
133
|
+
strokeColor: d.NONE,
|
|
1283
134
|
strokeWidth: 0,
|
|
1284
135
|
cornerRadius: 0.08,
|
|
1285
136
|
pillShape: !1,
|
|
@@ -1290,11 +141,11 @@ const Ne = {
|
|
|
1290
141
|
},
|
|
1291
142
|
neon: {
|
|
1292
143
|
fontSize: 0.38,
|
|
1293
|
-
textColor:
|
|
144
|
+
textColor: a("#E0F2FE"),
|
|
1294
145
|
textOpacity: 1,
|
|
1295
|
-
backdropColor:
|
|
146
|
+
backdropColor: a("#030712"),
|
|
1296
147
|
backdropOpacity: 0.92,
|
|
1297
|
-
strokeColor:
|
|
148
|
+
strokeColor: a("#00F0FF"),
|
|
1298
149
|
strokeWidth: 0.025,
|
|
1299
150
|
cornerRadius: 0.24,
|
|
1300
151
|
pillShape: !1,
|
|
@@ -1305,11 +156,11 @@ const Ne = {
|
|
|
1305
156
|
},
|
|
1306
157
|
glass: {
|
|
1307
158
|
fontSize: 0.38,
|
|
1308
|
-
textColor:
|
|
159
|
+
textColor: a("#FFFFFF"),
|
|
1309
160
|
textOpacity: 1,
|
|
1310
|
-
backdropColor: new
|
|
161
|
+
backdropColor: new d(0.05, 0.09, 0.15, 0.65),
|
|
1311
162
|
backdropOpacity: 0.65,
|
|
1312
|
-
strokeColor: new
|
|
163
|
+
strokeColor: new d(1, 1, 1, 0.25),
|
|
1313
164
|
strokeWidth: 0.015,
|
|
1314
165
|
cornerRadius: 0.25,
|
|
1315
166
|
pillShape: !1,
|
|
@@ -1320,11 +171,11 @@ const Ne = {
|
|
|
1320
171
|
},
|
|
1321
172
|
light: {
|
|
1322
173
|
fontSize: 0.38,
|
|
1323
|
-
textColor:
|
|
174
|
+
textColor: a("#0F172A"),
|
|
1324
175
|
textOpacity: 1,
|
|
1325
|
-
backdropColor:
|
|
176
|
+
backdropColor: a("#F8FAFC"),
|
|
1326
177
|
backdropOpacity: 0.92,
|
|
1327
|
-
strokeColor: new
|
|
178
|
+
strokeColor: new d(0.39, 0.45, 0.55, 0.25),
|
|
1328
179
|
strokeWidth: 0.015,
|
|
1329
180
|
cornerRadius: 0.2,
|
|
1330
181
|
pillShape: !1,
|
|
@@ -1334,18 +185,18 @@ const Ne = {
|
|
|
1334
185
|
showBackdrop: !0
|
|
1335
186
|
}
|
|
1336
187
|
};
|
|
1337
|
-
function
|
|
1338
|
-
return
|
|
188
|
+
function n(r, t) {
|
|
189
|
+
return r ? typeof r == "string" ? a(r) : r : t;
|
|
1339
190
|
}
|
|
1340
|
-
class
|
|
191
|
+
class R extends b {
|
|
1341
192
|
_textEntity;
|
|
1342
193
|
_backdrop = null;
|
|
1343
194
|
_fontSize = 0.38;
|
|
1344
|
-
_textColor =
|
|
195
|
+
_textColor = a("#F8FAFC");
|
|
1345
196
|
_textOpacity = 1;
|
|
1346
|
-
_backdropColor =
|
|
197
|
+
_backdropColor = a("#060913");
|
|
1347
198
|
_backdropOpacity = 0.85;
|
|
1348
|
-
_strokeColor = new
|
|
199
|
+
_strokeColor = new d(0.22, 0.74, 0.97, 0.35);
|
|
1349
200
|
_strokeWidth = 0.02;
|
|
1350
201
|
_showBorder = !0;
|
|
1351
202
|
_cornerRadius = 0.22;
|
|
@@ -1356,16 +207,16 @@ class Re extends ie {
|
|
|
1356
207
|
_maxLineChars = 65;
|
|
1357
208
|
_lineHeight = 1.35;
|
|
1358
209
|
_clearTimeout = null;
|
|
1359
|
-
constructor(
|
|
210
|
+
constructor(t = {}) {
|
|
1360
211
|
super();
|
|
1361
|
-
const
|
|
1362
|
-
this._textEntity = new
|
|
212
|
+
const i = t.zIndex ?? 999;
|
|
213
|
+
this._textEntity = new m("", {
|
|
1363
214
|
fontSize: this._fontSize,
|
|
1364
215
|
fill: this._textColor,
|
|
1365
|
-
anchor:
|
|
1366
|
-
}), this._textEntity.paint.z_index =
|
|
1367
|
-
const
|
|
1368
|
-
this.transform.position.set([0,
|
|
216
|
+
anchor: S
|
|
217
|
+
}), this._textEntity.paint.z_index = i + 1, this._backdrop = new g(2, 1, { cornerRadius: this._cornerRadius }), this._backdrop.paint.fill = this._backdropColor, this._backdrop.paint.stroke = this._strokeColor, this._backdrop.paint.strokeWidth = this._strokeWidth, this._backdrop.paint.z_index = i, this._backdrop.paint.opacity = 0, this.add(this._backdrop), this.add(this._textEntity), this.paint.z_index = i, this.applyOptions(t);
|
|
218
|
+
const e = t.bottomOffset ?? -5;
|
|
219
|
+
this.transform.position.set([0, e, 0]);
|
|
1369
220
|
}
|
|
1370
221
|
/** Access the underlying SDFText entity for advanced low-level styling */
|
|
1371
222
|
get textEntity() {
|
|
@@ -1378,128 +229,128 @@ class Re extends ie {
|
|
|
1378
229
|
/**
|
|
1379
230
|
* Applies a complete configuration options object or partial updates.
|
|
1380
231
|
*/
|
|
1381
|
-
applyOptions(
|
|
1382
|
-
const
|
|
1383
|
-
return
|
|
232
|
+
applyOptions(t = {}) {
|
|
233
|
+
const e = { ...t.preset ? v[t.preset] : {}, ...t };
|
|
234
|
+
return e.fontSize !== void 0 && (this._fontSize = e.fontSize, this._textEntity.fontSize = e.fontSize), e.textColor !== void 0 && (this._textColor = n(e.textColor, this._textColor), this._textEntity.paint.fill = this._textColor), e.textOpacity !== void 0 && (this._textOpacity = e.textOpacity), e.backdropColor !== void 0 && (this._backdropColor = n(e.backdropColor, this._backdropColor)), e.backdropOpacity !== void 0 && (this._backdropOpacity = e.backdropOpacity), e.strokeColor !== void 0 && (this._strokeColor = n(e.strokeColor, this._strokeColor)), e.strokeWidth !== void 0 && (this._strokeWidth = e.strokeWidth), e.showBorder !== void 0 && (this._showBorder = e.showBorder), e.cornerRadius !== void 0 && (this._cornerRadius = e.cornerRadius), e.pillShape !== void 0 && (this._pillShape = e.pillShape), e.showBackdrop !== void 0 && (this._showBackdrop = e.showBackdrop), e.padding !== void 0 && (typeof e.padding == "number" ? this._padding = [e.padding, e.padding] : Array.isArray(e.padding) && (this._padding = [e.padding[0], e.padding[1]])), e.maxWidth !== void 0 && (this._maxWidth = e.maxWidth), e.maxLineChars !== void 0 && (this._maxLineChars = Math.max(15, e.maxLineChars)), e.lineHeight !== void 0 && (this._lineHeight = e.lineHeight), e.bottomOffset !== void 0 && this.setBottomOffset(e.bottomOffset), this._textEntity.text && this._updateBackdropDimensions(this._textEntity.text), this.version++, this;
|
|
1384
235
|
}
|
|
1385
236
|
/** Set an aesthetic preset theme */
|
|
1386
|
-
setPreset(
|
|
1387
|
-
return this.applyOptions({ preset:
|
|
237
|
+
setPreset(t) {
|
|
238
|
+
return this.applyOptions({ preset: t });
|
|
1388
239
|
}
|
|
1389
240
|
/** Set the corner radius of the backdrop pill without distortion */
|
|
1390
|
-
setCornerRadius(
|
|
1391
|
-
return this._cornerRadius =
|
|
241
|
+
setCornerRadius(t) {
|
|
242
|
+
return this._cornerRadius = t, this._pillShape = !1, this._textEntity.text && this._updateBackdropDimensions(this._textEntity.text), this;
|
|
1392
243
|
}
|
|
1393
244
|
/** Enable or disable stadium pill shape (semicircular ends where cornerRadius = height / 2) */
|
|
1394
|
-
setPillShape(
|
|
1395
|
-
return this._pillShape =
|
|
245
|
+
setPillShape(t = !0) {
|
|
246
|
+
return this._pillShape = t, this._textEntity.text && this._updateBackdropDimensions(this._textEntity.text), this;
|
|
1396
247
|
}
|
|
1397
248
|
/** Set the inner horizontal and vertical padding around the subtitle text */
|
|
1398
|
-
setPadding(
|
|
1399
|
-
return this._padding = [
|
|
249
|
+
setPadding(t, i = t) {
|
|
250
|
+
return this._padding = [t, i], this._textEntity.text && this._updateBackdropDimensions(this._textEntity.text), this;
|
|
1400
251
|
}
|
|
1401
252
|
/** Configure backdrop fill color and opacity */
|
|
1402
|
-
setBackdropColor(
|
|
1403
|
-
return this._backdropColor =
|
|
253
|
+
setBackdropColor(t, i) {
|
|
254
|
+
return this._backdropColor = n(t, this._backdropColor), i !== void 0 && (this._backdropOpacity = Math.max(0, Math.min(1, i))), this._backdrop && (this._backdrop.paint.fill = this._backdropColor, this._textEntity.text && (this._backdrop.paint.opacity = this._backdropOpacity), this._backdrop.invalidate()), this;
|
|
1404
255
|
}
|
|
1405
|
-
setStroke(
|
|
1406
|
-
return typeof
|
|
256
|
+
setStroke(t, i) {
|
|
257
|
+
return typeof t == "number" ? (this._strokeWidth = t, this._showBorder = t > 0, i !== void 0 && (typeof i == "string" || i instanceof d) && (this._strokeColor = n(i, this._strokeColor))) : (this._strokeColor = n(t, this._strokeColor), typeof i == "number" && (this._strokeWidth = i, this._showBorder = i > 0)), this._backdrop && (this._backdrop.paint.stroke = this._strokeColor, this._backdrop.paint.strokeWidth = this._strokeWidth, this._backdrop.invalidate()), this;
|
|
1407
258
|
}
|
|
1408
259
|
/** Set backdrop border stroke color */
|
|
1409
|
-
setStrokeColor(
|
|
1410
|
-
return this._strokeColor =
|
|
260
|
+
setStrokeColor(t) {
|
|
261
|
+
return this._strokeColor = n(t, this._strokeColor), this._backdrop && (this._backdrop.paint.stroke = this._strokeColor, this._backdrop.invalidate()), this;
|
|
1411
262
|
}
|
|
1412
263
|
/** Set backdrop border stroke width */
|
|
1413
|
-
setStrokeWidth(
|
|
1414
|
-
return this._strokeWidth =
|
|
264
|
+
setStrokeWidth(t) {
|
|
265
|
+
return this._strokeWidth = t, this._showBorder = t > 0, this._backdrop && (this._backdrop.paint.strokeWidth = this._strokeWidth, this._backdrop.invalidate()), this;
|
|
1415
266
|
}
|
|
1416
267
|
/** Configure subtitle typography (font color and world unit font size) */
|
|
1417
|
-
setTextColor(
|
|
1418
|
-
return this._textColor =
|
|
268
|
+
setTextColor(t, i = 1) {
|
|
269
|
+
return this._textColor = n(t, this._textColor), this._textOpacity = i, this._textEntity.paint.fill = this._textColor, this._textEntity.paint.opacity = i, this.version++, this;
|
|
1419
270
|
}
|
|
1420
271
|
/** Set subtitle font size in world units */
|
|
1421
|
-
setFontSize(
|
|
1422
|
-
return
|
|
272
|
+
setFontSize(t) {
|
|
273
|
+
return t > 0 && (this._fontSize = t, this._textEntity.fontSize = t, this._textEntity.text && this._updateBackdropDimensions(this._textEntity.text)), this;
|
|
1423
274
|
}
|
|
1424
275
|
/** Configure backdrop visual styling (colors, stroke border, corner radius) */
|
|
1425
|
-
setBackdropStyle(
|
|
1426
|
-
return this._backdropColor =
|
|
276
|
+
setBackdropStyle(t, i, e, s) {
|
|
277
|
+
return this._backdropColor = n(t, this._backdropColor), i !== void 0 && (this._strokeColor = n(i, this._strokeColor), this._showBorder = !0), e !== void 0 && (this._strokeWidth = e, this._showBorder = e > 0), s !== void 0 && (this._cornerRadius = s, this._pillShape = !1), this._textEntity.text && this._updateBackdropDimensions(this._textEntity.text), this.version++, this;
|
|
1427
278
|
}
|
|
1428
279
|
/** Configure subtitle typography */
|
|
1429
|
-
setTextStyle(
|
|
1430
|
-
return this._textColor =
|
|
280
|
+
setTextStyle(t, i) {
|
|
281
|
+
return this._textColor = n(t, this._textColor), this._textEntity.paint.fill = this._textColor, i !== void 0 && i > 0 && (this._fontSize = i, this._textEntity.fontSize = i), this._textEntity.text && this._updateBackdropDimensions(this._textEntity.text), this.version++, this;
|
|
1431
282
|
}
|
|
1432
283
|
/** Set maximum characters per line before word-wrapping occurs */
|
|
1433
|
-
setMaxLineChars(
|
|
1434
|
-
return this._maxLineChars = Math.max(15,
|
|
284
|
+
setMaxLineChars(t) {
|
|
285
|
+
return this._maxLineChars = Math.max(15, t), this;
|
|
1435
286
|
}
|
|
1436
287
|
/** Set maximum bounding box width in world units */
|
|
1437
|
-
setMaxWidth(
|
|
1438
|
-
return this._maxWidth =
|
|
288
|
+
setMaxWidth(t) {
|
|
289
|
+
return this._maxWidth = t, this;
|
|
1439
290
|
}
|
|
1440
291
|
/** Positions the subtitles at the bottom center with a custom Y world coordinate */
|
|
1441
|
-
setBottomOffset(
|
|
1442
|
-
return this.transform.position.set([0,
|
|
292
|
+
setBottomOffset(t) {
|
|
293
|
+
return this.transform.position.set([0, t, 0]), this;
|
|
1443
294
|
}
|
|
1444
295
|
/**
|
|
1445
296
|
* Computes safe corner radius: clamped so circular arcs never self-intersect,
|
|
1446
297
|
* or computes stadium capsule radius when pillShape is enabled.
|
|
1447
298
|
*/
|
|
1448
|
-
_getEffectiveCornerRadius(
|
|
1449
|
-
const
|
|
1450
|
-
return this._pillShape ?
|
|
1451
|
-
Math.max(0, Math.min(this._cornerRadius[0],
|
|
1452
|
-
Math.max(0, Math.min(this._cornerRadius[1],
|
|
1453
|
-
Math.max(0, Math.min(this._cornerRadius[2],
|
|
1454
|
-
Math.max(0, Math.min(this._cornerRadius[3],
|
|
1455
|
-
] : Math.min(0.22,
|
|
299
|
+
_getEffectiveCornerRadius(t, i) {
|
|
300
|
+
const e = Math.min(t, i) / 2;
|
|
301
|
+
return this._pillShape ? e : typeof this._cornerRadius == "number" ? Math.max(0, Math.min(this._cornerRadius, e)) : Array.isArray(this._cornerRadius) ? [
|
|
302
|
+
Math.max(0, Math.min(this._cornerRadius[0], e)),
|
|
303
|
+
Math.max(0, Math.min(this._cornerRadius[1], e)),
|
|
304
|
+
Math.max(0, Math.min(this._cornerRadius[2], e)),
|
|
305
|
+
Math.max(0, Math.min(this._cornerRadius[3], e))
|
|
306
|
+
] : Math.min(0.22, e);
|
|
1456
307
|
}
|
|
1457
308
|
/**
|
|
1458
309
|
* Internal geometry reflow: updates backdrop width & height using genuine Rect
|
|
1459
310
|
* geometry regeneration (Rect.sync()) to preserve pristine, circular corner arcs.
|
|
1460
311
|
*/
|
|
1461
|
-
_updateBackdropDimensions(
|
|
312
|
+
_updateBackdropDimensions(t) {
|
|
1462
313
|
if (!this._backdrop) return;
|
|
1463
|
-
if (!this._showBackdrop || !
|
|
314
|
+
if (!this._showBackdrop || !t || t.trim().length === 0) {
|
|
1464
315
|
this._backdrop.paint.opacity = 0, this._backdrop.invalidate();
|
|
1465
316
|
return;
|
|
1466
317
|
}
|
|
1467
|
-
const
|
|
1468
|
-
let
|
|
1469
|
-
if (
|
|
1470
|
-
const f =
|
|
318
|
+
const i = this._textEntity.getGroupLocalAABB(), e = i.isEmpty() ? 0 : i.size.x, s = i.isEmpty() ? 0 : i.size.y, [c, l] = this._padding;
|
|
319
|
+
let o = e, h = s;
|
|
320
|
+
if (o <= 0.1 || h <= 0.1) {
|
|
321
|
+
const f = t.split(`
|
|
1471
322
|
`);
|
|
1472
|
-
|
|
323
|
+
o = Math.max(...f.map((y) => y.length)) * (this._fontSize * 0.44), h = f.length * (this._fontSize * this._lineHeight);
|
|
1473
324
|
}
|
|
1474
|
-
const
|
|
1475
|
-
this._backdrop.transform.setScale([1, 1, 1]), this._backdrop.width =
|
|
325
|
+
const _ = Math.max(2.4, Math.min(this._maxWidth, o + c * 2)), u = h + l * 2, k = this._getEffectiveCornerRadius(_, u);
|
|
326
|
+
this._backdrop.transform.setScale([1, 1, 1]), this._backdrop.width = _, this._backdrop.height = u, this._backdrop.cornerRadius = k, this._backdrop.paint.fill = this._backdropColor, this._backdrop.paint.stroke = this._showBorder ? this._strokeColor : d.NONE, this._backdrop.paint.strokeWidth = this._showBorder ? this._strokeWidth : 0, this._backdrop.paint.opacity = this._backdropOpacity, this._backdrop.invalidate();
|
|
1476
327
|
}
|
|
1477
328
|
/**
|
|
1478
329
|
* Displays a subtitle sentence, formatting lines with word-wrapping and
|
|
1479
330
|
* reflowing the backdrop pill with true circular corner arcs.
|
|
1480
331
|
*/
|
|
1481
|
-
showText(
|
|
332
|
+
showText(t, i) {
|
|
1482
333
|
this._clearTimeout && (clearTimeout(this._clearTimeout), this._clearTimeout = null);
|
|
1483
|
-
const
|
|
1484
|
-
let
|
|
1485
|
-
if (
|
|
1486
|
-
const
|
|
1487
|
-
let
|
|
1488
|
-
for (const
|
|
1489
|
-
(
|
|
1490
|
-
|
|
334
|
+
const e = t.trim();
|
|
335
|
+
let s = e;
|
|
336
|
+
if (e.length > this._maxLineChars) {
|
|
337
|
+
const c = e.split(" "), l = [];
|
|
338
|
+
let o = "";
|
|
339
|
+
for (const h of c)
|
|
340
|
+
(o + " " + h).trim().length > this._maxLineChars ? (o && l.push(o), o = h) : o = o ? o + " " + h : h;
|
|
341
|
+
o && l.push(o), s = l.join(`
|
|
1491
342
|
`);
|
|
1492
343
|
}
|
|
1493
|
-
return this._textEntity.text =
|
|
344
|
+
return this._textEntity.text = s, this._textEntity.paint.opacity = this._textOpacity, this._updateBackdropDimensions(s), this.version++, i && i > 0 && (this._clearTimeout = setTimeout(() => {
|
|
1494
345
|
this.clear();
|
|
1495
|
-
},
|
|
346
|
+
}, i)), this;
|
|
1496
347
|
}
|
|
1497
348
|
/**
|
|
1498
349
|
* Synchronizes this subtitle banner with a [[TTSAudioResult]], displaying the spoken text
|
|
1499
350
|
* for the duration of the utterance and clearing on finish.
|
|
1500
351
|
*/
|
|
1501
|
-
syncWithAudio(
|
|
1502
|
-
return this.showText(
|
|
352
|
+
syncWithAudio(t) {
|
|
353
|
+
return this.showText(t.text, t.durationMs);
|
|
1503
354
|
}
|
|
1504
355
|
/**
|
|
1505
356
|
* Immediately clears and hides the subtitle banner.
|
|
@@ -1508,7 +359,7 @@ class Re extends ie {
|
|
|
1508
359
|
return this._clearTimeout && (clearTimeout(this._clearTimeout), this._clearTimeout = null), this._textEntity.text = "", this._textEntity.paint.opacity = 0, this._backdrop && (this._backdrop.paint.opacity = 0, this._backdrop.invalidate()), this.version++, this;
|
|
1509
360
|
}
|
|
1510
361
|
}
|
|
1511
|
-
class
|
|
362
|
+
class T extends C {
|
|
1512
363
|
text;
|
|
1513
364
|
voice;
|
|
1514
365
|
speed;
|
|
@@ -1519,40 +370,56 @@ class De extends ne {
|
|
|
1519
370
|
duckingRatio;
|
|
1520
371
|
volume;
|
|
1521
372
|
_audioResult = null;
|
|
373
|
+
_audioTask = null;
|
|
374
|
+
_synthesisOptions;
|
|
1522
375
|
_isStarted = !1;
|
|
1523
376
|
_baseScale = [1, 1, 1];
|
|
1524
|
-
constructor(
|
|
1525
|
-
super(
|
|
1526
|
-
|
|
1527
|
-
|
|
377
|
+
constructor(t, i = {}) {
|
|
378
|
+
super(i), this.text = t, this.voice = i.voice, this.speed = i.speed ?? 1, this.pitch = i.pitch, this.subtitles = i.subtitles, this.targetEntity = i.entity, this.pulseAmplitude = i.pulseAmplitude ?? 0.05, this.duckingRatio = i.duckingRatio ?? 0.25, this.volume = i.volume ?? 1, this._synthesisOptions = {
|
|
379
|
+
voice: i.voice,
|
|
380
|
+
speed: i.speed,
|
|
381
|
+
pitch: i.pitch,
|
|
382
|
+
volume: i.volume,
|
|
383
|
+
displayText: i.displayText,
|
|
384
|
+
elevenlabs: i.elevenlabs
|
|
385
|
+
};
|
|
386
|
+
const e = t.trim().split(/\s+/).length;
|
|
387
|
+
this.duration = Math.max(1e3, e * 420 * (1 / this.speed));
|
|
1528
388
|
}
|
|
1529
389
|
/**
|
|
1530
390
|
* Prepares animation state.
|
|
1531
391
|
*/
|
|
1532
392
|
prepare() {
|
|
1533
393
|
if (this.targetEntity?.transform) {
|
|
1534
|
-
const
|
|
1535
|
-
this._baseScale = [
|
|
394
|
+
const t = this.targetEntity.transform.getScale();
|
|
395
|
+
this._baseScale = [t.x, t.y, t.z];
|
|
1536
396
|
}
|
|
1537
397
|
}
|
|
1538
398
|
/**
|
|
1539
399
|
* Synthesizes audio ahead of time and locks exact duration.
|
|
1540
400
|
*/
|
|
1541
401
|
async prepareAudio() {
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
402
|
+
if (!this._audioResult) {
|
|
403
|
+
this._audioTask ??= p.synthesize(this.text, this._synthesisOptions);
|
|
404
|
+
try {
|
|
405
|
+
this._audioResult = await this._audioTask, this.duration = this._audioResult.durationMs;
|
|
406
|
+
} finally {
|
|
407
|
+
this._audioTask = null;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return this._audioResult;
|
|
1548
411
|
}
|
|
1549
|
-
update(
|
|
412
|
+
update(t) {
|
|
1550
413
|
if (this.paused) return !1;
|
|
1551
|
-
if (this.
|
|
1552
|
-
|
|
414
|
+
if (this.delay > 0) {
|
|
415
|
+
if (this.delay -= t, this.delay > 0) return !1;
|
|
416
|
+
t = -this.delay, this.delay = 0;
|
|
417
|
+
}
|
|
418
|
+
if (this._isStarted || (this._isStarted = !0, this._beginPlayback()), this.elapsed += t, this.targetEntity?.transform) {
|
|
419
|
+
const i = this.elapsed / 1e3 * 4 * Math.PI * 2, e = 1 + Math.sin(i) * this.pulseAmplitude;
|
|
1553
420
|
this.targetEntity.transform.setScale([
|
|
1554
|
-
this._baseScale[0] *
|
|
1555
|
-
this._baseScale[1] *
|
|
421
|
+
this._baseScale[0] * e,
|
|
422
|
+
this._baseScale[1] * e,
|
|
1556
423
|
this._baseScale[2]
|
|
1557
424
|
]), this.targetEntity.version++;
|
|
1558
425
|
}
|
|
@@ -1560,13 +427,13 @@ class De extends ne {
|
|
|
1560
427
|
}
|
|
1561
428
|
async _beginPlayback() {
|
|
1562
429
|
if (this.targetEntity?.transform) {
|
|
1563
|
-
const
|
|
1564
|
-
this._baseScale = [
|
|
430
|
+
const e = this.targetEntity.transform.getScale();
|
|
431
|
+
this._baseScale = [e.x, e.y, e.z];
|
|
1565
432
|
}
|
|
1566
|
-
const
|
|
1567
|
-
this.subtitles && this.subtitles.syncWithAudio(
|
|
1568
|
-
const
|
|
1569
|
-
await
|
|
433
|
+
const t = await this.prepareAudio();
|
|
434
|
+
this.subtitles && this.subtitles.syncWithAudio(t);
|
|
435
|
+
const i = this.targetEntity?.scene;
|
|
436
|
+
await t.play(i, {
|
|
1570
437
|
duckingRatio: this.duckingRatio,
|
|
1571
438
|
volume: this.volume
|
|
1572
439
|
});
|
|
@@ -1575,38 +442,41 @@ class De extends ne {
|
|
|
1575
442
|
this.targetEntity?.transform && (this.targetEntity.transform.setScale(this._baseScale), this.targetEntity.version++);
|
|
1576
443
|
}
|
|
1577
444
|
}
|
|
1578
|
-
async function
|
|
1579
|
-
const
|
|
1580
|
-
|
|
1581
|
-
const
|
|
1582
|
-
voice:
|
|
1583
|
-
speed:
|
|
1584
|
-
pitch:
|
|
1585
|
-
volume:
|
|
445
|
+
async function M(r, t, i = {}) {
|
|
446
|
+
const e = r?.audio || r;
|
|
447
|
+
e && typeof e.awaitUnlock == "function" && await e.awaitUnlock();
|
|
448
|
+
const s = await p.synthesize(t, {
|
|
449
|
+
voice: i.voice,
|
|
450
|
+
speed: i.speed,
|
|
451
|
+
pitch: i.pitch,
|
|
452
|
+
volume: i.volume,
|
|
453
|
+
displayText: i.displayText,
|
|
454
|
+
elevenlabs: i.elevenlabs
|
|
1586
455
|
});
|
|
1587
|
-
return
|
|
1588
|
-
duckingRatio:
|
|
1589
|
-
volume:
|
|
1590
|
-
}),
|
|
456
|
+
return i.subtitles && i.subtitles.syncWithAudio(s), s.play(e, {
|
|
457
|
+
duckingRatio: i.duckingRatio ?? 0.25,
|
|
458
|
+
volume: i.volume ?? 1
|
|
459
|
+
}), r && typeof r.wait == "function" && await r.wait(s.durationMs), s;
|
|
1591
460
|
}
|
|
1592
461
|
export {
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
462
|
+
I as DEFAULT_MSEDGE_VOICE,
|
|
463
|
+
W as ElevenLabsTTSProvider,
|
|
464
|
+
N as MSEDGE_VOICES,
|
|
465
|
+
A as MsEdgeTTSProvider,
|
|
466
|
+
v as SUBTITLE_PRESETS,
|
|
467
|
+
T as Speak,
|
|
468
|
+
R as Subtitles,
|
|
469
|
+
p as TTS,
|
|
470
|
+
D as TTSAudio,
|
|
471
|
+
L as TTSCache,
|
|
472
|
+
H as TTSClient,
|
|
473
|
+
F as TTSNarrationComponent,
|
|
474
|
+
P as encodeWAV,
|
|
475
|
+
Y as fetchRemoteMsEdgeVoices,
|
|
476
|
+
X as findMsEdgeVoice,
|
|
477
|
+
Z as getAvailableMsEdgeVoices,
|
|
478
|
+
q as getMsEdgeVoicesByLanguage,
|
|
479
|
+
G as parseMp3Metadata,
|
|
480
|
+
U as setDynamicMsEdgeVoices,
|
|
481
|
+
M as speak
|
|
1612
482
|
};
|