@sage-rsc/talking-head-react 1.0.70 → 1.0.71
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.cjs +2 -2
- package/dist/index.js +459 -448
- package/package.json +1 -1
- package/src/components/SimpleTalkingAvatar.jsx +27 -9
package/package.json
CHANGED
|
@@ -178,7 +178,7 @@ const SimpleTalkingAvatar = forwardRef(({
|
|
|
178
178
|
setIsLoading(false);
|
|
179
179
|
onError(err);
|
|
180
180
|
}
|
|
181
|
-
}, [
|
|
181
|
+
}, []); // Empty deps - only initialize once
|
|
182
182
|
|
|
183
183
|
useEffect(() => {
|
|
184
184
|
initializeTalkingHead();
|
|
@@ -192,15 +192,31 @@ const SimpleTalkingAvatar = forwardRef(({
|
|
|
192
192
|
};
|
|
193
193
|
}, [initializeTalkingHead]);
|
|
194
194
|
|
|
195
|
+
// Resume audio context helper
|
|
196
|
+
const resumeAudioContext = useCallback(async () => {
|
|
197
|
+
if (talkingHeadRef.current) {
|
|
198
|
+
try {
|
|
199
|
+
// Try to access audio context through talkingHead instance
|
|
200
|
+
const audioCtx = talkingHeadRef.current.audioCtx || talkingHeadRef.current.audioContext;
|
|
201
|
+
if (audioCtx && (audioCtx.state === 'suspended' || audioCtx.state === 'interrupted')) {
|
|
202
|
+
await audioCtx.resume();
|
|
203
|
+
console.log('Audio context resumed');
|
|
204
|
+
}
|
|
205
|
+
} catch (err) {
|
|
206
|
+
console.warn('Failed to resume audio context:', err);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}, []);
|
|
210
|
+
|
|
195
211
|
// Auto-speak text when ready and autoSpeak is true
|
|
196
212
|
useEffect(() => {
|
|
197
213
|
if (isReady && text && autoSpeak && talkingHeadRef.current) {
|
|
198
214
|
speakText(text);
|
|
199
215
|
}
|
|
200
|
-
}, [isReady, text, autoSpeak]);
|
|
216
|
+
}, [isReady, text, autoSpeak, speakText]);
|
|
201
217
|
|
|
202
218
|
// Speak text with proper callback handling
|
|
203
|
-
const speakText = useCallback((textToSpeak, options = {}) => {
|
|
219
|
+
const speakText = useCallback(async (textToSpeak, options = {}) => {
|
|
204
220
|
if (!talkingHeadRef.current || !isReady) {
|
|
205
221
|
console.warn('Avatar not ready for speaking');
|
|
206
222
|
return;
|
|
@@ -211,6 +227,9 @@ const SimpleTalkingAvatar = forwardRef(({
|
|
|
211
227
|
return;
|
|
212
228
|
}
|
|
213
229
|
|
|
230
|
+
// Always resume audio context first (required for user interaction)
|
|
231
|
+
await resumeAudioContext();
|
|
232
|
+
|
|
214
233
|
// Reset speech progress tracking
|
|
215
234
|
speechProgressRef.current = { remainingText: null, originalText: null, options: null };
|
|
216
235
|
originalSentencesRef.current = [];
|
|
@@ -255,7 +274,7 @@ const SimpleTalkingAvatar = forwardRef(({
|
|
|
255
274
|
console.error('Error speaking text:', err);
|
|
256
275
|
setError(err.message || 'Failed to speak text');
|
|
257
276
|
}
|
|
258
|
-
}, [isReady, onSpeechEnd]);
|
|
277
|
+
}, [isReady, onSpeechEnd, resumeAudioContext]);
|
|
259
278
|
|
|
260
279
|
// Pause speaking
|
|
261
280
|
const pauseSpeaking = useCallback(() => {
|
|
@@ -308,10 +327,8 @@ const SimpleTalkingAvatar = forwardRef(({
|
|
|
308
327
|
if (!talkingHeadRef.current || !isPaused) return;
|
|
309
328
|
|
|
310
329
|
try {
|
|
311
|
-
// Resume audio context
|
|
312
|
-
|
|
313
|
-
await talkingHeadRef.current.audioContext.resume();
|
|
314
|
-
}
|
|
330
|
+
// Resume audio context first
|
|
331
|
+
await resumeAudioContext();
|
|
315
332
|
|
|
316
333
|
setIsPaused(false);
|
|
317
334
|
isPausedRef.current = false;
|
|
@@ -331,7 +348,7 @@ const SimpleTalkingAvatar = forwardRef(({
|
|
|
331
348
|
setIsPaused(false);
|
|
332
349
|
isPausedRef.current = false;
|
|
333
350
|
}
|
|
334
|
-
}, [isPaused, speakText]);
|
|
351
|
+
}, [isPaused, speakText, resumeAudioContext]);
|
|
335
352
|
|
|
336
353
|
// Stop speaking
|
|
337
354
|
const stopSpeaking = useCallback(() => {
|
|
@@ -352,6 +369,7 @@ const SimpleTalkingAvatar = forwardRef(({
|
|
|
352
369
|
pauseSpeaking,
|
|
353
370
|
resumeSpeaking,
|
|
354
371
|
stopSpeaking,
|
|
372
|
+
resumeAudioContext,
|
|
355
373
|
isPaused: () => isPaused,
|
|
356
374
|
setMood: (mood) => talkingHeadRef.current?.setMood(mood),
|
|
357
375
|
setBodyMovement: (movement) => {
|