@sage-rsc/talking-head-react 1.0.60 → 1.0.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2 -2
- package/dist/index.js +1044 -1042
- package/package.json +1 -1
- package/src/components/TalkingHeadAvatar.jsx +63 -32
package/dist/index.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { forwardRef as
|
|
1
|
+
import { jsxs as Ee, jsx as ue } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as Ie, useRef as G, useState as de, useEffect as me, useCallback as T, useImperativeHandle as Le, useLayoutEffect as Ue } from "react";
|
|
3
3
|
import * as f from "three";
|
|
4
|
-
import { OrbitControls as
|
|
5
|
-
import { GLTFLoader as
|
|
6
|
-
import { DRACOLoader as
|
|
7
|
-
import { FBXLoader as
|
|
8
|
-
import { RoomEnvironment as
|
|
9
|
-
import
|
|
10
|
-
let m,
|
|
11
|
-
const L = [0, 0, 0, 0], k = new f.Vector3(),
|
|
4
|
+
import { OrbitControls as We } from "three/addons/controls/OrbitControls.js";
|
|
5
|
+
import { GLTFLoader as Ve } from "three/addons/loaders/GLTFLoader.js";
|
|
6
|
+
import { DRACOLoader as Ge } from "three/addons/loaders/DRACOLoader.js";
|
|
7
|
+
import { FBXLoader as ze } from "three/addons/loaders/FBXLoader.js";
|
|
8
|
+
import { RoomEnvironment as Ze } from "three/addons/environments/RoomEnvironment.js";
|
|
9
|
+
import Xe from "three/addons/libs/stats.module.js";
|
|
10
|
+
let m, J, ee;
|
|
11
|
+
const L = [0, 0, 0, 0], k = new f.Vector3(), xe = new f.Vector3(), j = new f.Vector3(), be = new f.Vector3();
|
|
12
12
|
new f.Plane();
|
|
13
13
|
new f.Ray();
|
|
14
14
|
new f.Euler();
|
|
15
|
-
const
|
|
15
|
+
const Q = new f.Quaternion(), Ce = new f.Quaternion(), ie = new f.Matrix4(), oe = new f.Matrix4();
|
|
16
16
|
new f.Vector3();
|
|
17
|
-
const
|
|
18
|
-
class
|
|
17
|
+
const ve = new f.Vector3(0, 0, 1), Ye = new f.Vector3(1, 0, 0), je = new f.Vector3(0, 1, 0), Qe = new f.Vector3(0, 0, 1);
|
|
18
|
+
class qe {
|
|
19
19
|
constructor(t = null) {
|
|
20
20
|
this.opt = Object.assign({
|
|
21
21
|
warmupMs: 2e3,
|
|
@@ -80,34 +80,34 @@ class je {
|
|
|
80
80
|
throw new Error("Dynamic bones has not been setup yet.");
|
|
81
81
|
if (!this.dict.hasOwnProperty(t))
|
|
82
82
|
throw new Error("Dynamic bone '" + t + "' not found.");
|
|
83
|
-
const
|
|
84
|
-
let
|
|
83
|
+
const n = this.dict[t];
|
|
84
|
+
let i;
|
|
85
85
|
if (e === "type")
|
|
86
|
-
|
|
86
|
+
i = n.type;
|
|
87
87
|
else if (e === "stiffness")
|
|
88
|
-
|
|
88
|
+
i = n.k.every((s) => s === n.k[0]) ? n.k[0] : [...n.k];
|
|
89
89
|
else if (e === "damping")
|
|
90
|
-
|
|
90
|
+
i = n.c.every((s) => s === n.c[0]) ? n.c[0] : [...n.c];
|
|
91
91
|
else if (e === "external")
|
|
92
|
-
|
|
92
|
+
i = n.ext < 1 ? n.ext : null;
|
|
93
93
|
else if (e === "limits")
|
|
94
|
-
|
|
94
|
+
i = n.limits?.map((s) => s === null ? null : [...s]);
|
|
95
95
|
else if (e === "deltaLocal")
|
|
96
|
-
|
|
96
|
+
i = n.dl ? [...n.dl] : null;
|
|
97
97
|
else if (e === "excludes")
|
|
98
|
-
|
|
98
|
+
i = n.excludes ? [...n.excludes.map((s) => {
|
|
99
99
|
const o = { bone: s.bone.name.slice(), radius: s.radius };
|
|
100
100
|
return s.deltaLocal && (o.deltaLocal = [...s.deltaLocal]), o;
|
|
101
101
|
})] : null;
|
|
102
102
|
else if (e === "deltaWorld")
|
|
103
|
-
|
|
103
|
+
i = n.dw ? [...n.dw] : null;
|
|
104
104
|
else if (e === "pivot")
|
|
105
|
-
|
|
105
|
+
i = n.pivot;
|
|
106
106
|
else if (e === "helper")
|
|
107
|
-
|
|
107
|
+
i = n.helper;
|
|
108
108
|
else
|
|
109
109
|
throw new Error("Unsupported property '" + e + "'.");
|
|
110
|
-
return
|
|
110
|
+
return i;
|
|
111
111
|
}
|
|
112
112
|
/**
|
|
113
113
|
* Set property value for a dynamic bone.
|
|
@@ -116,77 +116,77 @@ class je {
|
|
|
116
116
|
* @param {string} key Property name
|
|
117
117
|
* @param {any} val Property value
|
|
118
118
|
*/
|
|
119
|
-
setValue(t, e,
|
|
119
|
+
setValue(t, e, n) {
|
|
120
120
|
if (this.scene === null)
|
|
121
121
|
throw new Error("Dynamic bones has not been setup yet.");
|
|
122
122
|
if (!this.dict.hasOwnProperty(t))
|
|
123
123
|
throw new Error("Dynamic bone '" + t + "' not found.");
|
|
124
|
-
const
|
|
124
|
+
const i = this.dict[t];
|
|
125
125
|
if (e === "type") {
|
|
126
|
-
if (!
|
|
127
|
-
if (typeof
|
|
128
|
-
switch (
|
|
126
|
+
if (!n) throw new Error("Parameter 'type' not set.");
|
|
127
|
+
if (typeof n != "string") throw new Error("Type must be a string.");
|
|
128
|
+
switch (n) {
|
|
129
129
|
case "point":
|
|
130
|
-
|
|
130
|
+
i.isPoint = !0, i.isX = !0, i.isY = !0, i.isZ = !0, i.isT = !1;
|
|
131
131
|
break;
|
|
132
132
|
case "link":
|
|
133
|
-
|
|
133
|
+
i.isPoint = !1, i.isX = !0, i.isY = !1, i.isZ = !0, i.isT = !1;
|
|
134
134
|
break;
|
|
135
135
|
case "mix1":
|
|
136
|
-
|
|
136
|
+
i.isPoint = !1, i.isX = !0, i.isY = !0, i.isZ = !0, i.isT = !1;
|
|
137
137
|
break;
|
|
138
138
|
case "mix2":
|
|
139
|
-
|
|
139
|
+
i.isPoint = !1, i.isX = !0, i.isY = !1, i.isZ = !0, i.isT = !0;
|
|
140
140
|
break;
|
|
141
141
|
case "full":
|
|
142
|
-
|
|
142
|
+
i.isPoint = !1, i.isX = !0, i.isY = !0, i.isZ = !0, i.isT = !0;
|
|
143
143
|
break;
|
|
144
144
|
default:
|
|
145
|
-
throw new Error("Unknown type'" +
|
|
145
|
+
throw new Error("Unknown type'" + n + "'.");
|
|
146
146
|
}
|
|
147
|
-
|
|
147
|
+
i.type = n.slice();
|
|
148
148
|
} else if (e === "stiffness") {
|
|
149
|
-
if (!
|
|
150
|
-
if (!Number.isNaN(
|
|
151
|
-
|
|
152
|
-
else if (Array.isArray(
|
|
153
|
-
|
|
149
|
+
if (!n) throw new Error("Parameter 'stiffness' not set.");
|
|
150
|
+
if (!Number.isNaN(n) && n >= 0)
|
|
151
|
+
i.k = Array(4).fill(n);
|
|
152
|
+
else if (Array.isArray(n) && n.length === 4 && n.every((s) => s >= 0))
|
|
153
|
+
i.k = [...n];
|
|
154
154
|
else
|
|
155
155
|
throw new Error("Stiffness must be a non-negative number or an array of four non-negative numbers.");
|
|
156
156
|
} else if (e === "damping") {
|
|
157
|
-
if (!
|
|
158
|
-
if (!Number.isNaN(
|
|
159
|
-
|
|
160
|
-
else if (Array.isArray(
|
|
161
|
-
|
|
157
|
+
if (!n) throw new Error("Parameter 'damping' not set.");
|
|
158
|
+
if (!Number.isNaN(n) && n >= 0)
|
|
159
|
+
i.c = Array(4).fill(n);
|
|
160
|
+
else if (Array.isArray(n) && n.length === 4 && n.every((s) => s >= 0))
|
|
161
|
+
i.c = [...n];
|
|
162
162
|
else
|
|
163
163
|
throw new Error("Damping must be a non-negative number or an array of four non-negative numbers.");
|
|
164
164
|
} else if (e === "external")
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
else if (!Number.isNaN(
|
|
168
|
-
|
|
165
|
+
if (n == null)
|
|
166
|
+
i.ext = 1;
|
|
167
|
+
else if (!Number.isNaN(n) && n >= 0 && n <= 1)
|
|
168
|
+
i.ext = n;
|
|
169
169
|
else
|
|
170
170
|
throw new Error("External (if set) must be a number between [0,1].");
|
|
171
171
|
else if (e === "limits")
|
|
172
|
-
if (
|
|
173
|
-
|
|
172
|
+
if (n == null)
|
|
173
|
+
i.limits = null;
|
|
174
174
|
else {
|
|
175
|
-
if (!Array.isArray(
|
|
176
|
-
if (!
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
175
|
+
if (!Array.isArray(n) || n.length !== 4) throw new Error("Limits (if set) must null, or an array of four arrays.");
|
|
176
|
+
if (!n.every((s) => s === null || Array.isArray(s) && s.length === 2 && (s[0] === null || !Number.isNaN(s[0])) && (s[1] === null || !Number.isNaN(s)))) throw new Error("Limit values must be null or numbers.");
|
|
177
|
+
i.limits = [
|
|
178
|
+
n[0] ? [...n[0]] : null,
|
|
179
|
+
n[1] ? [...n[1]] : null,
|
|
180
|
+
n[2] ? [...n[2]] : null,
|
|
181
|
+
n[3] ? [...n[3]] : null
|
|
182
182
|
];
|
|
183
183
|
}
|
|
184
184
|
else if (e === "excludes") {
|
|
185
|
-
if (
|
|
186
|
-
|
|
185
|
+
if (n == null)
|
|
186
|
+
i.excludes = null;
|
|
187
187
|
else {
|
|
188
|
-
if (!Array.isArray(
|
|
189
|
-
|
|
188
|
+
if (!Array.isArray(n)) throw new Error("Excludes (if set) must null, or an array.");
|
|
189
|
+
i.excludes = [], n.forEach((s, o) => {
|
|
190
190
|
if (!s.bone) throw new Error("Bone not specified in #" + o + " exclude.");
|
|
191
191
|
if (typeof s.bone != "string" || s.bone.length === 0) throw new Error("Bone name must be a non-empty string in #" + o + " exclude.");
|
|
192
192
|
const l = this.armature.getObjectByName(s.bone);
|
|
@@ -205,41 +205,41 @@ class je {
|
|
|
205
205
|
if (!Array.isArray(s.deltaLocal) || s.deltaLocal.length !== 3 || s.deltaLocal.some((a) => Number.isNaN(a))) throw new Error("deltaLocal must be an array of three numbers in #" + o + " exclude.");
|
|
206
206
|
u.deltaLocal = [...s.deltaLocal];
|
|
207
207
|
}
|
|
208
|
-
|
|
208
|
+
i.excludes.push(u);
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
211
|
this.showHelpers();
|
|
212
212
|
} else if (e === "helper") {
|
|
213
|
-
if (
|
|
214
|
-
|
|
213
|
+
if (n == null)
|
|
214
|
+
i.helper = null;
|
|
215
215
|
else {
|
|
216
|
-
if (
|
|
217
|
-
|
|
216
|
+
if (n !== !1 && n !== !0) throw new Error("Helper, if set, must be false or true.");
|
|
217
|
+
i.helper = n;
|
|
218
218
|
}
|
|
219
219
|
this.showHelpers();
|
|
220
220
|
} else if (e === "pivot")
|
|
221
|
-
if (
|
|
222
|
-
|
|
221
|
+
if (n == null)
|
|
222
|
+
i.pivot = null;
|
|
223
223
|
else {
|
|
224
|
-
if (
|
|
225
|
-
if (
|
|
226
|
-
|
|
224
|
+
if (n !== !1 && n !== !0) throw new Error("Pivot, if set, must be false or true.");
|
|
225
|
+
if (n === !0 && i.type === 0) throw new Error("Point type bone can't be a pivot.");
|
|
226
|
+
i.pivot = n;
|
|
227
227
|
}
|
|
228
228
|
else if (e === "deltaLocal")
|
|
229
|
-
if (
|
|
230
|
-
|
|
229
|
+
if (n == null)
|
|
230
|
+
i.dl = null;
|
|
231
231
|
else {
|
|
232
|
-
if (!Array.isArray(
|
|
233
|
-
if (!
|
|
234
|
-
|
|
232
|
+
if (!Array.isArray(n) || n.length !== 3) throw new Error("deltaLocal, is set, must be an array of three numbers.");
|
|
233
|
+
if (!n.every((s) => !Number.isNaN(s))) throw new Error("deltaLocal values must be numbers.");
|
|
234
|
+
i.dl = [...n];
|
|
235
235
|
}
|
|
236
236
|
else if (e === "deltaWorld")
|
|
237
|
-
if (
|
|
238
|
-
|
|
237
|
+
if (n == null)
|
|
238
|
+
i.dw = null;
|
|
239
239
|
else {
|
|
240
|
-
if (!Array.isArray(
|
|
241
|
-
if (!
|
|
242
|
-
|
|
240
|
+
if (!Array.isArray(n) || n.length !== 3) throw new Error("deltaWorld, is set, must be an array of three values.");
|
|
241
|
+
if (!n.every((s) => !Number.isNaN(s))) throw new Error("deltaWorld values must be numbers.");
|
|
242
|
+
i.dw = [...n];
|
|
243
243
|
}
|
|
244
244
|
else
|
|
245
245
|
throw new Error("Unsupported property " + e);
|
|
@@ -263,8 +263,8 @@ class je {
|
|
|
263
263
|
"excludes",
|
|
264
264
|
"pivot",
|
|
265
265
|
"helper"
|
|
266
|
-
].forEach((
|
|
267
|
-
m = this.getValue(t.name,
|
|
266
|
+
].forEach((n) => {
|
|
267
|
+
m = this.getValue(t.name, n), m && (e[n] = m);
|
|
268
268
|
}), e;
|
|
269
269
|
});
|
|
270
270
|
}
|
|
@@ -281,9 +281,9 @@ class je {
|
|
|
281
281
|
}), this.data.sort((o, l) => e.get(o.bone) - e.get(l.bone)), this.data.forEach((o) => {
|
|
282
282
|
m = this.dict[o.boneParent.name], m && (m.children || (m.children = []), m.children.push(o));
|
|
283
283
|
}), this.objectsUpdate = [];
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
284
|
+
const n = /* @__PURE__ */ new WeakSet(), i = (o) => o.parent?.isBone ? [o, ...i(o.parent)] : [o], s = (o) => {
|
|
285
|
+
i(o).forEach((u) => {
|
|
286
|
+
n.has(u) || (this.objectsUpdate.push(u), n.add(u));
|
|
287
287
|
});
|
|
288
288
|
};
|
|
289
289
|
this.data.forEach((o) => {
|
|
@@ -299,19 +299,19 @@ class je {
|
|
|
299
299
|
* @param {Object3D} armature Armature object
|
|
300
300
|
* @param {Object[]} config Array of configuration objects
|
|
301
301
|
*/
|
|
302
|
-
setup(t, e,
|
|
302
|
+
setup(t, e, n) {
|
|
303
303
|
this.dispose();
|
|
304
|
-
const
|
|
304
|
+
const i = (s, o) => {
|
|
305
305
|
if (!s)
|
|
306
306
|
throw this.dispose(), new Error(o);
|
|
307
307
|
};
|
|
308
|
-
|
|
308
|
+
i(t?.isScene, "First parameter must be Scene."), this.scene = t, i(e?.isObject3D, "Second parameter must be the armature Object3D."), this.armature = e, i(Array.isArray(n), "Third parameter must be an array of bone configs."), this.config = n, this.config.forEach((s, o) => {
|
|
309
309
|
const l = "Config item #" + o + ": ";
|
|
310
|
-
|
|
310
|
+
i(s.bone, l + "Bone not specified.");
|
|
311
311
|
const u = s.bone;
|
|
312
|
-
|
|
312
|
+
i(typeof u == "string" && u.length > 0, l + "Bone name must be a non-empty string.");
|
|
313
313
|
const a = this.armature.getObjectByName(u);
|
|
314
|
-
|
|
314
|
+
i(a, l + "Bone '" + u + "' not found."), i(a.parent?.isBone, l + "Bone must have a parent bone."), i(this.data.every((r) => r.bone !== a), l + "Bone '" + u + "' already exists."), a.updateMatrixWorld(!0);
|
|
315
315
|
const h = {
|
|
316
316
|
name: u,
|
|
317
317
|
// Bone name
|
|
@@ -338,11 +338,11 @@ class je {
|
|
|
338
338
|
ea: [0, 0, 0, 0]
|
|
339
339
|
// External acceleration [m/s^2]
|
|
340
340
|
};
|
|
341
|
-
h.boneParent.matrixWorld.decompose(k,
|
|
341
|
+
h.boneParent.matrixWorld.decompose(k, Q, j), k.copy(ve).applyQuaternion(Q).setY(0).normalize(), Q.premultiply(Ce.setFromUnitVectors(ve, k).invert()).normalize(), h.qWorldInverseYaw = Q.clone().normalize(), this.data.push(h), this.dict[u] = h;
|
|
342
342
|
try {
|
|
343
343
|
this.setValue(u, "type", s.type), this.setValue(u, "stiffness", s.stiffness), this.setValue(u, "damping", s.damping), this.setValue(u, "external", s.external), this.setValue(u, "limits", s.limits), this.setValue(u, "excludes", s.excludes), this.setValue(u, "deltaLocal", s.deltaLocal), this.setValue(u, "deltaWorld", s.deltaWorld), this.setValue(u, "pivot", s.pivot), this.setValue(u, "helper", s.helper);
|
|
344
344
|
} catch (r) {
|
|
345
|
-
|
|
345
|
+
i(!1, l + r);
|
|
346
346
|
}
|
|
347
347
|
}), this.sortBones(), this.start();
|
|
348
348
|
}
|
|
@@ -352,26 +352,26 @@ class je {
|
|
|
352
352
|
*/
|
|
353
353
|
update(t) {
|
|
354
354
|
if (!this.running) return;
|
|
355
|
-
let e,
|
|
356
|
-
for (this.timerMs += t, t > 1e3 && (this.timerMs = 0), t /= 1e3, e = 0,
|
|
355
|
+
let e, n, i, s, o;
|
|
356
|
+
for (this.timerMs += t, t > 1e3 && (this.timerMs = 0), t /= 1e3, e = 0, i = this.objectsUpdate.length; e < i; e++)
|
|
357
357
|
o = this.objectsUpdate[e], o.updateMatrix(), o.parent === null ? o.matrixWorld.copy(o.matrix) : o.matrixWorld.multiplyMatrices(o.parent.matrixWorld, o.matrix), o.matrixWorldNeedsUpdate = !1;
|
|
358
|
-
for (e = 0,
|
|
359
|
-
if (o = this.data[e], k.copy(o.vWorld),
|
|
360
|
-
for (
|
|
361
|
-
m = o.children[
|
|
358
|
+
for (e = 0, i = this.data.length; e < i; e++) {
|
|
359
|
+
if (o = this.data[e], k.copy(o.vWorld), ie.copy(o.boneParent.matrixWorld), oe.copy(ie).invert(), o.vWorld.setFromMatrixPosition(ie), k.applyMatrix4(oe), k.length() > 0.5 && (console.info("Info: Unrealistic jump of " + k.length().toFixed(2) + " meters."), k.setLength(0.5)), k.applyQuaternion(o.bone.quaternion), L[0] = k.x, L[1] = k.y, L[2] = -k.z, L[3] = k.length() / 3, o.children)
|
|
360
|
+
for (n = 0, s = o.children.length; n < s; n++)
|
|
361
|
+
m = o.children[n], L[0] -= m.v[0] * t / 3, L[1] -= m.v[1] * t / 3, L[2] += m.v[2] * t / 3, L[3] -= m.v[3] * t / 3;
|
|
362
362
|
if (m = this.opt.sensitivityFactor, L[0] *= o.ext * m, L[1] *= o.ext * m, L[2] *= o.ext * m, L[3] *= o.ext * m, o.isX && (m = L[0] / t, o.ea[0] = (m - o.ev[0]) / t, o.ev[0] = m, o.a[0] = -o.k[0] * o.p[0] - o.c[0] * o.v[0] - o.ea[0], o.p[0] += o.v[0] * t + o.a[0] * t * t / 2 + L[0], m = o.v[0] + o.a[0] * t / 2, m = -o.k[0] * o.p[0] - o.c[0] * m - o.ea[0], o.v[0] = o.v[0] + (m + o.a[0]) * t / 2), o.isY && (m = L[1] / t, o.ea[1] = (m - o.ev[1]) / t, o.ev[1] = m, o.a[1] = -o.k[1] * o.p[1] - o.c[1] * o.v[1] - o.ea[1], o.p[1] += o.v[1] * t + o.a[1] * t * t / 2 + L[1], m = o.v[1] + o.a[1] * t / 2, m = -o.k[1] * o.p[1] - o.c[1] * m - o.ea[1], o.v[1] = o.v[1] + (m + o.a[1]) * t / 2), o.isZ && (m = L[2] / t, o.ea[2] = (m - o.ev[2]) / t, o.ev[2] = m, o.a[2] = -o.k[2] * o.p[2] - o.c[2] * o.v[2] - o.ea[2], o.p[2] += o.v[2] * t + o.a[2] * t * t / 2 + L[2], m = o.v[2] + o.a[2] * t / 2, m = -o.k[2] * o.p[2] - o.c[2] * m - o.ea[2], o.v[2] = o.v[2] + (m + o.a[2]) * t / 2), o.isT && (m = L[3] / t, o.ea[3] = (m - o.ev[3]) / t, o.ev[3] = m, o.a[3] = -o.k[3] * o.p[3] - o.c[3] * o.v[3] - o.ea[3], o.p[3] += o.v[3] * t + o.a[3] * t * t / 2 + L[3], m = o.v[3] + o.a[3] * t / 2, m = -o.k[3] * o.p[3] - o.c[3] * m - o.ea[3], o.v[3] = o.v[3] + (m + o.a[3]) * t / 2), this.timerMs < this.opt.warmupMs && (o.v[0] *= 1e-4, o.p[0] *= 1e-4, o.v[1] *= 1e-4, o.p[1] *= 1e-4, o.v[2] *= 1e-4, o.p[2] *= 1e-4, o.v[3] *= 1e-4, o.p[3] *= 1e-4), L[0] = o.p[0], L[1] = o.p[1], L[2] = o.p[2], L[3] = o.p[3], m = this.opt.movementFactor, L[0] *= m, L[1] *= m, L[2] *= m, L[3] *= m, o.dl && (m = o.dl, L[0] += m[0], L[1] += m[1], L[2] += m[2]), o.dw && (m = o.dw, k.set(
|
|
363
363
|
o.vBasis.x + L[0],
|
|
364
364
|
o.vBasis.y + L[1],
|
|
365
365
|
o.vBasis.z + L[2]
|
|
366
|
-
), k.applyMatrix4(
|
|
366
|
+
), k.applyMatrix4(ie), k.x += m[0], k.y += m[1], k.z += m[2], k.applyMatrix4(oe), L[0] += k.x - o.vBasis.x, L[1] += k.y - o.vBasis.y, L[2] += k.z - o.vBasis.z), o.limits && this.opt.isLimits && (m = o.limits, m[0] && (m[0][0] !== null && L[0] < m[0][0] && (L[0] = m[0][0]), m[0][1] !== null && L[0] > m[0][1] && (L[0] = m[0][1])), m[1] && (m[1][0] !== null && L[1] < m[1][0] && (L[1] = m[1][0]), m[1][1] !== null && L[1] > m[1][1] && (L[1] = m[1][1])), m[2] && (m[2][0] !== null && L[2] < m[2][0] && (L[2] = m[2][0]), m[2][1] !== null && L[2] > m[2][1] && (L[2] = m[2][1])), m[3] && (m[3][0] !== null && L[3] < m[3][0] && (L[3] = m[3][0]), m[3][1] !== null && L[3] > m[3][1] && (L[3] = m[3][1]))), o.isPoint)
|
|
367
367
|
o.bone.position.set(
|
|
368
368
|
o.vBasis.x + L[0],
|
|
369
369
|
o.vBasis.y + L[1],
|
|
370
370
|
o.vBasis.z - L[2]
|
|
371
371
|
);
|
|
372
|
-
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(k,
|
|
373
|
-
for (
|
|
374
|
-
m = o.excludes[
|
|
372
|
+
else if (o.boneParent.quaternion.copy(o.qBasis), o.pivot && this.opt.isPivots && (o.boneParent.updateWorldMatrix(!1, !1), o.boneParent.matrixWorld.decompose(k, Q, j), k.copy(ve).applyQuaternion(Q).setY(0).normalize(), Q.premultiply(Ce.setFromUnitVectors(ve, k).invert()).normalize(), o.boneParent.quaternion.multiply(Q.invert()), o.boneParent.quaternion.multiply(o.qWorldInverseYaw)), o.isZ && (m = Math.atan(L[0] / o.l), Q.setFromAxisAngle(Qe, -m), o.boneParent.quaternion.multiply(Q)), o.isY && (m = o.l / 3, m = m * Math.tanh(L[1] / m), o.bone.position.setLength(o.l + m)), o.isX && (m = Math.atan(L[2] / o.l), Q.setFromAxisAngle(Ye, -m), o.boneParent.quaternion.multiply(Q)), o.isT && (m = 1.5 * Math.tanh(L[3] * 1.5), Q.setFromAxisAngle(je, -m), o.boneParent.quaternion.multiply(Q)), o.boneParent.updateWorldMatrix(!1, !0), o.excludes && this.opt.isExcludes)
|
|
373
|
+
for (n = 0, s = o.excludes.length; n < s; n++)
|
|
374
|
+
m = o.excludes[n], j.set(0, 0, 0), m.deltaLocal && (j.x += m.deltaLocal[0], j.y += m.deltaLocal[1], j.z += m.deltaLocal[2]), j.applyMatrix4(m.bone.matrixWorld), oe.copy(o.boneParent.matrixWorld).invert(), j.applyMatrix4(oe), k.copy(o.bone.position), !(k.distanceToSquared(j) >= m.radiusSq) && (ee = k.length(), J = j.length(), !(J > m.radius + ee) && (J < Math.abs(m.radius - ee) || (J = (J * J + ee * ee - m.radiusSq) / (2 * J), j.normalize(), be.copy(j).multiplyScalar(J), J = Math.sqrt(ee * ee - J * J), k.subVectors(k, be).projectOnPlane(j).normalize().multiplyScalar(J), xe.subVectors(o.vBasis, be).projectOnPlane(j).normalize(), ee = xe.dot(k), ee < 0 && (ee = Math.sqrt(J * J - ee * ee), xe.multiplyScalar(ee), k.add(xe)), k.add(be).normalize(), j.copy(o.bone.position).normalize(), Q.setFromUnitVectors(j, k), o.boneParent.quaternion.premultiply(Q), o.boneParent.updateWorldMatrix(!1, !0))));
|
|
375
375
|
}
|
|
376
376
|
this.helpers.isActive && this.updateHelpers();
|
|
377
377
|
}
|
|
@@ -383,17 +383,17 @@ class je {
|
|
|
383
383
|
*/
|
|
384
384
|
showHelpers(t) {
|
|
385
385
|
if (this.hideHelpers(), this.helpers.isShowAll = t === void 0 ? this.helpers.isShowAll : t === !0, m = this.helpers, this.data.forEach((e) => {
|
|
386
|
-
(this.helpers.isShowAll || e.helper === !0) && (m.points.bones.push(e.bone), m.points.pivots.push(e.pivot), e.type !== 0 && m.lines.bones.push(e.bone), e.excludes && e.excludes.forEach((
|
|
387
|
-
let
|
|
386
|
+
(this.helpers.isShowAll || e.helper === !0) && (m.points.bones.push(e.bone), m.points.pivots.push(e.pivot), e.type !== 0 && m.lines.bones.push(e.bone), e.excludes && e.excludes.forEach((n) => {
|
|
387
|
+
let i = !1;
|
|
388
388
|
for (let s = 0; s < m.excludes.bones.length; s++)
|
|
389
|
-
if (m.excludes.bones[s] ===
|
|
390
|
-
|
|
389
|
+
if (m.excludes.bones[s] === n.bone && m.excludes.radii[s] === n.radius && !(m.excludes.deltaLocals[s] === null && n.deltaLocal !== null) && !(m.excludes.deltaLocals[s] !== null && n.deltaLocal === null) && !(m.excludes.deltaLocals[s] !== null && m.excludes.deltaLocals[s].some((o, l) => o !== n.deltaLocal[l]))) {
|
|
390
|
+
i = !0;
|
|
391
391
|
break;
|
|
392
392
|
}
|
|
393
|
-
|
|
393
|
+
i || (m.excludes.bones.push(n.bone), m.excludes.radii.push(n.radius), m.excludes.deltaLocals.push(n.deltaLocal ? [...n.deltaLocal] : null), m.excludes.objects.push(null));
|
|
394
394
|
}));
|
|
395
|
-
}), m = this.helpers.excludes, this.opt.isExcludes && m.bones.length && m.bones.forEach((e,
|
|
396
|
-
const
|
|
395
|
+
}), m = this.helpers.excludes, this.opt.isExcludes && m.bones.length && m.bones.forEach((e, n) => {
|
|
396
|
+
const i = new f.SphereGeometry(m.radii[n], 6, 6), s = new f.MeshBasicMaterial({
|
|
397
397
|
depthTest: !1,
|
|
398
398
|
depthWrite: !1,
|
|
399
399
|
toneMapped: !1,
|
|
@@ -401,16 +401,16 @@ class je {
|
|
|
401
401
|
wireframe: !0,
|
|
402
402
|
color: this.opt.helperExcludesColor
|
|
403
403
|
});
|
|
404
|
-
m.objects[
|
|
405
|
-
m.deltaLocals[
|
|
406
|
-
m.deltaLocals[
|
|
407
|
-
m.deltaLocals[
|
|
404
|
+
m.objects[n] = new f.Mesh(i, s), m.objects[n].renderOrder = 997, e.add(m.objects[n]), m.deltaLocals[n] && m.objects[n].position.set(
|
|
405
|
+
m.deltaLocals[n][0],
|
|
406
|
+
m.deltaLocals[n][1],
|
|
407
|
+
m.deltaLocals[n][2]
|
|
408
408
|
);
|
|
409
409
|
}), m = this.helpers.points, m.bones.length) {
|
|
410
410
|
this.helpers.isActive = !0;
|
|
411
|
-
const e = new f.BufferGeometry(),
|
|
412
|
-
e.setAttribute("position", new f.Float32BufferAttribute(
|
|
413
|
-
const
|
|
411
|
+
const e = new f.BufferGeometry(), n = m.bones.map((u) => [0, 0, 0]).flat();
|
|
412
|
+
e.setAttribute("position", new f.Float32BufferAttribute(n, 3));
|
|
413
|
+
const i = new f.Color(this.opt.helperBoneColor1), s = new f.Color(this.opt.helperBoneColor2), o = m.pivots.map((u) => u && this.opt.isPivots ? [s.r, s.g, s.b] : [i.r, i.g, i.b]).flat();
|
|
414
414
|
e.setAttribute("color", new f.Float32BufferAttribute(o, 3));
|
|
415
415
|
const l = new f.PointsMaterial({
|
|
416
416
|
depthTest: !1,
|
|
@@ -423,9 +423,9 @@ class je {
|
|
|
423
423
|
m.object = new f.Points(e, l), m.object.renderOrder = 998, m.object.matrix = this.armature.matrixWorld, m.object.matrixAutoUpdate = !1, this.scene.add(m.object);
|
|
424
424
|
}
|
|
425
425
|
if (m = this.helpers.lines, m.bones.length) {
|
|
426
|
-
const e = new f.BufferGeometry(),
|
|
427
|
-
e.setAttribute("position", new f.Float32BufferAttribute(
|
|
428
|
-
const
|
|
426
|
+
const e = new f.BufferGeometry(), n = m.bones.map((u) => [0, 0, 0, 0, 0, 0]).flat();
|
|
427
|
+
e.setAttribute("position", new f.Float32BufferAttribute(n, 3));
|
|
428
|
+
const i = new f.Color(this.opt.helperLinkColor1), s = new f.Color(this.opt.helperLinkColor2), o = m.bones.map((u) => [i.r, i.g, i.b, s.r, s.g, s.b]).flat();
|
|
429
429
|
e.setAttribute("color", new f.Float32BufferAttribute(o, 3));
|
|
430
430
|
const l = new f.LineBasicMaterial({
|
|
431
431
|
vertexColors: !0,
|
|
@@ -442,17 +442,17 @@ class je {
|
|
|
442
442
|
*/
|
|
443
443
|
updateHelpers() {
|
|
444
444
|
if (m = this.helpers.points, m.bones.length) {
|
|
445
|
-
|
|
445
|
+
oe.copy(this.armature.matrixWorld).invert();
|
|
446
446
|
const t = m.object.geometry.getAttribute("position");
|
|
447
|
-
for (let e = 0,
|
|
448
|
-
|
|
447
|
+
for (let e = 0, n = m.bones.length; e < n; e++)
|
|
448
|
+
ie.multiplyMatrices(oe, m.bones[e].matrixWorld), k.setFromMatrixPosition(ie), t.setXYZ(e, k.x, k.y, k.z);
|
|
449
449
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
450
450
|
}
|
|
451
451
|
if (m = this.helpers.lines, m.bones.length) {
|
|
452
|
-
|
|
452
|
+
oe.copy(this.armature.matrixWorld).invert();
|
|
453
453
|
const t = m.object.geometry.getAttribute("position");
|
|
454
|
-
for (let e = 0,
|
|
455
|
-
|
|
454
|
+
for (let e = 0, n = 0, i = m.bones.length; e < i; e++, n += 2)
|
|
455
|
+
ie.multiplyMatrices(oe, m.bones[e].matrixWorld), k.setFromMatrixPosition(ie), t.setXYZ(n, k.x, k.y, k.z), ie.multiplyMatrices(oe, m.bones[e].parent.matrixWorld), k.setFromMatrixPosition(ie), t.setXYZ(n + 1, k.x, k.y, k.z);
|
|
456
456
|
t.needsUpdate = !0, m.object.updateMatrixWorld();
|
|
457
457
|
}
|
|
458
458
|
}
|
|
@@ -478,8 +478,8 @@ class je {
|
|
|
478
478
|
stop() {
|
|
479
479
|
this.running = !1, this.hideHelpers();
|
|
480
480
|
for (let t = 0, e = this.data.length; t < e; t++) {
|
|
481
|
-
const
|
|
482
|
-
|
|
481
|
+
const n = this.data[t];
|
|
482
|
+
n.bone.position.copy(n.vBasis), n.boneParent.quaternion.copy(n.qBasis);
|
|
483
483
|
}
|
|
484
484
|
}
|
|
485
485
|
/**
|
|
@@ -489,7 +489,7 @@ class je {
|
|
|
489
489
|
this.stop(), this.scene = null, this.armature = null, this.config = [], this.data = [], this.dict = {}, this.objectsUpdate = [], this.timerMs = 0;
|
|
490
490
|
}
|
|
491
491
|
}
|
|
492
|
-
class
|
|
492
|
+
class _e {
|
|
493
493
|
constructor(t) {
|
|
494
494
|
this.audioContext = t, this.analyzer = null, this.dataArray = null, this.bufferLength = 0;
|
|
495
495
|
}
|
|
@@ -500,8 +500,8 @@ class Qe {
|
|
|
500
500
|
* @returns {Object} Timing data with visemes and precise timing
|
|
501
501
|
*/
|
|
502
502
|
async analyzeAudio(t, e) {
|
|
503
|
-
const
|
|
504
|
-
return this.generateTimingData(o, e,
|
|
503
|
+
const n = t.sampleRate, i = t.duration, s = t.getChannelData(0), o = this.extractAudioFeatures(s, n);
|
|
504
|
+
return this.generateTimingData(o, e, i);
|
|
505
505
|
}
|
|
506
506
|
/**
|
|
507
507
|
* Extract audio features from the audio data
|
|
@@ -510,25 +510,25 @@ class Qe {
|
|
|
510
510
|
* @returns {Object} Extracted audio features
|
|
511
511
|
*/
|
|
512
512
|
extractAudioFeatures(t, e) {
|
|
513
|
-
const
|
|
513
|
+
const n = {
|
|
514
514
|
energy: [],
|
|
515
515
|
spectralCentroid: [],
|
|
516
516
|
zeroCrossingRate: [],
|
|
517
517
|
mfcc: [],
|
|
518
518
|
onsets: [],
|
|
519
519
|
phonemeBoundaries: []
|
|
520
|
-
},
|
|
520
|
+
}, i = 1024, s = 512, o = Math.floor((t.length - i) / s) + 1;
|
|
521
521
|
for (let l = 0; l < o; l++) {
|
|
522
|
-
const u = l * s, a = Math.min(u +
|
|
523
|
-
|
|
522
|
+
const u = l * s, a = Math.min(u + i, t.length), h = t.slice(u, a), r = this.calculateEnergy(h);
|
|
523
|
+
n.energy.push(r);
|
|
524
524
|
const c = this.calculateSpectralCentroid(h);
|
|
525
|
-
|
|
525
|
+
n.spectralCentroid.push(c);
|
|
526
526
|
const d = this.calculateZeroCrossingRate(h);
|
|
527
|
-
|
|
527
|
+
n.zeroCrossingRate.push(d);
|
|
528
528
|
const g = this.calculateMFCC(h);
|
|
529
|
-
|
|
529
|
+
n.mfcc.push(g);
|
|
530
530
|
}
|
|
531
|
-
return
|
|
531
|
+
return n.onsets = this.detectOnsets(n.energy), n.phonemeBoundaries = this.detectPhonemeBoundaries(n), n;
|
|
532
532
|
}
|
|
533
533
|
/**
|
|
534
534
|
* Calculate energy of an audio frame
|
|
@@ -537,8 +537,8 @@ class Qe {
|
|
|
537
537
|
*/
|
|
538
538
|
calculateEnergy(t) {
|
|
539
539
|
let e = 0;
|
|
540
|
-
for (let
|
|
541
|
-
e += t[
|
|
540
|
+
for (let n = 0; n < t.length; n++)
|
|
541
|
+
e += t[n] * t[n];
|
|
542
542
|
return e / t.length;
|
|
543
543
|
}
|
|
544
544
|
/**
|
|
@@ -548,12 +548,12 @@ class Qe {
|
|
|
548
548
|
*/
|
|
549
549
|
calculateSpectralCentroid(t) {
|
|
550
550
|
const e = this.fft(t);
|
|
551
|
-
let
|
|
551
|
+
let n = 0, i = 0;
|
|
552
552
|
for (let s = 0; s < e.length / 2; s++) {
|
|
553
553
|
const o = Math.sqrt(e[s * 2] * e[s * 2] + e[s * 2 + 1] * e[s * 2 + 1]);
|
|
554
|
-
|
|
554
|
+
n += s * o, i += o;
|
|
555
555
|
}
|
|
556
|
-
return
|
|
556
|
+
return i > 0 ? n / i : 0;
|
|
557
557
|
}
|
|
558
558
|
/**
|
|
559
559
|
* Calculate zero crossing rate
|
|
@@ -562,8 +562,8 @@ class Qe {
|
|
|
562
562
|
*/
|
|
563
563
|
calculateZeroCrossingRate(t) {
|
|
564
564
|
let e = 0;
|
|
565
|
-
for (let
|
|
566
|
-
t[
|
|
565
|
+
for (let n = 1; n < t.length; n++)
|
|
566
|
+
t[n] >= 0 != t[n - 1] >= 0 && e++;
|
|
567
567
|
return e / (t.length - 1);
|
|
568
568
|
}
|
|
569
569
|
/**
|
|
@@ -572,16 +572,16 @@ class Qe {
|
|
|
572
572
|
* @returns {Array} MFCC coefficients
|
|
573
573
|
*/
|
|
574
574
|
calculateMFCC(t) {
|
|
575
|
-
const e = this.fft(t),
|
|
576
|
-
for (let
|
|
575
|
+
const e = this.fft(t), n = [];
|
|
576
|
+
for (let i = 0; i < 13; i++) {
|
|
577
577
|
let s = 0;
|
|
578
578
|
for (let o = 0; o < e.length / 2; o++) {
|
|
579
579
|
const l = Math.sqrt(e[o * 2] * e[o * 2] + e[o * 2 + 1] * e[o * 2 + 1]);
|
|
580
|
-
s += l * Math.cos(Math.PI *
|
|
580
|
+
s += l * Math.cos(Math.PI * i * (o + 0.5) / (e.length / 2));
|
|
581
581
|
}
|
|
582
|
-
|
|
582
|
+
n.push(s);
|
|
583
583
|
}
|
|
584
|
-
return
|
|
584
|
+
return n;
|
|
585
585
|
}
|
|
586
586
|
/**
|
|
587
587
|
* Simple FFT implementation
|
|
@@ -589,31 +589,31 @@ class Qe {
|
|
|
589
589
|
* @returns {Float32Array} FFT result
|
|
590
590
|
*/
|
|
591
591
|
fft(t) {
|
|
592
|
-
const e = t.length,
|
|
593
|
-
for (let
|
|
594
|
-
i
|
|
595
|
-
for (let
|
|
592
|
+
const e = t.length, n = new Float32Array(e * 2);
|
|
593
|
+
for (let i = 0; i < e; i++)
|
|
594
|
+
n[i * 2] = t[i], n[i * 2 + 1] = 0;
|
|
595
|
+
for (let i = 1, s = 0; i < e; i++) {
|
|
596
596
|
let o = e >> 1;
|
|
597
597
|
for (; s & o; )
|
|
598
598
|
s ^= o, o >>= 1;
|
|
599
|
-
if (s ^= o,
|
|
600
|
-
const l = i
|
|
601
|
-
i
|
|
599
|
+
if (s ^= o, i < s) {
|
|
600
|
+
const l = n[i * 2], u = n[i * 2 + 1];
|
|
601
|
+
n[i * 2] = n[s * 2], n[i * 2 + 1] = n[s * 2 + 1], n[s * 2] = l, n[s * 2 + 1] = u;
|
|
602
602
|
}
|
|
603
603
|
}
|
|
604
|
-
for (let
|
|
605
|
-
const s = -2 * Math.PI /
|
|
606
|
-
for (let u = 0; u < e; u +=
|
|
604
|
+
for (let i = 2; i <= e; i <<= 1) {
|
|
605
|
+
const s = -2 * Math.PI / i, o = Math.cos(s), l = Math.sin(s);
|
|
606
|
+
for (let u = 0; u < e; u += i) {
|
|
607
607
|
let a = 1, h = 0;
|
|
608
|
-
for (let r = 0; r <
|
|
609
|
-
const c =
|
|
610
|
-
|
|
608
|
+
for (let r = 0; r < i / 2; r++) {
|
|
609
|
+
const c = n[(u + r) * 2], d = n[(u + r) * 2 + 1], g = n[(u + r + i / 2) * 2] * a - n[(u + r + i / 2) * 2 + 1] * h, y = n[(u + r + i / 2) * 2] * h + n[(u + r + i / 2) * 2 + 1] * a;
|
|
610
|
+
n[(u + r) * 2] = c + g, n[(u + r) * 2 + 1] = d + y, n[(u + r + i / 2) * 2] = c - g, n[(u + r + i / 2) * 2 + 1] = d - y;
|
|
611
611
|
const x = a * o - h * l, I = a * l + h * o;
|
|
612
612
|
a = x, h = I;
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
}
|
|
616
|
-
return
|
|
616
|
+
return n;
|
|
617
617
|
}
|
|
618
618
|
/**
|
|
619
619
|
* Detect onsets in the audio
|
|
@@ -635,9 +635,9 @@ class Qe {
|
|
|
635
635
|
* @returns {Array} Phoneme boundary times
|
|
636
636
|
*/
|
|
637
637
|
detectPhonemeBoundaries(t) {
|
|
638
|
-
const e = [], { energy:
|
|
639
|
-
for (let o = 1; o <
|
|
640
|
-
const l = o * 0.023, u = Math.abs(
|
|
638
|
+
const e = [], { energy: n, spectralCentroid: i, zeroCrossingRate: s } = t;
|
|
639
|
+
for (let o = 1; o < n.length; o++) {
|
|
640
|
+
const l = o * 0.023, u = Math.abs(n[o] - n[o - 1]), a = Math.abs(i[o] - i[o - 1]), h = Math.abs(s[o] - s[o - 1]);
|
|
641
641
|
u + a * 0.1 + h * 0.5 > 0.2 && e.push(l);
|
|
642
642
|
}
|
|
643
643
|
return e;
|
|
@@ -649,13 +649,13 @@ class Qe {
|
|
|
649
649
|
* @param {number} duration - Audio duration in seconds
|
|
650
650
|
* @returns {Object} Precise timing data
|
|
651
651
|
*/
|
|
652
|
-
generateTimingData(t, e,
|
|
653
|
-
const
|
|
652
|
+
generateTimingData(t, e, n) {
|
|
653
|
+
const i = e.toLowerCase().split(/\s+/);
|
|
654
654
|
t.phonemeBoundaries, t.onsets;
|
|
655
655
|
const s = [];
|
|
656
656
|
let o = 0;
|
|
657
|
-
for (let u = 0; u <
|
|
658
|
-
const a =
|
|
657
|
+
for (let u = 0; u < i.length; u++) {
|
|
658
|
+
const a = i[u], h = this.estimateWordDuration(a, n / i.length);
|
|
659
659
|
s.push({
|
|
660
660
|
word: a,
|
|
661
661
|
startTime: o,
|
|
@@ -663,11 +663,11 @@ class Qe {
|
|
|
663
663
|
duration: h
|
|
664
664
|
}), o += h;
|
|
665
665
|
}
|
|
666
|
-
const l = this.generateVisemeTimings(t, e,
|
|
666
|
+
const l = this.generateVisemeTimings(t, e, n);
|
|
667
667
|
return {
|
|
668
668
|
words: s,
|
|
669
669
|
visemes: l,
|
|
670
|
-
duration:
|
|
670
|
+
duration: n,
|
|
671
671
|
features: t
|
|
672
672
|
};
|
|
673
673
|
}
|
|
@@ -678,8 +678,8 @@ class Qe {
|
|
|
678
678
|
* @returns {number} Estimated duration
|
|
679
679
|
*/
|
|
680
680
|
estimateWordDuration(t, e) {
|
|
681
|
-
const
|
|
682
|
-
return e *
|
|
681
|
+
const n = Math.max(0.5, Math.min(2, t.length / 5)), i = this.getWordComplexity(t);
|
|
682
|
+
return e * n * i;
|
|
683
683
|
}
|
|
684
684
|
/**
|
|
685
685
|
* Get word complexity factor
|
|
@@ -687,8 +687,8 @@ class Qe {
|
|
|
687
687
|
* @returns {number} Complexity factor
|
|
688
688
|
*/
|
|
689
689
|
getWordComplexity(t) {
|
|
690
|
-
const e = (t.match(/[bcdfghjklmnpqrstvwxyz]{2,}/g) || []).length,
|
|
691
|
-
return 1 + e * 0.2 +
|
|
690
|
+
const e = (t.match(/[bcdfghjklmnpqrstvwxyz]{2,}/g) || []).length, n = (t.match(/[aeiou]{2,}/g) || []).length;
|
|
691
|
+
return 1 + e * 0.2 + n * 0.1;
|
|
692
692
|
}
|
|
693
693
|
/**
|
|
694
694
|
* Generate viseme timings based on audio analysis
|
|
@@ -697,14 +697,14 @@ class Qe {
|
|
|
697
697
|
* @param {number} duration - Audio duration
|
|
698
698
|
* @returns {Array} Viseme timing data
|
|
699
699
|
*/
|
|
700
|
-
generateVisemeTimings(t, e,
|
|
701
|
-
const
|
|
700
|
+
generateVisemeTimings(t, e, n) {
|
|
701
|
+
const i = [], s = t.phonemeBoundaries;
|
|
702
702
|
t.onsets;
|
|
703
703
|
const o = this.textToVisemes(e);
|
|
704
704
|
let l = 0, u = 0;
|
|
705
705
|
for (let a = 0; a < s.length && l < o.length; a++) {
|
|
706
706
|
const h = s[a], r = o[l], c = t.energy[Math.floor(h / 0.023)] || 0, d = this.calculateVisemeDuration(r, c);
|
|
707
|
-
|
|
707
|
+
i.push({
|
|
708
708
|
viseme: r,
|
|
709
709
|
startTime: u,
|
|
710
710
|
endTime: u + d,
|
|
@@ -715,7 +715,7 @@ class Qe {
|
|
|
715
715
|
}
|
|
716
716
|
for (; l < o.length; ) {
|
|
717
717
|
const a = o[l], h = this.calculateVisemeDuration(a, 0.5);
|
|
718
|
-
|
|
718
|
+
i.push({
|
|
719
719
|
viseme: a,
|
|
720
720
|
startTime: u,
|
|
721
721
|
endTime: u + h,
|
|
@@ -723,7 +723,7 @@ class Qe {
|
|
|
723
723
|
intensity: 0.6
|
|
724
724
|
}), u += h, l++;
|
|
725
725
|
}
|
|
726
|
-
return
|
|
726
|
+
return i;
|
|
727
727
|
}
|
|
728
728
|
/**
|
|
729
729
|
* Convert text to visemes using phonetic analysis
|
|
@@ -770,25 +770,25 @@ class Qe {
|
|
|
770
770
|
w: "RR",
|
|
771
771
|
y: "I",
|
|
772
772
|
h: "kk"
|
|
773
|
-
},
|
|
774
|
-
for (const s of
|
|
773
|
+
}, n = [], i = t.toLowerCase().replace(/[^a-z\s]/g, "").split(/\s+/);
|
|
774
|
+
for (const s of i) {
|
|
775
775
|
let o = 0;
|
|
776
776
|
for (; o < s.length; ) {
|
|
777
777
|
let l = !1;
|
|
778
778
|
for (let u = 3; u >= 2; u--) {
|
|
779
779
|
const a = s.substr(o, u);
|
|
780
780
|
if (e[a]) {
|
|
781
|
-
|
|
781
|
+
n.push(e[a]), o += u, l = !0;
|
|
782
782
|
break;
|
|
783
783
|
}
|
|
784
784
|
}
|
|
785
785
|
if (!l) {
|
|
786
786
|
const u = s[o];
|
|
787
|
-
e[u] &&
|
|
787
|
+
e[u] && n.push(e[u]), o++;
|
|
788
788
|
}
|
|
789
789
|
}
|
|
790
790
|
}
|
|
791
|
-
return
|
|
791
|
+
return n;
|
|
792
792
|
}
|
|
793
793
|
/**
|
|
794
794
|
* Calculate viseme duration based on viseme type and audio energy
|
|
@@ -797,7 +797,7 @@ class Qe {
|
|
|
797
797
|
* @returns {number} Duration in seconds
|
|
798
798
|
*/
|
|
799
799
|
calculateVisemeDuration(t, e) {
|
|
800
|
-
const
|
|
800
|
+
const i = {
|
|
801
801
|
aa: 0.15,
|
|
802
802
|
E: 0.12,
|
|
803
803
|
I: 0.1,
|
|
@@ -811,10 +811,10 @@ class Qe {
|
|
|
811
811
|
nn: 0.1,
|
|
812
812
|
RR: 0.11
|
|
813
813
|
}[t] || 0.1, s = 0.5 + e * 0.5;
|
|
814
|
-
return
|
|
814
|
+
return i * s;
|
|
815
815
|
}
|
|
816
816
|
}
|
|
817
|
-
class
|
|
817
|
+
class Ke {
|
|
818
818
|
/**
|
|
819
819
|
* @constructor
|
|
820
820
|
*/
|
|
@@ -1205,8 +1205,8 @@ class qe {
|
|
|
1205
1205
|
// Start/end of the word
|
|
1206
1206
|
};
|
|
1207
1207
|
Object.keys(this.rules).forEach((e) => {
|
|
1208
|
-
this.rules[e] = this.rules[e].map((
|
|
1209
|
-
const
|
|
1208
|
+
this.rules[e] = this.rules[e].map((n) => {
|
|
1209
|
+
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), u = n.substring(i + 1, s), a = n.substring(s + 1, o), h = n.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
1210
1210
|
let c = "";
|
|
1211
1211
|
c += [...l].map((g) => t[g] || g).join("");
|
|
1212
1212
|
const d = [...u];
|
|
@@ -1278,13 +1278,13 @@ class qe {
|
|
|
1278
1278
|
convert_digit_by_digit(t) {
|
|
1279
1279
|
t = String(t).split("");
|
|
1280
1280
|
let e = "";
|
|
1281
|
-
for (let
|
|
1282
|
-
e += this.digits[t[
|
|
1281
|
+
for (let n = 0; n < t.length; n++)
|
|
1282
|
+
e += this.digits[t[n]] + " ";
|
|
1283
1283
|
return e = e.substring(0, e.length - 1), e;
|
|
1284
1284
|
}
|
|
1285
1285
|
convert_sets_of_two(t) {
|
|
1286
|
-
let e = String(t).substring(0, 2),
|
|
1287
|
-
return
|
|
1286
|
+
let e = String(t).substring(0, 2), n = String(t).substring(2, 4), i = this.convert_tens(e);
|
|
1287
|
+
return i += " " + this.convert_tens(n), i;
|
|
1288
1288
|
}
|
|
1289
1289
|
convert_millions(t) {
|
|
1290
1290
|
return t >= 1e6 ? this.convert_millions(Math.floor(t / 1e6)) + " million " + this.convert_thousands(t % 1e6) : this.convert_thousands(t);
|
|
@@ -1306,14 +1306,14 @@ class qe {
|
|
|
1306
1306
|
* @return {string} String
|
|
1307
1307
|
*/
|
|
1308
1308
|
convertNumberToWords(t, e = !1) {
|
|
1309
|
-
const
|
|
1309
|
+
const n = parseFloat(t);
|
|
1310
1310
|
if (t == "0")
|
|
1311
1311
|
return "zero";
|
|
1312
1312
|
if (t < 0)
|
|
1313
1313
|
return " minus " + this.convertNumberToWords(Math.abs(t).toString(), e).trim();
|
|
1314
|
-
if (
|
|
1315
|
-
const
|
|
1316
|
-
return this.convertNumberToWords(
|
|
1314
|
+
if (n && !Number.isInteger(n)) {
|
|
1315
|
+
const i = n.toString().split(".");
|
|
1316
|
+
return this.convertNumberToWords(i[0], e).trim() + " point " + this.convert_digit_by_digit(i[1]).trim();
|
|
1317
1317
|
} else return t.toString().startsWith("0") ? this.convert_digit_by_digit(t).trim() : !e && (t < 1e3 && t > 99 && t % 100 !== 0 || t > 1e4 && t < 1e6) ? this.convert_digit_by_digit(t).trim() : !e && (t > 1e3 && t < 2e3 || t > 2009 && t < 3e3) ? t % 100 != 0 ? this.convert_sets_of_two(t).trim() : this.convert_tens(t.toString().substring(0, 2)).trim() + " hundred" : this.convert_millions(t).trim();
|
|
1318
1318
|
}
|
|
1319
1319
|
/**
|
|
@@ -1323,7 +1323,7 @@ class qe {
|
|
|
1323
1323
|
* @return {string} Normalized text
|
|
1324
1324
|
*/
|
|
1325
1325
|
convertDecade(t) {
|
|
1326
|
-
const e = parseInt(t),
|
|
1326
|
+
const e = parseInt(t), n = !isNaN(e) && t.length === 2, i = !isNaN(e) && t.length > 2 && e > 0 && e <= 3e3, s = i && e % 1e3 === 0 ? Math.floor(e / 1e3) : null, o = i && !s ? Math.floor(e / 100) : null, l = n || i ? Math.floor(e % 100 / 10) * 10 : null;
|
|
1327
1327
|
let u = [];
|
|
1328
1328
|
return s ? u.push(this.convertNumberToWords(s).trim(), "thousands") : (o && u.push(this.convertNumberToWords(o).trim()), l ? u.push(this.decades[l] || this.convertNumberToWords(l).trim() + "s") : o ? u.push("hundreds") : u.push(t)), u.join(" ");
|
|
1329
1329
|
}
|
|
@@ -1336,9 +1336,9 @@ class qe {
|
|
|
1336
1336
|
convertOrdinal(t) {
|
|
1337
1337
|
if (this.ordinals.hasOwnProperty(t))
|
|
1338
1338
|
return this.ordinals[t];
|
|
1339
|
-
const e = Math.floor(t / 100),
|
|
1339
|
+
const e = Math.floor(t / 100), n = Math.floor(t % 100 / 10) * 10, i = t % 10;
|
|
1340
1340
|
let s = [];
|
|
1341
|
-
return e && (s.push(this.convertNumberToWords(e).trim()),
|
|
1341
|
+
return e && (s.push(this.convertNumberToWords(e).trim()), n || i ? s.push("hundred") : s.push("hundredth")), n && (i ? s.push(this.convertNumberToWords(n).trim()) : s.push(this.ordinals[n])), i && s.push(this.ordinals[i]), s.join(" ");
|
|
1342
1342
|
}
|
|
1343
1343
|
/**
|
|
1344
1344
|
* Preprocess text:
|
|
@@ -1350,18 +1350,18 @@ class qe {
|
|
|
1350
1350
|
*/
|
|
1351
1351
|
preProcessText(t) {
|
|
1352
1352
|
let e = t.replace('/[#_*":;]/g', "");
|
|
1353
|
-
return e = e.replace(this.symbolsReg, (
|
|
1354
|
-
const s = this.convertDecade(
|
|
1355
|
-
return s ===
|
|
1356
|
-
}), e = e.replace(/\b(\d+)\s*(st|nd|rd|th)(?=\s|[.,!?;:]|$)/gi, (
|
|
1353
|
+
return e = e.replace(this.symbolsReg, (n) => " " + this.symbols[n] + " "), /\d/.test(e) && (e = e.replace(/\b(\d{2,4})[''']?\s?[sS](?=\s|[.,!?;:]|$)/g, (n, i) => {
|
|
1354
|
+
const s = this.convertDecade(i);
|
|
1355
|
+
return s === i ? n : s;
|
|
1356
|
+
}), e = e.replace(/\b(\d+)\s*(st|nd|rd|th)(?=\s|[.,!?;:]|$)/gi, (n, i) => this.convertOrdinal(Number(i))), e = e.replace(/\b(\w*?)(\d+)([A-Za-z]+)\b/g, (n, i, s, o) => {
|
|
1357
1357
|
const l = this.convertNumberToWords(s);
|
|
1358
|
-
return `${
|
|
1359
|
-
}).replace(/\b([A-Za-z]+)(\d+)(\w*?)\b/g, (
|
|
1358
|
+
return `${i}${l} ${o}`;
|
|
1359
|
+
}).replace(/\b([A-Za-z]+)(\d+)(\w*?)\b/g, (n, i, s, o) => {
|
|
1360
1360
|
const l = this.convertNumberToWords(s);
|
|
1361
|
-
return `${
|
|
1362
|
-
}), e = e.replace(/-?(?:\d{1,3}(?:,\d{3})+|\d+)(\.\d+)?/g, (
|
|
1363
|
-
let s =
|
|
1364
|
-
return /,/.test(s) && (s = s.replace(/,/g, ""), o = !0),
|
|
1361
|
+
return `${i} ${l}${o}`;
|
|
1362
|
+
}), e = e.replace(/-?(?:\d{1,3}(?:,\d{3})+|\d+)(\.\d+)?/g, (n, i) => {
|
|
1363
|
+
let s = n, o = !1;
|
|
1364
|
+
return /,/.test(s) && (s = s.replace(/,/g, ""), o = !0), i && (o = !0), this.convertNumberToWords(s, o);
|
|
1365
1365
|
})), e = e.replace(/(\D)\1\1+/g, "$1$1").replaceAll(" ", " ").normalize("NFD").replace(/[\u0300-\u036f]/g, "").normalize("NFC").trim(), e;
|
|
1366
1366
|
}
|
|
1367
1367
|
/**
|
|
@@ -1370,10 +1370,10 @@ class qe {
|
|
|
1370
1370
|
* @return {Object} Oculus LipSync Visemes and durations.
|
|
1371
1371
|
*/
|
|
1372
1372
|
wordsToVisemes(t) {
|
|
1373
|
-
let e = { words: t.toUpperCase(), visemes: [], times: [], durations: [], i: 0 },
|
|
1374
|
-
const
|
|
1375
|
-
for (; e.i <
|
|
1376
|
-
const s =
|
|
1373
|
+
let e = { words: t.toUpperCase(), visemes: [], times: [], durations: [], i: 0 }, n = 0;
|
|
1374
|
+
const i = [...e.words];
|
|
1375
|
+
for (; e.i < i.length; ) {
|
|
1376
|
+
const s = i[e.i], o = this.rules[s];
|
|
1377
1377
|
if (o)
|
|
1378
1378
|
for (let l = 0; l < o.length; l++) {
|
|
1379
1379
|
const u = o[l];
|
|
@@ -1381,26 +1381,26 @@ class qe {
|
|
|
1381
1381
|
u.visemes.forEach((r) => {
|
|
1382
1382
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === r) {
|
|
1383
1383
|
const c = 0.7 * (this.visemeDurations[r] || 1);
|
|
1384
|
-
e.durations[e.durations.length - 1] += c,
|
|
1384
|
+
e.durations[e.durations.length - 1] += c, n += c;
|
|
1385
1385
|
} else {
|
|
1386
1386
|
const c = this.visemeDurations[r] || 1;
|
|
1387
|
-
e.visemes.push(r), e.times.push(
|
|
1387
|
+
e.visemes.push(r), e.times.push(n), e.durations.push(c), n += c;
|
|
1388
1388
|
}
|
|
1389
1389
|
}), e.i += u.move;
|
|
1390
1390
|
break;
|
|
1391
1391
|
}
|
|
1392
1392
|
}
|
|
1393
1393
|
else
|
|
1394
|
-
e.i++,
|
|
1394
|
+
e.i++, n += this.specialDurations[s] || 0;
|
|
1395
1395
|
}
|
|
1396
1396
|
return e;
|
|
1397
1397
|
}
|
|
1398
1398
|
}
|
|
1399
|
-
const
|
|
1399
|
+
const Je = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1400
1400
|
__proto__: null,
|
|
1401
|
-
LipsyncEn:
|
|
1401
|
+
LipsyncEn: Ke
|
|
1402
1402
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1403
|
-
class
|
|
1403
|
+
class $e {
|
|
1404
1404
|
/**
|
|
1405
1405
|
* @constructor
|
|
1406
1406
|
*/
|
|
@@ -1615,8 +1615,8 @@ class Ke {
|
|
|
1615
1615
|
// Word boundary
|
|
1616
1616
|
};
|
|
1617
1617
|
Object.keys(this.rules).forEach((e) => {
|
|
1618
|
-
this.rules[e] = this.rules[e].map((
|
|
1619
|
-
const
|
|
1618
|
+
this.rules[e] = this.rules[e].map((n) => {
|
|
1619
|
+
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), u = n.substring(i + 1, s), a = n.substring(s + 1, o), h = n.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
1620
1620
|
let c = "";
|
|
1621
1621
|
c += [...l].map((g) => t[g] || g).join("");
|
|
1622
1622
|
const d = [...u];
|
|
@@ -1666,31 +1666,31 @@ class Ke {
|
|
|
1666
1666
|
convert_digit_by_digit(t) {
|
|
1667
1667
|
t = String(t).split("");
|
|
1668
1668
|
let e = "";
|
|
1669
|
-
for (let
|
|
1670
|
-
e += this.digits[t[
|
|
1669
|
+
for (let n = 0; n < t.length; n++)
|
|
1670
|
+
e += this.digits[t[n]] + " ";
|
|
1671
1671
|
return e = e.substring(0, e.length - 1), e;
|
|
1672
1672
|
}
|
|
1673
1673
|
convert_millions(t) {
|
|
1674
1674
|
if (t >= 1e6) {
|
|
1675
|
-
const e = Math.floor(t / 1e6),
|
|
1676
|
-
let
|
|
1677
|
-
return
|
|
1675
|
+
const e = Math.floor(t / 1e6), n = t % 1e6;
|
|
1676
|
+
let i = this.convert_thousands(e);
|
|
1677
|
+
return i += e === 1 ? " million " : " millionen ", n > 0 && (i += this.convert_thousands(n)), i;
|
|
1678
1678
|
} else
|
|
1679
1679
|
return this.convert_thousands(t);
|
|
1680
1680
|
}
|
|
1681
1681
|
convert_thousands(t) {
|
|
1682
1682
|
if (t >= 1e3) {
|
|
1683
|
-
const e = Math.floor(t / 1e3),
|
|
1684
|
-
let
|
|
1685
|
-
return e === 1 ?
|
|
1683
|
+
const e = Math.floor(t / 1e3), n = t % 1e3;
|
|
1684
|
+
let i = "";
|
|
1685
|
+
return e === 1 ? i = "eintausend" : i = this.convert_hundreds(e) + "tausend", n > 0 && (i += this.convert_hundreds(n)), i;
|
|
1686
1686
|
} else
|
|
1687
1687
|
return this.convert_hundreds(t);
|
|
1688
1688
|
}
|
|
1689
1689
|
convert_hundreds(t) {
|
|
1690
1690
|
if (t > 99) {
|
|
1691
|
-
const e = Math.floor(t / 100),
|
|
1692
|
-
let
|
|
1693
|
-
return e === 1 ?
|
|
1691
|
+
const e = Math.floor(t / 100), n = t % 100;
|
|
1692
|
+
let i = "";
|
|
1693
|
+
return e === 1 ? i = "einhundert" : i = this.ones[e] + "hundert", n > 0 && (i += this.convert_tens(n)), i;
|
|
1694
1694
|
} else
|
|
1695
1695
|
return this.convert_tens(t);
|
|
1696
1696
|
}
|
|
@@ -1700,8 +1700,8 @@ class Ke {
|
|
|
1700
1700
|
if (t >= 10 && t < 20)
|
|
1701
1701
|
return this.teens[t - 10];
|
|
1702
1702
|
{
|
|
1703
|
-
const e = Math.floor(t / 10),
|
|
1704
|
-
return
|
|
1703
|
+
const e = Math.floor(t / 10), n = t % 10;
|
|
1704
|
+
return n === 0 ? this.tens[e] : this.ones[n] + "und" + this.tens[e];
|
|
1705
1705
|
}
|
|
1706
1706
|
}
|
|
1707
1707
|
convertNumberToWords(t) {
|
|
@@ -1726,10 +1726,10 @@ class Ke {
|
|
|
1726
1726
|
* @return {Object} Oculus LipSync Visemes and durations.
|
|
1727
1727
|
*/
|
|
1728
1728
|
wordsToVisemes(t) {
|
|
1729
|
-
let e = { words: t.toUpperCase(), visemes: [], times: [], durations: [], i: 0 },
|
|
1730
|
-
const
|
|
1731
|
-
for (; e.i <
|
|
1732
|
-
const s =
|
|
1729
|
+
let e = { words: t.toUpperCase(), visemes: [], times: [], durations: [], i: 0 }, n = 0;
|
|
1730
|
+
const i = [...e.words];
|
|
1731
|
+
for (; e.i < i.length; ) {
|
|
1732
|
+
const s = i[e.i], o = this.rules[s];
|
|
1733
1733
|
if (o) {
|
|
1734
1734
|
let l = !1;
|
|
1735
1735
|
for (let u = 0; u < o.length; u++) {
|
|
@@ -1738,27 +1738,27 @@ class Ke {
|
|
|
1738
1738
|
a.visemes.forEach((c) => {
|
|
1739
1739
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
1740
1740
|
const d = 0.7 * (this.visemeDurations[c] || 1);
|
|
1741
|
-
e.durations[e.durations.length - 1] += d,
|
|
1741
|
+
e.durations[e.durations.length - 1] += d, n += d;
|
|
1742
1742
|
} else {
|
|
1743
1743
|
const d = this.visemeDurations[c] || 1;
|
|
1744
|
-
e.visemes.push(c), e.times.push(
|
|
1744
|
+
e.visemes.push(c), e.times.push(n), e.durations.push(d), n += d;
|
|
1745
1745
|
}
|
|
1746
1746
|
}), e.i += a.move, l = !0;
|
|
1747
1747
|
break;
|
|
1748
1748
|
}
|
|
1749
1749
|
}
|
|
1750
|
-
l || (e.i++,
|
|
1750
|
+
l || (e.i++, n += this.specialDurations[s] || 0);
|
|
1751
1751
|
} else
|
|
1752
|
-
e.i++,
|
|
1752
|
+
e.i++, n += this.specialDurations[s] || 0;
|
|
1753
1753
|
}
|
|
1754
1754
|
return e;
|
|
1755
1755
|
}
|
|
1756
1756
|
}
|
|
1757
|
-
const
|
|
1757
|
+
const et = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1758
1758
|
__proto__: null,
|
|
1759
|
-
LipsyncDe:
|
|
1759
|
+
LipsyncDe: $e
|
|
1760
1760
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1761
|
-
class
|
|
1761
|
+
class tt {
|
|
1762
1762
|
/**
|
|
1763
1763
|
* @constructor
|
|
1764
1764
|
*/
|
|
@@ -2130,8 +2130,8 @@ class $e {
|
|
|
2130
2130
|
// End of word
|
|
2131
2131
|
};
|
|
2132
2132
|
Object.keys(this.rules).forEach((e) => {
|
|
2133
|
-
this.rules[e] = this.rules[e].map((
|
|
2134
|
-
const
|
|
2133
|
+
this.rules[e] = this.rules[e].map((n) => {
|
|
2134
|
+
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), u = n.substring(i + 1, s), a = n.substring(s + 1, o), h = n.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
2135
2135
|
let c = "";
|
|
2136
2136
|
c += [...l].map((g) => t[g] || g).join("");
|
|
2137
2137
|
const d = [...u];
|
|
@@ -2195,8 +2195,8 @@ class $e {
|
|
|
2195
2195
|
convert_digit_by_digit(t) {
|
|
2196
2196
|
t = String(t).split("");
|
|
2197
2197
|
let e = "";
|
|
2198
|
-
for (let
|
|
2199
|
-
e += this.digits[t[
|
|
2198
|
+
for (let n = 0; n < t.length; n++)
|
|
2199
|
+
e += this.digits[t[n]] + " ";
|
|
2200
2200
|
return e = e.substring(0, e.length - 1), e;
|
|
2201
2201
|
}
|
|
2202
2202
|
convert_tens(t) {
|
|
@@ -2211,31 +2211,31 @@ class $e {
|
|
|
2211
2211
|
const e = t - 80;
|
|
2212
2212
|
return e === 11 ? "quatre-vingt-onze" : "quatre-vingt-" + this.teens[e - 10];
|
|
2213
2213
|
} else {
|
|
2214
|
-
const e = Math.floor(t / 10),
|
|
2215
|
-
return e === 8 &&
|
|
2214
|
+
const e = Math.floor(t / 10), n = t % 10;
|
|
2215
|
+
return e === 8 && n === 0 ? "quatre-vingts" : e === 8 ? "quatre-vingt-" + this.ones[n] : (e === 2 || e === 3 || e === 4 || e === 5 || e === 6) && n === 1 ? this.tens[e] + " et un" : n === 0 ? this.tens[e] : this.tens[e] + "-" + this.ones[n];
|
|
2216
2216
|
}
|
|
2217
2217
|
}
|
|
2218
2218
|
convert_hundreds(t) {
|
|
2219
2219
|
if (t >= 100) {
|
|
2220
|
-
const e = Math.floor(t / 100),
|
|
2221
|
-
let
|
|
2222
|
-
return e === 1 ?
|
|
2220
|
+
const e = Math.floor(t / 100), n = t % 100;
|
|
2221
|
+
let i = "";
|
|
2222
|
+
return e === 1 ? i = "cent" : (i = this.ones[e] + " cent", n === 0 && (i += "s")), n > 0 && (i += " " + this.convert_tens(n)), i;
|
|
2223
2223
|
} else
|
|
2224
2224
|
return this.convert_tens(t);
|
|
2225
2225
|
}
|
|
2226
2226
|
convert_thousands(t) {
|
|
2227
2227
|
if (t >= 1e3) {
|
|
2228
|
-
const e = Math.floor(t / 1e3),
|
|
2229
|
-
let
|
|
2230
|
-
return e === 1 ?
|
|
2228
|
+
const e = Math.floor(t / 1e3), n = t % 1e3;
|
|
2229
|
+
let i = "";
|
|
2230
|
+
return e === 1 ? i = "mille" : i = this.convert_hundreds(e) + " mille", n > 0 && (i += " " + this.convert_hundreds(n)), i;
|
|
2231
2231
|
} else
|
|
2232
2232
|
return this.convert_hundreds(t);
|
|
2233
2233
|
}
|
|
2234
2234
|
convert_millions(t) {
|
|
2235
2235
|
if (t >= 1e6) {
|
|
2236
|
-
const e = Math.floor(t / 1e6),
|
|
2237
|
-
let
|
|
2238
|
-
return e === 1 ?
|
|
2236
|
+
const e = Math.floor(t / 1e6), n = t % 1e6;
|
|
2237
|
+
let i = "";
|
|
2238
|
+
return e === 1 ? i = "un million" : i = this.convert_hundreds(e) + " millions", n > 0 && (i += " " + this.convert_thousands(n)), i;
|
|
2239
2239
|
} else
|
|
2240
2240
|
return this.convert_thousands(t);
|
|
2241
2241
|
}
|
|
@@ -2261,10 +2261,10 @@ class $e {
|
|
|
2261
2261
|
* @return {Object} Oculus LipSync Visemes and durations.
|
|
2262
2262
|
*/
|
|
2263
2263
|
wordsToVisemes(t) {
|
|
2264
|
-
let e = { words: t.toUpperCase(), visemes: [], times: [], durations: [], i: 0 },
|
|
2265
|
-
const
|
|
2266
|
-
for (; e.i <
|
|
2267
|
-
const s =
|
|
2264
|
+
let e = { words: t.toUpperCase(), visemes: [], times: [], durations: [], i: 0 }, n = 0;
|
|
2265
|
+
const i = [...e.words];
|
|
2266
|
+
for (; e.i < i.length; ) {
|
|
2267
|
+
const s = i[e.i], o = this.rules[s];
|
|
2268
2268
|
if (o) {
|
|
2269
2269
|
let l = !1;
|
|
2270
2270
|
for (let u = 0; u < o.length; u++) {
|
|
@@ -2273,27 +2273,27 @@ class $e {
|
|
|
2273
2273
|
a.visemes.forEach((c) => {
|
|
2274
2274
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
2275
2275
|
const d = 0.7 * (this.visemeDurations[c] || 1);
|
|
2276
|
-
e.durations[e.durations.length - 1] += d,
|
|
2276
|
+
e.durations[e.durations.length - 1] += d, n += d;
|
|
2277
2277
|
} else {
|
|
2278
2278
|
const d = this.visemeDurations[c] || 1;
|
|
2279
|
-
e.visemes.push(c), e.times.push(
|
|
2279
|
+
e.visemes.push(c), e.times.push(n), e.durations.push(d), n += d;
|
|
2280
2280
|
}
|
|
2281
2281
|
}), e.i += a.move, l = !0;
|
|
2282
2282
|
break;
|
|
2283
2283
|
}
|
|
2284
2284
|
}
|
|
2285
|
-
l || (e.i++,
|
|
2285
|
+
l || (e.i++, n += this.specialDurations[s] || 0);
|
|
2286
2286
|
} else
|
|
2287
|
-
e.i++,
|
|
2287
|
+
e.i++, n += this.specialDurations[s] || 0;
|
|
2288
2288
|
}
|
|
2289
2289
|
return e;
|
|
2290
2290
|
}
|
|
2291
2291
|
}
|
|
2292
|
-
const
|
|
2292
|
+
const nt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2293
2293
|
__proto__: null,
|
|
2294
|
-
LipsyncFr:
|
|
2294
|
+
LipsyncFr: tt
|
|
2295
2295
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2296
|
-
class
|
|
2296
|
+
class it {
|
|
2297
2297
|
/**
|
|
2298
2298
|
* @constructor
|
|
2299
2299
|
*/
|
|
@@ -2379,18 +2379,18 @@ class tt {
|
|
|
2379
2379
|
*/
|
|
2380
2380
|
numberToFinnishWords(t) {
|
|
2381
2381
|
const e = [];
|
|
2382
|
-
let
|
|
2383
|
-
if (
|
|
2384
|
-
let
|
|
2382
|
+
let n = parseFloat(t);
|
|
2383
|
+
if (n === void 0) return t;
|
|
2384
|
+
let i = (s, o, l, u, a) => {
|
|
2385
2385
|
if (s < o) return s;
|
|
2386
2386
|
const h = Math.floor(s / o);
|
|
2387
2387
|
return e.push(l + (h === 1 ? u : this.numberToFinnishWords(h.toString()) + a)), s - h * o;
|
|
2388
2388
|
};
|
|
2389
|
-
if (
|
|
2390
|
-
let s = Math.floor(
|
|
2391
|
-
e.push(this.numbers[s]),
|
|
2389
|
+
if (n < 0 && (e.push("miinus "), n = Math.abs(n)), n = i(n, 1e9, " ", "miljardi", " miljardia"), n = i(n, 1e6, " ", "miljoona", " miljoonaa"), n = i(n, 1e3, "", "tuhat", "tuhatta"), n = i(n, 100, " ", "sata", "sataa"), n > 20 && (n = i(n, 10, "", "", "kymmentä")), n >= 1) {
|
|
2390
|
+
let s = Math.floor(n);
|
|
2391
|
+
e.push(this.numbers[s]), n -= s;
|
|
2392
2392
|
}
|
|
2393
|
-
if (
|
|
2393
|
+
if (n >= 0 && Math.abs(parseFloat(t)) < 1 && e.push("nolla"), n > 0) {
|
|
2394
2394
|
let s = t.split(".");
|
|
2395
2395
|
if (s.length > 1) {
|
|
2396
2396
|
e.push(" pilkku");
|
|
@@ -2418,29 +2418,29 @@ class tt {
|
|
|
2418
2418
|
* @return {Object} Oculus LipSync Visemes and durations.
|
|
2419
2419
|
*/
|
|
2420
2420
|
wordsToVisemes(t) {
|
|
2421
|
-
let e = { words: t, visemes: [], times: [], durations: [] },
|
|
2422
|
-
const
|
|
2423
|
-
for (let s = 0; s <
|
|
2424
|
-
const o = this.visemes[
|
|
2421
|
+
let e = { words: t, visemes: [], times: [], durations: [] }, n = 0;
|
|
2422
|
+
const i = [...t];
|
|
2423
|
+
for (let s = 0; s < i.length; s++) {
|
|
2424
|
+
const o = this.visemes[i[s].toLowerCase()];
|
|
2425
2425
|
if (o)
|
|
2426
2426
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === o) {
|
|
2427
2427
|
const l = 0.7 * (this.visemeDurations[o] || 1);
|
|
2428
|
-
e.durations[e.durations.length - 1] += l,
|
|
2428
|
+
e.durations[e.durations.length - 1] += l, n += l;
|
|
2429
2429
|
} else {
|
|
2430
2430
|
const l = this.visemeDurations[o] || 1;
|
|
2431
|
-
e.visemes.push(o), e.times.push(
|
|
2431
|
+
e.visemes.push(o), e.times.push(n), e.durations.push(l), n += l;
|
|
2432
2432
|
}
|
|
2433
2433
|
else
|
|
2434
|
-
|
|
2434
|
+
n += this.specialDurations[i[s]] || 0;
|
|
2435
2435
|
}
|
|
2436
2436
|
return e;
|
|
2437
2437
|
}
|
|
2438
2438
|
}
|
|
2439
|
-
const
|
|
2439
|
+
const ot = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2440
2440
|
__proto__: null,
|
|
2441
|
-
LipsyncFi:
|
|
2441
|
+
LipsyncFi: it
|
|
2442
2442
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2443
|
-
class
|
|
2443
|
+
class st {
|
|
2444
2444
|
/**
|
|
2445
2445
|
* @constructor
|
|
2446
2446
|
*/
|
|
@@ -2557,24 +2557,24 @@ class nt {
|
|
|
2557
2557
|
*/
|
|
2558
2558
|
numberToLithuanianWords(t) {
|
|
2559
2559
|
const e = [];
|
|
2560
|
-
let
|
|
2561
|
-
if (
|
|
2562
|
-
let
|
|
2560
|
+
let n = parseFloat(t);
|
|
2561
|
+
if (n === void 0) return t;
|
|
2562
|
+
let i = (s, o, l, u, a) => {
|
|
2563
2563
|
if (s < o) return s;
|
|
2564
2564
|
const h = Math.floor(s / o);
|
|
2565
2565
|
return h === 1 ? e.push(this.numbers[1]) : e.push(this.numberToLithuanianWords(h.toString())), h % 10 === 1 ? e.push(l) : h % 10 === 0 || h % 100 > 10 && h % 100 < 20 ? e.push(a) : e.push(u), s - h * o;
|
|
2566
2566
|
};
|
|
2567
|
-
|
|
2567
|
+
n < 0 && (e.push("minus"), n = Math.abs(n)), n = i(n, 1e9, "milijardas", "milijardai", "milijardų"), n = i(n, 1e6, "milijonas", "milijonai", "milijonų"), n = i(n, 1e3, "tūkstantis", "tūkstančiai", "tūkstančių"), n = i(n, 100, "šimtas", "šimtai", "šimtų");
|
|
2568
2568
|
for (let s = this.tens.length - 1; s >= 1; s--)
|
|
2569
|
-
if (
|
|
2570
|
-
e.push(this.tens[s]),
|
|
2569
|
+
if (n >= 10 * s) {
|
|
2570
|
+
e.push(this.tens[s]), n = n - 10 * s;
|
|
2571
2571
|
break;
|
|
2572
2572
|
}
|
|
2573
|
-
if (
|
|
2574
|
-
let s = Math.floor(
|
|
2575
|
-
e.push(this.numbers[s]),
|
|
2573
|
+
if (n >= 1) {
|
|
2574
|
+
let s = Math.floor(n);
|
|
2575
|
+
e.push(this.numbers[s]), n -= s;
|
|
2576
2576
|
}
|
|
2577
|
-
if (
|
|
2577
|
+
if (n >= 0 && Math.abs(parseFloat(t)) < 1 && e.push(this.numbers[0]), n > 0) {
|
|
2578
2578
|
let s = t.split(".");
|
|
2579
2579
|
if (s.length > 1) {
|
|
2580
2580
|
e.push("kablelis");
|
|
@@ -2602,42 +2602,42 @@ class nt {
|
|
|
2602
2602
|
* @return {Object} Oculus LipSync Visemes and durations.
|
|
2603
2603
|
*/
|
|
2604
2604
|
wordsToVisemes(t) {
|
|
2605
|
-
let e = { words: t, visemes: [], times: [], durations: [] },
|
|
2606
|
-
const
|
|
2607
|
-
for (let s = 0; s <
|
|
2608
|
-
const o =
|
|
2605
|
+
let e = { words: t, visemes: [], times: [], durations: [] }, n = 0;
|
|
2606
|
+
const i = [...t];
|
|
2607
|
+
for (let s = 0; s < i.length; s++) {
|
|
2608
|
+
const o = i[s].toLowerCase(), l = this.visemes[o];
|
|
2609
2609
|
if (l)
|
|
2610
2610
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === l) {
|
|
2611
2611
|
const u = 0.7 * (this.durations[o] || 1);
|
|
2612
|
-
e.durations[e.durations.length - 1] += u,
|
|
2612
|
+
e.durations[e.durations.length - 1] += u, n += u;
|
|
2613
2613
|
} else {
|
|
2614
2614
|
const u = this.durations[o] || 1;
|
|
2615
|
-
e.visemes.push(l), e.times.push(
|
|
2615
|
+
e.visemes.push(l), e.times.push(n), e.durations.push(u), n += u;
|
|
2616
2616
|
}
|
|
2617
2617
|
else
|
|
2618
|
-
|
|
2618
|
+
n += this.pauses[i[s]] || 0;
|
|
2619
2619
|
}
|
|
2620
2620
|
return e;
|
|
2621
2621
|
}
|
|
2622
2622
|
}
|
|
2623
|
-
const
|
|
2623
|
+
const at = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2624
2624
|
__proto__: null,
|
|
2625
|
-
LipsyncLt:
|
|
2626
|
-
}, Symbol.toStringTag, { value: "Module" })), st = new URL("data:text/javascript;base64,Y2xhc3MgUGxheWJhY2tXb3JrbGV0IGV4dGVuZHMgQXVkaW9Xb3JrbGV0UHJvY2Vzc29yIHsKICBzdGF0aWMgRlNNID0gewogICAgSURMRTogMCwKICAgIFBMQVlJTkc6IDEsCiAgfTsKCiAgY29uc3RydWN0b3Iob3B0aW9ucykgewogICAgc3VwZXIoKTsKICAgIHRoaXMucG9ydC5vbm1lc3NhZ2UgPSB0aGlzLmhhbmRsZU1lc3NhZ2UuYmluZCh0aGlzKTsKCiAgICB0aGlzLl9zYW1wbGVSYXRlID0gb3B0aW9ucz8ucHJvY2Vzc29yT3B0aW9ucz8uc2FtcGxlUmF0ZSB8fCBzYW1wbGVSYXRlOwogICAgdGhpcy5fc2NhbGUgPSAxIC8gMzI3Njg7IC8vIFBDTTE2IC0+IGZsb2F0CgogICAgLy8gU2lsZW5jZSBkZXRlY3Rpb24gdGhyZXNob2xkICgxIHNlY29uZCkgYXMgYSBmYWxsYmFjayBzYWZldHkgbmV0CiAgICBjb25zdCBzaWxlbmNlRHVyYXRpb25TZWNvbmRzID0gMS4wOwogICAgdGhpcy5fc2lsZW5jZVRocmVzaG9sZEJsb2NrcyA9IE1hdGguY2VpbCgodGhpcy5fc2FtcGxlUmF0ZSAqIHNpbGVuY2VEdXJhdGlvblNlY29uZHMpIC8gMTI4KTsKCiAgICAvLyBNZXRyaWNzIGNvbmZpZ3VyYXRpb24gdmlhIG9wdGlvbnMKICAgIGNvbnN0IG1ldHJpY3NDZmcgPSBvcHRpb25zPy5wcm9jZXNzb3JPcHRpb25zPy5tZXRyaWNzIHx8IHt9OwogICAgdGhpcy5fbWV0cmljc0VuYWJsZWQgPSBtZXRyaWNzQ2ZnLmVuYWJsZWQgIT09IGZhbHNlOwogICAgY29uc3QgaW50ZXJ2YWxIeiA9ICh0eXBlb2YgbWV0cmljc0NmZy5pbnRlcnZhbEh6ID09PSAibnVtYmVyIiAmJiBtZXRyaWNzQ2ZnLmludGVydmFsSHogPiAwKQogICAgICA/IG1ldHJpY3NDZmcuaW50ZXJ2YWxIeiA6IDI7CiAgICAvLyBNZXRyaWNzIHN0YXRlIChsb3ctb3ZlcmhlYWQpCiAgICB0aGlzLl9mcmFtZXNQcm9jZXNzZWQgPSAwOwogICAgdGhpcy5fdW5kZXJydW5CbG9ja3MgPSAwOwogICAgdGhpcy5fbWF4UXVldWVTYW1wbGVzID0gMDsKICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSAwOwogICAgLy8gQ29udmVydCB0byBmcmFtZXMgYmV0d2VlbiByZXBvcnRzCiAgICB0aGlzLl9tZXRyaWNzSW50ZXJ2YWxGcmFtZXMgPSBNYXRoLm1heCgxMjgsIE1hdGgucm91bmQodGhpcy5fc2FtcGxlUmF0ZSAvIGludGVydmFsSHopKTsKCiAgICB0aGlzLnJlc2V0KCk7CiAgfQoKICAvKioKICAgKiBSZXNldHMgdGhlIHdvcmtsZXQgdG8gaXRzIGluaXRpYWwgSURMRSBzdGF0ZS4KICAgKi8KICByZXNldCgpIHsKICAgIHRoaXMuX2J1ZmZlclF1ZXVlID0gW107CiAgICB0aGlzLl9jdXJyZW50Q2h1bmsgPSBudWxsOwogICAgdGhpcy5fY3VycmVudENodW5rT2Zmc2V0ID0gMDsKICAgIHRoaXMuX3N0YXRlID0gUGxheWJhY2tXb3JrbGV0LkZTTS5JRExFOwoKICAgIHRoaXMuX25vTW9yZURhdGFSZWNlaXZlZCA9IGZhbHNlOwogICAgdGhpcy5fc2lsZW5jZUZyYW1lc0NvdW50ID0gMDsKICAgIHRoaXMuX2hhc1NlbnRFbmRlZCA9IGZhbHNlOwogICAgLy8gUmVzZXQgbWF4IHF1ZXVlIHRyYWNrZXIgb25seSB3aGVuIGdvaW5nIGlkbGUKICAgIHRoaXMuX21heFF1ZXVlU2FtcGxlcyA9IDA7CiAgfQoKICBoYW5kbGVNZXNzYWdlKGV2ZW50KSB7CiAgICBjb25zdCB7IHR5cGUsIGRhdGEgfSA9IGV2ZW50LmRhdGE7CgogICAgLy8gSU5URVJSVVBUOiBUaGUgbWFpbiB0aHJlYWQgd2FudHMgdG8gc3RvcCBpbW1lZGlhdGVseS4KICAgIGlmICh0eXBlID09PSAic3RvcCIpIHsKICAgICAgdGhpcy5yZXNldCgpOwogICAgICAvLyBTZW5kIGZpbmFsIG1ldHJpY3Mgc2hvd2luZyBjbGVhcmVkIHN0YXRlCiAgICAgIGlmICh0aGlzLl9tZXRyaWNzRW5hYmxlZCkgewogICAgICAgIHRyeSB7CiAgICAgICAgICB0aGlzLnBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICB0eXBlOiAibWV0cmljcyIsCiAgICAgICAgICAgIGRhdGE6IHsKICAgICAgICAgICAgICBzdGF0ZTogUGxheWJhY2tXb3JrbGV0LkZTTS5JRExFLAogICAgICAgICAgICAgIHF1ZXVlZFNhbXBsZXM6IDAsCiAgICAgICAgICAgICAgcXVldWVkTXM6IDAsCiAgICAgICAgICAgICAgbWF4UXVldWVkTXM6IE1hdGgucm91bmQoKHRoaXMuX21heFF1ZXVlU2FtcGxlcyAvIHRoaXMuX3NhbXBsZVJhdGUpICogMTAwMCksCiAgICAgICAgICAgICAgdW5kZXJydW5CbG9ja3M6IHRoaXMuX3VuZGVycnVuQmxvY2tzLAogICAgICAgICAgICAgIGZyYW1lc1Byb2Nlc3NlZDogdGhpcy5fZnJhbWVzUHJvY2Vzc2VkCiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgIH0gY2F0Y2ggKF8pIHsgfQogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBNYWluIHRocmVhZCBoYXMgc2lnbmFsZWQgdGhhdCBubyBtb3JlIGF1ZGlvIGNodW5rcyB3aWxsIGJlIHNlbnQgZm9yIHRoaXMgdXR0ZXJhbmNlLgogICAgaWYgKHR5cGUgPT09ICJuby1tb3JlLWRhdGEiKSB7CiAgICAgIHRoaXMuX25vTW9yZURhdGFSZWNlaXZlZCA9IHRydWU7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBVcGRhdGUgbWV0cmljcyBjb25maWd1cmF0aW9uIGF0IHJ1bnRpbWUKICAgIGlmICh0eXBlID09PSAiY29uZmlnLW1ldHJpY3MiICYmIGRhdGEgJiYgdHlwZW9mIGRhdGEgPT09ICJvYmplY3QiKSB7CiAgICAgIGlmICgiZW5hYmxlZCIgaW4gZGF0YSkgdGhpcy5fbWV0cmljc0VuYWJsZWQgPSAhIWRhdGEuZW5hYmxlZDsKICAgICAgaWYgKHR5cGVvZiBkYXRhLmludGVydmFsSHogPT09ICJudW1iZXIiICYmIGRhdGEuaW50ZXJ2YWxIeiA+IDApIHsKICAgICAgICBjb25zdCBpbnRlcnZhbEh6ID0gZGF0YS5pbnRlcnZhbEh6OwogICAgICAgIHRoaXMuX21ldHJpY3NJbnRlcnZhbEZyYW1lcyA9IE1hdGgubWF4KDEyOCwgTWF0aC5yb3VuZCh0aGlzLl9zYW1wbGVSYXRlIC8gaW50ZXJ2YWxIeikpOwogICAgICB9CiAgICAgIC8vIFJlc2V0IHBhY2luZyBzbyB0aGUgbmV4dCByZXBvcnQgYWxpZ25zIHdpdGggbmV3IGludGVydmFsCiAgICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSB0aGlzLl9mcmFtZXNQcm9jZXNzZWQ7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBOZXcgYXVkaW8gZGF0YSBoYXMgYXJyaXZlZC4KICAgIGlmICh0eXBlID09PSAiYXVkaW9EYXRhIiAmJiBkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHsKICAgICAgdGhpcy5fbm9Nb3JlRGF0YVJlY2VpdmVkID0gZmFsc2U7CiAgICAgIC8vIElmIHdlIHdlcmUgaWRsZSwgdGhpcyBuZXcgZGF0YSBraWNrcyBvZmYgdGhlIHBsYXliYWNrLgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFBsYXliYWNrV29ya2xldC5GU00uSURMRSkgewogICAgICAgIHRoaXMuX3N0YXRlID0gUGxheWJhY2tXb3JrbGV0LkZTTS5QTEFZSU5HOwogICAgICAgIHRoaXMucG9ydC5wb3N0TWVzc2FnZSh7IHR5cGU6ICJwbGF5YmFjay1zdGFydGVkIiB9KTsKICAgICAgfQoKICAgICAgLy8gV2Ugb25seSBxdWV1ZSBkYXRhIGlmIHdlIGFyZSBpbiB0aGUgUExBWUlORyBzdGF0ZS4gVGhpcyBwcmV2ZW50cwogICAgICAvLyBkYXRhIGZyb20gYSBwcmV2aW91cywgaW50ZXJydXB0ZWQgc3RyZWFtIGZyb20gbGluZ2VyaW5nLgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFBsYXliYWNrV29ya2xldC5GU00uUExBWUlORykgewogICAgICAgIC8vIFN0b3JlIGFzIEludDE2QXJyYXkgdmlldyB0byBhdm9pZCBjb25zdHJ1Y3RpbmcgaXQgaW4gcHJvY2VzcygpCiAgICAgICAgdGhpcy5fYnVmZmVyUXVldWUucHVzaChuZXcgSW50MTZBcnJheShkYXRhKSk7CiAgICAgICAgdGhpcy5fc2lsZW5jZUZyYW1lc0NvdW50ID0gMDsgLy8gUmVzZXQgc2lsZW5jZSBjb3VudGVyIG9uIG5ldyBkYXRhCiAgICAgIH0KICAgIH0KICB9CgogIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CiAgICBjb25zdCBvdXRwdXRDaGFubmVsID0gb3V0cHV0c1swXT8uWzBdOwogICAgaWYgKCFvdXRwdXRDaGFubmVsKSB7CiAgICAgIHJldHVybiB0cnVlOyAvLyBLZWVwIGFsaXZlIGV2ZW4gaWYgb3V0cHV0IGlzIHRlbXBvcmFyaWx5IGRpc2Nvbm5lY3RlZAogICAgfQoKICAgIC8vIElmIHdlIGFyZSBub3QgcGxheWluZywganVzdCBvdXRwdXQgc2lsZW5jZSBhbmQgd2FpdC4KICAgIGlmICh0aGlzLl9zdGF0ZSAhPT0gUGxheWJhY2tXb3JrbGV0LkZTTS5QTEFZSU5HKSB7CiAgICAgIG91dHB1dENoYW5uZWwuZmlsbCgwKTsKICAgICAgcmV0dXJuIHRydWU7IC8vIEFsd2F5cyByZXR1cm4gdHJ1ZSB0byBrZWVwIHRoZSBwcm9jZXNzb3IgYWxpdmUKICAgIH0KCiAgICAvLyBDb3JlIFBMQVlJTkcgTG9naWMKICAgIGNvbnN0IGJsb2NrU2l6ZSA9IG91dHB1dENoYW5uZWwubGVuZ3RoOwogICAgbGV0IHNhbXBsZXNDb3BpZWQgPSAwOwoKICAgIHdoaWxlIChzYW1wbGVzQ29waWVkIDwgYmxvY2tTaXplKSB7CiAgICAgIGlmICghdGhpcy5fY3VycmVudENodW5rIHx8IHRoaXMuX2N1cnJlbnRDaHVua09mZnNldCA+PSB0aGlzLl9jdXJyZW50Q2h1bmsubGVuZ3RoKSB7CiAgICAgICAgaWYgKHRoaXMuX2J1ZmZlclF1ZXVlLmxlbmd0aCA+IDApIHsKICAgICAgICAgIHRoaXMuX2N1cnJlbnRDaHVuayA9IHRoaXMuX2J1ZmZlclF1ZXVlLnNoaWZ0KCk7CiAgICAgICAgICB0aGlzLl9jdXJyZW50Q2h1bmtPZmZzZXQgPSAwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBCdWZmZXIgaXMgZW1wdHkuIENoZWNrIGZvciBlbmQgY29uZGl0aW9ucy4KICAgICAgICAgIGNvbnN0IGlzVGltZWRPdXQgPSB0aGlzLl9zaWxlbmNlRnJhbWVzQ291bnQgPiB0aGlzLl9zaWxlbmNlVGhyZXNob2xkQmxvY2tzOwoKICAgICAgICAgIGlmICh0aGlzLl9ub01vcmVEYXRhUmVjZWl2ZWQgfHwgaXNUaW1lZE91dCkgewogICAgICAgICAgICAvLyBFTkQgT0YgUExBWUJBQ0s6IEVpdGhlciBleHBsaWNpdGx5IHNpZ25hbGVkIG9yIHRpbWVkIG91dC4KICAgICAgICAgICAgaWYgKCF0aGlzLl9oYXNTZW50RW5kZWQpIHsKICAgICAgICAgICAgICB0aGlzLnBvcnQucG9zdE1lc3NhZ2UoeyB0eXBlOiAicGxheWJhY2stZW5kZWQiIH0pOwogICAgICAgICAgICAgIHRoaXMuX2hhc1NlbnRFbmRlZCA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gU2VuZCBmaW5hbCBtZXRyaWNzIHNob3dpbmcgY2xlYXJlZCBzdGF0ZQogICAgICAgICAgICBpZiAodGhpcy5fbWV0cmljc0VuYWJsZWQpIHsKICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgdGhpcy5wb3J0LnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgICAgdHlwZTogIm1ldHJpY3MiLAogICAgICAgICAgICAgICAgICBkYXRhOiB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGU6IFBsYXliYWNrV29ya2xldC5GU00uSURMRSwKICAgICAgICAgICAgICAgICAgICBxdWV1ZWRTYW1wbGVzOiAwLAogICAgICAgICAgICAgICAgICAgIHF1ZXVlZE1zOiAwLAogICAgICAgICAgICAgICAgICAgIG1heFF1ZXVlZE1zOiBNYXRoLnJvdW5kKCh0aGlzLl9tYXhRdWV1ZVNhbXBsZXMgLyB0aGlzLl9zYW1wbGVSYXRlKSAqIDEwMDApLAogICAgICAgICAgICAgICAgICAgIHVuZGVycnVuQmxvY2tzOiB0aGlzLl91bmRlcnJ1bkJsb2NrcywKICAgICAgICAgICAgICAgICAgICBmcmFtZXNQcm9jZXNzZWQ6IHRoaXMuX2ZyYW1lc1Byb2Nlc3NlZAogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICB9IGNhdGNoIChfKSB7IH0KICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLnJlc2V0KCk7IC8vIFJlc2V0IHRvIElETEUgc3RhdGUgZm9yIHJldXNlCiAgICAgICAgICAgIGJyZWFrOyAvLyBFeGl0IHdoaWxlIGxvb3AKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vIEJVRkZFUiBVTkRFUlJVTiAoTEFHKTogUGxheSBzaWxlbmNlIGFuZCB3YWl0IGZvciBtb3JlIGRhdGEuCiAgICAgICAgICAgIHRoaXMuX3NpbGVuY2VGcmFtZXNDb3VudCsrOwogICAgICAgICAgICBpZiAodGhpcy5fbWV0cmljc0VuYWJsZWQpIHRoaXMuX3VuZGVycnVuQmxvY2tzKys7CiAgICAgICAgICAgIGJyZWFrOyAvLyBFeGl0IHdoaWxlIGxvb3AKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIElmIHdlIGhhdmUgYSBjaHVuayAoY291bGQgYmUgYSBuZXcgb25lIGZyb20gdGhlIGxvZ2ljIGFib3ZlKSwgcHJvY2VzcyBpdC4KICAgICAgaWYgKHRoaXMuX2N1cnJlbnRDaHVuaykgewogICAgICAgIGNvbnN0IHNhbXBsZXNUb0NvcHkgPSBNYXRoLm1pbigKICAgICAgICAgIGJsb2NrU2l6ZSAtIHNhbXBsZXNDb3BpZWQsCiAgICAgICAgICB0aGlzLl9jdXJyZW50Q2h1bmsubGVuZ3RoIC0gdGhpcy5fY3VycmVudENodW5rT2Zmc2V0CiAgICAgICAgKTsKICAgICAgICAvLyBEaXJlY3RseSB3cml0ZSB0byBvdXRwdXRDaGFubmVsIHRvIGF2b2lkIGV4dHJhIGNvcHkKICAgICAgICBjb25zdCBzcmMgPSB0aGlzLl9jdXJyZW50Q2h1bms7CiAgICAgICAgY29uc3QgYmFzZVNyYyA9IHRoaXMuX2N1cnJlbnRDaHVua09mZnNldDsKICAgICAgICBjb25zdCBiYXNlRHN0ID0gc2FtcGxlc0NvcGllZDsKICAgICAgICBjb25zdCBzY2FsZSA9IHRoaXMuX3NjYWxlOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2FtcGxlc1RvQ29weTsgaSsrKSB7CiAgICAgICAgICBvdXRwdXRDaGFubmVsW2Jhc2VEc3QgKyBpXSA9IHNyY1tiYXNlU3JjICsgaV0gKiBzY2FsZTsKICAgICAgICB9CgogICAgICAgIHRoaXMuX2N1cnJlbnRDaHVua09mZnNldCArPSBzYW1wbGVzVG9Db3B5OwogICAgICAgIHNhbXBsZXNDb3BpZWQgKz0gc2FtcGxlc1RvQ29weTsKICAgICAgfQogICAgfQoKICAgIC8vIFplcm8tZmlsbCB0aGUgcmVtYWluZGVyLCBpZiBhbnksIG9uY2UgcGVyIGJsb2NrCiAgICBpZiAoc2FtcGxlc0NvcGllZCA8IGJsb2NrU2l6ZSkgewogICAgICBvdXRwdXRDaGFubmVsLmZpbGwoMCwgc2FtcGxlc0NvcGllZCk7CiAgICB9CgogICAgLy8gVXBkYXRlIG1ldHJpY3MgKG9wdGlvbmFsKQogICAgaWYgKHRoaXMuX21ldHJpY3NFbmFibGVkKSB7CiAgICAgIHRoaXMuX2ZyYW1lc1Byb2Nlc3NlZCArPSBibG9ja1NpemU7CgogICAgICAvLyBUcmFjayBxdWV1ZSBkZXB0aCBpbiBzYW1wbGVzIChhcHByb3hpbWF0ZSkKICAgICAgbGV0IHF1ZXVlZFNhbXBsZXMgPSAwOwogICAgICBpZiAodGhpcy5fY3VycmVudENodW5rKSBxdWV1ZWRTYW1wbGVzICs9IE1hdGgubWF4KDAsIHRoaXMuX2N1cnJlbnRDaHVuay5sZW5ndGggLSB0aGlzLl9jdXJyZW50Q2h1bmtPZmZzZXQpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX2J1ZmZlclF1ZXVlLmxlbmd0aDsgaSsrKSBxdWV1ZWRTYW1wbGVzICs9IHRoaXMuX2J1ZmZlclF1ZXVlW2ldLmxlbmd0aDsKICAgICAgaWYgKHF1ZXVlZFNhbXBsZXMgPiB0aGlzLl9tYXhRdWV1ZVNhbXBsZXMpIHRoaXMuX21heFF1ZXVlU2FtcGxlcyA9IHF1ZXVlZFNhbXBsZXM7CgogICAgICAvLyBQZXJpb2RpY2FsbHkgc2VuZCBtZXRyaWNzIHRvIG1haW4gdGhyZWFkCiAgICAgIGlmICh0aGlzLl9mcmFtZXNQcm9jZXNzZWQgLSB0aGlzLl9sYXN0TWV0cmljc1NlbnRBdEZyYW1lID49IHRoaXMuX21ldHJpY3NJbnRlcnZhbEZyYW1lcykgewogICAgICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSB0aGlzLl9mcmFtZXNQcm9jZXNzZWQ7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHRoaXMucG9ydC5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgIHR5cGU6ICJtZXRyaWNzIiwKICAgICAgICAgICAgZGF0YTogewogICAgICAgICAgICAgIHN0YXRlOiB0aGlzLl9zdGF0ZSwKICAgICAgICAgICAgICBxdWV1ZWRTYW1wbGVzLAogICAgICAgICAgICAgIHF1ZXVlZE1zOiBNYXRoLnJvdW5kKChxdWV1ZWRTYW1wbGVzIC8gdGhpcy5fc2FtcGxlUmF0ZSkgKiAxMDAwKSwKICAgICAgICAgICAgICBtYXhRdWV1ZWRNczogTWF0aC5yb3VuZCgodGhpcy5fbWF4UXVldWVTYW1wbGVzIC8gdGhpcy5fc2FtcGxlUmF0ZSkgKiAxMDAwKSwKICAgICAgICAgICAgICB1bmRlcnJ1bkJsb2NrczogdGhpcy5fdW5kZXJydW5CbG9ja3MsCiAgICAgICAgICAgICAgZnJhbWVzUHJvY2Vzc2VkOiB0aGlzLl9mcmFtZXNQcm9jZXNzZWQKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfSBjYXRjaCAoXykgeyB9CiAgICAgICAgLy8gRG9uJ3QgcmVzZXQgbWF4IHRyYWNrZXIgLSBrZWVwIHNlc3Npb24gcGVhayB1bnRpbCBpZGxlCiAgICAgIH0KICAgIH0KCiAgICAvLyBBTFdBWVMgcmV0dXJuIHRydWUgdG8ga2VlcCB0aGUgcHJvY2Vzc29yIGFsaXZlIGZvciByZXVzZS4KICAgIHJldHVybiB0cnVlOwogIH0KfQoKcmVnaXN0ZXJQcm9jZXNzb3IoInBsYXliYWNrLXdvcmtsZXQiLCBQbGF5YmFja1dvcmtsZXQpOwo=", import.meta.url), ze = {
|
|
2627
|
-
en:
|
|
2628
|
-
de:
|
|
2629
|
-
fr:
|
|
2630
|
-
fi:
|
|
2631
|
-
lt:
|
|
2632
|
-
},
|
|
2625
|
+
LipsyncLt: st
|
|
2626
|
+
}, Symbol.toStringTag, { value: "Module" })), rt = new URL("data:text/javascript;base64,Y2xhc3MgUGxheWJhY2tXb3JrbGV0IGV4dGVuZHMgQXVkaW9Xb3JrbGV0UHJvY2Vzc29yIHsKICBzdGF0aWMgRlNNID0gewogICAgSURMRTogMCwKICAgIFBMQVlJTkc6IDEsCiAgfTsKCiAgY29uc3RydWN0b3Iob3B0aW9ucykgewogICAgc3VwZXIoKTsKICAgIHRoaXMucG9ydC5vbm1lc3NhZ2UgPSB0aGlzLmhhbmRsZU1lc3NhZ2UuYmluZCh0aGlzKTsKCiAgICB0aGlzLl9zYW1wbGVSYXRlID0gb3B0aW9ucz8ucHJvY2Vzc29yT3B0aW9ucz8uc2FtcGxlUmF0ZSB8fCBzYW1wbGVSYXRlOwogICAgdGhpcy5fc2NhbGUgPSAxIC8gMzI3Njg7IC8vIFBDTTE2IC0+IGZsb2F0CgogICAgLy8gU2lsZW5jZSBkZXRlY3Rpb24gdGhyZXNob2xkICgxIHNlY29uZCkgYXMgYSBmYWxsYmFjayBzYWZldHkgbmV0CiAgICBjb25zdCBzaWxlbmNlRHVyYXRpb25TZWNvbmRzID0gMS4wOwogICAgdGhpcy5fc2lsZW5jZVRocmVzaG9sZEJsb2NrcyA9IE1hdGguY2VpbCgodGhpcy5fc2FtcGxlUmF0ZSAqIHNpbGVuY2VEdXJhdGlvblNlY29uZHMpIC8gMTI4KTsKCiAgICAvLyBNZXRyaWNzIGNvbmZpZ3VyYXRpb24gdmlhIG9wdGlvbnMKICAgIGNvbnN0IG1ldHJpY3NDZmcgPSBvcHRpb25zPy5wcm9jZXNzb3JPcHRpb25zPy5tZXRyaWNzIHx8IHt9OwogICAgdGhpcy5fbWV0cmljc0VuYWJsZWQgPSBtZXRyaWNzQ2ZnLmVuYWJsZWQgIT09IGZhbHNlOwogICAgY29uc3QgaW50ZXJ2YWxIeiA9ICh0eXBlb2YgbWV0cmljc0NmZy5pbnRlcnZhbEh6ID09PSAibnVtYmVyIiAmJiBtZXRyaWNzQ2ZnLmludGVydmFsSHogPiAwKQogICAgICA/IG1ldHJpY3NDZmcuaW50ZXJ2YWxIeiA6IDI7CiAgICAvLyBNZXRyaWNzIHN0YXRlIChsb3ctb3ZlcmhlYWQpCiAgICB0aGlzLl9mcmFtZXNQcm9jZXNzZWQgPSAwOwogICAgdGhpcy5fdW5kZXJydW5CbG9ja3MgPSAwOwogICAgdGhpcy5fbWF4UXVldWVTYW1wbGVzID0gMDsKICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSAwOwogICAgLy8gQ29udmVydCB0byBmcmFtZXMgYmV0d2VlbiByZXBvcnRzCiAgICB0aGlzLl9tZXRyaWNzSW50ZXJ2YWxGcmFtZXMgPSBNYXRoLm1heCgxMjgsIE1hdGgucm91bmQodGhpcy5fc2FtcGxlUmF0ZSAvIGludGVydmFsSHopKTsKCiAgICB0aGlzLnJlc2V0KCk7CiAgfQoKICAvKioKICAgKiBSZXNldHMgdGhlIHdvcmtsZXQgdG8gaXRzIGluaXRpYWwgSURMRSBzdGF0ZS4KICAgKi8KICByZXNldCgpIHsKICAgIHRoaXMuX2J1ZmZlclF1ZXVlID0gW107CiAgICB0aGlzLl9jdXJyZW50Q2h1bmsgPSBudWxsOwogICAgdGhpcy5fY3VycmVudENodW5rT2Zmc2V0ID0gMDsKICAgIHRoaXMuX3N0YXRlID0gUGxheWJhY2tXb3JrbGV0LkZTTS5JRExFOwoKICAgIHRoaXMuX25vTW9yZURhdGFSZWNlaXZlZCA9IGZhbHNlOwogICAgdGhpcy5fc2lsZW5jZUZyYW1lc0NvdW50ID0gMDsKICAgIHRoaXMuX2hhc1NlbnRFbmRlZCA9IGZhbHNlOwogICAgLy8gUmVzZXQgbWF4IHF1ZXVlIHRyYWNrZXIgb25seSB3aGVuIGdvaW5nIGlkbGUKICAgIHRoaXMuX21heFF1ZXVlU2FtcGxlcyA9IDA7CiAgfQoKICBoYW5kbGVNZXNzYWdlKGV2ZW50KSB7CiAgICBjb25zdCB7IHR5cGUsIGRhdGEgfSA9IGV2ZW50LmRhdGE7CgogICAgLy8gSU5URVJSVVBUOiBUaGUgbWFpbiB0aHJlYWQgd2FudHMgdG8gc3RvcCBpbW1lZGlhdGVseS4KICAgIGlmICh0eXBlID09PSAic3RvcCIpIHsKICAgICAgdGhpcy5yZXNldCgpOwogICAgICAvLyBTZW5kIGZpbmFsIG1ldHJpY3Mgc2hvd2luZyBjbGVhcmVkIHN0YXRlCiAgICAgIGlmICh0aGlzLl9tZXRyaWNzRW5hYmxlZCkgewogICAgICAgIHRyeSB7CiAgICAgICAgICB0aGlzLnBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICB0eXBlOiAibWV0cmljcyIsCiAgICAgICAgICAgIGRhdGE6IHsKICAgICAgICAgICAgICBzdGF0ZTogUGxheWJhY2tXb3JrbGV0LkZTTS5JRExFLAogICAgICAgICAgICAgIHF1ZXVlZFNhbXBsZXM6IDAsCiAgICAgICAgICAgICAgcXVldWVkTXM6IDAsCiAgICAgICAgICAgICAgbWF4UXVldWVkTXM6IE1hdGgucm91bmQoKHRoaXMuX21heFF1ZXVlU2FtcGxlcyAvIHRoaXMuX3NhbXBsZVJhdGUpICogMTAwMCksCiAgICAgICAgICAgICAgdW5kZXJydW5CbG9ja3M6IHRoaXMuX3VuZGVycnVuQmxvY2tzLAogICAgICAgICAgICAgIGZyYW1lc1Byb2Nlc3NlZDogdGhpcy5fZnJhbWVzUHJvY2Vzc2VkCiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgIH0gY2F0Y2ggKF8pIHsgfQogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBNYWluIHRocmVhZCBoYXMgc2lnbmFsZWQgdGhhdCBubyBtb3JlIGF1ZGlvIGNodW5rcyB3aWxsIGJlIHNlbnQgZm9yIHRoaXMgdXR0ZXJhbmNlLgogICAgaWYgKHR5cGUgPT09ICJuby1tb3JlLWRhdGEiKSB7CiAgICAgIHRoaXMuX25vTW9yZURhdGFSZWNlaXZlZCA9IHRydWU7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBVcGRhdGUgbWV0cmljcyBjb25maWd1cmF0aW9uIGF0IHJ1bnRpbWUKICAgIGlmICh0eXBlID09PSAiY29uZmlnLW1ldHJpY3MiICYmIGRhdGEgJiYgdHlwZW9mIGRhdGEgPT09ICJvYmplY3QiKSB7CiAgICAgIGlmICgiZW5hYmxlZCIgaW4gZGF0YSkgdGhpcy5fbWV0cmljc0VuYWJsZWQgPSAhIWRhdGEuZW5hYmxlZDsKICAgICAgaWYgKHR5cGVvZiBkYXRhLmludGVydmFsSHogPT09ICJudW1iZXIiICYmIGRhdGEuaW50ZXJ2YWxIeiA+IDApIHsKICAgICAgICBjb25zdCBpbnRlcnZhbEh6ID0gZGF0YS5pbnRlcnZhbEh6OwogICAgICAgIHRoaXMuX21ldHJpY3NJbnRlcnZhbEZyYW1lcyA9IE1hdGgubWF4KDEyOCwgTWF0aC5yb3VuZCh0aGlzLl9zYW1wbGVSYXRlIC8gaW50ZXJ2YWxIeikpOwogICAgICB9CiAgICAgIC8vIFJlc2V0IHBhY2luZyBzbyB0aGUgbmV4dCByZXBvcnQgYWxpZ25zIHdpdGggbmV3IGludGVydmFsCiAgICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSB0aGlzLl9mcmFtZXNQcm9jZXNzZWQ7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBOZXcgYXVkaW8gZGF0YSBoYXMgYXJyaXZlZC4KICAgIGlmICh0eXBlID09PSAiYXVkaW9EYXRhIiAmJiBkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHsKICAgICAgdGhpcy5fbm9Nb3JlRGF0YVJlY2VpdmVkID0gZmFsc2U7CiAgICAgIC8vIElmIHdlIHdlcmUgaWRsZSwgdGhpcyBuZXcgZGF0YSBraWNrcyBvZmYgdGhlIHBsYXliYWNrLgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFBsYXliYWNrV29ya2xldC5GU00uSURMRSkgewogICAgICAgIHRoaXMuX3N0YXRlID0gUGxheWJhY2tXb3JrbGV0LkZTTS5QTEFZSU5HOwogICAgICAgIHRoaXMucG9ydC5wb3N0TWVzc2FnZSh7IHR5cGU6ICJwbGF5YmFjay1zdGFydGVkIiB9KTsKICAgICAgfQoKICAgICAgLy8gV2Ugb25seSBxdWV1ZSBkYXRhIGlmIHdlIGFyZSBpbiB0aGUgUExBWUlORyBzdGF0ZS4gVGhpcyBwcmV2ZW50cwogICAgICAvLyBkYXRhIGZyb20gYSBwcmV2aW91cywgaW50ZXJydXB0ZWQgc3RyZWFtIGZyb20gbGluZ2VyaW5nLgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFBsYXliYWNrV29ya2xldC5GU00uUExBWUlORykgewogICAgICAgIC8vIFN0b3JlIGFzIEludDE2QXJyYXkgdmlldyB0byBhdm9pZCBjb25zdHJ1Y3RpbmcgaXQgaW4gcHJvY2VzcygpCiAgICAgICAgdGhpcy5fYnVmZmVyUXVldWUucHVzaChuZXcgSW50MTZBcnJheShkYXRhKSk7CiAgICAgICAgdGhpcy5fc2lsZW5jZUZyYW1lc0NvdW50ID0gMDsgLy8gUmVzZXQgc2lsZW5jZSBjb3VudGVyIG9uIG5ldyBkYXRhCiAgICAgIH0KICAgIH0KICB9CgogIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CiAgICBjb25zdCBvdXRwdXRDaGFubmVsID0gb3V0cHV0c1swXT8uWzBdOwogICAgaWYgKCFvdXRwdXRDaGFubmVsKSB7CiAgICAgIHJldHVybiB0cnVlOyAvLyBLZWVwIGFsaXZlIGV2ZW4gaWYgb3V0cHV0IGlzIHRlbXBvcmFyaWx5IGRpc2Nvbm5lY3RlZAogICAgfQoKICAgIC8vIElmIHdlIGFyZSBub3QgcGxheWluZywganVzdCBvdXRwdXQgc2lsZW5jZSBhbmQgd2FpdC4KICAgIGlmICh0aGlzLl9zdGF0ZSAhPT0gUGxheWJhY2tXb3JrbGV0LkZTTS5QTEFZSU5HKSB7CiAgICAgIG91dHB1dENoYW5uZWwuZmlsbCgwKTsKICAgICAgcmV0dXJuIHRydWU7IC8vIEFsd2F5cyByZXR1cm4gdHJ1ZSB0byBrZWVwIHRoZSBwcm9jZXNzb3IgYWxpdmUKICAgIH0KCiAgICAvLyBDb3JlIFBMQVlJTkcgTG9naWMKICAgIGNvbnN0IGJsb2NrU2l6ZSA9IG91dHB1dENoYW5uZWwubGVuZ3RoOwogICAgbGV0IHNhbXBsZXNDb3BpZWQgPSAwOwoKICAgIHdoaWxlIChzYW1wbGVzQ29waWVkIDwgYmxvY2tTaXplKSB7CiAgICAgIGlmICghdGhpcy5fY3VycmVudENodW5rIHx8IHRoaXMuX2N1cnJlbnRDaHVua09mZnNldCA+PSB0aGlzLl9jdXJyZW50Q2h1bmsubGVuZ3RoKSB7CiAgICAgICAgaWYgKHRoaXMuX2J1ZmZlclF1ZXVlLmxlbmd0aCA+IDApIHsKICAgICAgICAgIHRoaXMuX2N1cnJlbnRDaHVuayA9IHRoaXMuX2J1ZmZlclF1ZXVlLnNoaWZ0KCk7CiAgICAgICAgICB0aGlzLl9jdXJyZW50Q2h1bmtPZmZzZXQgPSAwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBCdWZmZXIgaXMgZW1wdHkuIENoZWNrIGZvciBlbmQgY29uZGl0aW9ucy4KICAgICAgICAgIGNvbnN0IGlzVGltZWRPdXQgPSB0aGlzLl9zaWxlbmNlRnJhbWVzQ291bnQgPiB0aGlzLl9zaWxlbmNlVGhyZXNob2xkQmxvY2tzOwoKICAgICAgICAgIGlmICh0aGlzLl9ub01vcmVEYXRhUmVjZWl2ZWQgfHwgaXNUaW1lZE91dCkgewogICAgICAgICAgICAvLyBFTkQgT0YgUExBWUJBQ0s6IEVpdGhlciBleHBsaWNpdGx5IHNpZ25hbGVkIG9yIHRpbWVkIG91dC4KICAgICAgICAgICAgaWYgKCF0aGlzLl9oYXNTZW50RW5kZWQpIHsKICAgICAgICAgICAgICB0aGlzLnBvcnQucG9zdE1lc3NhZ2UoeyB0eXBlOiAicGxheWJhY2stZW5kZWQiIH0pOwogICAgICAgICAgICAgIHRoaXMuX2hhc1NlbnRFbmRlZCA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gU2VuZCBmaW5hbCBtZXRyaWNzIHNob3dpbmcgY2xlYXJlZCBzdGF0ZQogICAgICAgICAgICBpZiAodGhpcy5fbWV0cmljc0VuYWJsZWQpIHsKICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgdGhpcy5wb3J0LnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgICAgdHlwZTogIm1ldHJpY3MiLAogICAgICAgICAgICAgICAgICBkYXRhOiB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGU6IFBsYXliYWNrV29ya2xldC5GU00uSURMRSwKICAgICAgICAgICAgICAgICAgICBxdWV1ZWRTYW1wbGVzOiAwLAogICAgICAgICAgICAgICAgICAgIHF1ZXVlZE1zOiAwLAogICAgICAgICAgICAgICAgICAgIG1heFF1ZXVlZE1zOiBNYXRoLnJvdW5kKCh0aGlzLl9tYXhRdWV1ZVNhbXBsZXMgLyB0aGlzLl9zYW1wbGVSYXRlKSAqIDEwMDApLAogICAgICAgICAgICAgICAgICAgIHVuZGVycnVuQmxvY2tzOiB0aGlzLl91bmRlcnJ1bkJsb2NrcywKICAgICAgICAgICAgICAgICAgICBmcmFtZXNQcm9jZXNzZWQ6IHRoaXMuX2ZyYW1lc1Byb2Nlc3NlZAogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICB9IGNhdGNoIChfKSB7IH0KICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLnJlc2V0KCk7IC8vIFJlc2V0IHRvIElETEUgc3RhdGUgZm9yIHJldXNlCiAgICAgICAgICAgIGJyZWFrOyAvLyBFeGl0IHdoaWxlIGxvb3AKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vIEJVRkZFUiBVTkRFUlJVTiAoTEFHKTogUGxheSBzaWxlbmNlIGFuZCB3YWl0IGZvciBtb3JlIGRhdGEuCiAgICAgICAgICAgIHRoaXMuX3NpbGVuY2VGcmFtZXNDb3VudCsrOwogICAgICAgICAgICBpZiAodGhpcy5fbWV0cmljc0VuYWJsZWQpIHRoaXMuX3VuZGVycnVuQmxvY2tzKys7CiAgICAgICAgICAgIGJyZWFrOyAvLyBFeGl0IHdoaWxlIGxvb3AKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIElmIHdlIGhhdmUgYSBjaHVuayAoY291bGQgYmUgYSBuZXcgb25lIGZyb20gdGhlIGxvZ2ljIGFib3ZlKSwgcHJvY2VzcyBpdC4KICAgICAgaWYgKHRoaXMuX2N1cnJlbnRDaHVuaykgewogICAgICAgIGNvbnN0IHNhbXBsZXNUb0NvcHkgPSBNYXRoLm1pbigKICAgICAgICAgIGJsb2NrU2l6ZSAtIHNhbXBsZXNDb3BpZWQsCiAgICAgICAgICB0aGlzLl9jdXJyZW50Q2h1bmsubGVuZ3RoIC0gdGhpcy5fY3VycmVudENodW5rT2Zmc2V0CiAgICAgICAgKTsKICAgICAgICAvLyBEaXJlY3RseSB3cml0ZSB0byBvdXRwdXRDaGFubmVsIHRvIGF2b2lkIGV4dHJhIGNvcHkKICAgICAgICBjb25zdCBzcmMgPSB0aGlzLl9jdXJyZW50Q2h1bms7CiAgICAgICAgY29uc3QgYmFzZVNyYyA9IHRoaXMuX2N1cnJlbnRDaHVua09mZnNldDsKICAgICAgICBjb25zdCBiYXNlRHN0ID0gc2FtcGxlc0NvcGllZDsKICAgICAgICBjb25zdCBzY2FsZSA9IHRoaXMuX3NjYWxlOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2FtcGxlc1RvQ29weTsgaSsrKSB7CiAgICAgICAgICBvdXRwdXRDaGFubmVsW2Jhc2VEc3QgKyBpXSA9IHNyY1tiYXNlU3JjICsgaV0gKiBzY2FsZTsKICAgICAgICB9CgogICAgICAgIHRoaXMuX2N1cnJlbnRDaHVua09mZnNldCArPSBzYW1wbGVzVG9Db3B5OwogICAgICAgIHNhbXBsZXNDb3BpZWQgKz0gc2FtcGxlc1RvQ29weTsKICAgICAgfQogICAgfQoKICAgIC8vIFplcm8tZmlsbCB0aGUgcmVtYWluZGVyLCBpZiBhbnksIG9uY2UgcGVyIGJsb2NrCiAgICBpZiAoc2FtcGxlc0NvcGllZCA8IGJsb2NrU2l6ZSkgewogICAgICBvdXRwdXRDaGFubmVsLmZpbGwoMCwgc2FtcGxlc0NvcGllZCk7CiAgICB9CgogICAgLy8gVXBkYXRlIG1ldHJpY3MgKG9wdGlvbmFsKQogICAgaWYgKHRoaXMuX21ldHJpY3NFbmFibGVkKSB7CiAgICAgIHRoaXMuX2ZyYW1lc1Byb2Nlc3NlZCArPSBibG9ja1NpemU7CgogICAgICAvLyBUcmFjayBxdWV1ZSBkZXB0aCBpbiBzYW1wbGVzIChhcHByb3hpbWF0ZSkKICAgICAgbGV0IHF1ZXVlZFNhbXBsZXMgPSAwOwogICAgICBpZiAodGhpcy5fY3VycmVudENodW5rKSBxdWV1ZWRTYW1wbGVzICs9IE1hdGgubWF4KDAsIHRoaXMuX2N1cnJlbnRDaHVuay5sZW5ndGggLSB0aGlzLl9jdXJyZW50Q2h1bmtPZmZzZXQpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX2J1ZmZlclF1ZXVlLmxlbmd0aDsgaSsrKSBxdWV1ZWRTYW1wbGVzICs9IHRoaXMuX2J1ZmZlclF1ZXVlW2ldLmxlbmd0aDsKICAgICAgaWYgKHF1ZXVlZFNhbXBsZXMgPiB0aGlzLl9tYXhRdWV1ZVNhbXBsZXMpIHRoaXMuX21heFF1ZXVlU2FtcGxlcyA9IHF1ZXVlZFNhbXBsZXM7CgogICAgICAvLyBQZXJpb2RpY2FsbHkgc2VuZCBtZXRyaWNzIHRvIG1haW4gdGhyZWFkCiAgICAgIGlmICh0aGlzLl9mcmFtZXNQcm9jZXNzZWQgLSB0aGlzLl9sYXN0TWV0cmljc1NlbnRBdEZyYW1lID49IHRoaXMuX21ldHJpY3NJbnRlcnZhbEZyYW1lcykgewogICAgICAgIHRoaXMuX2xhc3RNZXRyaWNzU2VudEF0RnJhbWUgPSB0aGlzLl9mcmFtZXNQcm9jZXNzZWQ7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHRoaXMucG9ydC5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgIHR5cGU6ICJtZXRyaWNzIiwKICAgICAgICAgICAgZGF0YTogewogICAgICAgICAgICAgIHN0YXRlOiB0aGlzLl9zdGF0ZSwKICAgICAgICAgICAgICBxdWV1ZWRTYW1wbGVzLAogICAgICAgICAgICAgIHF1ZXVlZE1zOiBNYXRoLnJvdW5kKChxdWV1ZWRTYW1wbGVzIC8gdGhpcy5fc2FtcGxlUmF0ZSkgKiAxMDAwKSwKICAgICAgICAgICAgICBtYXhRdWV1ZWRNczogTWF0aC5yb3VuZCgodGhpcy5fbWF4UXVldWVTYW1wbGVzIC8gdGhpcy5fc2FtcGxlUmF0ZSkgKiAxMDAwKSwKICAgICAgICAgICAgICB1bmRlcnJ1bkJsb2NrczogdGhpcy5fdW5kZXJydW5CbG9ja3MsCiAgICAgICAgICAgICAgZnJhbWVzUHJvY2Vzc2VkOiB0aGlzLl9mcmFtZXNQcm9jZXNzZWQKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfSBjYXRjaCAoXykgeyB9CiAgICAgICAgLy8gRG9uJ3QgcmVzZXQgbWF4IHRyYWNrZXIgLSBrZWVwIHNlc3Npb24gcGVhayB1bnRpbCBpZGxlCiAgICAgIH0KICAgIH0KCiAgICAvLyBBTFdBWVMgcmV0dXJuIHRydWUgdG8ga2VlcCB0aGUgcHJvY2Vzc29yIGFsaXZlIGZvciByZXVzZS4KICAgIHJldHVybiB0cnVlOwogIH0KfQoKcmVnaXN0ZXJQcm9jZXNzb3IoInBsYXliYWNrLXdvcmtsZXQiLCBQbGF5YmFja1dvcmtsZXQpOwo=", import.meta.url), He = {
|
|
2627
|
+
en: Je,
|
|
2628
|
+
de: et,
|
|
2629
|
+
fr: nt,
|
|
2630
|
+
fi: ot,
|
|
2631
|
+
lt: at
|
|
2632
|
+
}, U = new f.Quaternion(), E = new f.Euler(), ae = new f.Vector3(), he = new f.Vector3(), Te = new f.Box3();
|
|
2633
2633
|
new f.Matrix4();
|
|
2634
2634
|
new f.Matrix4();
|
|
2635
2635
|
new f.Vector3();
|
|
2636
2636
|
new f.Vector3(0, 0, 1);
|
|
2637
|
-
const
|
|
2637
|
+
const lt = new f.Vector3(1, 0, 0);
|
|
2638
2638
|
new f.Vector3(0, 1, 0);
|
|
2639
2639
|
new f.Vector3(0, 0, 1);
|
|
2640
|
-
class
|
|
2640
|
+
class Fe {
|
|
2641
2641
|
/**
|
|
2642
2642
|
* Avatar.
|
|
2643
2643
|
* @typedef {Object} Avatar
|
|
@@ -2763,7 +2763,7 @@ class Me {
|
|
|
2763
2763
|
avatarOnlyCamera: null,
|
|
2764
2764
|
statsNode: null,
|
|
2765
2765
|
statsStyle: null
|
|
2766
|
-
}, Object.assign(this.opt, e || {}), this.opt.statsNode && (this.stats = new
|
|
2766
|
+
}, Object.assign(this.opt, e || {}), this.opt.statsNode && (this.stats = new Xe(), this.opt.statsStyle && (this.stats.dom.style.cssText = this.opt.statsStyle), this.opt.statsNode.appendChild(this.stats.dom)), this.poseTemplates = {
|
|
2767
2767
|
side: {
|
|
2768
2768
|
standing: !0,
|
|
2769
2769
|
props: {
|
|
@@ -3575,12 +3575,12 @@ class Me {
|
|
|
3575
3575
|
this.poseDelta.props[l + u + "1.quaternion"] = { x: 0, y: 0, z: 0 }, this.poseDelta.props[l + u + "2.quaternion"] = { x: 0, y: 0, z: 0 }, this.poseDelta.props[l + u + "3.quaternion"] = { x: 0, y: 0, z: 0 };
|
|
3576
3576
|
});
|
|
3577
3577
|
});
|
|
3578
|
-
const
|
|
3578
|
+
const n = /* @__PURE__ */ new Set();
|
|
3579
3579
|
Object.values(this.poseTemplates).forEach((l) => {
|
|
3580
|
-
Object.keys(this.propsToThreeObjects(l.props)).forEach((u) =>
|
|
3580
|
+
Object.keys(this.propsToThreeObjects(l.props)).forEach((u) => n.add(u));
|
|
3581
3581
|
}), Object.keys(this.poseDelta.props).forEach((l) => {
|
|
3582
|
-
|
|
3583
|
-
}), this.posePropNames = [...
|
|
3582
|
+
n.add(l);
|
|
3583
|
+
}), this.posePropNames = [...n], this.poseName = "side", this.poseWeightOnLeft = !0, this.gesture = null, this.poseCurrentTemplate = this.poseTemplates[this.poseName], this.poseStraight = this.propsToThreeObjects(this.poseTemplates.straight.props), this.poseBase = this.poseFactory(this.poseCurrentTemplate), this.poseTarget = this.poseFactory(this.poseCurrentTemplate), this.poseAvatar = null, this.avatarHeight = 1.7, this.animTemplateEyes = {
|
|
3584
3584
|
name: "eyes",
|
|
3585
3585
|
idle: { alt: [
|
|
3586
3586
|
{
|
|
@@ -4034,9 +4034,9 @@ class Me {
|
|
|
4034
4034
|
"CH",
|
|
4035
4035
|
"sil"
|
|
4036
4036
|
], this.segmenter = new Intl.Segmenter("en", { granularity: "grapheme" }), this.initAudioGraph(), this.audioPlaylist = [], this.volumeFrequencyData = new Uint8Array(16), this.volumeMax = 0, this.volumeHeadBase = 0, this.volumeHeadTarget = 0, this.volumeHeadCurrent = 0, this.volumeHeadVelocity = 0.15, this.volumeHeadEasing = this.sigmoidFactory(3), this.isListening = !1, this.listeningAnalyzer = null, this.listeningActive = !1, this.listeningVolume = 0, this.listeningSilenceThresholdLevel = this.opt.listeningSilenceThresholdLevel, this.listeningSilenceThresholdMs = this.opt.listeningSilenceThresholdMs, this.listeningSilenceDurationMax = this.opt.listeningSilenceDurationMax, this.listeningActiveThresholdLevel = this.opt.listeningActiveThresholdLevel, this.listeningActiveThresholdMs = this.opt.listeningActiveThresholdMs, this.listeningActiveDurationMax = this.opt.listeningActiveDurationMax, this.listeningTimer = 0, this.listeningTimerTotal = 0, this.dracoEnabled = this.opt.dracoEnabled, this.dracoDecoderPath = this.opt.dracoDecoderPath;
|
|
4037
|
-
const
|
|
4037
|
+
const i = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
4038
4038
|
this.b64Lookup = typeof Uint8Array > "u" ? [] : new Uint8Array(256);
|
|
4039
|
-
for (let l = 0; l <
|
|
4039
|
+
for (let l = 0; l < i.length; l++) this.b64Lookup[i.charCodeAt(l)] = l;
|
|
4040
4040
|
if (this.stateName = "idle", this.speechQueue = [], this.isSpeaking = !1, this.isListening = !1, this.opt.ttsEndpoint) {
|
|
4041
4041
|
let l = new Audio();
|
|
4042
4042
|
if (l.canPlayType("audio/ogg"))
|
|
@@ -4062,7 +4062,7 @@ class Me {
|
|
|
4062
4062
|
this.opt.lightSpotDispersion
|
|
4063
4063
|
), this.setLighting(this.opt);
|
|
4064
4064
|
const l = new f.PMREMGenerator(this.renderer);
|
|
4065
|
-
l.compileEquirectangularShader(), this.scene.environment = l.fromScene(new
|
|
4065
|
+
l.compileEquirectangularShader(), this.scene.environment = l.fromScene(new Ze()).texture, this.resizeobserver = new ResizeObserver(this.onResize.bind(this)), this.resizeobserver.observe(this.nodeAvatar), this.controls = new We(this.camera, this.renderer.domElement), this.controls.enableZoom = this.opt.cameraZoomEnable, this.controls.enableRotate = this.opt.cameraRotateEnable, this.controls.enablePan = this.opt.cameraPanEnable, this.controls.minDistance = 2, this.controls.maxDistance = 2e3, this.controls.autoRotateSpeed = 0, this.controls.autoRotate = !1, this.controls.update(), this.cameraClock = null;
|
|
4066
4066
|
}
|
|
4067
4067
|
this.ikMesh = new f.SkinnedMesh();
|
|
4068
4068
|
const s = {
|
|
@@ -4080,14 +4080,14 @@ class Me {
|
|
|
4080
4080
|
Object.entries(s).forEach((l, u) => {
|
|
4081
4081
|
const a = new f.Bone();
|
|
4082
4082
|
a.name = l[0], l[1] ? this.ikMesh.getObjectByName(l[1]).add(a) : this.ikMesh.add(a), o.push(a);
|
|
4083
|
-
}), this.ikMesh.bind(new f.Skeleton(o)), this.dynamicbones = new
|
|
4083
|
+
}), this.ikMesh.bind(new f.Skeleton(o)), this.dynamicbones = new qe(), this.isStreaming = !1, this.streamWorkletNode = null, this.streamAudioStartTime = null, this.streamWaitForAudioChunks = !0, this.streamLipsyncLang = null, this.streamLipsyncType = "visemes", this.streamLipsyncQueue = [];
|
|
4084
4084
|
}
|
|
4085
4085
|
/**
|
|
4086
4086
|
* Helper that re/creates the audio context and the other nodes.
|
|
4087
4087
|
* @param {number} sampleRate
|
|
4088
4088
|
*/
|
|
4089
4089
|
initAudioGraph(t = null) {
|
|
4090
|
-
if (this.audioCtx && this.audioCtx.state !== "closed" && this.audioCtx.close(), t ? this.audioCtx = new AudioContext({ sampleRate: t }) : this.audioCtx = new AudioContext(), this.audioSpeechSource = this.audioCtx.createBufferSource(), this.audioBackgroundSource = this.audioCtx.createBufferSource(), this.audioBackgroundGainNode = this.audioCtx.createGain(), this.audioSpeechGainNode = this.audioCtx.createGain(), this.audioStreamGainNode = this.audioCtx.createGain(), this.audioAnalyzerNode = this.audioCtx.createAnalyser(), this.audioAnalyzerNode.fftSize = 256, this.audioAnalyzerNode.smoothingTimeConstant = 0.1, this.audioAnalyzerNode.minDecibels = -70, this.audioAnalyzerNode.maxDecibels = -10, this.audioAnalyzer = new
|
|
4090
|
+
if (this.audioCtx && this.audioCtx.state !== "closed" && this.audioCtx.close(), t ? this.audioCtx = new AudioContext({ sampleRate: t }) : this.audioCtx = new AudioContext(), this.audioSpeechSource = this.audioCtx.createBufferSource(), this.audioBackgroundSource = this.audioCtx.createBufferSource(), this.audioBackgroundGainNode = this.audioCtx.createGain(), this.audioSpeechGainNode = this.audioCtx.createGain(), this.audioStreamGainNode = this.audioCtx.createGain(), this.audioAnalyzerNode = this.audioCtx.createAnalyser(), this.audioAnalyzerNode.fftSize = 256, this.audioAnalyzerNode.smoothingTimeConstant = 0.1, this.audioAnalyzerNode.minDecibels = -70, this.audioAnalyzerNode.maxDecibels = -10, this.audioAnalyzer = new _e(this.audioCtx), this.audioReverbNode = this.audioCtx.createConvolver(), this.audioBackgroundGainNode.connect(this.audioReverbNode), this.audioAnalyzerNode.connect(this.audioSpeechGainNode), this.audioSpeechGainNode.connect(this.audioReverbNode), this.audioStreamGainNode.connect(this.audioReverbNode), this.audioReverbNode.connect(this.audioCtx.destination), this.setReverb(this.currentReverb || null), this.setMixerGain(
|
|
4091
4091
|
this.opt.mixerGainSpeech,
|
|
4092
4092
|
this.opt.mixerGainBackground
|
|
4093
4093
|
), this.workletLoaded = !1, this.streamWorkletNode) {
|
|
@@ -4114,8 +4114,8 @@ class Me {
|
|
|
4114
4114
|
* @return {Object} Deep copy of the object.
|
|
4115
4115
|
*/
|
|
4116
4116
|
deepCopy(t, e = null) {
|
|
4117
|
-
const
|
|
4118
|
-
return e && typeof e == "function" && e(
|
|
4117
|
+
const n = JSON.parse(JSON.stringify(t));
|
|
4118
|
+
return e && typeof e == "function" && e(n), n;
|
|
4119
4119
|
}
|
|
4120
4120
|
/**
|
|
4121
4121
|
* Convert a Base64 MP3 chunk to ArrayBuffer.
|
|
@@ -4125,11 +4125,11 @@ class Me {
|
|
|
4125
4125
|
b64ToArrayBuffer(t) {
|
|
4126
4126
|
let e = 3 * t.length / 4;
|
|
4127
4127
|
t[t.length - 1] === "=" && (e--, t[t.length - 2] === "=" && e--);
|
|
4128
|
-
const
|
|
4128
|
+
const n = new ArrayBuffer(e), i = new Uint8Array(n);
|
|
4129
4129
|
let s, o = 0, l, u, a, h;
|
|
4130
4130
|
for (s = 0; s < t.length; s += 4)
|
|
4131
|
-
l = this.b64Lookup[t.charCodeAt(s)], u = this.b64Lookup[t.charCodeAt(s + 1)], a = this.b64Lookup[t.charCodeAt(s + 2)], h = this.b64Lookup[t.charCodeAt(s + 3)],
|
|
4132
|
-
return
|
|
4131
|
+
l = this.b64Lookup[t.charCodeAt(s)], u = this.b64Lookup[t.charCodeAt(s + 1)], a = this.b64Lookup[t.charCodeAt(s + 2)], h = this.b64Lookup[t.charCodeAt(s + 3)], i[o++] = l << 2 | u >> 4, i[o++] = (u & 15) << 4 | a >> 2, i[o++] = (a & 3) << 6 | h & 63;
|
|
4132
|
+
return n;
|
|
4133
4133
|
}
|
|
4134
4134
|
/**
|
|
4135
4135
|
* Concatenate an array of ArrayBuffers.
|
|
@@ -4141,10 +4141,10 @@ class Me {
|
|
|
4141
4141
|
let e = 0;
|
|
4142
4142
|
for (let o = 0; o < t.length; o++)
|
|
4143
4143
|
e += t[o].byteLength;
|
|
4144
|
-
let
|
|
4144
|
+
let n = new ArrayBuffer(e), i = new Uint8Array(n), s = 0;
|
|
4145
4145
|
for (let o = 0; o < t.length; o++)
|
|
4146
|
-
|
|
4147
|
-
return
|
|
4146
|
+
i.set(new Uint8Array(t[o]), s), s += t[o].byteLength;
|
|
4147
|
+
return n;
|
|
4148
4148
|
}
|
|
4149
4149
|
/**
|
|
4150
4150
|
* Convert PCM buffer to AudioBuffer.
|
|
@@ -4153,11 +4153,11 @@ class Me {
|
|
|
4153
4153
|
* @return {AudioBuffer} AudioBuffer
|
|
4154
4154
|
*/
|
|
4155
4155
|
pcmToAudioBuffer(t) {
|
|
4156
|
-
const e = new Int16Array(t),
|
|
4156
|
+
const e = new Int16Array(t), n = new Float32Array(e.length);
|
|
4157
4157
|
for (let s = 0; s < e.length; s++)
|
|
4158
|
-
|
|
4159
|
-
const
|
|
4160
|
-
return
|
|
4158
|
+
n[s] = e[s] >= 32768 ? -(65536 - e[s]) / 32768 : e[s] / 32767;
|
|
4159
|
+
const i = this.audioCtx.createBuffer(1, n.length, this.opt.pcmSampleRate);
|
|
4160
|
+
return i.copyToChannel(n, 0, 0), i;
|
|
4161
4161
|
}
|
|
4162
4162
|
/**
|
|
4163
4163
|
* Convert internal notation to THREE objects.
|
|
@@ -4167,10 +4167,10 @@ class Me {
|
|
|
4167
4167
|
*/
|
|
4168
4168
|
propsToThreeObjects(t) {
|
|
4169
4169
|
const e = {};
|
|
4170
|
-
for (let [
|
|
4171
|
-
const s =
|
|
4172
|
-
let o = Array.isArray(
|
|
4173
|
-
s[1] === "position" || s[1] === "scale" ? e[
|
|
4170
|
+
for (let [n, i] of Object.entries(t)) {
|
|
4171
|
+
const s = n.split(".");
|
|
4172
|
+
let o = Array.isArray(i.x) ? this.gaussianRandom(...i.x) : i.x, l = Array.isArray(i.y) ? this.gaussianRandom(...i.y) : i.y, u = Array.isArray(i.z) ? this.gaussianRandom(...i.z) : i.z;
|
|
4173
|
+
s[1] === "position" || s[1] === "scale" ? e[n] = new f.Vector3(o, l, u) : s[1] === "rotation" ? (n = s[0] + ".quaternion", e[n] = new f.Quaternion().setFromEuler(new f.Euler(o, l, u, "XYZ")).normalize()) : s[1] === "quaternion" && (e[n] = new f.Quaternion(o, l, u, i.w).normalize());
|
|
4174
4174
|
}
|
|
4175
4175
|
return e;
|
|
4176
4176
|
}
|
|
@@ -4194,12 +4194,12 @@ class Me {
|
|
|
4194
4194
|
* @param {Object} sources Object of existing morph target values, e.g. { mouthOpen: 1.0 }
|
|
4195
4195
|
* @param {boolean} [override=false] If true, override existing morph target
|
|
4196
4196
|
*/
|
|
4197
|
-
addMixedMorphTarget(t, e,
|
|
4197
|
+
addMixedMorphTarget(t, e, n, i = !1) {
|
|
4198
4198
|
t.forEach((s) => {
|
|
4199
|
-
if (!
|
|
4199
|
+
if (!i && s.morphTargetDictionary.hasOwnProperty(e)) return;
|
|
4200
4200
|
const o = s.geometry;
|
|
4201
4201
|
let l = null, u = null;
|
|
4202
|
-
for (const [a, h] of Object.entries(
|
|
4202
|
+
for (const [a, h] of Object.entries(n))
|
|
4203
4203
|
if (s.morphTargetDictionary.hasOwnProperty(a)) {
|
|
4204
4204
|
const r = s.morphTargetDictionary[a], c = o.morphAttributes.position[r], d = o.morphAttributes.normal?.[r];
|
|
4205
4205
|
l || (l = new f.Float32BufferAttribute(c.count * 3, 3), d && (u = new f.Float32BufferAttribute(c.count * 3, 3)));
|
|
@@ -4228,17 +4228,17 @@ class Me {
|
|
|
4228
4228
|
async showAvatar(t, e = null) {
|
|
4229
4229
|
if (!t || !t.hasOwnProperty("url"))
|
|
4230
4230
|
throw new Error("Invalid parameter. The avatar must have at least 'url' specified.");
|
|
4231
|
-
const
|
|
4231
|
+
const n = new Ve();
|
|
4232
4232
|
if (this.dracoEnabled) {
|
|
4233
|
-
const a = new
|
|
4234
|
-
a.setDecoderPath(this.dracoDecoderPath),
|
|
4233
|
+
const a = new Ge();
|
|
4234
|
+
a.setDecoderPath(this.dracoDecoderPath), n.setDRACOLoader(a);
|
|
4235
4235
|
}
|
|
4236
|
-
let
|
|
4236
|
+
let i = await n.loadAsync(t.url, e);
|
|
4237
4237
|
const s = [this.opt.modelRoot];
|
|
4238
4238
|
if (this.posePropNames.forEach((a) => s.push(a.split(".")[0])), s.forEach((a) => {
|
|
4239
|
-
if (!
|
|
4239
|
+
if (!i.scene.getObjectByName(a))
|
|
4240
4240
|
throw new Error("Avatar object " + a + " not found");
|
|
4241
|
-
}), this.stop(), this.avatar = t, this.bodyMovement = t.bodyMovement || "idle", this.movementIntensity = t.movementIntensity || 0.5, this.showFullAvatar = t.showFullAvatar || !1, this.fbxAnimationLoader = null, this.dynamicbones.dispose(), this.mixer = null, this.isAvatarOnly ? this.armature && this.clearThree(this.armature) : this.armature && this.clearThree(this.scene), this.armature =
|
|
4241
|
+
}), this.stop(), this.avatar = t, this.bodyMovement = t.bodyMovement || "idle", this.movementIntensity = t.movementIntensity || 0.5, this.showFullAvatar = t.showFullAvatar || !1, this.fbxAnimationLoader = null, this.dynamicbones.dispose(), this.mixer = null, this.isAvatarOnly ? this.armature && this.clearThree(this.armature) : this.armature && this.clearThree(this.scene), this.armature = i.scene.getObjectByName(this.opt.modelRoot), this.armature.scale.setScalar(1), this.animations = i.animations, this.userData = i.userData, this.morphs = [], this.armature.traverse((a) => {
|
|
4242
4242
|
a.morphTargetInfluences && a.morphTargetInfluences.length && a.morphTargetDictionary && this.morphs.push(a), a.frustumCulled = !1;
|
|
4243
4243
|
}), this.morphs.length === 0)
|
|
4244
4244
|
throw new Error("Blend shapes not found");
|
|
@@ -4283,7 +4283,7 @@ class Me {
|
|
|
4283
4283
|
this.poseAvatar.props[a] = r[h[1]], this.poseBase.props.hasOwnProperty(a) ? this.poseAvatar.props[a].copy(this.poseBase.props[a]) : this.poseBase.props[a] = this.poseAvatar.props[a].clone(), this.poseDelta.props.hasOwnProperty(a) && !this.poseTarget.props.hasOwnProperty(a) && (this.poseTarget.props[a] = this.poseAvatar.props[a].clone()), this.poseTarget.props[a].t = this.animClock, this.poseTarget.props[a].d = 2e3;
|
|
4284
4284
|
}), this.ikMesh.traverse((a) => {
|
|
4285
4285
|
a.isBone && a.position.copy(this.armature.getObjectByName(a.name).position);
|
|
4286
|
-
}), this.isAvatarOnly ? this.scene && this.scene.add(this.armature) : (this.scene.add(
|
|
4286
|
+
}), this.isAvatarOnly ? this.scene && this.scene.add(this.armature) : (this.scene.add(i.scene), this.scene.add(this.lightAmbient), this.scene.add(this.lightDirect), this.scene.add(this.lightSpot), this.lightSpot.target = this.armature.getObjectByName("Head")), t.hasOwnProperty("modelDynamicBones"))
|
|
4287
4287
|
try {
|
|
4288
4288
|
this.dynamicbones.setup(this.scene, this.armature, t.modelDynamicBones);
|
|
4289
4289
|
} catch (a) {
|
|
@@ -4319,8 +4319,8 @@ class Me {
|
|
|
4319
4319
|
return;
|
|
4320
4320
|
}
|
|
4321
4321
|
if (this.viewName = t || this.viewName, e = e || {}, this.isAvatarOnly) return;
|
|
4322
|
-
const
|
|
4323
|
-
let a = -
|
|
4322
|
+
const n = e.hasOwnProperty("cameraX") ? e.cameraX : this.opt.cameraX, i = e.hasOwnProperty("cameraY") ? e.cameraY : this.opt.cameraY, s = e.hasOwnProperty("cameraDistance") ? e.cameraDistance : this.opt.cameraDistance, o = e.hasOwnProperty("cameraRotateX") ? e.cameraRotateX : this.opt.cameraRotateX, l = e.hasOwnProperty("cameraRotateY") ? e.cameraRotateY : this.opt.cameraRotateY, u = this.camera.fov * (Math.PI / 180);
|
|
4323
|
+
let a = -n * Math.tan(u / 2), h = (1 - i) * Math.tan(u / 2), r = s;
|
|
4324
4324
|
switch (this.viewName) {
|
|
4325
4325
|
case "head":
|
|
4326
4326
|
r += 2, h = h * r + 4 * this.avatarHeight / 5;
|
|
@@ -4360,11 +4360,11 @@ class Me {
|
|
|
4360
4360
|
* @param {number} t High precision timestamp in ms.
|
|
4361
4361
|
*/
|
|
4362
4362
|
updatePoseBase(t) {
|
|
4363
|
-
for (const [e,
|
|
4364
|
-
const
|
|
4365
|
-
if (
|
|
4366
|
-
let s = (t -
|
|
4367
|
-
s > 1 || !this.poseBase.props.hasOwnProperty(e) ?
|
|
4363
|
+
for (const [e, n] of Object.entries(this.poseTarget.props)) {
|
|
4364
|
+
const i = this.poseAvatar.props[e];
|
|
4365
|
+
if (i) {
|
|
4366
|
+
let s = (t - n.t) / n.d;
|
|
4367
|
+
s > 1 || !this.poseBase.props.hasOwnProperty(e) ? i.copy(n) : i.isQuaternion ? i.copy(this.poseBase.props[e].slerp(n, this.easing(s))) : i.isVector3 && i.copy(this.poseBase.props[e].lerp(n, this.easing(s)));
|
|
4368
4368
|
}
|
|
4369
4369
|
}
|
|
4370
4370
|
}
|
|
@@ -4374,9 +4374,9 @@ class Me {
|
|
|
4374
4374
|
updatePoseDelta() {
|
|
4375
4375
|
for (const [t, e] of Object.entries(this.poseDelta.props)) {
|
|
4376
4376
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4377
|
-
|
|
4378
|
-
const
|
|
4379
|
-
|
|
4377
|
+
E.set(e.x, e.y, e.z);
|
|
4378
|
+
const n = this.poseAvatar.props[t];
|
|
4379
|
+
n.isQuaternion ? (U.setFromEuler(E), n.multiply(U)) : n.isVector3 && n.add(E);
|
|
4380
4380
|
}
|
|
4381
4381
|
}
|
|
4382
4382
|
/**
|
|
@@ -4384,43 +4384,43 @@ class Me {
|
|
|
4384
4384
|
* @param {number} dt Delta time in ms.
|
|
4385
4385
|
*/
|
|
4386
4386
|
updateMorphTargets(t) {
|
|
4387
|
-
for (let [e,
|
|
4388
|
-
if (!
|
|
4389
|
-
let
|
|
4390
|
-
if (
|
|
4391
|
-
if (
|
|
4392
|
-
|
|
4387
|
+
for (let [e, n] of Object.entries(this.mtAvatar)) {
|
|
4388
|
+
if (!n.needsUpdate) continue;
|
|
4389
|
+
let i = null, s = null;
|
|
4390
|
+
if (n.fixed !== null) {
|
|
4391
|
+
if (i = n.fixed, n.system = null, n.systemd = null, n.newvalue = null, n.ref && n.ref.hasOwnProperty(e) && delete n.ref[e], n.ref = null, n.base = null, n.value === i) {
|
|
4392
|
+
n.needsUpdate = !1;
|
|
4393
4393
|
continue;
|
|
4394
4394
|
}
|
|
4395
|
-
} else
|
|
4396
|
-
if (
|
|
4397
|
-
let o =
|
|
4398
|
-
o >= 0 ? o < 5e-3 ? (s =
|
|
4395
|
+
} else n.realtime !== null ? (n.ref = null, n.base = null, s = n.realtime) : n.system !== null ? (i = n.system, n.newvalue = null, n.ref && n.ref.hasOwnProperty(e) && delete n.ref[e], n.ref = null, n.base = null, n.systemd !== null ? n.systemd === 0 ? (i = null, n.system = null, n.systemd = null) : (n.systemd -= t, n.systemd < 0 && (n.systemd = 0), n.value === i && (i = null)) : n.value === i && (i = null, n.system = null)) : n.newvalue !== null ? (n.ref = null, n.base = null, s = n.newvalue, n.newvalue = null) : n.base !== null ? (i = n.base, n.ref = null, n.value === i && (i = null, n.base = null, n.needsUpdate = !1)) : (n.ref = null, n.baseline !== null && n.value !== n.baseline ? (i = n.baseline, n.base = n.baseline) : n.needsUpdate = !1);
|
|
4396
|
+
if (i !== null) {
|
|
4397
|
+
let o = i - n.value;
|
|
4398
|
+
o >= 0 ? o < 5e-3 ? (s = i, n.v = 0) : (n.v < n.maxv && (n.v += n.acc * t), n.v >= 0 ? s = n.value + o * (1 - Math.exp(-n.v * t)) : s = n.value + n.v * t * (1 - Math.exp(n.v * t))) : o > -5e-3 ? (s = i, n.v = 0) : (n.v > -n.maxv && (n.v -= n.acc * t), n.v >= 0 ? s = n.value + n.v * t * (1 - Math.exp(-n.v * t)) : s = n.value + o * (1 - Math.exp(n.v * t)));
|
|
4399
4399
|
}
|
|
4400
|
-
if (
|
|
4401
|
-
if (s !== null && s !==
|
|
4400
|
+
if (n.limit !== null) {
|
|
4401
|
+
if (s !== null && s !== n.value && (n.value = s, n.onchange !== null && n.onchange(s)), s = n.limit(n.value), s === n.applied) continue;
|
|
4402
4402
|
} else {
|
|
4403
|
-
if (s === null || s ===
|
|
4404
|
-
|
|
4403
|
+
if (s === null || s === n.value) continue;
|
|
4404
|
+
n.value = s, n.onchange !== null && n.onchange(s);
|
|
4405
4405
|
}
|
|
4406
|
-
switch (
|
|
4406
|
+
switch (n.applied = s, n.applied < n.min && (n.applied = n.min), n.applied > n.max && (n.applied = n.max), e) {
|
|
4407
4407
|
case "headRotateX":
|
|
4408
|
-
this.poseDelta.props["Head.quaternion"].x =
|
|
4408
|
+
this.poseDelta.props["Head.quaternion"].x = n.applied + this.mtAvatar.bodyRotateX.applied;
|
|
4409
4409
|
break;
|
|
4410
4410
|
case "headRotateY":
|
|
4411
|
-
this.poseDelta.props["Head.quaternion"].y =
|
|
4411
|
+
this.poseDelta.props["Head.quaternion"].y = n.applied + this.mtAvatar.bodyRotateY.applied;
|
|
4412
4412
|
break;
|
|
4413
4413
|
case "headRotateZ":
|
|
4414
|
-
this.poseDelta.props["Head.quaternion"].z =
|
|
4414
|
+
this.poseDelta.props["Head.quaternion"].z = n.applied + this.mtAvatar.bodyRotateZ.applied;
|
|
4415
4415
|
break;
|
|
4416
4416
|
case "bodyRotateX":
|
|
4417
|
-
this.poseDelta.props["Head.quaternion"].x =
|
|
4417
|
+
this.poseDelta.props["Head.quaternion"].x = n.applied + this.mtAvatar.headRotateX.applied, this.poseDelta.props["Spine1.quaternion"].x = n.applied / 2, this.poseDelta.props["Spine.quaternion"].x = n.applied / 8, this.poseDelta.props["Hips.quaternion"].x = n.applied / 24;
|
|
4418
4418
|
break;
|
|
4419
4419
|
case "bodyRotateY":
|
|
4420
|
-
this.poseDelta.props["Head.quaternion"].y =
|
|
4420
|
+
this.poseDelta.props["Head.quaternion"].y = n.applied + this.mtAvatar.headRotateY.applied, this.poseDelta.props["Spine1.quaternion"].y = n.applied / 2, this.poseDelta.props["Spine.quaternion"].y = n.applied / 2, this.poseDelta.props["Hips.quaternion"].y = n.applied / 4, this.poseDelta.props["LeftUpLeg.quaternion"].y = n.applied / 2, this.poseDelta.props["RightUpLeg.quaternion"].y = n.applied / 2, this.poseDelta.props["LeftLeg.quaternion"].y = n.applied / 4, this.poseDelta.props["RightLeg.quaternion"].y = n.applied / 4;
|
|
4421
4421
|
break;
|
|
4422
4422
|
case "bodyRotateZ":
|
|
4423
|
-
this.poseDelta.props["Head.quaternion"].z =
|
|
4423
|
+
this.poseDelta.props["Head.quaternion"].z = n.applied + this.mtAvatar.headRotateZ.applied, this.poseDelta.props["Spine1.quaternion"].z = n.applied / 12, this.poseDelta.props["Spine.quaternion"].z = n.applied / 12, this.poseDelta.props["Hips.quaternion"].z = n.applied / 24;
|
|
4424
4424
|
break;
|
|
4425
4425
|
case "handFistLeft":
|
|
4426
4426
|
case "handFistRight":
|
|
@@ -4432,16 +4432,16 @@ class Me {
|
|
|
4432
4432
|
"HandRing",
|
|
4433
4433
|
"HandPinky"
|
|
4434
4434
|
].forEach((h, r) => {
|
|
4435
|
-
r === 0 ? (this.poseDelta.props[o + h + "1.quaternion"].x = 0, this.poseDelta.props[o + h + "2.quaternion"].z = (o === "Left" ? -1 : 1) *
|
|
4435
|
+
r === 0 ? (this.poseDelta.props[o + h + "1.quaternion"].x = 0, this.poseDelta.props[o + h + "2.quaternion"].z = (o === "Left" ? -1 : 1) * n.applied, this.poseDelta.props[o + h + "3.quaternion"].z = (o === "Left" ? -1 : 1) * n.applied) : (this.poseDelta.props[o + h + "1.quaternion"].x = n.applied, this.poseDelta.props[o + h + "2.quaternion"].x = 1.5 * n.applied, this.poseDelta.props[o + h + "3.quaternion"].x = 1.5 * n.applied);
|
|
4436
4436
|
});
|
|
4437
4437
|
break;
|
|
4438
4438
|
case "chestInhale":
|
|
4439
|
-
const l =
|
|
4439
|
+
const l = n.applied / 20, u = { x: l, y: l / 2, z: 3 * l }, a = { x: 1 / (1 + l) - 1, y: 1 / (1 + l / 2) - 1, z: 1 / (1 + 3 * l) - 1 };
|
|
4440
4440
|
this.poseDelta.props["Spine1.scale"] = u, this.poseDelta.props["Neck.scale"] = a, this.poseDelta.props["LeftArm.scale"] = a, this.poseDelta.props["RightArm.scale"] = a;
|
|
4441
4441
|
break;
|
|
4442
4442
|
default:
|
|
4443
|
-
for (let h = 0, r =
|
|
4444
|
-
|
|
4443
|
+
for (let h = 0, r = n.ms.length; h < r; h++)
|
|
4444
|
+
n.ms[h][n.is[h]] = n.applied;
|
|
4445
4445
|
}
|
|
4446
4446
|
}
|
|
4447
4447
|
}
|
|
@@ -4452,14 +4452,14 @@ class Me {
|
|
|
4452
4452
|
* @return {string} Pose as a string
|
|
4453
4453
|
*/
|
|
4454
4454
|
getPoseString(t, e = 1e3) {
|
|
4455
|
-
let
|
|
4456
|
-
return Object.entries(t).forEach((
|
|
4457
|
-
const o =
|
|
4455
|
+
let n = "{";
|
|
4456
|
+
return Object.entries(t).forEach((i, s) => {
|
|
4457
|
+
const o = i[0].split(".");
|
|
4458
4458
|
if (o[1] === "position" || o[1] === "rotation" || o[1] === "quaternion") {
|
|
4459
|
-
const l = o[1] === "quaternion" ? o[0] + ".rotation" :
|
|
4460
|
-
|
|
4459
|
+
const l = o[1] === "quaternion" ? o[0] + ".rotation" : i[0], u = i[1].isQuaternion ? new f.Euler().setFromQuaternion(i[1]) : i[1];
|
|
4460
|
+
n += (s ? ", " : "") + "'" + l + "':{", n += "x:" + Math.round(u.x * e) / e, n += ", y:" + Math.round(u.y * e) / e, n += ", z:" + Math.round(u.z * e) / e, n += "}";
|
|
4461
4461
|
}
|
|
4462
|
-
}),
|
|
4462
|
+
}), n += "}", n;
|
|
4463
4463
|
}
|
|
4464
4464
|
/**
|
|
4465
4465
|
* Return pose template property taking into account mirror pose and gesture.
|
|
@@ -4468,19 +4468,19 @@ class Me {
|
|
|
4468
4468
|
*/
|
|
4469
4469
|
getPoseTemplateProp(t) {
|
|
4470
4470
|
const e = t.split(".");
|
|
4471
|
-
let
|
|
4472
|
-
if (this.gesture && this.gesture.hasOwnProperty(
|
|
4473
|
-
return this.gesture[
|
|
4471
|
+
let n = e[0] + "." + (e[1] === "rotation" ? "quaternion" : e[1]);
|
|
4472
|
+
if (this.gesture && this.gesture.hasOwnProperty(n))
|
|
4473
|
+
return this.gesture[n].clone();
|
|
4474
4474
|
{
|
|
4475
|
-
let
|
|
4476
|
-
this.poseWeightOnLeft || (
|
|
4475
|
+
let i = e[0] + "." + (e[1] === "quaternion" ? "rotation" : e[1]);
|
|
4476
|
+
this.poseWeightOnLeft || (i.startsWith("Left") ? (i = "Right" + i.substring(4), n = "Right" + n.substring(4)) : i.startsWith("Right") && (i = "Left" + i.substring(5), n = "Left" + n.substring(5)));
|
|
4477
4477
|
let s;
|
|
4478
|
-
if (this.poseTarget.template.props.hasOwnProperty(
|
|
4478
|
+
if (this.poseTarget.template.props.hasOwnProperty(n)) {
|
|
4479
4479
|
const o = {};
|
|
4480
|
-
o[
|
|
4481
|
-
} else if (this.poseTarget.template.props.hasOwnProperty(
|
|
4480
|
+
o[n] = this.poseTarget.template.props[n], s = this.propsToThreeObjects(o)[n];
|
|
4481
|
+
} else if (this.poseTarget.template.props.hasOwnProperty(i)) {
|
|
4482
4482
|
const o = {};
|
|
4483
|
-
o[
|
|
4483
|
+
o[i] = this.poseTarget.template.props[i], s = this.propsToThreeObjects(o)[n];
|
|
4484
4484
|
}
|
|
4485
4485
|
return s && !this.poseWeightOnLeft && s.isQuaternion && (s.x *= -1, s.w *= -1), s;
|
|
4486
4486
|
}
|
|
@@ -4492,8 +4492,8 @@ class Me {
|
|
|
4492
4492
|
*/
|
|
4493
4493
|
mirrorPose(t) {
|
|
4494
4494
|
const e = {};
|
|
4495
|
-
for (let [
|
|
4496
|
-
|
|
4495
|
+
for (let [n, i] of Object.entries(t))
|
|
4496
|
+
i.isQuaternion && (n.startsWith("Left") ? n = "Right" + n.substring(4) : n.startsWith("Right") && (n = "Left" + n.substring(5)), i.x *= -1, i.w *= -1), e[n] = i.clone(), e[n].t = i.t, e[n].d = i.d;
|
|
4497
4497
|
return e;
|
|
4498
4498
|
}
|
|
4499
4499
|
/**
|
|
@@ -4503,18 +4503,18 @@ class Me {
|
|
|
4503
4503
|
* @return {Object} A new pose object.
|
|
4504
4504
|
*/
|
|
4505
4505
|
poseFactory(t, e = 2e3) {
|
|
4506
|
-
const
|
|
4506
|
+
const n = {
|
|
4507
4507
|
template: t,
|
|
4508
4508
|
props: this.propsToThreeObjects(t.props)
|
|
4509
4509
|
};
|
|
4510
|
-
for (const [
|
|
4511
|
-
if (this.opt.modelMovementFactor < 1 && t.standing && (
|
|
4512
|
-
const o = this.poseStraight[
|
|
4510
|
+
for (const [i, s] of Object.entries(n.props)) {
|
|
4511
|
+
if (this.opt.modelMovementFactor < 1 && t.standing && (i === "Hips.quaternion" || i === "Spine.quaternion" || i === "Spine1.quaternion" || i === "Spine2.quaternion" || i === "Neck.quaternion" || i === "LeftUpLeg.quaternion" || i === "LeftLeg.quaternion" || i === "RightUpLeg.quaternion" || i === "RightLeg.quaternion")) {
|
|
4512
|
+
const o = this.poseStraight[i], l = s.angleTo(o);
|
|
4513
4513
|
s.rotateTowards(o, (1 - this.opt.modelMovementFactor) * l);
|
|
4514
4514
|
}
|
|
4515
4515
|
s.t = this.animClock, s.d = e;
|
|
4516
4516
|
}
|
|
4517
|
-
return
|
|
4517
|
+
return n;
|
|
4518
4518
|
}
|
|
4519
4519
|
/**
|
|
4520
4520
|
* Set a new pose and start transition timer.
|
|
@@ -4522,11 +4522,11 @@ class Me {
|
|
|
4522
4522
|
* @param {number} [ms=2000] Transition time in milliseconds
|
|
4523
4523
|
*/
|
|
4524
4524
|
setPoseFromTemplate(t, e = 2e3) {
|
|
4525
|
-
const
|
|
4526
|
-
let o =
|
|
4527
|
-
if (
|
|
4525
|
+
const n = t && this.poseTarget && this.poseTarget.template && (this.poseTarget.template.standing && t.lying || this.poseTarget.template.lying && t.standing), i = t && t === this.poseCurrentTemplate, s = this.poseWeightOnLeft;
|
|
4526
|
+
let o = n ? 1e3 : e;
|
|
4527
|
+
if (n ? (this.poseCurrentTemplate = this.poseTemplates.oneknee, setTimeout(() => {
|
|
4528
4528
|
this.setPoseFromTemplate(t, e);
|
|
4529
|
-
}, o)) : this.poseCurrentTemplate = t || this.poseCurrentTemplate, this.poseTarget = this.poseFactory(this.poseCurrentTemplate, o), this.poseWeightOnLeft = !0, (!
|
|
4529
|
+
}, o)) : this.poseCurrentTemplate = t || this.poseCurrentTemplate, this.poseTarget = this.poseFactory(this.poseCurrentTemplate, o), this.poseWeightOnLeft = !0, (!i && !s || i && s) && (this.poseTarget.props = this.mirrorPose(this.poseTarget.props), this.poseWeightOnLeft = !this.poseWeightOnLeft), this.gesture)
|
|
4530
4530
|
for (let [l, u] of Object.entries(this.gesture))
|
|
4531
4531
|
this.poseTarget.props.hasOwnProperty(l) && (this.poseTarget.props[l].copy(u), this.poseTarget.props[l].t = u.t, this.poseTarget.props[l].d = u.d);
|
|
4532
4532
|
Object.keys(this.poseDelta.props).forEach((l) => {
|
|
@@ -4547,8 +4547,8 @@ class Me {
|
|
|
4547
4547
|
* @param {number} val Value
|
|
4548
4548
|
* @param {number} [ms=null] Transition time in milliseconds.
|
|
4549
4549
|
*/
|
|
4550
|
-
setValue(t, e,
|
|
4551
|
-
this.mtAvatar.hasOwnProperty(t) && Object.assign(this.mtAvatar[t], { system: e, systemd:
|
|
4550
|
+
setValue(t, e, n = null) {
|
|
4551
|
+
this.mtAvatar.hasOwnProperty(t) && Object.assign(this.mtAvatar[t], { system: e, systemd: n, needsUpdate: !0 });
|
|
4552
4552
|
}
|
|
4553
4553
|
/**
|
|
4554
4554
|
* Get mood names.
|
|
@@ -4572,12 +4572,12 @@ class Me {
|
|
|
4572
4572
|
if (t = (t || "").trim().toLowerCase(), !this.animMoods.hasOwnProperty(t)) throw new Error("Unknown mood.");
|
|
4573
4573
|
this.moodName = t, this.mood = this.animMoods[this.moodName];
|
|
4574
4574
|
for (let e of Object.keys(this.mtAvatar)) {
|
|
4575
|
-
let
|
|
4576
|
-
this.mood.baseline.hasOwnProperty(e) ?
|
|
4575
|
+
let n = this.mtBaselineExceptions.hasOwnProperty(e) ? this.mtBaselineExceptions[e] : this.mtBaselineDefault;
|
|
4576
|
+
this.mood.baseline.hasOwnProperty(e) ? n = this.mood.baseline[e] : this.avatar.baseline?.hasOwnProperty(e) && (n = this.avatar.baseline[e]), this.setBaselineValue(e, n);
|
|
4577
4577
|
}
|
|
4578
4578
|
this.mood.anims.forEach((e) => {
|
|
4579
|
-
let
|
|
4580
|
-
|
|
4579
|
+
let n = this.animQueue.findIndex((i) => i.template.name === e.name);
|
|
4580
|
+
n !== -1 && this.animQueue.splice(n, 1), this.animQueue.push(this.animFactory(e, -1));
|
|
4581
4581
|
});
|
|
4582
4582
|
}
|
|
4583
4583
|
/**
|
|
@@ -4608,7 +4608,7 @@ class Me {
|
|
|
4608
4608
|
}
|
|
4609
4609
|
console.log("Avatar is running:", this.isRunning), console.log("Animation queue exists:", !!this.animQueue);
|
|
4610
4610
|
const t = this.animQueue.length;
|
|
4611
|
-
this.animQueue = this.animQueue.filter((
|
|
4611
|
+
this.animQueue = this.animQueue.filter((i) => !i.template.name.startsWith("bodyMovement"));
|
|
4612
4612
|
const e = this.animQueue.length;
|
|
4613
4613
|
if (console.log(`Filtered animation queue: ${t} -> ${e} animations`), this.bodyMovement === "idle") {
|
|
4614
4614
|
this.fbxAnimationLoader && this.fbxAnimationLoader.stopCurrentAnimation();
|
|
@@ -4618,16 +4618,16 @@ class Me {
|
|
|
4618
4618
|
try {
|
|
4619
4619
|
await this.fbxAnimationLoader.playGestureAnimation(this.bodyMovement, this.movementIntensity), console.log("Applied FBX body movement animation:", this.bodyMovement);
|
|
4620
4620
|
return;
|
|
4621
|
-
} catch (
|
|
4622
|
-
console.warn("FBX animation failed, falling back to code animation:",
|
|
4621
|
+
} catch (i) {
|
|
4622
|
+
console.warn("FBX animation failed, falling back to code animation:", i);
|
|
4623
4623
|
}
|
|
4624
|
-
const
|
|
4625
|
-
if (console.log("Created movement animation:",
|
|
4624
|
+
const n = this.createBodyMovementAnimation(this.bodyMovement);
|
|
4625
|
+
if (console.log("Created movement animation:", n), n)
|
|
4626
4626
|
try {
|
|
4627
|
-
const
|
|
4628
|
-
|
|
4629
|
-
} catch (
|
|
4630
|
-
console.error("Error creating body movement animation:",
|
|
4627
|
+
const i = this.animFactory(n, !0);
|
|
4628
|
+
i && i.ts && i.ts.length > 0 ? (this.animQueue.push(i), console.log("Applied code-based body movement animation:", this.bodyMovement), console.log("Animation queue length:", this.animQueue.length), console.log("Animation object:", i)) : (console.error("Invalid animation object created for:", this.bodyMovement), console.error("Animation object:", i));
|
|
4629
|
+
} catch (i) {
|
|
4630
|
+
console.error("Error creating body movement animation:", i);
|
|
4631
4631
|
}
|
|
4632
4632
|
}
|
|
4633
4633
|
/**
|
|
@@ -4668,14 +4668,14 @@ class Me {
|
|
|
4668
4668
|
*/
|
|
4669
4669
|
maintainLockedPosition() {
|
|
4670
4670
|
if (this.lockedPosition && this.armature) {
|
|
4671
|
-
const t = this.armature.position.y, e = this.lockedPosition.y - 2,
|
|
4671
|
+
const t = this.armature.position.y, e = this.lockedPosition.y - 2, n = this.lockedPosition.y + 0.1;
|
|
4672
4672
|
t < e ? this.armature.position.set(
|
|
4673
4673
|
this.lockedPosition.x,
|
|
4674
4674
|
e,
|
|
4675
4675
|
this.lockedPosition.z
|
|
4676
|
-
) : t >
|
|
4676
|
+
) : t > n && this.armature.position.set(
|
|
4677
4677
|
this.lockedPosition.x,
|
|
4678
|
-
|
|
4678
|
+
n,
|
|
4679
4679
|
this.lockedPosition.z
|
|
4680
4680
|
), this.armature.position.x = this.lockedPosition.x, this.armature.position.z = this.lockedPosition.z;
|
|
4681
4681
|
}
|
|
@@ -4686,7 +4686,7 @@ class Me {
|
|
|
4686
4686
|
* @returns {Object} Animation object.
|
|
4687
4687
|
*/
|
|
4688
4688
|
createBodyMovementAnimation(t) {
|
|
4689
|
-
const e = this.movementIntensity || 0.5,
|
|
4689
|
+
const e = this.movementIntensity || 0.5, n = {
|
|
4690
4690
|
walking: {
|
|
4691
4691
|
name: "bodyMovement_walking",
|
|
4692
4692
|
delay: [500, 2e3],
|
|
@@ -4843,10 +4843,10 @@ class Me {
|
|
|
4843
4843
|
}
|
|
4844
4844
|
};
|
|
4845
4845
|
if (t === "dancing") {
|
|
4846
|
-
const
|
|
4847
|
-
return
|
|
4846
|
+
const i = ["dancing", "dancing2", "dancing3"], s = i[Math.floor(Math.random() * i.length)];
|
|
4847
|
+
return n[s] || n.dancing;
|
|
4848
4848
|
}
|
|
4849
|
-
return
|
|
4849
|
+
return n[t] || null;
|
|
4850
4850
|
}
|
|
4851
4851
|
/**
|
|
4852
4852
|
* Play a random dance animation
|
|
@@ -4902,13 +4902,13 @@ class Me {
|
|
|
4902
4902
|
if (t === "eyesRotateY") {
|
|
4903
4903
|
const e = this.getBaselineValue("eyeLookOutLeft");
|
|
4904
4904
|
if (e === void 0) return;
|
|
4905
|
-
const
|
|
4906
|
-
return
|
|
4905
|
+
const n = this.getBaselineValue("eyeLookInLeft");
|
|
4906
|
+
return n === void 0 || this.getBaselineValue("eyeLookOutRight") === void 0 || this.getBaselineValue("eyeLookInRight") === void 0 ? void 0 : e - n;
|
|
4907
4907
|
} else if (t === "eyesRotateX") {
|
|
4908
4908
|
const e = this.getBaselineValue("eyesLookDown");
|
|
4909
4909
|
if (e === void 0) return;
|
|
4910
|
-
const
|
|
4911
|
-
return
|
|
4910
|
+
const n = this.getBaselineValue("eyesLookUp");
|
|
4911
|
+
return n === void 0 ? void 0 : e - n;
|
|
4912
4912
|
} else
|
|
4913
4913
|
return this.mtAvatar[t]?.baseline;
|
|
4914
4914
|
}
|
|
@@ -4929,13 +4929,13 @@ class Me {
|
|
|
4929
4929
|
if (t === "eyesRotateY") {
|
|
4930
4930
|
const e = this.getFixedValue("eyeLookOutLeft");
|
|
4931
4931
|
if (e === null) return null;
|
|
4932
|
-
const
|
|
4933
|
-
return
|
|
4932
|
+
const n = this.getFixedValue("eyeLookInLeft");
|
|
4933
|
+
return n === null || this.getFixedValue("eyeLookOutRight") === null || this.getFixedValue("eyeLookInRight") === null ? null : e - n;
|
|
4934
4934
|
} else if (t === "eyesRotateX") {
|
|
4935
4935
|
const e = this.getFixedValue("eyesLookDown");
|
|
4936
4936
|
if (e === null) return null;
|
|
4937
|
-
const
|
|
4938
|
-
return
|
|
4937
|
+
const n = this.getFixedValue("eyesLookUp");
|
|
4938
|
+
return n === null ? null : e - n;
|
|
4939
4939
|
} else
|
|
4940
4940
|
return this.mtAvatar[t]?.fixed;
|
|
4941
4941
|
}
|
|
@@ -4944,8 +4944,8 @@ class Me {
|
|
|
4944
4944
|
* @param {string} mt Morph target name
|
|
4945
4945
|
* @param {number} val Value, null if to be removed
|
|
4946
4946
|
*/
|
|
4947
|
-
setFixedValue(t, e,
|
|
4948
|
-
t === "eyesRotateY" ? (this.setFixedValue("eyeLookOutLeft", e === null ? null : e > 0 ? e : 0,
|
|
4947
|
+
setFixedValue(t, e, n = null) {
|
|
4948
|
+
t === "eyesRotateY" ? (this.setFixedValue("eyeLookOutLeft", e === null ? null : e > 0 ? e : 0, n), this.setFixedValue("eyeLookInLeft", e === null ? null : e > 0 ? 0 : -e, n), this.setFixedValue("eyeLookOutRight", e === null ? null : e > 0 ? 0 : -e, n), this.setFixedValue("eyeLookInRight", e === null ? null : e > 0 ? e : 0, n)) : t === "eyesRotateX" ? (this.setFixedValue("eyesLookDown", e === null ? null : e > 0 ? e : 0, n), this.setFixedValue("eyesLookUp", e === null ? null : e > 0 ? 0 : -e, n)) : this.mtAvatar.hasOwnProperty(t) && Object.assign(this.mtAvatar[t], { fixed: e, needsUpdate: !0 });
|
|
4949
4949
|
}
|
|
4950
4950
|
/**
|
|
4951
4951
|
* Create a new animation based on an animation template.
|
|
@@ -4956,7 +4956,7 @@ class Me {
|
|
|
4956
4956
|
* @param {boolean} [noClockOffset=false] Do not apply clock offset
|
|
4957
4957
|
* @return {Object} New animation object.
|
|
4958
4958
|
*/
|
|
4959
|
-
animFactory(t, e = !1,
|
|
4959
|
+
animFactory(t, e = !1, n = 1, i = 1, s = !1) {
|
|
4960
4960
|
const o = { template: t, ts: [0], vs: {} };
|
|
4961
4961
|
let l = t;
|
|
4962
4962
|
for (; ; )
|
|
@@ -4996,9 +4996,9 @@ class Me {
|
|
|
4996
4996
|
let a = Object.values(l.vs).reduce((h, r) => r.length > h ? r.length : h, 0);
|
|
4997
4997
|
o.ts = Array(a + 1).fill(0);
|
|
4998
4998
|
}
|
|
4999
|
-
s ? o.ts = o.ts.map((a) => u + a *
|
|
4999
|
+
s ? o.ts = o.ts.map((a) => u + a * n) : o.ts = o.ts.map((a) => this.animClock + u + a * n);
|
|
5000
5000
|
for (let [a, h] of Object.entries(l.vs)) {
|
|
5001
|
-
const r = this.getBaselineValue(a), c = h.map((d) => (d = this.valueFn(d), d === null ? null : typeof d == "function" ? d : typeof d == "string" || d instanceof String ? d.slice() : Array.isArray(d) ? a === "gesture" ? d.slice() : (r === void 0 ? 0 : r) +
|
|
5001
|
+
const r = this.getBaselineValue(a), c = h.map((d) => (d = this.valueFn(d), d === null ? null : typeof d == "function" ? d : typeof d == "string" || d instanceof String ? d.slice() : Array.isArray(d) ? a === "gesture" ? d.slice() : (r === void 0 ? 0 : r) + i * this.gaussianRandom(...d) : typeof d == "boolean" ? d : d instanceof Object && d.constructor === Object ? Object.assign({}, d) : (r === void 0 ? 0 : r) + i * d));
|
|
5002
5002
|
a === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...c.map((d) => d > 0 ? d : 0)], o.vs.eyeLookInLeft = [null, ...c.map((d) => d > 0 ? 0 : -d)], o.vs.eyeLookOutRight = [null, ...c.map((d) => d > 0 ? 0 : -d)], o.vs.eyeLookInRight = [null, ...c.map((d) => d > 0 ? d : 0)]) : a === "eyesRotateX" ? (o.vs.eyesLookDown = [null, ...c.map((d) => d > 0 ? d : 0)], o.vs.eyesLookUp = [null, ...c.map((d) => d > 0 ? 0 : -d)]) : o.vs[a] = [null, ...c];
|
|
5003
5003
|
}
|
|
5004
5004
|
for (let a of Object.keys(o.vs))
|
|
@@ -5015,10 +5015,10 @@ class Me {
|
|
|
5015
5015
|
* @param {function} [fun=null] Ease in/out function, null = linear
|
|
5016
5016
|
* @return {number} Value based on the given time.
|
|
5017
5017
|
*/
|
|
5018
|
-
valueAnimationSeq(t, e,
|
|
5019
|
-
t = this.valueFn(t), e = this.valueFn(e), s <
|
|
5020
|
-
let l = (e - t) / (
|
|
5021
|
-
return o && (l *= o((s -
|
|
5018
|
+
valueAnimationSeq(t, e, n, i, s, o = null) {
|
|
5019
|
+
t = this.valueFn(t), e = this.valueFn(e), s < n && (s = n), s > i && (s = i);
|
|
5020
|
+
let l = (e - t) / (i - n);
|
|
5021
|
+
return o && (l *= o((s - n) / (i - n))), l * s + (t - l * n);
|
|
5022
5022
|
}
|
|
5023
5023
|
/**
|
|
5024
5024
|
* Return gaussian distributed random value between start and end with skew.
|
|
@@ -5028,10 +5028,10 @@ class Me {
|
|
|
5028
5028
|
* @param {number} [samples=5] Number of samples, 1 = uniform distribution.
|
|
5029
5029
|
* @return {number} Gaussian random value.
|
|
5030
5030
|
*/
|
|
5031
|
-
gaussianRandom(t, e,
|
|
5031
|
+
gaussianRandom(t, e, n = 1, i = 5) {
|
|
5032
5032
|
let s = 0;
|
|
5033
|
-
for (let o = 0; o <
|
|
5034
|
-
return t + Math.pow(s /
|
|
5033
|
+
for (let o = 0; o < i; o++) s += Math.random();
|
|
5034
|
+
return t + Math.pow(s / i, n) * (e - t);
|
|
5035
5035
|
}
|
|
5036
5036
|
/**
|
|
5037
5037
|
* Create a sigmoid function.
|
|
@@ -5039,12 +5039,12 @@ class Me {
|
|
|
5039
5039
|
* @return {function} Sigmoid function.
|
|
5040
5040
|
*/
|
|
5041
5041
|
sigmoidFactory(t) {
|
|
5042
|
-
function e(
|
|
5043
|
-
return 1 / (1 + Math.exp(-t *
|
|
5042
|
+
function e(i) {
|
|
5043
|
+
return 1 / (1 + Math.exp(-t * i)) - 0.5;
|
|
5044
5044
|
}
|
|
5045
|
-
var
|
|
5046
|
-
return function(
|
|
5047
|
-
return
|
|
5045
|
+
var n = 0.5 / e(1);
|
|
5046
|
+
return function(i) {
|
|
5047
|
+
return n * e(2 * Math.max(Math.min(i, 1), 0) - 1) + 0.5;
|
|
5048
5048
|
};
|
|
5049
5049
|
}
|
|
5050
5050
|
/**
|
|
@@ -5054,8 +5054,8 @@ class Me {
|
|
|
5054
5054
|
* @param {number[]} r2 Target range
|
|
5055
5055
|
* @return {number} Scaled value
|
|
5056
5056
|
*/
|
|
5057
|
-
convertRange(t, e,
|
|
5058
|
-
return (t - e[0]) * (
|
|
5057
|
+
convertRange(t, e, n) {
|
|
5058
|
+
return (t - e[0]) * (n[1] - n[0]) / (e[1] - e[0]) + n[0];
|
|
5059
5059
|
}
|
|
5060
5060
|
/**
|
|
5061
5061
|
* Animate the avatar.
|
|
@@ -5071,32 +5071,32 @@ class Me {
|
|
|
5071
5071
|
this.animTimeLast = t;
|
|
5072
5072
|
}
|
|
5073
5073
|
e = e / this.animSlowdownRate, this.animClock += e, this.maintainLockedPosition();
|
|
5074
|
-
let
|
|
5074
|
+
let n, i, s, o, l = 0;
|
|
5075
5075
|
if (this.stats && this.stats.begin(), this.isListening) {
|
|
5076
|
-
for (this.listeningAnalyzer.getByteFrequencyData(this.volumeFrequencyData),
|
|
5077
|
-
this.volumeFrequencyData[
|
|
5076
|
+
for (this.listeningAnalyzer.getByteFrequencyData(this.volumeFrequencyData), n = 2, s = 10; n < s; n++)
|
|
5077
|
+
this.volumeFrequencyData[n] > l && (l = this.volumeFrequencyData[n]);
|
|
5078
5078
|
this.listeningVolume = (this.listeningVolume + l) / 2, this.listeningActive ? (this.listeningTimerTotal += e, this.listeningVolume < this.listeningSilenceThresholdLevel ? (this.listeningTimer += e, this.listeningTimer > this.listeningSilenceThresholdMs && (this.listeningOnchange && this.listeningOnchange("stop", this.listeningTimer), this.listeningActive = !1, this.listeningTimer = 0, this.listeningTimerTotal = 0)) : this.listeningTimer *= 0.5, this.listeningTimerTotal > this.listeningActiveDurationMax && (this.listeningOnchange && this.listeningOnchange("maxactive"), this.listeningTimerTotal = 0)) : (this.listeningTimerTotal += e, this.listeningVolume > this.listeningActiveThresholdLevel ? (this.listeningTimer += e, this.listeningTimer > this.listeningActiveThresholdMs && (this.listeningOnchange && this.listeningOnchange("start"), this.listeningActive = !0, this.listeningTimer = 0, this.listeningTimerTotal = 0)) : this.listeningTimer *= 0.5, this.listeningTimerTotal > this.listeningSilenceDurationMax && (this.listeningOnchange && this.listeningOnchange("maxsilence"), this.listeningTimerTotal = 0));
|
|
5079
5079
|
}
|
|
5080
5080
|
if (this.isSpeaking)
|
|
5081
|
-
for (l = 0, this.audioAnalyzerNode.getByteFrequencyData(this.volumeFrequencyData),
|
|
5082
|
-
this.volumeFrequencyData[
|
|
5081
|
+
for (l = 0, this.audioAnalyzerNode.getByteFrequencyData(this.volumeFrequencyData), n = 2, s = 10; n < s; n++)
|
|
5082
|
+
this.volumeFrequencyData[n] > l && (l = this.volumeFrequencyData[n]);
|
|
5083
5083
|
let u = null, a = null;
|
|
5084
5084
|
const h = [];
|
|
5085
|
-
for (
|
|
5086
|
-
const r = this.animQueue[
|
|
5085
|
+
for (n = 0, s = this.animQueue.length; n < s; n++) {
|
|
5086
|
+
const r = this.animQueue[n];
|
|
5087
5087
|
if (!(!r || !r.ts || !r.ts.length || this.animClock < r.ts[0])) {
|
|
5088
|
-
for (
|
|
5088
|
+
for (i = r.ndx || 0, o = r.ts.length; i < o && !(this.animClock < r.ts[i]); i++)
|
|
5089
5089
|
for (let [c, d] of Object.entries(r.vs))
|
|
5090
5090
|
if (this.mtAvatar.hasOwnProperty(c)) {
|
|
5091
|
-
if (d[
|
|
5091
|
+
if (d[i + 1] === null) continue;
|
|
5092
5092
|
const g = this.mtAvatar[c];
|
|
5093
|
-
if (d[
|
|
5094
|
-
g.newvalue = d[
|
|
5093
|
+
if (d[i] === null && (d[i] = g.value), i === o - 1)
|
|
5094
|
+
g.newvalue = d[i];
|
|
5095
5095
|
else {
|
|
5096
|
-
g.newvalue = d[
|
|
5097
|
-
const y = r.ts[
|
|
5096
|
+
g.newvalue = d[i + 1];
|
|
5097
|
+
const y = r.ts[i + 1] - r.ts[i];
|
|
5098
5098
|
let x = 1;
|
|
5099
|
-
y > 1e-4 && (x = (this.animClock - r.ts[
|
|
5099
|
+
y > 1e-4 && (x = (this.animClock - r.ts[i]) / y), x < 1 && (g.easing && (x = g.easing(x)), g.newvalue = (1 - x) * d[i] + x * g.newvalue), g.ref && g.ref !== r.vs && g.ref.hasOwnProperty(c) && delete g.ref[c], g.ref = r.vs;
|
|
5100
5100
|
}
|
|
5101
5101
|
if (l)
|
|
5102
5102
|
switch (c) {
|
|
@@ -5108,29 +5108,29 @@ class Me {
|
|
|
5108
5108
|
g.newvalue *= 1 + l / 255 - 0.5;
|
|
5109
5109
|
}
|
|
5110
5110
|
g.needsUpdate = !0;
|
|
5111
|
-
} else c === "eyeContact" && d[
|
|
5112
|
-
|
|
5111
|
+
} else c === "eyeContact" && d[i] !== null && u !== !1 ? u = !!d[i] : c === "headMove" && d[i] !== null && a !== !1 ? d[i] === 0 ? a = !1 : (Math.random() < d[i] && (a = !0), d[i] = null) : d[i] !== null && (h.push({ mt: c, val: d[i] }), d[i] = null);
|
|
5112
|
+
i === o ? (r.hasOwnProperty("mood") && this.setMood(r.mood), r.loop ? (o = this.isSpeaking && (r.template.name === "head" || r.template.name === "eyes") ? 4 : 1, this.animQueue[n] = this.animFactory(r.template, r.loop > 0 ? r.loop - 1 : r.loop, 1, 1 / o)) : (this.animQueue.splice(n--, 1), s--)) : r.ndx = i - 1;
|
|
5113
5113
|
}
|
|
5114
5114
|
}
|
|
5115
5115
|
for (let r = 0, c = h.length; r < c; r++)
|
|
5116
|
-
switch (
|
|
5116
|
+
switch (i = h[r].val, h[r].mt) {
|
|
5117
5117
|
case "speak":
|
|
5118
|
-
this.speakText(
|
|
5118
|
+
this.speakText(i);
|
|
5119
5119
|
break;
|
|
5120
5120
|
case "subtitles":
|
|
5121
|
-
this.onSubtitles && typeof this.onSubtitles == "function" && this.onSubtitles(
|
|
5121
|
+
this.onSubtitles && typeof this.onSubtitles == "function" && this.onSubtitles(i);
|
|
5122
5122
|
break;
|
|
5123
5123
|
case "pose":
|
|
5124
|
-
this.poseName =
|
|
5124
|
+
this.poseName = i, this.setPoseFromTemplate(this.poseTemplates[this.poseName]);
|
|
5125
5125
|
break;
|
|
5126
5126
|
case "gesture":
|
|
5127
|
-
this.playGesture(...
|
|
5127
|
+
this.playGesture(...i);
|
|
5128
5128
|
break;
|
|
5129
5129
|
case "function":
|
|
5130
|
-
|
|
5130
|
+
i && typeof i == "function" && i();
|
|
5131
5131
|
break;
|
|
5132
5132
|
case "moveto":
|
|
5133
|
-
Object.entries(
|
|
5133
|
+
Object.entries(i.props).forEach((d) => {
|
|
5134
5134
|
d[1] ? this.poseTarget.props[d[0]].copy(d[1]) : this.poseTarget.props[d[0]].copy(this.getPoseTemplateProp(d[0])), this.poseTarget.props[d[0]].t = this.animClock, this.poseTarget.props[d[0]].d = d[1] && d[1].d ? d[1].d : d.duration || 2e3;
|
|
5135
5135
|
});
|
|
5136
5136
|
break;
|
|
@@ -5144,7 +5144,7 @@ class Me {
|
|
|
5144
5144
|
{ link: "LeftForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -0.5, maxz: 3 },
|
|
5145
5145
|
{ link: "LeftArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
5146
5146
|
]
|
|
5147
|
-
},
|
|
5147
|
+
}, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5148
5148
|
break;
|
|
5149
5149
|
case "handRight":
|
|
5150
5150
|
this.ikSolve({
|
|
@@ -5156,31 +5156,31 @@ class Me {
|
|
|
5156
5156
|
{ link: "RightForeArm", minx: -0.5, maxx: 1.5, miny: -1.5, maxy: 1.5, minz: -3, maxz: 0.5, maxAngle: 0.2 },
|
|
5157
5157
|
{ link: "RightArm", minx: -1.5, maxx: 1.5, miny: 0, maxy: 0, minz: -1, maxz: 3 }
|
|
5158
5158
|
]
|
|
5159
|
-
},
|
|
5159
|
+
}, i.x ? new f.Vector3(i.x, i.y, i.z) : null, !0, i.d);
|
|
5160
5160
|
break;
|
|
5161
5161
|
}
|
|
5162
|
-
if ((u || a) && (
|
|
5162
|
+
if ((u || a) && (E.setFromQuaternion(this.poseAvatar.props["Head.quaternion"]), E.x = Math.max(-0.9, Math.min(0.9, 2 * E.x - 0.5)), E.y = Math.max(-0.9, Math.min(0.9, -2.5 * E.y)), u ? (Object.assign(this.mtAvatar.eyesLookDown, { system: E.x < 0 ? -E.x : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyesLookUp, { system: E.x < 0 ? 0 : E.x, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInLeft, { system: E.y < 0 ? -E.y : 0, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutLeft, { system: E.y < 0 ? 0 : E.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookInRight, { system: E.y < 0 ? 0 : E.y, needsUpdate: !0 }), Object.assign(this.mtAvatar.eyeLookOutRight, { system: E.y < 0 ? -E.y : 0, needsUpdate: !0 }), a && (n = -this.mtAvatar.bodyRotateY.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
5163
5163
|
name: "headmove",
|
|
5164
5164
|
dt: [[1e3, 2e3], [1e3, 2e3, 1, 2], [1e3, 2e3], [1e3, 2e3, 1, 2]],
|
|
5165
5165
|
vs: {
|
|
5166
|
-
headRotateY: [
|
|
5167
|
-
headRotateX: [
|
|
5168
|
-
headRotateZ: [-
|
|
5166
|
+
headRotateY: [n, n, 0],
|
|
5167
|
+
headRotateX: [i, i, 0],
|
|
5168
|
+
headRotateZ: [-n / 4, -n / 4, 0]
|
|
5169
5169
|
}
|
|
5170
|
-
})))) : (
|
|
5170
|
+
})))) : (n = this.mtAvatar.eyeLookInLeft.value - this.mtAvatar.eyeLookOutLeft.value, i = this.gaussianRandom(-0.2, 0.2), this.animQueue.push(this.animFactory({
|
|
5171
5171
|
name: "headmove",
|
|
5172
5172
|
dt: [[1e3, 2e3], [1e3, 2e3, 1, 2], [1e3, 2e3], [1e3, 2e3, 1, 2]],
|
|
5173
5173
|
vs: {
|
|
5174
|
-
headRotateY: [null,
|
|
5175
|
-
headRotateX: [null,
|
|
5176
|
-
headRotateZ: [null, -
|
|
5174
|
+
headRotateY: [null, n, n, 0],
|
|
5175
|
+
headRotateX: [null, i, i, 0],
|
|
5176
|
+
headRotateZ: [null, -n / 4, -n / 4, 0],
|
|
5177
5177
|
eyeLookInLeft: [null, 0],
|
|
5178
5178
|
eyeLookOutLeft: [null, 0],
|
|
5179
5179
|
eyeLookInRight: [null, 0],
|
|
5180
5180
|
eyeLookOutRight: [null, 0],
|
|
5181
5181
|
eyeContact: [0]
|
|
5182
5182
|
}
|
|
5183
|
-
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (
|
|
5183
|
+
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (n = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], i = this.mtAvatar[n], i.needsUpdate || Object.assign(i, { base: (this.mood.baseline[n] || 0) + (1 + l / 255) * Math.random() / 5, needsUpdate: !0 })), this.updatePoseBase(this.animClock), this.mixer && this.mixer.update(e / 1e3 * this.mixer.timeScale), this.updatePoseDelta(), (this.isSpeaking || this.isListening) && u ? l > this.volumeMax ? (this.volumeHeadBase = 0.05, Math.random() > 0.6 && (this.volumeHeadTarget = -0.05 - Math.random() / 15), this.volumeMax = l) : (this.volumeMax *= 0.92, this.volumeHeadTarget = this.volumeHeadBase - 0.9 * (this.volumeHeadBase - this.volumeHeadTarget)) : (this.volumeHeadTarget = 0, this.volumeMax = 0), n = this.volumeHeadTarget - this.volumeHeadCurrent, i = Math.abs(n), i > 1e-4 && (o = i * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / i) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(n) * Math.min(i, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (U.setFromAxisAngle(lt, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(U)), Te.setFromObject(this.armature), this.objectLeftToeBase.getWorldPosition(ae), ae.sub(this.armature.position), this.objectRightToeBase.getWorldPosition(he), he.sub(this.armature.position), this.objectHips.position.y -= Te.min.y / 2, this.objectHips.position.x -= (ae.x + he.x) / 4, this.objectHips.position.z -= (ae.z + he.z) / 2, this.dynamicbones.update(e), this.fbxAnimationLoader && this.fbxAnimationLoader.update(), this.opt.update && this.opt.update(e), this.updateMorphTargets(e), this.isAvatarOnly)
|
|
5184
5184
|
this.stats && this.stats.end();
|
|
5185
5185
|
else {
|
|
5186
5186
|
if (this.cameraClock !== null && this.cameraClock < 1e3) {
|
|
@@ -5197,8 +5197,8 @@ class Me {
|
|
|
5197
5197
|
resetLips() {
|
|
5198
5198
|
this.visemeNames.forEach((t) => {
|
|
5199
5199
|
this.morphs.forEach((e) => {
|
|
5200
|
-
const
|
|
5201
|
-
|
|
5200
|
+
const n = e.morphTargetDictionary["viseme_" + t];
|
|
5201
|
+
n !== void 0 && (e.morphTargetInfluences[n] = 0);
|
|
5202
5202
|
});
|
|
5203
5203
|
});
|
|
5204
5204
|
}
|
|
@@ -5209,10 +5209,10 @@ class Me {
|
|
|
5209
5209
|
*/
|
|
5210
5210
|
lipsyncGetProcessor(t, e = "./") {
|
|
5211
5211
|
if (!this.lipsync.hasOwnProperty(t)) {
|
|
5212
|
-
const
|
|
5212
|
+
const n = t.toLowerCase(), i = "Lipsync" + t.charAt(0).toUpperCase() + t.slice(1);
|
|
5213
5213
|
try {
|
|
5214
|
-
const s =
|
|
5215
|
-
s && s[
|
|
5214
|
+
const s = He[n];
|
|
5215
|
+
s && s[i] ? (this.lipsync[t] = new s[i](), console.log(`Loaded lip-sync module for ${t}`)) : console.warn(`Lip-sync module for ${t} not found. Available modules:`, Object.keys(He));
|
|
5216
5216
|
} catch (s) {
|
|
5217
5217
|
console.warn(`Failed to load lip-sync module for ${t}:`, s);
|
|
5218
5218
|
}
|
|
@@ -5245,16 +5245,16 @@ class Me {
|
|
|
5245
5245
|
* @param {subtitlesfn} [onsubtitles=null] Callback when a subtitle is written
|
|
5246
5246
|
* @param {number[][]} [excludes=null] Array of [start, end] index arrays to not speak
|
|
5247
5247
|
*/
|
|
5248
|
-
speakText(t, e = null,
|
|
5248
|
+
speakText(t, e = null, n = null, i = null) {
|
|
5249
5249
|
e = e || {};
|
|
5250
5250
|
const s = /[!\.\?\n\p{Extended_Pictographic}]/ug, o = /[ ]/ug, l = /[\p{L}\p{N},\.\p{Quotation_Mark}!€\$\+\p{Dash_Punctuation}%&\?]/ug, u = /[\p{Extended_Pictographic}]/ug, a = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang;
|
|
5251
5251
|
let h = "", r = "", c = 0, d = [], g = [];
|
|
5252
5252
|
const y = Array.from(this.segmenter.segment(t), (x) => x.segment);
|
|
5253
5253
|
for (let x = 0; x < y.length; x++) {
|
|
5254
|
-
const I = x === y.length - 1,
|
|
5254
|
+
const I = x === y.length - 1, F = y[x].match(l);
|
|
5255
5255
|
let p = y[x].match(s);
|
|
5256
5256
|
const H = y[x].match(u), z = y[x].match(o);
|
|
5257
|
-
if (p && !I && !H && y[x + 1].match(s) && (p = !1),
|
|
5257
|
+
if (p && !I && !H && y[x + 1].match(s) && (p = !1), n && (h += y[x]), F && (!i || i.every((v) => x < v[0] || x > v[1])) && (r += y[x]), (z || p || I) && (r.length && (r = this.lipsyncPreProcessText(r, a), r.length && d.push({
|
|
5258
5258
|
mark: c,
|
|
5259
5259
|
word: r
|
|
5260
5260
|
})), h.length && (g.push({
|
|
@@ -5265,16 +5265,16 @@ class Me {
|
|
|
5265
5265
|
subtitles: [h]
|
|
5266
5266
|
}
|
|
5267
5267
|
}), h = ""), r.length)) {
|
|
5268
|
-
const
|
|
5269
|
-
if (
|
|
5270
|
-
const
|
|
5271
|
-
for (let
|
|
5268
|
+
const v = this.lipsyncWordsToVisemes(r, a);
|
|
5269
|
+
if (v && v.visemes && v.visemes.length) {
|
|
5270
|
+
const M = v.times[v.visemes.length - 1] + v.durations[v.visemes.length - 1];
|
|
5271
|
+
for (let W = 0; W < v.visemes.length; W++)
|
|
5272
5272
|
g.push({
|
|
5273
5273
|
mark: c,
|
|
5274
5274
|
template: { name: "viseme" },
|
|
5275
|
-
ts: [(
|
|
5275
|
+
ts: [(v.times[W] - 0.6) / M, (v.times[W] + 0.5) / M, (v.times[W] + v.durations[W] + 0.5) / M],
|
|
5276
5276
|
vs: {
|
|
5277
|
-
["viseme_" +
|
|
5277
|
+
["viseme_" + v.visemes[W]]: [null, v.visemes[W] === "PP" || v.visemes[W] === "FF" ? 0.9 : 0.6, 0]
|
|
5278
5278
|
}
|
|
5279
5279
|
});
|
|
5280
5280
|
}
|
|
@@ -5282,14 +5282,14 @@ class Me {
|
|
|
5282
5282
|
}
|
|
5283
5283
|
if (p || I) {
|
|
5284
5284
|
if (d.length || I && g.length) {
|
|
5285
|
-
const
|
|
5285
|
+
const v = {
|
|
5286
5286
|
anim: g
|
|
5287
5287
|
};
|
|
5288
|
-
|
|
5288
|
+
n && (v.onSubtitles = n), d.length && !e.avatarMute && (v.text = d, e.avatarMood && (v.mood = e.avatarMood), e.ttsLang && (v.lang = e.ttsLang), e.ttsVoice && (v.voice = e.ttsVoice), e.ttsRate && (v.rate = e.ttsRate), e.ttsVoice && (v.pitch = e.ttsPitch), e.ttsVolume && (v.volume = e.ttsVolume)), this.speechQueue.push(v), d = [], r = "", c = 0, g = [];
|
|
5289
5289
|
}
|
|
5290
5290
|
if (H) {
|
|
5291
|
-
let
|
|
5292
|
-
|
|
5291
|
+
let v = this.animEmojis[y[x]];
|
|
5292
|
+
v && v.link && (v = this.animEmojis[v.link]), v && this.speechQueue.push({ emoji: v });
|
|
5293
5293
|
}
|
|
5294
5294
|
this.speechQueue.push({ break: 100 });
|
|
5295
5295
|
}
|
|
@@ -5323,8 +5323,8 @@ class Me {
|
|
|
5323
5323
|
* @param {string} url URL for the audio, stop if null.
|
|
5324
5324
|
*/
|
|
5325
5325
|
async playBackgroundAudio(t) {
|
|
5326
|
-
let
|
|
5327
|
-
this.stopBackgroundAudio(), this.audioBackgroundSource = this.audioCtx.createBufferSource(), this.audioBackgroundSource.loop = !0, this.audioBackgroundSource.buffer = await this.audioCtx.decodeAudioData(
|
|
5326
|
+
let n = await (await fetch(t)).arrayBuffer();
|
|
5327
|
+
this.stopBackgroundAudio(), this.audioBackgroundSource = this.audioCtx.createBufferSource(), this.audioBackgroundSource.loop = !0, this.audioBackgroundSource.buffer = await this.audioCtx.decodeAudioData(n), this.audioBackgroundSource.playbackRate.value = 1 / this.animSlowdownRate, this.audioBackgroundSource.connect(this.audioBackgroundGainNode), this.audioBackgroundSource.start(0);
|
|
5328
5328
|
}
|
|
5329
5329
|
/**
|
|
5330
5330
|
* Stop background audio.
|
|
@@ -5342,11 +5342,11 @@ class Me {
|
|
|
5342
5342
|
*/
|
|
5343
5343
|
async setReverb(t = null) {
|
|
5344
5344
|
if (t) {
|
|
5345
|
-
let
|
|
5346
|
-
this.audioReverbNode.buffer = await this.audioCtx.decodeAudioData(
|
|
5345
|
+
let n = await (await fetch(t)).arrayBuffer();
|
|
5346
|
+
this.audioReverbNode.buffer = await this.audioCtx.decodeAudioData(n);
|
|
5347
5347
|
} else {
|
|
5348
|
-
const e = this.audioCtx.sampleRate,
|
|
5349
|
-
|
|
5348
|
+
const e = this.audioCtx.sampleRate, n = this.audioCtx.createBuffer(2, e, e);
|
|
5349
|
+
n.getChannelData(0)[0] = 1, n.getChannelData(1)[0] = 1, this.audioReverbNode.buffer = n;
|
|
5350
5350
|
}
|
|
5351
5351
|
}
|
|
5352
5352
|
/**
|
|
@@ -5355,8 +5355,8 @@ class Me {
|
|
|
5355
5355
|
* @param {number} [background=null] Gain for background audio, if null do not change
|
|
5356
5356
|
* @param {number} [fadeSecs=0] Gradual exponential fade in/out time in seconds
|
|
5357
5357
|
*/
|
|
5358
|
-
setMixerGain(t, e = null,
|
|
5359
|
-
t !== null && (this.audioSpeechGainNode.gain.cancelScheduledValues(this.audioCtx.currentTime),
|
|
5358
|
+
setMixerGain(t, e = null, n = 0) {
|
|
5359
|
+
t !== null && (this.audioSpeechGainNode.gain.cancelScheduledValues(this.audioCtx.currentTime), n ? (this.audioSpeechGainNode.gain.setValueAtTime(Math.max(this.audioSpeechGainNode.gain.value, 1e-4), this.audioCtx.currentTime), this.audioSpeechGainNode.gain.exponentialRampToValueAtTime(Math.max(t, 1e-4), this.audioCtx.currentTime + n)) : this.audioSpeechGainNode.gain.setValueAtTime(t, this.audioCtx.currentTime)), e !== null && (this.audioBackgroundGainNode.gain.cancelScheduledValues(this.audioCtx.currentTime), n ? (this.audioBackgroundGainNode.gain.setValueAtTime(Math.max(this.audioBackgroundGainNode.gain.value, 1e-4), this.audioCtx.currentTime), this.audioBackgroundGainNode.gain.exponentialRampToValueAtTime(Math.max(e, 1e-4), this.audioCtx.currentTime + n)) : this.audioBackgroundGainNode.gain.setValueAtTime(e, this.audioCtx.currentTime));
|
|
5360
5360
|
}
|
|
5361
5361
|
/**
|
|
5362
5362
|
* Add audio to the speech queue.
|
|
@@ -5364,31 +5364,31 @@ class Me {
|
|
|
5364
5364
|
* @param {Options} [opt=null] Text-specific options for lipsyncLang
|
|
5365
5365
|
* @param {subtitlesfn} [onsubtitles=null] Callback when a subtitle is written
|
|
5366
5366
|
*/
|
|
5367
|
-
speakAudio(t, e = null,
|
|
5367
|
+
speakAudio(t, e = null, n = null) {
|
|
5368
5368
|
e = e || {};
|
|
5369
|
-
const
|
|
5369
|
+
const i = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, s = {};
|
|
5370
5370
|
if (t.words) {
|
|
5371
5371
|
let o = [];
|
|
5372
5372
|
for (let l = 0; l < t.words.length; l++) {
|
|
5373
5373
|
const u = t.words[l], a = t.wtimes[l];
|
|
5374
5374
|
let h = t.wdurations[l];
|
|
5375
|
-
if (u.length && (
|
|
5375
|
+
if (u.length && (n && o.push({
|
|
5376
5376
|
template: { name: "subtitles" },
|
|
5377
5377
|
ts: [a],
|
|
5378
5378
|
vs: {
|
|
5379
5379
|
subtitles: [" " + u]
|
|
5380
5380
|
}
|
|
5381
5381
|
}), !t.visemes)) {
|
|
5382
|
-
const r = this.lipsyncPreProcessText(u,
|
|
5382
|
+
const r = this.lipsyncPreProcessText(u, i), c = this.lipsyncWordsToVisemes(r, i);
|
|
5383
5383
|
if (c && c.visemes && c.visemes.length) {
|
|
5384
5384
|
const d = c.times[c.visemes.length - 1] + c.durations[c.visemes.length - 1], g = Math.min(h, Math.max(0, h - c.visemes.length * 150));
|
|
5385
5385
|
let y = 0.6 + this.convertRange(g, [0, h], [0, 0.4]);
|
|
5386
5386
|
if (h = Math.min(h, c.visemes.length * 200), d > 0)
|
|
5387
5387
|
for (let x = 0; x < c.visemes.length; x++) {
|
|
5388
|
-
const I = a + c.times[x] / d * h,
|
|
5388
|
+
const I = a + c.times[x] / d * h, F = c.durations[x] / d * h;
|
|
5389
5389
|
o.push({
|
|
5390
5390
|
template: { name: "viseme" },
|
|
5391
|
-
ts: [I - Math.min(60, 2 *
|
|
5391
|
+
ts: [I - Math.min(60, 2 * F / 3), I + Math.min(25, F / 2), I + F + Math.min(60, F / 2)],
|
|
5392
5392
|
vs: {
|
|
5393
5393
|
["viseme_" + c.visemes[x]]: [null, c.visemes[x] === "PP" || c.visemes[x] === "FF" ? 0.9 : y, 0]
|
|
5394
5394
|
}
|
|
@@ -5423,7 +5423,7 @@ class Me {
|
|
|
5423
5423
|
let o = this.animFactory(t.anim, !1, 1, 1, !0);
|
|
5424
5424
|
s.anim ? s.anim.push(o) : s.anim = [o];
|
|
5425
5425
|
}
|
|
5426
|
-
|
|
5426
|
+
n && (s.onSubtitles = n), e.isRaw && (s.isRaw = !0), Object.keys(s).length && (this.speechQueue.push(s), s.isRaw || this.speechQueue.push({ break: 300 }), this.startSpeaking());
|
|
5427
5427
|
}
|
|
5428
5428
|
/**
|
|
5429
5429
|
* Play audio playlist using Web Audio API.
|
|
@@ -5442,21 +5442,21 @@ class Me {
|
|
|
5442
5442
|
return;
|
|
5443
5443
|
}
|
|
5444
5444
|
}
|
|
5445
|
-
let
|
|
5445
|
+
let n;
|
|
5446
5446
|
if (Array.isArray(e.audio)) {
|
|
5447
5447
|
let s = this.concatArrayBuffers(e.audio);
|
|
5448
|
-
|
|
5448
|
+
n = this.pcmToAudioBuffer(s);
|
|
5449
5449
|
} else
|
|
5450
|
-
|
|
5451
|
-
this.audioSpeechSource = this.audioCtx.createBufferSource(), this.audioSpeechSource.buffer =
|
|
5450
|
+
n = e.audio;
|
|
5451
|
+
this.audioSpeechSource = this.audioCtx.createBufferSource(), this.audioSpeechSource.buffer = n, this.audioSpeechSource.playbackRate.value = 1 / this.animSlowdownRate, this.audioSpeechSource.connect(this.audioAnalyzerNode), this.audioSpeechSource.addEventListener("ended", () => {
|
|
5452
5452
|
this.audioSpeechSource.disconnect(), this.playAudio(!0);
|
|
5453
5453
|
}, { once: !0 });
|
|
5454
|
-
let
|
|
5455
|
-
e.anim && (e.isRaw || (
|
|
5454
|
+
let i = 0;
|
|
5455
|
+
e.anim && (e.isRaw || (i = Math.abs(Math.min(0, ...e.anim.map((s) => Math.min(...s.ts))))), e.anim.forEach((s) => {
|
|
5456
5456
|
for (let o = 0; o < s.ts.length; o++)
|
|
5457
|
-
s.ts[o] = this.animClock + s.ts[o] +
|
|
5457
|
+
s.ts[o] = this.animClock + s.ts[o] + i;
|
|
5458
5458
|
this.animQueue.push(s);
|
|
5459
|
-
})), this.audioSpeechSource.start(
|
|
5459
|
+
})), this.audioSpeechSource.start(i / 1e3);
|
|
5460
5460
|
} else
|
|
5461
5461
|
this.isAudioPlaying = !1, this.startSpeaking(!0);
|
|
5462
5462
|
}
|
|
@@ -5465,17 +5465,17 @@ class Me {
|
|
|
5465
5465
|
* @param {Object} line Speech line object
|
|
5466
5466
|
*/
|
|
5467
5467
|
async synthesizeWithBrowserTTS(t) {
|
|
5468
|
-
return new Promise((e,
|
|
5469
|
-
const
|
|
5468
|
+
return new Promise((e, n) => {
|
|
5469
|
+
const i = t.text.map((p) => p.word).join(" "), s = new SpeechSynthesisUtterance(i), o = t.lang || this.avatar.ttsLang || this.opt.ttsLang || "en-US", l = (t.rate || this.avatar.ttsRate || this.opt.ttsRate || 1) + this.mood.speech.deltaRate, u = (t.pitch || this.avatar.ttsPitch || this.opt.ttsPitch || 1) + this.mood.speech.deltaPitch, a = (t.volume || this.avatar.ttsVolume || this.opt.ttsVolume || 1) + this.mood.speech.deltaVolume;
|
|
5470
5470
|
s.lang = o, s.rate = Math.max(0.1, Math.min(10, l)), s.pitch = Math.max(0, Math.min(2, u)), s.volume = Math.max(0, Math.min(1, a));
|
|
5471
5471
|
const h = speechSynthesis.getVoices(), r = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice;
|
|
5472
5472
|
if (r && h.length > 0) {
|
|
5473
5473
|
const p = h.find((H) => H.name.includes(r) || H.lang === o);
|
|
5474
5474
|
p && (s.voice = p);
|
|
5475
5475
|
}
|
|
5476
|
-
const c =
|
|
5476
|
+
const c = i.length * 100 / s.rate, d = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (c / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", y = this.lipsyncPreProcessText(i, g), x = this.lipsyncWordsToVisemes(y, g);
|
|
5477
5477
|
console.log("Browser TTS Lip-sync Debug:", {
|
|
5478
|
-
text:
|
|
5478
|
+
text: i,
|
|
5479
5479
|
lipsyncLang: g,
|
|
5480
5480
|
processedText: y,
|
|
5481
5481
|
lipsyncData: x,
|
|
@@ -5486,21 +5486,21 @@ class Me {
|
|
|
5486
5486
|
if (x && x.visemes && x.visemes.length > 0) {
|
|
5487
5487
|
const p = x.times[x.visemes.length - 1] + x.durations[x.visemes.length - 1];
|
|
5488
5488
|
for (let H = 0; H < x.visemes.length; H++) {
|
|
5489
|
-
const z = x.visemes[H],
|
|
5489
|
+
const z = x.visemes[H], v = x.times[H] / p, M = x.durations[H] / p, W = v * c, _ = M * c;
|
|
5490
5490
|
I.push({
|
|
5491
5491
|
template: { name: "viseme" },
|
|
5492
|
-
ts: [
|
|
5492
|
+
ts: [W - Math.min(60, 2 * _ / 3), W + Math.min(25, _ / 2), W + _ + Math.min(60, _ / 2)],
|
|
5493
5493
|
vs: {
|
|
5494
5494
|
["viseme_" + z]: [null, z === "PP" || z === "FF" ? 0.9 : 0.6, 0]
|
|
5495
5495
|
}
|
|
5496
5496
|
});
|
|
5497
5497
|
}
|
|
5498
5498
|
}
|
|
5499
|
-
const
|
|
5500
|
-
this.audioPlaylist.push({ anim:
|
|
5499
|
+
const F = [...t.anim, ...I];
|
|
5500
|
+
this.audioPlaylist.push({ anim: F, audio: d }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
|
|
5501
5501
|
e();
|
|
5502
5502
|
}, s.onerror = (p) => {
|
|
5503
|
-
console.error("Speech synthesis error:", p.error),
|
|
5503
|
+
console.error("Speech synthesis error:", p.error), n(p.error);
|
|
5504
5504
|
}, speechSynthesis.speak(s);
|
|
5505
5505
|
});
|
|
5506
5506
|
}
|
|
@@ -5509,7 +5509,7 @@ class Me {
|
|
|
5509
5509
|
* @param {Object} line Speech line object
|
|
5510
5510
|
*/
|
|
5511
5511
|
async synthesizeWithElevenLabsTTS(t) {
|
|
5512
|
-
const e = t.text.map((c) => c.word).join(" "),
|
|
5512
|
+
const e = t.text.map((c) => c.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "21m00Tcm4TlvDq8ikWAM", i = {
|
|
5513
5513
|
text: e,
|
|
5514
5514
|
model_id: "eleven_monolingual_v1",
|
|
5515
5515
|
voice_settings: {
|
|
@@ -5518,14 +5518,14 @@ class Me {
|
|
|
5518
5518
|
style: 0,
|
|
5519
5519
|
use_speaker_boost: !0
|
|
5520
5520
|
}
|
|
5521
|
-
}, s = await fetch(`${this.opt.ttsEndpoint}/${
|
|
5521
|
+
}, s = await fetch(`${this.opt.ttsEndpoint}/${n}`, {
|
|
5522
5522
|
method: "POST",
|
|
5523
5523
|
headers: {
|
|
5524
5524
|
Accept: "audio/mpeg",
|
|
5525
5525
|
"Content-Type": "application/json",
|
|
5526
5526
|
"xi-api-key": this.opt.ttsApikey
|
|
5527
5527
|
},
|
|
5528
|
-
body: JSON.stringify(
|
|
5528
|
+
body: JSON.stringify(i)
|
|
5529
5529
|
});
|
|
5530
5530
|
if (!s.ok)
|
|
5531
5531
|
throw new Error(`ElevenLabs TTS error: ${s.status} ${s.statusText}`);
|
|
@@ -5616,7 +5616,7 @@ class Me {
|
|
|
5616
5616
|
* @param {Object} line Speech line object
|
|
5617
5617
|
*/
|
|
5618
5618
|
async synthesizeWithDeepgramTTS(t) {
|
|
5619
|
-
const e = t.text.map((c) => c.word).join(" "),
|
|
5619
|
+
const e = t.text.map((c) => c.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "aura-2-thalia-en", i = `${this.opt.ttsEndpoint}?model=${n}`, s = await fetch(i, {
|
|
5620
5620
|
method: "POST",
|
|
5621
5621
|
headers: {
|
|
5622
5622
|
Authorization: `Token ${this.opt.ttsApikey}`,
|
|
@@ -5714,7 +5714,7 @@ class Me {
|
|
|
5714
5714
|
* @param {Object} line Speech line object
|
|
5715
5715
|
*/
|
|
5716
5716
|
async synthesizeWithAzureTTS(t) {
|
|
5717
|
-
const e = t.text.map((r) => r.word).join(" "),
|
|
5717
|
+
const e = t.text.map((r) => r.word).join(" "), i = `
|
|
5718
5718
|
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
|
|
5719
5719
|
<voice name="${t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "en-US-AriaNeural"}">
|
|
5720
5720
|
${e}
|
|
@@ -5727,7 +5727,7 @@ class Me {
|
|
|
5727
5727
|
"Content-Type": "application/ssml+xml",
|
|
5728
5728
|
"X-Microsoft-OutputFormat": "audio-16khz-128kbitrate-mono-mp3"
|
|
5729
5729
|
},
|
|
5730
|
-
body:
|
|
5730
|
+
body: i
|
|
5731
5731
|
});
|
|
5732
5732
|
if (!s.ok)
|
|
5733
5733
|
throw new Error(`Azure TTS error: ${s.status} ${s.statusText}`);
|
|
@@ -5767,7 +5767,7 @@ class Me {
|
|
|
5767
5767
|
t.text.forEach((o, l) => {
|
|
5768
5768
|
l > 0 && (e += " <mark name='" + o.mark + "'/>"), e += o.word.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'").replace(new RegExp("^\\p{Dash_Punctuation}$", "ug"), '<break time="750ms"/>');
|
|
5769
5769
|
}), e += "</speak>";
|
|
5770
|
-
const
|
|
5770
|
+
const n = {
|
|
5771
5771
|
method: "POST",
|
|
5772
5772
|
headers: {
|
|
5773
5773
|
"Content-Type": "application/json; charset=utf-8"
|
|
@@ -5790,9 +5790,9 @@ class Me {
|
|
|
5790
5790
|
// Timepoint information for mark tags
|
|
5791
5791
|
})
|
|
5792
5792
|
};
|
|
5793
|
-
this.opt.jwtGet && typeof this.opt.jwtGet == "function" && (
|
|
5794
|
-
const
|
|
5795
|
-
if (
|
|
5793
|
+
this.opt.jwtGet && typeof this.opt.jwtGet == "function" && (n.headers.Authorization = "Bearer " + await this.opt.jwtGet());
|
|
5794
|
+
const i = await fetch(this.opt.ttsEndpoint + (this.opt.ttsApikey ? "?key=" + this.opt.ttsApikey : ""), n), s = await i.json();
|
|
5795
|
+
if (i.status === 200 && s && s.audioContent) {
|
|
5796
5796
|
const o = this.b64ToArrayBuffer(s.audioContent), l = await this.audioCtx.decodeAudioData(o);
|
|
5797
5797
|
this.speakWithHands();
|
|
5798
5798
|
const u = [0];
|
|
@@ -5831,8 +5831,8 @@ class Me {
|
|
|
5831
5831
|
let e = this.speechQueue.shift();
|
|
5832
5832
|
if (e.emoji) {
|
|
5833
5833
|
this.lookAtCamera(500);
|
|
5834
|
-
let
|
|
5835
|
-
this.animQueue.push(this.animFactory(e.emoji)), setTimeout(this.startSpeaking.bind(this),
|
|
5834
|
+
let n = e.emoji.dt.reduce((i, s) => i + s, 0);
|
|
5835
|
+
this.animQueue.push(this.animFactory(e.emoji)), setTimeout(this.startSpeaking.bind(this), n, !0);
|
|
5836
5836
|
} else if (e.break)
|
|
5837
5837
|
setTimeout(this.startSpeaking.bind(this), e.break, !0);
|
|
5838
5838
|
else if (e.audio)
|
|
@@ -5841,13 +5841,13 @@ class Me {
|
|
|
5841
5841
|
this.lookAtCamera(500);
|
|
5842
5842
|
try {
|
|
5843
5843
|
!this.opt.ttsEndpoint || this.opt.ttsEndpoint === "" ? await this.synthesizeWithBrowserTTS(e) : this.opt.ttsService === "elevenlabs" ? await this.synthesizeWithElevenLabsTTS(e) : this.opt.ttsService === "deepgram" ? await this.synthesizeWithDeepgramTTS(e) : this.opt.ttsService === "azure" ? await this.synthesizeWithAzureTTS(e) : await this.synthesizeWithExternalTTS(e);
|
|
5844
|
-
} catch (
|
|
5845
|
-
console.error("Error:",
|
|
5844
|
+
} catch (n) {
|
|
5845
|
+
console.error("Error:", n), this.startSpeaking(!0);
|
|
5846
5846
|
}
|
|
5847
|
-
} else e.anim ? (this.onSubtitles = e.onSubtitles || null, this.resetLips(), e.mood && this.setMood(e.mood), e.anim.forEach((
|
|
5848
|
-
for (let s = 0; s <
|
|
5849
|
-
|
|
5850
|
-
this.animQueue.push(
|
|
5847
|
+
} else e.anim ? (this.onSubtitles = e.onSubtitles || null, this.resetLips(), e.mood && this.setMood(e.mood), e.anim.forEach((n, i) => {
|
|
5848
|
+
for (let s = 0; s < n.ts.length; s++)
|
|
5849
|
+
n.ts[s] = this.animClock + 10 * i;
|
|
5850
|
+
this.animQueue.push(n);
|
|
5851
5851
|
}), setTimeout(this.startSpeaking.bind(this), 10 * e.anim.length, !0)) : e.marker ? (typeof e.marker == "function" && e.marker(), this.startSpeaking(!0)) : this.startSpeaking(!0);
|
|
5852
5852
|
} else
|
|
5853
5853
|
this.stateName = "idle", this.isSpeaking = !1;
|
|
@@ -5880,8 +5880,8 @@ class Me {
|
|
|
5880
5880
|
* @param {function} [onSubtitles=null] Optional callback to play subtitles
|
|
5881
5881
|
* @param {function} [onMetrics=null] Optional callback to receive metrics data during streaming
|
|
5882
5882
|
*/
|
|
5883
|
-
async streamStart(t = {}, e = null,
|
|
5884
|
-
if (this.stopSpeaking(), this.isStreaming = !0, t.waitForAudioChunks !== void 0 && (this.streamWaitForAudioChunks = t.waitForAudioChunks), this.streamWaitForAudioChunks || (this.streamAudioStartTime = this.animClock), this.streamLipsyncQueue = [], this.streamLipsyncType = t.lipsyncType || this.streamLipsyncType || "visemes", this.streamLipsyncLang = t.lipsyncLang || this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, this.onAudioStart = e, this.onAudioEnd =
|
|
5883
|
+
async streamStart(t = {}, e = null, n = null, i = null, s = null) {
|
|
5884
|
+
if (this.stopSpeaking(), this.isStreaming = !0, t.waitForAudioChunks !== void 0 && (this.streamWaitForAudioChunks = t.waitForAudioChunks), this.streamWaitForAudioChunks || (this.streamAudioStartTime = this.animClock), this.streamLipsyncQueue = [], this.streamLipsyncType = t.lipsyncType || this.streamLipsyncType || "visemes", this.streamLipsyncLang = t.lipsyncLang || this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, this.onAudioStart = e, this.onAudioEnd = n, this.onMetrics = s, t.sampleRate !== void 0) {
|
|
5885
5885
|
const l = t.sampleRate;
|
|
5886
5886
|
typeof l == "number" && l >= 8e3 && l <= 96e3 ? l !== this.audioCtx.sampleRate && this.initAudioGraph(l) : console.warn(
|
|
5887
5887
|
"Invalid sampleRate provided. It must be a number between 8000 and 96000 Hz."
|
|
@@ -5895,7 +5895,7 @@ class Me {
|
|
|
5895
5895
|
}
|
|
5896
5896
|
if (!this.workletLoaded)
|
|
5897
5897
|
try {
|
|
5898
|
-
const l = this.audioCtx.audioWorklet.addModule(
|
|
5898
|
+
const l = this.audioCtx.audioWorklet.addModule(rt.href), u = new Promise(
|
|
5899
5899
|
(a, h) => setTimeout(() => h(new Error("Worklet loading timed out")), 5e3)
|
|
5900
5900
|
);
|
|
5901
5901
|
await Promise.race([l, u]), this.workletLoaded = !0;
|
|
@@ -5931,7 +5931,7 @@ class Me {
|
|
|
5931
5931
|
this.streamWorkletNode.port.postMessage({ type: "config-metrics", data: t.metrics });
|
|
5932
5932
|
} catch {
|
|
5933
5933
|
}
|
|
5934
|
-
if (this.resetLips(), this.lookAtCamera(500), t.mood && this.setMood(t.mood), this.onSubtitles =
|
|
5934
|
+
if (this.resetLips(), this.lookAtCamera(500), t.mood && this.setMood(t.mood), this.onSubtitles = i || null, this.audioCtx.state === "suspended" || this.audioCtx.state === "interrupted") {
|
|
5935
5935
|
const l = this.audioCtx.resume(), u = new Promise((a, h) => setTimeout(() => h("p2"), 1e3));
|
|
5936
5936
|
try {
|
|
5937
5937
|
await Promise.race([l, u]);
|
|
@@ -6010,28 +6010,28 @@ class Me {
|
|
|
6010
6010
|
_processLipsyncData(t, e) {
|
|
6011
6011
|
if (this.isStreaming) {
|
|
6012
6012
|
if (t.visemes && this.streamLipsyncType == "visemes")
|
|
6013
|
-
for (let
|
|
6014
|
-
const
|
|
6013
|
+
for (let n = 0; n < t.visemes.length; n++) {
|
|
6014
|
+
const i = t.visemes[n], s = e + t.vtimes[n], o = t.vdurations[n], l = {
|
|
6015
6015
|
template: { name: "viseme" },
|
|
6016
6016
|
ts: [s - 2 * o / 3, s + o / 2, s + o + o / 2],
|
|
6017
6017
|
vs: {
|
|
6018
|
-
["viseme_" +
|
|
6018
|
+
["viseme_" + i]: [null, i === "PP" || i === "FF" ? 0.9 : 0.6, 0]
|
|
6019
6019
|
}
|
|
6020
6020
|
};
|
|
6021
6021
|
this.animQueue.push(l);
|
|
6022
6022
|
}
|
|
6023
6023
|
if (t.words && (this.onSubtitles || this.streamLipsyncType == "words"))
|
|
6024
|
-
for (let
|
|
6025
|
-
const
|
|
6026
|
-
let o = t.wdurations[
|
|
6027
|
-
if (
|
|
6024
|
+
for (let n = 0; n < t.words.length; n++) {
|
|
6025
|
+
const i = t.words[n], s = t.wtimes[n];
|
|
6026
|
+
let o = t.wdurations[n];
|
|
6027
|
+
if (i.length && (this.onSubtitles && this.animQueue.push({
|
|
6028
6028
|
template: { name: "subtitles" },
|
|
6029
6029
|
ts: [e + s],
|
|
6030
6030
|
vs: {
|
|
6031
|
-
subtitles: [" " +
|
|
6031
|
+
subtitles: [" " + i]
|
|
6032
6032
|
}
|
|
6033
6033
|
}), this.streamLipsyncType == "words")) {
|
|
6034
|
-
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, u = this.lipsyncPreProcessText(
|
|
6034
|
+
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, u = this.lipsyncPreProcessText(i, l), a = this.lipsyncWordsToVisemes(u, l);
|
|
6035
6035
|
if (a && a.visemes && a.visemes.length) {
|
|
6036
6036
|
const h = a.times[a.visemes.length - 1] + a.durations[a.visemes.length - 1], r = Math.min(o, Math.max(0, o - a.visemes.length * 150));
|
|
6037
6037
|
let c = 0.6 + this.convertRange(r, [0, o], [0, 0.4]);
|
|
@@ -6050,10 +6050,10 @@ class Me {
|
|
|
6050
6050
|
}
|
|
6051
6051
|
}
|
|
6052
6052
|
if (t.anims && this.streamLipsyncType == "blendshapes")
|
|
6053
|
-
for (let
|
|
6054
|
-
let
|
|
6055
|
-
|
|
6056
|
-
let s = this.animFactory(
|
|
6053
|
+
for (let n = 0; n < t.anims.length; n++) {
|
|
6054
|
+
let i = t.anims[n];
|
|
6055
|
+
i.delay += e;
|
|
6056
|
+
let s = this.animFactory(i, !1, 1, 1, !0);
|
|
6057
6057
|
this.animQueue.push(s);
|
|
6058
6058
|
}
|
|
6059
6059
|
}
|
|
@@ -6069,15 +6069,15 @@ class Me {
|
|
|
6069
6069
|
if (t.audio instanceof ArrayBuffer)
|
|
6070
6070
|
e.data = t.audio, this.streamWorkletNode.port.postMessage(e, [e.data]);
|
|
6071
6071
|
else if (t.audio instanceof Int16Array || t.audio instanceof Uint8Array) {
|
|
6072
|
-
const
|
|
6073
|
-
e.data =
|
|
6072
|
+
const n = t.audio.buffer.slice(t.audio.byteOffset, t.audio.byteOffset + t.audio.byteLength);
|
|
6073
|
+
e.data = n, this.streamWorkletNode.port.postMessage(e, [e.data]);
|
|
6074
6074
|
} else if (t.audio instanceof Float32Array) {
|
|
6075
|
-
const
|
|
6076
|
-
for (let
|
|
6077
|
-
let s = Math.max(-1, Math.min(1, t.audio[
|
|
6078
|
-
i
|
|
6075
|
+
const n = new Int16Array(t.audio.length);
|
|
6076
|
+
for (let i = 0; i < t.audio.length; i++) {
|
|
6077
|
+
let s = Math.max(-1, Math.min(1, t.audio[i]));
|
|
6078
|
+
n[i] = s < 0 ? s * 32768 : s * 32767;
|
|
6079
6079
|
}
|
|
6080
|
-
e.data =
|
|
6080
|
+
e.data = n.buffer, this.streamWorkletNode.port.postMessage(e, [e.data]);
|
|
6081
6081
|
} else
|
|
6082
6082
|
console.error("r.audio is not a supported type. Must be ArrayBuffer, Int16Array, Uint8Array, or Float32Array:", t.audio);
|
|
6083
6083
|
}
|
|
@@ -6107,16 +6107,16 @@ class Me {
|
|
|
6107
6107
|
*/
|
|
6108
6108
|
lookAhead(t) {
|
|
6109
6109
|
if (t) {
|
|
6110
|
-
let e = (Math.random() - 0.5) / 4,
|
|
6111
|
-
|
|
6110
|
+
let e = (Math.random() - 0.5) / 4, n = (Math.random() - 0.5) / 4, i = this.animQueue.findIndex((o) => o.template.name === "lookat");
|
|
6111
|
+
i !== -1 && this.animQueue.splice(i, 1);
|
|
6112
6112
|
const s = {
|
|
6113
6113
|
name: "lookat",
|
|
6114
6114
|
dt: [750, t],
|
|
6115
6115
|
vs: {
|
|
6116
6116
|
bodyRotateX: [e],
|
|
6117
|
-
bodyRotateY: [
|
|
6117
|
+
bodyRotateY: [n],
|
|
6118
6118
|
eyesRotateX: [-3 * e + 0.1],
|
|
6119
|
-
eyesRotateY: [-5 *
|
|
6119
|
+
eyesRotateY: [-5 * n],
|
|
6120
6120
|
browInnerUp: [[0, 0.7]],
|
|
6121
6121
|
mouthLeft: [[0, 0.7]],
|
|
6122
6122
|
mouthRight: [[0, 0.7]],
|
|
@@ -6133,7 +6133,7 @@ class Me {
|
|
|
6133
6133
|
*/
|
|
6134
6134
|
lookAtCamera(t) {
|
|
6135
6135
|
let e;
|
|
6136
|
-
if (this.speakTo && (e = new f.Vector3(), this.speakTo.objectLeftEye?.isObject3D ? (this.speakTo.armature.objectHead, this.speakTo.objectLeftEye.updateMatrixWorld(!0), this.speakTo.objectRightEye.updateMatrixWorld(!0), ae.setFromMatrixPosition(this.speakTo.objectLeftEye.matrixWorld),
|
|
6136
|
+
if (this.speakTo && (e = new f.Vector3(), this.speakTo.objectLeftEye?.isObject3D ? (this.speakTo.armature.objectHead, this.speakTo.objectLeftEye.updateMatrixWorld(!0), this.speakTo.objectRightEye.updateMatrixWorld(!0), ae.setFromMatrixPosition(this.speakTo.objectLeftEye.matrixWorld), he.setFromMatrixPosition(this.speakTo.objectRightEye.matrixWorld), e.addVectors(ae, he).divideScalar(2)) : this.speakTo.isObject3D ? this.speakTo.getWorldPosition(e) : this.speakTo.isVector3 ? e.set(this.speakTo) : this.speakTo.x && this.speakTo.y && this.speakTo.z && e.set(this.speakTo.x, this.speakTo.y, this.speakTo.z)), !e) {
|
|
6137
6137
|
if (this.avatar.hasOwnProperty("avatarIgnoreCamera")) {
|
|
6138
6138
|
if (this.avatar.avatarIgnoreCamera) {
|
|
6139
6139
|
this.lookAhead(t);
|
|
@@ -6146,12 +6146,12 @@ class Me {
|
|
|
6146
6146
|
this.lookAt(null, null, t);
|
|
6147
6147
|
return;
|
|
6148
6148
|
}
|
|
6149
|
-
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ae.setFromMatrixPosition(this.objectLeftEye.matrixWorld),
|
|
6150
|
-
const
|
|
6151
|
-
|
|
6152
|
-
const l = new f.Quaternion().setFromEuler(
|
|
6153
|
-
|
|
6154
|
-
let a =
|
|
6149
|
+
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ae.setFromMatrixPosition(this.objectLeftEye.matrixWorld), he.setFromMatrixPosition(this.objectRightEye.matrixWorld), ae.add(he).divideScalar(2), U.copy(this.armature.quaternion), U.multiply(this.poseTarget.props["Hips.quaternion"]), U.multiply(this.poseTarget.props["Spine.quaternion"]), U.multiply(this.poseTarget.props["Spine1.quaternion"]), U.multiply(this.poseTarget.props["Spine2.quaternion"]), U.multiply(this.poseTarget.props["Neck.quaternion"]), U.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6150
|
+
const n = new f.Vector3().subVectors(e, ae).normalize(), i = Math.atan2(n.x, n.z), s = Math.asin(-n.y);
|
|
6151
|
+
E.set(s, i, 0, "YXZ");
|
|
6152
|
+
const l = new f.Quaternion().setFromEuler(E), u = new f.Quaternion().copy(l).multiply(U.clone().invert());
|
|
6153
|
+
E.setFromQuaternion(u, "YXZ");
|
|
6154
|
+
let a = E.x / (40 / 24) + 0.2, h = E.y / (9 / 4), r = Math.min(0.6, Math.max(-0.3, a)), c = Math.min(0.8, Math.max(-0.8, h)), d = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6155
6155
|
if (t) {
|
|
6156
6156
|
let y = this.animQueue.findIndex((I) => I.template.name === "lookat");
|
|
6157
6157
|
y !== -1 && this.animQueue.splice(y, 1);
|
|
@@ -6179,27 +6179,27 @@ class Me {
|
|
|
6179
6179
|
* @param {number} y Y-coordinate relative to visual viewport
|
|
6180
6180
|
* @param {number} t Time in milliseconds
|
|
6181
6181
|
*/
|
|
6182
|
-
lookAt(t, e,
|
|
6182
|
+
lookAt(t, e, n) {
|
|
6183
6183
|
if (!this.camera) return;
|
|
6184
|
-
const
|
|
6184
|
+
const i = this.nodeAvatar.getBoundingClientRect();
|
|
6185
6185
|
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0);
|
|
6186
6186
|
const s = new f.Vector3().setFromMatrixPosition(this.objectLeftEye.matrixWorld), o = new f.Vector3().setFromMatrixPosition(this.objectRightEye.matrixWorld), l = new f.Vector3().addVectors(s, o).divideScalar(2);
|
|
6187
6187
|
l.project(this.camera);
|
|
6188
|
-
let u = (l.x + 1) / 2 *
|
|
6189
|
-
t === null && (t = u), e === null && (e = a),
|
|
6190
|
-
let h =
|
|
6188
|
+
let u = (l.x + 1) / 2 * i.width + i.left, a = -(l.y - 1) / 2 * i.height + i.top;
|
|
6189
|
+
t === null && (t = u), e === null && (e = a), U.copy(this.armature.quaternion), U.multiply(this.poseTarget.props["Hips.quaternion"]), U.multiply(this.poseTarget.props["Spine.quaternion"]), U.multiply(this.poseTarget.props["Spine1.quaternion"]), U.multiply(this.poseTarget.props["Spine2.quaternion"]), U.multiply(this.poseTarget.props["Neck.quaternion"]), U.multiply(this.poseTarget.props["Head.quaternion"]), E.setFromQuaternion(U);
|
|
6190
|
+
let h = E.x / (40 / 24), r = E.y / (9 / 4), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - u, u), y = Math.max(window.innerHeight - a, a), x = this.convertRange(e, [a - y, a + y], [-0.3, 0.6]) - h + c, I = this.convertRange(t, [u - g, u + g], [-0.8, 0.8]) - r + d;
|
|
6191
6191
|
x = Math.min(0.6, Math.max(-0.3, x)), I = Math.min(0.8, Math.max(-0.8, I));
|
|
6192
|
-
let
|
|
6193
|
-
if (
|
|
6194
|
-
let H = this.animQueue.findIndex((
|
|
6192
|
+
let F = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6193
|
+
if (n) {
|
|
6194
|
+
let H = this.animQueue.findIndex((v) => v.template.name === "lookat");
|
|
6195
6195
|
H !== -1 && this.animQueue.splice(H, 1);
|
|
6196
6196
|
const z = {
|
|
6197
6197
|
name: "lookat",
|
|
6198
|
-
dt: [750,
|
|
6198
|
+
dt: [750, n],
|
|
6199
6199
|
vs: {
|
|
6200
|
-
bodyRotateX: [x +
|
|
6200
|
+
bodyRotateX: [x + F],
|
|
6201
6201
|
bodyRotateY: [I + p],
|
|
6202
|
-
eyesRotateX: [-3 *
|
|
6202
|
+
eyesRotateX: [-3 * F + 0.1],
|
|
6203
6203
|
eyesRotateY: [-5 * p],
|
|
6204
6204
|
browInnerUp: [[0, 0.7]],
|
|
6205
6205
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6219,11 +6219,11 @@ class Me {
|
|
|
6219
6219
|
*/
|
|
6220
6220
|
touchAt(t, e) {
|
|
6221
6221
|
if (!this.camera) return;
|
|
6222
|
-
const
|
|
6223
|
-
(t -
|
|
6224
|
-
-((e -
|
|
6222
|
+
const n = this.nodeAvatar.getBoundingClientRect(), i = new f.Vector2(
|
|
6223
|
+
(t - n.left) / n.width * 2 - 1,
|
|
6224
|
+
-((e - n.top) / n.height) * 2 + 1
|
|
6225
6225
|
), s = new f.Raycaster();
|
|
6226
|
-
s.setFromCamera(
|
|
6226
|
+
s.setFromCamera(i, this.camera);
|
|
6227
6227
|
const o = s.intersectObject(this.armature);
|
|
6228
6228
|
if (o.length > 0) {
|
|
6229
6229
|
const l = o[0].point, u = new f.Vector3(), a = new f.Vector3();
|
|
@@ -6287,20 +6287,20 @@ class Me {
|
|
|
6287
6287
|
this.gaussianRandom(-0.8, -0.2),
|
|
6288
6288
|
this.gaussianRandom(0, 0.5)
|
|
6289
6289
|
), !0);
|
|
6290
|
-
const
|
|
6291
|
-
|
|
6290
|
+
const n = [], i = [];
|
|
6291
|
+
n.push(100 + Math.round(Math.random() * 500)), i.push({ duration: 1e3, props: {
|
|
6292
6292
|
"LeftHand.quaternion": new f.Quaternion().setFromEuler(new f.Euler(0, -1 - Math.random(), 0)),
|
|
6293
6293
|
"RightHand.quaternion": new f.Quaternion().setFromEuler(new f.Euler(0, 1 + Math.random(), 0))
|
|
6294
6294
|
} }), ["LeftArm", "LeftForeArm", "RightArm", "RightForeArm"].forEach((o) => {
|
|
6295
|
-
|
|
6296
|
-
}),
|
|
6297
|
-
|
|
6295
|
+
i[0].props[o + ".quaternion"] = this.ikMesh.getObjectByName(o).quaternion.clone();
|
|
6296
|
+
}), n.push(1e3 + Math.round(Math.random() * 500)), i.push({ duration: 2e3, props: {} }), ["LeftArm", "LeftForeArm", "RightArm", "RightForeArm", "LeftHand", "RightHand"].forEach((o) => {
|
|
6297
|
+
i[1].props[o + ".quaternion"] = null;
|
|
6298
6298
|
});
|
|
6299
6299
|
const s = this.animFactory({
|
|
6300
6300
|
name: "talkinghands",
|
|
6301
6301
|
delay: t,
|
|
6302
|
-
dt:
|
|
6303
|
-
vs: { moveto:
|
|
6302
|
+
dt: n,
|
|
6303
|
+
vs: { moveto: i }
|
|
6304
6304
|
});
|
|
6305
6305
|
this.animQueue.push(s);
|
|
6306
6306
|
}
|
|
@@ -6350,8 +6350,8 @@ class Me {
|
|
|
6350
6350
|
* @param {Object} [opt={}] Options
|
|
6351
6351
|
* @param {function} [onchange=null] Callback function for start
|
|
6352
6352
|
*/
|
|
6353
|
-
startListening(t, e = {},
|
|
6354
|
-
this.listeningAnalyzer = t, this.listeningAnalyzer.fftSize = 256, this.listeningAnalyzer.smoothingTimeConstant = 0.1, this.listeningAnalyzer.minDecibels = -70, this.listeningAnalyzer.maxDecibels = -10, this.listeningOnchange =
|
|
6353
|
+
startListening(t, e = {}, n = null) {
|
|
6354
|
+
this.listeningAnalyzer = t, this.listeningAnalyzer.fftSize = 256, this.listeningAnalyzer.smoothingTimeConstant = 0.1, this.listeningAnalyzer.minDecibels = -70, this.listeningAnalyzer.maxDecibels = -10, this.listeningOnchange = n && typeof n == "function" ? n : null, this.listeningSilenceThresholdLevel = e?.hasOwnProperty("listeningSilenceThresholdLevel") ? e.listeningSilenceThresholdLevel : this.opt.listeningSilenceThresholdLevel, this.listeningSilenceThresholdMs = e?.hasOwnProperty("listeningSilenceThresholdMs") ? e.listeningSilenceThresholdMs : this.opt.listeningSilenceThresholdMs, this.listeningSilenceDurationMax = e?.hasOwnProperty("listeningSilenceDurationMax") ? e.listeningSilenceDurationMax : this.opt.listeningSilenceDurationMax, this.listeningActiveThresholdLevel = e?.hasOwnProperty("listeningActiveThresholdLevel") ? e.listeningActiveThresholdLevel : this.opt.listeningActiveThresholdLevel, this.listeningActiveThresholdMs = e?.hasOwnProperty("listeningActiveThresholdMs") ? e.listeningActiveThresholdMs : this.opt.listeningActiveThresholdMs, this.listeningActiveDurationMax = e?.hasOwnProperty("listeningActiveDurationMax") ? e.listeningActiveDurationMax : this.opt.listeningActiveDurationMax, this.listeningActive = !1, this.listeningVolume = 0, this.listeningTimer = 0, this.listeningTimerTotal = 0, this.isListening = !0;
|
|
6355
6355
|
}
|
|
6356
6356
|
/**
|
|
6357
6357
|
* Stop animation cycle.
|
|
@@ -6367,16 +6367,16 @@ class Me {
|
|
|
6367
6367
|
* @param {number} [ndx=0] Index of the clip
|
|
6368
6368
|
* @param {number} [scale=0.01] Position scale factor
|
|
6369
6369
|
*/
|
|
6370
|
-
async playAnimation(t, e = null,
|
|
6370
|
+
async playAnimation(t, e = null, n = 10, i = 0, s = 0.01, o = !1) {
|
|
6371
6371
|
if (!this.armature) return;
|
|
6372
6372
|
this.positionWasLocked = !o, o ? console.log("Position locking disabled for FBX animation:", t) : (this.lockAvatarPosition(), console.log("Position locked immediately before FBX animation:", t));
|
|
6373
|
-
let l = this.animClips.find((u) => u.url === t + "-" +
|
|
6373
|
+
let l = this.animClips.find((u) => u.url === t + "-" + i);
|
|
6374
6374
|
if (l) {
|
|
6375
6375
|
let u = this.animQueue.find((r) => r.template.name === "pose");
|
|
6376
6376
|
u && (u.ts[0] = 1 / 0), Object.entries(l.pose.props).forEach((r) => {
|
|
6377
6377
|
this.poseBase.props[r[0]] = r[1].clone(), this.poseTarget.props[r[0]] = r[1].clone(), this.poseTarget.props[r[0]].t = 0, this.poseTarget.props[r[0]].d = 1e3;
|
|
6378
6378
|
}), this.mixer ? console.log("Using existing mixer for FBX animation, preserving morph targets") : (this.mixer = new f.AnimationMixer(this.armature), console.log("Created new mixer for FBX animation")), this.mixer.addEventListener("finished", this.stopAnimation.bind(this), { once: !0 });
|
|
6379
|
-
const a = Math.ceil(
|
|
6379
|
+
const a = Math.ceil(n / l.clip.duration), h = this.mixer.clipAction(l.clip);
|
|
6380
6380
|
h.setLoop(f.LoopRepeat, a), h.clampWhenFinished = !0, this.currentFBXAction = h;
|
|
6381
6381
|
try {
|
|
6382
6382
|
h.fadeIn(0.5).play(), console.log("FBX animation started successfully:", t);
|
|
@@ -6403,7 +6403,7 @@ class Me {
|
|
|
6403
6403
|
} catch (c) {
|
|
6404
6404
|
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, c);
|
|
6405
6405
|
}
|
|
6406
|
-
const h = new
|
|
6406
|
+
const h = new ze();
|
|
6407
6407
|
let r;
|
|
6408
6408
|
try {
|
|
6409
6409
|
r = await h.loadAsync(t, e);
|
|
@@ -6426,8 +6426,8 @@ class Me {
|
|
|
6426
6426
|
}
|
|
6427
6427
|
return;
|
|
6428
6428
|
}
|
|
6429
|
-
if (r && r.animations && r.animations[
|
|
6430
|
-
let c = r.animations[
|
|
6429
|
+
if (r && r.animations && r.animations[i]) {
|
|
6430
|
+
let c = r.animations[i];
|
|
6431
6431
|
const d = {};
|
|
6432
6432
|
c.tracks.forEach((y) => {
|
|
6433
6433
|
y.name = y.name.replaceAll("mixamorig", "");
|
|
@@ -6440,13 +6440,13 @@ class Me {
|
|
|
6440
6440
|
});
|
|
6441
6441
|
const g = { props: d };
|
|
6442
6442
|
d["Hips.position"] && (d["Hips.position"].y < 0.5 ? g.lying = !0 : g.standing = !0), this.animClips.push({
|
|
6443
|
-
url: t + "-" +
|
|
6443
|
+
url: t + "-" + i,
|
|
6444
6444
|
clip: c,
|
|
6445
6445
|
pose: g
|
|
6446
|
-
}), this.playAnimation(t, e,
|
|
6446
|
+
}), this.playAnimation(t, e, n, i, s);
|
|
6447
6447
|
} else {
|
|
6448
|
-
const c = "Animation " + t + " (ndx=" +
|
|
6449
|
-
console.error(c), r && r.animations ? console.error(`FBX file loaded but has ${r.animations.length} animation(s), requested index ${
|
|
6448
|
+
const c = "Animation " + t + " (ndx=" + i + ") not found";
|
|
6449
|
+
console.error(c), r && r.animations ? console.error(`FBX file loaded but has ${r.animations.length} animation(s), requested index ${i}`) : console.error(r ? "FBX file loaded but contains no animations" : "FBX file failed to load or is invalid");
|
|
6450
6450
|
}
|
|
6451
6451
|
}
|
|
6452
6452
|
}
|
|
@@ -6455,8 +6455,8 @@ class Me {
|
|
|
6455
6455
|
*/
|
|
6456
6456
|
stopAnimation() {
|
|
6457
6457
|
if (this.currentFBXAction && (this.currentFBXAction.stop(), this.currentFBXAction = null, console.log("FBX animation action stopped, mixer preserved for lip-sync")), this.mixer && this.mixer._actions.length === 0 && (this.mixer = null, console.log("Mixer destroyed as no actions remain")), this.positionWasLocked ? (this.unlockAvatarPosition(), console.log("Position unlocked after FBX animation stopped")) : console.log("Position was not locked, no unlock needed"), this.gesture)
|
|
6458
|
-
for (let [e,
|
|
6459
|
-
|
|
6458
|
+
for (let [e, n] of Object.entries(this.gesture))
|
|
6459
|
+
n.t = this.animClock, n.d = 1e3, this.poseTarget.props.hasOwnProperty(e) && (this.poseTarget.props[e].copy(n), this.poseTarget.props[e].t = this.animClock, this.poseTarget.props[e].d = 1e3);
|
|
6460
6460
|
let t = this.animQueue.find((e) => e.template.name === "pose");
|
|
6461
6461
|
t && (t.ts[0] = this.animClock), this.setPoseFromTemplate(null);
|
|
6462
6462
|
}
|
|
@@ -6468,21 +6468,21 @@ class Me {
|
|
|
6468
6468
|
* @param {number} [ndx=0] Index of the clip
|
|
6469
6469
|
* @param {number} [scale=0.01] Position scale factor
|
|
6470
6470
|
*/
|
|
6471
|
-
async playPose(t, e = null,
|
|
6471
|
+
async playPose(t, e = null, n = 5, i = 0, s = 0.01) {
|
|
6472
6472
|
if (!this.armature) return;
|
|
6473
6473
|
let o = this.poseTemplates[t];
|
|
6474
6474
|
if (!o) {
|
|
6475
|
-
const l = this.animPoses.find((u) => u.url === t + "-" +
|
|
6475
|
+
const l = this.animPoses.find((u) => u.url === t + "-" + i);
|
|
6476
6476
|
l && (o = l.pose);
|
|
6477
6477
|
}
|
|
6478
6478
|
if (o) {
|
|
6479
6479
|
this.poseName = t, this.mixer = null;
|
|
6480
6480
|
let l = this.animQueue.find((u) => u.template.name === "pose");
|
|
6481
|
-
l && (l.ts[0] = this.animClock +
|
|
6481
|
+
l && (l.ts[0] = this.animClock + n * 1e3 + 2e3), this.setPoseFromTemplate(o);
|
|
6482
6482
|
} else {
|
|
6483
|
-
let u = await new
|
|
6484
|
-
if (u && u.animations && u.animations[
|
|
6485
|
-
let a = u.animations[
|
|
6483
|
+
let u = await new ze().loadAsync(t, e);
|
|
6484
|
+
if (u && u.animations && u.animations[i]) {
|
|
6485
|
+
let a = u.animations[i];
|
|
6486
6486
|
const h = {};
|
|
6487
6487
|
a.tracks.forEach((c) => {
|
|
6488
6488
|
c.name = c.name.replaceAll("mixamorig", "");
|
|
@@ -6491,11 +6491,11 @@ class Me {
|
|
|
6491
6491
|
});
|
|
6492
6492
|
const r = { props: h };
|
|
6493
6493
|
h["Hips.position"] && (h["Hips.position"].y < 0.5 ? r.lying = !0 : r.standing = !0), this.animPoses.push({
|
|
6494
|
-
url: t + "-" +
|
|
6494
|
+
url: t + "-" + i,
|
|
6495
6495
|
pose: r
|
|
6496
|
-
}), this.playPose(t, e,
|
|
6496
|
+
}), this.playPose(t, e, n, i, s);
|
|
6497
6497
|
} else {
|
|
6498
|
-
const a = "Pose " + t + " (ndx=" +
|
|
6498
|
+
const a = "Pose " + t + " (ndx=" + i + ") not found";
|
|
6499
6499
|
console.error(a);
|
|
6500
6500
|
}
|
|
6501
6501
|
}
|
|
@@ -6514,16 +6514,16 @@ class Me {
|
|
|
6514
6514
|
* @param {boolean} [mirror=false] Mirror gesture
|
|
6515
6515
|
* @param {number} [ms=1000] Transition time in milliseconds
|
|
6516
6516
|
*/
|
|
6517
|
-
playGesture(t, e = 3,
|
|
6517
|
+
playGesture(t, e = 3, n = !1, i = 1e3) {
|
|
6518
6518
|
if (!this.armature) return;
|
|
6519
6519
|
let s = this.gestureTemplates[t];
|
|
6520
6520
|
if (s) {
|
|
6521
6521
|
this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null);
|
|
6522
6522
|
let l = this.animQueue.findIndex((u) => u.template.name === "talkinghands");
|
|
6523
|
-
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((u) => 0)), this.gesture = this.propsToThreeObjects(s),
|
|
6523
|
+
l !== -1 && (this.animQueue[l].ts = this.animQueue[l].ts.map((u) => 0)), this.gesture = this.propsToThreeObjects(s), n && (this.gesture = this.mirrorPose(this.gesture)), t === "namaste" && this.avatar.body === "M" && (this.gesture["RightArm.quaternion"].rotateTowards(new f.Quaternion(0, 1, 0, 0), -0.25), this.gesture["LeftArm.quaternion"].rotateTowards(new f.Quaternion(0, 1, 0, 0), -0.25));
|
|
6524
6524
|
for (let [u, a] of Object.entries(this.gesture))
|
|
6525
|
-
a.t = this.animClock, a.d =
|
|
6526
|
-
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this,
|
|
6525
|
+
a.t = this.animClock, a.d = i, this.poseTarget.props.hasOwnProperty(u) && (this.poseTarget.props[u].copy(a), this.poseTarget.props[u].t = this.animClock, this.poseTarget.props[u].d = i);
|
|
6526
|
+
e && Number.isFinite(e) && (this.gestureTimeout = setTimeout(this.stopGesture.bind(this, i), 1e3 * e));
|
|
6527
6527
|
}
|
|
6528
6528
|
let o = this.animEmojis[t];
|
|
6529
6529
|
if (o && (o && o.link && (o = this.animEmojis[o.link]), o)) {
|
|
@@ -6550,12 +6550,12 @@ class Me {
|
|
|
6550
6550
|
*/
|
|
6551
6551
|
stopGesture(t = 1e3) {
|
|
6552
6552
|
if (this.gestureTimeout && (clearTimeout(this.gestureTimeout), this.gestureTimeout = null), this.gesture) {
|
|
6553
|
-
const
|
|
6553
|
+
const n = Object.entries(this.gesture);
|
|
6554
6554
|
this.gesture = null;
|
|
6555
|
-
for (const [
|
|
6556
|
-
this.poseTarget.props.hasOwnProperty(
|
|
6555
|
+
for (const [i, s] of n)
|
|
6556
|
+
this.poseTarget.props.hasOwnProperty(i) && (this.poseTarget.props[i].copy(this.getPoseTemplateProp(i)), this.poseTarget.props[i].t = this.animClock, this.poseTarget.props[i].d = t);
|
|
6557
6557
|
}
|
|
6558
|
-
let e = this.animQueue.findIndex((
|
|
6558
|
+
let e = this.animQueue.findIndex((n) => n.gesture);
|
|
6559
6559
|
e !== -1 && this.animQueue.splice(e, 1);
|
|
6560
6560
|
}
|
|
6561
6561
|
/**
|
|
@@ -6567,9 +6567,9 @@ class Me {
|
|
|
6567
6567
|
* @param {Boolean} [relative=false] If true, target is relative to root
|
|
6568
6568
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6569
6569
|
*/
|
|
6570
|
-
ikSolve(t, e = null,
|
|
6570
|
+
ikSolve(t, e = null, n = !1, i = null) {
|
|
6571
6571
|
const s = new f.Vector3(), o = new f.Vector3(), l = new f.Vector3(), u = new f.Vector3(), a = new f.Quaternion(), h = new f.Vector3(), r = new f.Vector3(), c = new f.Vector3(), d = this.ikMesh.getObjectByName(t.root);
|
|
6572
|
-
d.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), d.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e &&
|
|
6572
|
+
d.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), d.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e && n && e.applyQuaternion(this.armature.quaternion).add(d.position);
|
|
6573
6573
|
const g = this.ikMesh.getObjectByName(t.effector), y = t.links;
|
|
6574
6574
|
y.forEach((I) => {
|
|
6575
6575
|
I.bone = this.ikMesh.getObjectByName(I.link), I.bone.quaternion.copy(this.getPoseTemplateProp(I.link + ".quaternion"));
|
|
@@ -6577,12 +6577,12 @@ class Me {
|
|
|
6577
6577
|
const x = t.iterations || 10;
|
|
6578
6578
|
if (e)
|
|
6579
6579
|
for (let I = 0; I < x; I++) {
|
|
6580
|
-
let
|
|
6580
|
+
let F = !1;
|
|
6581
6581
|
for (let p = 0, H = y.length; p < H; p++) {
|
|
6582
6582
|
const z = y[p].bone;
|
|
6583
6583
|
z.matrixWorld.decompose(u, a, h), a.invert(), o.setFromMatrixPosition(g.matrixWorld), l.subVectors(o, u), l.applyQuaternion(a), l.normalize(), s.subVectors(e, u), s.applyQuaternion(a), s.normalize();
|
|
6584
|
-
let
|
|
6585
|
-
|
|
6584
|
+
let v = s.dot(l);
|
|
6585
|
+
v > 1 ? v = 1 : v < -1 && (v = -1), v = Math.acos(v), !(v < 1e-5) && (y[p].minAngle !== void 0 && v < y[p].minAngle && (v = y[p].minAngle), y[p].maxAngle !== void 0 && v > y[p].maxAngle && (v = y[p].maxAngle), r.crossVectors(l, s), r.normalize(), U.setFromAxisAngle(r, v), z.quaternion.multiply(U), z.rotation.setFromVector3(c.setFromEuler(z.rotation).clamp(new f.Vector3(
|
|
6586
6586
|
y[p].minx !== void 0 ? y[p].minx : -1 / 0,
|
|
6587
6587
|
y[p].miny !== void 0 ? y[p].miny : -1 / 0,
|
|
6588
6588
|
y[p].minz !== void 0 ? y[p].minz : -1 / 0
|
|
@@ -6590,12 +6590,12 @@ class Me {
|
|
|
6590
6590
|
y[p].maxx !== void 0 ? y[p].maxx : 1 / 0,
|
|
6591
6591
|
y[p].maxy !== void 0 ? y[p].maxy : 1 / 0,
|
|
6592
6592
|
y[p].maxz !== void 0 ? y[p].maxz : 1 / 0
|
|
6593
|
-
))), z.updateMatrixWorld(!0),
|
|
6593
|
+
))), z.updateMatrixWorld(!0), F = !0);
|
|
6594
6594
|
}
|
|
6595
|
-
if (!
|
|
6595
|
+
if (!F) break;
|
|
6596
6596
|
}
|
|
6597
|
-
|
|
6598
|
-
this.poseTarget.props[I.link + ".quaternion"].copy(I.bone.quaternion), this.poseTarget.props[I.link + ".quaternion"].t = this.animClock, this.poseTarget.props[I.link + ".quaternion"].d =
|
|
6597
|
+
i && y.forEach((I) => {
|
|
6598
|
+
this.poseTarget.props[I.link + ".quaternion"].copy(I.bone.quaternion), this.poseTarget.props[I.link + ".quaternion"].t = this.animClock, this.poseTarget.props[I.link + ".quaternion"].d = i;
|
|
6599
6599
|
});
|
|
6600
6600
|
}
|
|
6601
6601
|
/**
|
|
@@ -6605,7 +6605,7 @@ class Me {
|
|
|
6605
6605
|
this.isRunning = !1, this.stop(), this.stopSpeaking(), this.streamStop(), this.isAvatarOnly ? this.armature && (this.armature.parent && this.armature.parent.remove(this.armature), this.clearThree(this.armature)) : (this.clearThree(this.scene), this.resizeobserver.disconnect(), this.renderer && (this.renderer.dispose(), this.renderer.domElement && this.renderer.domElement.parentNode && this.renderer.domElement.parentNode.removeChild(this.renderer.domElement), this.renderer = null)), this.clearThree(this.ikMesh), this.dynamicbones.dispose();
|
|
6606
6606
|
}
|
|
6607
6607
|
}
|
|
6608
|
-
const
|
|
6608
|
+
const ge = {
|
|
6609
6609
|
apiKey: "sk_ace57ef3ef65a92b9d3bee2a00183b78ca790bc3e10964f2",
|
|
6610
6610
|
// Replace with your actual API key (should start with sk_)
|
|
6611
6611
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
@@ -6625,7 +6625,7 @@ const me = {
|
|
|
6625
6625
|
josh: "VR6AewLTigWG4xSOukaG"
|
|
6626
6626
|
// Male, American
|
|
6627
6627
|
}
|
|
6628
|
-
},
|
|
6628
|
+
}, Me = {
|
|
6629
6629
|
defaultVoice: "aura-2-thalia-en",
|
|
6630
6630
|
// Thalia (Female, English)
|
|
6631
6631
|
voices: {
|
|
@@ -6645,30 +6645,30 @@ const me = {
|
|
|
6645
6645
|
// Male, English - Powerful
|
|
6646
6646
|
}
|
|
6647
6647
|
};
|
|
6648
|
-
function
|
|
6648
|
+
function Ae() {
|
|
6649
6649
|
return {
|
|
6650
6650
|
service: "elevenlabs",
|
|
6651
|
-
endpoint:
|
|
6652
|
-
apiKey:
|
|
6653
|
-
defaultVoice:
|
|
6654
|
-
voices:
|
|
6651
|
+
endpoint: ge.endpoint,
|
|
6652
|
+
apiKey: ge.apiKey,
|
|
6653
|
+
defaultVoice: ge.defaultVoice,
|
|
6654
|
+
voices: ge.voices
|
|
6655
6655
|
};
|
|
6656
6656
|
}
|
|
6657
|
-
function
|
|
6658
|
-
const
|
|
6659
|
-
return Object.entries(
|
|
6657
|
+
function vt() {
|
|
6658
|
+
const N = Ae(), t = [];
|
|
6659
|
+
return Object.entries(N.voices).forEach(([e, n]) => {
|
|
6660
6660
|
t.push({
|
|
6661
|
-
value:
|
|
6662
|
-
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${
|
|
6661
|
+
value: n,
|
|
6662
|
+
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${N.service})`
|
|
6663
6663
|
});
|
|
6664
6664
|
}), t;
|
|
6665
6665
|
}
|
|
6666
|
-
const
|
|
6667
|
-
avatarUrl:
|
|
6666
|
+
const Pe = Ie(({
|
|
6667
|
+
avatarUrl: N = "/avatars/brunette.glb",
|
|
6668
6668
|
avatarBody: t = "F",
|
|
6669
6669
|
mood: e = "neutral",
|
|
6670
|
-
ttsLang:
|
|
6671
|
-
ttsService:
|
|
6670
|
+
ttsLang: n = "en",
|
|
6671
|
+
ttsService: i = null,
|
|
6672
6672
|
ttsVoice: s = null,
|
|
6673
6673
|
ttsApiKey: o = null,
|
|
6674
6674
|
bodyMovement: l = "idle",
|
|
@@ -6685,230 +6685,232 @@ const Ee = Re(({
|
|
|
6685
6685
|
style: y = {},
|
|
6686
6686
|
animations: x = {}
|
|
6687
6687
|
}, I) => {
|
|
6688
|
-
const
|
|
6689
|
-
|
|
6688
|
+
const F = G(null), p = G(null), H = G(a), z = G(null), v = G(null), M = G(!1), [W, _] = de(!0), [re, S] = de(null), [D, Y] = de(!1), [O, q] = de(!1);
|
|
6689
|
+
me(() => {
|
|
6690
|
+
M.current = O;
|
|
6691
|
+
}, [O]), me(() => {
|
|
6690
6692
|
H.current = a;
|
|
6691
6693
|
}, [a]);
|
|
6692
|
-
const
|
|
6693
|
-
let
|
|
6694
|
-
|
|
6694
|
+
const Z = Ae(), le = i || Z.service;
|
|
6695
|
+
let se;
|
|
6696
|
+
le === "browser" ? se = {
|
|
6695
6697
|
service: "browser",
|
|
6696
6698
|
endpoint: "",
|
|
6697
6699
|
apiKey: null,
|
|
6698
6700
|
defaultVoice: "Google US English"
|
|
6699
|
-
} :
|
|
6701
|
+
} : le === "elevenlabs" ? se = {
|
|
6700
6702
|
service: "elevenlabs",
|
|
6701
6703
|
endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
|
|
6702
|
-
apiKey: o ||
|
|
6703
|
-
defaultVoice: s ||
|
|
6704
|
-
voices:
|
|
6705
|
-
} :
|
|
6704
|
+
apiKey: o || Z.apiKey,
|
|
6705
|
+
defaultVoice: s || Z.defaultVoice || ge.defaultVoice,
|
|
6706
|
+
voices: Z.voices || ge.voices
|
|
6707
|
+
} : le === "deepgram" ? se = {
|
|
6706
6708
|
service: "deepgram",
|
|
6707
6709
|
endpoint: "https://api.deepgram.com/v1/speak",
|
|
6708
|
-
apiKey: o ||
|
|
6709
|
-
defaultVoice: s ||
|
|
6710
|
-
voices:
|
|
6711
|
-
} :
|
|
6712
|
-
...
|
|
6710
|
+
apiKey: o || Z.apiKey,
|
|
6711
|
+
defaultVoice: s || Z.defaultVoice || Me.defaultVoice,
|
|
6712
|
+
voices: Z.voices || Me.voices
|
|
6713
|
+
} : se = {
|
|
6714
|
+
...Z,
|
|
6713
6715
|
// Override API key if provided via props
|
|
6714
|
-
apiKey: o !== null ? o :
|
|
6716
|
+
apiKey: o !== null ? o : Z.apiKey
|
|
6715
6717
|
};
|
|
6716
|
-
const
|
|
6717
|
-
url:
|
|
6718
|
+
const ce = {
|
|
6719
|
+
url: N,
|
|
6718
6720
|
body: t,
|
|
6719
6721
|
avatarMood: e,
|
|
6720
|
-
ttsLang:
|
|
6721
|
-
ttsVoice: s ||
|
|
6722
|
+
ttsLang: le === "browser" ? "en-US" : n,
|
|
6723
|
+
ttsVoice: s || se.defaultVoice,
|
|
6722
6724
|
lipsyncLang: "en",
|
|
6723
6725
|
showFullAvatar: a,
|
|
6724
6726
|
bodyMovement: l,
|
|
6725
6727
|
movementIntensity: u
|
|
6726
|
-
},
|
|
6727
|
-
ttsEndpoint:
|
|
6728
|
-
ttsApikey:
|
|
6729
|
-
ttsService:
|
|
6728
|
+
}, Re = {
|
|
6729
|
+
ttsEndpoint: se.endpoint,
|
|
6730
|
+
ttsApikey: se.apiKey,
|
|
6731
|
+
ttsService: le,
|
|
6730
6732
|
lipsyncModules: ["en"],
|
|
6731
6733
|
cameraView: h
|
|
6732
|
-
},
|
|
6733
|
-
if (!(!
|
|
6734
|
+
}, K = T(async () => {
|
|
6735
|
+
if (!(!F.current || p.current))
|
|
6734
6736
|
try {
|
|
6735
|
-
if (
|
|
6736
|
-
if (
|
|
6737
|
-
const
|
|
6738
|
-
c(
|
|
6737
|
+
if (_(!0), S(null), p.current = new Fe(F.current, Re), p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1), x && Object.keys(x).length > 0 && (p.current.customAnimations = x), await p.current.showAvatar(ce, (X) => {
|
|
6738
|
+
if (X.lengthComputable) {
|
|
6739
|
+
const P = Math.min(100, Math.round(X.loaded / X.total * 100));
|
|
6740
|
+
c(P);
|
|
6739
6741
|
}
|
|
6740
|
-
}), await new Promise((
|
|
6741
|
-
const
|
|
6742
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ?
|
|
6742
|
+
}), await new Promise((X) => {
|
|
6743
|
+
const P = () => {
|
|
6744
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? X() : setTimeout(P, 100);
|
|
6743
6745
|
};
|
|
6744
|
-
|
|
6746
|
+
P();
|
|
6745
6747
|
}), p.current && p.current.setShowFullAvatar)
|
|
6746
6748
|
try {
|
|
6747
6749
|
p.current.setShowFullAvatar(a);
|
|
6748
|
-
} catch (
|
|
6749
|
-
console.warn("Error setting full body mode on initialization:",
|
|
6750
|
+
} catch (X) {
|
|
6751
|
+
console.warn("Error setting full body mode on initialization:", X);
|
|
6750
6752
|
}
|
|
6751
|
-
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()),
|
|
6752
|
-
const
|
|
6753
|
+
p.current && p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1, p.current.controls.update()), _(!1), Y(!0), r(p.current);
|
|
6754
|
+
const B = () => {
|
|
6753
6755
|
document.visibilityState === "visible" ? p.current?.start() : p.current?.stop();
|
|
6754
6756
|
};
|
|
6755
|
-
return document.addEventListener("visibilitychange",
|
|
6756
|
-
document.removeEventListener("visibilitychange",
|
|
6757
|
+
return document.addEventListener("visibilitychange", B), () => {
|
|
6758
|
+
document.removeEventListener("visibilitychange", B);
|
|
6757
6759
|
};
|
|
6758
6760
|
} catch (A) {
|
|
6759
|
-
console.error("Error initializing TalkingHead:", A),
|
|
6761
|
+
console.error("Error initializing TalkingHead:", A), S(A.message || "Failed to initialize avatar"), _(!1), d(A);
|
|
6760
6762
|
}
|
|
6761
|
-
}, [
|
|
6762
|
-
|
|
6763
|
+
}, [N, t, e, n, i, s, o, a, l, u, h]);
|
|
6764
|
+
me(() => (K(), () => {
|
|
6763
6765
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6764
|
-
}), [
|
|
6765
|
-
if (!
|
|
6766
|
-
const A = new ResizeObserver((
|
|
6767
|
-
for (const
|
|
6766
|
+
}), [K]), me(() => {
|
|
6767
|
+
if (!F.current || !p.current) return;
|
|
6768
|
+
const A = new ResizeObserver((X) => {
|
|
6769
|
+
for (const P of X)
|
|
6768
6770
|
p.current && p.current.onResize && p.current.onResize();
|
|
6769
6771
|
});
|
|
6770
|
-
A.observe(
|
|
6771
|
-
const
|
|
6772
|
+
A.observe(F.current);
|
|
6773
|
+
const B = () => {
|
|
6772
6774
|
p.current && p.current.onResize && p.current.onResize();
|
|
6773
6775
|
};
|
|
6774
|
-
return window.addEventListener("resize",
|
|
6775
|
-
A.disconnect(), window.removeEventListener("resize",
|
|
6776
|
+
return window.addEventListener("resize", B), () => {
|
|
6777
|
+
A.disconnect(), window.removeEventListener("resize", B);
|
|
6776
6778
|
};
|
|
6777
|
-
}, [
|
|
6778
|
-
const
|
|
6779
|
+
}, [D]);
|
|
6780
|
+
const b = T(async () => {
|
|
6779
6781
|
if (p.current && p.current.audioCtx)
|
|
6780
6782
|
try {
|
|
6781
6783
|
(p.current.audioCtx.state === "suspended" || p.current.audioCtx.state === "interrupted") && (await p.current.audioCtx.resume(), console.log("Audio context resumed"));
|
|
6782
6784
|
} catch (A) {
|
|
6783
6785
|
console.warn("Failed to resume audio context:", A);
|
|
6784
6786
|
}
|
|
6785
|
-
}, []),
|
|
6786
|
-
if (p.current &&
|
|
6787
|
+
}, []), R = T(async (A, B = {}) => {
|
|
6788
|
+
if (p.current && D)
|
|
6787
6789
|
try {
|
|
6788
|
-
z.current = { text: A, options:
|
|
6789
|
-
const
|
|
6790
|
-
...
|
|
6791
|
-
lipsyncLang:
|
|
6790
|
+
v.current && (clearInterval(v.current), v.current = null), z.current = { text: A, options: B }, q(!1), await b();
|
|
6791
|
+
const X = {
|
|
6792
|
+
...B,
|
|
6793
|
+
lipsyncLang: B.lipsyncLang || ce.lipsyncLang || "en"
|
|
6792
6794
|
};
|
|
6793
|
-
if (
|
|
6794
|
-
const
|
|
6795
|
-
let
|
|
6796
|
-
const
|
|
6797
|
-
let
|
|
6798
|
-
|
|
6799
|
-
if (
|
|
6800
|
-
|
|
6801
|
-
|
|
6795
|
+
if (B.onSpeechEnd && p.current) {
|
|
6796
|
+
const P = p.current;
|
|
6797
|
+
let $ = null, pe = 0;
|
|
6798
|
+
const ke = 1200;
|
|
6799
|
+
let fe = !1;
|
|
6800
|
+
$ = setInterval(() => {
|
|
6801
|
+
if (pe++, M.current)
|
|
6802
|
+
return;
|
|
6803
|
+
if (pe > ke) {
|
|
6804
|
+
if ($ && (clearInterval($), $ = null, v.current = null), !fe && !M.current) {
|
|
6805
|
+
fe = !0;
|
|
6802
6806
|
try {
|
|
6803
|
-
|
|
6804
|
-
} catch (
|
|
6805
|
-
console.error("Error in onSpeechEnd callback (timeout):",
|
|
6807
|
+
B.onSpeechEnd();
|
|
6808
|
+
} catch (we) {
|
|
6809
|
+
console.error("Error in onSpeechEnd callback (timeout):", we);
|
|
6806
6810
|
}
|
|
6807
6811
|
}
|
|
6808
6812
|
return;
|
|
6809
6813
|
}
|
|
6810
|
-
const
|
|
6811
|
-
|
|
6812
|
-
if (
|
|
6813
|
-
|
|
6814
|
+
const De = !P.speechQueue || P.speechQueue.length === 0, Oe = !P.audioPlaylist || P.audioPlaylist.length === 0;
|
|
6815
|
+
P && P.isSpeaking === !1 && De && Oe && P.isAudioPlaying === !1 && !fe && !M.current && setTimeout(() => {
|
|
6816
|
+
if (P && !M.current && P.isSpeaking === !1 && (!P.speechQueue || P.speechQueue.length === 0) && (!P.audioPlaylist || P.audioPlaylist.length === 0) && P.isAudioPlaying === !1 && !fe && !M.current) {
|
|
6817
|
+
fe = !0, $ && (clearInterval($), $ = null, v.current = null);
|
|
6814
6818
|
try {
|
|
6815
|
-
|
|
6816
|
-
} catch (
|
|
6817
|
-
console.error("Error in onSpeechEnd callback:",
|
|
6819
|
+
B.onSpeechEnd();
|
|
6820
|
+
} catch (Ne) {
|
|
6821
|
+
console.error("Error in onSpeechEnd callback:", Ne);
|
|
6818
6822
|
}
|
|
6819
6823
|
}
|
|
6820
6824
|
}, 100);
|
|
6821
|
-
}, 100)
|
|
6825
|
+
}, 100), v.current = $;
|
|
6822
6826
|
}
|
|
6823
|
-
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(A,
|
|
6824
|
-
await
|
|
6827
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 ? (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(A, X)) : setTimeout(async () => {
|
|
6828
|
+
await b(), p.current && p.current.lipsync && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(A, X));
|
|
6825
6829
|
}, 100);
|
|
6826
|
-
} catch (
|
|
6827
|
-
console.error("Error speaking text:",
|
|
6830
|
+
} catch (X) {
|
|
6831
|
+
console.error("Error speaking text:", X), S(X.message || "Failed to speak text");
|
|
6828
6832
|
}
|
|
6829
|
-
}, [
|
|
6830
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), z.current = null,
|
|
6831
|
-
}, []),
|
|
6833
|
+
}, [D, b, ce.lipsyncLang]), w = T(() => {
|
|
6834
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), z.current = null, q(!1));
|
|
6835
|
+
}, []), C = T(() => {
|
|
6832
6836
|
if (p.current && p.current.pauseSpeaking) {
|
|
6833
|
-
const A = p.current
|
|
6834
|
-
(
|
|
6837
|
+
const A = p.current;
|
|
6838
|
+
(A.isSpeaking || A.audioPlaylist && A.audioPlaylist.length > 0 || A.speechQueue && A.speechQueue.length > 0) && (v.current && (clearInterval(v.current), v.current = null), A.speechQueue && (A.speechQueue.length = 0), p.current.pauseSpeaking(), M.current = !0, q(!0));
|
|
6835
6839
|
}
|
|
6836
|
-
}, []),
|
|
6837
|
-
if (p.current &&
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
z.current = null;
|
|
6848
|
-
}, [re, U]), C = T((A) => {
|
|
6840
|
+
}, []), V = T(async () => {
|
|
6841
|
+
if (p.current && O && z.current && z.current.text) {
|
|
6842
|
+
const A = z.current, B = A.options || {};
|
|
6843
|
+
q(!1), await b();
|
|
6844
|
+
const X = {
|
|
6845
|
+
...B,
|
|
6846
|
+
lipsyncLang: B.lipsyncLang || ce.lipsyncLang || "en"
|
|
6847
|
+
};
|
|
6848
|
+
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), await R(A.text, X));
|
|
6849
|
+
}
|
|
6850
|
+
}, [b, O, R]), te = T((A) => {
|
|
6849
6851
|
p.current && p.current.setMood(A);
|
|
6850
|
-
}, []),
|
|
6852
|
+
}, []), ne = T((A) => {
|
|
6851
6853
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(A);
|
|
6852
|
-
}, []),
|
|
6854
|
+
}, []), ye = T((A, B = !1) => {
|
|
6853
6855
|
if (p.current && p.current.playAnimation) {
|
|
6854
6856
|
if (x && x[A] && (A = x[A]), p.current.setShowFullAvatar)
|
|
6855
6857
|
try {
|
|
6856
6858
|
p.current.setShowFullAvatar(H.current);
|
|
6857
|
-
} catch (
|
|
6858
|
-
console.warn("Error setting full body mode:",
|
|
6859
|
+
} catch (P) {
|
|
6860
|
+
console.warn("Error setting full body mode:", P);
|
|
6859
6861
|
}
|
|
6860
6862
|
if (A.includes("."))
|
|
6861
6863
|
try {
|
|
6862
|
-
p.current.playAnimation(A, null, 10, 0, 0.01,
|
|
6863
|
-
} catch (
|
|
6864
|
-
console.warn(`Failed to play ${A}:`,
|
|
6864
|
+
p.current.playAnimation(A, null, 10, 0, 0.01, B);
|
|
6865
|
+
} catch (P) {
|
|
6866
|
+
console.warn(`Failed to play ${A}:`, P);
|
|
6865
6867
|
try {
|
|
6866
6868
|
p.current.setBodyMovement("idle");
|
|
6867
|
-
} catch (
|
|
6868
|
-
console.warn("Fallback animation also failed:",
|
|
6869
|
+
} catch ($) {
|
|
6870
|
+
console.warn("Fallback animation also failed:", $);
|
|
6869
6871
|
}
|
|
6870
6872
|
}
|
|
6871
6873
|
else {
|
|
6872
|
-
const
|
|
6873
|
-
let
|
|
6874
|
-
for (const
|
|
6874
|
+
const P = [".fbx", ".glb", ".gltf"];
|
|
6875
|
+
let $ = !1;
|
|
6876
|
+
for (const pe of P)
|
|
6875
6877
|
try {
|
|
6876
|
-
p.current.playAnimation(A +
|
|
6878
|
+
p.current.playAnimation(A + pe, null, 10, 0, 0.01, B), $ = !0;
|
|
6877
6879
|
break;
|
|
6878
6880
|
} catch {
|
|
6879
6881
|
}
|
|
6880
|
-
if (
|
|
6882
|
+
if (!$) {
|
|
6881
6883
|
console.warn("Animation not found:", A);
|
|
6882
6884
|
try {
|
|
6883
6885
|
p.current.setBodyMovement("idle");
|
|
6884
|
-
} catch (
|
|
6885
|
-
console.warn("Fallback animation also failed:",
|
|
6886
|
+
} catch (pe) {
|
|
6887
|
+
console.warn("Fallback animation also failed:", pe);
|
|
6886
6888
|
}
|
|
6887
6889
|
}
|
|
6888
6890
|
}
|
|
6889
6891
|
}
|
|
6890
|
-
}, [x]),
|
|
6892
|
+
}, [x]), Se = T(() => {
|
|
6891
6893
|
p.current && p.current.onResize && p.current.onResize();
|
|
6892
6894
|
}, []);
|
|
6893
|
-
return
|
|
6894
|
-
speakText:
|
|
6895
|
-
stopSpeaking:
|
|
6896
|
-
pauseSpeaking:
|
|
6897
|
-
resumeSpeaking:
|
|
6898
|
-
resumeAudioContext:
|
|
6899
|
-
setMood:
|
|
6900
|
-
setTimingAdjustment:
|
|
6901
|
-
playAnimation:
|
|
6902
|
-
isReady:
|
|
6903
|
-
isPaused:
|
|
6895
|
+
return Le(I, () => ({
|
|
6896
|
+
speakText: R,
|
|
6897
|
+
stopSpeaking: w,
|
|
6898
|
+
pauseSpeaking: C,
|
|
6899
|
+
resumeSpeaking: V,
|
|
6900
|
+
resumeAudioContext: b,
|
|
6901
|
+
setMood: te,
|
|
6902
|
+
setTimingAdjustment: ne,
|
|
6903
|
+
playAnimation: ye,
|
|
6904
|
+
isReady: D,
|
|
6905
|
+
isPaused: O,
|
|
6904
6906
|
talkingHead: p.current,
|
|
6905
|
-
handleResize:
|
|
6907
|
+
handleResize: Se,
|
|
6906
6908
|
setBodyMovement: (A) => {
|
|
6907
6909
|
if (p.current && p.current.setShowFullAvatar && p.current.setBodyMovement)
|
|
6908
6910
|
try {
|
|
6909
6911
|
p.current.setShowFullAvatar(H.current), p.current.setBodyMovement(A);
|
|
6910
|
-
} catch (
|
|
6911
|
-
console.warn("Error setting body movement:",
|
|
6912
|
+
} catch (B) {
|
|
6913
|
+
console.warn("Error setting body movement:", B);
|
|
6912
6914
|
}
|
|
6913
6915
|
},
|
|
6914
6916
|
setMovementIntensity: (A) => p.current?.setMovementIntensity(A),
|
|
@@ -6924,8 +6926,8 @@ const Ee = Re(({
|
|
|
6924
6926
|
if (p.current && p.current.setShowFullAvatar && p.current.playReaction)
|
|
6925
6927
|
try {
|
|
6926
6928
|
p.current.setShowFullAvatar(H.current), p.current.playReaction(A);
|
|
6927
|
-
} catch (
|
|
6928
|
-
console.warn("Error playing reaction:",
|
|
6929
|
+
} catch (B) {
|
|
6930
|
+
console.warn("Error playing reaction:", B);
|
|
6929
6931
|
}
|
|
6930
6932
|
},
|
|
6931
6933
|
playCelebration: () => {
|
|
@@ -6940,8 +6942,8 @@ const Ee = Re(({
|
|
|
6940
6942
|
if (p.current && p.current.setShowFullAvatar)
|
|
6941
6943
|
try {
|
|
6942
6944
|
H.current = A, p.current.setShowFullAvatar(A);
|
|
6943
|
-
} catch (
|
|
6944
|
-
console.warn("Error setting showFullAvatar:",
|
|
6945
|
+
} catch (B) {
|
|
6946
|
+
console.warn("Error setting showFullAvatar:", B);
|
|
6945
6947
|
}
|
|
6946
6948
|
},
|
|
6947
6949
|
lockAvatarPosition: () => {
|
|
@@ -6960,7 +6962,7 @@ const Ee = Re(({
|
|
|
6960
6962
|
console.warn("Error unlocking avatar position:", A);
|
|
6961
6963
|
}
|
|
6962
6964
|
}
|
|
6963
|
-
})), /* @__PURE__ */
|
|
6965
|
+
})), /* @__PURE__ */ Ee(
|
|
6964
6966
|
"div",
|
|
6965
6967
|
{
|
|
6966
6968
|
className: `talking-head-avatar ${g}`,
|
|
@@ -6971,10 +6973,10 @@ const Ee = Re(({
|
|
|
6971
6973
|
...y
|
|
6972
6974
|
},
|
|
6973
6975
|
children: [
|
|
6974
|
-
/* @__PURE__ */
|
|
6976
|
+
/* @__PURE__ */ ue(
|
|
6975
6977
|
"div",
|
|
6976
6978
|
{
|
|
6977
|
-
ref:
|
|
6979
|
+
ref: F,
|
|
6978
6980
|
className: "talking-head-viewer",
|
|
6979
6981
|
style: {
|
|
6980
6982
|
width: "100%",
|
|
@@ -6983,7 +6985,7 @@ const Ee = Re(({
|
|
|
6983
6985
|
}
|
|
6984
6986
|
}
|
|
6985
6987
|
),
|
|
6986
|
-
|
|
6988
|
+
W && /* @__PURE__ */ ue("div", { className: "loading-overlay", style: {
|
|
6987
6989
|
position: "absolute",
|
|
6988
6990
|
top: "50%",
|
|
6989
6991
|
left: "50%",
|
|
@@ -6992,7 +6994,7 @@ const Ee = Re(({
|
|
|
6992
6994
|
fontSize: "18px",
|
|
6993
6995
|
zIndex: 10
|
|
6994
6996
|
}, children: "Loading avatar..." }),
|
|
6995
|
-
|
|
6997
|
+
re && /* @__PURE__ */ ue("div", { className: "error-overlay", style: {
|
|
6996
6998
|
position: "absolute",
|
|
6997
6999
|
top: "50%",
|
|
6998
7000
|
left: "50%",
|
|
@@ -7003,25 +7005,25 @@ const Ee = Re(({
|
|
|
7003
7005
|
zIndex: 10,
|
|
7004
7006
|
padding: "20px",
|
|
7005
7007
|
borderRadius: "8px"
|
|
7006
|
-
}, children:
|
|
7008
|
+
}, children: re })
|
|
7007
7009
|
]
|
|
7008
7010
|
}
|
|
7009
7011
|
);
|
|
7010
7012
|
});
|
|
7011
|
-
|
|
7012
|
-
const
|
|
7013
|
-
text:
|
|
7013
|
+
Pe.displayName = "TalkingHeadAvatar";
|
|
7014
|
+
const ht = Ie(({
|
|
7015
|
+
text: N = "Hello! I'm a talking avatar. How are you today?",
|
|
7014
7016
|
onLoading: t = () => {
|
|
7015
7017
|
},
|
|
7016
7018
|
onError: e = () => {
|
|
7017
7019
|
},
|
|
7018
|
-
onReady:
|
|
7020
|
+
onReady: n = () => {
|
|
7019
7021
|
},
|
|
7020
|
-
className:
|
|
7022
|
+
className: i = "",
|
|
7021
7023
|
style: s = {},
|
|
7022
7024
|
avatarConfig: o = {}
|
|
7023
7025
|
}, l) => {
|
|
7024
|
-
const u =
|
|
7026
|
+
const u = G(null), a = G(null), [h, r] = de(!0), [c, d] = de(null), [g, y] = de(!1), x = Ae(), I = o.ttsService || x.service, F = I === "browser" ? {
|
|
7025
7027
|
endpoint: "",
|
|
7026
7028
|
apiKey: null,
|
|
7027
7029
|
defaultVoice: "Google US English"
|
|
@@ -7037,7 +7039,7 @@ const rt = Re(({
|
|
|
7037
7039
|
body: "F",
|
|
7038
7040
|
avatarMood: "neutral",
|
|
7039
7041
|
ttsLang: I === "browser" ? "en-US" : "en",
|
|
7040
|
-
ttsVoice: o.ttsVoice ||
|
|
7042
|
+
ttsVoice: o.ttsVoice || F.defaultVoice,
|
|
7041
7043
|
lipsyncLang: "en",
|
|
7042
7044
|
// English lip-sync
|
|
7043
7045
|
showFullAvatar: !0,
|
|
@@ -7046,122 +7048,122 @@ const rt = Re(({
|
|
|
7046
7048
|
movementIntensity: 0.5,
|
|
7047
7049
|
...o
|
|
7048
7050
|
}, H = {
|
|
7049
|
-
ttsEndpoint:
|
|
7050
|
-
ttsApikey:
|
|
7051
|
+
ttsEndpoint: F.endpoint,
|
|
7052
|
+
ttsApikey: F.apiKey,
|
|
7051
7053
|
ttsService: I,
|
|
7052
7054
|
lipsyncModules: ["en"],
|
|
7053
7055
|
cameraView: "upper"
|
|
7054
7056
|
}, z = T(async () => {
|
|
7055
7057
|
if (!(!u.current || a.current))
|
|
7056
7058
|
try {
|
|
7057
|
-
if (r(!0), d(null), a.current = new
|
|
7058
|
-
if (
|
|
7059
|
-
const
|
|
7060
|
-
t(
|
|
7059
|
+
if (r(!0), d(null), a.current = new Fe(u.current, H), await a.current.showAvatar(p, (Y) => {
|
|
7060
|
+
if (Y.lengthComputable) {
|
|
7061
|
+
const O = Math.min(100, Math.round(Y.loaded / Y.total * 100));
|
|
7062
|
+
t(O);
|
|
7061
7063
|
}
|
|
7062
7064
|
}), a.current.morphs && a.current.morphs.length > 0) {
|
|
7063
|
-
const
|
|
7064
|
-
console.log("Available morph targets:", Object.keys(
|
|
7065
|
-
const
|
|
7066
|
-
console.log("Viseme morph targets found:",
|
|
7065
|
+
const Y = a.current.morphs[0].morphTargetDictionary;
|
|
7066
|
+
console.log("Available morph targets:", Object.keys(Y));
|
|
7067
|
+
const O = Object.keys(Y).filter((q) => q.startsWith("viseme_"));
|
|
7068
|
+
console.log("Viseme morph targets found:", O), O.length === 0 && (console.warn("No viseme morph targets found! Lip-sync will not work properly."), console.log("Expected viseme targets: viseme_aa, viseme_E, viseme_I, viseme_O, viseme_U, viseme_PP, viseme_SS, viseme_TH, viseme_DD, viseme_FF, viseme_kk, viseme_nn, viseme_RR, viseme_CH, viseme_sil"));
|
|
7067
7069
|
}
|
|
7068
|
-
if (await new Promise((
|
|
7069
|
-
const
|
|
7070
|
-
a.current.lipsync && Object.keys(a.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(a.current.lipsync)),
|
|
7070
|
+
if (await new Promise((Y) => {
|
|
7071
|
+
const O = () => {
|
|
7072
|
+
a.current.lipsync && Object.keys(a.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(a.current.lipsync)), Y()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(O, 100));
|
|
7071
7073
|
};
|
|
7072
|
-
|
|
7074
|
+
O();
|
|
7073
7075
|
}), a.current && a.current.setShowFullAvatar)
|
|
7074
7076
|
try {
|
|
7075
7077
|
a.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7076
|
-
} catch (
|
|
7077
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7078
|
+
} catch (Y) {
|
|
7079
|
+
console.warn("Error setting full body mode on initialization:", Y);
|
|
7078
7080
|
}
|
|
7079
|
-
r(!1), y(!0),
|
|
7080
|
-
const
|
|
7081
|
+
r(!1), y(!0), n(a.current);
|
|
7082
|
+
const D = () => {
|
|
7081
7083
|
document.visibilityState === "visible" ? a.current?.start() : a.current?.stop();
|
|
7082
7084
|
};
|
|
7083
|
-
return document.addEventListener("visibilitychange",
|
|
7084
|
-
document.removeEventListener("visibilitychange",
|
|
7085
|
+
return document.addEventListener("visibilitychange", D), () => {
|
|
7086
|
+
document.removeEventListener("visibilitychange", D);
|
|
7085
7087
|
};
|
|
7086
7088
|
} catch (S) {
|
|
7087
7089
|
console.error("Error initializing TalkingHead:", S), d(S.message || "Failed to initialize avatar"), r(!1), e(S);
|
|
7088
7090
|
}
|
|
7089
7091
|
}, []);
|
|
7090
|
-
|
|
7092
|
+
me(() => (z(), () => {
|
|
7091
7093
|
a.current && (a.current.stop(), a.current.dispose(), a.current = null);
|
|
7092
7094
|
}), [z]);
|
|
7093
|
-
const
|
|
7095
|
+
const v = T((S) => {
|
|
7094
7096
|
if (a.current && g)
|
|
7095
7097
|
try {
|
|
7096
7098
|
console.log("Speaking text:", S), console.log("Avatar config:", p), console.log("TalkingHead instance:", a.current), a.current.lipsync && Object.keys(a.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(a.current.lipsync)), a.current.setSlowdownRate && (a.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), a.current.speakText(S)) : (console.warn("Lip-sync modules not ready, waiting..."), setTimeout(() => {
|
|
7097
7099
|
a.current && a.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), a.current.setSlowdownRate && (a.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), a.current.speakText(S)) : console.error("Lip-sync still not ready after waiting");
|
|
7098
7100
|
}, 500));
|
|
7099
|
-
} catch (
|
|
7100
|
-
console.error("Error speaking text:",
|
|
7101
|
+
} catch (D) {
|
|
7102
|
+
console.error("Error speaking text:", D), d(D.message || "Failed to speak text");
|
|
7101
7103
|
}
|
|
7102
7104
|
else
|
|
7103
7105
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!a.current);
|
|
7104
|
-
}, [g, p]),
|
|
7106
|
+
}, [g, p]), M = T(() => {
|
|
7105
7107
|
a.current && (a.current.stopSpeaking(), a.current.setSlowdownRate && (a.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7106
|
-
}, []),
|
|
7108
|
+
}, []), W = T((S) => {
|
|
7107
7109
|
a.current && a.current.setMood(S);
|
|
7108
7110
|
}, []), _ = T((S) => {
|
|
7109
7111
|
a.current && a.current.setSlowdownRate && (a.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7110
|
-
}, []),
|
|
7112
|
+
}, []), re = T((S, D = !1) => {
|
|
7111
7113
|
if (a.current && a.current.playAnimation) {
|
|
7112
7114
|
if (a.current.setShowFullAvatar)
|
|
7113
7115
|
try {
|
|
7114
7116
|
a.current.setShowFullAvatar(!0);
|
|
7115
|
-
} catch (
|
|
7116
|
-
console.warn("Error setting full body mode:",
|
|
7117
|
+
} catch (O) {
|
|
7118
|
+
console.warn("Error setting full body mode:", O);
|
|
7117
7119
|
}
|
|
7118
7120
|
if (S.includes("."))
|
|
7119
7121
|
try {
|
|
7120
|
-
a.current.playAnimation(S, null, 10, 0, 0.01,
|
|
7121
|
-
} catch (
|
|
7122
|
-
console.log(`Failed to play ${S}:`,
|
|
7122
|
+
a.current.playAnimation(S, null, 10, 0, 0.01, D), console.log("Playing animation:", S);
|
|
7123
|
+
} catch (O) {
|
|
7124
|
+
console.log(`Failed to play ${S}:`, O);
|
|
7123
7125
|
try {
|
|
7124
7126
|
a.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7125
|
-
} catch (
|
|
7126
|
-
console.warn("Fallback animation also failed:",
|
|
7127
|
+
} catch (q) {
|
|
7128
|
+
console.warn("Fallback animation also failed:", q);
|
|
7127
7129
|
}
|
|
7128
7130
|
}
|
|
7129
7131
|
else {
|
|
7130
|
-
const
|
|
7131
|
-
let
|
|
7132
|
-
for (const
|
|
7132
|
+
const O = [".fbx", ".glb", ".gltf"];
|
|
7133
|
+
let q = !1;
|
|
7134
|
+
for (const Z of O)
|
|
7133
7135
|
try {
|
|
7134
|
-
a.current.playAnimation(S +
|
|
7136
|
+
a.current.playAnimation(S + Z, null, 10, 0, 0.01, D), console.log("Playing animation:", S + Z), q = !0;
|
|
7135
7137
|
break;
|
|
7136
7138
|
} catch {
|
|
7137
|
-
console.log(`Failed to play ${S}${
|
|
7139
|
+
console.log(`Failed to play ${S}${Z}, trying next format...`);
|
|
7138
7140
|
}
|
|
7139
|
-
if (!
|
|
7141
|
+
if (!q) {
|
|
7140
7142
|
console.warn("Animation system not available or animation not found:", S);
|
|
7141
7143
|
try {
|
|
7142
7144
|
a.current.setBodyMovement("idle"), console.log("Fallback to idle animation");
|
|
7143
|
-
} catch (
|
|
7144
|
-
console.warn("Fallback animation also failed:",
|
|
7145
|
+
} catch (Z) {
|
|
7146
|
+
console.warn("Fallback animation also failed:", Z);
|
|
7145
7147
|
}
|
|
7146
7148
|
}
|
|
7147
7149
|
}
|
|
7148
7150
|
} else
|
|
7149
7151
|
console.warn("Animation system not available or animation not found:", S);
|
|
7150
7152
|
}, []);
|
|
7151
|
-
return
|
|
7152
|
-
speakText:
|
|
7153
|
-
stopSpeaking:
|
|
7154
|
-
setMood:
|
|
7153
|
+
return Le(l, () => ({
|
|
7154
|
+
speakText: v,
|
|
7155
|
+
stopSpeaking: M,
|
|
7156
|
+
setMood: W,
|
|
7155
7157
|
setTimingAdjustment: _,
|
|
7156
|
-
playAnimation:
|
|
7158
|
+
playAnimation: re,
|
|
7157
7159
|
isReady: g,
|
|
7158
7160
|
talkingHead: a.current,
|
|
7159
7161
|
setBodyMovement: (S) => {
|
|
7160
7162
|
if (a.current && a.current.setShowFullAvatar && a.current.setBodyMovement)
|
|
7161
7163
|
try {
|
|
7162
7164
|
a.current.setShowFullAvatar(!0), a.current.setBodyMovement(S), console.log("Body movement set with full body mode:", S);
|
|
7163
|
-
} catch (
|
|
7164
|
-
console.warn("Error setting body movement:",
|
|
7165
|
+
} catch (D) {
|
|
7166
|
+
console.warn("Error setting body movement:", D);
|
|
7165
7167
|
}
|
|
7166
7168
|
},
|
|
7167
7169
|
setMovementIntensity: (S) => a.current?.setMovementIntensity(S),
|
|
@@ -7177,8 +7179,8 @@ const rt = Re(({
|
|
|
7177
7179
|
if (a.current && a.current.setShowFullAvatar && a.current.playReaction)
|
|
7178
7180
|
try {
|
|
7179
7181
|
a.current.setShowFullAvatar(!0), a.current.playReaction(S), console.log("Reaction played with full body mode:", S);
|
|
7180
|
-
} catch (
|
|
7181
|
-
console.warn("Error playing reaction:",
|
|
7182
|
+
} catch (D) {
|
|
7183
|
+
console.warn("Error playing reaction:", D);
|
|
7182
7184
|
}
|
|
7183
7185
|
},
|
|
7184
7186
|
playCelebration: () => {
|
|
@@ -7193,8 +7195,8 @@ const rt = Re(({
|
|
|
7193
7195
|
if (a.current && a.current.setShowFullAvatar)
|
|
7194
7196
|
try {
|
|
7195
7197
|
a.current.setShowFullAvatar(S), console.log("Show full avatar set to:", S);
|
|
7196
|
-
} catch (
|
|
7197
|
-
console.warn("Error setting showFullAvatar:",
|
|
7198
|
+
} catch (D) {
|
|
7199
|
+
console.warn("Error setting showFullAvatar:", D);
|
|
7198
7200
|
}
|
|
7199
7201
|
},
|
|
7200
7202
|
lockAvatarPosition: () => {
|
|
@@ -7213,8 +7215,8 @@ const rt = Re(({
|
|
|
7213
7215
|
console.warn("Error unlocking avatar position:", S);
|
|
7214
7216
|
}
|
|
7215
7217
|
}
|
|
7216
|
-
})), /* @__PURE__ */
|
|
7217
|
-
/* @__PURE__ */
|
|
7218
|
+
})), /* @__PURE__ */ Ee("div", { className: `talking-head-container ${i}`, style: s, children: [
|
|
7219
|
+
/* @__PURE__ */ ue(
|
|
7218
7220
|
"div",
|
|
7219
7221
|
{
|
|
7220
7222
|
ref: u,
|
|
@@ -7226,7 +7228,7 @@ const rt = Re(({
|
|
|
7226
7228
|
}
|
|
7227
7229
|
}
|
|
7228
7230
|
),
|
|
7229
|
-
h && /* @__PURE__ */
|
|
7231
|
+
h && /* @__PURE__ */ ue("div", { className: "loading-overlay", style: {
|
|
7230
7232
|
position: "absolute",
|
|
7231
7233
|
top: "50%",
|
|
7232
7234
|
left: "50%",
|
|
@@ -7235,7 +7237,7 @@ const rt = Re(({
|
|
|
7235
7237
|
fontSize: "18px",
|
|
7236
7238
|
zIndex: 10
|
|
7237
7239
|
}, children: "Loading avatar..." }),
|
|
7238
|
-
c && /* @__PURE__ */
|
|
7240
|
+
c && /* @__PURE__ */ ue("div", { className: "error-overlay", style: {
|
|
7239
7241
|
position: "absolute",
|
|
7240
7242
|
top: "50%",
|
|
7241
7243
|
left: "50%",
|
|
@@ -7249,14 +7251,14 @@ const rt = Re(({
|
|
|
7249
7251
|
}, children: c })
|
|
7250
7252
|
] });
|
|
7251
7253
|
});
|
|
7252
|
-
|
|
7253
|
-
const
|
|
7254
|
-
curriculumData:
|
|
7254
|
+
ht.displayName = "TalkingHeadComponent";
|
|
7255
|
+
const ut = Ie(({
|
|
7256
|
+
curriculumData: N = null,
|
|
7255
7257
|
avatarConfig: t = {},
|
|
7256
7258
|
animations: e = {},
|
|
7257
|
-
onLessonStart:
|
|
7259
|
+
onLessonStart: n = () => {
|
|
7258
7260
|
},
|
|
7259
|
-
onLessonComplete:
|
|
7261
|
+
onLessonComplete: i = () => {
|
|
7260
7262
|
},
|
|
7261
7263
|
onQuestionAnswer: s = () => {
|
|
7262
7264
|
},
|
|
@@ -7266,7 +7268,7 @@ const lt = Re(({
|
|
|
7266
7268
|
},
|
|
7267
7269
|
autoStart: u = !1
|
|
7268
7270
|
}, a) => {
|
|
7269
|
-
const h =
|
|
7271
|
+
const h = G(null), r = G({
|
|
7270
7272
|
currentModuleIndex: 0,
|
|
7271
7273
|
currentLessonIndex: 0,
|
|
7272
7274
|
currentQuestionIndex: 0,
|
|
@@ -7276,18 +7278,18 @@ const lt = Re(({
|
|
|
7276
7278
|
curriculumCompleted: !1,
|
|
7277
7279
|
score: 0,
|
|
7278
7280
|
totalQuestions: 0
|
|
7279
|
-
}), c =
|
|
7280
|
-
onLessonStart:
|
|
7281
|
-
onLessonComplete:
|
|
7281
|
+
}), c = G({
|
|
7282
|
+
onLessonStart: n,
|
|
7283
|
+
onLessonComplete: i,
|
|
7282
7284
|
onQuestionAnswer: s,
|
|
7283
7285
|
onCurriculumComplete: o,
|
|
7284
7286
|
onCustomAction: l
|
|
7285
|
-
}), d =
|
|
7287
|
+
}), d = G(null), g = G(null), y = G(null), x = G(null), I = G(null), F = G(null), p = G(null), H = G(N?.curriculum || {
|
|
7286
7288
|
title: "Default Curriculum",
|
|
7287
7289
|
description: "No curriculum data provided",
|
|
7288
7290
|
language: "en",
|
|
7289
7291
|
modules: []
|
|
7290
|
-
}), z =
|
|
7292
|
+
}), z = G({
|
|
7291
7293
|
avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
|
|
7292
7294
|
avatarBody: t.avatarBody || "F",
|
|
7293
7295
|
mood: t.mood || "happy",
|
|
@@ -7301,16 +7303,16 @@ const lt = Re(({
|
|
|
7301
7303
|
animations: e,
|
|
7302
7304
|
lipsyncLang: "en"
|
|
7303
7305
|
});
|
|
7304
|
-
|
|
7306
|
+
me(() => {
|
|
7305
7307
|
c.current = {
|
|
7306
|
-
onLessonStart:
|
|
7307
|
-
onLessonComplete:
|
|
7308
|
+
onLessonStart: n,
|
|
7309
|
+
onLessonComplete: i,
|
|
7308
7310
|
onQuestionAnswer: s,
|
|
7309
7311
|
onCurriculumComplete: o,
|
|
7310
7312
|
onCustomAction: l
|
|
7311
7313
|
};
|
|
7312
|
-
}, [
|
|
7313
|
-
H.current =
|
|
7314
|
+
}, [n, i, s, o, l]), me(() => {
|
|
7315
|
+
H.current = N?.curriculum || {
|
|
7314
7316
|
title: "Default Curriculum",
|
|
7315
7317
|
description: "No curriculum data provided",
|
|
7316
7318
|
language: "en",
|
|
@@ -7329,12 +7331,12 @@ const lt = Re(({
|
|
|
7329
7331
|
animations: e,
|
|
7330
7332
|
lipsyncLang: "en"
|
|
7331
7333
|
};
|
|
7332
|
-
}, [
|
|
7333
|
-
const
|
|
7334
|
+
}, [N, t, e]);
|
|
7335
|
+
const v = T(() => (H.current || { modules: [] }).modules[r.current.currentModuleIndex]?.lessons[r.current.currentLessonIndex], []), M = T(() => v()?.questions[r.current.currentQuestionIndex], [v]), W = T((b, R) => R.type === "multiple_choice" || R.type === "true_false" ? b === R.answer : R.type === "code_test" && typeof b == "object" && b !== null ? b.passed === !0 : !1, []), _ = T(() => {
|
|
7334
7336
|
r.current.lessonCompleted = !0, r.current.isQuestionMode = !1;
|
|
7335
7337
|
const b = r.current.totalQuestions > 0 ? Math.round(r.current.score / r.current.totalQuestions * 100) : 100;
|
|
7336
|
-
let
|
|
7337
|
-
if (r.current.totalQuestions > 0 ?
|
|
7338
|
+
let R = "Congratulations! You've completed this lesson";
|
|
7339
|
+
if (r.current.totalQuestions > 0 ? R += ` You got ${r.current.score} correct out of ${r.current.totalQuestions} question${r.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${b} percent. ` : R += "! ", b >= 80 ? R += "Excellent work! You have a great understanding of this topic." : b >= 60 ? R += "Good job! You understand most of the concepts." : R += "Keep practicing! You're making progress.", c.current.onLessonComplete({
|
|
7338
7340
|
moduleIndex: r.current.currentModuleIndex,
|
|
7339
7341
|
lessonIndex: r.current.currentLessonIndex,
|
|
7340
7342
|
score: r.current.score,
|
|
@@ -7354,9 +7356,9 @@ const lt = Re(({
|
|
|
7354
7356
|
} catch {
|
|
7355
7357
|
h.current.playCelebration();
|
|
7356
7358
|
}
|
|
7357
|
-
const w = H.current || { modules: [] }, C = w.modules[r.current.currentModuleIndex],
|
|
7358
|
-
h.current.speakText(
|
|
7359
|
-
lipsyncLang:
|
|
7359
|
+
const w = H.current || { modules: [] }, C = w.modules[r.current.currentModuleIndex], V = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, te = r.current.currentModuleIndex < (w.modules?.length || 0) - 1, ne = V || te, ye = z.current || { lipsyncLang: "en" };
|
|
7360
|
+
h.current.speakText(R, {
|
|
7361
|
+
lipsyncLang: ye.lipsyncLang,
|
|
7360
7362
|
onSpeechEnd: () => {
|
|
7361
7363
|
c.current.onCustomAction({
|
|
7362
7364
|
type: "lessonCompleteFeedbackDone",
|
|
@@ -7365,17 +7367,17 @@ const lt = Re(({
|
|
|
7365
7367
|
score: r.current.score,
|
|
7366
7368
|
totalQuestions: r.current.totalQuestions,
|
|
7367
7369
|
percentage: b,
|
|
7368
|
-
hasNextLesson:
|
|
7370
|
+
hasNextLesson: ne
|
|
7369
7371
|
});
|
|
7370
7372
|
}
|
|
7371
7373
|
});
|
|
7372
7374
|
}
|
|
7373
|
-
}, [e.lessonComplete]),
|
|
7375
|
+
}, [e.lessonComplete]), re = T(() => {
|
|
7374
7376
|
r.current.curriculumCompleted = !0;
|
|
7375
7377
|
const b = H.current || { modules: [] };
|
|
7376
7378
|
if (c.current.onCurriculumComplete({
|
|
7377
7379
|
modules: b.modules.length,
|
|
7378
|
-
totalLessons: b.modules.reduce((
|
|
7380
|
+
totalLessons: b.modules.reduce((R, w) => R + w.lessons.length, 0)
|
|
7379
7381
|
}), h.current) {
|
|
7380
7382
|
if (h.current.setMood("celebrating"), e.curriculumComplete)
|
|
7381
7383
|
try {
|
|
@@ -7383,82 +7385,82 @@ const lt = Re(({
|
|
|
7383
7385
|
} catch {
|
|
7384
7386
|
h.current.playCelebration();
|
|
7385
7387
|
}
|
|
7386
|
-
const
|
|
7387
|
-
h.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang:
|
|
7388
|
+
const R = z.current || { lipsyncLang: "en" };
|
|
7389
|
+
h.current.speakText("Amazing! You've completed the entire curriculum! You're now ready to move on to more advanced topics. Well done!", { lipsyncLang: R.lipsyncLang });
|
|
7388
7390
|
}
|
|
7389
7391
|
}, [e.curriculumComplete]), S = T(() => {
|
|
7390
|
-
const b =
|
|
7392
|
+
const b = v();
|
|
7391
7393
|
r.current.isQuestionMode = !0, r.current.currentQuestionIndex = 0, r.current.totalQuestions = b?.questions?.length || 0, r.current.score = 0;
|
|
7392
|
-
const
|
|
7393
|
-
|
|
7394
|
+
const R = M();
|
|
7395
|
+
R && c.current.onCustomAction({
|
|
7394
7396
|
type: "questionStart",
|
|
7395
7397
|
moduleIndex: r.current.currentModuleIndex,
|
|
7396
7398
|
lessonIndex: r.current.currentLessonIndex,
|
|
7397
7399
|
questionIndex: r.current.currentQuestionIndex,
|
|
7398
7400
|
totalQuestions: r.current.totalQuestions,
|
|
7399
|
-
question:
|
|
7401
|
+
question: R,
|
|
7400
7402
|
score: r.current.score
|
|
7401
7403
|
});
|
|
7402
7404
|
const w = () => {
|
|
7403
|
-
if (!h.current || !
|
|
7405
|
+
if (!h.current || !R) return;
|
|
7404
7406
|
if (h.current.setMood("happy"), e.questionStart)
|
|
7405
7407
|
try {
|
|
7406
7408
|
h.current.playAnimation(e.questionStart, !0);
|
|
7407
|
-
} catch (
|
|
7408
|
-
console.warn("Failed to play questionStart animation:",
|
|
7409
|
+
} catch (V) {
|
|
7410
|
+
console.warn("Failed to play questionStart animation:", V);
|
|
7409
7411
|
}
|
|
7410
7412
|
const C = z.current || { lipsyncLang: "en" };
|
|
7411
|
-
|
|
7413
|
+
R.type === "code_test" ? h.current.speakText(`Let's test your coding skills! Here's your first challenge: ${R.question}`, { lipsyncLang: C.lipsyncLang }) : R.type === "multiple_choice" ? h.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: C.lipsyncLang }) : R.type === "true_false" ? h.current.speakText(`Let's start with some true or false questions. First question: ${R.question}`, { lipsyncLang: C.lipsyncLang }) : h.current.speakText(`Now let me ask you some questions. Here's the first one: ${R.question}`, { lipsyncLang: C.lipsyncLang });
|
|
7412
7414
|
};
|
|
7413
|
-
if (h.current && h.current.isReady &&
|
|
7415
|
+
if (h.current && h.current.isReady && R)
|
|
7414
7416
|
w();
|
|
7415
7417
|
else if (h.current && h.current.isReady) {
|
|
7416
7418
|
const C = z.current || { lipsyncLang: "en" };
|
|
7417
7419
|
h.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: C.lipsyncLang });
|
|
7418
7420
|
} else {
|
|
7419
7421
|
const C = setInterval(() => {
|
|
7420
|
-
h.current && h.current.isReady && (clearInterval(C),
|
|
7422
|
+
h.current && h.current.isReady && (clearInterval(C), R && w());
|
|
7421
7423
|
}, 100);
|
|
7422
7424
|
setTimeout(() => {
|
|
7423
7425
|
clearInterval(C);
|
|
7424
7426
|
}, 5e3);
|
|
7425
7427
|
}
|
|
7426
|
-
}, [e.questionStart,
|
|
7427
|
-
const b =
|
|
7428
|
+
}, [e.questionStart, v, M]), D = T(() => {
|
|
7429
|
+
const b = v();
|
|
7428
7430
|
if (r.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
|
|
7429
7431
|
h.current && h.current.stopSpeaking && h.current.stopSpeaking(), r.current.currentQuestionIndex += 1;
|
|
7430
|
-
const
|
|
7431
|
-
|
|
7432
|
+
const R = M();
|
|
7433
|
+
R && c.current.onCustomAction({
|
|
7432
7434
|
type: "nextQuestion",
|
|
7433
7435
|
moduleIndex: r.current.currentModuleIndex,
|
|
7434
7436
|
lessonIndex: r.current.currentLessonIndex,
|
|
7435
7437
|
questionIndex: r.current.currentQuestionIndex,
|
|
7436
7438
|
totalQuestions: r.current.totalQuestions,
|
|
7437
|
-
question:
|
|
7439
|
+
question: R,
|
|
7438
7440
|
score: r.current.score
|
|
7439
7441
|
});
|
|
7440
7442
|
const w = () => {
|
|
7441
|
-
if (!h.current || !
|
|
7443
|
+
if (!h.current || !R) return;
|
|
7442
7444
|
if (h.current.setMood("happy"), h.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7443
7445
|
try {
|
|
7444
7446
|
h.current.playAnimation(e.nextQuestion, !0);
|
|
7445
|
-
} catch (
|
|
7446
|
-
console.warn("Failed to play nextQuestion animation:",
|
|
7447
|
+
} catch (V) {
|
|
7448
|
+
console.warn("Failed to play nextQuestion animation:", V);
|
|
7447
7449
|
}
|
|
7448
7450
|
const C = z.current || { lipsyncLang: "en" };
|
|
7449
|
-
|
|
7451
|
+
R.type === "code_test" ? h.current.speakText(`Great! Now let's move on to your next coding challenge: ${R.question}`, {
|
|
7450
7452
|
lipsyncLang: C.lipsyncLang
|
|
7451
|
-
}) :
|
|
7453
|
+
}) : R.type === "multiple_choice" ? h.current.speakText(`Alright! Here's your next question: ${R.question}`, {
|
|
7452
7454
|
lipsyncLang: C.lipsyncLang
|
|
7453
|
-
}) :
|
|
7455
|
+
}) : R.type === "true_false" ? h.current.speakText(`Now let's try this one: ${R.question}`, {
|
|
7454
7456
|
lipsyncLang: C.lipsyncLang
|
|
7455
|
-
}) : h.current.speakText(`Here's the next question: ${
|
|
7457
|
+
}) : h.current.speakText(`Here's the next question: ${R.question}`, {
|
|
7456
7458
|
lipsyncLang: C.lipsyncLang
|
|
7457
7459
|
});
|
|
7458
7460
|
};
|
|
7459
|
-
if (h.current && h.current.isReady &&
|
|
7461
|
+
if (h.current && h.current.isReady && R)
|
|
7460
7462
|
w();
|
|
7461
|
-
else if (
|
|
7463
|
+
else if (R) {
|
|
7462
7464
|
const C = setInterval(() => {
|
|
7463
7465
|
h.current && h.current.isReady && (clearInterval(C), w());
|
|
7464
7466
|
}, 100);
|
|
@@ -7474,52 +7476,52 @@ const lt = Re(({
|
|
|
7474
7476
|
totalQuestions: r.current.totalQuestions,
|
|
7475
7477
|
score: r.current.score
|
|
7476
7478
|
});
|
|
7477
|
-
}, [e.nextQuestion,
|
|
7478
|
-
const b = H.current || { modules: [] },
|
|
7479
|
-
if (r.current.currentLessonIndex < (
|
|
7479
|
+
}, [e.nextQuestion, v, M]), Y = T(() => {
|
|
7480
|
+
const b = H.current || { modules: [] }, R = b.modules[r.current.currentModuleIndex];
|
|
7481
|
+
if (r.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7480
7482
|
r.current.currentLessonIndex += 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7481
|
-
const C = b.modules[r.current.currentModuleIndex],
|
|
7483
|
+
const C = b.modules[r.current.currentModuleIndex], V = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, te = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, ne = V || te;
|
|
7482
7484
|
c.current.onCustomAction({
|
|
7483
7485
|
type: "lessonStart",
|
|
7484
7486
|
moduleIndex: r.current.currentModuleIndex,
|
|
7485
7487
|
lessonIndex: r.current.currentLessonIndex,
|
|
7486
|
-
hasNextLesson:
|
|
7488
|
+
hasNextLesson: ne
|
|
7487
7489
|
}), c.current.onLessonStart({
|
|
7488
7490
|
moduleIndex: r.current.currentModuleIndex,
|
|
7489
7491
|
lessonIndex: r.current.currentLessonIndex,
|
|
7490
|
-
lesson:
|
|
7492
|
+
lesson: v()
|
|
7491
7493
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7492
7494
|
} else if (r.current.currentModuleIndex < (b.modules?.length || 0) - 1) {
|
|
7493
7495
|
r.current.currentModuleIndex += 1, r.current.currentLessonIndex = 0, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7494
|
-
const
|
|
7496
|
+
const V = b.modules[r.current.currentModuleIndex], te = r.current.currentLessonIndex < (V?.lessons?.length || 0) - 1, ne = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, ye = te || ne;
|
|
7495
7497
|
c.current.onCustomAction({
|
|
7496
7498
|
type: "lessonStart",
|
|
7497
7499
|
moduleIndex: r.current.currentModuleIndex,
|
|
7498
7500
|
lessonIndex: r.current.currentLessonIndex,
|
|
7499
|
-
hasNextLesson:
|
|
7501
|
+
hasNextLesson: ye
|
|
7500
7502
|
}), c.current.onLessonStart({
|
|
7501
7503
|
moduleIndex: r.current.currentModuleIndex,
|
|
7502
7504
|
lessonIndex: r.current.currentLessonIndex,
|
|
7503
|
-
lesson:
|
|
7505
|
+
lesson: v()
|
|
7504
7506
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7505
7507
|
} else
|
|
7506
7508
|
I.current && I.current();
|
|
7507
|
-
}, []),
|
|
7508
|
-
const b =
|
|
7509
|
-
let
|
|
7509
|
+
}, []), O = T(() => {
|
|
7510
|
+
const b = v();
|
|
7511
|
+
let R = null;
|
|
7510
7512
|
if (b?.avatar_script && b?.body) {
|
|
7511
|
-
const w = b.avatar_script.trim(), C = b.body.trim(),
|
|
7512
|
-
|
|
7513
|
+
const w = b.avatar_script.trim(), C = b.body.trim(), V = w.match(/[.!?]$/) ? " " : ". ";
|
|
7514
|
+
R = `${w}${V}${C}`;
|
|
7513
7515
|
} else
|
|
7514
|
-
|
|
7515
|
-
if (h.current && h.current.isReady &&
|
|
7516
|
+
R = b?.avatar_script || b?.body || null;
|
|
7517
|
+
if (h.current && h.current.isReady && R) {
|
|
7516
7518
|
r.current.isTeaching = !0, r.current.isQuestionMode = !1, r.current.score = 0, r.current.totalQuestions = 0, h.current.setMood("happy");
|
|
7517
7519
|
let w = !1;
|
|
7518
7520
|
if (e.teaching)
|
|
7519
7521
|
try {
|
|
7520
7522
|
h.current.playAnimation(e.teaching, !0), w = !0;
|
|
7521
|
-
} catch (
|
|
7522
|
-
console.warn("Failed to play teaching animation:",
|
|
7523
|
+
} catch (V) {
|
|
7524
|
+
console.warn("Failed to play teaching animation:", V);
|
|
7523
7525
|
}
|
|
7524
7526
|
w || h.current.setBodyMovement("gesturing");
|
|
7525
7527
|
const C = z.current || { lipsyncLang: "en" };
|
|
@@ -7532,7 +7534,7 @@ const lt = Re(({
|
|
|
7532
7534
|
moduleIndex: r.current.currentModuleIndex,
|
|
7533
7535
|
lessonIndex: r.current.currentLessonIndex,
|
|
7534
7536
|
lesson: b
|
|
7535
|
-
}), h.current.speakText(
|
|
7537
|
+
}), h.current.speakText(R, {
|
|
7536
7538
|
lipsyncLang: C.lipsyncLang,
|
|
7537
7539
|
onSpeechEnd: () => {
|
|
7538
7540
|
r.current.isTeaching = !1, c.current.onCustomAction({
|
|
@@ -7545,15 +7547,15 @@ const lt = Re(({
|
|
|
7545
7547
|
}
|
|
7546
7548
|
});
|
|
7547
7549
|
}
|
|
7548
|
-
}, [e.teaching,
|
|
7549
|
-
const
|
|
7550
|
+
}, [e.teaching, v]), q = T((b) => {
|
|
7551
|
+
const R = M(), w = W(b, R);
|
|
7550
7552
|
if (w && (r.current.score += 1), c.current.onQuestionAnswer({
|
|
7551
7553
|
moduleIndex: r.current.currentModuleIndex,
|
|
7552
7554
|
lessonIndex: r.current.currentLessonIndex,
|
|
7553
7555
|
questionIndex: r.current.currentQuestionIndex,
|
|
7554
7556
|
answer: b,
|
|
7555
7557
|
isCorrect: w,
|
|
7556
|
-
question:
|
|
7558
|
+
question: R
|
|
7557
7559
|
}), h.current)
|
|
7558
7560
|
if (w) {
|
|
7559
7561
|
if (h.current.setMood("happy"), e.correct)
|
|
@@ -7563,18 +7565,18 @@ const lt = Re(({
|
|
|
7563
7565
|
h.current.setBodyMovement("happy");
|
|
7564
7566
|
}
|
|
7565
7567
|
h.current.setBodyMovement("gesturing");
|
|
7566
|
-
const C =
|
|
7568
|
+
const C = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, V = z.current || { lipsyncLang: "en" };
|
|
7567
7569
|
h.current.speakText(C, {
|
|
7568
|
-
lipsyncLang:
|
|
7570
|
+
lipsyncLang: V.lipsyncLang,
|
|
7569
7571
|
onSpeechEnd: () => {
|
|
7570
|
-
const
|
|
7572
|
+
const ne = v()?.questions?.length || 0;
|
|
7571
7573
|
c.current.onCustomAction({
|
|
7572
7574
|
type: "answerFeedbackComplete",
|
|
7573
7575
|
moduleIndex: r.current.currentModuleIndex,
|
|
7574
7576
|
lessonIndex: r.current.currentLessonIndex,
|
|
7575
7577
|
questionIndex: r.current.currentQuestionIndex,
|
|
7576
7578
|
isCorrect: !0,
|
|
7577
|
-
hasNextQuestion: r.current.currentQuestionIndex <
|
|
7579
|
+
hasNextQuestion: r.current.currentQuestionIndex < ne - 1,
|
|
7578
7580
|
score: r.current.score,
|
|
7579
7581
|
totalQuestions: r.current.totalQuestions
|
|
7580
7582
|
});
|
|
@@ -7588,18 +7590,18 @@ const lt = Re(({
|
|
|
7588
7590
|
h.current.setBodyMovement("idle");
|
|
7589
7591
|
}
|
|
7590
7592
|
h.current.setBodyMovement("gesturing");
|
|
7591
|
-
const C =
|
|
7593
|
+
const C = R.type === "code_test" ? `Your code didn't pass all the tests. ${R.explanation || "Try again!"}` : `Not quite right, but don't worry! ${R.explanation || ""} Let's move on to the next question.`, V = z.current || { lipsyncLang: "en" };
|
|
7592
7594
|
h.current.speakText(C, {
|
|
7593
|
-
lipsyncLang:
|
|
7595
|
+
lipsyncLang: V.lipsyncLang,
|
|
7594
7596
|
onSpeechEnd: () => {
|
|
7595
|
-
const
|
|
7597
|
+
const ne = v()?.questions?.length || 0;
|
|
7596
7598
|
c.current.onCustomAction({
|
|
7597
7599
|
type: "answerFeedbackComplete",
|
|
7598
7600
|
moduleIndex: r.current.currentModuleIndex,
|
|
7599
7601
|
lessonIndex: r.current.currentLessonIndex,
|
|
7600
7602
|
questionIndex: r.current.currentQuestionIndex,
|
|
7601
7603
|
isCorrect: !1,
|
|
7602
|
-
hasNextQuestion: r.current.currentQuestionIndex <
|
|
7604
|
+
hasNextQuestion: r.current.currentQuestionIndex < ne - 1,
|
|
7603
7605
|
score: r.current.score,
|
|
7604
7606
|
totalQuestions: r.current.totalQuestions
|
|
7605
7607
|
});
|
|
@@ -7607,26 +7609,26 @@ const lt = Re(({
|
|
|
7607
7609
|
});
|
|
7608
7610
|
}
|
|
7609
7611
|
else {
|
|
7610
|
-
const
|
|
7612
|
+
const V = v()?.questions?.length || 0;
|
|
7611
7613
|
c.current.onCustomAction({
|
|
7612
7614
|
type: "answerFeedbackComplete",
|
|
7613
7615
|
moduleIndex: r.current.currentModuleIndex,
|
|
7614
7616
|
lessonIndex: r.current.currentLessonIndex,
|
|
7615
7617
|
questionIndex: r.current.currentQuestionIndex,
|
|
7616
7618
|
isCorrect: w,
|
|
7617
|
-
hasNextQuestion: r.current.currentQuestionIndex <
|
|
7619
|
+
hasNextQuestion: r.current.currentQuestionIndex < V - 1,
|
|
7618
7620
|
score: r.current.score,
|
|
7619
7621
|
totalQuestions: r.current.totalQuestions,
|
|
7620
7622
|
avatarNotReady: !0
|
|
7621
7623
|
});
|
|
7622
7624
|
}
|
|
7623
|
-
}, [e.correct, e.incorrect,
|
|
7624
|
-
const
|
|
7625
|
+
}, [e.correct, e.incorrect, M, v, W]), Z = T((b) => {
|
|
7626
|
+
const R = M();
|
|
7625
7627
|
if (!b || typeof b != "object") {
|
|
7626
7628
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
7627
7629
|
return;
|
|
7628
7630
|
}
|
|
7629
|
-
if (
|
|
7631
|
+
if (R?.type !== "code_test") {
|
|
7630
7632
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
7631
7633
|
return;
|
|
7632
7634
|
}
|
|
@@ -7646,12 +7648,12 @@ const lt = Re(({
|
|
|
7646
7648
|
lessonIndex: r.current.currentLessonIndex,
|
|
7647
7649
|
questionIndex: r.current.currentQuestionIndex,
|
|
7648
7650
|
testResult: w,
|
|
7649
|
-
question:
|
|
7651
|
+
question: R
|
|
7650
7652
|
}), p.current && p.current(w);
|
|
7651
|
-
}, [
|
|
7653
|
+
}, [M, W]), le = T(() => {
|
|
7652
7654
|
if (r.current.currentQuestionIndex > 0) {
|
|
7653
7655
|
r.current.currentQuestionIndex -= 1;
|
|
7654
|
-
const b =
|
|
7656
|
+
const b = M();
|
|
7655
7657
|
b && c.current.onCustomAction({
|
|
7656
7658
|
type: "questionStart",
|
|
7657
7659
|
moduleIndex: r.current.currentModuleIndex,
|
|
@@ -7661,7 +7663,7 @@ const lt = Re(({
|
|
|
7661
7663
|
question: b,
|
|
7662
7664
|
score: r.current.score
|
|
7663
7665
|
});
|
|
7664
|
-
const
|
|
7666
|
+
const R = () => {
|
|
7665
7667
|
if (!h.current || !b) return;
|
|
7666
7668
|
h.current.setMood("happy"), h.current.setBodyMovement("idle");
|
|
7667
7669
|
const w = z.current || { lipsyncLang: "en" };
|
|
@@ -7672,17 +7674,17 @@ const lt = Re(({
|
|
|
7672
7674
|
});
|
|
7673
7675
|
};
|
|
7674
7676
|
if (h.current && h.current.isReady && b)
|
|
7675
|
-
|
|
7677
|
+
R();
|
|
7676
7678
|
else if (b) {
|
|
7677
7679
|
const w = setInterval(() => {
|
|
7678
|
-
h.current && h.current.isReady && (clearInterval(w),
|
|
7680
|
+
h.current && h.current.isReady && (clearInterval(w), R());
|
|
7679
7681
|
}, 100);
|
|
7680
7682
|
setTimeout(() => {
|
|
7681
7683
|
clearInterval(w);
|
|
7682
7684
|
}, 5e3);
|
|
7683
7685
|
}
|
|
7684
7686
|
}
|
|
7685
|
-
}, [
|
|
7687
|
+
}, [M]), se = T(() => {
|
|
7686
7688
|
const b = H.current || { modules: [] };
|
|
7687
7689
|
if (b.modules[r.current.currentModuleIndex], r.current.currentLessonIndex > 0)
|
|
7688
7690
|
r.current.currentLessonIndex -= 1, r.current.currentQuestionIndex = 0, r.current.lessonCompleted = !1, r.current.isQuestionMode = !1, r.current.isTeaching = !1, r.current.score = 0, r.current.totalQuestions = 0, c.current.onCustomAction({
|
|
@@ -7692,7 +7694,7 @@ const lt = Re(({
|
|
|
7692
7694
|
}), c.current.onLessonStart({
|
|
7693
7695
|
moduleIndex: r.current.currentModuleIndex,
|
|
7694
7696
|
lessonIndex: r.current.currentLessonIndex,
|
|
7695
|
-
lesson:
|
|
7697
|
+
lesson: v()
|
|
7696
7698
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7697
7699
|
else if (r.current.currentModuleIndex > 0) {
|
|
7698
7700
|
const C = b.modules[r.current.currentModuleIndex - 1];
|
|
@@ -7703,53 +7705,53 @@ const lt = Re(({
|
|
|
7703
7705
|
}), c.current.onLessonStart({
|
|
7704
7706
|
moduleIndex: r.current.currentModuleIndex,
|
|
7705
7707
|
lessonIndex: r.current.currentLessonIndex,
|
|
7706
|
-
lesson:
|
|
7708
|
+
lesson: v()
|
|
7707
7709
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7708
7710
|
}
|
|
7709
|
-
}, [
|
|
7711
|
+
}, [v]), ce = T(() => {
|
|
7710
7712
|
r.current.currentModuleIndex = 0, r.current.currentLessonIndex = 0, r.current.currentQuestionIndex = 0, r.current.isTeaching = !1, r.current.isQuestionMode = !1, r.current.lessonCompleted = !1, r.current.curriculumCompleted = !1, r.current.score = 0, r.current.totalQuestions = 0;
|
|
7711
|
-
}, []),
|
|
7713
|
+
}, []), Re = T((b) => {
|
|
7712
7714
|
console.log("Avatar is ready!", b);
|
|
7713
|
-
const
|
|
7715
|
+
const R = v(), w = R?.avatar_script || R?.body;
|
|
7714
7716
|
u && w && setTimeout(() => {
|
|
7715
7717
|
d.current && d.current();
|
|
7716
7718
|
}, 10);
|
|
7717
|
-
}, [u,
|
|
7718
|
-
|
|
7719
|
-
d.current =
|
|
7720
|
-
}),
|
|
7719
|
+
}, [u, v]);
|
|
7720
|
+
Ue(() => {
|
|
7721
|
+
d.current = O, g.current = Y, y.current = _, x.current = D, I.current = re, F.current = S, p.current = q;
|
|
7722
|
+
}), Le(a, () => ({
|
|
7721
7723
|
// Curriculum control methods
|
|
7722
|
-
startTeaching:
|
|
7724
|
+
startTeaching: O,
|
|
7723
7725
|
startQuestions: S,
|
|
7724
|
-
handleAnswerSelect:
|
|
7725
|
-
handleCodeTestResult:
|
|
7726
|
-
nextQuestion:
|
|
7727
|
-
previousQuestion:
|
|
7728
|
-
nextLesson:
|
|
7729
|
-
previousLesson:
|
|
7726
|
+
handleAnswerSelect: q,
|
|
7727
|
+
handleCodeTestResult: Z,
|
|
7728
|
+
nextQuestion: D,
|
|
7729
|
+
previousQuestion: le,
|
|
7730
|
+
nextLesson: Y,
|
|
7731
|
+
previousLesson: se,
|
|
7730
7732
|
completeLesson: _,
|
|
7731
|
-
completeCurriculum:
|
|
7732
|
-
resetCurriculum:
|
|
7733
|
+
completeCurriculum: re,
|
|
7734
|
+
resetCurriculum: ce,
|
|
7733
7735
|
getState: () => ({ ...r.current }),
|
|
7734
|
-
getCurrentQuestion: () =>
|
|
7735
|
-
getCurrentLesson: () =>
|
|
7736
|
+
getCurrentQuestion: () => M(),
|
|
7737
|
+
getCurrentLesson: () => v(),
|
|
7736
7738
|
// Direct access to avatar ref (always returns current value)
|
|
7737
7739
|
getAvatarRef: () => h.current,
|
|
7738
7740
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
7739
|
-
speakText: async (b,
|
|
7741
|
+
speakText: async (b, R = {}) => {
|
|
7740
7742
|
await h.current?.resumeAudioContext?.();
|
|
7741
7743
|
const w = z.current || { lipsyncLang: "en" };
|
|
7742
|
-
h.current?.speakText(b, { ...
|
|
7744
|
+
h.current?.speakText(b, { ...R, lipsyncLang: R.lipsyncLang || w.lipsyncLang });
|
|
7743
7745
|
},
|
|
7744
7746
|
resumeAudioContext: async () => {
|
|
7745
7747
|
if (h.current?.resumeAudioContext)
|
|
7746
7748
|
return await h.current.resumeAudioContext();
|
|
7747
7749
|
const b = h.current?.talkingHead;
|
|
7748
7750
|
if (b?.audioCtx) {
|
|
7749
|
-
const
|
|
7750
|
-
if (
|
|
7751
|
+
const R = b.audioCtx;
|
|
7752
|
+
if (R.state === "suspended" || R.state === "interrupted")
|
|
7751
7753
|
try {
|
|
7752
|
-
await
|
|
7754
|
+
await R.resume(), console.log("Audio context resumed via talkingHead");
|
|
7753
7755
|
} catch (w) {
|
|
7754
7756
|
console.warn("Failed to resume audio context:", w);
|
|
7755
7757
|
}
|
|
@@ -7761,7 +7763,7 @@ const lt = Re(({
|
|
|
7761
7763
|
resumeSpeaking: async () => await h.current?.resumeSpeaking(),
|
|
7762
7764
|
isPaused: () => h.current && typeof h.current.isPaused < "u" ? h.current.isPaused : !1,
|
|
7763
7765
|
setMood: (b) => h.current?.setMood(b),
|
|
7764
|
-
playAnimation: (b,
|
|
7766
|
+
playAnimation: (b, R) => h.current?.playAnimation(b, R),
|
|
7765
7767
|
setBodyMovement: (b) => h.current?.setBodyMovement(b),
|
|
7766
7768
|
setMovementIntensity: (b) => h.current?.setMovementIntensity(b),
|
|
7767
7769
|
playRandomDance: () => h.current?.playRandomDance(),
|
|
@@ -7772,10 +7774,10 @@ const lt = Re(({
|
|
|
7772
7774
|
lockAvatarPosition: () => h.current?.lockAvatarPosition(),
|
|
7773
7775
|
unlockAvatarPosition: () => h.current?.unlockAvatarPosition(),
|
|
7774
7776
|
// Custom action trigger
|
|
7775
|
-
triggerCustomAction: (b,
|
|
7777
|
+
triggerCustomAction: (b, R) => {
|
|
7776
7778
|
c.current.onCustomAction({
|
|
7777
7779
|
type: b,
|
|
7778
|
-
...
|
|
7780
|
+
...R,
|
|
7779
7781
|
state: { ...r.current }
|
|
7780
7782
|
});
|
|
7781
7783
|
},
|
|
@@ -7783,8 +7785,8 @@ const lt = Re(({
|
|
|
7783
7785
|
handleResize: () => h.current?.handleResize(),
|
|
7784
7786
|
// Avatar readiness check (always returns current value)
|
|
7785
7787
|
isAvatarReady: () => h.current?.isReady || !1
|
|
7786
|
-
}), [
|
|
7787
|
-
const
|
|
7788
|
+
}), [O, S, q, Z, D, Y, _, re, ce, M, v]);
|
|
7789
|
+
const K = z.current || {
|
|
7788
7790
|
avatarUrl: "/avatars/brunette.glb",
|
|
7789
7791
|
avatarBody: "F",
|
|
7790
7792
|
mood: "happy",
|
|
@@ -7797,23 +7799,23 @@ const lt = Re(({
|
|
|
7797
7799
|
showFullAvatar: !1,
|
|
7798
7800
|
animations: e
|
|
7799
7801
|
};
|
|
7800
|
-
return /* @__PURE__ */
|
|
7801
|
-
|
|
7802
|
+
return /* @__PURE__ */ ue("div", { style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ ue(
|
|
7803
|
+
Pe,
|
|
7802
7804
|
{
|
|
7803
7805
|
ref: h,
|
|
7804
|
-
avatarUrl:
|
|
7805
|
-
avatarBody:
|
|
7806
|
-
mood:
|
|
7807
|
-
ttsLang:
|
|
7808
|
-
ttsService:
|
|
7809
|
-
ttsVoice:
|
|
7810
|
-
ttsApiKey:
|
|
7811
|
-
bodyMovement:
|
|
7812
|
-
movementIntensity:
|
|
7813
|
-
showFullAvatar:
|
|
7806
|
+
avatarUrl: K.avatarUrl,
|
|
7807
|
+
avatarBody: K.avatarBody,
|
|
7808
|
+
mood: K.mood,
|
|
7809
|
+
ttsLang: K.ttsLang,
|
|
7810
|
+
ttsService: K.ttsService,
|
|
7811
|
+
ttsVoice: K.ttsVoice,
|
|
7812
|
+
ttsApiKey: K.ttsApiKey,
|
|
7813
|
+
bodyMovement: K.bodyMovement,
|
|
7814
|
+
movementIntensity: K.movementIntensity,
|
|
7815
|
+
showFullAvatar: K.showFullAvatar,
|
|
7814
7816
|
cameraView: "upper",
|
|
7815
|
-
animations:
|
|
7816
|
-
onReady:
|
|
7817
|
+
animations: K.animations,
|
|
7818
|
+
onReady: Re,
|
|
7817
7819
|
onLoading: () => {
|
|
7818
7820
|
},
|
|
7819
7821
|
onError: (b) => {
|
|
@@ -7822,8 +7824,8 @@ const lt = Re(({
|
|
|
7822
7824
|
}
|
|
7823
7825
|
) });
|
|
7824
7826
|
});
|
|
7825
|
-
|
|
7826
|
-
const
|
|
7827
|
+
ut.displayName = "CurriculumLearning";
|
|
7828
|
+
const Be = {
|
|
7827
7829
|
// Code-based dance animations (no FBX required)
|
|
7828
7830
|
dance: {
|
|
7829
7831
|
name: "dance",
|
|
@@ -7926,14 +7928,14 @@ const Fe = {
|
|
|
7926
7928
|
duration: 5e3,
|
|
7927
7929
|
description: "Excited, energetic movement"
|
|
7928
7930
|
}
|
|
7929
|
-
},
|
|
7931
|
+
}, Rt = (N) => Be[N] || null, It = (N) => Be.hasOwnProperty(N);
|
|
7930
7932
|
export {
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
|
|
7933
|
+
ut as CurriculumLearning,
|
|
7934
|
+
Pe as TalkingHeadAvatar,
|
|
7935
|
+
ht as TalkingHeadComponent,
|
|
7936
|
+
Be as animations,
|
|
7937
|
+
Ae as getActiveTTSConfig,
|
|
7938
|
+
Rt as getAnimation,
|
|
7939
|
+
vt as getVoiceOptions,
|
|
7940
|
+
It as hasAnimation
|
|
7939
7941
|
};
|