diff --git a/android/src/screens/ChatScreen.tsx b/android/src/screens/ChatScreen.tsx index 5ba3462..766154b 100644 --- a/android/src/screens/ChatScreen.tsx +++ b/android/src/screens/ChatScreen.tsx @@ -1679,7 +1679,11 @@ const ChatScreen: React.FC = () => { rememberMyRequest(audioRequestId); const wasInterrupted = interruptAriaIfBusy(); const location = await getCurrentLocation(); - const windowMs = await loadConvWindowMs(); + // EIN Wert regiert: die Stille-Toleranz. Sie gilt sowohl als Pause WÄHREND + // des Redens (endpointMs) ALS AUCH als "wenn du nicht anfängst zu reden, + // ist Schluss" (noSpeechTimeoutMs). Kein separates 30s-Konversationsfenster + // mehr — Stefans Modell: sagst du nichts, greift der Stille-Wert. + const sttEndpointMs = await loadSttEndpointMs(); const userMsg: ChatMessage = { id: nextId(), @@ -1697,8 +1701,8 @@ const ChatScreen: React.FC = () => { speed: ttsSpeedRef.current, interrupted: wasInterrupted, location: location || null, - noSpeechTimeoutMs: windowMs, - endpointMs: await loadSttEndpointMs(), + noSpeechTimeoutMs: sttEndpointMs, + endpointMs: sttEndpointMs, // Notbremse 5 min (nicht 1 min) — der Stille-Endpoint beendet normale // Turns eh sofort; der Cap darf lange Diktate nicht mitten drin kappen. hardCapMs: await loadMaxRecordingMs(), @@ -1756,12 +1760,12 @@ const ChatScreen: React.FC = () => { !(m.audioRequestId === ev.audioRequestId && m.text.includes('Spracheingabe wird verarbeitet')))); } - // Bei Passive-Listen + speaker_mismatch oder no-speech: erneut passiv - // lauschen (Timer im wakeword-service laeuft weiter, regelt das Ende). - // Sonst endConversation wie bisher. + // Kein Re-Arm mehr: nach ARIAs Antwort gab es EIN Stille-Fenster (= + // Stille-Toleranz). Kam nichts, ist Schluss → zurück aufs Wake-Word. + // Kein 30s-Nachlauschen. (speaker_mismatch/no-speech landen beide hier.) if (wakeWordService.getState() === 'listening') { - console.log('[Chat] Passive-Listen: leeres Endpoint — naechste passive Aufnahme'); - startPassiveStreamingRecording(); + console.log('[Chat] Passive-Listen: leeres Endpoint — Ende, zurueck aufs Wake-Word'); + wakeWordService.exitPassiveListening('timeout').catch(() => {}); } else { wakeWordService.endConversation(); if (!wakeWordService.isActive()) setWakeWordActive(false); @@ -1791,7 +1795,7 @@ const ChatScreen: React.FC = () => { const audioRequestId = `audio_${Date.now()}_${Math.floor(Math.random() * 100000)}`; rememberMyRequest(audioRequestId); const location = await getCurrentLocation(); - const windowMs = await loadConvWindowMs(); + const sttEndpointMs = await loadSttEndpointMs(); // ein Wert für Pause + No-Speech const userMsg: ChatMessage = { id: nextId(), @@ -1809,8 +1813,8 @@ const ChatScreen: React.FC = () => { speed: ttsSpeedRef.current, interrupted: true, // Barge-In → Brain weiss "User hat unterbrochen" location: location || null, - noSpeechTimeoutMs: windowMs, - endpointMs: await loadSttEndpointMs(), + noSpeechTimeoutMs: sttEndpointMs, + endpointMs: sttEndpointMs, // Notbremse 5 min (s.o.) — lange Diktate nicht bei 1 min abschneiden. hardCapMs: await loadMaxRecordingMs(), projectId: focusedProjectIdRef.current, @@ -1871,16 +1875,20 @@ const ChatScreen: React.FC = () => { const audioRequestId = `audio_passive_${Date.now()}_${Math.floor(Math.random() * 100000)}`; rememberMyRequest(audioRequestId); const location = await getCurrentLocation(); - const passiveMs = await loadPassiveListenMs(); + // Kein 30s-Passiv-Fenster mehr: nach ARIAs Antwort geht das Mikro auf, und + // fängst du nicht innerhalb der Stille-Toleranz an zu reden, ist Schluss → + // zurück aufs Wake-Word. Derselbe Wert wie die Pause-Toleranz beim Reden. + const sttEndpointMs = await loadSttEndpointMs(); const { ok } = await audioService.startStreamingRecording({ audioRequestId, voice: localXttsVoiceRef.current, speed: ttsSpeedRef.current, interrupted: false, location: location || null, - noSpeechTimeoutMs: Math.min(passiveMs, 30000), - endpointMs: await loadSttEndpointMs(), - hardCapMs: Math.max(passiveMs + 5000, 35000), + noSpeechTimeoutMs: sttEndpointMs, + endpointMs: sttEndpointMs, + // Lange Antworten nicht kappen (früher 35s → schnitt langes Reden ab). + hardCapMs: await loadMaxRecordingMs(), projectId: focusedProjectIdRef.current, }); if (!ok) {