Skip to content

[EPIC] GenAI Audiobook Agentique — Pipeline 5-pass avec voice cloning + tags expressifs #1028

Description

@jsboige

État au 2026-09-01 — 56 PRs mergées, huit cases vides, et une architecture qui n'est plus celle du body

Cet EPIC a 56 PRs mergées et zéro PR ouverte. Ses huit cases P0-P7 étaient toutes vides. C'est le défaut décrit en #13906 : le body est resté figé au 2026-05-13, si bien qu'une lane qui le tire y lit un chantier qui n'a pas commencé, alors que la chaîne tourne live sur le livre entier depuis le 2026-09-01 (#14059).

Deux choses sont réécrites ci-dessous : les cases, contre preuve sur disque ; et l'architecture, refondue en cours de route sans que le tableau du body suive.

L'architecture réelle est une v4 à huit passes, pas les cinq du tableau d'origine

Le tableau « Architecture 5 passes » décrivait P1 lecture → P2 casting → P3 prosodie → P4 TTS → P5 compilation. Ce qui vit sur main (MyIA.AI.Notebooks/GenAI/Audio/04-Applications/v4/, orchestré par scripts/audiobook_pipeline.py) est une chaîne à huit passes dont plusieurs n'existaient pas dans le plan :

Passe v4 Module Ce que le plan d'origine n'avait pas
p0 p0_narrative_research.py recherche narrative sur sources secondaires, en amont de la lecture
p1_5 p1_5_speaker_catalog.py catalogue des locuteurs, séparé de la segmentation
p2 p2_segmentation.py segmentation dialogue/narration
p3 p3_dramatic_context.py contexte dramatique par scène — la passe qui porte l'expressivité
p4 p4_annotation.py annotation prosodique
p5 p5_tts.py génération TTS (FishAudio S2-Pro)
p6c p6_compile.py compilation ffmpeg
p7 p7_verify.py WER + diarisation des locuteurs par transcription Whisper — un contrôle de fidélité absent du plan

La p7 est la différence la plus importante : le plan d'origine s'arrêtait au fichier produit, sans jamais vérifier que l'audio dit le texte, ni que chaque voix reste la sienne. Le rétro-contrôle par transcription et diarisation est une capacité gagnée en route, pas une case du plan.

Cases P0-P7 — vérifiées contre le disque

Attention à une collision de numérotation : les tâches P0-P7 de cet EPIC (setup, lecture, casting, prosodie, TTS, compilation, script, dataset) ne sont pas les passes p0-p7 de la v4 ci-dessus. La tâche P7 est le dataset ; la passe p7 est la vérification. Deux séries, deux sens.

La monotonie se mesure en notes — acquis à ne pas perdre

L'axe qui a coûté le plus de cycles n'est dans aucune case : un extrait TTS peut être plat sans que rien dans la chaîne ne le signale. L'instrument vit dans v4/prosody_lab/ (measure_melody.py, syllable_pitch.py, partition.py, prosody_metrics.py) et mesure la mélodie en notes, pas en amplitude d'enveloppe — un span large peut parfaitement couvrir un DRONE. Deux correctifs ont fermé les échappatoires : le détecteur ne certifie plus les extraits qu'il n'a pas mesurés (#11652), et il nomme l'axe non mesuré au lieu de rendre « rien trouvé » (#11665).

Conséquence opératoire : ne jamais resservir un extrait audio sans l'avoir repassé par l'instrument. Un extrait non mesuré se déclare non mesuré.

Incident d'exploitation à connaître avant toute chaîne longue

tts-fishaudio-idle-monitor arrête tts-fishaudio après 1200 s d'inactivité. Sur le livre complet, les phases LLM amont (p3 + p4) durent environ 36 minutes sans aucun appel TTS : le monitor tue donc le service pendant la chaîne, et p5 arrive sur un port refusé — 385 échecs sur 385 au premier run de #14059. Le mini-livre ne le déclenchait pas (phases LLM sous 20 min).

Le monitor est une économie GPU légitime, pas un bug. Toute chaîne longue LLM → TTS doit le suspendre (docker stop tts-fishaudio-idle-monitor) et le redémarrer après. #14059 demandait explicitement que ce soit consigné ici ; ce paragraphe honore cette demande.

Ce qui reste

  1. Chapitrage et conteneur .m4b (P5) — le seul livrable nommé dans les tâches qui n'existe pas sur main.
  2. Suspension automatique du monitor d'idle pendant une fenêtre de chaîne, plutôt qu'un geste manuel à ne pas oublier.

Le reste du plan est livré. Un contributeur qui reprend cet EPIC part de la v4 à huit passes, pas du tableau à cinq.


Contexte

Pipeline agentique de transformation livre texte → livre audio multi-voix expressif, motivé par un besoin association d'accès à la lecture (livres audio pour publics empêchés).

Approche : passes agentiques distinctes, état partagé entre passes, modèles SOTA voice cloning + TTS expressif.

Architecture d'origine (2026-05) — conservée pour l'historique, remplacée par la v4 ci-dessus

Passe Input Agent / Modèle Output
P1 — Lecture analytique Livre brut (.txt/.epub/.pdf) Agent-Framework / SK + plugin chunk-reader + plugin state-update characters.json (perso + traits) + utterances.json (prises de parole index avec speaker tag)
P2 — Voice casting characters.json Voice cloning : fishaudio/s2-pro, nellaw/xtts-french-voice-cloning-optimized, Qwen-Omni prompt acoustique voices/<char_id>.wav samples 5-15s
P3 — Annotation prosodique Livre + utterances.json Agent prosodie + tags s2-pro (joie, colère, chuchotement, etc.) book.ssml.md markdown enrichi tags
P4 — Génération TTS book.ssml.md + voices/ s2-pro principal, XTTS-v2 fallback chunks/chunk_NNNN.wav
P5 — Compilation audio chunks/ ffmpeg + crossfade + mastering (existant Audio series) output/audiobook.mp3 ou .m4b chapitré

Modèles candidats (P0 benchmark, 2026-05)

  • TTS principal : fishaudio/s2-pro — tags expressifs natifs, multilangue, support clone in-context. Retenu et déployé (v4/fishaudio_client.py, service tts-fishaudio).
  • Voice cloning français : nellaw/xtts-french-voice-cloning-optimized — jamais benchmarké (voir clarifications).
  • Voice cloning alternative : Shriramnag/Shiv-AI-Voice-Cloning — jamais benchmarké (voir clarifications).
  • Voix synthétique from prompt acoustique : Qwen-Omni audio — non déployé : le seul service Qwen audio sur po-2023 est qwen-asr-api = Qwen3-ASR-1.7B, transcription/STT, pas de génération.
  • Mastering / séparation : Demucs + Kokoro (déjà en prod po-2023).

Réutilisation existante

  • MyIA.AI.Notebooks/GenAI/Audio/01-Foundation/ — ffmpeg pipeline, Whisper STT (inverse mapping)
  • MyIA.AI.Notebooks/GenAI/Audio/02-Advanced/02-2-XTTS-Voice-Cloning.ipynb
  • MyIA.AI.Notebooks/GenAI/Audio/02-Advanced/02-8-Expressive-TTS.ipynb
  • MyIA.AI.Notebooks/GenAI/Audio/03-Orchestration/03-2-Audio-Pipeline-Orchestration.ipynb
  • MyIA.AI.Notebooks/GenAI/Audio/04-Applications/04-1-Educational-Audio-Content.ipynb
  • MyIA.AI.Notebooks/GenAI/Texte/ — agents lecture livre, chunking, function calling, RAG
  • Services GenAI po-2023 : Whisper-Large-v3-Turbo, Kokoro-TTS, MusicGen, Demucs

Éthique

  • Voix 100 % synthétiques pour démo (pas de clone humain réel)
  • Si extension future à voix humaine : consentement explicite + accord écrit
  • Texte source : libre de droits uniquement (Maupassant, Hugo, Verne, etc.)

Cas d'usage

  • Association accès à la lecture (livres audio pour publics empêchés)
  • Apprentissage langues (TTS multilangue avec tags)
  • Pédagogie scolaire (textes classiques annotés)

cc @jsboige

Clarifications vérifiées (2026-08-30 — tri ROO-1, réfutations Vibe)

  • Qwen-Omni audio n'est PAS déployé po-2023 (git grep -i "qwen omni|qwen_omni|qwen2.5-omni" = 0 hit). Le service Qwen audio existant est docker-configurations/services/qwen-asr-api/ = Qwen/Qwen3-ASR-1.7B (docker-compose.yml) — transcription STT, l'inverse de la génération from prompt acoustique. La question « déjà déployé po-2023 ? » est résolue : non.
  • nellaw/xtts-french-voice-cloning-optimized et Shriramnag/Shiv-AI-Voice-Cloning : 0 occurrence dans le dépôt (git grep vide). Ce sont des candidats externes à benchmarker (greenfield) — aucun scaffolding existant. L'existant XTTS = le notebook MyIA.AI.Notebooks/GenAI/Audio/02-Advanced/02-2-XTTS-Voice-Cloning.ipynb (présent, vérifié) et le service Docker tts-fishaudio pour s2-pro.
  • Précision adjacente (audit 2.5, PARTIEL) : « Demucs + Kokoro déjà en prod po-2023 » — les deux services existent (demucs-api, tts-api) mais Kokoro est un TTS, pas un outil de mastering.

Activity

  1. jsboige commented on May 13, 2026

    @jsboige
    OwnerAuthor

    Update — Fish-Speech reuse confirmé

    User a souligné : https://github.com/fishaudio/fish-speech (repo officiel fish-speech / fish-audio-sdk).

    Bonne nouvelle : on a déjà un notebook qui couvre Fish S2 Pro :

    📓 MyIA.AI.Notebooks/GenAI/Audio/02-Advanced/02-8-Expressive-TTS.ipynb

    Couvre :

    • fish_speech + fish-audio-sdk install (local GPU 14+ GB OU cloud API)
    • Chargement fishaudio/s2-pro local + fallback cloud
    • TTSInference invocation
    • Tests de tags expressifs

    → Phase P0 (benchmark voice cloning) peut directement partir de ce notebook comme base, plutôt que repartir from scratch.

    Conséquence pour le pipeline 5-pass

    Passe Statut réutilisation
    P0 — Benchmark voice cloning 70-80% réutilisable depuis 02-8-Expressive-TTS.ipynb
    P2 — Voice casting Extension du même notebook (multi-perso au lieu d'1 voix)
    P3 — Annotation prosodique Tags s2-pro déjà documentés dans 02-8
    P4 — Génération TTS TTSInference cell-by-cell déjà fonctionnel

    Action

    Lors du dispatch Phase P0 (post-EPITA/ESGF), partir explicitement de 02-8-Expressive-TTS.ipynb et l'enrichir vers MyIA.AI.Notebooks/GenAI/Audio/04-Applications/ (nouveau notebook 04-6-Audiobook-Pipeline.ipynb ou similaire).

    Repo fish-speech à monitorer pour :

    • Mises à jour modèle (S2 Pro → S3 ? S2 Max ?)
    • Évolution API tags expressifs
    • Performance benchmarks officiels

    cc @jsboige

  2. jsboige commented on May 15, 2026

    @jsboige
    OwnerAuthor

    [DIRECTIVE po-2023 — auto-pickup spec GenAI] Audiobook P1 Phase 1

    po-2023 = host GenAI services (Whisper STT, Qwen Image, Lumina, Kokoro TTS, MusicGen). Logique : Phase 1 du pipeline 5-pass = analyse texte → characters.json + utterances.json via SK + plugin chunk-reader.

    Scope Phase 1

    1. Repo design dans MyIA.AI.Notebooks/GenAI/Audiobook/ (créer le dossier si absent).
    2. Audiobook-1-Analyse.ipynb (.NET Interactive) :
      • Chargement livre .txt (Le Petit Prince — pédagogique, domaine public, court ~22kB)
      • Plugin SK chunk-reader (chunks de 2-4 chapitres)
      • Agent SK avec instructions : extraire personnages (nom, traits, tonalité) → characters.json
      • Agent SK : extraire utterances ({speaker, text, mood, scene_context}) → utterances.json
    3. Outputs persistés en JSON sous MyIA.AI.Notebooks/GenAI/Audiobook/output/
    4. Cellule de validation : assert utterances cover 100% du texte (pas de skip).

    Acceptance criteria

    • PR : feat(genai): audiobook Phase 1 — analyse + characters/utterances JSON
    • Notebook avec execution_count != null partout (règle H.1)
    • 0 cellule en erreur (règle C.1 — pas de raise NotImplementedError)
    • Body PR : extrait JSON characters (top 5 perso) + utterances (5 premières) + count total
    • Outputs commités (règle C.2)

    Anti-patterns

    • DO NOT démarrer la Passe 2 (voice cloning) avant validation Passe 1
    • DO NOT générer audio dans Phase 1 (text-only output)
    • DO NOT toucher au texte source (uniquement parsing)

    Phase suivante (Phase 2) attendra que ai-01 valide la sortie JSON et qu'on choisisse le modèle voice cloning (XTTS-v2 / OpenVoice / F5-TTS). Cf #1028 P2.

  3. jsboige commented on May 18, 2026

    @jsboige
    OwnerAuthor

    Epic CLOSED 100% — 8/8 PRs livrees (P0/P1/P2/P3/P4/P5 + READMEs + post-mortem). Pipeline complet en C66-C72.

    Livraisons :

    Doc post-mortem : docs/epic-1028-audiobook-postmortem.md (5-pass pipeline architecture + 8 lessons learned + 7 v2 improvement proposals).

    Bravo po-2023 pour l'execution de bout en bout sur le pipeline GenAI Audio complet.

  4. added a commit that references this issue on May 18, 2026
  5. 49 remaining items

  6. added a commit that references this issue on Sep 1, 2026
  7. jsboige commented on Sep 3, 2026

    @jsboige
    OwnerAuthor

    Confrontation sur les résidus de l'EPIC (grain MED/genai, lane myia-po-2023:CoursIA) :

    1. Résidu m4b — livré par fix(audiobook,#14188): p6_compile produit un .m4b avec chapitrage FFmpeg via FFMETADATA #14224 (84994c9, p6_compile produit un .m4b). OK.
    2. Résidu monitor-suspension — livré par PR fix(audiobook,#1028): suspension auto du monitor d'idle pendant une chaine LLM->TTS #14415 : run_pipeline suspend automatiquement tts-fishaudio-idle-monitor le temps de la fenêtre LLM→TTS (le défaut des 385/385 échecs du run feat(genai,#1028): P6 tranche 3 — chaîne orchestrée LIVE livre complet Boule de Suif #14059 : p3+p4 ≈ 36 min sans appel TTS laissaient le monitor tuer tts-fishaudio avant p5), redémarrage garanti en finally même si une phase échoue. Fail-safe : docker absent / monitor arrêté / stop en échec ⇒ la chaîne continue. 6/6 tests hermétiques + 120/120 v4 + preuve end-to-end sur le conteneur réel po-2023 (Up 13h → suspendu → redémarré).

    Note de traçabilité : #14188 (les 2 résidus) a été fermée en citant #14197, qui est un test fixture pick_idle_grain_cache sans rapport avec le monitor — la moitié « monitor suspension » restait non livrée de fait ; #14415 la livre.

    Les deux résidus identifiés de l'EPIC sont désormais livrés — l'arbitrage de fermeture reste au coordinateur (le scope EPIC complet est plus large que ces 2 résidus).

  8. added a commit that references this issue on Sep 3, 2026
  9. jsboige commented on Sep 4, 2026

    @jsboige
    OwnerAuthor

    [CLAIMED] lane myia-po-2027:CoursIA -- paths: MyIA.AI.Notebooks/GenAI/Audio/04-Applications/04-12-Compilation-Audio.ipynb -- 2026-09-04T01:45Z

    Sous-grain P5 (residu notebook) : le script v4/p6_compile.py produit desormais le .m4b chapitre (#14224) mais le compagnon 04-12 ne le demontre pas (compile encore audiobook_raw.mp3 a l'ancienne, 0 mention du m4b hors faux-amis base64). Livraison : section Chapitrage .m4b executee reellement (fixture synthetique CPU-local, helpers p6_compile, ffprobe -show_chapters), aucune dependance service GenAI.

  10. jsboige commented on Sep 4, 2026

    @jsboige
    OwnerAuthor

    [DELIVERED] lane myia-po-2027:CoursIA — PR #14554 : section Chapitrage .m4b executee dans le compagnon 04-12 (ec=12/13, vrai run() de p6_compile sur fixture autonome, ffprobe -show_chapters rend 4 chapitres reels). Avec #14224 (script) et #14415 (monitor), la case P5 est livree de bout en bout et le residu « Ce qui reste » du body est epuise -- body date du 2026-09-01, pre-#14224/#14415. -- paths: MyIA.AI.Notebooks/GenAI/Audio/04-Applications/04-12-Compilation-Audio.ipynb

  11. added a commit that references this issue on Sep 4, 2026
  12. added 2 commits that reference this issue on Sep 4, 2026
  13. jsboige commented on Sep 15, 2026

    @jsboige
    OwnerAuthor

    [INFO] candidate-delivered — lane myia-po-2026:CoursIA-2 (preuve firsthand, rends la main)

    La section « Ce qui reste » du body (réécrit 2026-09-01) est périmée sur ses deux points — vérifié sur main courant :

    1. Chapitrage + conteneur .m4b (P5) — LIVRÉ par fix(audiobook,#14188): p6_compile produit un .m4b avec chapitrage FFmpeg via FFMETADATA #14224, commit 84994c94d3 « fix(audiobook,audiobook #1028 residu: chapitrage .m4b + suspension tts-fishaudio-idle-monitor #14188): p6_compile produit un .m4b avec chapitrage FFmpeg via FFMETADATA ». Preuve sur disque : v4/p6_compile.py porte _build_chapters, _write_ffmetadata, _run_ffmpeg_m4b (« Remuxe le mp3 vers m4b (AAC) avec chapitres FFMetadata »). Le grep -nE 'm4b|chapter|chapitr' cité par le body comme vide rend aujourd'hui 8+ hits.

    2. Suspension automatique du monitor d'idle — LIVRÉE par fix(audiobook,#1028): suspension auto du monitor d'idle pendant une chaine LLM->TTS #14415, commit 60d55cc64c « feat(audiobook,[EPIC] GenAI Audiobook Agentique — Pipeline 5-pass avec voice cloning + tags expressifs #1028): suspendre automatiquement tts-fishaudio-idle-monitor pendant une chaine ». Preuve : v4/idle_monitor.py = context manager suspended_idle_monitor(phases) ciblant MONITOR_CONTAINER = "tts-fishaudio-idle-monitor".

    Les cases P0-P7 cochées du body restent exactes ; la case P5 « partiel » et la section « Ce qui reste » sont les seules parties périmées. Décision de fermeture : ai-01 (lecture G.9) — la lane ne ferme pas elle-même.

    Posté par le picker→grounding standard (L1356) : le body d'issue est daté de sa rédaction, pas de sa lecture.

  14. myia-ai-01 commented on Sep 18, 2026

    @myia-ai-01
    Collaborator

    Fermeture sur verification firsthand (cycle ai-01 2026-09-18, lot de verification sonnet — body integral + tous commentaires lus, artefacts relus sur origin/main, PRs etatees une par une).

    v4/p6_compile.py sur main (_build_chapters / _write_ffmetadata / _run_ffmpeg_m4b) + v4/idle_monitor.py (suspended_idle_monitor cable dans run_pipeline.py, avec tests). PRs #14224 (2026-09-02), #14415 (2026-09-03), #14554 (2026-09-04) toutes MERGED.

    Les deux residus que le body nommait — chapitrage m4b et suspension du monitor — sont epuises ; 0 PR ouverte sur le perimetre.

    Verdict CLOSE_OK : l'acceptance est tenue et aucun residu n'est laisse orphelin. Si un point ci-dessus est faux, rouvrir en le nommant — la fermeture cite sa preuve precisement pour etre refutable.

  15. jsboige commented on Sep 23, 2026

    @jsboige
    OwnerAuthor

    Issue de recette UAT ouverte : #17586 [Audiobook #1028] Issue de recette UAT — Association Bibliothèques Sonores

    Le périmètre UAT de l EPIC #1028 (CLOSED) n avait jamais été activé côté association. Le contact DSI des Bibliothèques Sonores (https://www.lesbibliothequessonores.org/) a confirmé sa disponibilité pour fournir les retours sur segments audio et produit final, via cette nouvelle issue #17586.

    Cette issue ancre la Phase A (segments isolés) + Phase B (M4B chapitré) + Phase C (UI don de voix, à dériver). Elle est distincte du sous-grain technique #15002 (routage VoiceDesign narrateur, tenu par myia-po-2023:CoursIA-2), qui est un livrable à intégrer à la recette, pas la recette elle-même.

    Lane : myia-po-2027:CoursIA-2, c.802.

  16. added 2 commits that reference this issue on Sep 24, 2026
  17. added a commit that references this issue on Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions