From 6a94b574f29ad4fc6683e40f31ace48f4efe47c5 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sat, 11 Jul 2026 21:07:41 +0200 Subject: [PATCH] fix(app): Mund-Button stoppt laufendes Vorlesen wirklich (Cache bleibt) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zwei Fehler: (1) War der PCM-Stream schon komplett empfangen (isFinal durch), sind pcmStreamActive+isPlaying false — der AudioTrack spielt aber seinen Buffer noch sekundenlang aus. stopPlayback() returnte dann früh ("nichts aktiv") und rief PcmStreamPlayer.stop() NIE → Mund-Button wirkungslos. (2) stopPlayback() wirft pcmBuffer weg → die Cache-WAV waere unvollstaendig, Nachhoeren via Lautsprecher-Symbol kaputt. Neue _silenceAudibleOutput(): stoppt den AudioTrack IMMER (auch im Drain-Fall), laesst aber pcmBuffer/pcmMessageId/pcmStreamActive stehen — restliche Chunks cachen stumm weiter, isFinal schreibt die vollstaendige WAV. setMuted(true) nutzt das statt stopPlayback(). stopPlayback bleibt fuer Barge-In/Cancel. Co-Authored-By: Claude Opus 4.8 --- android/src/services/audio.ts | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/android/src/services/audio.ts b/android/src/services/audio.ts index 6a84bde..e7b72f4 100644 --- a/android/src/services/audio.ts +++ b/android/src/services/audio.ts @@ -1731,11 +1731,39 @@ class AudioService { this._stoppedMessageId = activeMsgId; console.log('[Audio] Antwort %s als gestoppt markiert', activeMsgId); } - this.stopPlayback(); + // NUR die hoerbare Wiedergabe stoppen — Cache-Buffer behalten, damit die + // Nachricht spaeter ueber das Lautsprecher-Symbol nachgehoert werden kann. + this._silenceAudibleOutput(); } } isMuted(): boolean { return this._muted; } + /** Mund-Button: laufendes Vorlesen SOFORT verstummen lassen, aber den + * PCM-Cache NICHT verwerfen (der Stream cached zu Ende → Nachhoeren via + * Lautsprecher-Symbol bleibt moeglich). Unterschied zu stopPlayback(): + * - stopt den AudioTrack IMMER (auch wenn pcmStreamActive schon false ist, + * weil der Stream fertig empfangen wurde aber der AudioTrack seinen Buffer + * noch sekundenlang ausspielt — genau da war der Mund-Button wirkungslos), + * - laesst pcmBuffer/pcmMessageId/pcmStreamActive stehen (Cache laeuft weiter). */ + private _silenceAudibleOutput(): void { + console.log('[Audio] _silenceAudibleOutput: AudioTrack+WAV stoppen, Cache behalten'); + this.audioQueue = []; + this.isPlaying = false; + if (this.currentSound) { + try { this.currentSound.stop(); this.currentSound.release(); } catch {} + this.currentSound = null; + } + if (this.resumeSound) { + try { this.resumeSound.stop(); this.resumeSound.release(); } catch {} + this.resumeSound = null; + } + // AudioTrack IMMER hart stoppen (idempotent) — auch im Drain-Fall. + PcmStreamPlayer?.stop().catch(() => {}); + stopBackgroundAudio().catch(() => {}); + this._cancelDeferredFocusRelease(); + AudioFocus?.release().catch(() => {}); + } + /** Laufende Wiedergabe stoppen + Queue leeren */ stopPlayback(): void { // Idempotent: wenn nichts mehr aktiv ist, NICHT noch einen Focus-Release/