@sage-rsc/talking-head-react 1.3.4 → 1.3.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sage-rsc/talking-head-react",
3
- "version": "1.3.4",
3
+ "version": "1.3.5",
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",
@@ -86,22 +86,27 @@ const SimpleTalkingAvatar = forwardRef(({
86
86
  const loadManifestAnimations = async () => {
87
87
  if (animations.manifest) {
88
88
  try {
89
+ console.log('🔄 Loading animations from manifest:', animations.manifest);
89
90
  const manifestAnimations = await loadAnimationsFromManifest(animations.manifest);
90
91
  setLoadedAnimations(manifestAnimations);
91
- console.log('Loaded animations from manifest:', manifestAnimations);
92
+ console.log(' Animations loaded and set:', manifestAnimations);
92
93
 
93
94
  // Log gender-specific groups if available
94
95
  if (manifestAnimations._genderSpecific) {
95
- console.log('Gender-specific animations detected:', {
96
+ console.log('👥 Gender-specific animations detected:', {
96
97
  male: Object.keys(manifestAnimations._genderSpecific.male || {}),
97
- female: Object.keys(manifestAnimations._genderSpecific.female || {})
98
+ female: Object.keys(manifestAnimations._genderSpecific.female || {}),
99
+ shared: Object.keys(manifestAnimations._genderSpecific.shared || {})
98
100
  });
101
+ } else {
102
+ console.log('⚠️ No gender-specific animations found in manifest');
99
103
  }
100
104
  } catch (error) {
101
- console.error('Failed to load animation manifest:', error);
105
+ console.error('Failed to load animation manifest:', error);
102
106
  setLoadedAnimations(animations);
103
107
  }
104
108
  } else {
109
+ console.log('📝 Using animations from props (no manifest):', animations);
105
110
  setLoadedAnimations(animations);
106
111
  }
107
112
  };
@@ -260,11 +265,12 @@ const SimpleTalkingAvatar = forwardRef(({
260
265
 
261
266
  // Helper function to get random animation from a group (with gender support)
262
267
  const getRandomAnimation = useCallback((groupName) => {
263
- if (!loadedAnimations || !loadedAnimations[groupName]) {
268
+ if (!loadedAnimations) {
269
+ console.warn('No animations loaded');
264
270
  return null;
265
271
  }
266
272
 
267
- let group = loadedAnimations[groupName];
273
+ let group = null;
268
274
 
269
275
  // Check if gender-specific animations are available
270
276
  if (loadedAnimations._genderSpecific) {
@@ -272,16 +278,34 @@ const SimpleTalkingAvatar = forwardRef(({
272
278
  const genderKey = avatarGender === 'M' ? 'male' : 'female';
273
279
  const genderGroups = loadedAnimations._genderSpecific[genderKey];
274
280
 
275
- // Try gender-specific first, fallback to shared
281
+ // Try gender-specific first
276
282
  if (genderGroups && genderGroups[groupName]) {
277
283
  group = genderGroups[groupName];
278
- console.log(`Using ${genderKey} animations for "${groupName}"`);
279
- } else if (loadedAnimations._genderSpecific.shared && loadedAnimations._genderSpecific.shared[groupName]) {
284
+ console.log(`Using ${genderKey} animations for "${groupName}":`, group);
285
+ }
286
+ // Fallback to shared gender-specific animations
287
+ else if (loadedAnimations._genderSpecific.shared && loadedAnimations._genderSpecific.shared[groupName]) {
280
288
  group = loadedAnimations._genderSpecific.shared[groupName];
281
- console.log(`Using shared animations for "${groupName}"`);
289
+ console.log(`Using shared animations for "${groupName}":`, group);
282
290
  }
283
291
  }
284
292
 
293
+ // Fallback to root-level animations if gender-specific not found
294
+ if (!group && loadedAnimations[groupName]) {
295
+ group = loadedAnimations[groupName];
296
+ console.log(`Using root-level animations for "${groupName}":`, group);
297
+ }
298
+
299
+ if (!group) {
300
+ console.warn(`Animation group "${groupName}" not found. Available groups:`, Object.keys(loadedAnimations).filter(k => k !== '_genderSpecific'));
301
+ if (loadedAnimations._genderSpecific) {
302
+ const avatarGender = avatarBody?.toUpperCase() || 'F';
303
+ const genderKey = avatarGender === 'M' ? 'male' : 'female';
304
+ console.warn(`Gender-specific groups (${genderKey}):`, Object.keys(loadedAnimations._genderSpecific[genderKey] || {}));
305
+ }
306
+ return null;
307
+ }
308
+
285
309
  // If it's an array, randomly select one
286
310
  if (Array.isArray(group) && group.length > 0) {
287
311
  const randomIndex = Math.floor(Math.random() * group.length);
@@ -293,21 +317,29 @@ const SimpleTalkingAvatar = forwardRef(({
293
317
  return group;
294
318
  }
295
319
 
320
+ console.warn(`Animation group "${groupName}" is not a valid format (expected array or string):`, group);
296
321
  return null;
297
322
  }, [loadedAnimations, avatarBody]);
298
323
 
299
324
  // Helper function to play random animation from a group
300
325
  const playRandomAnimation = useCallback((groupName, disablePositionLock = false) => {
326
+ if (!talkingHeadRef.current) {
327
+ console.warn('TalkingHead not initialized yet');
328
+ return null;
329
+ }
330
+
301
331
  const animationPath = getRandomAnimation(groupName);
302
- if (animationPath && talkingHeadRef.current) {
332
+ if (animationPath) {
303
333
  try {
304
334
  talkingHeadRef.current.playAnimation(animationPath, null, 10, 0, 0.01, disablePositionLock);
305
- console.log(`Playing random animation from "${groupName}" group:`, animationPath);
335
+ console.log(`✅ Playing random animation from "${groupName}" group:`, animationPath);
306
336
  return animationPath;
307
337
  } catch (error) {
308
- console.warn(`Failed to play random animation from "${groupName}" group:`, error);
338
+ console.error(`❌ Failed to play random animation from "${groupName}" group:`, error);
309
339
  return null;
310
340
  }
341
+ } else {
342
+ console.warn(`⚠️ No animation found for group "${groupName}"`);
311
343
  }
312
344
  return null;
313
345
  }, [getRandomAnimation]);
@@ -331,7 +363,11 @@ const SimpleTalkingAvatar = forwardRef(({
331
363
  // Check both autoAnimationGroup prop and options.animationGroup
332
364
  const animationGroup = options.animationGroup || autoAnimationGroup;
333
365
  if (animationGroup && !options.skipAnimation) {
366
+ console.log(`🎬 Attempting to play animation from group: "${animationGroup}"`);
367
+ console.log(`📊 Current avatarBody: "${avatarBody}", loadedAnimations:`, loadedAnimations);
334
368
  playRandomAnimation(animationGroup);
369
+ } else {
370
+ console.log(`⏭️ Skipping animation (group: ${animationGroup}, skipAnimation: ${options.skipAnimation})`);
335
371
  }
336
372
 
337
373
  // Reset speech progress tracking
@@ -11,11 +11,28 @@
11
11
  */
12
12
  export async function loadAnimationsFromManifest(manifestPath) {
13
13
  try {
14
+ console.log(`📥 Loading animation manifest from: ${manifestPath}`);
14
15
  const response = await fetch(manifestPath);
16
+ if (!response.ok) {
17
+ throw new Error(`Failed to fetch manifest: ${response.status} ${response.statusText}`);
18
+ }
15
19
  const manifest = await response.json();
16
- return manifest.animations || {};
20
+ console.log('📦 Raw manifest loaded:', manifest);
21
+
22
+ const animations = manifest.animations || {};
23
+ console.log('✅ Processed animations object:', animations);
24
+
25
+ if (animations._genderSpecific) {
26
+ console.log('👥 Gender-specific structure detected:', {
27
+ male: Object.keys(animations._genderSpecific.male || {}),
28
+ female: Object.keys(animations._genderSpecific.female || {}),
29
+ shared: Object.keys(animations._genderSpecific.shared || {})
30
+ });
31
+ }
32
+
33
+ return animations;
17
34
  } catch (error) {
18
- console.error('Failed to load animation manifest:', error);
35
+ console.error('Failed to load animation manifest:', error);
19
36
  return {};
20
37
  }
21
38
  }