/// 'use client' import { useCallback, useEffect, useRef, useState } from 'react' type VoiceState = 'idle' | 'listening' | 'processing' | 'error' interface UseVoiceTranscriptionOptions { onTranscript: (text: string) => void onError?: (message: string) => void lang?: string } export function useVoiceTranscription({ onTranscript, onError, lang = 'fr-FR' }: UseVoiceTranscriptionOptions) { const [state, setState] = useState('idle') const recognitionRef = useRef(null) const accumulatedRef = useRef('') const isSupported = typeof window !== 'undefined' && ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window) const start = useCallback(() => { if (!isSupported) { onError?.('La reconnaissance vocale n\'est pas disponible sur ce navigateur.') setState('error') return } const SR = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition const rec: SpeechRecognition = new SR() rec.lang = lang rec.continuous = true rec.interimResults = false accumulatedRef.current = '' rec.onstart = () => setState('listening') rec.onresult = (event: SpeechRecognitionEvent) => { let transcript = '' for (let i = event.resultIndex; i < event.results.length; i++) { if (event.results[i].isFinal) { transcript += event.results[i][0].transcript } } if (transcript) accumulatedRef.current += (accumulatedRef.current ? ' ' : '') + transcript } rec.onerror = (event: SpeechRecognitionErrorEvent) => { console.error('[voice] SpeechRecognition error:', event.error) onError?.(event.error === 'not-allowed' ? 'Microphone non autorisé.' : `Erreur: ${event.error}`) setState('error') } rec.onend = () => { setState('idle') if (accumulatedRef.current.trim()) { onTranscript(accumulatedRef.current.trim()) accumulatedRef.current = '' } } recognitionRef.current = rec rec.start() }, [isSupported, lang, onTranscript, onError]) const stop = useCallback(() => { recognitionRef.current?.stop() recognitionRef.current = null }, []) const toggle = useCallback(() => { if (state === 'listening') { stop() } else { start() } }, [state, start, stop]) useEffect(() => { return () => { recognitionRef.current?.stop() } }, []) return { state, toggle, start, stop, isSupported } }