@sage-rsc/talking-head-react 1.0.58 → 1.0.60
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 +321 -321
- package/package.json +1 -1
- package/src/components/CurriculumLearning.jsx +3 -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
|
|
2
|
+
import { forwardRef as Re, 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;
|
|
@@ -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]);
|
|
@@ -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":
|
|
@@ -5185,8 +5185,8 @@ class Me {
|
|
|
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,48 +5248,48 @@ 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((
|
|
5258
|
-
mark:
|
|
5257
|
+
if (p && !I && !H && y[x + 1].match(s) && (p = !1), i && (h += y[x]), P && (!n || n.every((R) => x < R[0] || x > R[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: {
|
|
5265
5265
|
subtitles: [h]
|
|
5266
5266
|
}
|
|
5267
5267
|
}), h = ""), r.length)) {
|
|
5268
|
-
const
|
|
5269
|
-
if (
|
|
5270
|
-
const D =
|
|
5271
|
-
for (let N = 0; N <
|
|
5268
|
+
const R = this.lipsyncWordsToVisemes(r, a);
|
|
5269
|
+
if (R && R.visemes && R.visemes.length) {
|
|
5270
|
+
const D = R.times[R.visemes.length - 1] + R.durations[R.visemes.length - 1];
|
|
5271
|
+
for (let N = 0; N < R.visemes.length; N++)
|
|
5272
5272
|
g.push({
|
|
5273
|
-
mark:
|
|
5273
|
+
mark: c,
|
|
5274
5274
|
template: { name: "viseme" },
|
|
5275
|
-
ts: [(
|
|
5275
|
+
ts: [(R.times[N] - 0.6) / D, (R.times[N] + 0.5) / D, (R.times[N] + R.durations[N] + 0.5) / D],
|
|
5276
5276
|
vs: {
|
|
5277
|
-
["viseme_" +
|
|
5277
|
+
["viseme_" + R.visemes[N]]: [null, R.visemes[N] === "PP" || R.visemes[N] === "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 (
|
|
5285
|
-
const
|
|
5284
|
+
if (d.length || I && g.length) {
|
|
5285
|
+
const R = {
|
|
5286
5286
|
anim: g
|
|
5287
5287
|
};
|
|
5288
|
-
i && (
|
|
5288
|
+
i && (R.onSubtitles = i), d.length && !e.avatarMute && (R.text = d, e.avatarMood && (R.mood = e.avatarMood), e.ttsLang && (R.lang = e.ttsLang), e.ttsVoice && (R.voice = e.ttsVoice), e.ttsRate && (R.rate = e.ttsRate), e.ttsVoice && (R.pitch = e.ttsPitch), e.ttsVolume && (R.volume = e.ttsVolume)), this.speechQueue.push(R), d = [], r = "", c = 0, g = [];
|
|
5289
5289
|
}
|
|
5290
5290
|
if (H) {
|
|
5291
|
-
let
|
|
5292
|
-
|
|
5291
|
+
let R = this.animEmojis[y[x]];
|
|
5292
|
+
R && R.link && (R = this.animEmojis[R.link]), R && this.speechQueue.push({ emoji: R });
|
|
5293
5293
|
}
|
|
5294
5294
|
this.speechQueue.push({ break: 100 });
|
|
5295
5295
|
}
|
|
@@ -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,20 +5473,20 @@ 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],
|
|
5489
|
+
const z = x.visemes[H], R = x.times[H] / p, D = x.durations[H] / p, N = R * c, _ = D * c;
|
|
5490
5490
|
I.push({
|
|
5491
5491
|
template: { name: "viseme" },
|
|
5492
5492
|
ts: [N - Math.min(60, 2 * _ / 3), N + Math.min(25, _ / 2), N + _ + Math.min(60, _ / 2)],
|
|
@@ -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
|
}
|
|
@@ -6151,7 +6151,7 @@ class Me {
|
|
|
6151
6151
|
M.set(s, n, 0, "YXZ");
|
|
6152
6152
|
const l = new f.Quaternion().setFromEuler(M), u = new f.Quaternion().copy(l).multiply(W.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]],
|
|
@@ -6187,11 +6187,11 @@ class Me {
|
|
|
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
6189
|
t === null && (t = u), e === null && (e = a), W.copy(this.armature.quaternion), W.multiply(this.poseTarget.props["Hips.quaternion"]), W.multiply(this.poseTarget.props["Spine.quaternion"]), W.multiply(this.poseTarget.props["Spine1.quaternion"]), W.multiply(this.poseTarget.props["Spine2.quaternion"]), W.multiply(this.poseTarget.props["Neck.quaternion"]), W.multiply(this.poseTarget.props["Head.quaternion"]), M.setFromQuaternion(W);
|
|
6190
|
-
let h = M.x / (40 / 24), r = M.y / (9 / 4),
|
|
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) {
|
|
6194
|
-
let H = this.animQueue.findIndex((
|
|
6194
|
+
let H = this.animQueue.findIndex((R) => R.template.name === "lookat");
|
|
6195
6195
|
H !== -1 && this.animQueue.splice(H, 1);
|
|
6196
6196
|
const z = {
|
|
6197
6197
|
name: "lookat",
|
|
@@ -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++) {
|
|
@@ -6581,8 +6581,8 @@ class Me {
|
|
|
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 R = s.dot(l);
|
|
6585
|
+
R > 1 ? R = 1 : R < -1 && (R = -1), R = Math.acos(R), !(R < 1e-5) && (y[p].minAngle !== void 0 && R < y[p].minAngle && (R = y[p].minAngle), y[p].maxAngle !== void 0 && R > y[p].maxAngle && (R = y[p].maxAngle), r.crossVectors(l, s), r.normalize(), W.setFromAxisAngle(r, R), z.quaternion.multiply(W), 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
|
|
@@ -6663,7 +6663,7 @@ function xt() {
|
|
|
6663
6663
|
});
|
|
6664
6664
|
}), t;
|
|
6665
6665
|
}
|
|
6666
|
-
const Ee =
|
|
6666
|
+
const Ee = Re(({
|
|
6667
6667
|
avatarUrl: O = "/avatars/brunette.glb",
|
|
6668
6668
|
avatarBody: t = "F",
|
|
6669
6669
|
mood: e = "neutral",
|
|
@@ -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), [
|
|
6688
|
+
const P = Z(null), p = Z(null), H = Z(a), z = Z(null), [R, D] = ce(!0), [N, _] = ce(null), [ne, S] = ce(!1), [U, V] = ce(!1);
|
|
6689
6689
|
pe(() => {
|
|
6690
6690
|
H.current = a;
|
|
6691
6691
|
}, [a]);
|
|
@@ -6723,7 +6723,7 @@ const Ee = ve(({
|
|
|
6723
6723
|
showFullAvatar: a,
|
|
6724
6724
|
bodyMovement: l,
|
|
6725
6725
|
movementIntensity: u
|
|
6726
|
-
},
|
|
6726
|
+
}, ve = {
|
|
6727
6727
|
ttsEndpoint: Y.endpoint,
|
|
6728
6728
|
ttsApikey: Y.apiKey,
|
|
6729
6729
|
ttsService: X,
|
|
@@ -6732,10 +6732,10 @@ const Ee = ve(({
|
|
|
6732
6732
|
}, ge = T(async () => {
|
|
6733
6733
|
if (!(!P.current || p.current))
|
|
6734
6734
|
try {
|
|
6735
|
-
if (D(!0), _(null), p.current = new Me(P.current,
|
|
6735
|
+
if (D(!0), _(null), p.current = new Me(P.current, ve), 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,7 +6756,7 @@ 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
|
}, [O, t, e, i, n, s, o, a, l, u, h]);
|
|
6762
6762
|
pe(() => (ge(), () => {
|
|
@@ -6792,11 +6792,11 @@ const Ee = ve(({
|
|
|
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 {
|
|
@@ -6828,7 +6828,7 @@ const Ee = ve(({
|
|
|
6828
6828
|
}
|
|
6829
6829
|
}, [ne, re, ue.lipsyncLang]), b = T(() => {
|
|
6830
6830
|
p.current && (p.current.stopSpeaking(), p.current.setSlowdownRate && p.current.setSlowdownRate(1), z.current = null, V(!1));
|
|
6831
|
-
}, []),
|
|
6831
|
+
}, []), v = 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
6834
|
(F && z.current && z.current.text || F) && (p.current.pauseSpeaking(), V(!0));
|
|
@@ -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
|
}
|
|
@@ -6893,7 +6893,7 @@ const Ee = ve(({
|
|
|
6893
6893
|
return Ie(I, () => ({
|
|
6894
6894
|
speakText: J,
|
|
6895
6895
|
stopSpeaking: b,
|
|
6896
|
-
pauseSpeaking:
|
|
6896
|
+
pauseSpeaking: v,
|
|
6897
6897
|
resumeSpeaking: w,
|
|
6898
6898
|
resumeAudioContext: re,
|
|
6899
6899
|
setMood: C,
|
|
@@ -6983,7 +6983,7 @@ const Ee = ve(({
|
|
|
6983
6983
|
}
|
|
6984
6984
|
}
|
|
6985
6985
|
),
|
|
6986
|
-
|
|
6986
|
+
R && /* @__PURE__ */ he("div", { className: "loading-overlay", style: {
|
|
6987
6987
|
position: "absolute",
|
|
6988
6988
|
top: "50%",
|
|
6989
6989
|
left: "50%",
|
|
@@ -7009,7 +7009,7 @@ const Ee = ve(({
|
|
|
7009
7009
|
);
|
|
7010
7010
|
});
|
|
7011
7011
|
Ee.displayName = "TalkingHeadAvatar";
|
|
7012
|
-
const rt =
|
|
7012
|
+
const rt = Re(({
|
|
7013
7013
|
text: O = "Hello! I'm a talking avatar. How are you today?",
|
|
7014
7014
|
onLoading: t = () => {
|
|
7015
7015
|
},
|
|
@@ -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,7 +7054,7 @@ const rt = ve(({
|
|
|
7054
7054
|
}, z = T(async () => {
|
|
7055
7055
|
if (!(!u.current || a.current))
|
|
7056
7056
|
try {
|
|
7057
|
-
if (r(!0),
|
|
7057
|
+
if (r(!0), d(null), a.current = new Me(u.current, H), await a.current.showAvatar(p, (V) => {
|
|
7058
7058
|
if (V.lengthComputable) {
|
|
7059
7059
|
const E = Math.min(100, Math.round(V.loaded / V.total * 100));
|
|
7060
7060
|
t(E);
|
|
@@ -7084,20 +7084,20 @@ const rt = ve(({
|
|
|
7084
7084
|
document.removeEventListener("visibilitychange", U);
|
|
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(), () => {
|
|
7091
7091
|
a.current && (a.current.stop(), a.current.dispose(), a.current = null);
|
|
7092
7092
|
}), [z]);
|
|
7093
|
-
const
|
|
7093
|
+
const R = T((S) => {
|
|
7094
7094
|
if (a.current && g)
|
|
7095
7095
|
try {
|
|
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
7099
|
} catch (U) {
|
|
7100
|
-
console.error("Error speaking text:", U),
|
|
7100
|
+
console.error("Error speaking text:", U), d(U.message || "Failed to speak text");
|
|
7101
7101
|
}
|
|
7102
7102
|
else
|
|
7103
7103
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!a.current);
|
|
@@ -7149,7 +7149,7 @@ const rt = ve(({
|
|
|
7149
7149
|
console.warn("Animation system not available or animation not found:", S);
|
|
7150
7150
|
}, []);
|
|
7151
7151
|
return Ie(l, () => ({
|
|
7152
|
-
speakText:
|
|
7152
|
+
speakText: R,
|
|
7153
7153
|
stopSpeaking: D,
|
|
7154
7154
|
setMood: N,
|
|
7155
7155
|
setTimingAdjustment: _,
|
|
@@ -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,11 +7246,11 @@ 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
|
-
const lt =
|
|
7253
|
+
const lt = Re(({
|
|
7254
7254
|
curriculumData: O = null,
|
|
7255
7255
|
avatarConfig: t = {},
|
|
7256
7256
|
animations: e = {},
|
|
@@ -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(O?.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,
|
|
@@ -7330,17 +7330,17 @@ const lt = ve(({
|
|
|
7330
7330
|
lipsyncLang: "en"
|
|
7331
7331
|
};
|
|
7332
7332
|
}, [O, t, e]);
|
|
7333
|
-
const
|
|
7333
|
+
const R = T(() => (H.current || { modules: [] }).modules[r.current.currentModuleIndex]?.lessons[r.current.currentLessonIndex], []), D = T(() => R()?.questions[r.current.currentQuestionIndex], [R]), N = T((b, v) => v.type === "multiple_choice" || v.type === "true_false" ? b === v.answer : v.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
|
-
let
|
|
7337
|
-
if (r.current.totalQuestions > 0 ?
|
|
7336
|
+
let v = "Congratulations! You've completed this lesson";
|
|
7337
|
+
if (r.current.totalQuestions > 0 ? v += ` You got ${r.current.score} correct out of ${r.current.totalQuestions} question${r.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${b} percent. ` : v += "! ", b >= 80 ? v += "Excellent work! You have a great understanding of this topic." : b >= 60 ? v += "Good job! You understand most of the concepts." : v += "Keep practicing! You're making progress.", c.current.onLessonComplete({
|
|
7338
7338
|
moduleIndex: r.current.currentModuleIndex,
|
|
7339
7339
|
lessonIndex: r.current.currentLessonIndex,
|
|
7340
7340
|
score: r.current.score,
|
|
7341
7341
|
totalQuestions: r.current.totalQuestions,
|
|
7342
7342
|
percentage: b
|
|
7343
|
-
}),
|
|
7343
|
+
}), c.current.onCustomAction({
|
|
7344
7344
|
type: "lessonComplete",
|
|
7345
7345
|
moduleIndex: r.current.currentModuleIndex,
|
|
7346
7346
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7355,10 +7355,10 @@ const lt = ve(({
|
|
|
7355
7355
|
h.current.playCelebration();
|
|
7356
7356
|
}
|
|
7357
7357
|
const w = H.current || { modules: [] }, C = w.modules[r.current.currentModuleIndex], G = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, te = r.current.currentModuleIndex < (w.modules?.length || 0) - 1, ie = G || te, A = z.current || { lipsyncLang: "en" };
|
|
7358
|
-
h.current.speakText(
|
|
7358
|
+
h.current.speakText(v, {
|
|
7359
7359
|
lipsyncLang: A.lipsyncLang,
|
|
7360
7360
|
onSpeechEnd: () => {
|
|
7361
|
-
|
|
7361
|
+
c.current.onCustomAction({
|
|
7362
7362
|
type: "lessonCompleteFeedbackDone",
|
|
7363
7363
|
moduleIndex: r.current.currentModuleIndex,
|
|
7364
7364
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7373,9 +7373,9 @@ const lt = ve(({
|
|
|
7373
7373
|
}, [e.lessonComplete]), ne = T(() => {
|
|
7374
7374
|
r.current.curriculumCompleted = !0;
|
|
7375
7375
|
const b = H.current || { modules: [] };
|
|
7376
|
-
if (
|
|
7376
|
+
if (c.current.onCurriculumComplete({
|
|
7377
7377
|
modules: b.modules.length,
|
|
7378
|
-
totalLessons: b.modules.reduce((
|
|
7378
|
+
totalLessons: b.modules.reduce((v, w) => v + w.lessons.length, 0)
|
|
7379
7379
|
}), h.current) {
|
|
7380
7380
|
if (h.current.setMood("celebrating"), e.curriculumComplete)
|
|
7381
7381
|
try {
|
|
@@ -7383,24 +7383,24 @@ const lt = ve(({
|
|
|
7383
7383
|
} catch {
|
|
7384
7384
|
h.current.playCelebration();
|
|
7385
7385
|
}
|
|
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:
|
|
7386
|
+
const v = z.current || { lipsyncLang: "en" };
|
|
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: v.lipsyncLang });
|
|
7388
7388
|
}
|
|
7389
7389
|
}, [e.curriculumComplete]), S = T(() => {
|
|
7390
|
-
const b =
|
|
7390
|
+
const b = R();
|
|
7391
7391
|
r.current.isQuestionMode = !0, r.current.currentQuestionIndex = 0, r.current.totalQuestions = b?.questions?.length || 0, r.current.score = 0;
|
|
7392
|
-
const
|
|
7393
|
-
|
|
7392
|
+
const v = D();
|
|
7393
|
+
v && c.current.onCustomAction({
|
|
7394
7394
|
type: "questionStart",
|
|
7395
7395
|
moduleIndex: r.current.currentModuleIndex,
|
|
7396
7396
|
lessonIndex: r.current.currentLessonIndex,
|
|
7397
7397
|
questionIndex: r.current.currentQuestionIndex,
|
|
7398
7398
|
totalQuestions: r.current.totalQuestions,
|
|
7399
|
-
question:
|
|
7399
|
+
question: v,
|
|
7400
7400
|
score: r.current.score
|
|
7401
7401
|
});
|
|
7402
7402
|
const w = () => {
|
|
7403
|
-
if (!h.current || !
|
|
7403
|
+
if (!h.current || !v) return;
|
|
7404
7404
|
if (h.current.setMood("happy"), e.questionStart)
|
|
7405
7405
|
try {
|
|
7406
7406
|
h.current.playAnimation(e.questionStart, !0);
|
|
@@ -7408,37 +7408,37 @@ const lt = ve(({
|
|
|
7408
7408
|
console.warn("Failed to play questionStart animation:", G);
|
|
7409
7409
|
}
|
|
7410
7410
|
const C = z.current || { lipsyncLang: "en" };
|
|
7411
|
-
|
|
7411
|
+
v.type === "code_test" ? h.current.speakText(`Let's test your coding skills! Here's your first challenge: ${v.question}`, { lipsyncLang: C.lipsyncLang }) : v.type === "multiple_choice" ? h.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: C.lipsyncLang }) : v.type === "true_false" ? h.current.speakText(`Let's start with some true or false questions. First question: ${v.question}`, { lipsyncLang: C.lipsyncLang }) : h.current.speakText(`Now let me ask you some questions. Here's the first one: ${v.question}`, { lipsyncLang: C.lipsyncLang });
|
|
7412
7412
|
};
|
|
7413
|
-
if (h.current && h.current.isReady &&
|
|
7413
|
+
if (h.current && h.current.isReady && v)
|
|
7414
7414
|
w();
|
|
7415
7415
|
else if (h.current && h.current.isReady) {
|
|
7416
7416
|
const C = z.current || { lipsyncLang: "en" };
|
|
7417
7417
|
h.current.speakText("Now let me ask you some questions to test your understanding.", { lipsyncLang: C.lipsyncLang });
|
|
7418
7418
|
} else {
|
|
7419
7419
|
const C = setInterval(() => {
|
|
7420
|
-
h.current && h.current.isReady && (clearInterval(C),
|
|
7420
|
+
h.current && h.current.isReady && (clearInterval(C), v && w());
|
|
7421
7421
|
}, 100);
|
|
7422
7422
|
setTimeout(() => {
|
|
7423
7423
|
clearInterval(C);
|
|
7424
7424
|
}, 5e3);
|
|
7425
7425
|
}
|
|
7426
|
-
}, [e.questionStart,
|
|
7427
|
-
const b =
|
|
7426
|
+
}, [e.questionStart, R, D]), U = T(() => {
|
|
7427
|
+
const b = R();
|
|
7428
7428
|
if (r.current.currentQuestionIndex < (b?.questions?.length || 0) - 1) {
|
|
7429
7429
|
h.current && h.current.stopSpeaking && h.current.stopSpeaking(), r.current.currentQuestionIndex += 1;
|
|
7430
|
-
const
|
|
7431
|
-
|
|
7430
|
+
const v = D();
|
|
7431
|
+
v && c.current.onCustomAction({
|
|
7432
7432
|
type: "nextQuestion",
|
|
7433
7433
|
moduleIndex: r.current.currentModuleIndex,
|
|
7434
7434
|
lessonIndex: r.current.currentLessonIndex,
|
|
7435
7435
|
questionIndex: r.current.currentQuestionIndex,
|
|
7436
7436
|
totalQuestions: r.current.totalQuestions,
|
|
7437
|
-
question:
|
|
7437
|
+
question: v,
|
|
7438
7438
|
score: r.current.score
|
|
7439
7439
|
});
|
|
7440
7440
|
const w = () => {
|
|
7441
|
-
if (!h.current || !
|
|
7441
|
+
if (!h.current || !v) return;
|
|
7442
7442
|
if (h.current.setMood("happy"), h.current.setBodyMovement("idle"), e.nextQuestion)
|
|
7443
7443
|
try {
|
|
7444
7444
|
h.current.playAnimation(e.nextQuestion, !0);
|
|
@@ -7446,19 +7446,19 @@ const lt = ve(({
|
|
|
7446
7446
|
console.warn("Failed to play nextQuestion animation:", G);
|
|
7447
7447
|
}
|
|
7448
7448
|
const C = z.current || { lipsyncLang: "en" };
|
|
7449
|
-
|
|
7449
|
+
v.type === "code_test" ? h.current.speakText(`Great! Now let's move on to your next coding challenge: ${v.question}`, {
|
|
7450
7450
|
lipsyncLang: C.lipsyncLang
|
|
7451
|
-
}) :
|
|
7451
|
+
}) : v.type === "multiple_choice" ? h.current.speakText(`Alright! Here's your next question: ${v.question}`, {
|
|
7452
7452
|
lipsyncLang: C.lipsyncLang
|
|
7453
|
-
}) :
|
|
7453
|
+
}) : v.type === "true_false" ? h.current.speakText(`Now let's try this one: ${v.question}`, {
|
|
7454
7454
|
lipsyncLang: C.lipsyncLang
|
|
7455
|
-
}) : h.current.speakText(`Here's the next question: ${
|
|
7455
|
+
}) : h.current.speakText(`Here's the next question: ${v.question}`, {
|
|
7456
7456
|
lipsyncLang: C.lipsyncLang
|
|
7457
7457
|
});
|
|
7458
7458
|
};
|
|
7459
|
-
if (h.current && h.current.isReady &&
|
|
7459
|
+
if (h.current && h.current.isReady && v)
|
|
7460
7460
|
w();
|
|
7461
|
-
else if (
|
|
7461
|
+
else if (v) {
|
|
7462
7462
|
const C = setInterval(() => {
|
|
7463
7463
|
h.current && h.current.isReady && (clearInterval(C), w());
|
|
7464
7464
|
}, 100);
|
|
@@ -7467,52 +7467,52 @@ const lt = ve(({
|
|
|
7467
7467
|
}, 5e3);
|
|
7468
7468
|
}
|
|
7469
7469
|
} else
|
|
7470
|
-
|
|
7470
|
+
c.current.onCustomAction({
|
|
7471
7471
|
type: "allQuestionsComplete",
|
|
7472
7472
|
moduleIndex: r.current.currentModuleIndex,
|
|
7473
7473
|
lessonIndex: r.current.currentLessonIndex,
|
|
7474
7474
|
totalQuestions: r.current.totalQuestions,
|
|
7475
7475
|
score: r.current.score
|
|
7476
7476
|
});
|
|
7477
|
-
}, [e.nextQuestion,
|
|
7478
|
-
const b = H.current || { modules: [] },
|
|
7479
|
-
if (r.current.currentLessonIndex < (
|
|
7477
|
+
}, [e.nextQuestion, R, D]), V = T(() => {
|
|
7478
|
+
const b = H.current || { modules: [] }, v = b.modules[r.current.currentModuleIndex];
|
|
7479
|
+
if (r.current.currentLessonIndex < (v?.lessons?.length || 0) - 1) {
|
|
7480
7480
|
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
7481
|
const C = b.modules[r.current.currentModuleIndex], G = r.current.currentLessonIndex < (C?.lessons?.length || 0) - 1, te = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, ie = G || te;
|
|
7482
|
-
|
|
7482
|
+
c.current.onCustomAction({
|
|
7483
7483
|
type: "lessonStart",
|
|
7484
7484
|
moduleIndex: r.current.currentModuleIndex,
|
|
7485
7485
|
lessonIndex: r.current.currentLessonIndex,
|
|
7486
7486
|
hasNextLesson: ie
|
|
7487
|
-
}),
|
|
7487
|
+
}), c.current.onLessonStart({
|
|
7488
7488
|
moduleIndex: r.current.currentModuleIndex,
|
|
7489
7489
|
lessonIndex: r.current.currentLessonIndex,
|
|
7490
|
-
lesson:
|
|
7490
|
+
lesson: R()
|
|
7491
7491
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7492
7492
|
} else if (r.current.currentModuleIndex < (b.modules?.length || 0) - 1) {
|
|
7493
7493
|
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
7494
|
const G = b.modules[r.current.currentModuleIndex], te = r.current.currentLessonIndex < (G?.lessons?.length || 0) - 1, ie = r.current.currentModuleIndex < (b.modules?.length || 0) - 1, A = te || ie;
|
|
7495
|
-
|
|
7495
|
+
c.current.onCustomAction({
|
|
7496
7496
|
type: "lessonStart",
|
|
7497
7497
|
moduleIndex: r.current.currentModuleIndex,
|
|
7498
7498
|
lessonIndex: r.current.currentLessonIndex,
|
|
7499
7499
|
hasNextLesson: A
|
|
7500
|
-
}),
|
|
7500
|
+
}), c.current.onLessonStart({
|
|
7501
7501
|
moduleIndex: r.current.currentModuleIndex,
|
|
7502
7502
|
lessonIndex: r.current.currentLessonIndex,
|
|
7503
|
-
lesson:
|
|
7503
|
+
lesson: R()
|
|
7504
7504
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7505
7505
|
} else
|
|
7506
7506
|
I.current && I.current();
|
|
7507
7507
|
}, []), E = T(() => {
|
|
7508
|
-
const b =
|
|
7509
|
-
let
|
|
7508
|
+
const b = R();
|
|
7509
|
+
let v = null;
|
|
7510
7510
|
if (b?.avatar_script && b?.body) {
|
|
7511
7511
|
const w = b.avatar_script.trim(), C = b.body.trim(), G = w.match(/[.!?]$/) ? " " : ". ";
|
|
7512
|
-
|
|
7512
|
+
v = `${w}${G}${C}`;
|
|
7513
7513
|
} else
|
|
7514
|
-
|
|
7515
|
-
if (h.current && h.current.isReady &&
|
|
7514
|
+
v = b?.avatar_script || b?.body || null;
|
|
7515
|
+
if (h.current && h.current.isReady && v) {
|
|
7516
7516
|
r.current.isTeaching = !0, r.current.isQuestionMode = !1, r.current.score = 0, r.current.totalQuestions = 0, h.current.setMood("happy");
|
|
7517
7517
|
let w = !1;
|
|
7518
7518
|
if (e.teaching)
|
|
@@ -7523,19 +7523,19 @@ const lt = ve(({
|
|
|
7523
7523
|
}
|
|
7524
7524
|
w || h.current.setBodyMovement("gesturing");
|
|
7525
7525
|
const C = z.current || { lipsyncLang: "en" };
|
|
7526
|
-
|
|
7526
|
+
c.current.onLessonStart({
|
|
7527
7527
|
moduleIndex: r.current.currentModuleIndex,
|
|
7528
7528
|
lessonIndex: r.current.currentLessonIndex,
|
|
7529
7529
|
lesson: b
|
|
7530
|
-
}),
|
|
7530
|
+
}), c.current.onCustomAction({
|
|
7531
7531
|
type: "teachingStart",
|
|
7532
7532
|
moduleIndex: r.current.currentModuleIndex,
|
|
7533
7533
|
lessonIndex: r.current.currentLessonIndex,
|
|
7534
7534
|
lesson: b
|
|
7535
|
-
}), h.current.speakText(
|
|
7535
|
+
}), h.current.speakText(v, {
|
|
7536
7536
|
lipsyncLang: C.lipsyncLang,
|
|
7537
7537
|
onSpeechEnd: () => {
|
|
7538
|
-
r.current.isTeaching = !1,
|
|
7538
|
+
r.current.isTeaching = !1, c.current.onCustomAction({
|
|
7539
7539
|
type: "teachingComplete",
|
|
7540
7540
|
moduleIndex: r.current.currentModuleIndex,
|
|
7541
7541
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7545,15 +7545,15 @@ const lt = ve(({
|
|
|
7545
7545
|
}
|
|
7546
7546
|
});
|
|
7547
7547
|
}
|
|
7548
|
-
}, [e.teaching,
|
|
7549
|
-
const
|
|
7550
|
-
if (w && (r.current.score += 1),
|
|
7548
|
+
}, [e.teaching, R]), X = T((b) => {
|
|
7549
|
+
const v = D(), w = N(b, v);
|
|
7550
|
+
if (w && (r.current.score += 1), c.current.onQuestionAnswer({
|
|
7551
7551
|
moduleIndex: r.current.currentModuleIndex,
|
|
7552
7552
|
lessonIndex: r.current.currentLessonIndex,
|
|
7553
7553
|
questionIndex: r.current.currentQuestionIndex,
|
|
7554
7554
|
answer: b,
|
|
7555
7555
|
isCorrect: w,
|
|
7556
|
-
question:
|
|
7556
|
+
question: v
|
|
7557
7557
|
}), h.current)
|
|
7558
7558
|
if (w) {
|
|
7559
7559
|
if (h.current.setMood("happy"), e.correct)
|
|
@@ -7563,12 +7563,12 @@ const lt = ve(({
|
|
|
7563
7563
|
h.current.setBodyMovement("happy");
|
|
7564
7564
|
}
|
|
7565
7565
|
h.current.setBodyMovement("gesturing");
|
|
7566
|
-
const C =
|
|
7566
|
+
const C = v.type === "code_test" ? `Great job! Your code passed all the tests! ${v.explanation || ""}` : `Excellent! That's correct! ${v.explanation || ""}`, G = z.current || { lipsyncLang: "en" };
|
|
7567
7567
|
h.current.speakText(C, {
|
|
7568
7568
|
lipsyncLang: G.lipsyncLang,
|
|
7569
7569
|
onSpeechEnd: () => {
|
|
7570
|
-
const ie =
|
|
7571
|
-
|
|
7570
|
+
const ie = R()?.questions?.length || 0;
|
|
7571
|
+
c.current.onCustomAction({
|
|
7572
7572
|
type: "answerFeedbackComplete",
|
|
7573
7573
|
moduleIndex: r.current.currentModuleIndex,
|
|
7574
7574
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7588,12 +7588,12 @@ const lt = ve(({
|
|
|
7588
7588
|
h.current.setBodyMovement("idle");
|
|
7589
7589
|
}
|
|
7590
7590
|
h.current.setBodyMovement("gesturing");
|
|
7591
|
-
const C =
|
|
7591
|
+
const C = v.type === "code_test" ? `Your code didn't pass all the tests. ${v.explanation || "Try again!"}` : `Not quite right, but don't worry! ${v.explanation || ""} Let's move on to the next question.`, G = z.current || { lipsyncLang: "en" };
|
|
7592
7592
|
h.current.speakText(C, {
|
|
7593
7593
|
lipsyncLang: G.lipsyncLang,
|
|
7594
7594
|
onSpeechEnd: () => {
|
|
7595
|
-
const ie =
|
|
7596
|
-
|
|
7595
|
+
const ie = R()?.questions?.length || 0;
|
|
7596
|
+
c.current.onCustomAction({
|
|
7597
7597
|
type: "answerFeedbackComplete",
|
|
7598
7598
|
moduleIndex: r.current.currentModuleIndex,
|
|
7599
7599
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7607,8 +7607,8 @@ const lt = ve(({
|
|
|
7607
7607
|
});
|
|
7608
7608
|
}
|
|
7609
7609
|
else {
|
|
7610
|
-
const G =
|
|
7611
|
-
|
|
7610
|
+
const G = R()?.questions?.length || 0;
|
|
7611
|
+
c.current.onCustomAction({
|
|
7612
7612
|
type: "answerFeedbackComplete",
|
|
7613
7613
|
moduleIndex: r.current.currentModuleIndex,
|
|
7614
7614
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7620,13 +7620,13 @@ const lt = ve(({
|
|
|
7620
7620
|
avatarNotReady: !0
|
|
7621
7621
|
});
|
|
7622
7622
|
}
|
|
7623
|
-
}, [e.correct, e.incorrect, D,
|
|
7624
|
-
const
|
|
7623
|
+
}, [e.correct, e.incorrect, D, R, N]), Y = T((b) => {
|
|
7624
|
+
const v = D();
|
|
7625
7625
|
if (!b || typeof b != "object") {
|
|
7626
7626
|
console.error("Invalid code test result format. Expected object with {passed: boolean, ...}");
|
|
7627
7627
|
return;
|
|
7628
7628
|
}
|
|
7629
|
-
if (
|
|
7629
|
+
if (v?.type !== "code_test") {
|
|
7630
7630
|
console.warn("Current question is not a code test. Use handleAnswerSelect for other question types.");
|
|
7631
7631
|
return;
|
|
7632
7632
|
}
|
|
@@ -7640,19 +7640,19 @@ const lt = ve(({
|
|
|
7640
7640
|
passedCount: b.passedCount || 0,
|
|
7641
7641
|
failedCount: b.failedCount || 0
|
|
7642
7642
|
};
|
|
7643
|
-
|
|
7643
|
+
c.current.onCustomAction({
|
|
7644
7644
|
type: "codeTestSubmitted",
|
|
7645
7645
|
moduleIndex: r.current.currentModuleIndex,
|
|
7646
7646
|
lessonIndex: r.current.currentLessonIndex,
|
|
7647
7647
|
questionIndex: r.current.currentQuestionIndex,
|
|
7648
7648
|
testResult: w,
|
|
7649
|
-
question:
|
|
7649
|
+
question: v
|
|
7650
7650
|
}), p.current && p.current(w);
|
|
7651
7651
|
}, [D, N]), ue = T(() => {
|
|
7652
7652
|
if (r.current.currentQuestionIndex > 0) {
|
|
7653
7653
|
r.current.currentQuestionIndex -= 1;
|
|
7654
7654
|
const b = D();
|
|
7655
|
-
b &&
|
|
7655
|
+
b && c.current.onCustomAction({
|
|
7656
7656
|
type: "questionStart",
|
|
7657
7657
|
moduleIndex: r.current.currentModuleIndex,
|
|
7658
7658
|
lessonIndex: r.current.currentLessonIndex,
|
|
@@ -7661,7 +7661,7 @@ const lt = ve(({
|
|
|
7661
7661
|
question: b,
|
|
7662
7662
|
score: r.current.score
|
|
7663
7663
|
});
|
|
7664
|
-
const
|
|
7664
|
+
const v = () => {
|
|
7665
7665
|
if (!h.current || !b) return;
|
|
7666
7666
|
h.current.setMood("happy"), h.current.setBodyMovement("idle");
|
|
7667
7667
|
const w = z.current || { lipsyncLang: "en" };
|
|
@@ -7672,51 +7672,51 @@ const lt = ve(({
|
|
|
7672
7672
|
});
|
|
7673
7673
|
};
|
|
7674
7674
|
if (h.current && h.current.isReady && b)
|
|
7675
|
-
|
|
7675
|
+
v();
|
|
7676
7676
|
else if (b) {
|
|
7677
7677
|
const w = setInterval(() => {
|
|
7678
|
-
h.current && h.current.isReady && (clearInterval(w),
|
|
7678
|
+
h.current && h.current.isReady && (clearInterval(w), v());
|
|
7679
7679
|
}, 100);
|
|
7680
7680
|
setTimeout(() => {
|
|
7681
7681
|
clearInterval(w);
|
|
7682
7682
|
}, 5e3);
|
|
7683
7683
|
}
|
|
7684
7684
|
}
|
|
7685
|
-
}, [D]),
|
|
7685
|
+
}, [D]), ve = T(() => {
|
|
7686
7686
|
const b = H.current || { modules: [] };
|
|
7687
7687
|
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,
|
|
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, c.current.onCustomAction({
|
|
7689
7689
|
type: "lessonStart",
|
|
7690
7690
|
moduleIndex: r.current.currentModuleIndex,
|
|
7691
7691
|
lessonIndex: r.current.currentLessonIndex
|
|
7692
|
-
}),
|
|
7692
|
+
}), c.current.onLessonStart({
|
|
7693
7693
|
moduleIndex: r.current.currentModuleIndex,
|
|
7694
7694
|
lessonIndex: r.current.currentLessonIndex,
|
|
7695
|
-
lesson:
|
|
7695
|
+
lesson: R()
|
|
7696
7696
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7697
7697
|
else if (r.current.currentModuleIndex > 0) {
|
|
7698
7698
|
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,
|
|
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, c.current.onCustomAction({
|
|
7700
7700
|
type: "lessonStart",
|
|
7701
7701
|
moduleIndex: r.current.currentModuleIndex,
|
|
7702
7702
|
lessonIndex: r.current.currentLessonIndex
|
|
7703
|
-
}),
|
|
7703
|
+
}), c.current.onLessonStart({
|
|
7704
7704
|
moduleIndex: r.current.currentModuleIndex,
|
|
7705
7705
|
lessonIndex: r.current.currentLessonIndex,
|
|
7706
|
-
lesson:
|
|
7706
|
+
lesson: R()
|
|
7707
7707
|
}), h.current && (h.current.setMood("happy"), h.current.setBodyMovement("idle"));
|
|
7708
7708
|
}
|
|
7709
|
-
}, [
|
|
7709
|
+
}, [R]), ge = T(() => {
|
|
7710
7710
|
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
7711
|
}, []), re = T((b) => {
|
|
7712
7712
|
console.log("Avatar is ready!", b);
|
|
7713
|
-
const
|
|
7713
|
+
const v = R(), w = v?.avatar_script || v?.body;
|
|
7714
7714
|
u && w && setTimeout(() => {
|
|
7715
|
-
|
|
7715
|
+
d.current && d.current();
|
|
7716
7716
|
}, 10);
|
|
7717
|
-
}, [u,
|
|
7717
|
+
}, [u, R]);
|
|
7718
7718
|
Oe(() => {
|
|
7719
|
-
|
|
7719
|
+
d.current = E, g.current = V, y.current = _, x.current = U, I.current = ne, P.current = S, p.current = X;
|
|
7720
7720
|
}), Ie(a, () => ({
|
|
7721
7721
|
// Curriculum control methods
|
|
7722
7722
|
startTeaching: E,
|
|
@@ -7726,30 +7726,30 @@ const lt = ve(({
|
|
|
7726
7726
|
nextQuestion: U,
|
|
7727
7727
|
previousQuestion: ue,
|
|
7728
7728
|
nextLesson: V,
|
|
7729
|
-
previousLesson:
|
|
7729
|
+
previousLesson: ve,
|
|
7730
7730
|
completeLesson: _,
|
|
7731
7731
|
completeCurriculum: ne,
|
|
7732
7732
|
resetCurriculum: ge,
|
|
7733
7733
|
getState: () => ({ ...r.current }),
|
|
7734
7734
|
getCurrentQuestion: () => D(),
|
|
7735
|
-
getCurrentLesson: () =>
|
|
7735
|
+
getCurrentLesson: () => R(),
|
|
7736
7736
|
// Direct access to avatar ref (always returns current value)
|
|
7737
7737
|
getAvatarRef: () => h.current,
|
|
7738
7738
|
// Convenience methods that delegate to avatar (always check current ref)
|
|
7739
|
-
speakText: async (b,
|
|
7739
|
+
speakText: async (b, v = {}) => {
|
|
7740
7740
|
await h.current?.resumeAudioContext?.();
|
|
7741
7741
|
const w = z.current || { lipsyncLang: "en" };
|
|
7742
|
-
h.current?.speakText(b, { ...
|
|
7742
|
+
h.current?.speakText(b, { ...v, lipsyncLang: v.lipsyncLang || w.lipsyncLang });
|
|
7743
7743
|
},
|
|
7744
7744
|
resumeAudioContext: async () => {
|
|
7745
7745
|
if (h.current?.resumeAudioContext)
|
|
7746
7746
|
return await h.current.resumeAudioContext();
|
|
7747
7747
|
const b = h.current?.talkingHead;
|
|
7748
7748
|
if (b?.audioCtx) {
|
|
7749
|
-
const
|
|
7750
|
-
if (
|
|
7749
|
+
const v = b.audioCtx;
|
|
7750
|
+
if (v.state === "suspended" || v.state === "interrupted")
|
|
7751
7751
|
try {
|
|
7752
|
-
await
|
|
7752
|
+
await v.resume(), console.log("Audio context resumed via talkingHead");
|
|
7753
7753
|
} catch (w) {
|
|
7754
7754
|
console.warn("Failed to resume audio context:", w);
|
|
7755
7755
|
}
|
|
@@ -7761,7 +7761,7 @@ const lt = ve(({
|
|
|
7761
7761
|
resumeSpeaking: async () => await h.current?.resumeSpeaking(),
|
|
7762
7762
|
isPaused: () => h.current && typeof h.current.isPaused < "u" ? h.current.isPaused : !1,
|
|
7763
7763
|
setMood: (b) => h.current?.setMood(b),
|
|
7764
|
-
playAnimation: (b,
|
|
7764
|
+
playAnimation: (b, v) => h.current?.playAnimation(b, v),
|
|
7765
7765
|
setBodyMovement: (b) => h.current?.setBodyMovement(b),
|
|
7766
7766
|
setMovementIntensity: (b) => h.current?.setMovementIntensity(b),
|
|
7767
7767
|
playRandomDance: () => h.current?.playRandomDance(),
|
|
@@ -7772,10 +7772,10 @@ const lt = ve(({
|
|
|
7772
7772
|
lockAvatarPosition: () => h.current?.lockAvatarPosition(),
|
|
7773
7773
|
unlockAvatarPosition: () => h.current?.unlockAvatarPosition(),
|
|
7774
7774
|
// Custom action trigger
|
|
7775
|
-
triggerCustomAction: (b,
|
|
7776
|
-
|
|
7775
|
+
triggerCustomAction: (b, v) => {
|
|
7776
|
+
c.current.onCustomAction({
|
|
7777
7777
|
type: b,
|
|
7778
|
-
...
|
|
7778
|
+
...v,
|
|
7779
7779
|
state: { ...r.current }
|
|
7780
7780
|
});
|
|
7781
7781
|
},
|
|
@@ -7783,7 +7783,7 @@ const lt = ve(({
|
|
|
7783
7783
|
handleResize: () => h.current?.handleResize(),
|
|
7784
7784
|
// Avatar readiness check (always returns current value)
|
|
7785
7785
|
isAvatarReady: () => h.current?.isReady || !1
|
|
7786
|
-
}), [E, S, X, Y, U, V, _, ne, ge, D,
|
|
7786
|
+
}), [E, S, X, Y, U, V, _, ne, ge, D, R]);
|
|
7787
7787
|
const J = z.current || {
|
|
7788
7788
|
avatarUrl: "/avatars/brunette.glb",
|
|
7789
7789
|
avatarBody: "F",
|
|
@@ -7926,7 +7926,7 @@ const Fe = {
|
|
|
7926
7926
|
duration: 5e3,
|
|
7927
7927
|
description: "Excited, energetic movement"
|
|
7928
7928
|
}
|
|
7929
|
-
}, bt = (O) => Fe[O] || null,
|
|
7929
|
+
}, bt = (O) => Fe[O] || null, vt = (O) => Fe.hasOwnProperty(O);
|
|
7930
7930
|
export {
|
|
7931
7931
|
lt as CurriculumLearning,
|
|
7932
7932
|
Ee as TalkingHeadAvatar,
|
|
@@ -7935,5 +7935,5 @@ export {
|
|
|
7935
7935
|
Le as getActiveTTSConfig,
|
|
7936
7936
|
bt as getAnimation,
|
|
7937
7937
|
xt as getVoiceOptions,
|
|
7938
|
-
|
|
7938
|
+
vt as hasAnimation
|
|
7939
7939
|
};
|