@sage-rsc/talking-head-react 1.7.6 → 1.7.7

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.7.6",
3
+ "version": "1.7.7",
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",
@@ -118,11 +118,12 @@ const SimpleTalkingAvatar = forwardRef(({
118
118
 
119
119
  // Option 1: Load from manifest file only
120
120
  if (animations.manifest && !animations.auto) {
121
- try {
122
- const manifestAnimations = await loadAnimationsFromManifest(animations.manifest);
121
+ const manifestAnimations = await loadAnimationsFromManifest(animations.manifest);
122
+ // loadAnimationsFromManifest returns {} on error, so check if we got anything
123
+ const hasAnimations = Object.keys(manifestAnimations).length > 0;
124
+ if (hasAnimations) {
123
125
  setLoadedAnimations(manifestAnimations);
124
- } catch (error) {
125
- console.error('Failed to load animation manifest:', error);
126
+ } else {
126
127
  setLoadedAnimations(animations);
127
128
  }
128
129
  }
@@ -155,7 +156,7 @@ const SimpleTalkingAvatar = forwardRef(({
155
156
  folderPaths[`shared_talking`] = `${basePath}/shared/talking`;
156
157
  folderPaths[`shared_idle`] = `${basePath}/shared/idle`;
157
158
 
158
- console.log(`📁 Loading animations from folders with genderKey="${genderKey}" for avatarBody="${avatarBody}"`);
159
+ // Loading animations from folders
159
160
  const discoveredAnimations = await autoLoadAnimationsFromFolders(folderPaths, avatarBody);
160
161
 
161
162
  // Check if we found any animations
@@ -406,33 +407,30 @@ const SimpleTalkingAvatar = forwardRef(({
406
407
  if (loadedAnimations._genderSpecific) {
407
408
  const genderKey = getGenderKey(avatarBody);
408
409
 
409
- // Debug: Log gender detection
410
- console.log(`🔍 Gender detection: avatarBody="${avatarBody}" -> genderKey="${genderKey}"`);
411
-
412
410
  const genderGroups = loadedAnimations._genderSpecific[genderKey];
413
411
 
414
412
  // Try gender-specific first
415
413
  if (genderGroups && genderGroups[groupName]) {
416
414
  group = genderGroups[groupName];
417
- console.log(`✅ Found ${genderKey} animations for "${groupName}": ${Array.isArray(group) ? group.length : 1} animation(s)`);
418
415
  }
419
416
  // Fallback to shared gender-specific animations
420
417
  else if (loadedAnimations._genderSpecific.shared && loadedAnimations._genderSpecific.shared[groupName]) {
421
418
  group = loadedAnimations._genderSpecific.shared[groupName];
422
- console.log(`✅ Found shared animations for "${groupName}": ${Array.isArray(group) ? group.length : 1} animation(s)`);
423
- } else {
424
- console.log(`⚠️ No ${genderKey} or shared animations found for "${groupName}"`);
425
419
  }
426
420
  }
427
421
 
428
422
  // Fallback to root-level animations if gender-specific not found
429
423
  if (!group && loadedAnimations[groupName]) {
430
424
  group = loadedAnimations[groupName];
431
- console.log(`✅ Found root-level animations for "${groupName}": ${Array.isArray(group) ? group.length : 1} animation(s)`);
432
425
  }
433
426
 
434
427
  if (!group) {
435
- console.log(`❌ No animations found for "${groupName}"`);
428
+ // Only log warning if animations were actually configured (not just empty object)
429
+ const hasAnyAnimations = Object.keys(loadedAnimations).length > 0 ||
430
+ (loadedAnimations._genderSpecific && Object.keys(loadedAnimations._genderSpecific).length > 0);
431
+ if (hasAnyAnimations) {
432
+ console.warn(`⚠️ No animations found for group "${groupName}". Make sure animations are configured correctly.`);
433
+ }
436
434
  return [];
437
435
  }
438
436
 
@@ -13,13 +13,35 @@ export async function loadAnimationsFromManifest(manifestPath) {
13
13
  try {
14
14
  const response = await fetch(manifestPath);
15
15
  if (!response.ok) {
16
+ // Don't log error for 404 - manifest is optional
17
+ if (response.status === 404) {
18
+ return {};
19
+ }
16
20
  throw new Error(`Failed to fetch manifest: ${response.status} ${response.statusText}`);
17
21
  }
18
- const manifest = await response.json();
22
+
23
+ // Check if response is actually JSON (not HTML error page)
24
+ const contentType = response.headers.get('content-type');
25
+ if (contentType && !contentType.includes('application/json')) {
26
+ // Response is not JSON (probably HTML error page)
27
+ return {};
28
+ }
29
+
30
+ const text = await response.text();
31
+ // Try to parse JSON, but check if it looks like HTML first
32
+ if (text.trim().startsWith('<!')) {
33
+ // This is HTML, not JSON (likely a 404 page)
34
+ return {};
35
+ }
36
+
37
+ const manifest = JSON.parse(text);
19
38
  const animations = manifest.animations || {};
20
39
  return animations;
21
40
  } catch (error) {
22
- console.error('Failed to load animation manifest:', error);
41
+ // Only log if it's not a JSON parse error (which we handle above)
42
+ if (!(error instanceof SyntaxError)) {
43
+ console.warn('⚠️ Could not load animation manifest (this is optional):', manifestPath);
44
+ }
23
45
  return {};
24
46
  }
25
47
  }