fix: Chrome speechSynthesis paused-state bug + better TTS diagnostics
_speakBrowser: Chrome sets speechSynthesis.paused=true after tab is
backgrounded/minimized. Calling cancel() does NOT clear this state.
Adding resume() before speak() inside the setTimeout fixes silent
failure when user returns to the tab (e.g. switch app → back to browser).
testTTS: add diagnostic messages for:
- Android kiosk: check isTtsReady() and show actionable error if
the native TTS engine hasn't initialized yet
- Web browser: check getVoices().length before speaking; if empty,
show error asking user to install a voice pack in OS settings
(instead of always showing '✅ Riproduzione in corso' even when silent)
This commit is contained in:
+20
-2
@@ -14127,8 +14127,14 @@ function _speakBrowser(text) {
|
|||||||
utt.lang = _currentLang === 'de' ? 'de-DE' : _currentLang === 'en' ? 'en-US' : 'it-IT';
|
utt.lang = _currentLang === 'de' ? 'de-DE' : _currentLang === 'en' ? 'en-US' : 'it-IT';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Chrome quirk: cancel() + immediate speak() is silently dropped — 50 ms gap fixes it
|
// Chrome quirks:
|
||||||
setTimeout(() => window.speechSynthesis.speak(utt), 50);
|
// 1. cancel() + immediate speak() is silently dropped → 50 ms gap fixes it
|
||||||
|
// 2. speechSynthesis gets paused after tab backgrounding; cancel() does NOT
|
||||||
|
// clear the paused state — need an explicit resume() before speak()
|
||||||
|
setTimeout(() => {
|
||||||
|
if (window.speechSynthesis.paused) window.speechSynthesis.resume();
|
||||||
|
window.speechSynthesis.speak(utt);
|
||||||
|
}, 50);
|
||||||
};
|
};
|
||||||
|
|
||||||
// If voices haven't loaded yet (async in Chrome/Android), wait once then speak
|
// If voices haven't loaded yet (async in Chrome/Android), wait once then speak
|
||||||
@@ -14161,6 +14167,12 @@ async function testTTS() {
|
|||||||
if (engine === 'browser') {
|
if (engine === 'browser') {
|
||||||
// Kiosk native TTS bridge takes priority over Web Speech API
|
// Kiosk native TTS bridge takes priority over Web Speech API
|
||||||
if (typeof _kioskBridge !== 'undefined' && typeof _kioskBridge.speak === 'function') {
|
if (typeof _kioskBridge !== 'undefined' && typeof _kioskBridge.speak === 'function') {
|
||||||
|
// Diagnostic: check if Android TTS engine is ready
|
||||||
|
const ready = typeof _kioskBridge.isTtsReady === 'function' ? _kioskBridge.isTtsReady() : 'unknown';
|
||||||
|
if (ready === 'false') {
|
||||||
|
if (statusEl) { statusEl.style.display = 'block'; statusEl.className = 'settings-status error'; statusEl.textContent = '❌ Android TTS non inizializzato — riavvia l\'app kiosk o installa un motore TTS dal Play Store.'; }
|
||||||
|
return;
|
||||||
|
}
|
||||||
const s = getSettings();
|
const s = getSettings();
|
||||||
s.tts_rate = parseFloat(document.getElementById('setting-tts-rate')?.value) || 1;
|
s.tts_rate = parseFloat(document.getElementById('setting-tts-rate')?.value) || 1;
|
||||||
s.tts_pitch = parseFloat(document.getElementById('setting-tts-pitch')?.value) || 1;
|
s.tts_pitch = parseFloat(document.getElementById('setting-tts-pitch')?.value) || 1;
|
||||||
@@ -14180,6 +14192,12 @@ async function testTTS() {
|
|||||||
s.tts_rate = parseFloat(document.getElementById('setting-tts-rate')?.value) || 1;
|
s.tts_rate = parseFloat(document.getElementById('setting-tts-rate')?.value) || 1;
|
||||||
s.tts_pitch = parseFloat(document.getElementById('setting-tts-pitch')?.value) || 1;
|
s.tts_pitch = parseFloat(document.getElementById('setting-tts-pitch')?.value) || 1;
|
||||||
saveSettingsToStorage(s);
|
saveSettingsToStorage(s);
|
||||||
|
// Diagnostic: surface paused/no-voices state to user
|
||||||
|
const voices = window.speechSynthesis.getVoices();
|
||||||
|
if (!voices.length) {
|
||||||
|
if (statusEl) { statusEl.style.display = 'block'; statusEl.className = 'settings-status error'; statusEl.textContent = '❌ Nessuna voce disponibile nel browser. Installa un pacchetto vocale nelle impostazioni del sistema operativo.'; }
|
||||||
|
return;
|
||||||
|
}
|
||||||
_speakBrowser('Test vocale EverShelf. La sintesi vocale funziona correttamente.');
|
_speakBrowser('Test vocale EverShelf. La sintesi vocale funziona correttamente.');
|
||||||
if (statusEl) { statusEl.style.display = 'block'; statusEl.className = 'settings-status success'; statusEl.textContent = '✅ Riproduzione in corso — controlla l\'audio del dispositivo.'; }
|
if (statusEl) { statusEl.style.display = 'block'; statusEl.className = 'settings-status success'; statusEl.textContent = '✅ Riproduzione in corso — controlla l\'audio del dispositivo.'; }
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user