updated voice, avatar and frontend to reflect changes
Some checks failed
Deploy FluentGerman.ai / deploy (push) Failing after 51s
Some checks failed
Deploy FluentGerman.ai / deploy (push) Failing after 51s
This commit is contained in:
@@ -81,6 +81,14 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
const voice = new VoiceManager();
|
||||
await voice.init();
|
||||
|
||||
// Disable mic button if no STT method is available
|
||||
if (voice.isDisabled) {
|
||||
voiceBtn.disabled = true;
|
||||
voiceBtn.title = 'Voice input requires Chrome or Edge (with HTTPS)';
|
||||
voiceBtn.style.opacity = '0.35';
|
||||
voiceBtn.style.cursor = 'not-allowed';
|
||||
}
|
||||
|
||||
voice.onResult = (text) => {
|
||||
inputEl.value = text;
|
||||
voice.lastInputWasVoice = true;
|
||||
|
||||
@@ -6,12 +6,14 @@ class VoiceManager {
|
||||
this.recognition = null;
|
||||
this.synthesis = window.speechSynthesis;
|
||||
this.isRecording = false;
|
||||
this.lastInputWasVoice = false; // tracks if last message was spoken
|
||||
this.isDisabled = false; // true when no STT method is available
|
||||
this.lastInputWasVoice = false;
|
||||
this.mediaRecorder = null;
|
||||
this.audioChunks = [];
|
||||
this.onResult = null;
|
||||
this.onStateChange = null;
|
||||
this.browserSTTSupported = false;
|
||||
this.apiAvailable = false;
|
||||
}
|
||||
|
||||
async init() {
|
||||
@@ -24,21 +26,37 @@ class VoiceManager {
|
||||
if (response?.ok) {
|
||||
const config = await response.json();
|
||||
this.mode = config.voice_mode;
|
||||
console.log('[Voice] Server mode:', this.mode);
|
||||
this.apiAvailable = config.voice_api_available || false;
|
||||
console.log('[Voice] Server mode:', this.mode, '| API available:', this.apiAvailable);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[Voice] Could not fetch config, using browser mode');
|
||||
this.mode = 'browser';
|
||||
}
|
||||
|
||||
// Auto-fallback: if server says "browser" but browser doesn't support STT, use API
|
||||
// Determine the best available mode
|
||||
if (this.mode === 'browser' && !this.browserSTTSupported) {
|
||||
console.warn('[Voice] Browser STT not supported, falling back to API mode');
|
||||
this.mode = 'api';
|
||||
showToast('Using cloud voice recognition — your browser doesn\'t support built-in speech recognition.', 'info');
|
||||
if (this.apiAvailable) {
|
||||
console.log('[Voice] Browser STT not supported, falling back to API mode');
|
||||
this.mode = 'api';
|
||||
showToast('Using cloud voice recognition — your browser doesn\'t support built-in speech recognition.', 'info');
|
||||
} else {
|
||||
// Neither method works
|
||||
console.warn('[Voice] No STT method available — disabling voice input');
|
||||
this.isDisabled = true;
|
||||
}
|
||||
} else if (this.mode === 'api' && !this.apiAvailable) {
|
||||
// Server says API but API isn't actually configured
|
||||
if (this.browserSTTSupported) {
|
||||
console.log('[Voice] API STT not configured, using browser STT');
|
||||
this.mode = 'browser';
|
||||
} else {
|
||||
console.warn('[Voice] No STT method available — disabling voice input');
|
||||
this.isDisabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[Voice] Active mode:', this.mode);
|
||||
console.log('[Voice] Final mode:', this.isDisabled ? 'DISABLED' : this.mode);
|
||||
}
|
||||
|
||||
_initBrowserSTT() {
|
||||
@@ -84,6 +102,11 @@ class VoiceManager {
|
||||
}
|
||||
|
||||
async startRecording() {
|
||||
if (this.isDisabled) {
|
||||
showToast('Voice input requires Chrome or Edge (with HTTPS). Firefox is not supported.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
this.isRecording = true;
|
||||
this.lastInputWasVoice = true;
|
||||
if (this.onStateChange) this.onStateChange(true);
|
||||
@@ -126,12 +149,10 @@ class VoiceManager {
|
||||
showToast('Voice recognition failed to start. Try again.', 'error');
|
||||
}
|
||||
} else {
|
||||
// Shouldn't happen after init() fallback, but safety net
|
||||
console.warn('[Voice] No speech recognition available, switching to API');
|
||||
this.mode = 'api';
|
||||
console.warn('[Voice] No speech recognition available');
|
||||
this.isRecording = false;
|
||||
if (this.onStateChange) this.onStateChange(false);
|
||||
showToast('Switched to cloud voice recognition. Please try again.', 'info');
|
||||
showToast('Voice input requires Chrome or Edge (with HTTPS).', 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,7 +208,7 @@ class VoiceManager {
|
||||
}
|
||||
|
||||
async speak(text) {
|
||||
if (this.mode === 'api') {
|
||||
if (this.mode === 'api' && this.apiAvailable) {
|
||||
return this._speakAPI(text);
|
||||
} else {
|
||||
return this._speakBrowser(text);
|
||||
@@ -233,6 +254,10 @@ class VoiceManager {
|
||||
}
|
||||
|
||||
toggleRecording() {
|
||||
if (this.isDisabled) {
|
||||
showToast('Voice input requires Chrome or Edge (with HTTPS). Firefox is not supported.', 'error');
|
||||
return;
|
||||
}
|
||||
if (this.isRecording) {
|
||||
this.stopRecording();
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user