talking-head-studio 0.3.6 → 0.3.8

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.
Files changed (40) hide show
  1. package/dist/TalkingHead.web.js +7 -17
  2. package/dist/api/studioApi.js +26 -25
  3. package/dist/appearance/apply.d.ts +6 -0
  4. package/dist/appearance/apply.js +72 -7
  5. package/dist/appearance/index.d.ts +1 -1
  6. package/dist/appearance/index.js +2 -1
  7. package/dist/appearance/matchers.js +2 -1
  8. package/dist/appearance/schema.d.ts +1 -0
  9. package/dist/appearance/schema.js +3 -1
  10. package/dist/appearance/sharedState.d.ts +11 -0
  11. package/dist/appearance/sharedState.js +13 -0
  12. package/dist/editor/AvatarCanvas.d.ts +1 -0
  13. package/dist/editor/AvatarCanvas.js +3 -2
  14. package/dist/editor/AvatarModel.d.ts +1 -3
  15. package/dist/editor/AvatarModel.js +13 -5
  16. package/dist/editor/RigidAccessory.js +2 -1
  17. package/dist/editor/SkinnedClothing.js +9 -18
  18. package/dist/filament/FilamentAvatar.js +20 -42
  19. package/dist/filament/editor/FilamentEditor.js +12 -21
  20. package/dist/filament/editor/FilamentEditor.web.js +2 -1
  21. package/dist/filament/editor/PrecisionPanel.js +8 -18
  22. package/dist/filament/editor/boneSnap.js +13 -23
  23. package/dist/filament/editor/studioTheme.js +2 -2
  24. package/dist/filament/useAuthedFilamentUri.js +9 -18
  25. package/dist/html.js +2 -1
  26. package/dist/index.d.ts +0 -2
  27. package/dist/index.js +1 -3
  28. package/dist/sketchfab/api.js +5 -4
  29. package/dist/sketchfab/useSketchfabSearch.js +2 -1
  30. package/dist/tts/useDirectVisemeStream.js +2 -1
  31. package/dist/tts/useMotionMarkers.d.ts +1 -0
  32. package/dist/tts/useMotionMarkers.js +2 -1
  33. package/dist/utils/avatarUtils.js +3 -2
  34. package/dist/utils/faceLandmarkerToShapeWeights.d.ts +44 -0
  35. package/dist/utils/faceLandmarkerToShapeWeights.js +112 -0
  36. package/dist/voice/convertToWav.js +2 -1
  37. package/dist/voice/useAudioPlayer.js +2 -1
  38. package/dist/voice/useAudioRecording.js +2 -1
  39. package/dist/wardrobe/useAvatarWardrobeHydration.js +2 -1
  40. package/package.json +15 -3
@@ -15,23 +15,13 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
35
25
  Object.defineProperty(exports, "__esModule", { value: true });
36
26
  exports.FilamentAvatar = exports.CAMERA_FOCAL_PIP = exports.CAMERA_FOCAL_FULL = void 0;
37
27
  const jsx_runtime_1 = require("react/jsx-runtime");
@@ -51,7 +41,6 @@ const react_1 = __importStar(require("react"));
51
41
  const react_native_1 = require("react-native");
52
42
  const react_native_filament_1 = require("react-native-filament");
53
43
  const useAuthedFilamentUri_1 = require("./useAuthedFilamentUri");
54
- const expo_asset_1 = require("expo-asset");
55
44
  const faceSqueezeAssets_1 = require("./faceSqueezeAssets");
56
45
  const morphTables_1 = require("./morphTables");
57
46
  // ---------------------------------------------------------------------------
@@ -148,10 +137,11 @@ function buildVisemeMorphCache(dispatchMap) {
148
137
  }
149
138
  function FilamentAvatarInner({ localUri, mood: initialMood = 'neutral', hairColor: initialHairColor, skinColor: initialSkinColor, eyeColor: initialEyeColor, onReady, onError: _onError, // eslint-disable-line @typescript-eslint/no-unused-vars
150
139
  innerRef, aspect, focalLength = exports.CAMERA_FOCAL_FULL, }) {
151
- // When localUri is empty (model not yet downloaded), pass a stable placeholder
152
- // so useModel doesn't error. ModelRenderer is gated on model.state === 'loaded'
153
- // so nothing will render until the real URI arrives.
154
- const model = (0, react_native_filament_1.useModel)({ uri: localUri || '' });
140
+ // localUri is either a file:// string (remote download) or a require() number (bundled fallback).
141
+ // useModel accepts both as BufferSource (number | { uri: string }) — cast to any since
142
+ // tsconfig resolves to an older type declaration that only shows { uri: string }.
143
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
144
+ const model = (0, react_native_filament_1.useModel)(typeof localUri === 'number' ? localUri : { uri: localUri });
155
145
  const modelRef = (0, react_1.useRef)(model);
156
146
  modelRef.current = model;
157
147
  const { renderableManager } = (0, react_native_filament_1.useFilamentContext)();
@@ -697,36 +687,24 @@ innerRef, aspect, focalLength = exports.CAMERA_FOCAL_FULL, }) {
697
687
  // ---------------------------------------------------------------------------
698
688
  // Outer component — handles URL resolution + FilamentScene wrapper
699
689
  // ---------------------------------------------------------------------------
700
- let _fallbackGlbUri = null;
701
- async function getFallbackGlbUri() {
702
- if (_fallbackGlbUri)
703
- return _fallbackGlbUri;
704
- const asset = expo_asset_1.Asset.fromModule(faceSqueezeAssets_1.FACE_SQUEEZE_LOCAL_MODULE);
705
- await asset.downloadAsync();
706
- _fallbackGlbUri = asset.localUri ?? asset.uri ?? '';
707
- return _fallbackGlbUri;
708
- }
690
+ // The fallback is the bundled require() number — useModel accepts this directly
691
+ // (BufferSource = number | { uri: string }), so no async asset resolution needed.
709
692
  exports.FilamentAvatar = (0, react_1.forwardRef)(({ style, avatarUrl, aspect, focalLength, mood, hairColor, skinColor, eyeColor, accessories, onReady, onError }, ref) => {
710
693
  const fileResult = (0, useAuthedFilamentUri_1.useAuthedFilamentUri)(avatarUrl ?? null);
711
694
  const currentUri = fileResult?.uri ?? null;
712
- const [fallbackUri, setFallbackUri] = react_1.default.useState(_fallbackGlbUri);
713
- react_1.default.useEffect(() => {
714
- getFallbackGlbUri().then(setFallbackUri).catch((e) => console.error('[FilamentAvatar] fallback uri failed:', e));
715
- }, []);
716
- // Stabilize localUri: once a valid file URI resolves, keep it until a new one
717
- // arrives. Never let it drop to null between URL transitions — that would cause
718
- // the conditional below to unmount FilamentScene mid-render.
695
+ // Stabilize localUri: once a valid remote file URI resolves, keep it until a new
696
+ // one arrives. Falls back to the bundled require() number — always available sync.
719
697
  const stableUriRef = react_1.default.useRef(null);
720
698
  if (currentUri)
721
699
  stableUriRef.current = currentUri;
722
- const localUri = stableUriRef.current ?? fallbackUri;
700
+ const localUri = stableUriRef.current ?? faceSqueezeAssets_1.FACE_SQUEEZE_LOCAL_MODULE;
723
701
  // FilamentScene MUST stay mounted for the lifetime of this component.
724
702
  // Unmounting it disposes GPU assets on the JS thread while Filament's native
725
703
  // render thread (FEngine::loop) and surface thread (JNISurfaceTextu) still hold
726
704
  // references to those objects → SIGSEGV / corrupted-PC use-after-free crashes.
727
- // We always render FilamentScene and conditionally render FilamentAvatarInner
728
- // inside it once the local file URI is ready.
729
- return ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [style, styles.fill], children: (0, jsx_runtime_1.jsx)(react_native_filament_1.FilamentScene, { children: (0, jsx_runtime_1.jsx)(FilamentAvatarInner, { localUri: localUri ?? '', avatarUrl: avatarUrl, aspect: aspect, focalLength: focalLength, mood: mood, hairColor: hairColor, skinColor: skinColor, eyeColor: eyeColor, accessories: accessories, innerRef: ref, onReady: onReady, onError: onError }) }) }));
705
+ // FilamentAvatarInner keeps FilamentView permanently mounted; only ModelRenderer
706
+ // is conditional on the model being ready.
707
+ return ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [style, styles.fill], children: (0, jsx_runtime_1.jsx)(react_native_filament_1.FilamentScene, { children: (0, jsx_runtime_1.jsx)(FilamentAvatarInner, { localUri: localUri, avatarUrl: avatarUrl, aspect: aspect, focalLength: focalLength, mood: mood, hairColor: hairColor, skinColor: skinColor, eyeColor: eyeColor, accessories: accessories, innerRef: ref, onReady: onReady, onError: onError }) }) }));
730
708
  });
731
709
  exports.FilamentAvatar.displayName = 'FilamentAvatar';
732
710
  const styles = react_native_1.StyleSheet.create({
@@ -15,28 +15,18 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
35
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
36
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
27
  };
38
28
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.FilamentEditor = FilamentEditor;
29
+ exports.FilamentEditor = void 0;
40
30
  const jsx_runtime_1 = require("react/jsx-runtime");
41
31
  /* eslint-disable @typescript-eslint/no-explicit-any */
42
32
  const vector_icons_1 = require("@expo/vector-icons");
@@ -44,9 +34,6 @@ const Haptics = __importStar(require("expo-haptics"));
44
34
  const react_1 = require("react");
45
35
  const react_native_1 = require("react-native");
46
36
  const react_native_filament_1 = require("react-native-filament");
47
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
- const rnFilament = require('react-native-filament'); // eslint-disable-line @typescript-eslint/no-require-imports
49
- const useCameraManipulator = rnFilament.useCameraManipulator;
50
37
  const react_native_gesture_handler_1 = require("react-native-gesture-handler");
51
38
  const react_native_reanimated_1 = __importStar(require("react-native-reanimated"));
52
39
  const useAuthedFilamentUri_1 = require("../useAuthedFilamentUri");
@@ -54,6 +41,9 @@ const boneSnap_1 = require("./boneSnap");
54
41
  const studioApi_1 = require("../../api/studioApi");
55
42
  const PrecisionPanel_1 = __importDefault(require("./PrecisionPanel"));
56
43
  const studioTheme_1 = require("./studioTheme");
44
+ // Lazy require avoids mixing require/import at module top level (Metro bug).
45
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-explicit-any
46
+ const useCameraManipulator = require('react-native-filament').useCameraManipulator;
57
47
  // Pure JS transform helpers (no 'worklet' directive — avoids Reanimated
58
48
  // babel plugin serializing gesture closure variables).
59
49
  function applyDragTranslate(startPos, translationX, translationY, sensitivity) {
@@ -294,6 +284,7 @@ function AvatarModel({ uri, onLoaded, skinColor }) {
294
284
  function FilamentEditor(props) {
295
285
  return ((0, jsx_runtime_1.jsx)(react_native_filament_1.FilamentScene, { children: (0, jsx_runtime_1.jsx)(FilamentEditorContent, { ...props }) }));
296
286
  }
287
+ exports.FilamentEditor = FilamentEditor;
297
288
  // ---------------------------------------------------------------------------
298
289
  // Inner component — has access to Filament context
299
290
  // ---------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FilamentEditor = FilamentEditor;
3
+ exports.FilamentEditor = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_native_1 = require("react-native");
6
6
  const editor_1 = require("../../editor");
@@ -34,6 +34,7 @@ function FilamentEditor({ avatarUrl, style, onDone, appearance, equipped, placem
34
34
  };
35
35
  return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [styles.container, style], children: [(0, jsx_runtime_1.jsx)(editor_1.AvatarCanvas, { avatarUrl: avatarUrl, appearance: appearance, equipped: equippedItems, placements: normalizedPlacements, editingAssetId: activeAssetId, onPlacementChange: handlePlacementChange, style: { width: '100%', height: '100%' } }), (0, jsx_runtime_1.jsx)(react_native_1.Pressable, { style: styles.doneButton, onPress: onDone, children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: styles.doneText, children: "Done" }) })] }));
36
36
  }
37
+ exports.FilamentEditor = FilamentEditor;
37
38
  exports.default = FilamentEditor;
38
39
  const styles = react_native_1.StyleSheet.create({
39
40
  container: {
@@ -15,25 +15,14 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
35
25
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.default = PrecisionPanel;
37
26
  const jsx_runtime_1 = require("react/jsx-runtime");
38
27
  const react_1 = require("react");
39
28
  const react_native_1 = require("react-native");
@@ -158,6 +147,7 @@ function PrecisionPanel() {
158
147
  }, children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: [styles.segmentText, isActive && styles.segmentTextActive], children: m.label }) }, m.key));
159
148
  }) }), gizmoMode === 'translate' && ((0, jsx_runtime_1.jsxs)(react_native_reanimated_1.default.View, { children: [(0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "X", value: placement.position[0], onChange: (v) => updateAxis('x', v), step: 0.01 }), (0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "Y", value: placement.position[1], onChange: (v) => updateAxis('y', v), step: 0.01 }), (0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "Z", value: placement.position[2], onChange: (v) => updateAxis('z', v), step: 0.01 })] })), gizmoMode === 'rotate' && ((0, jsx_runtime_1.jsxs)(react_native_reanimated_1.default.View, { children: [(0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "Pitch", value: placement.rotation[0], onChange: (v) => updateAxis('x', v), step: 1, unit: "\u00B0" }), (0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "Yaw", value: placement.rotation[1], onChange: (v) => updateAxis('y', v), step: 1, unit: "\u00B0" }), (0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "Roll", value: placement.rotation[2], onChange: (v) => updateAxis('z', v), step: 1, unit: "\u00B0" })] })), gizmoMode === 'scale' && ((0, jsx_runtime_1.jsx)(react_native_reanimated_1.default.View, { children: (0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "Uniform", value: placement.scale, onChange: updateScale, step: 0.01 }) }))] }));
160
149
  }
150
+ exports.default = PrecisionPanel;
161
151
  const styles = react_native_1.StyleSheet.create({
162
152
  container: {
163
153
  position: 'absolute',
@@ -15,34 +15,20 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
35
25
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.HUMANOID_BONES = void 0;
37
- exports.findNearestBone = findNearestBone;
38
- exports.getWorldPositionForPlacement = getWorldPositionForPlacement;
39
- exports.snapPlacementToNearestBone = snapPlacementToNearestBone;
40
- exports.useBoneSnap = useBoneSnap;
26
+ exports.useBoneSnap = exports.snapPlacementToNearestBone = exports.getWorldPositionForPlacement = exports.findNearestBone = exports.HUMANOID_BONES = void 0;
41
27
  const react_1 = require("react");
42
28
  const Haptics = __importStar(require("expo-haptics"));
43
29
  const wardrobeStore_1 = require("../../wardrobe/wardrobeStore");
44
30
  exports.HUMANOID_BONES = {
45
- Head: [0, 1.7, 0],
31
+ Head: [0, 0.12, 0],
46
32
  Neck: [0, 1.5, 0],
47
33
  Spine: [0, 1.0, 0],
48
34
  RightHand: [0.8, 1.0, 0],
@@ -72,6 +58,7 @@ function findNearestBone(position) {
72
58
  position: nearestPos,
73
59
  };
74
60
  }
61
+ exports.findNearestBone = findNearestBone;
75
62
  function getWorldPositionForPlacement(placement) {
76
63
  const bonePos = exports.HUMANOID_BONES[placement.bone] ?? exports.HUMANOID_BONES['Head'];
77
64
  return [
@@ -80,6 +67,7 @@ function getWorldPositionForPlacement(placement) {
80
67
  bonePos[2] + placement.position[2],
81
68
  ];
82
69
  }
70
+ exports.getWorldPositionForPlacement = getWorldPositionForPlacement;
83
71
  function snapPlacementToNearestBone(placement) {
84
72
  const nearest = findNearestBone(getWorldPositionForPlacement(placement));
85
73
  return {
@@ -88,6 +76,7 @@ function snapPlacementToNearestBone(placement) {
88
76
  position: [0, 0, 0],
89
77
  };
90
78
  }
79
+ exports.snapPlacementToNearestBone = snapPlacementToNearestBone;
91
80
  function useBoneSnap() {
92
81
  const activeAssetId = (0, wardrobeStore_1.useWardrobeStore)((state) => state.activeAssetId);
93
82
  const placements = (0, wardrobeStore_1.useWardrobeStore)((state) => state.placements);
@@ -105,3 +94,4 @@ function useBoneSnap() {
105
94
  }, [activeAssetId, placements, setPlacement]);
106
95
  return snap;
107
96
  }
97
+ exports.useBoneSnap = useBoneSnap;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.studioTheme = void 0;
4
- exports.withAlpha = withAlpha;
3
+ exports.withAlpha = exports.studioTheme = void 0;
5
4
  exports.studioTheme = {
6
5
  colors: {
7
6
  background: '#111315',
@@ -87,3 +86,4 @@ function withAlpha(hexOrRgb, alphaHex) {
87
86
  }
88
87
  return hexOrRgb;
89
88
  }
89
+ exports.withAlpha = withAlpha;
@@ -15,25 +15,15 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
35
25
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.useAuthedFilamentUri = useAuthedFilamentUri;
26
+ exports.useAuthedFilamentUri = void 0;
37
27
  const react_1 = require("react");
38
28
  const FileSystem = __importStar(require("expo-file-system/legacy"));
39
29
  const studioApi_1 = require("../api/studioApi");
@@ -124,3 +114,4 @@ function useAuthedFilamentUri(remoteUrl) {
124
114
  }, [remoteUrl]);
125
115
  return result;
126
116
  }
117
+ exports.useAuthedFilamentUri = useAuthedFilamentUri;
package/dist/html.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildAvatarHtml = buildAvatarHtml;
3
+ exports.buildAvatarHtml = void 0;
4
4
  const UPSTREAM_SAFE_MOOD_MAP = {
5
5
  neutral: 'neutral',
6
6
  happy: 'happy',
@@ -1138,3 +1138,4 @@ await init();
1138
1138
  </html>
1139
1139
  `;
1140
1140
  }
1141
+ exports.buildAvatarHtml = buildAvatarHtml;
package/dist/index.d.ts CHANGED
@@ -6,8 +6,6 @@ export { normalizeAppearance } from './appearance/schema';
6
6
  export type { AppearanceTarget } from './appearance/matchers';
7
7
  export * from './api';
8
8
  export * from './wardrobe';
9
- export { TalkingHeadVisualization } from './TalkingHeadVisualization';
10
- export type { TalkingHeadVisualizationRef } from './TalkingHeadVisualization';
11
9
  export { useDirectVisemeStream } from './tts/useDirectVisemeStream';
12
10
  export type { VisemeStreamPayload } from './tts/useDirectVisemeStream';
13
11
  export { useMotionMarkers } from './tts/useMotionMarkers';
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.useMotionMarkers = exports.useDirectVisemeStream = exports.TalkingHeadVisualization = exports.normalizeAppearance = exports.pickTargetForMaterialName = exports.applyAppearanceToObject3D = exports.TalkingHead = void 0;
17
+ exports.useMotionMarkers = exports.useDirectVisemeStream = exports.normalizeAppearance = exports.pickTargetForMaterialName = exports.applyAppearanceToObject3D = exports.TalkingHead = void 0;
18
18
  var TalkingHead_1 = require("./TalkingHead");
19
19
  Object.defineProperty(exports, "TalkingHead", { enumerable: true, get: function () { return TalkingHead_1.TalkingHead; } });
20
20
  // Export appearance utilities, but exclude AvatarAppearance — the canonical
@@ -27,8 +27,6 @@ var schema_1 = require("./appearance/schema");
27
27
  Object.defineProperty(exports, "normalizeAppearance", { enumerable: true, get: function () { return schema_1.normalizeAppearance; } });
28
28
  __exportStar(require("./api"), exports);
29
29
  __exportStar(require("./wardrobe"), exports);
30
- var TalkingHeadVisualization_1 = require("./TalkingHeadVisualization");
31
- Object.defineProperty(exports, "TalkingHeadVisualization", { enumerable: true, get: function () { return TalkingHeadVisualization_1.TalkingHeadVisualization; } });
32
30
  var useDirectVisemeStream_1 = require("./tts/useDirectVisemeStream");
33
31
  Object.defineProperty(exports, "useDirectVisemeStream", { enumerable: true, get: function () { return useDirectVisemeStream_1.useDirectVisemeStream; } });
34
32
  var useMotionMarkers_1 = require("./tts/useMotionMarkers");
@@ -1,9 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.searchSketchfab = searchSketchfab;
4
- exports.getDownloadUrl = getDownloadUrl;
5
- exports.downloadModel = downloadModel;
6
- exports.getBestThumbnail = getBestThumbnail;
3
+ exports.getBestThumbnail = exports.downloadModel = exports.getDownloadUrl = exports.searchSketchfab = void 0;
7
4
  const SKETCHFAB_API_BASE = 'https://api.sketchfab.com/v3';
8
5
  const PAGE_SIZE = 24;
9
6
  async function searchSketchfab(options) {
@@ -26,6 +23,7 @@ async function searchSketchfab(options) {
26
23
  }
27
24
  return response.json();
28
25
  }
26
+ exports.searchSketchfab = searchSketchfab;
29
27
  async function getDownloadUrl(uid, apiKey) {
30
28
  const response = await fetch(`${SKETCHFAB_API_BASE}/models/${uid}/download`, {
31
29
  headers: { Authorization: `Token ${apiKey}` },
@@ -36,6 +34,7 @@ async function getDownloadUrl(uid, apiKey) {
36
34
  const data = (await response.json());
37
35
  return data?.glb?.url ?? data?.gltf?.url ?? null;
38
36
  }
37
+ exports.getDownloadUrl = getDownloadUrl;
39
38
  async function downloadModel(uid, name, apiKey) {
40
39
  const url = await getDownloadUrl(uid, apiKey);
41
40
  if (!url) {
@@ -49,6 +48,7 @@ async function downloadModel(uid, name, apiKey) {
49
48
  const cleanName = name.replace(/[^\w\s-]/g, '').trim() || 'model';
50
49
  return new File([blob], `${cleanName}.glb`, { type: 'model/gltf-binary' });
51
50
  }
51
+ exports.downloadModel = downloadModel;
52
52
  function getBestThumbnail(thumbnails, targetWidth = 280) {
53
53
  if (!thumbnails?.images?.length) {
54
54
  return '';
@@ -56,3 +56,4 @@ function getBestThumbnail(thumbnails, targetWidth = 280) {
56
56
  const sorted = [...thumbnails.images].sort((left, right) => Math.abs(left.width - targetWidth) - Math.abs(right.width - targetWidth));
57
57
  return sorted[0].url;
58
58
  }
59
+ exports.getBestThumbnail = getBestThumbnail;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useSketchfabSearch = useSketchfabSearch;
3
+ exports.useSketchfabSearch = void 0;
4
4
  const react_1 = require("react");
5
5
  const api_1 = require("./api");
6
6
  function useSketchfabSearch({ apiKey, initialQuery = 'character humanoid avatar', debounceMs = 400, }) {
@@ -79,3 +79,4 @@ function useSketchfabSearch({ apiKey, initialQuery = 'character humanoid avatar'
79
79
  prevPage,
80
80
  };
81
81
  }
82
+ exports.useSketchfabSearch = useSketchfabSearch;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useDirectVisemeStream = useDirectVisemeStream;
3
+ exports.useDirectVisemeStream = void 0;
4
4
  const react_1 = require("react");
5
5
  const fetch_1 = require("expo/fetch");
6
6
  // How long to keep retrying a stream before giving up (ms).
@@ -100,6 +100,7 @@ function useDirectVisemeStream(onVisemes) {
100
100
  }, []);
101
101
  return { openStream };
102
102
  }
103
+ exports.useDirectVisemeStream = useDirectVisemeStream;
103
104
  // ─── SSE parser ──────────────────────────────────────────────────────────────
104
105
  /**
105
106
  * Reads an SSE stream to completion, dispatching `event: visemes` messages.
@@ -1,2 +1,3 @@
1
+ /// <reference types="react" />
1
2
  import type { TalkingHeadRef } from '../TalkingHead';
2
3
  export declare function useMotionMarkers(ref: React.RefObject<TalkingHeadRef | null>): (text: string) => string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useMotionMarkers = useMotionMarkers;
3
+ exports.useMotionMarkers = void 0;
4
4
  const react_1 = require("react");
5
5
  /**
6
6
  * Parses ::marker_name:: tokens out of LLM transcript text, fires the
@@ -22,3 +22,4 @@ function useMotionMarkers(ref) {
22
22
  return '';
23
23
  }), [ref]);
24
24
  }
25
+ exports.useMotionMarkers = useMotionMarkers;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveFilamentAssetUri = resolveFilamentAssetUri;
4
- exports.resolveLocalAssetUrl = resolveLocalAssetUrl;
3
+ exports.resolveLocalAssetUrl = exports.resolveFilamentAssetUri = void 0;
5
4
  const expo_asset_1 = require("expo-asset");
6
5
  const react_native_1 = require("react-native");
7
6
  const expo_file_system_1 = require("expo-file-system");
@@ -22,6 +21,7 @@ async function resolveFilamentAssetUri(module) {
22
21
  return null;
23
22
  }
24
23
  }
24
+ exports.resolveFilamentAssetUri = resolveFilamentAssetUri;
25
25
  /**
26
26
  * Resolves a local Expo asset module (from require()) into a usable URL string.
27
27
  * On web, returns an absolute URL.
@@ -54,3 +54,4 @@ async function resolveLocalAssetUrl(module) {
54
54
  return null;
55
55
  }
56
56
  }
57
+ exports.resolveLocalAssetUrl = resolveLocalAssetUrl;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * faceLandmarkerToShapeWeights
3
+ *
4
+ * Runs MediaPipe FaceLandmarker on a photo and returns a
5
+ * faceShapeWeights Record<string, number> ready to store in
6
+ * AvatarAppearance. Works with any GLB that has ARKit morph
7
+ * target names — mesh-agnostic, pure named floats.
8
+ *
9
+ * Lazy-loads @mediapipe/tasks-vision on first call (~3MB WASM).
10
+ * Subsequent calls reuse the same FaceLandmarker instance.
11
+ *
12
+ * Apache 2.0 — no API key, no license restrictions.
13
+ */
14
+ type ImageSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap;
15
+ export type FaceShapeWeights = Record<string, number>;
16
+ export interface FaceLandmarkerOptions {
17
+ /**
18
+ * Minimum score threshold to include a blendshape weight.
19
+ * Shapes below this are omitted to keep the dict lean.
20
+ * Default: 0.01
21
+ */
22
+ minScore?: number;
23
+ /**
24
+ * If true, also includes near-zero weights (useful for
25
+ * resetting a previously shaped face to neutral).
26
+ * Default: false
27
+ */
28
+ includeNeutral?: boolean;
29
+ }
30
+ /**
31
+ * Detect face blendshapes from a photo and return a faceShapeWeights
32
+ * dict compatible with AvatarAppearance.
33
+ *
34
+ * @param source Any image/video/canvas/bitmap element
35
+ * @param options Optional thresholds
36
+ * @returns faceShapeWeights Record<string, number>, or null if no face detected
37
+ */
38
+ export declare function faceLandmarkerToShapeWeights(source: ImageSource, options?: FaceLandmarkerOptions): Promise<FaceShapeWeights | null>;
39
+ /**
40
+ * Load the FaceLandmarker WASM bundle eagerly — call this on app start
41
+ * to avoid a cold-start delay when the user first uploads a photo.
42
+ */
43
+ export declare function prefetchFaceLandmarker(): void;
44
+ export {};