@sage-rsc/talking-head-react 1.0.80 → 1.0.82

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.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { jsxs as Pe, jsx as me } from "react/jsx-runtime";
2
- import { forwardRef as Me, useRef as D, useState as ce, useEffect as de, useCallback as T, useImperativeHandle as Ee, useLayoutEffect as Xe } from "react";
2
+ import { forwardRef as Me, useRef as O, useState as ce, useEffect as de, useCallback as T, useImperativeHandle as Ee, useLayoutEffect as Xe } from "react";
3
3
  import * as x from "three";
4
4
  import { OrbitControls as Ye } from "three/addons/controls/OrbitControls.js";
5
5
  import { GLTFLoader as je } from "three/addons/loaders/GLTFLoader.js";
6
6
  import { DRACOLoader as Qe } from "three/addons/loaders/DRACOLoader.js";
7
- import { FBXLoader as Oe } from "three/addons/loaders/FBXLoader.js";
7
+ import { FBXLoader as De } from "three/addons/loaders/FBXLoader.js";
8
8
  import { RoomEnvironment as qe } from "three/addons/environments/RoomEnvironment.js";
9
9
  import Ke from "three/addons/libs/stats.module.js";
10
10
  let m, re, ue;
@@ -4961,15 +4961,15 @@ class Be {
4961
4961
  let l = t;
4962
4962
  for (; ; )
4963
4963
  if (l.hasOwnProperty(this.stateName))
4964
- l = l[this.stateName];
4964
+ (this.stateName === "speaking" || this.stateName === "idle") && console.log("Selected state:", this.stateName, "for avatar body:", this.avatar?.body), l = l[this.stateName];
4965
4965
  else if (l.hasOwnProperty(this.moodName))
4966
4966
  l = l[this.moodName];
4967
4967
  else if (l.hasOwnProperty(this.poseName))
4968
4968
  l = l[this.poseName];
4969
4969
  else if (l.hasOwnProperty(this.viewName))
4970
4970
  l = l[this.viewName];
4971
- else if (this.avatar.body && l.hasOwnProperty(this.avatar.body))
4972
- console.log("Applying gender-specific override:", this.avatar.body, "for object:", Object.keys(l)), l = l[this.avatar.body];
4971
+ else if (this.avatar && this.avatar.body && l.hasOwnProperty(this.avatar.body))
4972
+ console.log("Applying gender-specific override:", this.avatar.body, "for state:", this.stateName, "keys:", Object.keys(l)), l = l[this.avatar.body];
4973
4973
  else if (l.hasOwnProperty("alt")) {
4974
4974
  let r = l.alt[0];
4975
4975
  if (l.alt.length > 1) {
@@ -5122,7 +5122,7 @@ class Be {
5122
5122
  this.onSubtitles && typeof this.onSubtitles == "function" && this.onSubtitles(i);
5123
5123
  break;
5124
5124
  case "pose":
5125
- this.poseName = i, console.log("Setting pose to:", this.poseName, "for avatar body:", this.avatar?.body), this.setPoseFromTemplate(this.poseTemplates[this.poseName]);
5125
+ this.avatar && this.avatar.body === "M" && i === "hip" && (this.poseTemplates.wide ? (i = "wide", console.log("Overriding hip pose to wide for male avatar")) : this.poseTemplates.side && (i = "side", console.log("Overriding hip pose to side 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
5126
  break;
5127
5127
  case "gesture":
5128
5128
  this.playGesture(...i);
@@ -6404,7 +6404,7 @@ class Be {
6404
6404
  } catch (c) {
6405
6405
  console.warn(`Could not verify file existence for ${t}, attempting to load anyway:`, c);
6406
6406
  }
6407
- const u = new Oe();
6407
+ const u = new De();
6408
6408
  let a;
6409
6409
  try {
6410
6410
  a = await u.loadAsync(t, e);
@@ -6481,7 +6481,7 @@ class Be {
6481
6481
  let l = this.animQueue.find((h) => h.template.name === "pose");
6482
6482
  l && (l.ts[0] = this.animClock + n * 1e3 + 2e3), this.setPoseFromTemplate(o);
6483
6483
  } else {
6484
- let h = await new Oe().loadAsync(t, e);
6484
+ let h = await new De().loadAsync(t, e);
6485
6485
  if (h && h.animations && h.animations[i]) {
6486
6486
  let r = h.animations[i];
6487
6487
  const u = {};
@@ -6686,32 +6686,32 @@ const Ve = Me(({
6686
6686
  style: y = {},
6687
6687
  animations: b = {}
6688
6688
  }, I) => {
6689
- const V = D(null), p = D(null), M = D(r), z = D(null), f = D(null), E = D(!1), P = D({ remainingText: null, originalText: null, options: null }), U = D([]), oe = D(0), [S, Z] = ce(!0), [K, X] = ce(null), [$, se] = ce(!1), [ae, pe] = ce(!1);
6689
+ const V = O(null), p = O(null), M = O(r), z = O(null), f = O(null), E = O(!1), P = O({ remainingText: null, originalText: null, options: null }), U = O([]), oe = O(0), [S, Z] = ce(!0), [K, X] = ce(null), [$, se] = ce(!1), [ae, pe] = ce(!1);
6690
6690
  de(() => {
6691
6691
  E.current = ae;
6692
6692
  }, [ae]), de(() => {
6693
6693
  M.current = r;
6694
6694
  }, [r]);
6695
6695
  const ee = Fe(), le = i || ee.service;
6696
- let O;
6697
- le === "browser" ? O = {
6696
+ let D;
6697
+ le === "browser" ? D = {
6698
6698
  service: "browser",
6699
6699
  endpoint: "",
6700
6700
  apiKey: null,
6701
6701
  defaultVoice: "Google US English"
6702
- } : le === "elevenlabs" ? O = {
6702
+ } : le === "elevenlabs" ? D = {
6703
6703
  service: "elevenlabs",
6704
6704
  endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
6705
6705
  apiKey: o || ee.apiKey,
6706
6706
  defaultVoice: s || ee.defaultVoice || Ie.defaultVoice,
6707
6707
  voices: ee.voices || Ie.voices
6708
- } : le === "deepgram" ? O = {
6708
+ } : le === "deepgram" ? D = {
6709
6709
  service: "deepgram",
6710
6710
  endpoint: "https://api.deepgram.com/v1/speak",
6711
6711
  apiKey: o || ee.apiKey,
6712
6712
  defaultVoice: s || ee.defaultVoice || Te.defaultVoice,
6713
6713
  voices: ee.voices || Te.voices
6714
- } : O = {
6714
+ } : D = {
6715
6715
  ...ee,
6716
6716
  // Override API key if provided via props
6717
6717
  apiKey: o !== null ? o : ee.apiKey
@@ -6721,14 +6721,14 @@ const Ve = Me(({
6721
6721
  body: t,
6722
6722
  avatarMood: e,
6723
6723
  ttsLang: le === "browser" ? "en-US" : n,
6724
- ttsVoice: s || O.defaultVoice,
6724
+ ttsVoice: s || D.defaultVoice,
6725
6725
  lipsyncLang: "en",
6726
6726
  showFullAvatar: r,
6727
6727
  bodyMovement: l,
6728
6728
  movementIntensity: h
6729
6729
  }, R = {
6730
- ttsEndpoint: O.endpoint,
6731
- ttsApikey: O.apiKey,
6730
+ ttsEndpoint: D.endpoint,
6731
+ ttsApikey: D.apiKey,
6732
6732
  ttsService: le,
6733
6733
  lipsyncModules: ["en"],
6734
6734
  cameraView: u
@@ -6808,8 +6808,8 @@ const Ve = Me(({
6808
6808
  be = !0;
6809
6809
  try {
6810
6810
  F.onSpeechEnd();
6811
- } catch (De) {
6812
- console.error("Error in onSpeechEnd callback (timeout):", De);
6811
+ } catch (Oe) {
6812
+ console.error("Error in onSpeechEnd callback (timeout):", Oe);
6813
6813
  }
6814
6814
  }
6815
6815
  return;
@@ -7053,7 +7053,7 @@ const pt = Me(({
7053
7053
  style: s = {},
7054
7054
  avatarConfig: o = {}
7055
7055
  }, l) => {
7056
- const h = D(null), r = D(null), [u, a] = ce(!0), [c, d] = ce(null), [g, y] = ce(!1), b = Fe(), I = o.ttsService || b.service, V = I === "browser" ? {
7056
+ const h = O(null), r = O(null), [u, a] = ce(!0), [c, d] = ce(null), [g, y] = ce(!1), b = Fe(), I = o.ttsService || b.service, V = I === "browser" ? {
7057
7057
  endpoint: "",
7058
7058
  apiKey: null,
7059
7059
  defaultVoice: "Google US English"
@@ -7308,13 +7308,13 @@ const gt = Me(({
7308
7308
  animations: V = {},
7309
7309
  autoSpeak: p = !1
7310
7310
  }, M) => {
7311
- const z = D(null), f = D(null), E = D(u), P = D(null), U = D(null), oe = D(!1), S = D({ remainingText: null, originalText: null, options: null }), Z = D([]), [K, X] = ce(!0), [$, se] = ce(null), [ae, pe] = ce(!1), [ee, le] = ce(!1);
7311
+ const z = O(null), f = O(null), E = O(u), P = O(null), U = O(null), oe = O(!1), S = O({ remainingText: null, originalText: null, options: null }), Z = O([]), [K, X] = ce(!0), [$, se] = ce(null), [ae, pe] = ce(!1), [ee, le] = ce(!1);
7312
7312
  de(() => {
7313
7313
  oe.current = ee;
7314
7314
  }, [ee]), de(() => {
7315
7315
  E.current = u;
7316
7316
  }, [u]);
7317
- const O = Fe(), v = s || O.service;
7317
+ const D = Fe(), v = s || D.service;
7318
7318
  let R;
7319
7319
  v === "browser" ? R = {
7320
7320
  service: "browser",
@@ -7324,18 +7324,18 @@ const gt = Me(({
7324
7324
  } : v === "elevenlabs" ? R = {
7325
7325
  service: "elevenlabs",
7326
7326
  endpoint: "https://api.elevenlabs.io/v1/text-to-speech",
7327
- apiKey: l || O.apiKey,
7328
- defaultVoice: o || O.defaultVoice || Ie.defaultVoice,
7329
- voices: O.voices || Ie.voices
7327
+ apiKey: l || D.apiKey,
7328
+ defaultVoice: o || D.defaultVoice || Ie.defaultVoice,
7329
+ voices: D.voices || Ie.voices
7330
7330
  } : v === "deepgram" ? R = {
7331
7331
  service: "deepgram",
7332
7332
  endpoint: "https://api.deepgram.com/v1/speak",
7333
- apiKey: l || O.apiKey,
7334
- defaultVoice: o || O.defaultVoice || Te.defaultVoice,
7335
- voices: O.voices || Te.voices
7333
+ apiKey: l || D.apiKey,
7334
+ defaultVoice: o || D.defaultVoice || Te.defaultVoice,
7335
+ voices: D.voices || Te.voices
7336
7336
  } : R = {
7337
- ...O,
7338
- apiKey: l !== null ? l : O.apiKey
7337
+ ...D,
7338
+ apiKey: l !== null ? l : D.apiKey
7339
7339
  };
7340
7340
  const k = {
7341
7341
  url: t,
@@ -7516,7 +7516,7 @@ const yt = Me(({
7516
7516
  },
7517
7517
  autoStart: h = !1
7518
7518
  }, r) => {
7519
- const u = D(null), a = D({
7519
+ const u = O(null), a = O({
7520
7520
  currentModuleIndex: 0,
7521
7521
  currentLessonIndex: 0,
7522
7522
  currentQuestionIndex: 0,
@@ -7526,18 +7526,18 @@ const yt = Me(({
7526
7526
  curriculumCompleted: !1,
7527
7527
  score: 0,
7528
7528
  totalQuestions: 0
7529
- }), c = D({
7529
+ }), c = O({
7530
7530
  onLessonStart: n,
7531
7531
  onLessonComplete: i,
7532
7532
  onQuestionAnswer: s,
7533
7533
  onCurriculumComplete: o,
7534
7534
  onCustomAction: l
7535
- }), d = D(null), g = D(null), y = D(null), b = D(null), I = D(null), V = D(null), p = D(null), M = D(G?.curriculum || {
7535
+ }), d = 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
7536
  title: "Default Curriculum",
7537
7537
  description: "No curriculum data provided",
7538
7538
  language: "en",
7539
7539
  modules: []
7540
- }), z = D({
7540
+ }), z = O({
7541
7541
  avatarUrl: t.avatarUrl || "/avatars/brunette.glb",
7542
7542
  avatarBody: t.avatarBody || "F",
7543
7543
  mood: t.mood || "happy",
@@ -8056,7 +8056,7 @@ const yt = Me(({
8056
8056
  // Avatar readiness check (always returns current value)
8057
8057
  isAvatarReady: () => u.current?.isReady || !1
8058
8058
  }), [X, S, $, se, Z, K, U, oe, ee, E, f]);
8059
- const O = z.current || {
8059
+ const D = z.current || {
8060
8060
  avatarUrl: "/avatars/brunette.glb",
8061
8061
  avatarBody: "F",
8062
8062
  mood: "happy",
@@ -8073,18 +8073,18 @@ const yt = Me(({
8073
8073
  Ve,
8074
8074
  {
8075
8075
  ref: u,
8076
- avatarUrl: O.avatarUrl,
8077
- avatarBody: O.avatarBody,
8078
- mood: O.mood,
8079
- ttsLang: O.ttsLang,
8080
- ttsService: O.ttsService,
8081
- ttsVoice: O.ttsVoice,
8082
- ttsApiKey: O.ttsApiKey,
8083
- bodyMovement: O.bodyMovement,
8084
- movementIntensity: O.movementIntensity,
8085
- showFullAvatar: O.showFullAvatar,
8076
+ avatarUrl: D.avatarUrl,
8077
+ avatarBody: D.avatarBody,
8078
+ mood: D.mood,
8079
+ ttsLang: D.ttsLang,
8080
+ ttsService: D.ttsService,
8081
+ ttsVoice: D.ttsVoice,
8082
+ ttsApiKey: D.ttsApiKey,
8083
+ bodyMovement: D.bodyMovement,
8084
+ movementIntensity: D.movementIntensity,
8085
+ showFullAvatar: D.showFullAvatar,
8086
8086
  cameraView: "upper",
8087
- animations: O.animations,
8087
+ animations: D.animations,
8088
8088
  onReady: le,
8089
8089
  onLoading: () => {
8090
8090
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sage-rsc/talking-head-react",
3
- "version": "1.0.80",
3
+ "version": "1.0.82",
4
4
  "description": "A reusable React component for 3D talking avatars with lip-sync and text-to-speech",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -2660,6 +2660,10 @@ class TalkingHead {
2660
2660
  let a = t;
2661
2661
  while(1) {
2662
2662
  if ( a.hasOwnProperty(this.stateName) ) {
2663
+ // Debug: Log state selection
2664
+ if (this.stateName === 'speaking' || this.stateName === 'idle') {
2665
+ console.log('Selected state:', this.stateName, 'for avatar body:', this.avatar?.body);
2666
+ }
2663
2667
  a = a[this.stateName];
2664
2668
  } else if ( a.hasOwnProperty(this.moodName) ) {
2665
2669
  a = a[this.moodName];
@@ -2667,9 +2671,9 @@ class TalkingHead {
2667
2671
  a = a[this.poseName];
2668
2672
  } else if ( a.hasOwnProperty(this.viewName) ) {
2669
2673
  a = a[this.viewName];
2670
- } else if ( this.avatar.body && a.hasOwnProperty(this.avatar.body) ) {
2674
+ } else if ( this.avatar && this.avatar.body && a.hasOwnProperty(this.avatar.body) ) {
2671
2675
  // Debug: Log gender-specific override
2672
- console.log('Applying gender-specific override:', this.avatar.body, 'for object:', Object.keys(a));
2676
+ console.log('Applying gender-specific override:', this.avatar.body, 'for state:', this.stateName, 'keys:', Object.keys(a));
2673
2677
  a = a[this.avatar.body];
2674
2678
  } else if ( a.hasOwnProperty('alt') ) {
2675
2679
 
@@ -3028,8 +3032,20 @@ class TalkingHead {
3028
3032
  break;
3029
3033
 
3030
3034
  case 'pose':
3035
+ // Ensure gender-appropriate pose for male avatars
3036
+ // If 'hip' pose is selected for male avatar, override to 'wide' or 'side'
3037
+ if (this.avatar && this.avatar.body === 'M' && j === 'hip') {
3038
+ // Prefer 'wide' for male avatars, fallback to 'side' if 'wide' doesn't exist
3039
+ if (this.poseTemplates['wide']) {
3040
+ j = 'wide';
3041
+ console.log('Overriding hip pose to wide for male avatar');
3042
+ } else if (this.poseTemplates['side']) {
3043
+ j = 'side';
3044
+ console.log('Overriding hip pose to side for male avatar');
3045
+ }
3046
+ }
3031
3047
  this.poseName = j;
3032
- console.log('Setting pose to:', this.poseName, 'for avatar body:', this.avatar?.body);
3048
+ console.log('Setting pose to:', this.poseName, 'for avatar body:', this.avatar?.body, 'state:', this.stateName);
3033
3049
  this.setPoseFromTemplate( this.poseTemplates[ this.poseName ] );
3034
3050
  break;
3035
3051