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 43 44 45 46 47 48 49 50 51 52 53 | import { useCallback, useEffect, useRef, useState } from 'react'; export function useSpeechRecognition(lang = 'en-US') { const isBrowser = typeof window !== 'undefined'; const [supported, setSupported] = useState(false); const [listening, setListening] = useState(false); const [transcript, setTranscript] = useState(''); const [error, setError] = useState<string | null>(null); const recRef = useRef<any>(null); useEffect(() => { if (!isBrowser) return; const SR: any = (window as any).webkitSpeechRecognition || (window as any).SpeechRecognition; if (!SR) return setSupported(false); setSupported(true); const rec = new SR(); rec.lang = lang; rec.interimResults = true; rec.continuous = true; rec.onresult = (e: any) => { let t = ''; for (let i = e.resultIndex; i < e.results.length; i++) t += e.results[i][0].transcript; setTranscript(t.trim()); }; rec.onend = () => setListening(false); rec.onerror = (ev: any) => setError(ev?.error || 'speech_recognition_error'); recRef.current = rec; return () => { try { rec.stop(); } catch {} recRef.current = null; }; }, [isBrowser, lang]); const start = useCallback(() => { setError(null); setTranscript(''); try { recRef.current?.start(); setListening(true); } catch (e: any) { setError(e?.message || 'cannot_start_recognition'); } }, []); const stop = useCallback(() => { try { recRef.current?.stop(); } catch {} setListening(false); }, []); return { supported, listening, transcript, start, stop, error, setTranscript }; } |