From db0e56b26c3803c192e601dbf2b2086aec2c3324 Mon Sep 17 00:00:00 2001 From: Kazeia Team Date: Mon, 15 Jun 2026 12:29:25 +0200 Subject: [PATCH] =?UTF-8?q?perf(tts):=20NE=20PAS=20streamer=20LLM=E2=86=92?= =?UTF-8?q?CosyVoice=20(contention=20CPU)=20=E2=80=94=20document=C3=A9=20?= =?UTF-8?q?=E2=80=94=20v0.1.9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit « Reste optionnel » : tenté le streaming LLM→TTS pour CosyVoice (synthèse de la 1ʳᵉ phrase pendant que le LLM décode, comme le chemin Qwen TTS-B). Mesuré device : CONTRE-PRODUCTIF. LLM decode (6 threads CPU) et synthèse CosyVoice (8 threads CPU) saturent tous les cœurs ; les chevaucher écroule le LLM (17 → 0,55 tok/s, tour 1,1s → 41s, 1er son à 43s). Reverté. Le streaming LLM→TTS n'a de sens que si les 2 étages utilisent des compute distincts (Qwen3 NPU + TTS CPU). Pour CosyVoice (tout CPU) : laisser le LLM finir vite PUIS synthesizeAndPlay, qui streame déjà phrase-par-phrase EN INTERNE (synthèse N+1 pendant lecture N, sans contention). Net diff = un commentaire garde-fou dans KazeiaService pour ne pas re-tenter ; code de streaming retiré. Re-validé batch : LLM 17,1 tok/s (1,9s), TTS 1er son ~8s (RTF CosyVoice inhérent). Co-Authored-By: Claude Opus 4.8 (1M context) --- kazeia-android/app/build.gradle.kts | 4 ++-- .../app/src/main/java/com/kazeia/service/KazeiaService.kt | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/kazeia-android/app/build.gradle.kts b/kazeia-android/app/build.gradle.kts index 0a3ecc6..b7791e6 100644 --- a/kazeia-android/app/build.gradle.kts +++ b/kazeia-android/app/build.gradle.kts @@ -44,8 +44,8 @@ android { applicationId = "com.kazeia" minSdk = 28 targetSdk = 36 - versionCode = 9 - versionName = "0.1.8" + versionCode = 10 + versionName = "0.1.9" // WebDAV de distribution — injecté depuis local.properties. buildConfigField("String", "WEBDAV_BASE", "\"${localProp("webdav.base")}\"") diff --git a/kazeia-android/app/src/main/java/com/kazeia/service/KazeiaService.kt b/kazeia-android/app/src/main/java/com/kazeia/service/KazeiaService.kt index b0597b9..ca87a6a 100644 --- a/kazeia-android/app/src/main/java/com/kazeia/service/KazeiaService.kt +++ b/kazeia-android/app/src/main/java/com/kazeia/service/KazeiaService.kt @@ -1837,6 +1837,11 @@ Pas d'introduction, pas d'explication. Juste les 4 lignes en francais. /no_think // the enqueueSentence plumbing fall through to the legacy post-LLM // pipeline.speakText batch call. val qwen = tts as? com.kazeia.tts.Qwen3TtsEngine + // NB CosyVoice : PAS de streaming LLM→TTS. LLM decode et synthèse CosyVoice + // sont tous deux CPU-bound (saturent les cœurs) ; les chevaucher étrangle le + // LLM (mesuré : 17→0,55 tok/s, tour 1,1s→41s). On laisse le LLM finir vite + // (session ~1,1s) PUIS synthesizeAndPlay (chemin legacy) qui streame déjà + // phrase-par-phrase EN INTERNE (synthèse N+1 pendant lecture N, sans contention). // Bulle vide + signal Thinking sur le visualizer : la couleur de l'orbe // pulse pendant que le LLM réfléchit, plus de "..." textuels parasites. // L'écran reveal mot-par-mot s'enchaîne quand le premier audio joue. @@ -1899,6 +1904,8 @@ Pas d'introduction, pas d'explication. Juste les 4 lignes en francais. /no_think val sentenceCounter = java.util.concurrent.atomic.AtomicInteger(0) // TTS coupé (llmOnly) → pas de session de synthèse ouverte ; la bulle // se remplit token par token dans onToken (voir plus bas). + // Streaming LLM→TTS réservé à Qwen3 (NPU/Hexagon : pas de contention CPU avec + // le LLM). CosyVoice (CPU) passe par le chemin batch (voir note plus haut). val ttsStreamer: com.kazeia.tts.SentenceStreamer? = if (qwen != null && !llmOnly) { qwen.onSegmentPlaying = onSegPlay