diff --git a/src/lib/components/chat/SettingsModal.svelte b/src/lib/components/chat/SettingsModal.svelte index 10363df2..e0404267 100644 --- a/src/lib/components/chat/SettingsModal.svelte +++ b/src/lib/components/chat/SettingsModal.svelte @@ -31,6 +31,7 @@ let pullProgress = null; // Addons + let speechAutoSend = false; let gravatarEmail = ''; let OPENAI_API_KEY = ''; @@ -89,7 +90,7 @@ document.documentElement.classList.add(theme); }; - const togglerequestFormat = async () => { + const toggleRequestFormat = async () => { if (requestFormat === '') { requestFormat = 'json'; } else { @@ -99,6 +100,11 @@ saveSettings({ requestFormat: requestFormat !== '' ? requestFormat : undefined }); }; + const toggleSpeechAutoSend = async () => { + speechAutoSend = !speechAutoSend; + saveSettings({ speechAutoSend: speechAutoSend }); + }; + const pullModelHandler = async () => { const res = await fetch(`${API_BASE_URL}/pull`, { method: 'POST', @@ -218,8 +224,9 @@ top_k = settings.top_k ?? 40; top_p = settings.top_p ?? 0.9; - OPENAI_API_KEY = settings.OPENAI_API_KEY ?? ''; + speechAutoSend = settings.speechAutoSend ?? false; gravatarEmail = settings.gravatarEmail ?? ''; + OPENAI_API_KEY = settings.OPENAI_API_KEY ?? ''; } @@ -501,7 +508,7 @@ + + + +
Gravatar Email (optional) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index bb35c41b..98362453 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -26,6 +26,12 @@ temperature: null }; + let fileUploadEnabled = false; + + let speechRecognition; + let speechRecognitionEnabled = true; + let speechRecognitionListening = false; + let models = []; let chats = []; @@ -186,6 +192,66 @@ } }; + const speechRecognitionHandler = () => { + // Check if SpeechRecognition is supported + + if (speechRecognitionListening) { + speechRecognition.stop(); + } else { + if ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window) { + // Create a SpeechRecognition object + speechRecognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)(); + + // Set continuous to true for continuous recognition + speechRecognition.continuous = true; + + // Set the timeout for turning off the recognition after inactivity (in milliseconds) + const inactivityTimeout = 3000; // 3 seconds + + let timeoutId; + // Start recognition + speechRecognition.start(); + speechRecognitionListening = true; + + // Event triggered when speech is recognized + speechRecognition.onresult = function (event) { + // Clear the inactivity timeout + clearTimeout(timeoutId); + + // Handle recognized speech + console.log(event); + const transcript = event.results[Object.keys(event.results).length - 1][0].transcript; + prompt = `${prompt}${transcript}`; + + // Restart the inactivity timeout + timeoutId = setTimeout(() => { + console.log('Speech recognition turned off due to inactivity.'); + speechRecognition.stop(); + }, inactivityTimeout); + }; + + // Event triggered when recognition is ended + speechRecognition.onend = function () { + // Restart recognition after it ends + console.log('recognition ended'); + speechRecognitionListening = false; + if (prompt !== '' && settings?.speechAutoSend === true) { + submitPrompt(prompt); + } + }; + + // Event triggered when an error occurs + speechRecognition.onerror = function (event) { + console.log(event); + toast.error(`Speech recognition error: ${event.error}`); + speechRecognitionListening = false; + }; + } else { + toast.error('SpeechRecognition API is not supported in this browser.'); + } + } + }; + ////////////////////////// // Web functions ////////////////////////// @@ -1199,8 +1265,9 @@ >