///
'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 }
}