fix: Streaming TTS — Queue in XTTS-Bridge + groesserer Android-Buffer
1) Ueberlappende Streams Wenn zwei xtts_requests schnell hintereinander kamen, rannten sie parallel durch handleTTSRequest. Beide HTTP-Requests an XTTS liefen gleichzeitig, beide streamen PCM an App → Chunks aus BEIDEN Renders landeten interleaved in der AudioTrack-Queue → Chaos. Fix: ttsQueue als Promise-Chain — handleTTSRequest() haengt sich ans Ende der Kette an. Requests werden sequenziell abgearbeitet. 2) AudioTrack-Buffer zu klein fuer bursty Delivery XTTS /tts_to_audio/ ist NICHT echt streaming — der Server rendert intern den kompletten WAV und schickt ihn dann burst-weise. Der alte 8x-MinBuffer (ca 200-400ms) war zu klein um das abzufangen. Fix: Buffer auf 32x MinSize / mind. 128KB = ca. 2.7s bei 24kHz. Das toleriert typische XTTS-Render-Latenz. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
350069d371
commit
402bddc18a
|
|
@ -50,8 +50,10 @@ class PcmStreamPlayerModule(reactContext: ReactApplicationContext) : ReactContex
|
|||
val channelConfig = if (channels == 2) AudioFormat.CHANNEL_OUT_STEREO else AudioFormat.CHANNEL_OUT_MONO
|
||||
val encoding = AudioFormat.ENCODING_PCM_16BIT
|
||||
val minBuf = AudioTrack.getMinBufferSize(sampleRate, channelConfig, encoding)
|
||||
// Etwas grosszuegiger Buffer: 8x MinSize (ca. 200-400ms bei 24kHz) — glatt auch bei kleinen Netzwerk-Aussetzern
|
||||
val bufferSize = (minBuf * 8).coerceAtLeast(32 * 1024)
|
||||
// Grosszuegiger Buffer: 32x MinSize — tolerant gegen Netzwerk-Jitter und
|
||||
// bursty XTTS-Delivery (Render dauert 1-3s, dann kommen alle Samples
|
||||
// auf einmal). Bei 24kHz mono s16 entspricht 128KB ca. 2.7 Sekunden.
|
||||
val bufferSize = (minBuf * 32).coerceAtLeast(128 * 1024)
|
||||
|
||||
val newTrack = AudioTrack.Builder()
|
||||
.setAudioAttributes(
|
||||
|
|
|
|||
|
|
@ -95,7 +95,20 @@ function connectRVS(forcePlain) {
|
|||
|
||||
// ── TTS Request Handler ─────────────────────────────
|
||||
|
||||
async function handleTTSRequest(payload) {
|
||||
// ── TTS-Queue ──────────────────────────────────────
|
||||
// XTTS verarbeitet Requests sequenziell, damit Streams sich nicht ueberlappen.
|
||||
// Ohne Queue wuerden parallele Requests parallel streamen → App bekommt
|
||||
// interleaved PCM-Chunks aus zwei Rendern → klingt wie Chaos.
|
||||
let ttsQueue = Promise.resolve();
|
||||
|
||||
function handleTTSRequest(payload) {
|
||||
ttsQueue = ttsQueue.then(() => _runTTSRequest(payload)).catch(err => {
|
||||
log(`TTS-Queue Fehler: ${err.message}`);
|
||||
});
|
||||
return ttsQueue;
|
||||
}
|
||||
|
||||
async function _runTTSRequest(payload) {
|
||||
const { text, voice, requestId, language, messageId } = payload;
|
||||
if (!text) return;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue