@@ -12296,12 +12296,31 @@ class FastSearchCard extends HTMLElement {
1229612296 }
1229712297 }
1229812298
12299- speakTTS(text, entityId) {
12299+ async speakTTS(text, entityId) {
1230012300 console.log(`🗣️ Speaking: "${text}" on ${entityId}`);
1230112301
12302+ // 🆕 NEU: Player Status vor TTS merken
12303+ const playerState = this._hass.states[entityId];
12304+ const wasPlaying = playerState?.state === 'playing';
12305+
12306+ console.log(`🎵 Player was playing before TTS: ${wasPlaying}`);
12307+
12308+ // 🆕 NEU: Musik pausieren falls sie läuft
12309+ if (wasPlaying) {
12310+ console.log(`⏸️ Pausing music for TTS...`);
12311+ await this.callMusicAssistantService('media_pause', entityId);
12312+
12313+ // Kurz warten bis Pause durch ist
12314+ await new Promise(resolve => setTimeout(resolve, 500));
12315+ }
12316+
12317+ // Speichere Status für später
12318+ this.ttsPlayerWasPlaying = wasPlaying;
12319+ this.ttsStartedAt = Date.now(); // Zeitstempel für TTS Start
12320+
1230212321 try {
1230312322 // Versuche zuerst Amazon Polly
12304- this._hass.callService('tts', 'amazon_polly_say', {
12323+ await this._hass.callService('tts', 'amazon_polly_say', {
1230512324 entity_id: entityId,
1230612325 message: text
1230712326 });
@@ -12312,8 +12331,8 @@ class FastSearchCard extends HTMLElement {
1231212331 } catch (error) {
1231312332 console.warn('⚠️ Amazon Polly failed, trying fallback TTS:', error);
1231412333
12315- // Fallback zu Standard TTS Services
12316- this.tryFallbackTTS(text, entityId);
12334+ // Fallback zu deinen anderen TTS Services
12335+ await this.tryFallbackTTS(text, entityId);
1231712336 }
1231812337 }
1231912338
@@ -12371,19 +12390,42 @@ class FastSearchCard extends HTMLElement {
1237112390 // Auto-Reset nach geschätzter Zeit (150 Wörter/min)
1237212391 const textarea = activeTTSContainer.querySelector('.tts-textarea');
1237312392 if (textarea) {
12374- const wordCount = textarea.value.trim().split(/\s+/).length;
12375- const estimatedDuration = Math.max(3000, (wordCount / 150) * 60 * 1000); // Min 3 Sekunden
12376-
12393+ // ✅ VERBESSERT: Intelligentere TTS Duration Schätzung
12394+ const text = textarea.value.trim();
12395+ const estimatedDuration = this.calculateTTSDuration(text);
12396+
1237712397 setTimeout(() => {
1237812398 this.updateTTSButtonState('ready');
1237912399
12380- // ✅ NEU: Auto-Resume nach TTS
12400+ // ✅ VERBESSERT: Smart Auto-Resume mit Status-Check
1238112401 const entityId = this.currentDetailItem?.id;
12382- if (entityId) {
12383- console.log('🎵 Auto-resuming music after TTS:', entityId);
12384- setTimeout(() => {
12385- this.callMusicAssistantService('media_play', entityId);
12386- }, 1000); // 1 Sekunde warten nach TTS Ende
12402+ if (entityId && this.ttsPlayerWasPlaying) {
12403+ // Double-check: Ist der Player immer noch im gleichen Zustand?
12404+ const currentState = this._hass.states[entityId];
12405+ const ttsAge = Date.now() - (this.ttsStartedAt || 0);
12406+
12407+ console.log(`🔍 TTS finished after ${Math.round(ttsAge/1000)}s, player state: ${currentState?.state}`);
12408+
12409+ // Nur fortsetzen wenn:
12410+ // 1. Player nicht manuell gestartet wurde während TTS
12411+ // 2. TTS nicht zu alt ist (max 60s)
12412+ if (currentState?.state !== 'playing' && ttsAge < 60000) {
12413+ console.log('🎵 Auto-resuming music after TTS (was playing before):', entityId);
12414+ setTimeout(() => {
12415+ this.callMusicAssistantService('media_play', entityId);
12416+ }, 1000);
12417+ } else {
12418+ console.log('⏭️ Skipping auto-resume (player manually controlled or TTS too old)');
12419+ }
12420+
12421+ // Status zurücksetzen
12422+ this.ttsPlayerWasPlaying = false;
12423+ this.ttsStartedAt = null;
12424+
12425+ } else if (entityId) {
12426+ console.log('⏭️ Player was not playing before TTS, no auto-resume');
12427+ this.ttsPlayerWasPlaying = false;
12428+ this.ttsStartedAt = null;
1238712429 }
1238812430 }, estimatedDuration);
1238912431 }
@@ -12411,6 +12453,35 @@ class FastSearchCard extends HTMLElement {
1241112453 }
1241212454 }
1241312455
12456+ // Helper: Calculate TTS duration based on text and service
12457+ calculateTTSDuration(text) {
12458+ if (!text) return 3000;
12459+
12460+ const charCount = text.length;
12461+ const wordCount = text.split(/\s+/).length;
12462+
12463+ // Verschiedene Faktoren berücksichtigen
12464+ let baseDuration;
12465+
12466+ if (charCount < 50) {
12467+ // Kurze Texte: 100ms pro Zeichen + 1s Buffer
12468+ baseDuration = (charCount * 100) + 1000;
12469+ } else {
12470+ // Längere Texte: Wort-basiert mit Punctuation
12471+ const punctuationCount = (text.match(/[.!?;,]/g) || []).length;
12472+
12473+ // Basis: 2.5 Wörter/Sekunde + Pause für Satzzeichen
12474+ baseDuration = (wordCount / 2.5 * 1000) + (punctuationCount * 300);
12475+ }
12476+
12477+ // Minimum 2 Sekunden, Maximum 30 Sekunden
12478+ const finalDuration = Math.max(2000, Math.min(baseDuration, 30000));
12479+
12480+ console.log(`⏱️ TTS Duration: ${Math.round(finalDuration/1000)}s for ${wordCount} words`);
12481+
12482+ return finalDuration;
12483+ }
12484+
1241412485 setupTTSEventListeners(item, container) {
1241512486 console.log('🔍 setupTTSEventListeners called for:', item.id);
1241612487 console.log('🔍 Container:', container);
0 commit comments