@lakshmiprasanth/react-voice-to-text
Version:
A modern React package for voice-to-text conversion with real-time speech recognition and file upload support
202 lines (197 loc) • 7.32 kB
JavaScript
;
var react = require('react');
/**
* Check browser support for speech recognition and related APIs
*/
function getBrowserSupport() {
if (typeof window === 'undefined') {
return {
webSpeechAPI: false,
mediaRecorder: false,
getUserMedia: false,
browser: {
name: 'unknown',
version: 'unknown'
}
};
}
const browserInfo = getBrowserInfo();
return {
webSpeechAPI: 'SpeechRecognition' in window || 'webkitSpeechRecognition' in window,
mediaRecorder: 'MediaRecorder' in window,
getUserMedia: 'mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices,
browser: browserInfo
};
}
/**
* Get browser name and version
*/
function getBrowserInfo() {
if (typeof navigator === 'undefined') {
return { name: 'unknown', version: 'unknown' };
}
const userAgent = navigator.userAgent;
let name = 'unknown';
let version = 'unknown';
// Chrome
if (userAgent.includes('Chrome') && !userAgent.includes('Edg')) {
name = 'Chrome';
const match = userAgent.match(/Chrome\/(\d+)/);
if (match)
version = match[1];
}
// Safari
else if (userAgent.includes('Safari') && !userAgent.includes('Chrome')) {
name = 'Safari';
const match = userAgent.match(/Version\/(\d+)/);
if (match)
version = match[1];
}
// Firefox
else if (userAgent.includes('Firefox')) {
name = 'Firefox';
const match = userAgent.match(/Firefox\/(\d+)/);
if (match)
version = match[1];
}
// Edge
else if (userAgent.includes('Edg')) {
name = 'Edge';
const match = userAgent.match(/Edg\/(\d+)/);
if (match)
version = match[1];
}
return { name, version };
}
const useSpeechRecognition = (options = {}) => {
const { language = 'en-US', continuous = true, interimResults = true, maxAlternatives = 1, onResult, onError, onStart, onEnd, onAudioStart, onAudioEnd, onSoundStart, onSoundEnd, onSpeechStart, onSpeechEnd, onNoMatch, onNomatch } = options;
const [isSupported, setIsSupported] = react.useState(false);
const [isListening, setIsListening] = react.useState(false);
const [transcript, setTranscript] = react.useState('');
const [finalTranscript, setFinalTranscript] = react.useState('');
const [interimTranscript, setInterimTranscript] = react.useState('');
const [error, setError] = react.useState(null);
const recognitionRef = react.useRef(null);
const finalTranscriptRef = react.useRef('');
// Check browser support and initialize
react.useEffect(() => {
const support = getBrowserSupport();
setIsSupported(support.webSpeechAPI);
if (support.webSpeechAPI) {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
recognitionRef.current = new SpeechRecognition();
const recognition = recognitionRef.current;
// Configure recognition
recognition.continuous = continuous;
recognition.interimResults = interimResults;
recognition.lang = language;
recognition.maxAlternatives = maxAlternatives;
// Set up event listeners
recognition.onresult = (event) => {
let interimTranscript = '';
let finalTranscript = '';
for (let i = event.resultIndex; i < event.results.length; i++) {
const transcript = event.results[i][0].transcript;
if (event.results[i].isFinal) {
finalTranscript += transcript;
}
else {
interimTranscript += transcript;
}
}
finalTranscriptRef.current = finalTranscript;
setFinalTranscript(finalTranscript);
setInterimTranscript(interimTranscript);
setTranscript(finalTranscript + interimTranscript);
onResult?.(event);
};
recognition.onerror = (event) => {
setError(event.error);
setIsListening(false);
onError?.(event);
};
recognition.onstart = () => {
setIsListening(true);
setError(null);
onStart?.();
};
recognition.onend = () => {
setIsListening(false);
onEnd?.();
};
recognition.onaudiostart = onAudioStart;
recognition.onaudioend = onAudioEnd;
recognition.onsoundstart = onSoundStart;
recognition.onsoundend = onSoundEnd;
recognition.onspeechstart = onSpeechStart;
recognition.onspeechend = onSpeechEnd;
recognition.onnomatch = onNomatch || onNoMatch;
}
// Cleanup
return () => {
if (recognitionRef.current) {
recognitionRef.current.abort();
}
};
}, [continuous, interimResults, language, maxAlternatives, onResult, onError, onStart, onEnd, onAudioStart, onAudioEnd, onSoundStart, onSoundEnd, onSpeechStart, onSpeechEnd, onNoMatch, onNomatch]);
const start = react.useCallback(() => {
if (!isSupported || !recognitionRef.current) {
setError('Speech recognition is not supported');
return;
}
try {
recognitionRef.current.start();
}
catch (err) {
setError(err instanceof Error ? err.message : 'Failed to start recognition');
}
}, [isSupported]);
const stop = react.useCallback(() => {
if (recognitionRef.current) {
recognitionRef.current.stop();
}
}, []);
const abort = react.useCallback(() => {
if (recognitionRef.current) {
recognitionRef.current.abort();
}
}, []);
const reset = react.useCallback(() => {
setTranscript('');
setFinalTranscript('');
setInterimTranscript('');
setError(null);
finalTranscriptRef.current = '';
}, []);
const updateConfig = react.useCallback((config) => {
if (recognitionRef.current) {
if (config.language !== undefined) {
recognitionRef.current.lang = config.language;
}
if (config.continuous !== undefined) {
recognitionRef.current.continuous = config.continuous;
}
if (config.interimResults !== undefined) {
recognitionRef.current.interimResults = config.interimResults;
}
if (config.maxAlternatives !== undefined) {
recognitionRef.current.maxAlternatives = config.maxAlternatives;
}
}
}, []);
return {
isSupported,
isListening,
transcript,
finalTranscript,
interimTranscript,
error,
start,
stop,
abort,
reset,
updateConfig
};
};
exports.useSpeechRecognition = useSpeechRecognition;
//# sourceMappingURL=useSpeechRecognition.js.map