story-generator/src/features/voice-commands/hooks/useSpeechRecognition.ts
2025-01-26 11:11:04 -03:00

100 lines
2.7 KiB
TypeScript

import { useState, useEffect, useCallback } from 'react';
import { SpeechRecognition } from '../../../types/speech';
type RecognitionState = 'idle' | 'recording' | 'processing' | 'error';
interface UseSpeechRecognitionReturn {
transcript: string;
start: () => void;
stop: () => void;
reset: () => void;
status: RecognitionState;
error: string | null;
isSupported: boolean;
}
export function useSpeechRecognition(): UseSpeechRecognitionReturn {
const [status, setStatus] = useState<RecognitionState>('idle');
const [transcript, setTranscript] = useState('');
const [error, setError] = useState<string | null>(null);
const [recognition, setRecognition] = useState<SpeechRecognition | null>(null);
const isSupported = typeof window !== 'undefined' && ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window);
useEffect(() => {
if (!isSupported) {
setError('Reconhecimento de voz não é suportado neste navegador');
return;
}
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();
recognition.continuous = false;
recognition.lang = 'pt-BR';
recognition.interimResults = false;
recognition.maxAlternatives = 1;
recognition.onstart = () => setStatus('recording');
recognition.onend = () => setStatus('idle');
recognition.onerror = (event) => {
setStatus('error');
setError(`Erro na gravação: ${event.error}`);
};
recognition.onresult = (event) => {
const result = event.results[0][0].transcript;
setTranscript(prev => prev + ' ' + result);
setStatus('processing');
setTimeout(() => setStatus('idle'), 2000);
};
setRecognition(recognition);
}, [isSupported]);
const start = useCallback(() => {
if (!recognition || status === 'recording') return;
setTranscript('');
setError(null);
try {
recognition.start();
} catch (err) {
setError('Não foi possível iniciar a gravação');
setStatus('error');
}
}, [recognition, status]);
const stop = useCallback(() => {
if (recognition && status === 'recording') {
recognition.stop();
}
}, [recognition, status]);
const reset = useCallback(() => {
setTranscript('');
setError(null);
setStatus('idle');
}, []);
useEffect(() => {
if (status === 'recording') {
const timeout = setTimeout(() => {
stop();
setError('Tempo máximo de gravação atingido (2 minutos)');
}, 120_000);
return () => clearTimeout(timeout);
}
}, [status, stop]);
return {
transcript,
start,
stop,
reset,
status,
error,
isSupported
};
}