fix(voice): ARIA schliesst bei Steuerbefehl die Aufnahme selbst (stiller Stop)
Steuerbefehle laufen stumm (speak=false in Fast-Path/Local/Claude-Pfad) — ohne TTS feuert aber onPlaybackFinished nie, und daran hing bisher das Aufraeumen der Aufnahme. Folge: nach "spotify play" blieb das Mikro-/Konversations-Fenster offen (30s Leerlauf), obwohl der Befehl laengst ausgefuehrt war. Neu: ariaStopRecording() — das programmatische Gegenstueck zum Stop-Button. Nach einer stillen Antwort (speak=false) schliesst ARIA jede offene Aufnahme selbst und geht zurueck aufs Wake-Word, egal in welchem Zustand: passives Lauschen sauber beenden, offene Streaming-Aufnahme (aktiv/Barge) verwerfen, sonst endConversation. Vorher nur der conversing-Fall abgedeckt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1407,11 +1407,14 @@ const ChatScreen: React.FC = () => {
|
||||
// sofort (zurueck aufs Wake-Word), nur echte Gespraeche lauschen weiter.
|
||||
converseRef.current = (message.payload as any).converse === true;
|
||||
const _isSilent = (message.payload as any).speak === false;
|
||||
if (_isSilent && wakeWordService.isConversing()) {
|
||||
// Klarer Steuerbefehl (Liedersteuerung etc.) = KEINE Konversation →
|
||||
// STOP: direkt zurueck aufs Wake-Word. Kein Gong, keine Aufnahme,
|
||||
// kein 30s-Fenster (skipPassive=true).
|
||||
wakeWordService.endConversation(true).catch(() => {});
|
||||
if (_isSilent) {
|
||||
// Steuerbefehl (speak=false) ist ausgefuehrt und wird NICHT vorgelesen.
|
||||
// Ohne TTS feuert onPlaybackFinished nie — der Mikro-/Konversations-
|
||||
// Lifecycle haengt sonst (das Ohr bleibt grau, das Aufnahme-Fenster offen).
|
||||
// ARIA "drueckt hier selbst Stop": jede offene Aufnahme schliessen +
|
||||
// zurueck aufs Wake-Word, egal in welchem Zustand (conversing, passives
|
||||
// Lauschen ODER eine noch offene Streaming-Aufnahme).
|
||||
ariaStopRecording('silent-command').catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2298,6 +2301,36 @@ const ChatScreen: React.FC = () => {
|
||||
return true;
|
||||
}, [getCurrentLocation, interruptAriaIfBusy, scheduleStaleAudioCleanup]);
|
||||
|
||||
// ARIA schliesst die Aufnahme SELBST — das programmatische Gegenstueck zum
|
||||
// Stop-Button. Aufgerufen nach einem stillen Steuerbefehl (speak=false): der
|
||||
// Befehl ist ausgefuehrt, ARIA hat die Rueckinfo (Skill-Ergebnis) und antwortet
|
||||
// NICHT vorgelesen. Weil ohne TTS kein onPlaybackFinished kommt, muss der
|
||||
// Aufnahme-/Konversations-Zustand hier aktiv aufgeraeumt werden, sonst bleibt
|
||||
// das Ohr haengen bzw. das Aufnahme-Fenster laeuft leer weiter (Stefans
|
||||
// Reproduktion: "spotify play" und das Mikro wartet trotzdem 30s).
|
||||
// Unterschied zum manuellen Stop: der verwirft NICHT, sondern finalisiert die
|
||||
// Aufnahme (User will seinen Satz verarbeitet haben) — hier ist der Befehl
|
||||
// schon durch, ein evtl. offenes Folge-Fenster wird verworfen.
|
||||
const ariaStopRecording = useCallback(async (reason: string): Promise<void> => {
|
||||
converseRef.current = false;
|
||||
// 1) Passiv-Lauschen: sauber beenden (cancelt den Stream selbst, startet
|
||||
// KEINE neue passive Aufnahme).
|
||||
if (wakeWordService.getState() === 'listening') {
|
||||
await wakeWordService.exitPassiveListening('manual').catch(() => {});
|
||||
return;
|
||||
}
|
||||
// 2) Noch offene Streaming-Aufnahme (aktiv / Barge-In) verwerfen.
|
||||
if (audioService.isStreamingRecording()) {
|
||||
await audioService.cancelStreamingRecording(reason).catch(() => {});
|
||||
}
|
||||
// 3) Konversation beenden → zurueck aufs Wake-Word (skipPassive: kein 30s-Fenster).
|
||||
if (wakeWordService.isConversing()) {
|
||||
await wakeWordService.endConversation(true).catch(() => {});
|
||||
} else if (!wakeWordService.isActive()) {
|
||||
setWakeWordActive(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Manueller Aufnahme-Knopf — Stop. Sendet stt_stream_end an Whisper, die
|
||||
// dann ihrerseits den finalen Text als stt_endpoint emittiert. aria-bridge
|
||||
// forwarded direkt an Brain. Im wake-word-conversing-Fall zusaetzlich
|
||||
|
||||
Reference in New Issue
Block a user