Spaces:
Runtime error
Runtime error
File size: 1,523 Bytes
b040061 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | import { useState, useRef, useCallback } from 'react';
const BACKEND_URL = import.meta.env.VITE_BACKEND_URL || (import.meta.env.DEV ? 'http://localhost:8000' : '');
export default function useTTS() {
const [isSpeaking, setIsSpeaking] = useState(false);
const audioRef = useRef(null);
const speak = useCallback(async (text) => {
if (!text) return;
setIsSpeaking(true);
try {
const res = await fetch(`${BACKEND_URL}/api/tts`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text }),
});
if (!res.ok) throw new Error('TTS failed');
const blob = await res.blob();
const url = URL.createObjectURL(blob);
const audio = new Audio(url);
audioRef.current = audio;
return new Promise((resolve) => {
audio.onended = () => {
setIsSpeaking(false);
URL.revokeObjectURL(url);
resolve();
};
audio.onerror = () => {
setIsSpeaking(false);
URL.revokeObjectURL(url);
resolve();
};
audio.play().catch(() => {
setIsSpeaking(false);
resolve();
});
});
} catch (err) {
console.error('TTS error:', err);
setIsSpeaking(false);
}
}, []);
const stop = useCallback(() => {
if (audioRef.current) {
audioRef.current.pause();
audioRef.current.currentTime = 0;
}
setIsSpeaking(false);
}, []);
return { speak, stop, isSpeaking };
}
|