@memori.ai/memori-react 7.7.0 → 7.7.1
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/CHANGELOG.md +12 -0
- package/dist/components/Avatar/Avatar.js +2 -2
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +3 -4
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +6 -10
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.d.ts +17 -11
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js +111 -110
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +4 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +4 -2
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/index.d.ts +3 -5
- package/dist/components/Avatar/AvatarView/index.js +2 -2
- package/dist/components/Avatar/AvatarView/index.js.map +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.js +119 -117
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/components/layouts/ZoomedFullBody.js.map +1 -1
- package/dist/components/layouts/zoomed-full-body.css +1 -1
- package/dist/context/visemeContext.d.ts +15 -8
- package/dist/context/visemeContext.js +191 -64
- package/dist/context/visemeContext.js.map +1 -1
- package/dist/styles.css +0 -1
- package/esm/components/Avatar/Avatar.js +2 -2
- package/esm/components/Avatar/Avatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +3 -4
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +6 -10
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.d.ts +17 -11
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js +113 -112
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +4 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +4 -2
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/index.d.ts +3 -5
- package/esm/components/Avatar/AvatarView/index.js +2 -2
- package/esm/components/Avatar/AvatarView/index.js.map +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.js +119 -117
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/components/layouts/ZoomedFullBody.js.map +1 -1
- package/esm/components/layouts/zoomed-full-body.css +1 -1
- package/esm/context/visemeContext.d.ts +15 -8
- package/esm/context/visemeContext.js +192 -65
- package/esm/context/visemeContext.js.map +1 -1
- package/esm/styles.css +0 -1
- package/package.json +1 -1
- package/src/components/Avatar/Avatar.stories.tsx +5 -7
- package/src/components/Avatar/Avatar.tsx +5 -3
- package/src/components/Avatar/AvatarView/AvatarComponent/avatarComponent.tsx +19 -20
- package/src/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.tsx +158 -179
- package/src/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.tsx +7 -1
- package/src/components/Avatar/AvatarView/AvatarView.stories.tsx +24 -36
- package/src/components/Avatar/AvatarView/index.tsx +8 -3
- package/src/components/MemoriWidget/MemoriWidget.tsx +161 -140
- package/src/components/layouts/ZoomedFullBody.test.tsx +1 -1
- package/src/components/layouts/ZoomedFullBody.tsx +2 -2
- package/src/components/layouts/zoomed-full-body.css +1 -1
- package/src/context/visemeContext.tsx +298 -111
- package/src/index.stories.tsx +23 -21
- package/src/styles.css +0 -1
|
@@ -1,145 +1,332 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
useContext,
|
|
4
|
+
useState,
|
|
5
|
+
useCallback,
|
|
6
|
+
useRef,
|
|
7
|
+
useEffect,
|
|
8
|
+
} from 'react';
|
|
9
|
+
import { MathUtils, SkinnedMesh } from 'three';
|
|
2
10
|
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
11
|
+
type AzureViseme = { visemeId: number; audioOffset: number };
|
|
12
|
+
|
|
13
|
+
type ProcessedViseme = {
|
|
14
|
+
name: string;
|
|
15
|
+
duration: number;
|
|
16
|
+
weight: number;
|
|
17
|
+
startTime: number;
|
|
8
18
|
};
|
|
9
19
|
|
|
10
20
|
interface VisemeContextType {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
setMeshRef: (mesh: SkinnedMesh | null) => void;
|
|
22
|
+
addVisemeToQueue: (viseme: AzureViseme) => void;
|
|
23
|
+
processVisemeQueue: () => ProcessedViseme[];
|
|
24
|
+
clearVisemes: () => void;
|
|
25
|
+
isMeshSet: boolean;
|
|
26
|
+
setEmotion: (emotion: string) => void;
|
|
27
|
+
emotion: string;
|
|
28
|
+
getAzureStyleForEmotion: (emotion: string) => string;
|
|
17
29
|
}
|
|
18
30
|
|
|
19
31
|
const VisemeContext = createContext<VisemeContextType | undefined>(undefined);
|
|
20
32
|
|
|
33
|
+
const VISEME_SMOOTHING = 0.3;
|
|
34
|
+
const DEFAULT_VISEME_DURATION = 0.1;
|
|
35
|
+
const MINIMUM_ELAPSED_TIME = 0.01;
|
|
36
|
+
const VISEME_SPEED_FACTOR = 1;
|
|
37
|
+
const AUDIO_PLAYBACK_RATE = 1;
|
|
38
|
+
const VISEME_BASE_SPEED = 1;
|
|
39
|
+
|
|
21
40
|
const VISEME_MAP: { [key: number]: string } = {
|
|
22
|
-
0: 'viseme_sil',
|
|
23
|
-
1: 'viseme_PP',
|
|
24
|
-
2: 'viseme_FF',
|
|
25
|
-
3: 'viseme_TH',
|
|
26
|
-
4: 'viseme_DD',
|
|
27
|
-
5: 'viseme_kk',
|
|
28
|
-
6: 'viseme_CH',
|
|
29
|
-
7: 'viseme_SS',
|
|
30
|
-
8: 'viseme_nn',
|
|
31
|
-
9: 'viseme_RR',
|
|
32
|
-
10: 'viseme_aa',
|
|
33
|
-
11: 'viseme_E',
|
|
34
|
-
12: 'viseme_I',
|
|
35
|
-
13: 'viseme_O',
|
|
36
|
-
14: 'viseme_U',
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
21: 'viseme_PP', // y (closest match, could be debated)
|
|
41
|
+
0: 'viseme_sil',
|
|
42
|
+
1: 'viseme_PP',
|
|
43
|
+
2: 'viseme_FF',
|
|
44
|
+
3: 'viseme_TH',
|
|
45
|
+
4: 'viseme_DD',
|
|
46
|
+
5: 'viseme_kk',
|
|
47
|
+
6: 'viseme_CH',
|
|
48
|
+
7: 'viseme_SS',
|
|
49
|
+
8: 'viseme_nn',
|
|
50
|
+
9: 'viseme_RR',
|
|
51
|
+
10: 'viseme_aa',
|
|
52
|
+
11: 'viseme_E',
|
|
53
|
+
12: 'viseme_I',
|
|
54
|
+
13: 'viseme_O',
|
|
55
|
+
14: 'viseme_U',
|
|
56
|
+
15: 'viseme_kk',
|
|
57
|
+
16: 'viseme_CH',
|
|
58
|
+
17: 'viseme_SS',
|
|
59
|
+
18: 'viseme_TH',
|
|
60
|
+
19: 'viseme_RR',
|
|
61
|
+
20: 'viseme_kk',
|
|
62
|
+
21: 'viseme_PP',
|
|
45
63
|
};
|
|
46
64
|
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const visemeQueueRef = useRef<
|
|
65
|
+
export const VisemeProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
66
|
+
children,
|
|
67
|
+
}) => {
|
|
68
|
+
const [isMeshSet, setIsMeshSet] = useState(false);
|
|
69
|
+
const [emotion, setEmotion] = useState('Neutral');
|
|
70
|
+
const isAnimatingRef = useRef(false);
|
|
71
|
+
const currentVisemesRef = useRef<ProcessedViseme[]>([]);
|
|
72
|
+
const visemeQueueRef = useRef<AzureViseme[]>([]);
|
|
73
|
+
const animationFrameRef = useRef<number | null>(null);
|
|
55
74
|
const startTimeRef = useRef<number | null>(null);
|
|
56
|
-
const [
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
const addViseme = useCallback((visemeId: number, audioOffset: number) => {
|
|
60
|
-
const visemeName = VISEME_MAP[visemeId] || 'viseme_sil';
|
|
61
|
-
const startTime = audioOffset / 10000000 + TIME_OFFSET;
|
|
62
|
-
const endTime = startTime + DEFAULT_VISEME_DURATION;
|
|
63
|
-
const newViseme: Viseme = {
|
|
64
|
-
name: visemeName,
|
|
65
|
-
weight: 0,
|
|
66
|
-
startTime,
|
|
67
|
-
endTime,
|
|
68
|
-
};
|
|
69
|
-
visemeQueueRef.current.push(newViseme);
|
|
75
|
+
const currentVisemeWeightRef = useRef<{ [key: string]: number }>({});
|
|
76
|
+
const meshRef = useRef<SkinnedMesh | null>(null);
|
|
70
77
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}, [isProcessing]);
|
|
78
|
+
const lerp = (start: number, end: number, alpha: number): number => {
|
|
79
|
+
return start * (1 - alpha) + end * alpha;
|
|
80
|
+
};
|
|
75
81
|
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
82
|
+
const easeInOutQuad = (x: number): number => {
|
|
83
|
+
return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2;
|
|
84
|
+
};
|
|
81
85
|
|
|
82
|
-
|
|
86
|
+
const setMeshRef = useCallback(
|
|
87
|
+
(mesh: SkinnedMesh | null) => {
|
|
88
|
+
if (mesh && mesh.morphTargetDictionary && mesh.morphTargetInfluences) {
|
|
89
|
+
meshRef.current = mesh;
|
|
90
|
+
setIsMeshSet(true);
|
|
91
|
+
} else {
|
|
92
|
+
console.error('Invalid mesh provided:', mesh);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
[meshRef]
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const addVisemeToQueue = useCallback((viseme: AzureViseme) => {
|
|
99
|
+
visemeQueueRef.current.push(viseme);
|
|
100
|
+
}, []);
|
|
83
101
|
|
|
84
|
-
|
|
85
|
-
|
|
102
|
+
const getCurrentViseme = useCallback((elapsedTime: number) => {
|
|
103
|
+
if (elapsedTime < MINIMUM_ELAPSED_TIME) return null;
|
|
86
104
|
|
|
87
|
-
|
|
88
|
-
|
|
105
|
+
return currentVisemesRef.current.find((viseme, index) => {
|
|
106
|
+
const nextViseme = currentVisemesRef.current[index + 1];
|
|
107
|
+
return (
|
|
108
|
+
elapsedTime >= viseme.startTime &&
|
|
109
|
+
(!nextViseme || elapsedTime < nextViseme.startTime)
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
}, []);
|
|
113
|
+
|
|
114
|
+
const getDynamicSpeedFactor = (visemeDuration: number): number => {
|
|
115
|
+
const baseDuration = 0.1;
|
|
116
|
+
return (
|
|
117
|
+
VISEME_BASE_SPEED * (baseDuration / visemeDuration) * AUDIO_PLAYBACK_RATE
|
|
89
118
|
);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const applyViseme = useCallback(
|
|
122
|
+
(viseme: ProcessedViseme, elapsedTime: number) => {
|
|
123
|
+
if (!meshRef.current) {
|
|
124
|
+
console.error('Mesh not set');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const visemeProgress = Math.min(
|
|
129
|
+
(elapsedTime - viseme.startTime) / viseme.duration,
|
|
130
|
+
1
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
const dynamicSpeedFactor = getDynamicSpeedFactor(viseme.duration);
|
|
134
|
+
const adjustedProgress = visemeProgress * dynamicSpeedFactor;
|
|
135
|
+
|
|
136
|
+
const easedProgress = easeInOutQuad(adjustedProgress);
|
|
137
|
+
const targetWeight = Math.sin(easedProgress * Math.PI) * viseme.weight;
|
|
138
|
+
|
|
139
|
+
currentVisemeWeightRef.current[viseme.name] = MathUtils.lerp(
|
|
140
|
+
currentVisemeWeightRef.current[viseme.name] || 0,
|
|
141
|
+
targetWeight,
|
|
142
|
+
VISEME_SMOOTHING
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
const visemeIndex = meshRef.current.morphTargetDictionary?.[viseme.name];
|
|
146
|
+
if (
|
|
147
|
+
typeof visemeIndex === 'number' &&
|
|
148
|
+
meshRef.current.morphTargetInfluences
|
|
149
|
+
) {
|
|
150
|
+
meshRef.current.morphTargetInfluences[visemeIndex] =
|
|
151
|
+
currentVisemeWeightRef.current[viseme.name];
|
|
152
|
+
} else {
|
|
153
|
+
console.error(
|
|
154
|
+
`Viseme not found in morph target dictionary: ${viseme.name}`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
Object.keys(currentVisemeWeightRef.current).forEach((visemeName) => {
|
|
159
|
+
if (visemeName !== viseme.name) {
|
|
160
|
+
currentVisemeWeightRef.current[visemeName] = lerp(
|
|
161
|
+
currentVisemeWeightRef.current[visemeName],
|
|
162
|
+
0,
|
|
163
|
+
VISEME_SMOOTHING * 0.5
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const index = meshRef.current!.morphTargetDictionary?.[visemeName];
|
|
167
|
+
if (typeof index === 'number' && meshRef.current!.morphTargetInfluences) {
|
|
168
|
+
meshRef.current!.morphTargetInfluences[index] = currentVisemeWeightRef.current[visemeName];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
[]
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
const animate = useCallback(
|
|
177
|
+
(time: number) => {
|
|
178
|
+
if (startTimeRef.current === null) {
|
|
179
|
+
startTimeRef.current = time;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const elapsedTime =
|
|
183
|
+
((time - startTimeRef.current) / 1000) * VISEME_SPEED_FACTOR;
|
|
184
|
+
|
|
185
|
+
const currentViseme = getCurrentViseme(elapsedTime);
|
|
90
186
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
187
|
+
if (currentViseme) {
|
|
188
|
+
applyViseme(currentViseme, elapsedTime);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (
|
|
192
|
+
currentVisemesRef.current.length > 0 &&
|
|
193
|
+
elapsedTime <
|
|
194
|
+
currentVisemesRef.current[currentVisemesRef.current.length - 1]
|
|
195
|
+
.startTime +
|
|
196
|
+
currentVisemesRef.current[currentVisemesRef.current.length - 1]
|
|
197
|
+
.duration
|
|
198
|
+
) {
|
|
199
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
200
|
+
} else {
|
|
201
|
+
clearVisemes();
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
[getCurrentViseme, applyViseme]
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
const processVisemeQueue = useCallback(() => {
|
|
208
|
+
const azureVisemes = [...visemeQueueRef.current];
|
|
209
|
+
visemeQueueRef.current = [];
|
|
210
|
+
|
|
211
|
+
if (azureVisemes.length === 0) {
|
|
212
|
+
return [];
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const processedVisemes: ProcessedViseme[] = azureVisemes.map(
|
|
216
|
+
(currentViseme, i) => {
|
|
217
|
+
const nextViseme = azureVisemes[i + 1];
|
|
218
|
+
const duration = nextViseme
|
|
219
|
+
? (nextViseme.audioOffset - currentViseme.audioOffset) / 10000000
|
|
220
|
+
: DEFAULT_VISEME_DURATION;
|
|
221
|
+
|
|
222
|
+
const processedViseme = {
|
|
223
|
+
name: VISEME_MAP[currentViseme.visemeId] || 'viseme_sil',
|
|
224
|
+
duration,
|
|
225
|
+
weight: 1,
|
|
226
|
+
startTime: currentViseme.audioOffset / 10000000,
|
|
227
|
+
};
|
|
228
|
+
return processedViseme;
|
|
229
|
+
}
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
const interpolatedVisemes: ProcessedViseme[] = [];
|
|
233
|
+
for (let i = 0; i < processedVisemes.length - 1; i++) {
|
|
234
|
+
const currentViseme = processedVisemes[i];
|
|
235
|
+
const nextViseme = processedVisemes[i + 1];
|
|
236
|
+
|
|
237
|
+
interpolatedVisemes.push(currentViseme);
|
|
95
238
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return updatedViseme;
|
|
239
|
+
const intermediateDuration = (nextViseme.startTime - currentViseme.startTime) * 0.5;
|
|
240
|
+
interpolatedVisemes.push({
|
|
241
|
+
name: 'viseme_sil',
|
|
242
|
+
duration: intermediateDuration,
|
|
243
|
+
weight: 0.5,
|
|
244
|
+
startTime: currentViseme.startTime + intermediateDuration,
|
|
245
|
+
});
|
|
104
246
|
}
|
|
247
|
+
interpolatedVisemes.push(processedVisemes[processedVisemes.length - 1]);
|
|
248
|
+
|
|
249
|
+
currentVisemesRef.current = interpolatedVisemes;
|
|
105
250
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
251
|
+
if (!isAnimatingRef.current) {
|
|
252
|
+
isAnimatingRef.current = true;
|
|
253
|
+
startTimeRef.current = performance.now();
|
|
254
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
255
|
+
} else {
|
|
256
|
+
if (startTimeRef.current !== null) {
|
|
257
|
+
const currentTime = performance.now();
|
|
258
|
+
const elapsedTime =
|
|
259
|
+
((currentTime - startTimeRef.current) / 1000) * VISEME_SPEED_FACTOR;
|
|
260
|
+
startTimeRef.current =
|
|
261
|
+
currentTime - (elapsedTime / VISEME_SPEED_FACTOR) * 1000;
|
|
112
262
|
}
|
|
113
263
|
}
|
|
114
264
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}, [isProcessing]);
|
|
265
|
+
return interpolatedVisemes;
|
|
266
|
+
}, [animate]);
|
|
118
267
|
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
268
|
+
const clearVisemes = useCallback(() => {
|
|
269
|
+
currentVisemesRef.current = [];
|
|
270
|
+
visemeQueueRef.current = [];
|
|
271
|
+
|
|
272
|
+
if (animationFrameRef.current !== null) {
|
|
273
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
274
|
+
animationFrameRef.current = null;
|
|
275
|
+
}
|
|
124
276
|
|
|
125
|
-
|
|
126
|
-
|
|
277
|
+
if (
|
|
278
|
+
meshRef.current?.morphTargetDictionary &&
|
|
279
|
+
meshRef.current?.morphTargetInfluences
|
|
280
|
+
) {
|
|
281
|
+
Object.values(meshRef.current.morphTargetDictionary).forEach(index => {
|
|
282
|
+
if (typeof index === 'number') {
|
|
283
|
+
meshRef.current!.morphTargetInfluences![index] = 0;
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
currentVisemeWeightRef.current = {};
|
|
127
289
|
startTimeRef.current = null;
|
|
128
|
-
|
|
290
|
+
isAnimatingRef.current = false;
|
|
129
291
|
}, []);
|
|
130
292
|
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
293
|
+
const emotionMap: Record<string, Record<string, number>> = {
|
|
294
|
+
Gioia: { Gioria: 1 },
|
|
295
|
+
Rabbia: { Rabbia: 1 },
|
|
296
|
+
Sorpresa: { Sorpresa: 1 },
|
|
297
|
+
Tristezza: { Tristezza: 1 },
|
|
298
|
+
Timore: { Timore: 1 },
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const emotionToAzureStyleMap: Record<string, string> = {
|
|
302
|
+
Gioia: 'cheerful',
|
|
303
|
+
Rabbia: 'angry',
|
|
304
|
+
Sorpresa: 'excited',
|
|
305
|
+
Tristezza: 'sad',
|
|
306
|
+
Timore: 'terrified',
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
function getAzureStyleForEmotion(emotion: string): string {
|
|
310
|
+
return emotionToAzureStyleMap[emotion] || 'neutral';
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
useEffect(() => {
|
|
314
|
+
return () => {
|
|
315
|
+
if (animationFrameRef.current !== null) {
|
|
316
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
317
|
+
}
|
|
318
|
+
};
|
|
134
319
|
}, []);
|
|
135
320
|
|
|
136
|
-
const contextValue = {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
321
|
+
const contextValue: VisemeContextType = {
|
|
322
|
+
setMeshRef,
|
|
323
|
+
addVisemeToQueue,
|
|
324
|
+
processVisemeQueue,
|
|
325
|
+
clearVisemes,
|
|
326
|
+
isMeshSet,
|
|
327
|
+
setEmotion,
|
|
328
|
+
emotion,
|
|
329
|
+
getAzureStyleForEmotion,
|
|
143
330
|
};
|
|
144
331
|
|
|
145
332
|
return (
|
|
@@ -151,7 +338,7 @@ export const VisemeProvider: React.FC<{ children: React.ReactNode }> = ({ childr
|
|
|
151
338
|
|
|
152
339
|
export const useViseme = (): VisemeContextType => {
|
|
153
340
|
const context = useContext(VisemeContext);
|
|
154
|
-
if (
|
|
341
|
+
if (context === undefined) {
|
|
155
342
|
throw new Error('useViseme must be used within a VisemeProvider');
|
|
156
343
|
}
|
|
157
344
|
return context;
|
package/src/index.stories.tsx
CHANGED
|
@@ -111,29 +111,31 @@ Giovanna.args = {
|
|
|
111
111
|
|
|
112
112
|
export const GiovannaProva = Template.bind({});
|
|
113
113
|
GiovannaProva.args = {
|
|
114
|
-
memoriName: '
|
|
115
|
-
ownerUserName: '
|
|
116
|
-
memoriID: '
|
|
117
|
-
ownerUserID: '
|
|
118
|
-
tenantID: '
|
|
119
|
-
engineURL: 'https://engine.memori.ai',
|
|
120
|
-
apiURL: 'https://backend.memori.ai',
|
|
121
|
-
baseURL: 'https://
|
|
122
|
-
uiLang: '
|
|
114
|
+
memoriName: 'Giovanna Test',
|
|
115
|
+
ownerUserName: 'andrea.patini3',
|
|
116
|
+
memoriID: '431d9819-c958-442c-a799-f90617371c0c',
|
|
117
|
+
ownerUserID: '58770358-a5db-4b49-b3a4-734fc468e745',
|
|
118
|
+
tenantID: 'aisuru-staging.aclambda.online',
|
|
119
|
+
engineURL: 'https://engine-staging.memori.ai',
|
|
120
|
+
apiURL: 'https://backend-staging.memori.ai',
|
|
121
|
+
baseURL: 'https://aisuru-staging.aclambda.online',
|
|
122
|
+
uiLang: 'EN',
|
|
123
123
|
spokenLang: 'IT',
|
|
124
124
|
layout: 'ZOOMED_FULL_BODY',
|
|
125
|
-
showInstruct: false,
|
|
126
|
-
showSettings: true,
|
|
127
|
-
showClear: false,
|
|
128
|
-
showAIicon: true,
|
|
129
|
-
showWhyThisAnswer: true,
|
|
130
|
-
showTypingText: false,
|
|
131
|
-
showOnlyLastMessages: false,
|
|
132
|
-
showTranslationOriginal: false,
|
|
133
|
-
showCopyButton: false,
|
|
134
|
-
showShare: true,
|
|
135
|
-
showLogin: false,
|
|
136
|
-
enableAudio: true,
|
|
125
|
+
showInstruct: 'false',
|
|
126
|
+
showSettings: 'true',
|
|
127
|
+
showClear: 'false',
|
|
128
|
+
showAIicon: 'true',
|
|
129
|
+
showWhyThisAnswer: 'true',
|
|
130
|
+
showTypingText: 'false',
|
|
131
|
+
showOnlyLastMessages: 'false',
|
|
132
|
+
showTranslationOriginal: 'false',
|
|
133
|
+
showCopyButton: 'false',
|
|
134
|
+
showShare: 'true',
|
|
135
|
+
showLogin: 'false',
|
|
136
|
+
enableAudio: 'true',
|
|
137
|
+
integrationID: 'e92ac275-39b5-474d-8f9e-826cc5284f1e',
|
|
138
|
+
initialQuestion: 'inizio simulazione',
|
|
137
139
|
};
|
|
138
140
|
|
|
139
141
|
const TemplateWithBatchButton: Story<Props> = args => (
|
package/src/styles.css
CHANGED
|
@@ -53,7 +53,6 @@
|
|
|
53
53
|
@import url('./components/layouts/website-assistant.css');
|
|
54
54
|
@import url('./components/layouts/chat.css');
|
|
55
55
|
@import url('./components/layouts/zoomed-full-body.css');
|
|
56
|
-
|
|
57
56
|
@import url('https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css');
|
|
58
57
|
|
|
59
58
|
.sr-only {
|