All files / lib/awareness/collective/components/hooks useVoiceSynthesis.ts

68.75% Statements 22/32
71.42% Branches 5/7
60% Functions 3/5
68.75% Lines 22/32

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 421x     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 };
}