Update version to 0.1.47 and improve TTS fallback handling and voice-mode responsiveness

This commit is contained in:
techartdev
2026-02-21 01:34:43 +02:00
parent f65c064569
commit 6bd3047c71
5 changed files with 60 additions and 17 deletions
+6
View File
@@ -2,6 +2,12 @@
All notable changes to the OpenClaw Home Assistant Integration will be documented in this file. All notable changes to the OpenClaw Home Assistant Integration will be documented in this file.
## [0.1.47] - 2026-02-21
### Fixed
- Improved continuous voice-mode responsiveness by finalizing recognition on speech end, reducing delay before sending spoken messages.
- Improved TTS fallback order: when no matching browser language voice is available, the card now tries Home Assistant TTS first before browser default-language fallback.
## [0.1.46] - 2026-02-21 ## [0.1.46] - 2026-02-21
### Fixed ### Fixed
+1 -1
View File
@@ -92,7 +92,7 @@ _CARD_PATH = Path(__file__).parent / "www" / _CARD_FILENAME
# URL at which the card JS is served (registered via register_static_path) # URL at which the card JS is served (registered via register_static_path)
_CARD_STATIC_URL = f"/openclaw/{_CARD_FILENAME}" _CARD_STATIC_URL = f"/openclaw/{_CARD_FILENAME}"
# Versioned URL used for Lovelace resource registration to avoid stale browser cache # Versioned URL used for Lovelace resource registration to avoid stale browser cache
_CARD_URL = f"{_CARD_STATIC_URL}?v=0.1.46" _CARD_URL = f"{_CARD_STATIC_URL}?v=0.1.47"
OpenClawConfigEntry = ConfigEntry OpenClawConfigEntry = ConfigEntry
+1 -1
View File
@@ -8,7 +8,7 @@
"iot_class": "local_polling", "iot_class": "local_polling",
"issue_tracker": "https://github.com/techartdev/OpenClawHomeAssistant/issues", "issue_tracker": "https://github.com/techartdev/OpenClawHomeAssistant/issues",
"requirements": [], "requirements": [],
"version": "0.1.46", "version": "0.1.47",
"dependencies": ["conversation"], "dependencies": ["conversation"],
"after_dependencies": ["hassio", "lovelace"] "after_dependencies": ["hassio", "lovelace"]
} }
@@ -1260,7 +1260,6 @@ class OpenClawChatCard extends HTMLElement {
const fallbackLanguage = this._normalizeSpeechLanguage( const fallbackLanguage = this._normalizeSpeechLanguage(
this._hass?.locale?.language || this._hass?.selectedLanguage || this._hass?.language || navigator.language || "en-US" this._hass?.locale?.language || this._hass?.selectedLanguage || this._hass?.language || navigator.language || "en-US"
); );
let attemptedFallback = false;
const pickVoice = (targetLanguage, voices) => { const pickVoice = (targetLanguage, voices) => {
const normalizedTarget = String(targetLanguage || "").toLowerCase(); const normalizedTarget = String(targetLanguage || "").toLowerCase();
@@ -1297,6 +1296,7 @@ class OpenClawChatCard extends HTMLElement {
const speakNow = (targetLanguage, allowFallback = true) => { const speakNow = (targetLanguage, allowFallback = true) => {
const utterance = new SpeechSynthesisUtterance(plain); const utterance = new SpeechSynthesisUtterance(plain);
utterance.lang = targetLanguage; utterance.lang = targetLanguage;
let preSpeakHaFallbackAttempted = false;
const voices = speechSynthesis.getVoices() || []; const voices = speechSynthesis.getVoices() || [];
if (voices.length) { if (voices.length) {
@@ -1307,26 +1307,63 @@ class OpenClawChatCard extends HTMLElement {
if (selection.lang) { if (selection.lang) {
utterance.lang = selection.lang; utterance.lang = selection.lang;
} }
if (!selection.matched && allowFallback) {
preSpeakHaFallbackAttempted = true;
this._voiceStatus = "No matching browser TTS voice, trying Home Assistant TTS…";
this._render();
this._speakViaHomeAssistantTts(plain, targetLanguage).then((ok) => {
if (ok) {
this._voiceStatus = "";
this._render();
return;
}
this._voiceStatus =
"Home Assistant TTS unavailable; using browser default voice as fallback.";
this._render();
try {
speechSynthesis.cancel();
} catch (e) {
// ignore
}
speechSynthesis.speak(utterance);
});
return;
}
} }
utterance.onerror = (event) => { utterance.onerror = (event) => {
if (allowFallback && !attemptedFallback && targetLanguage !== fallbackLanguage) { if (!preSpeakHaFallbackAttempted) {
attemptedFallback = true; this._voiceStatus = "Browser TTS failed, trying Home Assistant TTS…";
this._render();
this._speakViaHomeAssistantTts(plain, targetLanguage).then((ok) => {
if (ok) {
this._voiceStatus = "";
this._render();
return;
}
if (allowFallback && targetLanguage !== fallbackLanguage) {
speakNow(fallbackLanguage, false);
return;
}
const reason = event?.error ? ` (${event.error})` : "";
this._voiceStatus = `TTS error for language ${targetLanguage}${reason}`;
this._render();
});
return;
}
if (allowFallback && targetLanguage !== fallbackLanguage) {
speakNow(fallbackLanguage, false); speakNow(fallbackLanguage, false);
return; return;
} }
this._voiceStatus = "Browser TTS failed, trying Home Assistant TTS…";
const reason = event?.error ? ` (${event.error})` : "";
this._voiceStatus = `TTS error for language ${targetLanguage}${reason}`;
this._render(); this._render();
this._speakViaHomeAssistantTts(plain, targetLanguage).then((ok) => {
if (ok) {
this._voiceStatus = "";
this._render();
return;
}
const reason = event?.error ? ` (${event.error})` : "";
this._voiceStatus = `TTS error for language ${targetLanguage}${reason}`;
this._render();
});
}; };
try { try {
+1 -1
View File
@@ -1,7 +1,7 @@
(async () => { (async () => {
try { try {
if (!customElements.get("openclaw-chat-card")) { if (!customElements.get("openclaw-chat-card")) {
const src = "/openclaw/openclaw-chat-card.js?v=0.1.46"; const src = "/openclaw/openclaw-chat-card.js?v=0.1.47";
console.info("OpenClaw loader importing", src); console.info("OpenClaw loader importing", src);
await import(src); await import(src);
} }