From e4e0e793a834dc3e54214e05169f17cf82a298fc Mon Sep 17 00:00:00 2001 From: duffyduck Date: Fri, 10 Apr 2026 02:09:35 +0200 Subject: [PATCH] fix: Audio queue for sequential TTS playback (no overlap/skip) - Audio packets queued instead of stopping previous - _playNext() plays sequentially, each sentence after the previous - stopPlayback() clears queue - Fixes overlapping/skipping with XTTS sentence-by-sentence rendering Co-Authored-By: Claude Opus 4.6 (1M context) --- android/src/services/audio.ts | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/android/src/services/audio.ts b/android/src/services/audio.ts index d56fd43..6588c6c 100644 --- a/android/src/services/audio.ts +++ b/android/src/services/audio.ts @@ -55,6 +55,10 @@ class AudioService { private recorder: AudioRecorderPlayer; private recordingPath: string = ''; + // Audio-Queue fuer sequentielle TTS-Wiedergabe + private audioQueue: string[] = []; + private isPlaying: boolean = false; + // VAD State private vadEnabled: boolean = false; private lastSpeechTime: number = 0; @@ -198,15 +202,27 @@ class AudioService { // --- Wiedergabe --- - /** Base64-kodiertes Audio abspielen (z.B. TTS-Antwort von ARIA) */ + /** Base64-kodiertes Audio in die Queue stellen und abspielen */ async playAudio(base64Data: string): Promise { if (!base64Data) return; - // Laufende Wiedergabe stoppen - this.stopPlayback(); + this.audioQueue.push(base64Data); + if (!this.isPlaying) { + this._playNext(); + } + } + + /** Naechstes Audio aus der Queue abspielen */ + private async _playNext(): Promise { + if (this.audioQueue.length === 0) { + this.isPlaying = false; + return; + } + + this.isPlaying = true; + const base64Data = this.audioQueue.shift()!; try { - // Base64 -> temporaere WAV-Datei -> Sound abspielen const tmpPath = `${RNFS.CachesDirectoryPath}/aria_tts_${Date.now()}.wav`; await RNFS.writeFile(tmpPath, base64Data, 'base64'); @@ -214,6 +230,7 @@ class AudioService { if (error) { console.error('[Audio] Fehler beim Laden:', error); RNFS.unlink(tmpPath).catch(() => {}); + this._playNext(); return; } this.currentSound?.play((success) => { @@ -225,15 +242,20 @@ class AudioService { this.currentSound?.release(); this.currentSound = null; RNFS.unlink(tmpPath).catch(() => {}); + // Naechstes Audio abspielen + this._playNext(); }); }); } catch (err) { console.error('[Audio] Wiedergabefehler:', err); + this._playNext(); } } - /** Laufende Wiedergabe stoppen */ + /** Laufende Wiedergabe stoppen + Queue leeren */ stopPlayback(): void { + this.audioQueue = []; + this.isPlaying = false; if (this.currentSound) { this.currentSound.stop(); this.currentSound.release();