@lakshmiprasanth/react-voice-to-text
Version:
A modern React package for voice-to-text conversion with real-time speech recognition and file upload support
472 lines (469 loc) • 14.1 kB
JavaScript
/**
* 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 the SpeechRecognition constructor for the current browser
*/
function getSpeechRecognition() {
if (typeof window === 'undefined') {
return null;
}
return (window.SpeechRecognition ||
window.webkitSpeechRecognition ||
null);
}
/**
* 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 };
}
// Recognition utility functions for voice-to-text package
/**
* Create a new SpeechRecognition instance with the given configuration
*/
function createSpeechRecognition(config) {
const SpeechRecognition = getSpeechRecognition();
if (!SpeechRecognition) {
return null;
}
const recognition = new SpeechRecognition();
// Configure recognition properties
recognition.continuous = config.continuous ?? true;
recognition.interimResults = config.interimResults ?? true;
recognition.lang = config.language ?? 'en-US';
recognition.maxAlternatives = config.maxAlternatives ?? 1;
return recognition;
}
/**
* Check if speech recognition is available in the current environment
*/
function isSpeechRecognitionAvailable() {
const support = getBrowserSupport();
return support.webSpeechAPI;
}
/**
* Validate speech recognition configuration
*/
function validateSpeechRecognitionConfig(config) {
const errors = [];
if (config.language && !isValidLanguageCode(config.language)) {
errors.push(`Invalid language code: ${config.language}`);
}
if (config.maxAlternatives && (config.maxAlternatives < 1 || config.maxAlternatives > 10)) {
errors.push('maxAlternatives must be between 1 and 10');
}
return {
isValid: errors.length === 0,
errors
};
}
/**
* Check if a language code is valid
*/
function isValidLanguageCode(languageCode) {
// Basic validation - language codes should be in format like 'en-US', 'es-ES', etc.
const languageCodePattern = /^[a-z]{2}(-[A-Z]{2})?$/;
return languageCodePattern.test(languageCode);
}
/**
* Get supported language codes
*/
function getSupportedLanguages() {
return [
'en-US', 'en-GB', 'en-AU', 'en-CA', 'en-IN', 'en-IE', 'en-NZ', 'en-ZA',
'es-ES', 'es-MX', 'es-AR', 'es-CL', 'es-CO', 'es-PE', 'es-VE', 'es-EC',
'fr-FR', 'fr-CA', 'fr-BE', 'fr-CH', 'fr-LU', 'fr-MC',
'de-DE', 'de-AT', 'de-CH', 'de-LU', 'de-LI',
'it-IT', 'it-CH',
'pt-BR', 'pt-PT',
'ru-RU', 'ru-UA', 'ru-KZ',
'ja-JP',
'ko-KR',
'zh-CN', 'zh-TW', 'zh-HK',
'ar-SA', 'ar-EG', 'ar-IL', 'ar-JO', 'ar-LB', 'ar-MA', 'ar-PS', 'ar-SY',
'hi-IN',
'th-TH',
'tr-TR',
'pl-PL',
'nl-NL', 'nl-BE',
'sv-SE',
'da-DK',
'no-NO',
'fi-FI',
'cs-CZ',
'hu-HU',
'ro-RO',
'bg-BG',
'hr-HR',
'sk-SK',
'sl-SI',
'et-EE',
'lv-LV',
'lt-LT',
'mt-MT',
'el-GR',
'he-IL',
'id-ID',
'ms-MY',
'vi-VN',
'uk-UA',
'ca-ES',
'eu-ES',
'gl-ES',
'cy-GB',
'ga-IE',
'is-IS',
'mk-MK',
'sq-AL',
'sr-RS',
'bs-BA',
'me-ME',
'mn-MN',
'ka-GE',
'hy-AM',
'az-AZ',
'uz-UZ',
'kk-KZ',
'ky-KG',
'tg-TJ',
'fa-IR',
'ur-PK',
'bn-BD',
'si-LK',
'my-MM',
'km-KH',
'lo-LA',
'ne-NP',
'gu-IN',
'pa-IN',
'te-IN',
'kn-IN',
'ml-IN',
'ta-IN',
'or-IN',
'as-IN',
'mr-IN',
'sa-IN',
'bo-CN',
'dz-BT',
'ti-ER',
'so-SO',
'sw-KE',
'rw-RW',
'lg-UG',
'am-ET',
'ha-NG',
'yo-NG',
'ig-NG',
'zu-ZA',
'af-ZA',
'xh-ZA',
'st-ZA',
'tn-ZA',
'ts-ZA',
've-ZA',
'nr-ZA',
'ss-ZA',
'sn-ZW',
'ny-MW',
'mg-MG',
'co-FR',
'br-FR',
'oc-FR',
'gv-GB',
'kw-GB',
'fo-FO',
'sm-WS',
'to-TO',
'fj-FJ',
'haw-US',
'mi-NZ',
'qu-PE',
'qu-EC',
'qu-BO',
'ay-BO',
'gn-PY',
'gn-AR',
'gn-BO',
'gn-PE',
'gn-EC',
'gn-CO',
'gn-VE',
'gn-GY',
'gn-SR',
'gn-FR',
'gn-BR',
'gn-UY',
'gn-AR',
'gn-PY',
'gn-BO',
'gn-PE',
'gn-EC',
'gn-CO',
'gn-VE',
'gn-GY',
'gn-SR',
'gn-FR',
'gn-BR',
'gn-UY'
];
}
/**
* Get language name from language code
*/
function getLanguageName(languageCode) {
const languageNames = {
'en-US': 'English (US)',
'en-GB': 'English (UK)',
'en-AU': 'English (Australia)',
'en-CA': 'English (Canada)',
'en-IN': 'English (India)',
'en-IE': 'English (Ireland)',
'en-NZ': 'English (New Zealand)',
'en-ZA': 'English (South Africa)',
'es-ES': 'Spanish (Spain)',
'es-MX': 'Spanish (Mexico)',
'es-AR': 'Spanish (Argentina)',
'es-CL': 'Spanish (Chile)',
'es-CO': 'Spanish (Colombia)',
'es-PE': 'Spanish (Peru)',
'es-VE': 'Spanish (Venezuela)',
'es-EC': 'Spanish (Ecuador)',
'fr-FR': 'French (France)',
'fr-CA': 'French (Canada)',
'fr-BE': 'French (Belgium)',
'fr-CH': 'French (Switzerland)',
'fr-LU': 'French (Luxembourg)',
'fr-MC': 'French (Monaco)',
'de-DE': 'German (Germany)',
'de-AT': 'German (Austria)',
'de-CH': 'German (Switzerland)',
'de-LU': 'German (Luxembourg)',
'de-LI': 'German (Liechtenstein)',
'it-IT': 'Italian (Italy)',
'it-CH': 'Italian (Switzerland)',
'pt-BR': 'Portuguese (Brazil)',
'pt-PT': 'Portuguese (Portugal)',
'ru-RU': 'Russian (Russia)',
'ru-UA': 'Russian (Ukraine)',
'ru-KZ': 'Russian (Kazakhstan)',
'ja-JP': 'Japanese (Japan)',
'ko-KR': 'Korean (South Korea)',
'zh-CN': 'Chinese (Simplified)',
'zh-TW': 'Chinese (Traditional)',
'zh-HK': 'Chinese (Hong Kong)',
'ar-SA': 'Arabic (Saudi Arabia)',
'ar-EG': 'Arabic (Egypt)',
'ar-IL': 'Arabic (Israel)',
'ar-JO': 'Arabic (Jordan)',
'ar-LB': 'Arabic (Lebanon)',
'ar-MA': 'Arabic (Morocco)',
'ar-PS': 'Arabic (Palestine)',
'ar-SY': 'Arabic (Syria)',
'hi-IN': 'Hindi (India)',
'th-TH': 'Thai (Thailand)',
'tr-TR': 'Turkish (Turkey)',
'pl-PL': 'Polish (Poland)',
'nl-NL': 'Dutch (Netherlands)',
'nl-BE': 'Dutch (Belgium)',
'sv-SE': 'Swedish (Sweden)',
'da-DK': 'Danish (Denmark)',
'no-NO': 'Norwegian (Norway)',
'fi-FI': 'Finnish (Finland)',
'cs-CZ': 'Czech (Czech Republic)',
'hu-HU': 'Hungarian (Hungary)',
'ro-RO': 'Romanian (Romania)',
'bg-BG': 'Bulgarian (Bulgaria)',
'hr-HR': 'Croatian (Croatia)',
'sk-SK': 'Slovak (Slovakia)',
'sl-SI': 'Slovenian (Slovenia)',
'et-EE': 'Estonian (Estonia)',
'lv-LV': 'Latvian (Latvia)',
'lt-LT': 'Lithuanian (Lithuania)',
'mt-MT': 'Maltese (Malta)',
'el-GR': 'Greek (Greece)',
'he-IL': 'Hebrew (Israel)',
'id-ID': 'Indonesian (Indonesia)',
'ms-MY': 'Malay (Malaysia)',
'vi-VN': 'Vietnamese (Vietnam)',
'uk-UA': 'Ukrainian (Ukraine)',
'ca-ES': 'Catalan (Spain)',
'eu-ES': 'Basque (Spain)',
'gl-ES': 'Galician (Spain)',
'cy-GB': 'Welsh (UK)',
'ga-IE': 'Irish (Ireland)',
'is-IS': 'Icelandic (Iceland)',
'mk-MK': 'Macedonian (North Macedonia)',
'sq-AL': 'Albanian (Albania)',
'sr-RS': 'Serbian (Serbia)',
'bs-BA': 'Bosnian (Bosnia and Herzegovina)',
'me-ME': 'Montenegrin (Montenegro)',
'mn-MN': 'Mongolian (Mongolia)',
'ka-GE': 'Georgian (Georgia)',
'hy-AM': 'Armenian (Armenia)',
'az-AZ': 'Azerbaijani (Azerbaijan)',
'uz-UZ': 'Uzbek (Uzbekistan)',
'kk-KZ': 'Kazakh (Kazakhstan)',
'ky-KG': 'Kyrgyz (Kyrgyzstan)',
'tg-TJ': 'Tajik (Tajikistan)',
'fa-IR': 'Persian (Iran)',
'ur-PK': 'Urdu (Pakistan)',
'bn-BD': 'Bengali (Bangladesh)',
'si-LK': 'Sinhala (Sri Lanka)',
'my-MM': 'Burmese (Myanmar)',
'km-KH': 'Khmer (Cambodia)',
'lo-LA': 'Lao (Laos)',
'ne-NP': 'Nepali (Nepal)',
'gu-IN': 'Gujarati (India)',
'pa-IN': 'Punjabi (India)',
'te-IN': 'Telugu (India)',
'kn-IN': 'Kannada (India)',
'ml-IN': 'Malayalam (India)',
'ta-IN': 'Tamil (India)',
'or-IN': 'Odia (India)',
'as-IN': 'Assamese (India)',
'mr-IN': 'Marathi (India)',
'sa-IN': 'Sanskrit (India)',
'bo-CN': 'Tibetan (China)',
'dz-BT': 'Dzongkha (Bhutan)',
'ti-ER': 'Tigrinya (Eritrea)',
'so-SO': 'Somali (Somalia)',
'sw-KE': 'Swahili (Kenya)',
'rw-RW': 'Kinyarwanda (Rwanda)',
'lg-UG': 'Ganda (Uganda)',
'am-ET': 'Amharic (Ethiopia)',
'ha-NG': 'Hausa (Nigeria)',
'yo-NG': 'Yoruba (Nigeria)',
'ig-NG': 'Igbo (Nigeria)',
'zu-ZA': 'Zulu (South Africa)',
'af-ZA': 'Afrikaans (South Africa)',
'xh-ZA': 'Xhosa (South Africa)',
'st-ZA': 'Southern Sotho (South Africa)',
'tn-ZA': 'Tswana (South Africa)',
'ts-ZA': 'Tsonga (South Africa)',
've-ZA': 'Venda (South Africa)',
'nr-ZA': 'Southern Ndebele (South Africa)',
'ss-ZA': 'Swati (South Africa)',
'sn-ZW': 'Shona (Zimbabwe)',
'ny-MW': 'Chichewa (Malawi)',
'mg-MG': 'Malagasy (Madagascar)',
'co-FR': 'Corsican (France)',
'br-FR': 'Breton (France)',
'oc-FR': 'Occitan (France)',
'gv-GB': 'Manx (UK)',
'kw-GB': 'Cornish (UK)',
'fo-FO': 'Faroese (Faroe Islands)',
'sm-WS': 'Samoan (Samoa)',
'to-TO': 'Tongan (Tonga)',
'fj-FJ': 'Fijian (Fiji)',
'haw-US': 'Hawaiian (US)',
'mi-NZ': 'Maori (New Zealand)',
'qu-PE': 'Quechua (Peru)',
'qu-EC': 'Quechua (Ecuador)',
'qu-BO': 'Quechua (Bolivia)',
'ay-BO': 'Aymara (Bolivia)',
'gn-PY': 'Guarani (Paraguay)',
'gn-AR': 'Guarani (Argentina)',
'gn-BO': 'Guarani (Bolivia)',
'gn-PE': 'Guarani (Peru)',
'gn-EC': 'Guarani (Ecuador)',
'gn-CO': 'Guarani (Colombia)',
'gn-VE': 'Guarani (Venezuela)',
'gn-GY': 'Guarani (Guyana)',
'gn-SR': 'Guarani (Suriname)',
'gn-FR': 'Guarani (French Guiana)',
'gn-BR': 'Guarani (Brazil)',
'gn-UY': 'Guarani (Uruguay)'
};
return languageNames[languageCode] || languageCode;
}
/**
* Format a SpeechRecognitionResult for display
*/
function formatRecognitionResult(result) {
const confidence = result.confidence ? ` (${(result.confidence * 100).toFixed(1)}%)` : '';
const status = result.isFinal ? 'Final' : 'Interim';
return `${result.transcript}${confidence} [${status}]`;
}
/**
* Merge multiple recognition results
*/
function mergeRecognitionResults(results) {
return results
.filter(result => result.isFinal)
.map(result => result.transcript)
.join(' ');
}
/**
* Get the best result from multiple alternatives
*/
function getBestResult(results) {
if (results.length === 0) {
return null;
}
// Return the result with the highest confidence
return results.reduce((best, current) => {
if (!best)
return current;
if (!current)
return best;
return (current.confidence || 0) > (best.confidence || 0) ? current : best;
});
}
export { createSpeechRecognition, formatRecognitionResult, getBestResult, getLanguageName, getSupportedLanguages, isSpeechRecognitionAvailable, isValidLanguageCode, mergeRecognitionResults, validateSpeechRecognitionConfig };
//# sourceMappingURL=recognition.esm.js.map