Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 1x 1x 1x 1x 9x 9x 9x 9x 3x 3x 3x 3x 3x 9x 9x 3x 9x 4x 4x 4x 9x 9x | /**
* useVoiceSynthesis.ts
* Hook to convert text summaries into speech using Web Speech API
*/
import { useEffect, useRef, useState } from 'react';
export function useVoiceSynthesis() {
const synthRef = useRef<SpeechSynthesis | null>(null);
const [isSpeaking, setIsSpeaking] = useState(false);
const [voice, setVoice] = useState<SpeechSynthesisVoice | null>(null);
useEffect(() => {
synthRef.current = window.speechSynthesis;
const voices = synthRef.current.getVoices();
const englishVoice = voices.find(
(v) => v.lang.startsWith('en') && (v.name.includes('Google') || v.name.includes('Microsoft'))
);
setVoice(englishVoice || voices[0] || null);
}, []);
const speak = (text: string) => {
if (!synthRef.current || !voice) return;
synthRef.current.cancel();
const utter = new SpeechSynthesisUtterance(text);
utter.voice = voice;
utter.pitch = 1;
utter.rate = 1.02;
utter.volume = 1;
utter.onstart = () => setIsSpeaking(true);
utter.onend = () => setIsSpeaking(false);
synthRef.current.speak(utter);
};
const stop = () => {
synthRef.current?.cancel();
setIsSpeaking(false);
};
return { speak, stop, isSpeaking };
}
|