UNPKG

@bitrix24/b24ui-nuxt

Version:

Bitrix24 UI-Kit for developing web applications REST API for NUXT & VUE

167 lines (166 loc) 4.36 kB
import { ref, computed, onMounted, onBeforeUnmount, readonly } from "vue"; export function useSpeechRecognition(options = {}, events = {}) { const { lang = "en-US", continuous = true, interimResults = true, maxAlternatives = 1 } = options; const { onStart, onEnd, onError, onResult } = events; const state = ref({ isAvailable: false, isListening: false, lastRecognizedText: "" }); let recognizer; const isAvailable = computed(() => state.value.isAvailable); const isListening = computed(() => state.value.isListening); const init = () => { if (typeof window === "undefined") { onError?.("Speech recognition is not available in this environment"); return false; } const SpeechRecognition = window && (window.SpeechRecognition || window.webkitSpeechRecognition); if (!SpeechRecognition) { state.value.isAvailable = false; onError?.("Speech recognition is not supported in this browser"); return false; } try { recognizer = new SpeechRecognition(); recognizer.lang = lang; recognizer.continuous = continuous; recognizer.interimResults = interimResults; recognizer.maxAlternatives = maxAlternatives; setupEventHandlers(); state.value.isAvailable = true; return true; } catch (error) { onError?.(error instanceof Error ? error.message : "Failed to initialize speech recognition"); state.value.isAvailable = false; return false; } }; const setupEventHandlers = () => { if (!recognizer) return; recognizer.onstart = () => { state.value.isListening = true; onStart?.(); }; recognizer.onerror = (event) => { state.value.isListening = false; onError?.(event.error); }; recognizer.onend = () => { state.value.isListening = false; onEnd?.(); }; recognizer.onresult = (event) => { const recognizedText = _getRecognizedText(event); const nextText = _getNewText(recognizedText); if (nextText !== "") { onResult?.({ text: nextText }); } state.value.lastRecognizedText = recognizedText; }; }; const _getRecognizedText = (event) => { let recognizedChunk = ""; Object.values(event.results).forEach((result) => { if (result.isFinal) { return; } const [alternative] = result; const { transcript } = alternative; recognizedChunk += transcript; }); return recognizedChunk; }; const _getNewText = (fullText) => { let additionalText = ""; const lastChunkLength = state.value.lastRecognizedText.length; if (fullText.length > lastChunkLength) { additionalText = fullText.slice(lastChunkLength); } return additionalText; }; const start = async () => { if (!state.value.isAvailable) { return false; } if (state.value.isListening) { return false; } if (!recognizer) { if (!init()) { return false; } } try { recognizer.start(); return true; } catch (error) { onError?.(error instanceof Error ? error.message : "Failed to start speech recognition"); return false; } }; const stop = async () => { if (!state.value.isListening || !recognizer) { return false; } try { recognizer.stop(); return true; } catch (error) { onError?.(error instanceof Error ? error.message : "Failed to stop speech recognition"); return false; } }; const toggle = async () => { if (state.value.isListening) { return stop(); } else { return start(); } }; const setLanguage = (lang2) => { if (!recognizer) { return false; } try { recognizer.lang = lang2; return true; } catch (error) { onError?.(error instanceof Error ? error.message : "Failed to set language"); return false; } }; onMounted(() => { init(); }); onBeforeUnmount(() => { if (state.value.isListening) { stop(); } recognizer = void 0; }); return { // State (readonly) state: readonly(state), // Computed properties isAvailable, isListening, // Controls start, stop, toggle, setLanguage, // Recognizer instance (for advanced usage) recognizer }; }