@sage-rsc/talking-head-react 1.0.58 → 1.0.59
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 +318 -313
- package/package.json +1 -1
- package/src/components/CurriculumLearning.jsx +5 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs as Te, jsx as he } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as ve, useRef as Z, useState as
|
|
2
|
+
import { forwardRef as ve, useRef as Z, useState as ce, useEffect as pe, useCallback as T, useImperativeHandle as Ie, useLayoutEffect as Oe } from "react";
|
|
3
3
|
import * as f from "three";
|
|
4
4
|
import { OrbitControls as Ne } from "three/addons/controls/OrbitControls.js";
|
|
5
5
|
import { GLTFLoader as Ue } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -521,10 +521,10 @@ class Qe {
|
|
|
521
521
|
for (let l = 0; l < o; l++) {
|
|
522
522
|
const u = l * s, a = Math.min(u + n, t.length), h = t.slice(u, a), r = this.calculateEnergy(h);
|
|
523
523
|
i.energy.push(r);
|
|
524
|
-
const
|
|
525
|
-
i.spectralCentroid.push(
|
|
526
|
-
const
|
|
527
|
-
i.zeroCrossingRate.push(
|
|
524
|
+
const c = this.calculateSpectralCentroid(h);
|
|
525
|
+
i.spectralCentroid.push(c);
|
|
526
|
+
const d = this.calculateZeroCrossingRate(h);
|
|
527
|
+
i.zeroCrossingRate.push(d);
|
|
528
528
|
const g = this.calculateMFCC(h);
|
|
529
529
|
i.mfcc.push(g);
|
|
530
530
|
}
|
|
@@ -606,8 +606,8 @@ class Qe {
|
|
|
606
606
|
for (let u = 0; u < e; u += n) {
|
|
607
607
|
let a = 1, h = 0;
|
|
608
608
|
for (let r = 0; r < n / 2; r++) {
|
|
609
|
-
const
|
|
610
|
-
i[(u + r) * 2] =
|
|
609
|
+
const c = i[(u + r) * 2], d = i[(u + r) * 2 + 1], g = i[(u + r + n / 2) * 2] * a - i[(u + r + n / 2) * 2 + 1] * h, y = i[(u + r + n / 2) * 2] * h + i[(u + r + n / 2) * 2 + 1] * a;
|
|
610
|
+
i[(u + r) * 2] = c + g, i[(u + r) * 2 + 1] = d + y, i[(u + r + n / 2) * 2] = c - g, i[(u + r + n / 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
|
}
|
|
@@ -703,15 +703,15 @@ class Qe {
|
|
|
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
|
-
const h = s[a], r = o[l],
|
|
706
|
+
const h = s[a], r = o[l], c = t.energy[Math.floor(h / 0.023)] || 0, d = this.calculateVisemeDuration(r, c);
|
|
707
707
|
n.push({
|
|
708
708
|
viseme: r,
|
|
709
709
|
startTime: u,
|
|
710
|
-
endTime: u +
|
|
711
|
-
duration:
|
|
712
|
-
intensity: Math.min(1,
|
|
710
|
+
endTime: u + d,
|
|
711
|
+
duration: d,
|
|
712
|
+
intensity: Math.min(1, c * 2)
|
|
713
713
|
// Map energy to viseme intensity
|
|
714
|
-
}), u +=
|
|
714
|
+
}), u += d, l++;
|
|
715
715
|
}
|
|
716
716
|
for (; l < o.length; ) {
|
|
717
717
|
const a = o[l], h = this.calculateVisemeDuration(a, 0.5);
|
|
@@ -1207,10 +1207,10 @@ class qe {
|
|
|
1207
1207
|
Object.keys(this.rules).forEach((e) => {
|
|
1208
1208
|
this.rules[e] = this.rules[e].map((i) => {
|
|
1209
1209
|
const n = i.indexOf("["), s = i.indexOf("]"), o = i.indexOf("="), l = i.substring(0, n), u = i.substring(n + 1, s), a = i.substring(s + 1, o), h = i.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
1210
|
-
let
|
|
1211
|
-
|
|
1212
|
-
const
|
|
1213
|
-
return
|
|
1210
|
+
let c = "";
|
|
1211
|
+
c += [...l].map((g) => t[g] || g).join("");
|
|
1212
|
+
const d = [...u];
|
|
1213
|
+
return d[0] = d[0].toLowerCase(), c += d.join(""), r.move = d.length, c += [...a].map((g) => t[g] || g).join(""), r.regex = new RegExp(c), h.length && h.split(" ").forEach((g) => {
|
|
1214
1214
|
r.visemes.push(g);
|
|
1215
1215
|
}), r;
|
|
1216
1216
|
});
|
|
@@ -1380,11 +1380,11 @@ class qe {
|
|
|
1380
1380
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(u.regex)) {
|
|
1381
1381
|
u.visemes.forEach((r) => {
|
|
1382
1382
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === r) {
|
|
1383
|
-
const
|
|
1384
|
-
e.durations[e.durations.length - 1] +=
|
|
1383
|
+
const c = 0.7 * (this.visemeDurations[r] || 1);
|
|
1384
|
+
e.durations[e.durations.length - 1] += c, i += c;
|
|
1385
1385
|
} else {
|
|
1386
|
-
const
|
|
1387
|
-
e.visemes.push(r), e.times.push(i), e.durations.push(
|
|
1386
|
+
const c = this.visemeDurations[r] || 1;
|
|
1387
|
+
e.visemes.push(r), e.times.push(i), e.durations.push(c), i += c;
|
|
1388
1388
|
}
|
|
1389
1389
|
}), e.i += u.move;
|
|
1390
1390
|
break;
|
|
@@ -1617,10 +1617,10 @@ class Ke {
|
|
|
1617
1617
|
Object.keys(this.rules).forEach((e) => {
|
|
1618
1618
|
this.rules[e] = this.rules[e].map((i) => {
|
|
1619
1619
|
const n = i.indexOf("["), s = i.indexOf("]"), o = i.indexOf("="), l = i.substring(0, n), u = i.substring(n + 1, s), a = i.substring(s + 1, o), h = i.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
1620
|
-
let
|
|
1621
|
-
|
|
1622
|
-
const
|
|
1623
|
-
return
|
|
1620
|
+
let c = "";
|
|
1621
|
+
c += [...l].map((g) => t[g] || g).join("");
|
|
1622
|
+
const d = [...u];
|
|
1623
|
+
return d[0] = d[0].toLowerCase(), c += d.join(""), r.move = d.length, c += [...a].map((g) => t[g] || g).join(""), r.regex = new RegExp(c), h.length && h.split(" ").forEach((g) => {
|
|
1624
1624
|
r.visemes.push(g);
|
|
1625
1625
|
}), r;
|
|
1626
1626
|
});
|
|
@@ -1735,13 +1735,13 @@ class Ke {
|
|
|
1735
1735
|
for (let u = 0; u < o.length; u++) {
|
|
1736
1736
|
const a = o[u];
|
|
1737
1737
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(a.regex)) {
|
|
1738
|
-
a.visemes.forEach((
|
|
1739
|
-
if (e.visemes.length && e.visemes[e.visemes.length - 1] ===
|
|
1740
|
-
const
|
|
1741
|
-
e.durations[e.durations.length - 1] +=
|
|
1738
|
+
a.visemes.forEach((c) => {
|
|
1739
|
+
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
1740
|
+
const d = 0.7 * (this.visemeDurations[c] || 1);
|
|
1741
|
+
e.durations[e.durations.length - 1] += d, i += d;
|
|
1742
1742
|
} else {
|
|
1743
|
-
const
|
|
1744
|
-
e.visemes.push(
|
|
1743
|
+
const d = this.visemeDurations[c] || 1;
|
|
1744
|
+
e.visemes.push(c), e.times.push(i), e.durations.push(d), i += d;
|
|
1745
1745
|
}
|
|
1746
1746
|
}), e.i += a.move, l = !0;
|
|
1747
1747
|
break;
|
|
@@ -2132,10 +2132,10 @@ class $e {
|
|
|
2132
2132
|
Object.keys(this.rules).forEach((e) => {
|
|
2133
2133
|
this.rules[e] = this.rules[e].map((i) => {
|
|
2134
2134
|
const n = i.indexOf("["), s = i.indexOf("]"), o = i.indexOf("="), l = i.substring(0, n), u = i.substring(n + 1, s), a = i.substring(s + 1, o), h = i.substring(o + 1), r = { regex: "", move: 0, visemes: [] };
|
|
2135
|
-
let
|
|
2136
|
-
|
|
2137
|
-
const
|
|
2138
|
-
return
|
|
2135
|
+
let c = "";
|
|
2136
|
+
c += [...l].map((g) => t[g] || g).join("");
|
|
2137
|
+
const d = [...u];
|
|
2138
|
+
return d[0] = d[0].toLowerCase(), c += d.join(""), r.move = d.length, c += [...a].map((g) => t[g] || g).join(""), r.regex = new RegExp(c, "i"), h.length && h.split(" ").forEach((g) => {
|
|
2139
2139
|
g && r.visemes.push(g);
|
|
2140
2140
|
}), r;
|
|
2141
2141
|
});
|
|
@@ -2270,13 +2270,13 @@ class $e {
|
|
|
2270
2270
|
for (let u = 0; u < o.length; u++) {
|
|
2271
2271
|
const a = o[u];
|
|
2272
2272
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(a.regex)) {
|
|
2273
|
-
a.visemes.forEach((
|
|
2274
|
-
if (e.visemes.length && e.visemes[e.visemes.length - 1] ===
|
|
2275
|
-
const
|
|
2276
|
-
e.durations[e.durations.length - 1] +=
|
|
2273
|
+
a.visemes.forEach((c) => {
|
|
2274
|
+
if (e.visemes.length && e.visemes[e.visemes.length - 1] === c) {
|
|
2275
|
+
const d = 0.7 * (this.visemeDurations[c] || 1);
|
|
2276
|
+
e.durations[e.durations.length - 1] += d, i += d;
|
|
2277
2277
|
} else {
|
|
2278
|
-
const
|
|
2279
|
-
e.visemes.push(
|
|
2278
|
+
const d = this.visemeDurations[c] || 1;
|
|
2279
|
+
e.visemes.push(c), e.times.push(i), e.durations.push(d), i += d;
|
|
2280
2280
|
}
|
|
2281
2281
|
}), e.i += a.move, l = !0;
|
|
2282
2282
|
break;
|
|
@@ -2629,7 +2629,7 @@ const ot = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
2629
2629
|
fr: et,
|
|
2630
2630
|
fi: it,
|
|
2631
2631
|
lt: ot
|
|
2632
|
-
},
|
|
2632
|
+
}, V = new f.Quaternion(), M = new f.Euler(), ae = new f.Vector3(), le = new f.Vector3(), Ce = new f.Box3();
|
|
2633
2633
|
new f.Matrix4();
|
|
2634
2634
|
new f.Matrix4();
|
|
2635
2635
|
new f.Vector3();
|
|
@@ -4201,15 +4201,15 @@ class Me {
|
|
|
4201
4201
|
let l = null, u = null;
|
|
4202
4202
|
for (const [a, h] of Object.entries(i))
|
|
4203
4203
|
if (s.morphTargetDictionary.hasOwnProperty(a)) {
|
|
4204
|
-
const r = s.morphTargetDictionary[a],
|
|
4205
|
-
l || (l = new f.Float32BufferAttribute(
|
|
4206
|
-
for (let g = 0; g <
|
|
4207
|
-
const y = l.getX(g) +
|
|
4204
|
+
const r = s.morphTargetDictionary[a], c = o.morphAttributes.position[r], d = o.morphAttributes.normal?.[r];
|
|
4205
|
+
l || (l = new f.Float32BufferAttribute(c.count * 3, 3), d && (u = new f.Float32BufferAttribute(c.count * 3, 3)));
|
|
4206
|
+
for (let g = 0; g < c.count; g++) {
|
|
4207
|
+
const y = l.getX(g) + c.getX(g) * h, x = l.getY(g) + c.getY(g) * h, I = l.getZ(g) + c.getZ(g) * h;
|
|
4208
4208
|
l.setXYZ(g, y, x, I);
|
|
4209
4209
|
}
|
|
4210
|
-
if (
|
|
4211
|
-
for (let g = 0; g <
|
|
4212
|
-
const y = u.getX(g) +
|
|
4210
|
+
if (d)
|
|
4211
|
+
for (let g = 0; g < c.count; g++) {
|
|
4212
|
+
const y = u.getX(g) + d.getX(g) * h, x = u.getY(g) + d.getY(g) * h, I = u.getZ(g) + d.getZ(g) * h;
|
|
4213
4213
|
u.setXYZ(g, y, x, I);
|
|
4214
4214
|
}
|
|
4215
4215
|
}
|
|
@@ -4275,8 +4275,8 @@ class Me {
|
|
|
4275
4275
|
h && ["fixed", "system", "systemd", "realtime", "base", "v", "value", "applied"].forEach((r) => {
|
|
4276
4276
|
l[a][r] = h[r];
|
|
4277
4277
|
}), this.morphs.forEach((r) => {
|
|
4278
|
-
const
|
|
4279
|
-
|
|
4278
|
+
const c = r.morphTargetDictionary[a];
|
|
4279
|
+
c !== void 0 && (l[a].ms.push(r.morphTargetInfluences), l[a].is.push(c), r.morphTargetInfluences[c] = l[a].applied);
|
|
4280
4280
|
});
|
|
4281
4281
|
}), this.mtAvatar = l, this.poseAvatar = { props: {} }, this.posePropNames.forEach((a) => {
|
|
4282
4282
|
const h = a.split("."), r = this.armature.getObjectByName(h[0]);
|
|
@@ -4376,7 +4376,7 @@ class Me {
|
|
|
4376
4376
|
if (e.x === 0 && e.y === 0 && e.z === 0) continue;
|
|
4377
4377
|
M.set(e.x, e.y, e.z);
|
|
4378
4378
|
const i = this.poseAvatar.props[t];
|
|
4379
|
-
i.isQuaternion ? (
|
|
4379
|
+
i.isQuaternion ? (V.setFromEuler(M), i.multiply(V)) : i.isVector3 && i.add(M);
|
|
4380
4380
|
}
|
|
4381
4381
|
}
|
|
4382
4382
|
/**
|
|
@@ -4975,10 +4975,10 @@ class Me {
|
|
|
4975
4975
|
if (l.alt.length > 1) {
|
|
4976
4976
|
const h = Math.random();
|
|
4977
4977
|
let r = 0;
|
|
4978
|
-
for (let
|
|
4979
|
-
let
|
|
4980
|
-
if (r +=
|
|
4981
|
-
a = l.alt[
|
|
4978
|
+
for (let c = 0; c < l.alt.length; c++) {
|
|
4979
|
+
let d = this.valueFn(l.alt[c].p);
|
|
4980
|
+
if (r += d === void 0 ? (1 - r) / (l.alt.length - 1 - c) : d, h < r) {
|
|
4981
|
+
a = l.alt[c];
|
|
4982
4982
|
break;
|
|
4983
4983
|
}
|
|
4984
4984
|
}
|
|
@@ -4998,8 +4998,8 @@ class Me {
|
|
|
4998
4998
|
}
|
|
4999
4999
|
s ? o.ts = o.ts.map((a) => u + a * i) : o.ts = o.ts.map((a) => this.animClock + u + a * i);
|
|
5000
5000
|
for (let [a, h] of Object.entries(l.vs)) {
|
|
5001
|
-
const r = this.getBaselineValue(a),
|
|
5002
|
-
a === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...
|
|
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) + n * this.gaussianRandom(...d) : typeof d == "boolean" ? d : d instanceof Object && d.constructor === Object ? Object.assign({}, d) : (r === void 0 ? 0 : r) + n * d));
|
|
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))
|
|
5005
5005
|
for (; o.vs[a].length <= o.ts.length; ) o.vs[a].push(o.vs[a][o.vs[a].length - 1]);
|
|
@@ -5086,20 +5086,20 @@ class Me {
|
|
|
5086
5086
|
const r = this.animQueue[i];
|
|
5087
5087
|
if (!(!r || !r.ts || !r.ts.length || this.animClock < r.ts[0])) {
|
|
5088
5088
|
for (n = r.ndx || 0, o = r.ts.length; n < o && !(this.animClock < r.ts[n]); n++)
|
|
5089
|
-
for (let [
|
|
5090
|
-
if (this.mtAvatar.hasOwnProperty(
|
|
5091
|
-
if (
|
|
5092
|
-
const g = this.mtAvatar[
|
|
5093
|
-
if (
|
|
5094
|
-
g.newvalue =
|
|
5089
|
+
for (let [c, d] of Object.entries(r.vs))
|
|
5090
|
+
if (this.mtAvatar.hasOwnProperty(c)) {
|
|
5091
|
+
if (d[n + 1] === null) continue;
|
|
5092
|
+
const g = this.mtAvatar[c];
|
|
5093
|
+
if (d[n] === null && (d[n] = g.value), n === o - 1)
|
|
5094
|
+
g.newvalue = d[n];
|
|
5095
5095
|
else {
|
|
5096
|
-
g.newvalue =
|
|
5096
|
+
g.newvalue = d[n + 1];
|
|
5097
5097
|
const y = r.ts[n + 1] - r.ts[n];
|
|
5098
5098
|
let x = 1;
|
|
5099
|
-
y > 1e-4 && (x = (this.animClock - r.ts[n]) / y), x < 1 && (g.easing && (x = g.easing(x)), g.newvalue = (1 - x) *
|
|
5099
|
+
y > 1e-4 && (x = (this.animClock - r.ts[n]) / y), x < 1 && (g.easing && (x = g.easing(x)), g.newvalue = (1 - x) * d[n] + 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
|
-
switch (
|
|
5102
|
+
switch (c) {
|
|
5103
5103
|
case "viseme_aa":
|
|
5104
5104
|
case "viseme_E":
|
|
5105
5105
|
case "viseme_I":
|
|
@@ -5108,11 +5108,11 @@ class Me {
|
|
|
5108
5108
|
g.newvalue *= 1 + l / 255 - 0.5;
|
|
5109
5109
|
}
|
|
5110
5110
|
g.needsUpdate = !0;
|
|
5111
|
-
} else
|
|
5111
|
+
} else c === "eyeContact" && d[n] !== null && u !== !1 ? u = !!d[n] : c === "headMove" && d[n] !== null && a !== !1 ? d[n] === 0 ? a = !1 : (Math.random() < d[n] && (a = !0), d[n] = null) : d[n] !== null && (h.push({ mt: c, val: d[n] }), d[n] = null);
|
|
5112
5112
|
n === 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[i] = this.animFactory(r.template, r.loop > 0 ? r.loop - 1 : r.loop, 1, 1 / o)) : (this.animQueue.splice(i--, 1), s--)) : r.ndx = n - 1;
|
|
5113
5113
|
}
|
|
5114
5114
|
}
|
|
5115
|
-
for (let r = 0,
|
|
5115
|
+
for (let r = 0, c = h.length; r < c; r++)
|
|
5116
5116
|
switch (n = h[r].val, h[r].mt) {
|
|
5117
5117
|
case "speak":
|
|
5118
5118
|
this.speakText(n);
|
|
@@ -5130,8 +5130,8 @@ class Me {
|
|
|
5130
5130
|
n && typeof n == "function" && n();
|
|
5131
5131
|
break;
|
|
5132
5132
|
case "moveto":
|
|
5133
|
-
Object.entries(n.props).forEach((
|
|
5134
|
-
|
|
5133
|
+
Object.entries(n.props).forEach((d) => {
|
|
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;
|
|
5137
5137
|
case "handLeft":
|
|
@@ -5180,13 +5180,13 @@ class Me {
|
|
|
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) && (i = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], n = this.mtAvatar[i], n.needsUpdate || Object.assign(n, { base: (this.mood.baseline[i] || 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), i = this.volumeHeadTarget - this.volumeHeadCurrent, n = Math.abs(i), n > 1e-4 && (o = n * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / n) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(i) * Math.min(n, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (
|
|
5183
|
+
})))), e > 2 * this.animFrameDur && (e = 2 * this.animFrameDur), (this.viewName !== "full" || this.isAvatarOnly) && (i = this.mtRandomized[Math.floor(Math.random() * this.mtRandomized.length)], n = this.mtAvatar[i], n.needsUpdate || Object.assign(n, { base: (this.mood.baseline[i] || 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), i = this.volumeHeadTarget - this.volumeHeadCurrent, n = Math.abs(i), n > 1e-4 && (o = n * (this.volumeHeadEasing(Math.min(1, this.volumeHeadVelocity * e / 1e3 / n) / 2 + 0.5) - 0.5), this.volumeHeadCurrent += Math.sign(i) * Math.min(n, o)), Math.abs(this.volumeHeadCurrent) > 1e-4 && (V.setFromAxisAngle(at, this.volumeHeadCurrent), this.objectNeck.quaternion.multiply(V)), Ce.setFromObject(this.armature), this.objectLeftToeBase.getWorldPosition(ae), ae.sub(this.armature.position), this.objectRightToeBase.getWorldPosition(le), le.sub(this.armature.position), this.objectHips.position.y -= Ce.min.y / 2, this.objectHips.position.x -= (ae.x + le.x) / 4, this.objectHips.position.z -= (ae.z + le.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) {
|
|
5187
5187
|
this.cameraClock += e, this.cameraClock > 1e3 && (this.cameraClock = 1e3);
|
|
5188
|
-
let r = new f.Spherical().setFromVector3(this.cameraStart),
|
|
5189
|
-
r.phi += this.easing(this.cameraClock / 1e3) * (
|
|
5188
|
+
let r = new f.Spherical().setFromVector3(this.cameraStart), c = new f.Spherical().setFromVector3(this.cameraEnd);
|
|
5189
|
+
r.phi += this.easing(this.cameraClock / 1e3) * (c.phi - r.phi), r.theta += this.easing(this.cameraClock / 1e3) * (c.theta - r.theta), r.radius += this.easing(this.cameraClock / 1e3) * (c.radius - r.radius), r.makeSafe(), this.camera.position.setFromSpherical(r), this.controlsStart.x !== this.controlsEnd.x ? this.controls.target.copy(this.controlsStart.lerp(this.controlsEnd, this.easing(this.cameraClock / 1e3))) : (r.setFromVector3(this.controlsStart), c.setFromVector3(this.controlsEnd), r.phi += this.easing(this.cameraClock / 1e3) * (c.phi - r.phi), r.theta += this.easing(this.cameraClock / 1e3) * (c.theta - r.theta), r.radius += this.easing(this.cameraClock / 1e3) * (c.radius - r.radius), r.makeSafe(), this.controls.target.setFromSpherical(r)), this.controls.update();
|
|
5190
5190
|
}
|
|
5191
5191
|
this.controls.autoRotate && this.controls.update(), this.stats && this.stats.end(), this.render();
|
|
5192
5192
|
}
|
|
@@ -5248,17 +5248,17 @@ class Me {
|
|
|
5248
5248
|
speakText(t, e = null, i = null, n = 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
|
-
let h = "", r = "",
|
|
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
5254
|
const I = x === y.length - 1, P = 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), i && (h += y[x]), P && (!n || n.every((v) => x < v[0] || x > v[1])) && (r += y[x]), (z || p || I) && (r.length && (r = this.lipsyncPreProcessText(r, a), r.length &&
|
|
5258
|
-
mark:
|
|
5257
|
+
if (p && !I && !H && y[x + 1].match(s) && (p = !1), i && (h += y[x]), P && (!n || n.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
|
+
mark: c,
|
|
5259
5259
|
word: r
|
|
5260
5260
|
})), h.length && (g.push({
|
|
5261
|
-
mark:
|
|
5261
|
+
mark: c,
|
|
5262
5262
|
template: { name: "subtitles" },
|
|
5263
5263
|
ts: [0],
|
|
5264
5264
|
vs: {
|
|
@@ -5268,24 +5268,24 @@ class Me {
|
|
|
5268
5268
|
const v = this.lipsyncWordsToVisemes(r, a);
|
|
5269
5269
|
if (v && v.visemes && v.visemes.length) {
|
|
5270
5270
|
const D = v.times[v.visemes.length - 1] + v.durations[v.visemes.length - 1];
|
|
5271
|
-
for (let
|
|
5271
|
+
for (let U = 0; U < v.visemes.length; U++)
|
|
5272
5272
|
g.push({
|
|
5273
|
-
mark:
|
|
5273
|
+
mark: c,
|
|
5274
5274
|
template: { name: "viseme" },
|
|
5275
|
-
ts: [(v.times[
|
|
5275
|
+
ts: [(v.times[U] - 0.6) / D, (v.times[U] + 0.5) / D, (v.times[U] + v.durations[U] + 0.5) / D],
|
|
5276
5276
|
vs: {
|
|
5277
|
-
["viseme_" + v.visemes[
|
|
5277
|
+
["viseme_" + v.visemes[U]]: [null, v.visemes[U] === "PP" || v.visemes[U] === "FF" ? 0.9 : 0.6, 0]
|
|
5278
5278
|
}
|
|
5279
5279
|
});
|
|
5280
5280
|
}
|
|
5281
|
-
r = "",
|
|
5281
|
+
r = "", c++;
|
|
5282
5282
|
}
|
|
5283
5283
|
if (p || I) {
|
|
5284
|
-
if (
|
|
5284
|
+
if (d.length || I && g.length) {
|
|
5285
5285
|
const v = {
|
|
5286
5286
|
anim: g
|
|
5287
5287
|
};
|
|
5288
|
-
i && (v.onSubtitles = i),
|
|
5288
|
+
i && (v.onSubtitles = i), 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
5291
|
let v = this.animEmojis[y[x]];
|
|
@@ -5379,18 +5379,18 @@ class Me {
|
|
|
5379
5379
|
subtitles: [" " + u]
|
|
5380
5380
|
}
|
|
5381
5381
|
}), !t.visemes)) {
|
|
5382
|
-
const r = this.lipsyncPreProcessText(u, n),
|
|
5383
|
-
if (
|
|
5384
|
-
const
|
|
5382
|
+
const r = this.lipsyncPreProcessText(u, n), c = this.lipsyncWordsToVisemes(r, n);
|
|
5383
|
+
if (c && c.visemes && c.visemes.length) {
|
|
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
|
-
if (h = Math.min(h,
|
|
5387
|
-
for (let x = 0; x <
|
|
5388
|
-
const I = a +
|
|
5386
|
+
if (h = Math.min(h, c.visemes.length * 200), d > 0)
|
|
5387
|
+
for (let x = 0; x < c.visemes.length; x++) {
|
|
5388
|
+
const I = a + c.times[x] / d * h, P = c.durations[x] / d * h;
|
|
5389
5389
|
o.push({
|
|
5390
5390
|
template: { name: "viseme" },
|
|
5391
5391
|
ts: [I - Math.min(60, 2 * P / 3), I + Math.min(25, P / 2), I + P + Math.min(60, P / 2)],
|
|
5392
5392
|
vs: {
|
|
5393
|
-
["viseme_" +
|
|
5393
|
+
["viseme_" + c.visemes[x]]: [null, c.visemes[x] === "PP" || c.visemes[x] === "FF" ? 0.9 : y, 0]
|
|
5394
5394
|
}
|
|
5395
5395
|
});
|
|
5396
5396
|
}
|
|
@@ -5473,23 +5473,23 @@ class Me {
|
|
|
5473
5473
|
const p = h.find((H) => H.name.includes(r) || H.lang === o);
|
|
5474
5474
|
p && (s.voice = p);
|
|
5475
5475
|
}
|
|
5476
|
-
const
|
|
5476
|
+
const c = n.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(n, g), x = this.lipsyncWordsToVisemes(y, g);
|
|
5477
5477
|
console.log("Browser TTS Lip-sync Debug:", {
|
|
5478
5478
|
text: n,
|
|
5479
5479
|
lipsyncLang: g,
|
|
5480
5480
|
processedText: y,
|
|
5481
5481
|
lipsyncData: x,
|
|
5482
5482
|
hasVisemes: x && x.visemes && x.visemes.length > 0,
|
|
5483
|
-
estimatedDuration:
|
|
5483
|
+
estimatedDuration: c
|
|
5484
5484
|
});
|
|
5485
5485
|
const I = [];
|
|
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], v = x.times[H] / p, D = x.durations[H] / p,
|
|
5489
|
+
const z = x.visemes[H], v = x.times[H] / p, D = x.durations[H] / p, U = v * c, _ = D * c;
|
|
5490
5490
|
I.push({
|
|
5491
5491
|
template: { name: "viseme" },
|
|
5492
|
-
ts: [
|
|
5492
|
+
ts: [U - Math.min(60, 2 * _ / 3), U + Math.min(25, _ / 2), U + _ + Math.min(60, _ / 2)],
|
|
5493
5493
|
vs: {
|
|
5494
5494
|
["viseme_" + z]: [null, z === "PP" || z === "FF" ? 0.9 : 0.6, 0]
|
|
5495
5495
|
}
|
|
@@ -5497,7 +5497,7 @@ class Me {
|
|
|
5497
5497
|
}
|
|
5498
5498
|
}
|
|
5499
5499
|
const P = [...t.anim, ...I];
|
|
5500
|
-
this.audioPlaylist.push({ anim: P, audio:
|
|
5500
|
+
this.audioPlaylist.push({ anim: P, 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
5503
|
console.error("Speech synthesis error:", p.error), i(p.error);
|
|
@@ -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((
|
|
5512
|
+
const e = t.text.map((c) => c.word).join(" "), i = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "21m00Tcm4TlvDq8ikWAM", n = {
|
|
5513
5513
|
text: e,
|
|
5514
5514
|
model_id: "eleven_monolingual_v1",
|
|
5515
5515
|
voice_settings: {
|
|
@@ -5539,18 +5539,18 @@ class Me {
|
|
|
5539
5539
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5540
5540
|
lipsyncLang: u
|
|
5541
5541
|
});
|
|
5542
|
-
const
|
|
5542
|
+
const c = this.lipsyncPreProcessText(e, u), d = this.lipsyncWordsToVisemes(c, u);
|
|
5543
5543
|
if (console.log("Lip-sync data:", {
|
|
5544
|
-
processedText:
|
|
5545
|
-
lipsyncData:
|
|
5546
|
-
hasVisemes:
|
|
5547
|
-
}),
|
|
5544
|
+
processedText: c,
|
|
5545
|
+
lipsyncData: d,
|
|
5546
|
+
hasVisemes: d && d.visemes && d.visemes.length > 0
|
|
5547
|
+
}), d && d.visemes && d.visemes.length > 0)
|
|
5548
5548
|
a = {
|
|
5549
|
-
visemes:
|
|
5549
|
+
visemes: d.visemes.map((g, y) => ({
|
|
5550
5550
|
viseme: g,
|
|
5551
|
-
startTime: y * l.duration /
|
|
5552
|
-
endTime: (y + 1) * l.duration /
|
|
5553
|
-
duration: l.duration /
|
|
5551
|
+
startTime: y * l.duration / d.visemes.length,
|
|
5552
|
+
endTime: (y + 1) * l.duration / d.visemes.length,
|
|
5553
|
+
duration: l.duration / d.visemes.length,
|
|
5554
5554
|
intensity: 0.7
|
|
5555
5555
|
})),
|
|
5556
5556
|
words: [],
|
|
@@ -5559,10 +5559,10 @@ class Me {
|
|
|
5559
5559
|
};
|
|
5560
5560
|
else
|
|
5561
5561
|
throw new Error("No visemes generated from text");
|
|
5562
|
-
} catch (
|
|
5563
|
-
console.error("Text-based lip-sync failed, using fallback:",
|
|
5564
|
-
const
|
|
5565
|
-
for (const y of
|
|
5562
|
+
} catch (c) {
|
|
5563
|
+
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5564
|
+
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5565
|
+
for (const y of d)
|
|
5566
5566
|
for (const x of y) {
|
|
5567
5567
|
let I = "aa";
|
|
5568
5568
|
"aeiou".includes(x) ? I = "aa" : "bp".includes(x) ? I = "PP" : "fv".includes(x) ? I = "FF" : "st".includes(x) ? I = "SS" : "dln".includes(x) ? I = "DD" : "kg".includes(x) ? I = "kk" : "rw".includes(x) && (I = "RR"), g.push(I);
|
|
@@ -5595,13 +5595,13 @@ class Me {
|
|
|
5595
5595
|
const h = [];
|
|
5596
5596
|
if (a.visemes && a.visemes.length > 0) {
|
|
5597
5597
|
console.log("ElevenLabs: Generating lip-sync animation from", a.visemes.length, "visemes");
|
|
5598
|
-
for (let
|
|
5599
|
-
const
|
|
5598
|
+
for (let c = 0; c < a.visemes.length; c++) {
|
|
5599
|
+
const d = a.visemes[c], g = d.startTime * 1e3, y = d.duration * 1e3, x = d.intensity;
|
|
5600
5600
|
h.push({
|
|
5601
5601
|
template: { name: "viseme" },
|
|
5602
5602
|
ts: [g - Math.min(60, 2 * y / 3), g + Math.min(25, y / 2), g + y + Math.min(60, y / 2)],
|
|
5603
5603
|
vs: {
|
|
5604
|
-
["viseme_" +
|
|
5604
|
+
["viseme_" + d.viseme]: [null, x, 0]
|
|
5605
5605
|
}
|
|
5606
5606
|
});
|
|
5607
5607
|
}
|
|
@@ -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((
|
|
5619
|
+
const e = t.text.map((c) => c.word).join(" "), i = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "aura-2-thalia-en", n = `${this.opt.ttsEndpoint}?model=${i}`, s = await fetch(n, {
|
|
5620
5620
|
method: "POST",
|
|
5621
5621
|
headers: {
|
|
5622
5622
|
Authorization: `Token ${this.opt.ttsApikey}`,
|
|
@@ -5637,18 +5637,18 @@ class Me {
|
|
|
5637
5637
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5638
5638
|
lipsyncLang: u
|
|
5639
5639
|
});
|
|
5640
|
-
const
|
|
5640
|
+
const c = this.lipsyncPreProcessText(e, u), d = this.lipsyncWordsToVisemes(c, u);
|
|
5641
5641
|
if (console.log("Lip-sync data:", {
|
|
5642
|
-
processedText:
|
|
5643
|
-
lipsyncData:
|
|
5644
|
-
hasVisemes:
|
|
5645
|
-
}),
|
|
5642
|
+
processedText: c,
|
|
5643
|
+
lipsyncData: d,
|
|
5644
|
+
hasVisemes: d && d.visemes && d.visemes.length > 0
|
|
5645
|
+
}), d && d.visemes && d.visemes.length > 0)
|
|
5646
5646
|
a = {
|
|
5647
|
-
visemes:
|
|
5647
|
+
visemes: d.visemes.map((g, y) => ({
|
|
5648
5648
|
viseme: g,
|
|
5649
|
-
startTime: y * l.duration /
|
|
5650
|
-
endTime: (y + 1) * l.duration /
|
|
5651
|
-
duration: l.duration /
|
|
5649
|
+
startTime: y * l.duration / d.visemes.length,
|
|
5650
|
+
endTime: (y + 1) * l.duration / d.visemes.length,
|
|
5651
|
+
duration: l.duration / d.visemes.length,
|
|
5652
5652
|
intensity: 0.7
|
|
5653
5653
|
})),
|
|
5654
5654
|
words: [],
|
|
@@ -5657,10 +5657,10 @@ class Me {
|
|
|
5657
5657
|
};
|
|
5658
5658
|
else
|
|
5659
5659
|
throw new Error("No visemes generated from text");
|
|
5660
|
-
} catch (
|
|
5661
|
-
console.error("Text-based lip-sync failed, using fallback:",
|
|
5662
|
-
const
|
|
5663
|
-
for (const y of
|
|
5660
|
+
} catch (c) {
|
|
5661
|
+
console.error("Text-based lip-sync failed, using fallback:", c);
|
|
5662
|
+
const d = e.toLowerCase().split(/\s+/), g = [];
|
|
5663
|
+
for (const y of d)
|
|
5664
5664
|
for (const x of y) {
|
|
5665
5665
|
let I = "aa";
|
|
5666
5666
|
"aeiou".includes(x) ? I = "aa" : "bp".includes(x) ? I = "PP" : "fv".includes(x) ? I = "FF" : "st".includes(x) ? I = "SS" : "dln".includes(x) ? I = "DD" : "kg".includes(x) ? I = "kk" : "rw".includes(x) && (I = "RR"), g.push(I);
|
|
@@ -5693,13 +5693,13 @@ class Me {
|
|
|
5693
5693
|
const h = [];
|
|
5694
5694
|
if (a.visemes && a.visemes.length > 0) {
|
|
5695
5695
|
console.log("Deepgram: Generating lip-sync animation from", a.visemes.length, "visemes");
|
|
5696
|
-
for (let
|
|
5697
|
-
const
|
|
5696
|
+
for (let c = 0; c < a.visemes.length; c++) {
|
|
5697
|
+
const d = a.visemes[c], g = d.startTime * 1e3, y = d.duration * 1e3, x = d.intensity;
|
|
5698
5698
|
h.push({
|
|
5699
5699
|
template: { name: "viseme" },
|
|
5700
5700
|
ts: [g - Math.min(60, 2 * y / 3), g + Math.min(25, y / 2), g + y + Math.min(60, y / 2)],
|
|
5701
5701
|
vs: {
|
|
5702
|
-
["viseme_" +
|
|
5702
|
+
["viseme_" + d.viseme]: [null, x, 0]
|
|
5703
5703
|
}
|
|
5704
5704
|
});
|
|
5705
5705
|
}
|
|
@@ -5746,12 +5746,12 @@ class Me {
|
|
|
5746
5746
|
});
|
|
5747
5747
|
const a = [];
|
|
5748
5748
|
for (let r = 0; r < u.visemes.length; r++) {
|
|
5749
|
-
const
|
|
5749
|
+
const c = u.visemes[r], d = c.startTime * 1e3, g = c.duration * 1e3, y = c.intensity;
|
|
5750
5750
|
a.push({
|
|
5751
5751
|
template: { name: "viseme" },
|
|
5752
|
-
ts: [
|
|
5752
|
+
ts: [d - Math.min(60, 2 * g / 3), d + Math.min(25, g / 2), d + g + Math.min(60, g / 2)],
|
|
5753
5753
|
vs: {
|
|
5754
|
-
["viseme_" +
|
|
5754
|
+
["viseme_" + c.viseme]: [null, y, 0]
|
|
5755
5755
|
}
|
|
5756
5756
|
});
|
|
5757
5757
|
}
|
|
@@ -5797,25 +5797,25 @@ class Me {
|
|
|
5797
5797
|
this.speakWithHands();
|
|
5798
5798
|
const u = [0];
|
|
5799
5799
|
let a = 0;
|
|
5800
|
-
t.text.forEach((
|
|
5801
|
-
if (
|
|
5800
|
+
t.text.forEach((c, d) => {
|
|
5801
|
+
if (d > 0) {
|
|
5802
5802
|
let g = u[u.length - 1];
|
|
5803
|
-
s.timepoints[a] && (g = s.timepoints[a].timeSeconds * 1e3, s.timepoints[a].markName === "" +
|
|
5803
|
+
s.timepoints[a] && (g = s.timepoints[a].timeSeconds * 1e3, s.timepoints[a].markName === "" + c.mark && a++), u.push(g);
|
|
5804
5804
|
}
|
|
5805
5805
|
});
|
|
5806
5806
|
const h = [{ mark: 0, time: 0 }];
|
|
5807
|
-
u.forEach((
|
|
5808
|
-
if (
|
|
5809
|
-
let g =
|
|
5810
|
-
h[
|
|
5807
|
+
u.forEach((c, d) => {
|
|
5808
|
+
if (d > 0) {
|
|
5809
|
+
let g = c - u[d - 1];
|
|
5810
|
+
h[d - 1].duration = g, h.push({ mark: d, time: c });
|
|
5811
5811
|
}
|
|
5812
5812
|
});
|
|
5813
5813
|
let r = 1e3 * l.duration;
|
|
5814
|
-
r > this.opt.ttsTrimEnd && (r = r - this.opt.ttsTrimEnd), h[h.length - 1].duration = r - h[h.length - 1].time, t.anim.forEach((
|
|
5815
|
-
const
|
|
5816
|
-
if (
|
|
5817
|
-
for (let g = 0; g <
|
|
5818
|
-
|
|
5814
|
+
r > this.opt.ttsTrimEnd && (r = r - this.opt.ttsTrimEnd), h[h.length - 1].duration = r - h[h.length - 1].time, t.anim.forEach((c) => {
|
|
5815
|
+
const d = h[c.mark];
|
|
5816
|
+
if (d)
|
|
5817
|
+
for (let g = 0; g < c.ts.length; g++)
|
|
5818
|
+
c.ts[g] = d.time + c.ts[g] * d.duration + this.opt.ttsTrimStart;
|
|
5819
5819
|
}), this.audioPlaylist.push({ anim: t.anim, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5820
5820
|
} else
|
|
5821
5821
|
this.startSpeaking(!0);
|
|
@@ -6034,15 +6034,15 @@ class Me {
|
|
|
6034
6034
|
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, u = this.lipsyncPreProcessText(n, 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
|
-
let
|
|
6037
|
+
let c = 0.6 + this.convertRange(r, [0, o], [0, 0.4]);
|
|
6038
6038
|
if (o = Math.min(o, a.visemes.length * 200), h > 0)
|
|
6039
|
-
for (let
|
|
6040
|
-
const g = e + s + a.times[
|
|
6039
|
+
for (let d = 0; d < a.visemes.length; d++) {
|
|
6040
|
+
const g = e + s + a.times[d] / h * o, y = a.durations[d] / h * o;
|
|
6041
6041
|
this.animQueue.push({
|
|
6042
6042
|
template: { name: "viseme" },
|
|
6043
6043
|
ts: [g - Math.min(60, 2 * y / 3), g + Math.min(25, y / 2), g + y + Math.min(60, y / 2)],
|
|
6044
6044
|
vs: {
|
|
6045
|
-
["viseme_" + a.visemes[
|
|
6045
|
+
["viseme_" + a.visemes[d]]: [null, a.visemes[d] === "PP" || a.visemes[d] === "FF" ? 0.9 : c, 0]
|
|
6046
6046
|
}
|
|
6047
6047
|
});
|
|
6048
6048
|
}
|
|
@@ -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), le.setFromMatrixPosition(this.objectRightEye.matrixWorld), ae.add(le).divideScalar(2),
|
|
6149
|
+
this.objectLeftEye.updateMatrixWorld(!0), this.objectRightEye.updateMatrixWorld(!0), ae.setFromMatrixPosition(this.objectLeftEye.matrixWorld), le.setFromMatrixPosition(this.objectRightEye.matrixWorld), ae.add(le).divideScalar(2), V.copy(this.armature.quaternion), V.multiply(this.poseTarget.props["Hips.quaternion"]), V.multiply(this.poseTarget.props["Spine.quaternion"]), V.multiply(this.poseTarget.props["Spine1.quaternion"]), V.multiply(this.poseTarget.props["Spine2.quaternion"]), V.multiply(this.poseTarget.props["Neck.quaternion"]), V.multiply(this.poseTarget.props["Head.quaternion"]);
|
|
6150
6150
|
const i = new f.Vector3().subVectors(e, ae).normalize(), n = Math.atan2(i.x, i.z), s = Math.asin(-i.y);
|
|
6151
6151
|
M.set(s, n, 0, "YXZ");
|
|
6152
|
-
const l = new f.Quaternion().setFromEuler(M), u = new f.Quaternion().copy(l).multiply(
|
|
6152
|
+
const l = new f.Quaternion().setFromEuler(M), u = new f.Quaternion().copy(l).multiply(V.clone().invert());
|
|
6153
6153
|
M.setFromQuaternion(u, "YXZ");
|
|
6154
|
-
let a = M.x / (40 / 24) + 0.2, h = M.y / (9 / 4), r = Math.min(0.6, Math.max(-0.3, a)),
|
|
6154
|
+
let a = M.x / (40 / 24) + 0.2, h = M.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);
|
|
@@ -6159,9 +6159,9 @@ class Me {
|
|
|
6159
6159
|
name: "lookat",
|
|
6160
6160
|
dt: [750, t],
|
|
6161
6161
|
vs: {
|
|
6162
|
-
bodyRotateX: [r +
|
|
6163
|
-
bodyRotateY: [
|
|
6164
|
-
eyesRotateX: [-3 *
|
|
6162
|
+
bodyRotateX: [r + d],
|
|
6163
|
+
bodyRotateY: [c + g],
|
|
6164
|
+
eyesRotateX: [-3 * d + 0.1],
|
|
6165
6165
|
eyesRotateY: [-5 * g],
|
|
6166
6166
|
browInnerUp: [[0, 0.7]],
|
|
6167
6167
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6186,8 +6186,8 @@ class Me {
|
|
|
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
6188
|
let u = (l.x + 1) / 2 * n.width + n.left, a = -(l.y - 1) / 2 * n.height + n.top;
|
|
6189
|
-
t === null && (t = u), e === null && (e = a),
|
|
6190
|
-
let h = M.x / (40 / 24), r = M.y / (9 / 4),
|
|
6189
|
+
t === null && (t = u), e === null && (e = a), V.copy(this.armature.quaternion), V.multiply(this.poseTarget.props["Hips.quaternion"]), V.multiply(this.poseTarget.props["Spine.quaternion"]), V.multiply(this.poseTarget.props["Spine1.quaternion"]), V.multiply(this.poseTarget.props["Spine2.quaternion"]), V.multiply(this.poseTarget.props["Neck.quaternion"]), V.multiply(this.poseTarget.props["Head.quaternion"]), M.setFromQuaternion(V);
|
|
6190
|
+
let h = M.x / (40 / 24), r = M.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
6192
|
let P = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6193
6193
|
if (i) {
|
|
@@ -6395,58 +6395,58 @@ class Me {
|
|
|
6395
6395
|
}
|
|
6396
6396
|
let a = !1;
|
|
6397
6397
|
try {
|
|
6398
|
-
const
|
|
6399
|
-
if (a =
|
|
6400
|
-
console.error(`FBX file not found at ${t}. Status: ${
|
|
6398
|
+
const c = await fetch(t, { method: "HEAD" });
|
|
6399
|
+
if (a = c.ok, !a) {
|
|
6400
|
+
console.error(`FBX file not found at ${t}. Status: ${c.status}`), console.error("Please check:"), console.error("1. File path is correct (note: path is case-sensitive)"), console.error("2. File exists in your public folder"), console.error("3. File is accessible (not blocked by server)");
|
|
6401
6401
|
return;
|
|
6402
6402
|
}
|
|
6403
|
-
} catch (
|
|
6404
|
-
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`,
|
|
6403
|
+
} catch (c) {
|
|
6404
|
+
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, c);
|
|
6405
6405
|
}
|
|
6406
6406
|
const h = new ke();
|
|
6407
6407
|
let r;
|
|
6408
6408
|
try {
|
|
6409
6409
|
r = await h.loadAsync(t, e);
|
|
6410
|
-
} catch (
|
|
6411
|
-
console.error(`Failed to load FBX animation from ${t}:`,
|
|
6412
|
-
message:
|
|
6410
|
+
} catch (c) {
|
|
6411
|
+
console.error(`Failed to load FBX animation from ${t}:`, c), console.error("Error details:", {
|
|
6412
|
+
message: c.message,
|
|
6413
6413
|
url: t,
|
|
6414
6414
|
suggestion: "Make sure the file is a valid FBX file and the path is correct"
|
|
6415
|
-
}),
|
|
6415
|
+
}), c.message && c.message.includes("version number") && (console.error("FBX Loader Error: Cannot find version number"), console.error("This error usually means:"), console.error("1. The file is not a valid FBX file (might be GLB, corrupted, or wrong format)"), console.error("2. The file might be corrupted"), console.error("3. The file path might be incorrect"), console.error("4. The server returned an HTML error page instead of the FBX file"), console.error("5. The file might not exist at that path"), console.error(""), console.error("Solution: Please verify:"), console.error(` - File exists at: ${t}`), console.error(" - File is a valid FBX binary file"), console.error(" - File path matches your public folder structure"), console.error(" - File is not corrupted"));
|
|
6416
6416
|
try {
|
|
6417
|
-
const
|
|
6417
|
+
const d = await fetch(t), g = d.headers.get("content-type"), y = await d.text();
|
|
6418
6418
|
console.error("Response details:", {
|
|
6419
|
-
status:
|
|
6419
|
+
status: d.status,
|
|
6420
6420
|
contentType: g,
|
|
6421
6421
|
firstBytes: y.substring(0, 100),
|
|
6422
6422
|
isHTML: y.trim().startsWith("<!DOCTYPE") || y.trim().startsWith("<html")
|
|
6423
6423
|
}), (y.trim().startsWith("<!DOCTYPE") || y.trim().startsWith("<html")) && console.error("The server returned an HTML page instead of an FBX file. The file path is likely incorrect.");
|
|
6424
|
-
} catch (
|
|
6425
|
-
console.error("Could not fetch file for debugging:",
|
|
6424
|
+
} catch (d) {
|
|
6425
|
+
console.error("Could not fetch file for debugging:", d);
|
|
6426
6426
|
}
|
|
6427
6427
|
return;
|
|
6428
6428
|
}
|
|
6429
6429
|
if (r && r.animations && r.animations[n]) {
|
|
6430
|
-
let
|
|
6431
|
-
const
|
|
6432
|
-
|
|
6430
|
+
let c = r.animations[n];
|
|
6431
|
+
const d = {};
|
|
6432
|
+
c.tracks.forEach((y) => {
|
|
6433
6433
|
y.name = y.name.replaceAll("mixamorig", "");
|
|
6434
6434
|
const x = y.name.split(".");
|
|
6435
6435
|
if (x[1] === "position") {
|
|
6436
6436
|
for (let I = 0; I < y.values.length; I++)
|
|
6437
6437
|
y.values[I] = y.values[I] * s;
|
|
6438
|
-
|
|
6439
|
-
} else x[1] === "quaternion" ?
|
|
6438
|
+
d[y.name] = new f.Vector3(y.values[0], y.values[1], y.values[2]);
|
|
6439
|
+
} else x[1] === "quaternion" ? d[y.name] = new f.Quaternion(y.values[0], y.values[1], y.values[2], y.values[3]) : x[1] === "rotation" && (d[x[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(y.values[0], y.values[1], y.values[2], "XYZ")).normalize());
|
|
6440
6440
|
});
|
|
6441
|
-
const g = { props:
|
|
6442
|
-
|
|
6441
|
+
const g = { props: d };
|
|
6442
|
+
d["Hips.position"] && (d["Hips.position"].y < 0.5 ? g.lying = !0 : g.standing = !0), this.animClips.push({
|
|
6443
6443
|
url: t + "-" + n,
|
|
6444
|
-
clip:
|
|
6444
|
+
clip: c,
|
|
6445
6445
|
pose: g
|
|
6446
6446
|
}), this.playAnimation(t, e, i, n, s);
|
|
6447
6447
|
} else {
|
|
6448
|
-
const
|
|
6449
|
-
console.error(
|
|
6448
|
+
const c = "Animation " + t + " (ndx=" + n + ") not found";
|
|
6449
|
+
console.error(c), r && r.animations ? console.error(`FBX file loaded but has ${r.animations.length} animation(s), requested index ${n}`) : console.error(r ? "FBX file loaded but contains no animations" : "FBX file failed to load or is invalid");
|
|
6450
6450
|
}
|
|
6451
6451
|
}
|
|
6452
6452
|
}
|
|
@@ -6484,10 +6484,10 @@ class Me {
|
|
|
6484
6484
|
if (u && u.animations && u.animations[n]) {
|
|
6485
6485
|
let a = u.animations[n];
|
|
6486
6486
|
const h = {};
|
|
6487
|
-
a.tracks.forEach((
|
|
6488
|
-
|
|
6489
|
-
const
|
|
6490
|
-
|
|
6487
|
+
a.tracks.forEach((c) => {
|
|
6488
|
+
c.name = c.name.replaceAll("mixamorig", "");
|
|
6489
|
+
const d = c.name.split(".");
|
|
6490
|
+
d[1] === "position" ? h[c.name] = new f.Vector3(c.values[0] * s, c.values[1] * s, c.values[2] * s) : d[1] === "quaternion" ? h[c.name] = new f.Quaternion(c.values[0], c.values[1], c.values[2], c.values[3]) : d[1] === "rotation" && (h[d[0] + ".quaternion"] = new f.Quaternion().setFromEuler(new f.Euler(c.values[0], c.values[1], c.values[2], "XYZ")).normalize());
|
|
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({
|
|
@@ -6532,13 +6532,13 @@ class Me {
|
|
|
6532
6532
|
if (l.gesture = !0, e && Number.isFinite(e)) {
|
|
6533
6533
|
const u = l.ts[0], h = l.ts[l.ts.length - 1] - u;
|
|
6534
6534
|
if (e * 1e3 - h > 0) {
|
|
6535
|
-
const
|
|
6536
|
-
for (let y = 1; y < l.ts.length; y++)
|
|
6537
|
-
const
|
|
6538
|
-
l.ts = l.ts.map((y, x, I) => x === 0 ? u : I[x - 1] +
|
|
6535
|
+
const c = [];
|
|
6536
|
+
for (let y = 1; y < l.ts.length; y++) c.push(l.ts[y] - l.ts[y - 1]);
|
|
6537
|
+
const d = o.template?.rescale || c.map((y) => y / h), g = e * 1e3 - h;
|
|
6538
|
+
l.ts = l.ts.map((y, x, I) => x === 0 ? u : I[x - 1] + c[x - 1] + d[x - 1] * g);
|
|
6539
6539
|
} else {
|
|
6540
|
-
const
|
|
6541
|
-
l.ts = l.ts.map((
|
|
6540
|
+
const c = e * 1e3 / h;
|
|
6541
|
+
l.ts = l.ts.map((d) => u + c * (d - u));
|
|
6542
6542
|
}
|
|
6543
6543
|
}
|
|
6544
6544
|
this.animQueue.push(l);
|
|
@@ -6568,12 +6568,12 @@ class Me {
|
|
|
6568
6568
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6569
6569
|
*/
|
|
6570
6570
|
ikSolve(t, e = null, i = !1, n = null) {
|
|
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(),
|
|
6572
|
-
|
|
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 && i && 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"));
|
|
6576
|
-
}),
|
|
6576
|
+
}), d.updateMatrixWorld(!0);
|
|
6577
6577
|
const x = t.iterations || 10;
|
|
6578
6578
|
if (e)
|
|
6579
6579
|
for (let I = 0; I < x; I++) {
|
|
@@ -6582,7 +6582,7 @@ class Me {
|
|
|
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
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(),
|
|
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(), V.setFromAxisAngle(r, v), z.quaternion.multiply(V), 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
|
|
@@ -6655,16 +6655,16 @@ function Le() {
|
|
|
6655
6655
|
};
|
|
6656
6656
|
}
|
|
6657
6657
|
function xt() {
|
|
6658
|
-
const
|
|
6659
|
-
return Object.entries(
|
|
6658
|
+
const N = Le(), t = [];
|
|
6659
|
+
return Object.entries(N.voices).forEach(([e, i]) => {
|
|
6660
6660
|
t.push({
|
|
6661
6661
|
value: i,
|
|
6662
|
-
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${
|
|
6662
|
+
label: `${e.charAt(0).toUpperCase() + e.slice(1)} (${N.service})`
|
|
6663
6663
|
});
|
|
6664
6664
|
}), t;
|
|
6665
6665
|
}
|
|
6666
6666
|
const Ee = ve(({
|
|
6667
|
-
avatarUrl:
|
|
6667
|
+
avatarUrl: N = "/avatars/brunette.glb",
|
|
6668
6668
|
avatarBody: t = "F",
|
|
6669
6669
|
mood: e = "neutral",
|
|
6670
6670
|
ttsLang: i = "en",
|
|
@@ -6677,15 +6677,15 @@ const Ee = ve(({
|
|
|
6677
6677
|
cameraView: h = "upper",
|
|
6678
6678
|
onReady: r = () => {
|
|
6679
6679
|
},
|
|
6680
|
-
onLoading:
|
|
6680
|
+
onLoading: c = () => {
|
|
6681
6681
|
},
|
|
6682
|
-
onError:
|
|
6682
|
+
onError: d = () => {
|
|
6683
6683
|
},
|
|
6684
6684
|
className: g = "",
|
|
6685
6685
|
style: y = {},
|
|
6686
6686
|
animations: x = {}
|
|
6687
6687
|
}, I) => {
|
|
6688
|
-
const P = Z(null), p = Z(null), H = Z(a), z = Z(null), [v, D] =
|
|
6688
|
+
const P = Z(null), p = Z(null), H = Z(a), z = Z(null), [v, D] = ce(!0), [U, _] = ce(null), [ne, S] = ce(!1), [W, G] = ce(!1);
|
|
6689
6689
|
pe(() => {
|
|
6690
6690
|
H.current = a;
|
|
6691
6691
|
}, [a]);
|
|
@@ -6714,7 +6714,7 @@ const Ee = ve(({
|
|
|
6714
6714
|
apiKey: o !== null ? o : E.apiKey
|
|
6715
6715
|
};
|
|
6716
6716
|
const ue = {
|
|
6717
|
-
url:
|
|
6717
|
+
url: N,
|
|
6718
6718
|
body: t,
|
|
6719
6719
|
avatarMood: e,
|
|
6720
6720
|
ttsLang: X === "browser" ? "en-US" : i,
|
|
@@ -6735,7 +6735,7 @@ const Ee = ve(({
|
|
|
6735
6735
|
if (D(!0), _(null), p.current = new Me(P.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(ue, (j) => {
|
|
6736
6736
|
if (j.lengthComputable) {
|
|
6737
6737
|
const B = Math.min(100, Math.round(j.loaded / j.total * 100));
|
|
6738
|
-
|
|
6738
|
+
c(B);
|
|
6739
6739
|
}
|
|
6740
6740
|
}), await new Promise((j) => {
|
|
6741
6741
|
const B = () => {
|
|
@@ -6756,9 +6756,9 @@ const Ee = ve(({
|
|
|
6756
6756
|
document.removeEventListener("visibilitychange", F);
|
|
6757
6757
|
};
|
|
6758
6758
|
} catch (A) {
|
|
6759
|
-
console.error("Error initializing TalkingHead:", A), _(A.message || "Failed to initialize avatar"), D(!1),
|
|
6759
|
+
console.error("Error initializing TalkingHead:", A), _(A.message || "Failed to initialize avatar"), D(!1), d(A);
|
|
6760
6760
|
}
|
|
6761
|
-
}, [
|
|
6761
|
+
}, [N, t, e, i, n, s, o, a, l, u, h]);
|
|
6762
6762
|
pe(() => (ge(), () => {
|
|
6763
6763
|
p.current && (p.current.stop(), p.current.dispose(), p.current = null);
|
|
6764
6764
|
}), [ge]), pe(() => {
|
|
@@ -6785,18 +6785,18 @@ const Ee = ve(({
|
|
|
6785
6785
|
}, []), J = T(async (A, F = {}) => {
|
|
6786
6786
|
if (p.current && ne)
|
|
6787
6787
|
try {
|
|
6788
|
-
z.current = { text: A, options: F },
|
|
6788
|
+
z.current = { text: A, options: F }, G(!1), await re();
|
|
6789
6789
|
const j = {
|
|
6790
6790
|
...F,
|
|
6791
6791
|
lipsyncLang: F.lipsyncLang || ue.lipsyncLang || "en"
|
|
6792
6792
|
};
|
|
6793
6793
|
if (F.onSpeechEnd && p.current) {
|
|
6794
6794
|
const B = p.current;
|
|
6795
|
-
let ee = null,
|
|
6795
|
+
let ee = null, de = 0;
|
|
6796
6796
|
const Ae = 1200;
|
|
6797
6797
|
let ye = !1;
|
|
6798
6798
|
ee = setInterval(() => {
|
|
6799
|
-
if (
|
|
6799
|
+
if (de++, de > Ae) {
|
|
6800
6800
|
if (ee && (clearInterval(ee), ee = null), !ye) {
|
|
6801
6801
|
ye = !0;
|
|
6802
6802
|
try {
|
|
@@ -6827,15 +6827,15 @@ const Ee = ve(({
|
|
|
6827
6827
|
console.error("Error speaking text:", j), _(j.message || "Failed to speak text");
|
|
6828
6828
|
}
|
|
6829
6829
|
}, [ne, re, ue.lipsyncLang]), b = T(() => {
|
|
6830
|
-
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), z.current = null,
|
|
6830
|
+
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), z.current = null, G(!1));
|
|
6831
6831
|
}, []), R = T(() => {
|
|
6832
6832
|
if (p.current && p.current.pauseSpeaking) {
|
|
6833
6833
|
const A = p.current, F = A.isSpeaking || A.audioPlaylist && A.audioPlaylist.length > 0 || A.speechQueue && A.speechQueue.length > 0;
|
|
6834
|
-
(F && z.current && z.current.text || F) && (p.current.pauseSpeaking(),
|
|
6834
|
+
(F && z.current && z.current.text || F) && (p.current.pauseSpeaking(), G(!0));
|
|
6835
6835
|
}
|
|
6836
6836
|
}, []), w = T(async () => {
|
|
6837
|
-
if (p.current &&
|
|
6838
|
-
if (
|
|
6837
|
+
if (p.current && W)
|
|
6838
|
+
if (G(!1), await re(), z.current && z.current.text) {
|
|
6839
6839
|
const A = z.current;
|
|
6840
6840
|
z.current = null;
|
|
6841
6841
|
const F = {
|
|
@@ -6845,9 +6845,9 @@ const Ee = ve(({
|
|
|
6845
6845
|
p.current.lipsync && Object.keys(p.current.lipsync).length > 0 && (p.current.setSlowdownRate && p.current.setSlowdownRate(1.05), p.current.speakText(A.text, F));
|
|
6846
6846
|
} else
|
|
6847
6847
|
z.current = null;
|
|
6848
|
-
}, [re,
|
|
6848
|
+
}, [re, W]), C = T((A) => {
|
|
6849
6849
|
p.current && p.current.setMood(A);
|
|
6850
|
-
}, []),
|
|
6850
|
+
}, []), O = T((A) => {
|
|
6851
6851
|
p.current && p.current.setSlowdownRate && p.current.setSlowdownRate(A);
|
|
6852
6852
|
}, []), te = T((A, F = !1) => {
|
|
6853
6853
|
if (p.current && p.current.playAnimation) {
|
|
@@ -6871,9 +6871,9 @@ const Ee = ve(({
|
|
|
6871
6871
|
else {
|
|
6872
6872
|
const B = [".fbx", ".glb", ".gltf"];
|
|
6873
6873
|
let ee = !1;
|
|
6874
|
-
for (const
|
|
6874
|
+
for (const de of B)
|
|
6875
6875
|
try {
|
|
6876
|
-
p.current.playAnimation(A +
|
|
6876
|
+
p.current.playAnimation(A + de, null, 10, 0, 0.01, F), ee = !0;
|
|
6877
6877
|
break;
|
|
6878
6878
|
} catch {
|
|
6879
6879
|
}
|
|
@@ -6881,8 +6881,8 @@ const Ee = ve(({
|
|
|
6881
6881
|
console.warn("Animation not found:", A);
|
|
6882
6882
|
try {
|
|
6883
6883
|
p.current.setBodyMovement("idle");
|
|
6884
|
-
} catch (
|
|
6885
|
-
console.warn("Fallback animation also failed:",
|
|
6884
|
+
} catch (de) {
|
|
6885
|
+
console.warn("Fallback animation also failed:", de);
|
|
6886
6886
|
}
|
|
6887
6887
|
}
|
|
6888
6888
|
}
|
|
@@ -6897,10 +6897,10 @@ const Ee = ve(({
|
|
|
6897
6897
|
resumeSpeaking: w,
|
|
6898
6898
|
resumeAudioContext: re,
|
|
6899
6899
|
setMood: C,
|
|
6900
|
-
setTimingAdjustment:
|
|
6900
|
+
setTimingAdjustment: O,
|
|
6901
6901
|
playAnimation: te,
|
|
6902
6902
|
isReady: ne,
|
|
6903
|
-
isPaused:
|
|
6903
|
+
isPaused: W,
|
|
6904
6904
|
talkingHead: p.current,
|
|
6905
6905
|
handleResize: ie,
|
|
6906
6906
|
setBodyMovement: (A) => {
|
|
@@ -6992,7 +6992,7 @@ const Ee = ve(({
|
|
|
6992
6992
|
fontSize: "18px",
|
|
6993
6993
|
zIndex: 10
|
|
6994
6994
|
}, children: "Loading avatar..." }),
|
|
6995
|
-
|
|
6995
|
+
U && /* @__PURE__ */ he("div", { className: "error-overlay", style: {
|
|
6996
6996
|
position: "absolute",
|
|
6997
6997
|
top: "50%",
|
|
6998
6998
|
left: "50%",
|
|
@@ -7003,14 +7003,14 @@ const Ee = ve(({
|
|
|
7003
7003
|
zIndex: 10,
|
|
7004
7004
|
padding: "20px",
|
|
7005
7005
|
borderRadius: "8px"
|
|
7006
|
-
}, children:
|
|
7006
|
+
}, children: U })
|
|
7007
7007
|
]
|
|
7008
7008
|
}
|
|
7009
7009
|
);
|
|
7010
7010
|
});
|
|
7011
7011
|
Ee.displayName = "TalkingHeadAvatar";
|
|
7012
7012
|
const rt = ve(({
|
|
7013
|
-
text:
|
|
7013
|
+
text: N = "Hello! I'm a talking avatar. How are you today?",
|
|
7014
7014
|
onLoading: t = () => {
|
|
7015
7015
|
},
|
|
7016
7016
|
onError: e = () => {
|
|
@@ -7021,7 +7021,7 @@ const rt = ve(({
|
|
|
7021
7021
|
style: s = {},
|
|
7022
7022
|
avatarConfig: o = {}
|
|
7023
7023
|
}, l) => {
|
|
7024
|
-
const u = Z(null), a = Z(null), [h, r] =
|
|
7024
|
+
const u = Z(null), a = Z(null), [h, r] = ce(!0), [c, d] = ce(null), [g, y] = ce(!1), x = Le(), I = o.ttsService || x.service, P = I === "browser" ? {
|
|
7025
7025
|
endpoint: "",
|
|
7026
7026
|
apiKey: null,
|
|
7027
7027
|
defaultVoice: "Google US English"
|
|
@@ -7054,37 +7054,37 @@ const rt = ve(({
|
|
|
7054
7054
|
}, z = T(async () => {
|
|
7055
7055
|
if (!(!u.current || a.current))
|
|
7056
7056
|
try {
|
|
7057
|
-
if (r(!0),
|
|
7058
|
-
if (
|
|
7059
|
-
const E = Math.min(100, Math.round(
|
|
7057
|
+
if (r(!0), d(null), a.current = new Me(u.current, H), await a.current.showAvatar(p, (G) => {
|
|
7058
|
+
if (G.lengthComputable) {
|
|
7059
|
+
const E = Math.min(100, Math.round(G.loaded / G.total * 100));
|
|
7060
7060
|
t(E);
|
|
7061
7061
|
}
|
|
7062
7062
|
}), a.current.morphs && a.current.morphs.length > 0) {
|
|
7063
|
-
const
|
|
7064
|
-
console.log("Available morph targets:", Object.keys(
|
|
7065
|
-
const E = Object.keys(
|
|
7063
|
+
const G = a.current.morphs[0].morphTargetDictionary;
|
|
7064
|
+
console.log("Available morph targets:", Object.keys(G));
|
|
7065
|
+
const E = Object.keys(G).filter((X) => X.startsWith("viseme_"));
|
|
7066
7066
|
console.log("Viseme morph targets found:", E), E.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
7067
|
}
|
|
7068
|
-
if (await new Promise((
|
|
7068
|
+
if (await new Promise((G) => {
|
|
7069
7069
|
const E = () => {
|
|
7070
|
-
a.current.lipsync && Object.keys(a.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(a.current.lipsync)),
|
|
7070
|
+
a.current.lipsync && Object.keys(a.current.lipsync).length > 0 ? (console.log("Lip-sync modules loaded:", Object.keys(a.current.lipsync)), G()) : (console.log("Waiting for lip-sync modules to load..."), setTimeout(E, 100));
|
|
7071
7071
|
};
|
|
7072
7072
|
E();
|
|
7073
7073
|
}), a.current && a.current.setShowFullAvatar)
|
|
7074
7074
|
try {
|
|
7075
7075
|
a.current.setShowFullAvatar(!0), console.log("Avatar initialized in full body mode");
|
|
7076
|
-
} catch (
|
|
7077
|
-
console.warn("Error setting full body mode on initialization:",
|
|
7076
|
+
} catch (G) {
|
|
7077
|
+
console.warn("Error setting full body mode on initialization:", G);
|
|
7078
7078
|
}
|
|
7079
7079
|
r(!1), y(!0), i(a.current);
|
|
7080
|
-
const
|
|
7080
|
+
const W = () => {
|
|
7081
7081
|
document.visibilityState === "visible" ? a.current?.start() : a.current?.stop();
|
|
7082
7082
|
};
|
|
7083
|
-
return document.addEventListener("visibilitychange",
|
|
7084
|
-
document.removeEventListener("visibilitychange",
|
|
7083
|
+
return document.addEventListener("visibilitychange", W), () => {
|
|
7084
|
+
document.removeEventListener("visibilitychange", W);
|
|
7085
7085
|
};
|
|
7086
7086
|
} catch (S) {
|
|
7087
|
-
console.error("Error initializing TalkingHead:", S),
|
|
7087
|
+
console.error("Error initializing TalkingHead:", S), d(S.message || "Failed to initialize avatar"), r(!1), e(S);
|
|
7088
7088
|
}
|
|
7089
7089
|
}, []);
|
|
7090
7090
|
pe(() => (z(), () => {
|
|
@@ -7096,18 +7096,18 @@ const rt = ve(({
|
|
|
7096
7096
|
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
7097
|
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
7098
|
}, 500));
|
|
7099
|
-
} catch (
|
|
7100
|
-
console.error("Error speaking text:",
|
|
7099
|
+
} catch (W) {
|
|
7100
|
+
console.error("Error speaking text:", W), d(W.message || "Failed to speak text");
|
|
7101
7101
|
}
|
|
7102
7102
|
else
|
|
7103
7103
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!a.current);
|
|
7104
7104
|
}, [g, p]), D = T(() => {
|
|
7105
7105
|
a.current && (a.current.stopSpeaking(), a.current.setSlowdownRate && (a.current.setSlowdownRate(1), console.log("Reset timing to normal")));
|
|
7106
|
-
}, []),
|
|
7106
|
+
}, []), U = T((S) => {
|
|
7107
7107
|
a.current && a.current.setMood(S);
|
|
7108
7108
|
}, []), _ = T((S) => {
|
|
7109
7109
|
a.current && a.current.setSlowdownRate && (a.current.setSlowdownRate(S), console.log("Timing adjustment set to:", S));
|
|
7110
|
-
}, []), ne = T((S,
|
|
7110
|
+
}, []), ne = T((S, W = !1) => {
|
|
7111
7111
|
if (a.current && a.current.playAnimation) {
|
|
7112
7112
|
if (a.current.setShowFullAvatar)
|
|
7113
7113
|
try {
|
|
@@ -7117,7 +7117,7 @@ const rt = ve(({
|
|
|
7117
7117
|
}
|
|
7118
7118
|
if (S.includes("."))
|
|
7119
7119
|
try {
|
|
7120
|
-
a.current.playAnimation(S, null, 10, 0, 0.01,
|
|
7120
|
+
a.current.playAnimation(S, null, 10, 0, 0.01, W), console.log("Playing animation:", S);
|
|
7121
7121
|
} catch (E) {
|
|
7122
7122
|
console.log(`Failed to play ${S}:`, E);
|
|
7123
7123
|
try {
|
|
@@ -7131,7 +7131,7 @@ const rt = ve(({
|
|
|
7131
7131
|
let X = !1;
|
|
7132
7132
|
for (const Y of E)
|
|
7133
7133
|
try {
|
|
7134
|
-
a.current.playAnimation(S + Y, null, 10, 0, 0.01,
|
|
7134
|
+
a.current.playAnimation(S + Y, null, 10, 0, 0.01, W), console.log("Playing animation:", S + Y), X = !0;
|
|
7135
7135
|
break;
|
|
7136
7136
|
} catch {
|
|
7137
7137
|
console.log(`Failed to play ${S}${Y}, trying next format...`);
|
|
@@ -7151,7 +7151,7 @@ const rt = ve(({
|
|
|
7151
7151
|
return Ie(l, () => ({
|
|
7152
7152
|
speakText: v,
|
|
7153
7153
|
stopSpeaking: D,
|
|
7154
|
-
setMood:
|
|
7154
|
+
setMood: U,
|
|
7155
7155
|
setTimingAdjustment: _,
|
|
7156
7156
|
playAnimation: ne,
|
|
7157
7157
|
isReady: g,
|
|
@@ -7160,8 +7160,8 @@ const rt = ve(({
|
|
|
7160
7160
|
if (a.current && a.current.setShowFullAvatar && a.current.setBodyMovement)
|
|
7161
7161
|
try {
|
|
7162
7162
|
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:",
|
|
7163
|
+
} catch (W) {
|
|
7164
|
+
console.warn("Error setting body movement:", W);
|
|
7165
7165
|
}
|
|
7166
7166
|
},
|
|
7167
7167
|
setMovementIntensity: (S) => a.current?.setMovementIntensity(S),
|
|
@@ -7177,8 +7177,8 @@ const rt = ve(({
|
|
|
7177
7177
|
if (a.current && a.current.setShowFullAvatar && a.current.playReaction)
|
|
7178
7178
|
try {
|
|
7179
7179
|
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:",
|
|
7180
|
+
} catch (W) {
|
|
7181
|
+
console.warn("Error playing reaction:", W);
|
|
7182
7182
|
}
|
|
7183
7183
|
},
|
|
7184
7184
|
playCelebration: () => {
|
|
@@ -7193,8 +7193,8 @@ const rt = ve(({
|
|
|
7193
7193
|
if (a.current && a.current.setShowFullAvatar)
|
|
7194
7194
|
try {
|
|
7195
7195
|
a.current.setShowFullAvatar(S), console.log("Show full avatar set to:", S);
|
|
7196
|
-
} catch (
|
|
7197
|
-
console.warn("Error setting showFullAvatar:",
|
|
7196
|
+
} catch (W) {
|
|
7197
|
+
console.warn("Error setting showFullAvatar:", W);
|
|
7198
7198
|
}
|
|
7199
7199
|
},
|
|
7200
7200
|
lockAvatarPosition: () => {
|
|
@@ -7235,7 +7235,7 @@ const rt = ve(({
|
|
|
7235
7235
|
fontSize: "18px",
|
|
7236
7236
|
zIndex: 10
|
|
7237
7237
|
}, children: "Loading avatar..." }),
|
|
7238
|
-
|
|
7238
|
+
c && /* @__PURE__ */ he("div", { className: "error-overlay", style: {
|
|
7239
7239
|
position: "absolute",
|
|
7240
7240
|
top: "50%",
|
|
7241
7241
|
left: "50%",
|
|
@@ -7246,12 +7246,12 @@ const rt = ve(({
|
|
|
7246
7246
|
zIndex: 10,
|
|
7247
7247
|
padding: "20px",
|
|
7248
7248
|
borderRadius: "8px"
|
|
7249
|
-
}, children:
|
|
7249
|
+
}, children: c })
|
|
7250
7250
|
] });
|
|
7251
7251
|
});
|
|
7252
7252
|
rt.displayName = "TalkingHeadComponent";
|
|
7253
7253
|
const lt = ve(({
|
|
7254
|
-
curriculumData:
|
|
7254
|
+
curriculumData: N = null,
|
|
7255
7255
|
avatarConfig: t = {},
|
|
7256
7256
|
animations: e = {},
|
|
7257
7257
|
onLessonStart: i = () => {
|
|
@@ -7276,13 +7276,13 @@ const lt = ve(({
|
|
|
7276
7276
|
curriculumCompleted: !1,
|
|
7277
7277
|
score: 0,
|
|
7278
7278
|
totalQuestions: 0
|
|
7279
|
-
}),
|
|
7279
|
+
}), c = Z({
|
|
7280
7280
|
onLessonStart: i,
|
|
7281
7281
|
onLessonComplete: n,
|
|
7282
7282
|
onQuestionAnswer: s,
|
|
7283
7283
|
onCurriculumComplete: o,
|
|
7284
7284
|
onCustomAction: l
|
|
7285
|
-
}),
|
|
7285
|
+
}), d = Z(null), g = Z(null), y = Z(null), x = Z(null), I = Z(null), P = Z(null), p = Z(null), H = Z(N?.curriculum || {
|
|
7286
7286
|
title: "Default Curriculum",
|
|
7287
7287
|
description: "No curriculum data provided",
|
|
7288
7288
|
language: "en",
|
|
@@ -7302,7 +7302,7 @@ const lt = ve(({
|
|
|
7302
7302
|
lipsyncLang: "en"
|
|
7303
7303
|
});
|
|
7304
7304
|
pe(() => {
|
|
7305
|
-
|
|
7305
|
+
c.current = {
|
|
7306
7306
|
onLessonStart: i,
|
|
7307
7307
|
onLessonComplete: n,
|
|
7308
7308
|
onQuestionAnswer: s,
|
|
@@ -7310,7 +7310,7 @@ const lt = ve(({
|
|
|
7310
7310
|
onCustomAction: l
|
|
7311
7311
|
};
|
|
7312
7312
|
}, [i, n, s, o, l]), pe(() => {
|
|
7313
|
-
H.current =
|
|
7313
|
+
H.current = N?.curriculum || {
|
|
7314
7314
|
title: "Default Curriculum",
|
|
7315
7315
|
description: "No curriculum data provided",
|
|
7316
7316
|
language: "en",
|
|
@@ -7329,18 +7329,23 @@ const lt = ve(({
|
|
|
7329
7329
|
animations: e,
|
|
7330
7330
|
lipsyncLang: "en"
|
|
7331
7331
|
};
|
|
7332
|
-
}, [
|
|
7333
|
-
const v = T(() => (H.current || { modules: [] }).modules[r.current.currentModuleIndex]?.lessons[r.current.currentLessonIndex], []), D = T(() => v()?.questions[r.current.currentQuestionIndex], [v]),
|
|
7332
|
+
}, [N, t, e]);
|
|
7333
|
+
const v = T(() => (H.current || { modules: [] }).modules[r.current.currentModuleIndex]?.lessons[r.current.currentLessonIndex], []), D = T(() => v()?.questions[r.current.currentQuestionIndex], [v]), U = 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
7334
|
r.current.lessonCompleted = !0, r.current.isQuestionMode = !1;
|
|
7335
7335
|
const b = r.current.totalQuestions > 0 ? Math.round(r.current.score / r.current.totalQuestions * 100) : 100;
|
|
7336
7336
|
let R = "Congratulations! You've completed this lesson";
|
|
7337
|
-
if (r.current.totalQuestions > 0
|
|
7337
|
+
if (r.current.totalQuestions > 0) {
|
|
7338
|
+
const w = r.current.score === 1 ? "one" : r.current.score, C = r.current.totalQuestions === 1 ? "one" : r.current.totalQuestions, O = b === 50 ? "fifty" : `${b}`;
|
|
7339
|
+
R += ` You got ${w} correct out of ${C} question${r.current.totalQuestions === 1 ? "" : "s"}, which is ${O} percent. `;
|
|
7340
|
+
} else
|
|
7341
|
+
R += "! ";
|
|
7342
|
+
if (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
7343
|
moduleIndex: r.current.currentModuleIndex,
|
|
7339
7344
|
lessonIndex: r.current.currentLessonIndex,
|
|
7340
7345
|
score: r.current.score,
|
|
7341
7346
|
totalQuestions: r.current.totalQuestions,
|
|
7342
7347
|
percentage: b
|
|
7343
|
-
}),
|
|
7348
|
+
}), c.current.onCustomAction({
|
|
7344
7349
|
type: "lessonComplete",
|
|
7345
7350
|
moduleIndex: r.current.currentModuleIndex,
|
|
7346
7351
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7354,11 +7359,11 @@ const lt = ve(({
|
|
|
7354
7359
|
} catch {
|
|
7355
7360
|
h.current.playCelebration();
|
|
7356
7361
|
}
|
|
7357
|
-
const w = H.current || { modules: [] }, C = w.modules[r.current.currentModuleIndex],
|
|
7362
|
+
const w = H.current || { modules: [] }, C = w.modules[r.current.currentModuleIndex], O = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, te = r.current.currentModuleIndex < (w.modules?.length || 0) - 1, ie = O || te, A = z.current || { lipsyncLang: "en" };
|
|
7358
7363
|
h.current.speakText(R, {
|
|
7359
7364
|
lipsyncLang: A.lipsyncLang,
|
|
7360
7365
|
onSpeechEnd: () => {
|
|
7361
|
-
|
|
7366
|
+
c.current.onCustomAction({
|
|
7362
7367
|
type: "lessonCompleteFeedbackDone",
|
|
7363
7368
|
moduleIndex: r.current.currentModuleIndex,
|
|
7364
7369
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7373,7 +7378,7 @@ const lt = ve(({
|
|
|
7373
7378
|
}, [e.lessonComplete]), ne = T(() => {
|
|
7374
7379
|
r.current.curriculumCompleted = !0;
|
|
7375
7380
|
const b = H.current || { modules: [] };
|
|
7376
|
-
if (
|
|
7381
|
+
if (c.current.onCurriculumComplete({
|
|
7377
7382
|
modules: b.modules.length,
|
|
7378
7383
|
totalLessons: b.modules.reduce((R, w) => R + w.lessons.length, 0)
|
|
7379
7384
|
}), h.current) {
|
|
@@ -7390,7 +7395,7 @@ const lt = ve(({
|
|
|
7390
7395
|
const b = v();
|
|
7391
7396
|
r.current.isQuestionMode = !0, r.current.currentQuestionIndex = 0, r.current.totalQuestions = b?.questions?.length || 0, r.current.score = 0;
|
|
7392
7397
|
const R = D();
|
|
7393
|
-
R &&
|
|
7398
|
+
R && c.current.onCustomAction({
|
|
7394
7399
|
type: "questionStart",
|
|
7395
7400
|
moduleIndex: r.current.currentModuleIndex,
|
|
7396
7401
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7404,8 +7409,8 @@ const lt = ve(({
|
|
|
7404
7409
|
if (h.current.setMood("happy"), e.questionStart)
|
|
7405
7410
|
try {
|
|
7406
7411
|
h.current.playAnimation(e.questionStart, !0);
|
|
7407
|
-
} catch (
|
|
7408
|
-
console.warn("Failed to play questionStart animation:",
|
|
7412
|
+
} catch (O) {
|
|
7413
|
+
console.warn("Failed to play questionStart animation:", O);
|
|
7409
7414
|
}
|
|
7410
7415
|
const C = z.current || { lipsyncLang: "en" };
|
|
7411
7416
|
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 });
|
|
@@ -7423,12 +7428,12 @@ const lt = ve(({
|
|
|
7423
7428
|
clearInterval(C);
|
|
7424
7429
|
}, 5e3);
|
|
7425
7430
|
}
|
|
7426
|
-
}, [e.questionStart, v, D]),
|
|
7431
|
+
}, [e.questionStart, v, D]), W = T(() => {
|
|
7427
7432
|
const b = v();
|
|
7428
7433
|
if (r.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
|
|
7429
7434
|
h.current && h.current.stopSpeaking && h.current.stopSpeaking(), r.current.currentQuestionIndex += 1;
|
|
7430
7435
|
const R = D();
|
|
7431
|
-
R &&
|
|
7436
|
+
R && c.current.onCustomAction({
|
|
7432
7437
|
type: "nextQuestion",
|
|
7433
7438
|
moduleIndex: r.current.currentModuleIndex,
|
|
7434
7439
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7442,8 +7447,8 @@ const lt = ve(({
|
|
|
7442
7447
|
if (h.current.setMood("happy"), h.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7443
7448
|
try {
|
|
7444
7449
|
h.current.playAnimation(e.nextQuestion, !0);
|
|
7445
|
-
} catch (
|
|
7446
|
-
console.warn("Failed to play nextQuestion animation:",
|
|
7450
|
+
} catch (O) {
|
|
7451
|
+
console.warn("Failed to play nextQuestion animation:", O);
|
|
7447
7452
|
}
|
|
7448
7453
|
const C = z.current || { lipsyncLang: "en" };
|
|
7449
7454
|
R.type === "code_test" ? h.current.speakText(`Great! Now let's move on to your next coding challenge: ${R.question}`, {
|
|
@@ -7467,37 +7472,37 @@ const lt = ve(({
|
|
|
7467
7472
|
}, 5e3);
|
|
7468
7473
|
}
|
|
7469
7474
|
} else
|
|
7470
|
-
|
|
7475
|
+
c.current.onCustomAction({
|
|
7471
7476
|
type: "allQuestionsComplete",
|
|
7472
7477
|
moduleIndex: r.current.currentModuleIndex,
|
|
7473
7478
|
lessonIndex: r.current.currentLessonIndex,
|
|
7474
7479
|
totalQuestions: r.current.totalQuestions,
|
|
7475
7480
|
score: r.current.score
|
|
7476
7481
|
});
|
|
7477
|
-
}, [e.nextQuestion, v, D]),
|
|
7482
|
+
}, [e.nextQuestion, v, D]), G = T(() => {
|
|
7478
7483
|
const b = H.current || { modules: [] }, R = b.modules[r.current.currentModuleIndex];
|
|
7479
7484
|
if (r.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7480
7485
|
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],
|
|
7482
|
-
|
|
7486
|
+
const C = b.modules[r.current.currentModuleIndex], O = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, te = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, ie = O || te;
|
|
7487
|
+
c.current.onCustomAction({
|
|
7483
7488
|
type: "lessonStart",
|
|
7484
7489
|
moduleIndex: r.current.currentModuleIndex,
|
|
7485
7490
|
lessonIndex: r.current.currentLessonIndex,
|
|
7486
7491
|
hasNextLesson: ie
|
|
7487
|
-
}),
|
|
7492
|
+
}), c.current.onLessonStart({
|
|
7488
7493
|
moduleIndex: r.current.currentModuleIndex,
|
|
7489
7494
|
lessonIndex: r.current.currentLessonIndex,
|
|
7490
7495
|
lesson: v()
|
|
7491
7496
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7492
7497
|
} else if (r.current.currentModuleIndex < (b.modules?.length || 0) - 1) {
|
|
7493
7498
|
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
|
|
7495
|
-
|
|
7499
|
+
const O = b.modules[r.current.currentModuleIndex], te = r.current.currentLessonIndex < (O?.lessons?.length || 0) - 1, ie = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, A = te || ie;
|
|
7500
|
+
c.current.onCustomAction({
|
|
7496
7501
|
type: "lessonStart",
|
|
7497
7502
|
moduleIndex: r.current.currentModuleIndex,
|
|
7498
7503
|
lessonIndex: r.current.currentLessonIndex,
|
|
7499
7504
|
hasNextLesson: A
|
|
7500
|
-
}),
|
|
7505
|
+
}), c.current.onLessonStart({
|
|
7501
7506
|
moduleIndex: r.current.currentModuleIndex,
|
|
7502
7507
|
lessonIndex: r.current.currentLessonIndex,
|
|
7503
7508
|
lesson: v()
|
|
@@ -7508,8 +7513,8 @@ const lt = ve(({
|
|
|
7508
7513
|
const b = v();
|
|
7509
7514
|
let R = null;
|
|
7510
7515
|
if (b?.avatar_script && b?.body) {
|
|
7511
|
-
const w = b.avatar_script.trim(), C = b.body.trim(),
|
|
7512
|
-
R = `${w}${
|
|
7516
|
+
const w = b.avatar_script.trim(), C = b.body.trim(), O = w.match(/[.!?]$/) ? " " : ". ";
|
|
7517
|
+
R = `${w}${O}${C}`;
|
|
7513
7518
|
} else
|
|
7514
7519
|
R = b?.avatar_script || b?.body || null;
|
|
7515
7520
|
if (h.current && h.current.isReady && R) {
|
|
@@ -7518,16 +7523,16 @@ const lt = ve(({
|
|
|
7518
7523
|
if (e.teaching)
|
|
7519
7524
|
try {
|
|
7520
7525
|
h.current.playAnimation(e.teaching, !0), w = !0;
|
|
7521
|
-
} catch (
|
|
7522
|
-
console.warn("Failed to play teaching animation:",
|
|
7526
|
+
} catch (O) {
|
|
7527
|
+
console.warn("Failed to play teaching animation:", O);
|
|
7523
7528
|
}
|
|
7524
7529
|
w || h.current.setBodyMovement("gesturing");
|
|
7525
7530
|
const C = z.current || { lipsyncLang: "en" };
|
|
7526
|
-
|
|
7531
|
+
c.current.onLessonStart({
|
|
7527
7532
|
moduleIndex: r.current.currentModuleIndex,
|
|
7528
7533
|
lessonIndex: r.current.currentLessonIndex,
|
|
7529
7534
|
lesson: b
|
|
7530
|
-
}),
|
|
7535
|
+
}), c.current.onCustomAction({
|
|
7531
7536
|
type: "teachingStart",
|
|
7532
7537
|
moduleIndex: r.current.currentModuleIndex,
|
|
7533
7538
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7535,7 +7540,7 @@ const lt = ve(({
|
|
|
7535
7540
|
}), h.current.speakText(R, {
|
|
7536
7541
|
lipsyncLang: C.lipsyncLang,
|
|
7537
7542
|
onSpeechEnd: () => {
|
|
7538
|
-
r.current.isTeaching = !1,
|
|
7543
|
+
r.current.isTeaching = !1, c.current.onCustomAction({
|
|
7539
7544
|
type: "teachingComplete",
|
|
7540
7545
|
moduleIndex: r.current.currentModuleIndex,
|
|
7541
7546
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7546,8 +7551,8 @@ const lt = ve(({
|
|
|
7546
7551
|
});
|
|
7547
7552
|
}
|
|
7548
7553
|
}, [e.teaching, v]), X = T((b) => {
|
|
7549
|
-
const R = D(), w =
|
|
7550
|
-
if (w && (r.current.score += 1),
|
|
7554
|
+
const R = D(), w = U(b, R);
|
|
7555
|
+
if (w && (r.current.score += 1), c.current.onQuestionAnswer({
|
|
7551
7556
|
moduleIndex: r.current.currentModuleIndex,
|
|
7552
7557
|
lessonIndex: r.current.currentLessonIndex,
|
|
7553
7558
|
questionIndex: r.current.currentQuestionIndex,
|
|
@@ -7563,12 +7568,12 @@ const lt = ve(({
|
|
|
7563
7568
|
h.current.setBodyMovement("happy");
|
|
7564
7569
|
}
|
|
7565
7570
|
h.current.setBodyMovement("gesturing");
|
|
7566
|
-
const C = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`,
|
|
7571
|
+
const C = R.type === "code_test" ? `Great job! Your code passed all the tests! ${R.explanation || ""}` : `Excellent! That's correct! ${R.explanation || ""}`, O = z.current || { lipsyncLang: "en" };
|
|
7567
7572
|
h.current.speakText(C, {
|
|
7568
|
-
lipsyncLang:
|
|
7573
|
+
lipsyncLang: O.lipsyncLang,
|
|
7569
7574
|
onSpeechEnd: () => {
|
|
7570
7575
|
const ie = v()?.questions?.length || 0;
|
|
7571
|
-
|
|
7576
|
+
c.current.onCustomAction({
|
|
7572
7577
|
type: "answerFeedbackComplete",
|
|
7573
7578
|
moduleIndex: r.current.currentModuleIndex,
|
|
7574
7579
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7588,12 +7593,12 @@ const lt = ve(({
|
|
|
7588
7593
|
h.current.setBodyMovement("idle");
|
|
7589
7594
|
}
|
|
7590
7595
|
h.current.setBodyMovement("gesturing");
|
|
7591
|
-
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.`,
|
|
7596
|
+
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.`, O = z.current || { lipsyncLang: "en" };
|
|
7592
7597
|
h.current.speakText(C, {
|
|
7593
|
-
lipsyncLang:
|
|
7598
|
+
lipsyncLang: O.lipsyncLang,
|
|
7594
7599
|
onSpeechEnd: () => {
|
|
7595
7600
|
const ie = v()?.questions?.length || 0;
|
|
7596
|
-
|
|
7601
|
+
c.current.onCustomAction({
|
|
7597
7602
|
type: "answerFeedbackComplete",
|
|
7598
7603
|
moduleIndex: r.current.currentModuleIndex,
|
|
7599
7604
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7607,20 +7612,20 @@ const lt = ve(({
|
|
|
7607
7612
|
});
|
|
7608
7613
|
}
|
|
7609
7614
|
else {
|
|
7610
|
-
const
|
|
7611
|
-
|
|
7615
|
+
const O = v()?.questions?.length || 0;
|
|
7616
|
+
c.current.onCustomAction({
|
|
7612
7617
|
type: "answerFeedbackComplete",
|
|
7613
7618
|
moduleIndex: r.current.currentModuleIndex,
|
|
7614
7619
|
lessonIndex: r.current.currentLessonIndex,
|
|
7615
7620
|
questionIndex: r.current.currentQuestionIndex,
|
|
7616
7621
|
isCorrect: w,
|
|
7617
|
-
hasNextQuestion: r.current.currentQuestionIndex <
|
|
7622
|
+
hasNextQuestion: r.current.currentQuestionIndex < O - 1,
|
|
7618
7623
|
score: r.current.score,
|
|
7619
7624
|
totalQuestions: r.current.totalQuestions,
|
|
7620
7625
|
avatarNotReady: !0
|
|
7621
7626
|
});
|
|
7622
7627
|
}
|
|
7623
|
-
}, [e.correct, e.incorrect, D, v,
|
|
7628
|
+
}, [e.correct, e.incorrect, D, v, U]), Y = T((b) => {
|
|
7624
7629
|
const R = D();
|
|
7625
7630
|
if (!b || typeof b != "object") {
|
|
7626
7631
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
@@ -7640,7 +7645,7 @@ const lt = ve(({
|
|
|
7640
7645
|
passedCount: b.passedCount || 0,
|
|
7641
7646
|
failedCount: b.failedCount || 0
|
|
7642
7647
|
};
|
|
7643
|
-
|
|
7648
|
+
c.current.onCustomAction({
|
|
7644
7649
|
type: "codeTestSubmitted",
|
|
7645
7650
|
moduleIndex: r.current.currentModuleIndex,
|
|
7646
7651
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7648,11 +7653,11 @@ const lt = ve(({
|
|
|
7648
7653
|
testResult: w,
|
|
7649
7654
|
question: R
|
|
7650
7655
|
}), p.current && p.current(w);
|
|
7651
|
-
}, [D,
|
|
7656
|
+
}, [D, U]), ue = T(() => {
|
|
7652
7657
|
if (r.current.currentQuestionIndex > 0) {
|
|
7653
7658
|
r.current.currentQuestionIndex -= 1;
|
|
7654
7659
|
const b = D();
|
|
7655
|
-
b &&
|
|
7660
|
+
b && c.current.onCustomAction({
|
|
7656
7661
|
type: "questionStart",
|
|
7657
7662
|
moduleIndex: r.current.currentModuleIndex,
|
|
7658
7663
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7685,22 +7690,22 @@ const lt = ve(({
|
|
|
7685
7690
|
}, [D]), Re = T(() => {
|
|
7686
7691
|
const b = H.current || { modules: [] };
|
|
7687
7692
|
if (b.modules[r.current.currentModuleIndex], r.current.currentLessonIndex > 0)
|
|
7688
|
-
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,
|
|
7693
|
+
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({
|
|
7689
7694
|
type: "lessonStart",
|
|
7690
7695
|
moduleIndex: r.current.currentModuleIndex,
|
|
7691
7696
|
lessonIndex: r.current.currentLessonIndex
|
|
7692
|
-
}),
|
|
7697
|
+
}), c.current.onLessonStart({
|
|
7693
7698
|
moduleIndex: r.current.currentModuleIndex,
|
|
7694
7699
|
lessonIndex: r.current.currentLessonIndex,
|
|
7695
7700
|
lesson: v()
|
|
7696
7701
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7697
7702
|
else if (r.current.currentModuleIndex > 0) {
|
|
7698
7703
|
const C = b.modules[r.current.currentModuleIndex - 1];
|
|
7699
|
-
r.current.currentModuleIndex -= 1, r.current.currentLessonIndex = (C?.lessons?.length || 1) - 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,
|
|
7704
|
+
r.current.currentModuleIndex -= 1, r.current.currentLessonIndex = (C?.lessons?.length || 1) - 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({
|
|
7700
7705
|
type: "lessonStart",
|
|
7701
7706
|
moduleIndex: r.current.currentModuleIndex,
|
|
7702
7707
|
lessonIndex: r.current.currentLessonIndex
|
|
7703
|
-
}),
|
|
7708
|
+
}), c.current.onLessonStart({
|
|
7704
7709
|
moduleIndex: r.current.currentModuleIndex,
|
|
7705
7710
|
lessonIndex: r.current.currentLessonIndex,
|
|
7706
7711
|
lesson: v()
|
|
@@ -7712,20 +7717,20 @@ const lt = ve(({
|
|
|
7712
7717
|
console.log("Avatar is ready!", b);
|
|
7713
7718
|
const R = v(), w = R?.avatar_script || R?.body;
|
|
7714
7719
|
u && w && setTimeout(() => {
|
|
7715
|
-
|
|
7720
|
+
d.current && d.current();
|
|
7716
7721
|
}, 10);
|
|
7717
7722
|
}, [u, v]);
|
|
7718
7723
|
Oe(() => {
|
|
7719
|
-
|
|
7724
|
+
d.current = E, g.current = G, y.current = _, x.current = W, I.current = ne, P.current = S, p.current = X;
|
|
7720
7725
|
}), Ie(a, () => ({
|
|
7721
7726
|
// Curriculum control methods
|
|
7722
7727
|
startTeaching: E,
|
|
7723
7728
|
startQuestions: S,
|
|
7724
7729
|
handleAnswerSelect: X,
|
|
7725
7730
|
handleCodeTestResult: Y,
|
|
7726
|
-
nextQuestion:
|
|
7731
|
+
nextQuestion: W,
|
|
7727
7732
|
previousQuestion: ue,
|
|
7728
|
-
nextLesson:
|
|
7733
|
+
nextLesson: G,
|
|
7729
7734
|
previousLesson: Re,
|
|
7730
7735
|
completeLesson: _,
|
|
7731
7736
|
completeCurriculum: ne,
|
|
@@ -7773,7 +7778,7 @@ const lt = ve(({
|
|
|
7773
7778
|
unlockAvatarPosition: () => h.current?.unlockAvatarPosition(),
|
|
7774
7779
|
// Custom action trigger
|
|
7775
7780
|
triggerCustomAction: (b, R) => {
|
|
7776
|
-
|
|
7781
|
+
c.current.onCustomAction({
|
|
7777
7782
|
type: b,
|
|
7778
7783
|
...R,
|
|
7779
7784
|
state: { ...r.current }
|
|
@@ -7783,7 +7788,7 @@ const lt = ve(({
|
|
|
7783
7788
|
handleResize: () => h.current?.handleResize(),
|
|
7784
7789
|
// Avatar readiness check (always returns current value)
|
|
7785
7790
|
isAvatarReady: () => h.current?.isReady || !1
|
|
7786
|
-
}), [E, S, X, Y,
|
|
7791
|
+
}), [E, S, X, Y, W, G, _, ne, ge, D, v]);
|
|
7787
7792
|
const J = z.current || {
|
|
7788
7793
|
avatarUrl: "/avatars/brunette.glb",
|
|
7789
7794
|
avatarBody: "F",
|
|
@@ -7926,7 +7931,7 @@ const Fe = {
|
|
|
7926
7931
|
duration: 5e3,
|
|
7927
7932
|
description: "Excited, energetic movement"
|
|
7928
7933
|
}
|
|
7929
|
-
}, bt = (
|
|
7934
|
+
}, bt = (N) => Fe[N] || null, Rt = (N) => Fe.hasOwnProperty(N);
|
|
7930
7935
|
export {
|
|
7931
7936
|
lt as CurriculumLearning,
|
|
7932
7937
|
Ee as TalkingHeadAvatar,
|