@sage-rsc/talking-head-react 1.0.83 → 1.0.84
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 +259 -235
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +28 -20
package/dist/index.js
CHANGED
|
@@ -521,10 +521,10 @@ class tt {
|
|
|
521
521
|
for (let l = 0; l < o; l++) {
|
|
522
522
|
const h = l * s, r = Math.min(h + i, t.length), u = t.slice(h, r), a = this.calculateEnergy(u);
|
|
523
523
|
n.energy.push(a);
|
|
524
|
-
const
|
|
525
|
-
n.spectralCentroid.push(
|
|
526
|
-
const
|
|
527
|
-
n.zeroCrossingRate.push(
|
|
524
|
+
const d = this.calculateSpectralCentroid(u);
|
|
525
|
+
n.spectralCentroid.push(d);
|
|
526
|
+
const c = this.calculateZeroCrossingRate(u);
|
|
527
|
+
n.zeroCrossingRate.push(c);
|
|
528
528
|
const g = this.calculateMFCC(u);
|
|
529
529
|
n.mfcc.push(g);
|
|
530
530
|
}
|
|
@@ -606,8 +606,8 @@ class tt {
|
|
|
606
606
|
for (let h = 0; h < e; h += i) {
|
|
607
607
|
let r = 1, u = 0;
|
|
608
608
|
for (let a = 0; a < i / 2; a++) {
|
|
609
|
-
const
|
|
610
|
-
n[(h + a) * 2] =
|
|
609
|
+
const d = n[(h + a) * 2], c = n[(h + a) * 2 + 1], g = n[(h + a + i / 2) * 2] * r - n[(h + a + i / 2) * 2 + 1] * u, y = n[(h + a + i / 2) * 2] * u + n[(h + a + i / 2) * 2 + 1] * r;
|
|
610
|
+
n[(h + a) * 2] = d + g, n[(h + a) * 2 + 1] = c + y, n[(h + a + i / 2) * 2] = d - g, n[(h + a + i / 2) * 2 + 1] = c - y;
|
|
611
611
|
const b = r * o - u * l, I = r * l + u * o;
|
|
612
612
|
r = b, u = I;
|
|
613
613
|
}
|
|
@@ -703,15 +703,15 @@ class tt {
|
|
|
703
703
|
const o = this.textToVisemes(e);
|
|
704
704
|
let l = 0, h = 0;
|
|
705
705
|
for (let r = 0; r < s.length && l < o.length; r++) {
|
|
706
|
-
const u = s[r], a = o[l],
|
|
706
|
+
const u = s[r], a = o[l], d = t.energy[Math.floor(u / 0.023)] || 0, c = this.calculateVisemeDuration(a, d);
|
|
707
707
|
i.push({
|
|
708
708
|
viseme: a,
|
|
709
709
|
startTime: h,
|
|
710
|
-
endTime: h +
|
|
711
|
-
duration:
|
|
712
|
-
intensity: Math.min(1,
|
|
710
|
+
endTime: h + c,
|
|
711
|
+
duration: c,
|
|
712
|
+
intensity: Math.min(1, d * 2)
|
|
713
713
|
// Map energy to viseme intensity
|
|
714
|
-
}), h +=
|
|
714
|
+
}), h += c, l++;
|
|
715
715
|
}
|
|
716
716
|
for (; l < o.length; ) {
|
|
717
717
|
const r = o[l], u = this.calculateVisemeDuration(r, 0.5);
|
|
@@ -1207,10 +1207,10 @@ class nt {
|
|
|
1207
1207
|
Object.keys(this.rules).forEach((e) => {
|
|
1208
1208
|
this.rules[e] = this.rules[e].map((n) => {
|
|
1209
1209
|
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
1210
|
-
let
|
|
1211
|
-
|
|
1212
|
-
const
|
|
1213
|
-
return
|
|
1210
|
+
let d = "";
|
|
1211
|
+
d += [...l].map((g) => t[g] || g).join("");
|
|
1212
|
+
const c = [...h];
|
|
1213
|
+
return c[0] = c[0].toLowerCase(), d += c.join(""), a.move = c.length, d += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(d), u.length && u.split(" ").forEach((g) => {
|
|
1214
1214
|
a.visemes.push(g);
|
|
1215
1215
|
}), a;
|
|
1216
1216
|
});
|
|
@@ -1380,11 +1380,11 @@ class nt {
|
|
|
1380
1380
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(h.regex)) {
|
|
1381
1381
|
h.visemes.forEach((a) => {
|
|
1382
1382
|
if (e.visemes.length && e.visemes[e.visemes.length - 1] === a) {
|
|
1383
|
-
const
|
|
1384
|
-
e.durations[e.durations.length - 1] +=
|
|
1383
|
+
const d = 0.7 * (this.visemeDurations[a] || 1);
|
|
1384
|
+
e.durations[e.durations.length - 1] += d, n += d;
|
|
1385
1385
|
} else {
|
|
1386
|
-
const
|
|
1387
|
-
e.visemes.push(a), e.times.push(n), e.durations.push(
|
|
1386
|
+
const d = this.visemeDurations[a] || 1;
|
|
1387
|
+
e.visemes.push(a), e.times.push(n), e.durations.push(d), n += d;
|
|
1388
1388
|
}
|
|
1389
1389
|
}), e.i += h.move;
|
|
1390
1390
|
break;
|
|
@@ -1617,10 +1617,10 @@ class ot {
|
|
|
1617
1617
|
Object.keys(this.rules).forEach((e) => {
|
|
1618
1618
|
this.rules[e] = this.rules[e].map((n) => {
|
|
1619
1619
|
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
1620
|
-
let
|
|
1621
|
-
|
|
1622
|
-
const
|
|
1623
|
-
return
|
|
1620
|
+
let d = "";
|
|
1621
|
+
d += [...l].map((g) => t[g] || g).join("");
|
|
1622
|
+
const c = [...h];
|
|
1623
|
+
return c[0] = c[0].toLowerCase(), d += c.join(""), a.move = c.length, d += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(d), u.length && u.split(" ").forEach((g) => {
|
|
1624
1624
|
a.visemes.push(g);
|
|
1625
1625
|
}), a;
|
|
1626
1626
|
});
|
|
@@ -1735,13 +1735,13 @@ class ot {
|
|
|
1735
1735
|
for (let h = 0; h < o.length; h++) {
|
|
1736
1736
|
const r = o[h];
|
|
1737
1737
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
|
|
1738
|
-
r.visemes.forEach((
|
|
1739
|
-
if (e.visemes.length && e.visemes[e.visemes.length - 1] ===
|
|
1740
|
-
const
|
|
1741
|
-
e.durations[e.durations.length - 1] +=
|
|
1738
|
+
r.visemes.forEach((d) => {
|
|
1739
|
+
if (e.visemes.length && e.visemes[e.visemes.length - 1] === d) {
|
|
1740
|
+
const c = 0.7 * (this.visemeDurations[d] || 1);
|
|
1741
|
+
e.durations[e.durations.length - 1] += c, n += c;
|
|
1742
1742
|
} else {
|
|
1743
|
-
const
|
|
1744
|
-
e.visemes.push(
|
|
1743
|
+
const c = this.visemeDurations[d] || 1;
|
|
1744
|
+
e.visemes.push(d), e.times.push(n), e.durations.push(c), n += c;
|
|
1745
1745
|
}
|
|
1746
1746
|
}), e.i += r.move, l = !0;
|
|
1747
1747
|
break;
|
|
@@ -2132,10 +2132,10 @@ class at {
|
|
|
2132
2132
|
Object.keys(this.rules).forEach((e) => {
|
|
2133
2133
|
this.rules[e] = this.rules[e].map((n) => {
|
|
2134
2134
|
const i = n.indexOf("["), s = n.indexOf("]"), o = n.indexOf("="), l = n.substring(0, i), h = n.substring(i + 1, s), r = n.substring(s + 1, o), u = n.substring(o + 1), a = { regex: "", move: 0, visemes: [] };
|
|
2135
|
-
let
|
|
2136
|
-
|
|
2137
|
-
const
|
|
2138
|
-
return
|
|
2135
|
+
let d = "";
|
|
2136
|
+
d += [...l].map((g) => t[g] || g).join("");
|
|
2137
|
+
const c = [...h];
|
|
2138
|
+
return c[0] = c[0].toLowerCase(), d += c.join(""), a.move = c.length, d += [...r].map((g) => t[g] || g).join(""), a.regex = new RegExp(d, "i"), u.length && u.split(" ").forEach((g) => {
|
|
2139
2139
|
g && a.visemes.push(g);
|
|
2140
2140
|
}), a;
|
|
2141
2141
|
});
|
|
@@ -2270,13 +2270,13 @@ class at {
|
|
|
2270
2270
|
for (let h = 0; h < o.length; h++) {
|
|
2271
2271
|
const r = o[h];
|
|
2272
2272
|
if ((e.words.substring(0, e.i) + s.toLowerCase() + e.words.substring(e.i + 1)).match(r.regex)) {
|
|
2273
|
-
r.visemes.forEach((
|
|
2274
|
-
if (e.visemes.length && e.visemes[e.visemes.length - 1] ===
|
|
2275
|
-
const
|
|
2276
|
-
e.durations[e.durations.length - 1] +=
|
|
2273
|
+
r.visemes.forEach((d) => {
|
|
2274
|
+
if (e.visemes.length && e.visemes[e.visemes.length - 1] === d) {
|
|
2275
|
+
const c = 0.7 * (this.visemeDurations[d] || 1);
|
|
2276
|
+
e.durations[e.durations.length - 1] += c, n += c;
|
|
2277
2277
|
} else {
|
|
2278
|
-
const
|
|
2279
|
-
e.visemes.push(
|
|
2278
|
+
const c = this.visemeDurations[d] || 1;
|
|
2279
|
+
e.visemes.push(d), e.times.push(n), e.durations.push(c), n += c;
|
|
2280
2280
|
}
|
|
2281
2281
|
}), e.i += r.move, l = !0;
|
|
2282
2282
|
break;
|
|
@@ -3636,14 +3636,23 @@ class Be {
|
|
|
3636
3636
|
anims: [
|
|
3637
3637
|
{ name: "breathing", delay: 1500, dt: [1200, 500, 1e3], vs: { chestInhale: [0.5, 0.5, 0] } },
|
|
3638
3638
|
{ name: "pose", alt: [
|
|
3639
|
-
{
|
|
3639
|
+
{
|
|
3640
|
+
p: 0.5,
|
|
3641
|
+
delay: [5e3, 3e4],
|
|
3642
|
+
vs: { pose: ["side"] },
|
|
3643
|
+
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3644
|
+
},
|
|
3640
3645
|
{
|
|
3641
3646
|
p: 0.3,
|
|
3642
3647
|
delay: [5e3, 3e4],
|
|
3643
3648
|
vs: { pose: ["hip"] },
|
|
3644
3649
|
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3645
3650
|
},
|
|
3646
|
-
{
|
|
3651
|
+
{
|
|
3652
|
+
delay: [5e3, 3e4],
|
|
3653
|
+
vs: { pose: ["straight"] },
|
|
3654
|
+
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3655
|
+
}
|
|
3647
3656
|
] },
|
|
3648
3657
|
{
|
|
3649
3658
|
name: "head",
|
|
@@ -3665,12 +3674,17 @@ class Be {
|
|
|
3665
3674
|
name: "pose",
|
|
3666
3675
|
idle: {
|
|
3667
3676
|
alt: [
|
|
3668
|
-
{
|
|
3677
|
+
{
|
|
3678
|
+
p: 0.6,
|
|
3679
|
+
delay: [5e3, 3e4],
|
|
3680
|
+
vs: { pose: ["side"] },
|
|
3681
|
+
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3682
|
+
},
|
|
3669
3683
|
{
|
|
3670
3684
|
p: 0.2,
|
|
3671
3685
|
delay: [5e3, 3e4],
|
|
3672
3686
|
vs: { pose: ["hip"] },
|
|
3673
|
-
M: { delay: [5e3, 3e4], vs: { pose: ["
|
|
3687
|
+
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3674
3688
|
},
|
|
3675
3689
|
{ p: 0.1, delay: [5e3, 3e4], vs: { pose: ["straight"] } },
|
|
3676
3690
|
{ delay: [5e3, 1e4], vs: { pose: ["wide"] } },
|
|
@@ -3679,8 +3693,18 @@ class Be {
|
|
|
3679
3693
|
},
|
|
3680
3694
|
speaking: {
|
|
3681
3695
|
alt: [
|
|
3682
|
-
{
|
|
3683
|
-
|
|
3696
|
+
{
|
|
3697
|
+
p: 0.4,
|
|
3698
|
+
delay: [5e3, 3e4],
|
|
3699
|
+
vs: { pose: ["side"] },
|
|
3700
|
+
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3701
|
+
},
|
|
3702
|
+
{
|
|
3703
|
+
p: 0.4,
|
|
3704
|
+
delay: [5e3, 3e4],
|
|
3705
|
+
vs: { pose: ["straight"] },
|
|
3706
|
+
M: { delay: [5e3, 3e4], vs: { pose: ["wide"] } }
|
|
3707
|
+
},
|
|
3684
3708
|
{
|
|
3685
3709
|
delay: [5e3, 2e4],
|
|
3686
3710
|
vs: { pose: ["hip"] },
|
|
@@ -4201,15 +4225,15 @@ class Be {
|
|
|
4201
4225
|
let l = null, h = null;
|
|
4202
4226
|
for (const [r, u] of Object.entries(n))
|
|
4203
4227
|
if (s.morphTargetDictionary.hasOwnProperty(r)) {
|
|
4204
|
-
const a = s.morphTargetDictionary[r],
|
|
4205
|
-
l || (l = new x.Float32BufferAttribute(
|
|
4206
|
-
for (let g = 0; g <
|
|
4207
|
-
const y = l.getX(g) +
|
|
4228
|
+
const a = s.morphTargetDictionary[r], d = o.morphAttributes.position[a], c = o.morphAttributes.normal?.[a];
|
|
4229
|
+
l || (l = new x.Float32BufferAttribute(d.count * 3, 3), c && (h = new x.Float32BufferAttribute(d.count * 3, 3)));
|
|
4230
|
+
for (let g = 0; g < d.count; g++) {
|
|
4231
|
+
const y = l.getX(g) + d.getX(g) * u, b = l.getY(g) + d.getY(g) * u, I = l.getZ(g) + d.getZ(g) * u;
|
|
4208
4232
|
l.setXYZ(g, y, b, I);
|
|
4209
4233
|
}
|
|
4210
|
-
if (
|
|
4211
|
-
for (let g = 0; g <
|
|
4212
|
-
const y = h.getX(g) +
|
|
4234
|
+
if (c)
|
|
4235
|
+
for (let g = 0; g < d.count; g++) {
|
|
4236
|
+
const y = h.getX(g) + c.getX(g) * u, b = h.getY(g) + c.getY(g) * u, I = h.getZ(g) + c.getZ(g) * u;
|
|
4213
4237
|
h.setXYZ(g, y, b, I);
|
|
4214
4238
|
}
|
|
4215
4239
|
}
|
|
@@ -4275,8 +4299,8 @@ class Be {
|
|
|
4275
4299
|
u && ["fixed", "system", "systemd", "realtime", "base", "v", "value", "applied"].forEach((a) => {
|
|
4276
4300
|
l[r][a] = u[a];
|
|
4277
4301
|
}), this.morphs.forEach((a) => {
|
|
4278
|
-
const
|
|
4279
|
-
|
|
4302
|
+
const d = a.morphTargetDictionary[r];
|
|
4303
|
+
d !== void 0 && (l[r].ms.push(a.morphTargetInfluences), l[r].is.push(d), a.morphTargetInfluences[d] = l[r].applied);
|
|
4280
4304
|
});
|
|
4281
4305
|
}), this.mtAvatar = l, this.poseAvatar = { props: {} }, this.posePropNames.forEach((r) => {
|
|
4282
4306
|
const u = r.split("."), a = this.armature.getObjectByName(u[0]);
|
|
@@ -4975,10 +4999,10 @@ class Be {
|
|
|
4975
4999
|
if (l.alt.length > 1) {
|
|
4976
5000
|
const u = Math.random();
|
|
4977
5001
|
let a = 0;
|
|
4978
|
-
for (let
|
|
4979
|
-
let
|
|
4980
|
-
if (a +=
|
|
4981
|
-
r = l.alt[
|
|
5002
|
+
for (let d = 0; d < l.alt.length; d++) {
|
|
5003
|
+
let c = this.valueFn(l.alt[d].p);
|
|
5004
|
+
if (a += c === void 0 ? (1 - a) / (l.alt.length - 1 - d) : c, u < a) {
|
|
5005
|
+
r = l.alt[d];
|
|
4982
5006
|
break;
|
|
4983
5007
|
}
|
|
4984
5008
|
}
|
|
@@ -4999,8 +5023,8 @@ class Be {
|
|
|
4999
5023
|
}
|
|
5000
5024
|
s ? o.ts = o.ts.map((r) => h + r * n) : o.ts = o.ts.map((r) => this.animClock + h + r * n), l.vs && l.vs.pose && console.log("Pose being selected from vs.pose:", l.vs.pose, "for avatar body:", this.avatar?.body);
|
|
5001
5025
|
for (let [r, u] of Object.entries(l.vs)) {
|
|
5002
|
-
const a = this.getBaselineValue(r),
|
|
5003
|
-
r === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...
|
|
5026
|
+
const a = this.getBaselineValue(r), d = u.map((c) => (c = this.valueFn(c), c === null ? null : typeof c == "function" ? c : typeof c == "string" || c instanceof String ? r === "pose" && this.avatar && this.avatar.body === "M" && (c === "hip" || c === "side") ? (console.log("Intercepting pose", c, "in animation factory, overriding to wide for male avatar"), "wide") : c.slice() : Array.isArray(c) ? r === "gesture" ? c.slice() : (a === void 0 ? 0 : a) + i * this.gaussianRandom(...c) : typeof c == "boolean" ? c : c instanceof Object && c.constructor === Object ? Object.assign({}, c) : (a === void 0 ? 0 : a) + i * c));
|
|
5027
|
+
r === "eyesRotateY" ? (o.vs.eyeLookOutLeft = [null, ...d.map((c) => c > 0 ? c : 0)], o.vs.eyeLookInLeft = [null, ...d.map((c) => c > 0 ? 0 : -c)], o.vs.eyeLookOutRight = [null, ...d.map((c) => c > 0 ? 0 : -c)], o.vs.eyeLookInRight = [null, ...d.map((c) => c > 0 ? c : 0)]) : r === "eyesRotateX" ? (o.vs.eyesLookDown = [null, ...d.map((c) => c > 0 ? c : 0)], o.vs.eyesLookUp = [null, ...d.map((c) => c > 0 ? 0 : -c)]) : o.vs[r] = [null, ...d];
|
|
5004
5028
|
}
|
|
5005
5029
|
for (let r of Object.keys(o.vs))
|
|
5006
5030
|
for (; o.vs[r].length <= o.ts.length; ) o.vs[r].push(o.vs[r][o.vs[r].length - 1]);
|
|
@@ -5087,20 +5111,20 @@ class Be {
|
|
|
5087
5111
|
const a = this.animQueue[n];
|
|
5088
5112
|
if (!(!a || !a.ts || !a.ts.length || this.animClock < a.ts[0])) {
|
|
5089
5113
|
for (i = a.ndx || 0, o = a.ts.length; i < o && !(this.animClock < a.ts[i]); i++)
|
|
5090
|
-
for (let [
|
|
5091
|
-
if (this.mtAvatar.hasOwnProperty(
|
|
5092
|
-
if (
|
|
5093
|
-
const g = this.mtAvatar[
|
|
5094
|
-
if (
|
|
5095
|
-
g.newvalue =
|
|
5114
|
+
for (let [d, c] of Object.entries(a.vs))
|
|
5115
|
+
if (this.mtAvatar.hasOwnProperty(d)) {
|
|
5116
|
+
if (c[i + 1] === null) continue;
|
|
5117
|
+
const g = this.mtAvatar[d];
|
|
5118
|
+
if (c[i] === null && (c[i] = g.value), i === o - 1)
|
|
5119
|
+
g.newvalue = c[i];
|
|
5096
5120
|
else {
|
|
5097
|
-
g.newvalue =
|
|
5121
|
+
g.newvalue = c[i + 1];
|
|
5098
5122
|
const y = a.ts[i + 1] - a.ts[i];
|
|
5099
5123
|
let b = 1;
|
|
5100
|
-
y > 1e-4 && (b = (this.animClock - a.ts[i]) / y), b < 1 && (g.easing && (b = g.easing(b)), g.newvalue = (1 - b) *
|
|
5124
|
+
y > 1e-4 && (b = (this.animClock - a.ts[i]) / y), b < 1 && (g.easing && (b = g.easing(b)), g.newvalue = (1 - b) * c[i] + b * g.newvalue), g.ref && g.ref !== a.vs && g.ref.hasOwnProperty(d) && delete g.ref[d], g.ref = a.vs;
|
|
5101
5125
|
}
|
|
5102
5126
|
if (l)
|
|
5103
|
-
switch (
|
|
5127
|
+
switch (d) {
|
|
5104
5128
|
case "viseme_aa":
|
|
5105
5129
|
case "viseme_E":
|
|
5106
5130
|
case "viseme_I":
|
|
@@ -5109,11 +5133,11 @@ class Be {
|
|
|
5109
5133
|
g.newvalue *= 1 + l / 255 - 0.5;
|
|
5110
5134
|
}
|
|
5111
5135
|
g.needsUpdate = !0;
|
|
5112
|
-
} else
|
|
5136
|
+
} else d === "eyeContact" && c[i] !== null && h !== !1 ? h = !!c[i] : d === "headMove" && c[i] !== null && r !== !1 ? c[i] === 0 ? r = !1 : (Math.random() < c[i] && (r = !0), c[i] = null) : c[i] !== null && (u.push({ mt: d, val: c[i] }), c[i] = null);
|
|
5113
5137
|
i === o ? (a.hasOwnProperty("mood") && this.setMood(a.mood), a.loop ? (o = this.isSpeaking && (a.template.name === "head" || a.template.name === "eyes") ? 4 : 1, this.animQueue[n] = this.animFactory(a.template, a.loop > 0 ? a.loop - 1 : a.loop, 1, 1 / o)) : (this.animQueue.splice(n--, 1), s--)) : a.ndx = i - 1;
|
|
5114
5138
|
}
|
|
5115
5139
|
}
|
|
5116
|
-
for (let a = 0,
|
|
5140
|
+
for (let a = 0, d = u.length; a < d; a++)
|
|
5117
5141
|
switch (i = u[a].val, u[a].mt) {
|
|
5118
5142
|
case "speak":
|
|
5119
5143
|
this.speakText(i);
|
|
@@ -5122,7 +5146,7 @@ class Be {
|
|
|
5122
5146
|
this.onSubtitles && typeof this.onSubtitles == "function" && this.onSubtitles(i);
|
|
5123
5147
|
break;
|
|
5124
5148
|
case "pose":
|
|
5125
|
-
this.avatar && this.avatar.body === "M" && i === "hip" &&
|
|
5149
|
+
this.avatar && this.avatar.body === "M" && (i === "hip" || i === "side") && this.poseTemplates.wide && (i = "wide", console.log("Overriding pose", i === "hip" ? "hip" : "side", "to wide for male avatar")), this.poseName = i, console.log("Setting pose to:", this.poseName, "for avatar body:", this.avatar?.body, "state:", this.stateName), this.setPoseFromTemplate(this.poseTemplates[this.poseName]);
|
|
5126
5150
|
break;
|
|
5127
5151
|
case "gesture":
|
|
5128
5152
|
this.playGesture(...i);
|
|
@@ -5131,8 +5155,8 @@ class Be {
|
|
|
5131
5155
|
i && typeof i == "function" && i();
|
|
5132
5156
|
break;
|
|
5133
5157
|
case "moveto":
|
|
5134
|
-
Object.entries(i.props).forEach((
|
|
5135
|
-
|
|
5158
|
+
Object.entries(i.props).forEach((c) => {
|
|
5159
|
+
c[1] ? this.poseTarget.props[c[0]].copy(c[1]) : this.poseTarget.props[c[0]].copy(this.getPoseTemplateProp(c[0])), this.poseTarget.props[c[0]].t = this.animClock, this.poseTarget.props[c[0]].d = c[1] && c[1].d ? c[1].d : c.duration || 2e3;
|
|
5136
5160
|
});
|
|
5137
5161
|
break;
|
|
5138
5162
|
case "handLeft":
|
|
@@ -5186,8 +5210,8 @@ class Be {
|
|
|
5186
5210
|
else {
|
|
5187
5211
|
if (this.cameraClock !== null && this.cameraClock < 1e3) {
|
|
5188
5212
|
this.cameraClock += e, this.cameraClock > 1e3 && (this.cameraClock = 1e3);
|
|
5189
|
-
let a = new x.Spherical().setFromVector3(this.cameraStart),
|
|
5190
|
-
a.phi += this.easing(this.cameraClock / 1e3) * (
|
|
5213
|
+
let a = new x.Spherical().setFromVector3(this.cameraStart), d = new x.Spherical().setFromVector3(this.cameraEnd);
|
|
5214
|
+
a.phi += this.easing(this.cameraClock / 1e3) * (d.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (d.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (d.radius - a.radius), a.makeSafe(), this.camera.position.setFromSpherical(a), this.controlsStart.x !== this.controlsEnd.x ? this.controls.target.copy(this.controlsStart.lerp(this.controlsEnd, this.easing(this.cameraClock / 1e3))) : (a.setFromVector3(this.controlsStart), d.setFromVector3(this.controlsEnd), a.phi += this.easing(this.cameraClock / 1e3) * (d.phi - a.phi), a.theta += this.easing(this.cameraClock / 1e3) * (d.theta - a.theta), a.radius += this.easing(this.cameraClock / 1e3) * (d.radius - a.radius), a.makeSafe(), this.controls.target.setFromSpherical(a)), this.controls.update();
|
|
5191
5215
|
}
|
|
5192
5216
|
this.controls.autoRotate && this.controls.update(), this.stats && this.stats.end(), this.render();
|
|
5193
5217
|
}
|
|
@@ -5249,17 +5273,17 @@ class Be {
|
|
|
5249
5273
|
speakText(t, e = null, n = null, i = null) {
|
|
5250
5274
|
e = e || {};
|
|
5251
5275
|
const s = /[!\.\?\n\p{Extended_Pictographic}]/ug, o = /[ ]/ug, l = /[\p{L}\p{N},\.\p{Quotation_Mark}!€\$\+\p{Dash_Punctuation}%&\?]/ug, h = /[\p{Extended_Pictographic}]/ug, r = e.lipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang;
|
|
5252
|
-
let u = "", a = "",
|
|
5276
|
+
let u = "", a = "", d = 0, c = [], g = [];
|
|
5253
5277
|
const y = Array.from(this.segmenter.segment(t), (b) => b.segment);
|
|
5254
5278
|
for (let b = 0; b < y.length; b++) {
|
|
5255
5279
|
const I = b === y.length - 1, V = y[b].match(l);
|
|
5256
5280
|
let p = y[b].match(s);
|
|
5257
5281
|
const M = y[b].match(h), z = y[b].match(o);
|
|
5258
|
-
if (p && !I && !M && y[b + 1].match(s) && (p = !1), n && (u += y[b]), V && (!i || i.every((f) => b < f[0] || b > f[1])) && (a += y[b]), (z || p || I) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length &&
|
|
5259
|
-
mark:
|
|
5282
|
+
if (p && !I && !M && y[b + 1].match(s) && (p = !1), n && (u += y[b]), V && (!i || i.every((f) => b < f[0] || b > f[1])) && (a += y[b]), (z || p || I) && (a.length && (a = this.lipsyncPreProcessText(a, r), a.length && c.push({
|
|
5283
|
+
mark: d,
|
|
5260
5284
|
word: a
|
|
5261
5285
|
})), u.length && (g.push({
|
|
5262
|
-
mark:
|
|
5286
|
+
mark: d,
|
|
5263
5287
|
template: { name: "subtitles" },
|
|
5264
5288
|
ts: [0],
|
|
5265
5289
|
vs: {
|
|
@@ -5271,7 +5295,7 @@ class Be {
|
|
|
5271
5295
|
const E = f.times[f.visemes.length - 1] + f.durations[f.visemes.length - 1];
|
|
5272
5296
|
for (let P = 0; P < f.visemes.length; P++)
|
|
5273
5297
|
g.push({
|
|
5274
|
-
mark:
|
|
5298
|
+
mark: d,
|
|
5275
5299
|
template: { name: "viseme" },
|
|
5276
5300
|
ts: [(f.times[P] - 0.6) / E, (f.times[P] + 0.5) / E, (f.times[P] + f.durations[P] + 0.5) / E],
|
|
5277
5301
|
vs: {
|
|
@@ -5279,14 +5303,14 @@ class Be {
|
|
|
5279
5303
|
}
|
|
5280
5304
|
});
|
|
5281
5305
|
}
|
|
5282
|
-
a = "",
|
|
5306
|
+
a = "", d++;
|
|
5283
5307
|
}
|
|
5284
5308
|
if (p || I) {
|
|
5285
|
-
if (
|
|
5309
|
+
if (c.length || I && g.length) {
|
|
5286
5310
|
const f = {
|
|
5287
5311
|
anim: g
|
|
5288
5312
|
};
|
|
5289
|
-
n && (f.onSubtitles = n),
|
|
5313
|
+
n && (f.onSubtitles = n), c.length && !e.avatarMute && (f.text = c, e.avatarMood && (f.mood = e.avatarMood), e.ttsLang && (f.lang = e.ttsLang), e.ttsVoice && (f.voice = e.ttsVoice), e.ttsRate && (f.rate = e.ttsRate), e.ttsVoice && (f.pitch = e.ttsPitch), e.ttsVolume && (f.volume = e.ttsVolume)), this.speechQueue.push(f), c = [], a = "", d = 0, g = [];
|
|
5290
5314
|
}
|
|
5291
5315
|
if (M) {
|
|
5292
5316
|
let f = this.animEmojis[y[b]];
|
|
@@ -5380,18 +5404,18 @@ class Be {
|
|
|
5380
5404
|
subtitles: [" " + h]
|
|
5381
5405
|
}
|
|
5382
5406
|
}), !t.visemes)) {
|
|
5383
|
-
const a = this.lipsyncPreProcessText(h, i),
|
|
5384
|
-
if (
|
|
5385
|
-
const
|
|
5407
|
+
const a = this.lipsyncPreProcessText(h, i), d = this.lipsyncWordsToVisemes(a, i);
|
|
5408
|
+
if (d && d.visemes && d.visemes.length) {
|
|
5409
|
+
const c = d.times[d.visemes.length - 1] + d.durations[d.visemes.length - 1], g = Math.min(u, Math.max(0, u - d.visemes.length * 150));
|
|
5386
5410
|
let y = 0.6 + this.convertRange(g, [0, u], [0, 0.4]);
|
|
5387
|
-
if (u = Math.min(u,
|
|
5388
|
-
for (let b = 0; b <
|
|
5389
|
-
const I = r +
|
|
5411
|
+
if (u = Math.min(u, d.visemes.length * 200), c > 0)
|
|
5412
|
+
for (let b = 0; b < d.visemes.length; b++) {
|
|
5413
|
+
const I = r + d.times[b] / c * u, V = d.durations[b] / c * u;
|
|
5390
5414
|
o.push({
|
|
5391
5415
|
template: { name: "viseme" },
|
|
5392
5416
|
ts: [I - Math.min(60, 2 * V / 3), I + Math.min(25, V / 2), I + V + Math.min(60, V / 2)],
|
|
5393
5417
|
vs: {
|
|
5394
|
-
["viseme_" +
|
|
5418
|
+
["viseme_" + d.visemes[b]]: [null, d.visemes[b] === "PP" || d.visemes[b] === "FF" ? 0.9 : y, 0]
|
|
5395
5419
|
}
|
|
5396
5420
|
});
|
|
5397
5421
|
}
|
|
@@ -5474,20 +5498,20 @@ class Be {
|
|
|
5474
5498
|
const p = u.find((M) => M.name.includes(a) || M.lang === o);
|
|
5475
5499
|
p && (s.voice = p);
|
|
5476
5500
|
}
|
|
5477
|
-
const
|
|
5501
|
+
const d = i.length * 100 / s.rate, c = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate * (d / 1e3), this.audioCtx.sampleRate), g = this.avatar.lipsyncLang || this.opt.lipsyncLang || "en", y = this.lipsyncPreProcessText(i, g), b = this.lipsyncWordsToVisemes(y, g);
|
|
5478
5502
|
console.log("Browser TTS Lip-sync Debug:", {
|
|
5479
5503
|
text: i,
|
|
5480
5504
|
lipsyncLang: g,
|
|
5481
5505
|
processedText: y,
|
|
5482
5506
|
lipsyncData: b,
|
|
5483
5507
|
hasVisemes: b && b.visemes && b.visemes.length > 0,
|
|
5484
|
-
estimatedDuration:
|
|
5508
|
+
estimatedDuration: d
|
|
5485
5509
|
});
|
|
5486
5510
|
const I = [];
|
|
5487
5511
|
if (b && b.visemes && b.visemes.length > 0) {
|
|
5488
5512
|
const p = b.times[b.visemes.length - 1] + b.durations[b.visemes.length - 1];
|
|
5489
5513
|
for (let M = 0; M < b.visemes.length; M++) {
|
|
5490
|
-
const z = b.visemes[M], f = b.times[M] / p, E = b.durations[M] / p, P = f *
|
|
5514
|
+
const z = b.visemes[M], f = b.times[M] / p, E = b.durations[M] / p, P = f * d, U = E * d;
|
|
5491
5515
|
I.push({
|
|
5492
5516
|
template: { name: "viseme" },
|
|
5493
5517
|
ts: [P - Math.min(60, 2 * U / 3), P + Math.min(25, U / 2), P + U + Math.min(60, U / 2)],
|
|
@@ -5498,7 +5522,7 @@ class Be {
|
|
|
5498
5522
|
}
|
|
5499
5523
|
}
|
|
5500
5524
|
const V = [...t.anim, ...I];
|
|
5501
|
-
this.audioPlaylist.push({ anim: V, audio:
|
|
5525
|
+
this.audioPlaylist.push({ anim: V, audio: c }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio(), s.onend = () => {
|
|
5502
5526
|
e();
|
|
5503
5527
|
}, s.onerror = (p) => {
|
|
5504
5528
|
console.error("Speech synthesis error:", p.error), n(p.error);
|
|
@@ -5510,7 +5534,7 @@ class Be {
|
|
|
5510
5534
|
* @param {Object} line Speech line object
|
|
5511
5535
|
*/
|
|
5512
5536
|
async synthesizeWithElevenLabsTTS(t) {
|
|
5513
|
-
const e = t.text.map((
|
|
5537
|
+
const e = t.text.map((d) => d.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "21m00Tcm4TlvDq8ikWAM", i = {
|
|
5514
5538
|
text: e,
|
|
5515
5539
|
model_id: "eleven_monolingual_v1",
|
|
5516
5540
|
voice_settings: {
|
|
@@ -5540,18 +5564,18 @@ class Be {
|
|
|
5540
5564
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5541
5565
|
lipsyncLang: h
|
|
5542
5566
|
});
|
|
5543
|
-
const
|
|
5567
|
+
const d = this.lipsyncPreProcessText(e, h), c = this.lipsyncWordsToVisemes(d, h);
|
|
5544
5568
|
if (console.log("Lip-sync data:", {
|
|
5545
|
-
processedText:
|
|
5546
|
-
lipsyncData:
|
|
5547
|
-
hasVisemes:
|
|
5548
|
-
}),
|
|
5569
|
+
processedText: d,
|
|
5570
|
+
lipsyncData: c,
|
|
5571
|
+
hasVisemes: c && c.visemes && c.visemes.length > 0
|
|
5572
|
+
}), c && c.visemes && c.visemes.length > 0)
|
|
5549
5573
|
r = {
|
|
5550
|
-
visemes:
|
|
5574
|
+
visemes: c.visemes.map((g, y) => ({
|
|
5551
5575
|
viseme: g,
|
|
5552
|
-
startTime: y * l.duration /
|
|
5553
|
-
endTime: (y + 1) * l.duration /
|
|
5554
|
-
duration: l.duration /
|
|
5576
|
+
startTime: y * l.duration / c.visemes.length,
|
|
5577
|
+
endTime: (y + 1) * l.duration / c.visemes.length,
|
|
5578
|
+
duration: l.duration / c.visemes.length,
|
|
5555
5579
|
intensity: 0.7
|
|
5556
5580
|
})),
|
|
5557
5581
|
words: [],
|
|
@@ -5560,10 +5584,10 @@ class Be {
|
|
|
5560
5584
|
};
|
|
5561
5585
|
else
|
|
5562
5586
|
throw new Error("No visemes generated from text");
|
|
5563
|
-
} catch (
|
|
5564
|
-
console.error("Text-based lip-sync failed, using fallback:",
|
|
5565
|
-
const
|
|
5566
|
-
for (const y of
|
|
5587
|
+
} catch (d) {
|
|
5588
|
+
console.error("Text-based lip-sync failed, using fallback:", d);
|
|
5589
|
+
const c = e.toLowerCase().split(/\s+/), g = [];
|
|
5590
|
+
for (const y of c)
|
|
5567
5591
|
for (const b of y) {
|
|
5568
5592
|
let I = "aa";
|
|
5569
5593
|
"aeiou".includes(b) ? I = "aa" : "bp".includes(b) ? I = "PP" : "fv".includes(b) ? I = "FF" : "st".includes(b) ? I = "SS" : "dln".includes(b) ? I = "DD" : "kg".includes(b) ? I = "kk" : "rw".includes(b) && (I = "RR"), g.push(I);
|
|
@@ -5596,13 +5620,13 @@ class Be {
|
|
|
5596
5620
|
const u = [];
|
|
5597
5621
|
if (r.visemes && r.visemes.length > 0) {
|
|
5598
5622
|
console.log("ElevenLabs: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5599
|
-
for (let
|
|
5600
|
-
const
|
|
5623
|
+
for (let d = 0; d < r.visemes.length; d++) {
|
|
5624
|
+
const c = r.visemes[d], g = c.startTime * 1e3, y = c.duration * 1e3, b = c.intensity;
|
|
5601
5625
|
u.push({
|
|
5602
5626
|
template: { name: "viseme" },
|
|
5603
5627
|
ts: [g - Math.min(60, 2 * y / 3), g + Math.min(25, y / 2), g + y + Math.min(60, y / 2)],
|
|
5604
5628
|
vs: {
|
|
5605
|
-
["viseme_" +
|
|
5629
|
+
["viseme_" + c.viseme]: [null, b, 0]
|
|
5606
5630
|
}
|
|
5607
5631
|
});
|
|
5608
5632
|
}
|
|
@@ -5617,7 +5641,7 @@ class Be {
|
|
|
5617
5641
|
* @param {Object} line Speech line object
|
|
5618
5642
|
*/
|
|
5619
5643
|
async synthesizeWithDeepgramTTS(t) {
|
|
5620
|
-
const e = t.text.map((
|
|
5644
|
+
const e = t.text.map((d) => d.word).join(" "), n = t.voice || this.avatar.ttsVoice || this.opt.ttsVoice || "aura-2-thalia-en", i = `${this.opt.ttsEndpoint}?model=${n}`, s = await fetch(i, {
|
|
5621
5645
|
method: "POST",
|
|
5622
5646
|
headers: {
|
|
5623
5647
|
Authorization: `Token ${this.opt.ttsApikey}`,
|
|
@@ -5638,18 +5662,18 @@ class Be {
|
|
|
5638
5662
|
lipsyncKeys: this.lipsync ? Object.keys(this.lipsync) : [],
|
|
5639
5663
|
lipsyncLang: h
|
|
5640
5664
|
});
|
|
5641
|
-
const
|
|
5665
|
+
const d = this.lipsyncPreProcessText(e, h), c = this.lipsyncWordsToVisemes(d, h);
|
|
5642
5666
|
if (console.log("Lip-sync data:", {
|
|
5643
|
-
processedText:
|
|
5644
|
-
lipsyncData:
|
|
5645
|
-
hasVisemes:
|
|
5646
|
-
}),
|
|
5667
|
+
processedText: d,
|
|
5668
|
+
lipsyncData: c,
|
|
5669
|
+
hasVisemes: c && c.visemes && c.visemes.length > 0
|
|
5670
|
+
}), c && c.visemes && c.visemes.length > 0)
|
|
5647
5671
|
r = {
|
|
5648
|
-
visemes:
|
|
5672
|
+
visemes: c.visemes.map((g, y) => ({
|
|
5649
5673
|
viseme: g,
|
|
5650
|
-
startTime: y * l.duration /
|
|
5651
|
-
endTime: (y + 1) * l.duration /
|
|
5652
|
-
duration: l.duration /
|
|
5674
|
+
startTime: y * l.duration / c.visemes.length,
|
|
5675
|
+
endTime: (y + 1) * l.duration / c.visemes.length,
|
|
5676
|
+
duration: l.duration / c.visemes.length,
|
|
5653
5677
|
intensity: 0.7
|
|
5654
5678
|
})),
|
|
5655
5679
|
words: [],
|
|
@@ -5658,10 +5682,10 @@ class Be {
|
|
|
5658
5682
|
};
|
|
5659
5683
|
else
|
|
5660
5684
|
throw new Error("No visemes generated from text");
|
|
5661
|
-
} catch (
|
|
5662
|
-
console.error("Text-based lip-sync failed, using fallback:",
|
|
5663
|
-
const
|
|
5664
|
-
for (const y of
|
|
5685
|
+
} catch (d) {
|
|
5686
|
+
console.error("Text-based lip-sync failed, using fallback:", d);
|
|
5687
|
+
const c = e.toLowerCase().split(/\s+/), g = [];
|
|
5688
|
+
for (const y of c)
|
|
5665
5689
|
for (const b of y) {
|
|
5666
5690
|
let I = "aa";
|
|
5667
5691
|
"aeiou".includes(b) ? I = "aa" : "bp".includes(b) ? I = "PP" : "fv".includes(b) ? I = "FF" : "st".includes(b) ? I = "SS" : "dln".includes(b) ? I = "DD" : "kg".includes(b) ? I = "kk" : "rw".includes(b) && (I = "RR"), g.push(I);
|
|
@@ -5694,13 +5718,13 @@ class Be {
|
|
|
5694
5718
|
const u = [];
|
|
5695
5719
|
if (r.visemes && r.visemes.length > 0) {
|
|
5696
5720
|
console.log("Deepgram: Generating lip-sync animation from", r.visemes.length, "visemes");
|
|
5697
|
-
for (let
|
|
5698
|
-
const
|
|
5721
|
+
for (let d = 0; d < r.visemes.length; d++) {
|
|
5722
|
+
const c = r.visemes[d], g = c.startTime * 1e3, y = c.duration * 1e3, b = c.intensity;
|
|
5699
5723
|
u.push({
|
|
5700
5724
|
template: { name: "viseme" },
|
|
5701
5725
|
ts: [g - Math.min(60, 2 * y / 3), g + Math.min(25, y / 2), g + y + Math.min(60, y / 2)],
|
|
5702
5726
|
vs: {
|
|
5703
|
-
["viseme_" +
|
|
5727
|
+
["viseme_" + c.viseme]: [null, b, 0]
|
|
5704
5728
|
}
|
|
5705
5729
|
});
|
|
5706
5730
|
}
|
|
@@ -5747,12 +5771,12 @@ class Be {
|
|
|
5747
5771
|
});
|
|
5748
5772
|
const r = [];
|
|
5749
5773
|
for (let a = 0; a < h.visemes.length; a++) {
|
|
5750
|
-
const
|
|
5774
|
+
const d = h.visemes[a], c = d.startTime * 1e3, g = d.duration * 1e3, y = d.intensity;
|
|
5751
5775
|
r.push({
|
|
5752
5776
|
template: { name: "viseme" },
|
|
5753
|
-
ts: [
|
|
5777
|
+
ts: [c - Math.min(60, 2 * g / 3), c + Math.min(25, g / 2), c + g + Math.min(60, g / 2)],
|
|
5754
5778
|
vs: {
|
|
5755
|
-
["viseme_" +
|
|
5779
|
+
["viseme_" + d.viseme]: [null, y, 0]
|
|
5756
5780
|
}
|
|
5757
5781
|
});
|
|
5758
5782
|
}
|
|
@@ -5798,25 +5822,25 @@ class Be {
|
|
|
5798
5822
|
this.speakWithHands();
|
|
5799
5823
|
const h = [0];
|
|
5800
5824
|
let r = 0;
|
|
5801
|
-
t.text.forEach((
|
|
5802
|
-
if (
|
|
5825
|
+
t.text.forEach((d, c) => {
|
|
5826
|
+
if (c > 0) {
|
|
5803
5827
|
let g = h[h.length - 1];
|
|
5804
|
-
s.timepoints[r] && (g = s.timepoints[r].timeSeconds * 1e3, s.timepoints[r].markName === "" +
|
|
5828
|
+
s.timepoints[r] && (g = s.timepoints[r].timeSeconds * 1e3, s.timepoints[r].markName === "" + d.mark && r++), h.push(g);
|
|
5805
5829
|
}
|
|
5806
5830
|
});
|
|
5807
5831
|
const u = [{ mark: 0, time: 0 }];
|
|
5808
|
-
h.forEach((
|
|
5809
|
-
if (
|
|
5810
|
-
let g =
|
|
5811
|
-
u[
|
|
5832
|
+
h.forEach((d, c) => {
|
|
5833
|
+
if (c > 0) {
|
|
5834
|
+
let g = d - h[c - 1];
|
|
5835
|
+
u[c - 1].duration = g, u.push({ mark: c, time: d });
|
|
5812
5836
|
}
|
|
5813
5837
|
});
|
|
5814
5838
|
let a = 1e3 * l.duration;
|
|
5815
|
-
a > this.opt.ttsTrimEnd && (a = a - this.opt.ttsTrimEnd), u[u.length - 1].duration = a - u[u.length - 1].time, t.anim.forEach((
|
|
5816
|
-
const
|
|
5817
|
-
if (
|
|
5818
|
-
for (let g = 0; g <
|
|
5819
|
-
|
|
5839
|
+
a > this.opt.ttsTrimEnd && (a = a - this.opt.ttsTrimEnd), u[u.length - 1].duration = a - u[u.length - 1].time, t.anim.forEach((d) => {
|
|
5840
|
+
const c = u[d.mark];
|
|
5841
|
+
if (c)
|
|
5842
|
+
for (let g = 0; g < d.ts.length; g++)
|
|
5843
|
+
d.ts[g] = c.time + d.ts[g] * c.duration + this.opt.ttsTrimStart;
|
|
5820
5844
|
}), this.audioPlaylist.push({ anim: t.anim, audio: l }), this.onSubtitles = t.onSubtitles || null, this.resetLips(), t.mood && this.setMood(t.mood), this.playAudio();
|
|
5821
5845
|
} else
|
|
5822
5846
|
this.startSpeaking(!0);
|
|
@@ -6035,15 +6059,15 @@ class Be {
|
|
|
6035
6059
|
const l = this.streamLipsyncLang || this.avatar.lipsyncLang || this.opt.lipsyncLang, h = this.lipsyncPreProcessText(i, l), r = this.lipsyncWordsToVisemes(h, l);
|
|
6036
6060
|
if (r && r.visemes && r.visemes.length) {
|
|
6037
6061
|
const u = r.times[r.visemes.length - 1] + r.durations[r.visemes.length - 1], a = Math.min(o, Math.max(0, o - r.visemes.length * 150));
|
|
6038
|
-
let
|
|
6062
|
+
let d = 0.6 + this.convertRange(a, [0, o], [0, 0.4]);
|
|
6039
6063
|
if (o = Math.min(o, r.visemes.length * 200), u > 0)
|
|
6040
|
-
for (let
|
|
6041
|
-
const g = e + s + r.times[
|
|
6064
|
+
for (let c = 0; c < r.visemes.length; c++) {
|
|
6065
|
+
const g = e + s + r.times[c] / u * o, y = r.durations[c] / u * o;
|
|
6042
6066
|
this.animQueue.push({
|
|
6043
6067
|
template: { name: "viseme" },
|
|
6044
6068
|
ts: [g - Math.min(60, 2 * y / 3), g + Math.min(25, y / 2), g + y + Math.min(60, y / 2)],
|
|
6045
6069
|
vs: {
|
|
6046
|
-
["viseme_" + r.visemes[
|
|
6070
|
+
["viseme_" + r.visemes[c]]: [null, r.visemes[c] === "PP" || r.visemes[c] === "FF" ? 0.9 : d, 0]
|
|
6047
6071
|
}
|
|
6048
6072
|
});
|
|
6049
6073
|
}
|
|
@@ -6152,7 +6176,7 @@ class Be {
|
|
|
6152
6176
|
W.set(s, i, 0, "YXZ");
|
|
6153
6177
|
const l = new x.Quaternion().setFromEuler(W), h = new x.Quaternion().copy(l).multiply(Q.clone().invert());
|
|
6154
6178
|
W.setFromQuaternion(h, "YXZ");
|
|
6155
|
-
let r = W.x / (40 / 24) + 0.2, u = W.y / (9 / 4), a = Math.min(0.6, Math.max(-0.3, r)),
|
|
6179
|
+
let r = W.x / (40 / 24) + 0.2, u = W.y / (9 / 4), a = Math.min(0.6, Math.max(-0.3, r)), d = Math.min(0.8, Math.max(-0.8, u)), c = (Math.random() - 0.5) / 4, g = (Math.random() - 0.5) / 4;
|
|
6156
6180
|
if (t) {
|
|
6157
6181
|
let y = this.animQueue.findIndex((I) => I.template.name === "lookat");
|
|
6158
6182
|
y !== -1 && this.animQueue.splice(y, 1);
|
|
@@ -6160,9 +6184,9 @@ class Be {
|
|
|
6160
6184
|
name: "lookat",
|
|
6161
6185
|
dt: [750, t],
|
|
6162
6186
|
vs: {
|
|
6163
|
-
bodyRotateX: [a +
|
|
6164
|
-
bodyRotateY: [
|
|
6165
|
-
eyesRotateX: [-3 *
|
|
6187
|
+
bodyRotateX: [a + c],
|
|
6188
|
+
bodyRotateY: [d + g],
|
|
6189
|
+
eyesRotateX: [-3 * c + 0.1],
|
|
6166
6190
|
eyesRotateY: [-5 * g],
|
|
6167
6191
|
browInnerUp: [[0, 0.7]],
|
|
6168
6192
|
mouthLeft: [[0, 0.7]],
|
|
@@ -6188,7 +6212,7 @@ class Be {
|
|
|
6188
6212
|
l.project(this.camera);
|
|
6189
6213
|
let h = (l.x + 1) / 2 * i.width + i.left, r = -(l.y - 1) / 2 * i.height + i.top;
|
|
6190
6214
|
t === null && (t = h), e === null && (e = r), Q.copy(this.armature.quaternion), Q.multiply(this.poseTarget.props["Hips.quaternion"]), Q.multiply(this.poseTarget.props["Spine.quaternion"]), Q.multiply(this.poseTarget.props["Spine1.quaternion"]), Q.multiply(this.poseTarget.props["Spine2.quaternion"]), Q.multiply(this.poseTarget.props["Neck.quaternion"]), Q.multiply(this.poseTarget.props["Head.quaternion"]), W.setFromQuaternion(Q);
|
|
6191
|
-
let u = W.x / (40 / 24), a = W.y / (9 / 4),
|
|
6215
|
+
let u = W.x / (40 / 24), a = W.y / (9 / 4), d = Math.min(0.4, Math.max(-0.4, this.camera.rotation.x)), c = Math.min(0.4, Math.max(-0.4, this.camera.rotation.y)), g = Math.max(window.innerWidth - h, h), y = Math.max(window.innerHeight - r, r), b = this.convertRange(e, [r - y, r + y], [-0.3, 0.6]) - u + d, I = this.convertRange(t, [h - g, h + g], [-0.8, 0.8]) - a + c;
|
|
6192
6216
|
b = Math.min(0.6, Math.max(-0.3, b)), I = Math.min(0.8, Math.max(-0.8, I));
|
|
6193
6217
|
let V = (Math.random() - 0.5) / 4, p = (Math.random() - 0.5) / 4;
|
|
6194
6218
|
if (n) {
|
|
@@ -6396,58 +6420,58 @@ class Be {
|
|
|
6396
6420
|
}
|
|
6397
6421
|
let r = !1;
|
|
6398
6422
|
try {
|
|
6399
|
-
const
|
|
6400
|
-
if (r =
|
|
6401
|
-
console.error(`FBX file not found at ${t}. Status: ${
|
|
6423
|
+
const d = await fetch(t, { method: "HEAD" });
|
|
6424
|
+
if (r = d.ok, !r) {
|
|
6425
|
+
console.error(`FBX file not found at ${t}. Status: ${d.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)");
|
|
6402
6426
|
return;
|
|
6403
6427
|
}
|
|
6404
|
-
} catch (
|
|
6405
|
-
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`,
|
|
6428
|
+
} catch (d) {
|
|
6429
|
+
console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, d);
|
|
6406
6430
|
}
|
|
6407
6431
|
const u = new De();
|
|
6408
6432
|
let a;
|
|
6409
6433
|
try {
|
|
6410
6434
|
a = await u.loadAsync(t, e);
|
|
6411
|
-
} catch (
|
|
6412
|
-
console.error(`Failed to load FBX animation from ${t}:`,
|
|
6413
|
-
message:
|
|
6435
|
+
} catch (d) {
|
|
6436
|
+
console.error(`Failed to load FBX animation from ${t}:`, d), console.error("Error details:", {
|
|
6437
|
+
message: d.message,
|
|
6414
6438
|
url: t,
|
|
6415
6439
|
suggestion: "Make sure the file is a valid FBX file and the path is correct"
|
|
6416
|
-
}),
|
|
6440
|
+
}), d.message && d.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"));
|
|
6417
6441
|
try {
|
|
6418
|
-
const
|
|
6442
|
+
const c = await fetch(t), g = c.headers.get("content-type"), y = await c.text();
|
|
6419
6443
|
console.error("Response details:", {
|
|
6420
|
-
status:
|
|
6444
|
+
status: c.status,
|
|
6421
6445
|
contentType: g,
|
|
6422
6446
|
firstBytes: y.substring(0, 100),
|
|
6423
6447
|
isHTML: y.trim().startsWith("<!DOCTYPE") || y.trim().startsWith("<html")
|
|
6424
6448
|
}), (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.");
|
|
6425
|
-
} catch (
|
|
6426
|
-
console.error("Could not fetch file for debugging:",
|
|
6449
|
+
} catch (c) {
|
|
6450
|
+
console.error("Could not fetch file for debugging:", c);
|
|
6427
6451
|
}
|
|
6428
6452
|
return;
|
|
6429
6453
|
}
|
|
6430
6454
|
if (a && a.animations && a.animations[i]) {
|
|
6431
|
-
let
|
|
6432
|
-
const
|
|
6433
|
-
|
|
6455
|
+
let d = a.animations[i];
|
|
6456
|
+
const c = {};
|
|
6457
|
+
d.tracks.forEach((y) => {
|
|
6434
6458
|
y.name = y.name.replaceAll("mixamorig", "");
|
|
6435
6459
|
const b = y.name.split(".");
|
|
6436
6460
|
if (b[1] === "position") {
|
|
6437
6461
|
for (let I = 0; I < y.values.length; I++)
|
|
6438
6462
|
y.values[I] = y.values[I] * s;
|
|
6439
|
-
|
|
6440
|
-
} else b[1] === "quaternion" ?
|
|
6463
|
+
c[y.name] = new x.Vector3(y.values[0], y.values[1], y.values[2]);
|
|
6464
|
+
} else b[1] === "quaternion" ? c[y.name] = new x.Quaternion(y.values[0], y.values[1], y.values[2], y.values[3]) : b[1] === "rotation" && (c[b[0] + ".quaternion"] = new x.Quaternion().setFromEuler(new x.Euler(y.values[0], y.values[1], y.values[2], "XYZ")).normalize());
|
|
6441
6465
|
});
|
|
6442
|
-
const g = { props:
|
|
6443
|
-
|
|
6466
|
+
const g = { props: c };
|
|
6467
|
+
c["Hips.position"] && (c["Hips.position"].y < 0.5 ? g.lying = !0 : g.standing = !0), this.animClips.push({
|
|
6444
6468
|
url: t + "-" + i,
|
|
6445
|
-
clip:
|
|
6469
|
+
clip: d,
|
|
6446
6470
|
pose: g
|
|
6447
6471
|
}), this.playAnimation(t, e, n, i, s);
|
|
6448
6472
|
} else {
|
|
6449
|
-
const
|
|
6450
|
-
console.error(
|
|
6473
|
+
const d = "Animation " + t + " (ndx=" + i + ") not found";
|
|
6474
|
+
console.error(d), a && a.animations ? console.error(`FBX file loaded but has ${a.animations.length} animation(s), requested index ${i}`) : console.error(a ? "FBX file loaded but contains no animations" : "FBX file failed to load or is invalid");
|
|
6451
6475
|
}
|
|
6452
6476
|
}
|
|
6453
6477
|
}
|
|
@@ -6485,10 +6509,10 @@ class Be {
|
|
|
6485
6509
|
if (h && h.animations && h.animations[i]) {
|
|
6486
6510
|
let r = h.animations[i];
|
|
6487
6511
|
const u = {};
|
|
6488
|
-
r.tracks.forEach((
|
|
6489
|
-
|
|
6490
|
-
const
|
|
6491
|
-
|
|
6512
|
+
r.tracks.forEach((d) => {
|
|
6513
|
+
d.name = d.name.replaceAll("mixamorig", "");
|
|
6514
|
+
const c = d.name.split(".");
|
|
6515
|
+
c[1] === "position" ? u[d.name] = new x.Vector3(d.values[0] * s, d.values[1] * s, d.values[2] * s) : c[1] === "quaternion" ? u[d.name] = new x.Quaternion(d.values[0], d.values[1], d.values[2], d.values[3]) : c[1] === "rotation" && (u[c[0] + ".quaternion"] = new x.Quaternion().setFromEuler(new x.Euler(d.values[0], d.values[1], d.values[2], "XYZ")).normalize());
|
|
6492
6516
|
});
|
|
6493
6517
|
const a = { props: u };
|
|
6494
6518
|
u["Hips.position"] && (u["Hips.position"].y < 0.5 ? a.lying = !0 : a.standing = !0), this.animPoses.push({
|
|
@@ -6533,13 +6557,13 @@ class Be {
|
|
|
6533
6557
|
if (l.gesture = !0, e && Number.isFinite(e)) {
|
|
6534
6558
|
const h = l.ts[0], u = l.ts[l.ts.length - 1] - h;
|
|
6535
6559
|
if (e * 1e3 - u > 0) {
|
|
6536
|
-
const
|
|
6537
|
-
for (let y = 1; y < l.ts.length; y++)
|
|
6538
|
-
const
|
|
6539
|
-
l.ts = l.ts.map((y, b, I) => b === 0 ? h : I[b - 1] +
|
|
6560
|
+
const d = [];
|
|
6561
|
+
for (let y = 1; y < l.ts.length; y++) d.push(l.ts[y] - l.ts[y - 1]);
|
|
6562
|
+
const c = o.template?.rescale || d.map((y) => y / u), g = e * 1e3 - u;
|
|
6563
|
+
l.ts = l.ts.map((y, b, I) => b === 0 ? h : I[b - 1] + d[b - 1] + c[b - 1] * g);
|
|
6540
6564
|
} else {
|
|
6541
|
-
const
|
|
6542
|
-
l.ts = l.ts.map((
|
|
6565
|
+
const d = e * 1e3 / u;
|
|
6566
|
+
l.ts = l.ts.map((c) => h + d * (c - h));
|
|
6543
6567
|
}
|
|
6544
6568
|
}
|
|
6545
6569
|
this.animQueue.push(l);
|
|
@@ -6569,12 +6593,12 @@ class Be {
|
|
|
6569
6593
|
* @param {numeric} [d=null] If set, apply in d milliseconds
|
|
6570
6594
|
*/
|
|
6571
6595
|
ikSolve(t, e = null, n = !1, i = null) {
|
|
6572
|
-
const s = new x.Vector3(), o = new x.Vector3(), l = new x.Vector3(), h = new x.Vector3(), r = new x.Quaternion(), u = new x.Vector3(), a = new x.Vector3(),
|
|
6573
|
-
|
|
6596
|
+
const s = new x.Vector3(), o = new x.Vector3(), l = new x.Vector3(), h = new x.Vector3(), r = new x.Quaternion(), u = new x.Vector3(), a = new x.Vector3(), d = new x.Vector3(), c = this.ikMesh.getObjectByName(t.root);
|
|
6597
|
+
c.position.setFromMatrixPosition(this.armature.getObjectByName(t.root).matrixWorld), c.quaternion.setFromRotationMatrix(this.armature.getObjectByName(t.root).matrixWorld), e && n && e.applyQuaternion(this.armature.quaternion).add(c.position);
|
|
6574
6598
|
const g = this.ikMesh.getObjectByName(t.effector), y = t.links;
|
|
6575
6599
|
y.forEach((I) => {
|
|
6576
6600
|
I.bone = this.ikMesh.getObjectByName(I.link), I.bone.quaternion.copy(this.getPoseTemplateProp(I.link + ".quaternion"));
|
|
6577
|
-
}),
|
|
6601
|
+
}), c.updateMatrixWorld(!0);
|
|
6578
6602
|
const b = t.iterations || 10;
|
|
6579
6603
|
if (e)
|
|
6580
6604
|
for (let I = 0; I < b; I++) {
|
|
@@ -6583,7 +6607,7 @@ class Be {
|
|
|
6583
6607
|
const z = y[p].bone;
|
|
6584
6608
|
z.matrixWorld.decompose(h, r, u), r.invert(), o.setFromMatrixPosition(g.matrixWorld), l.subVectors(o, h), l.applyQuaternion(r), l.normalize(), s.subVectors(e, h), s.applyQuaternion(r), s.normalize();
|
|
6585
6609
|
let f = s.dot(l);
|
|
6586
|
-
f > 1 ? f = 1 : f < -1 && (f = -1), f = Math.acos(f), !(f < 1e-5) && (y[p].minAngle !== void 0 && f < y[p].minAngle && (f = y[p].minAngle), y[p].maxAngle !== void 0 && f > y[p].maxAngle && (f = y[p].maxAngle), a.crossVectors(l, s), a.normalize(), Q.setFromAxisAngle(a, f), z.quaternion.multiply(Q), z.rotation.setFromVector3(
|
|
6610
|
+
f > 1 ? f = 1 : f < -1 && (f = -1), f = Math.acos(f), !(f < 1e-5) && (y[p].minAngle !== void 0 && f < y[p].minAngle && (f = y[p].minAngle), y[p].maxAngle !== void 0 && f > y[p].maxAngle && (f = y[p].maxAngle), a.crossVectors(l, s), a.normalize(), Q.setFromAxisAngle(a, f), z.quaternion.multiply(Q), z.rotation.setFromVector3(d.setFromEuler(z.rotation).clamp(new x.Vector3(
|
|
6587
6611
|
y[p].minx !== void 0 ? y[p].minx : -1 / 0,
|
|
6588
6612
|
y[p].miny !== void 0 ? y[p].miny : -1 / 0,
|
|
6589
6613
|
y[p].minz !== void 0 ? y[p].minz : -1 / 0
|
|
@@ -6678,9 +6702,9 @@ const Ve = Me(({
|
|
|
6678
6702
|
cameraView: u = "upper",
|
|
6679
6703
|
onReady: a = () => {
|
|
6680
6704
|
},
|
|
6681
|
-
onLoading:
|
|
6705
|
+
onLoading: d = () => {
|
|
6682
6706
|
},
|
|
6683
|
-
onError:
|
|
6707
|
+
onError: c = () => {
|
|
6684
6708
|
},
|
|
6685
6709
|
className: g = "",
|
|
6686
6710
|
style: y = {},
|
|
@@ -6738,7 +6762,7 @@ const Ve = Me(({
|
|
|
6738
6762
|
if (Z(!0), X(null), p.current = new Be(V.current, R), p.current.controls && (p.current.controls.enableRotate = !1, p.current.controls.enableZoom = !1, p.current.controls.enablePan = !1, p.current.controls.enableDamping = !1), b && Object.keys(b).length > 0 && (p.current.customAnimations = b), await p.current.showAvatar(v, (B) => {
|
|
6739
6763
|
if (B.lengthComputable) {
|
|
6740
6764
|
const J = Math.min(100, Math.round(B.loaded / B.total * 100));
|
|
6741
|
-
|
|
6765
|
+
d(J);
|
|
6742
6766
|
}
|
|
6743
6767
|
}), await new Promise((B) => {
|
|
6744
6768
|
const J = () => {
|
|
@@ -6759,7 +6783,7 @@ const Ve = Me(({
|
|
|
6759
6783
|
document.removeEventListener("visibilitychange", F);
|
|
6760
6784
|
};
|
|
6761
6785
|
} catch (L) {
|
|
6762
|
-
console.error("Error initializing TalkingHead:", L), X(L.message || "Failed to initialize avatar"), Z(!1),
|
|
6786
|
+
console.error("Error initializing TalkingHead:", L), X(L.message || "Failed to initialize avatar"), Z(!1), c(L);
|
|
6763
6787
|
}
|
|
6764
6788
|
}, [G, t, e, n, i, s, o, r, l, h, u]);
|
|
6765
6789
|
de(() => (k(), () => {
|
|
@@ -7053,7 +7077,7 @@ const pt = Me(({
|
|
|
7053
7077
|
style: s = {},
|
|
7054
7078
|
avatarConfig: o = {}
|
|
7055
7079
|
}, l) => {
|
|
7056
|
-
const h = O(null), r = O(null), [u, a] = ce(!0), [
|
|
7080
|
+
const h = O(null), r = O(null), [u, a] = ce(!0), [d, c] = ce(null), [g, y] = ce(!1), b = Fe(), I = o.ttsService || b.service, V = I === "browser" ? {
|
|
7057
7081
|
endpoint: "",
|
|
7058
7082
|
apiKey: null,
|
|
7059
7083
|
defaultVoice: "Google US English"
|
|
@@ -7086,7 +7110,7 @@ const pt = Me(({
|
|
|
7086
7110
|
}, z = T(async () => {
|
|
7087
7111
|
if (!(!h.current || r.current))
|
|
7088
7112
|
try {
|
|
7089
|
-
if (a(!0),
|
|
7113
|
+
if (a(!0), c(null), r.current = new Be(h.current, M), await r.current.showAvatar(p, (K) => {
|
|
7090
7114
|
if (K.lengthComputable) {
|
|
7091
7115
|
const X = Math.min(100, Math.round(K.loaded / K.total * 100));
|
|
7092
7116
|
t(X);
|
|
@@ -7116,7 +7140,7 @@ const pt = Me(({
|
|
|
7116
7140
|
document.removeEventListener("visibilitychange", Z);
|
|
7117
7141
|
};
|
|
7118
7142
|
} catch (S) {
|
|
7119
|
-
console.error("Error initializing TalkingHead:", S),
|
|
7143
|
+
console.error("Error initializing TalkingHead:", S), c(S.message || "Failed to initialize avatar"), a(!1), e(S);
|
|
7120
7144
|
}
|
|
7121
7145
|
}, []);
|
|
7122
7146
|
de(() => (z(), () => {
|
|
@@ -7129,7 +7153,7 @@ const pt = Me(({
|
|
|
7129
7153
|
r.current && r.current.lipsync ? (console.log("Lip-sync now ready, speaking..."), r.current.setSlowdownRate && (r.current.setSlowdownRate(1.05), console.log("Applied timing adjustment for better lip-sync")), r.current.speakText(S)) : console.error("Lip-sync still not ready after waiting");
|
|
7130
7154
|
}, 500));
|
|
7131
7155
|
} catch (Z) {
|
|
7132
|
-
console.error("Error speaking text:", Z),
|
|
7156
|
+
console.error("Error speaking text:", Z), c(Z.message || "Failed to speak text");
|
|
7133
7157
|
}
|
|
7134
7158
|
else
|
|
7135
7159
|
console.warn("Avatar not ready for speaking. isReady:", g, "talkingHeadRef:", !!r.current);
|
|
@@ -7267,7 +7291,7 @@ const pt = Me(({
|
|
|
7267
7291
|
fontSize: "18px",
|
|
7268
7292
|
zIndex: 10
|
|
7269
7293
|
}, children: "Loading avatar..." }),
|
|
7270
|
-
|
|
7294
|
+
d && /* @__PURE__ */ me("div", { className: "error-overlay", style: {
|
|
7271
7295
|
position: "absolute",
|
|
7272
7296
|
top: "50%",
|
|
7273
7297
|
left: "50%",
|
|
@@ -7278,7 +7302,7 @@ const pt = Me(({
|
|
|
7278
7302
|
zIndex: 10,
|
|
7279
7303
|
padding: "20px",
|
|
7280
7304
|
borderRadius: "8px"
|
|
7281
|
-
}, children:
|
|
7305
|
+
}, children: d })
|
|
7282
7306
|
] });
|
|
7283
7307
|
});
|
|
7284
7308
|
pt.displayName = "TalkingHeadComponent";
|
|
@@ -7295,9 +7319,9 @@ const gt = Me(({
|
|
|
7295
7319
|
movementIntensity: r = 0.5,
|
|
7296
7320
|
showFullAvatar: u = !1,
|
|
7297
7321
|
cameraView: a = "upper",
|
|
7298
|
-
onReady:
|
|
7322
|
+
onReady: d = () => {
|
|
7299
7323
|
},
|
|
7300
|
-
onLoading:
|
|
7324
|
+
onLoading: c = () => {
|
|
7301
7325
|
},
|
|
7302
7326
|
onError: g = () => {
|
|
7303
7327
|
},
|
|
@@ -7363,9 +7387,9 @@ const gt = Me(({
|
|
|
7363
7387
|
}), await f.current.showAvatar(k, (te) => {
|
|
7364
7388
|
if (te.lengthComputable) {
|
|
7365
7389
|
const L = Math.min(100, Math.round(te.loaded / te.total * 100));
|
|
7366
|
-
|
|
7390
|
+
c(L);
|
|
7367
7391
|
}
|
|
7368
|
-
}), f.current?.avatar && console.log("Avatar body after initialization:", f.current.avatar.body), X(!1), pe(!0),
|
|
7392
|
+
}), f.current?.avatar && console.log("Avatar body after initialization:", f.current.avatar.body), X(!1), pe(!0), d(f.current);
|
|
7369
7393
|
const C = () => {
|
|
7370
7394
|
document.visibilityState === "visible" ? f.current?.start() : f.current?.stop();
|
|
7371
7395
|
};
|
|
@@ -7526,13 +7550,13 @@ const yt = Me(({
|
|
|
7526
7550
|
curriculumCompleted: !1,
|
|
7527
7551
|
score: 0,
|
|
7528
7552
|
totalQuestions: 0
|
|
7529
|
-
}),
|
|
7553
|
+
}), d = O({
|
|
7530
7554
|
onLessonStart: n,
|
|
7531
7555
|
onLessonComplete: i,
|
|
7532
7556
|
onQuestionAnswer: s,
|
|
7533
7557
|
onCurriculumComplete: o,
|
|
7534
7558
|
onCustomAction: l
|
|
7535
|
-
}),
|
|
7559
|
+
}), c = O(null), g = O(null), y = O(null), b = O(null), I = O(null), V = O(null), p = O(null), M = O(G?.curriculum || {
|
|
7536
7560
|
title: "Default Curriculum",
|
|
7537
7561
|
description: "No curriculum data provided",
|
|
7538
7562
|
language: "en",
|
|
@@ -7552,7 +7576,7 @@ const yt = Me(({
|
|
|
7552
7576
|
lipsyncLang: "en"
|
|
7553
7577
|
});
|
|
7554
7578
|
de(() => {
|
|
7555
|
-
|
|
7579
|
+
d.current = {
|
|
7556
7580
|
onLessonStart: n,
|
|
7557
7581
|
onLessonComplete: i,
|
|
7558
7582
|
onQuestionAnswer: s,
|
|
@@ -7584,13 +7608,13 @@ const yt = Me(({
|
|
|
7584
7608
|
a.current.lessonCompleted = !0, a.current.isQuestionMode = !1;
|
|
7585
7609
|
const v = a.current.totalQuestions > 0 ? Math.round(a.current.score / a.current.totalQuestions * 100) : 100;
|
|
7586
7610
|
let R = "Congratulations! You've completed this lesson";
|
|
7587
|
-
if (a.current.totalQuestions > 0 ? R += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${v} percent. ` : R += "! ", v >= 80 ? R += "Excellent work! You have a great understanding of this topic." : v >= 60 ? R += "Good job! You understand most of the concepts." : R += "Keep practicing! You're making progress.",
|
|
7611
|
+
if (a.current.totalQuestions > 0 ? R += ` You got ${a.current.score} correct out of ${a.current.totalQuestions} question${a.current.totalQuestions === 1 ? "" : "s"}, achieving a score of ${v} percent. ` : R += "! ", v >= 80 ? R += "Excellent work! You have a great understanding of this topic." : v >= 60 ? R += "Good job! You understand most of the concepts." : R += "Keep practicing! You're making progress.", d.current.onLessonComplete({
|
|
7588
7612
|
moduleIndex: a.current.currentModuleIndex,
|
|
7589
7613
|
lessonIndex: a.current.currentLessonIndex,
|
|
7590
7614
|
score: a.current.score,
|
|
7591
7615
|
totalQuestions: a.current.totalQuestions,
|
|
7592
7616
|
percentage: v
|
|
7593
|
-
}),
|
|
7617
|
+
}), d.current.onCustomAction({
|
|
7594
7618
|
type: "lessonComplete",
|
|
7595
7619
|
moduleIndex: a.current.currentModuleIndex,
|
|
7596
7620
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7608,7 +7632,7 @@ const yt = Me(({
|
|
|
7608
7632
|
u.current.speakText(R, {
|
|
7609
7633
|
lipsyncLang: q.lipsyncLang,
|
|
7610
7634
|
onSpeechEnd: () => {
|
|
7611
|
-
|
|
7635
|
+
d.current.onCustomAction({
|
|
7612
7636
|
type: "lessonCompleteFeedbackDone",
|
|
7613
7637
|
moduleIndex: a.current.currentModuleIndex,
|
|
7614
7638
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7623,7 +7647,7 @@ const yt = Me(({
|
|
|
7623
7647
|
}, [e.lessonComplete]), oe = T(() => {
|
|
7624
7648
|
a.current.curriculumCompleted = !0;
|
|
7625
7649
|
const v = M.current || { modules: [] };
|
|
7626
|
-
if (
|
|
7650
|
+
if (d.current.onCurriculumComplete({
|
|
7627
7651
|
modules: v.modules.length,
|
|
7628
7652
|
totalLessons: v.modules.reduce((R, k) => R + k.lessons.length, 0)
|
|
7629
7653
|
}), u.current) {
|
|
@@ -7640,7 +7664,7 @@ const yt = Me(({
|
|
|
7640
7664
|
const v = f();
|
|
7641
7665
|
a.current.isQuestionMode = !0, a.current.currentQuestionIndex = 0, a.current.totalQuestions = v?.questions?.length || 0, a.current.score = 0;
|
|
7642
7666
|
const R = E();
|
|
7643
|
-
R &&
|
|
7667
|
+
R && d.current.onCustomAction({
|
|
7644
7668
|
type: "questionStart",
|
|
7645
7669
|
moduleIndex: a.current.currentModuleIndex,
|
|
7646
7670
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7678,7 +7702,7 @@ const yt = Me(({
|
|
|
7678
7702
|
if (a.current.currentQuestionIndex < (v?.questions?.length || 0) - 1) {
|
|
7679
7703
|
u.current && u.current.stopSpeaking && u.current.stopSpeaking(), a.current.currentQuestionIndex += 1;
|
|
7680
7704
|
const R = E();
|
|
7681
|
-
R &&
|
|
7705
|
+
R && d.current.onCustomAction({
|
|
7682
7706
|
type: "nextQuestion",
|
|
7683
7707
|
moduleIndex: a.current.currentModuleIndex,
|
|
7684
7708
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7729,7 +7753,7 @@ const yt = Me(({
|
|
|
7729
7753
|
}, 5e3);
|
|
7730
7754
|
}
|
|
7731
7755
|
} else
|
|
7732
|
-
|
|
7756
|
+
d.current.onCustomAction({
|
|
7733
7757
|
type: "allQuestionsComplete",
|
|
7734
7758
|
moduleIndex: a.current.currentModuleIndex,
|
|
7735
7759
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7741,12 +7765,12 @@ const yt = Me(({
|
|
|
7741
7765
|
if (a.current.currentLessonIndex < (R?.lessons?.length || 0) - 1) {
|
|
7742
7766
|
a.current.currentLessonIndex += 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0;
|
|
7743
7767
|
const H = v.modules[a.current.currentModuleIndex], N = a.current.currentLessonIndex < (H?.lessons?.length || 0) - 1, _ = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, j = N || _;
|
|
7744
|
-
|
|
7768
|
+
d.current.onCustomAction({
|
|
7745
7769
|
type: "lessonStart",
|
|
7746
7770
|
moduleIndex: a.current.currentModuleIndex,
|
|
7747
7771
|
lessonIndex: a.current.currentLessonIndex,
|
|
7748
7772
|
hasNextLesson: j
|
|
7749
|
-
}),
|
|
7773
|
+
}), d.current.onLessonStart({
|
|
7750
7774
|
moduleIndex: a.current.currentModuleIndex,
|
|
7751
7775
|
lessonIndex: a.current.currentLessonIndex,
|
|
7752
7776
|
lesson: f()
|
|
@@ -7754,12 +7778,12 @@ const yt = Me(({
|
|
|
7754
7778
|
} else if (a.current.currentModuleIndex < (v.modules?.length || 0) - 1) {
|
|
7755
7779
|
a.current.currentModuleIndex += 1, a.current.currentLessonIndex = 0, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0;
|
|
7756
7780
|
const N = v.modules[a.current.currentModuleIndex], _ = a.current.currentLessonIndex < (N?.lessons?.length || 0) - 1, j = a.current.currentModuleIndex < (v.modules?.length || 0) - 1, q = _ || j;
|
|
7757
|
-
|
|
7781
|
+
d.current.onCustomAction({
|
|
7758
7782
|
type: "lessonStart",
|
|
7759
7783
|
moduleIndex: a.current.currentModuleIndex,
|
|
7760
7784
|
lessonIndex: a.current.currentLessonIndex,
|
|
7761
7785
|
hasNextLesson: q
|
|
7762
|
-
}),
|
|
7786
|
+
}), d.current.onLessonStart({
|
|
7763
7787
|
moduleIndex: a.current.currentModuleIndex,
|
|
7764
7788
|
lessonIndex: a.current.currentLessonIndex,
|
|
7765
7789
|
lesson: f()
|
|
@@ -7785,11 +7809,11 @@ const yt = Me(({
|
|
|
7785
7809
|
}
|
|
7786
7810
|
k || u.current.setBodyMovement("gesturing");
|
|
7787
7811
|
const H = z.current || { lipsyncLang: "en" };
|
|
7788
|
-
|
|
7812
|
+
d.current.onLessonStart({
|
|
7789
7813
|
moduleIndex: a.current.currentModuleIndex,
|
|
7790
7814
|
lessonIndex: a.current.currentLessonIndex,
|
|
7791
7815
|
lesson: v
|
|
7792
|
-
}),
|
|
7816
|
+
}), d.current.onCustomAction({
|
|
7793
7817
|
type: "teachingStart",
|
|
7794
7818
|
moduleIndex: a.current.currentModuleIndex,
|
|
7795
7819
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7797,13 +7821,13 @@ const yt = Me(({
|
|
|
7797
7821
|
}), u.current.speakText(R, {
|
|
7798
7822
|
lipsyncLang: H.lipsyncLang,
|
|
7799
7823
|
onSpeechEnd: () => {
|
|
7800
|
-
a.current.isTeaching = !1,
|
|
7824
|
+
a.current.isTeaching = !1, d.current.onCustomAction({
|
|
7801
7825
|
type: "teachingComplete",
|
|
7802
7826
|
moduleIndex: a.current.currentModuleIndex,
|
|
7803
7827
|
lessonIndex: a.current.currentLessonIndex,
|
|
7804
7828
|
lesson: v,
|
|
7805
7829
|
hasQuestions: v.questions && v.questions.length > 0
|
|
7806
|
-
}), v?.code_example &&
|
|
7830
|
+
}), v?.code_example && d.current.onCustomAction({
|
|
7807
7831
|
type: "codeExampleReady",
|
|
7808
7832
|
moduleIndex: a.current.currentModuleIndex,
|
|
7809
7833
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7815,7 +7839,7 @@ const yt = Me(({
|
|
|
7815
7839
|
}
|
|
7816
7840
|
}, [e.teaching, f]), $ = T((v) => {
|
|
7817
7841
|
const R = E(), k = P(v, R);
|
|
7818
|
-
if (k && (a.current.score += 1),
|
|
7842
|
+
if (k && (a.current.score += 1), d.current.onQuestionAnswer({
|
|
7819
7843
|
moduleIndex: a.current.currentModuleIndex,
|
|
7820
7844
|
lessonIndex: a.current.currentLessonIndex,
|
|
7821
7845
|
questionIndex: a.current.currentQuestionIndex,
|
|
@@ -7839,7 +7863,7 @@ const yt = Me(({
|
|
|
7839
7863
|
u.current.speakText(j, {
|
|
7840
7864
|
lipsyncLang: q.lipsyncLang,
|
|
7841
7865
|
onSpeechEnd: () => {
|
|
7842
|
-
|
|
7866
|
+
d.current.onCustomAction({
|
|
7843
7867
|
type: "answerFeedbackComplete",
|
|
7844
7868
|
moduleIndex: a.current.currentModuleIndex,
|
|
7845
7869
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7865,7 +7889,7 @@ const yt = Me(({
|
|
|
7865
7889
|
u.current.speakText(q, {
|
|
7866
7890
|
lipsyncLang: Le.lipsyncLang,
|
|
7867
7891
|
onSpeechEnd: () => {
|
|
7868
|
-
|
|
7892
|
+
d.current.onCustomAction({
|
|
7869
7893
|
type: "answerFeedbackComplete",
|
|
7870
7894
|
moduleIndex: a.current.currentModuleIndex,
|
|
7871
7895
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7880,7 +7904,7 @@ const yt = Me(({
|
|
|
7880
7904
|
}
|
|
7881
7905
|
else {
|
|
7882
7906
|
const N = f()?.questions?.length || 0;
|
|
7883
|
-
|
|
7907
|
+
d.current.onCustomAction({
|
|
7884
7908
|
type: "answerFeedbackComplete",
|
|
7885
7909
|
moduleIndex: a.current.currentModuleIndex,
|
|
7886
7910
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7912,7 +7936,7 @@ const yt = Me(({
|
|
|
7912
7936
|
passedCount: v.passedCount || 0,
|
|
7913
7937
|
failedCount: v.failedCount || 0
|
|
7914
7938
|
};
|
|
7915
|
-
|
|
7939
|
+
d.current.onCustomAction({
|
|
7916
7940
|
type: "codeTestSubmitted",
|
|
7917
7941
|
moduleIndex: a.current.currentModuleIndex,
|
|
7918
7942
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7924,7 +7948,7 @@ const yt = Me(({
|
|
|
7924
7948
|
if (a.current.currentQuestionIndex > 0) {
|
|
7925
7949
|
a.current.currentQuestionIndex -= 1;
|
|
7926
7950
|
const v = E();
|
|
7927
|
-
v &&
|
|
7951
|
+
v && d.current.onCustomAction({
|
|
7928
7952
|
type: "questionStart",
|
|
7929
7953
|
moduleIndex: a.current.currentModuleIndex,
|
|
7930
7954
|
lessonIndex: a.current.currentLessonIndex,
|
|
@@ -7957,22 +7981,22 @@ const yt = Me(({
|
|
|
7957
7981
|
}, [E]), pe = T(() => {
|
|
7958
7982
|
const v = M.current || { modules: [] };
|
|
7959
7983
|
if (v.modules[a.current.currentModuleIndex], a.current.currentLessonIndex > 0)
|
|
7960
|
-
a.current.currentLessonIndex -= 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0,
|
|
7984
|
+
a.current.currentLessonIndex -= 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, d.current.onCustomAction({
|
|
7961
7985
|
type: "lessonStart",
|
|
7962
7986
|
moduleIndex: a.current.currentModuleIndex,
|
|
7963
7987
|
lessonIndex: a.current.currentLessonIndex
|
|
7964
|
-
}),
|
|
7988
|
+
}), d.current.onLessonStart({
|
|
7965
7989
|
moduleIndex: a.current.currentModuleIndex,
|
|
7966
7990
|
lessonIndex: a.current.currentLessonIndex,
|
|
7967
7991
|
lesson: f()
|
|
7968
7992
|
}), u.current && (u.current.setMood("happy"), u.current.setBodyMovement("idle"));
|
|
7969
7993
|
else if (a.current.currentModuleIndex > 0) {
|
|
7970
7994
|
const H = v.modules[a.current.currentModuleIndex - 1];
|
|
7971
|
-
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (H?.lessons?.length || 1) - 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0,
|
|
7995
|
+
a.current.currentModuleIndex -= 1, a.current.currentLessonIndex = (H?.lessons?.length || 1) - 1, a.current.currentQuestionIndex = 0, a.current.lessonCompleted = !1, a.current.isQuestionMode = !1, a.current.isTeaching = !1, a.current.score = 0, a.current.totalQuestions = 0, d.current.onCustomAction({
|
|
7972
7996
|
type: "lessonStart",
|
|
7973
7997
|
moduleIndex: a.current.currentModuleIndex,
|
|
7974
7998
|
lessonIndex: a.current.currentLessonIndex
|
|
7975
|
-
}),
|
|
7999
|
+
}), d.current.onLessonStart({
|
|
7976
8000
|
moduleIndex: a.current.currentModuleIndex,
|
|
7977
8001
|
lessonIndex: a.current.currentLessonIndex,
|
|
7978
8002
|
lesson: f()
|
|
@@ -7984,11 +8008,11 @@ const yt = Me(({
|
|
|
7984
8008
|
console.log("Avatar is ready!", v);
|
|
7985
8009
|
const R = f(), k = R?.avatar_script || R?.body;
|
|
7986
8010
|
h && k && setTimeout(() => {
|
|
7987
|
-
|
|
8011
|
+
c.current && c.current();
|
|
7988
8012
|
}, 10);
|
|
7989
8013
|
}, [h, f]);
|
|
7990
8014
|
Xe(() => {
|
|
7991
|
-
|
|
8015
|
+
c.current = X, g.current = K, y.current = U, b.current = Z, I.current = oe, V.current = S, p.current = $;
|
|
7992
8016
|
}), Ee(r, () => ({
|
|
7993
8017
|
// Curriculum control methods
|
|
7994
8018
|
startTeaching: X,
|
|
@@ -8045,7 +8069,7 @@ const yt = Me(({
|
|
|
8045
8069
|
unlockAvatarPosition: () => u.current?.unlockAvatarPosition(),
|
|
8046
8070
|
// Custom action trigger
|
|
8047
8071
|
triggerCustomAction: (v, R) => {
|
|
8048
|
-
|
|
8072
|
+
d.current.onCustomAction({
|
|
8049
8073
|
type: v,
|
|
8050
8074
|
...R,
|
|
8051
8075
|
state: { ...a.current }
|