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 channelConfig = if (channels == 2) AudioFormat.CHANNEL_OUT_STEREO else AudioFormat.CHANNEL_OUT_MONO
|
||||||
val encoding = AudioFormat.ENCODING_PCM_16BIT
|
val encoding = AudioFormat.ENCODING_PCM_16BIT
|
||||||
val minBuf = AudioTrack.getMinBufferSize(sampleRate, channelConfig, encoding)
|
val minBuf = AudioTrack.getMinBufferSize(sampleRate, channelConfig, encoding)
|
||||||
// Etwas grosszuegiger Buffer: 8x MinSize (ca. 200-400ms bei 24kHz) — glatt auch bei kleinen Netzwerk-Aussetzern
|
// Grosszuegiger Buffer: 32x MinSize — tolerant gegen Netzwerk-Jitter und
|
||||||
val bufferSize = (minBuf * 8).coerceAtLeast(32 * 1024)
|
// 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()
|
val newTrack = AudioTrack.Builder()
|
||||||
.setAudioAttributes(
|
.setAudioAttributes(
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,20 @@ function connectRVS(forcePlain) {
|
||||||
|
|
||||||
// ── TTS Request Handler ─────────────────────────────
|
// ── 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;
|
const { text, voice, requestId, language, messageId } = payload;
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue