Repository navigation
[EPIC] GenAI Audiobook Agentique — Pipeline 5-pass avec voice cloning + tags expressifs #1028
Description
Activity
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.ipynbCouvre :
fish_speech+fish-audio-sdkinstall (local GPU 14+ GB OU cloud API)- Chargement
fishaudio/s2-prolocal + fallback cloud TTSInferenceinvocation- 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.ipynbP2 — Voice casting Extension du même notebook (multi-perso au lieu d'1 voix) P3 — Annotation prosodique Tags s2-prodéjà documentés dans 02-8P4 — Génération TTS TTSInferencecell-by-cell déjà fonctionnelAction
Lors du dispatch Phase P0 (post-EPITA/ESGF), partir explicitement de
02-8-Expressive-TTS.ipynbet l'enrichir versMyIA.AI.Notebooks/GenAI/Audio/04-Applications/(nouveau notebook04-6-Audiobook-Pipeline.ipynbou similaire).Repo
fish-speechà monitorer pour :- Mises à jour modèle (S2 Pro → S3 ? S2 Max ?)
- Évolution API tags expressifs
- Performance benchmarks officiels
cc @jsboige
[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.jsonvia SK + plugin chunk-reader.Scope Phase 1
- Repo design dans
MyIA.AI.Notebooks/GenAI/Audiobook/(créer le dossier si absent). 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
- Chargement livre
- Outputs persistés en JSON sous
MyIA.AI.Notebooks/GenAI/Audiobook/output/ - 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 != nullpartout (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.
- Repo design dans
- added 9 commits that reference this issue
on May 15, 2026 Epic CLOSED 100% — 8/8 PRs livrees (P0/P1/P2/P3/P4/P5 + READMEs + post-mortem). Pipeline complet en C66-C72.
Livraisons :
- P0/P1/P2 : initial ingest + segmentation + voice mapping (PRs anterieures Epic)
- P3 feat(audio): P3 prosodic annotation — FishAudio expressive tags (Epic #1028) #1247 prosodic annotation MERGED C70
- P4 feat(audio): P4 TTS generation — Kokoro 14 segments (Epic #1028) #1251 TTS Kokoro 14/14 segments MP3 128kbps MERGED C71
- P5 feat(audio): P5 audio compilation — audiobook final (Epic #1028) #1254 audiobook compilation (boule_de_suif_finalized.mp3 2.0 MB) MERGED C72
- docs(audio): update READMEs for Epic #1028 audiobook pipeline #1258 Audio READMEs MERGED C71
- docs: Epic #1028 audiobook pipeline post-mortem #1259 Post-mortem doc MERGED C72
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.
- added a commit that references this issue
on May 18, 2026 - added a commit that references this issue
on May 18, 2026 49 remaining items
- added a commit that references this issue
on Sep 1, 2026 Confrontation sur les résidus de l'EPIC (grain MED/genai, lane myia-po-2023:CoursIA) :
- 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.
- Résidu monitor-suspension — livré par PR fix(audiobook,#1028): suspension auto du monitor d'idle pendant une chaine LLM->TTS #14415 :
run_pipelinesuspend automatiquementtts-fishaudio-idle-monitorle 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 tuertts-fishaudioavant p5), redémarrage garanti enfinallymê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_cachesans 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).
- added a commit that references this issue
on Sep 3, 2026 [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.
[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
- added a commit that references this issue
on Sep 4, 2026 [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
maincourant :-
Chapitrage + conteneur
.m4b(P5) — LIVRÉ par fix(audiobook,#14188): p6_compile produit un .m4b avec chapitrage FFmpeg via FFMETADATA #14224, commit84994c94d3« 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.pyporte_build_chapters,_write_ffmetadata,_run_ffmpeg_m4b(« Remuxe le mp3 vers m4b (AAC) avec chapitres FFMetadata »). Legrep -nE 'm4b|chapter|chapitr'cité par le body comme vide rend aujourd'hui 8+ hits. -
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 managersuspended_idle_monitor(phases)ciblantMONITOR_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.
-
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.pysur main (_build_chapters/_write_ffmetadata/_run_ffmpeg_m4b) +v4/idle_monitor.py(suspended_idle_monitorcable dansrun_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.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.
- added a commit that references this issue
on Sep 25, 2026
É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é parscripts/audiobook_pipeline.py) est une chaîne à huit passes dont plusieurs n'existaient pas dans le plan :p0p0_narrative_research.pyp1_5p1_5_speaker_catalog.pyp2p2_segmentation.pyp3p3_dramatic_context.pyp4p4_annotation.pyp5p5_tts.pyp6cp6_compile.pyp7p7_verify.pyLa
p7est 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-p7de la v4 ci-dessus. La tâche P7 est le dataset ; la passep7est la vérification. Deux séries, deux sens.04-7-TTS-Voice-Benchmark.ipynb, plus le bancv4/prosody_lab/(ab_engine_test.py,ab_clone_test.py,clone_decisive.py, clients OpenAI / Qwen / FishAudio). Substitution de candidats, à noter honnêtement : les deux dépôts HF nommés en 2026-05 (nellaw/…,Shriramnag/…) n'ont jamais été benchmarkés — 0 occurrence dans le dépôt (clarification du 2026-08-30, conservée plus bas). L'axe clonage a bien été couvert, par un A/B clonage vs prompt (feat(audio,#11624): TTS gateway revival + cloning-vs-prompt A/B + melody partition, gated extract regen #11646) sur les moteurs réellement déployés. La case est cochée sur l'axe, pas sur la liste de candidats d'origine.04-8-Lecture-Analytique.ipynb+v4/p2_segmentation.py.04-9-Voice-Casting.ipynb+v4/remediate_voice_casting.py. Les trois voixREJECT-MONOTONEdu casting v4 ont été reprises et repassées (issue Audiobook #1028 sous-grain: remediation voice casting v4 (8 segments sous le floor) + dossier de revue DoR #11346, livrée par feat(genai,#11346): remediation voice casting v4 — 2/3 REJECT-MONOTONE corriges (comtesse, loiseau PASS-TO-EAR) #11350 et fix(genai,#11346): re-clone cornudet — sample interrogatif, seg118 REJECT->WARN (3/3 traites) #11353), et la validation « par écoute » est instrumentée, pas déclarative (voir ci-dessous).04-10-Annotation-Prosodique.ipynb+v4/p4_annotation.py.04-11-Generation-TTS.ipynb+v4/p5_tts.py.04-12-Compilation-Audio.ipynbetv4/p6_compile.pyexistent, ffmpeg tourne, et la compilation s'est exécutée live sur le livre entier (feat(genai,#1028): P6 tranche 3 — chaîne orchestrée LIVE livre complet Boule de Suif #14059). Maisp6_compile.pyproduit un.mp3unique (outputs/boule_de_suif_v4.mp3) : ni conteneur.m4b, ni chapitrage — les deux mots que la tâche P5 nomme. Ungrep -nE 'm4b|chapter|chapitr'sur ce fichier ne rend aucune ligne. C'est le résidu réel de cet EPIC.scripts/audiobook_pipeline.py, livré en trois tranches : orchestrateur--bookarbitraire +--dry-run(feat(genai,#1028): P6 tranche 1 -- orchestrateur audiobook_pipeline.py (chainage p0..p7, --book arbitraire, --dry-run) #12355), première chaîne LIVE bornée sur mini-livre (feat(genai,#13898): P6 tranche 2 — première chaîne orchestrée LIVE p1_5..p7 (passes gated) #13905), puis chaîne LIVE complète 385 paragraphes / 64 chunks, toutes passes gated réellement exécutées (feat(genai,#1028): P6 tranche 3 — chaîne orchestrée LIVE livre complet Boule de Suif #14059).boule_de_suif_full.txt,datasets/le_horla_1887.txt(feat(genai,#1028): P7 tranche 1 -- dataset livres arbitraires (Le Horla 1887 PD + personas 100% synthetiques) #12362),datasets/mlle_fifi_nouveaux_contes.txt(feat(genai,#1028): add second public-domain audiobook dataset #13521), plusdatasets/synthetic/pour les personas 100 % synthétiques.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-monitorarrêtetts-fishaudioaprè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, etp5arrive 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
.m4b(P5) — le seul livrable nommé dans les tâches qui n'existe pas surmain.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
characters.json(perso + traits) +utterances.json(prises de parole index avec speaker tag)characters.jsonfishaudio/s2-pro,nellaw/xtts-french-voice-cloning-optimized, Qwen-Omni prompt acoustiquevoices/<char_id>.wavsamples 5-15sutterances.jsons2-pro(joie, colère, chuchotement, etc.)book.ssml.mdmarkdown enrichi tagsbook.ssml.md+voices/s2-proprincipal, XTTS-v2 fallbackchunks/chunk_NNNN.wavchunks/output/audiobook.mp3ou.m4bchapitréModèles candidats (P0 benchmark, 2026-05)
fishaudio/s2-pro— tags expressifs natifs, multilangue, support clone in-context. Retenu et déployé (v4/fishaudio_client.py, servicetts-fishaudio).nellaw/xtts-french-voice-cloning-optimized— jamais benchmarké (voir clarifications).Shriramnag/Shiv-AI-Voice-Cloning— jamais benchmarké (voir clarifications).qwen-asr-api= Qwen3-ASR-1.7B, transcription/STT, pas de génération.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.ipynbMyIA.AI.Notebooks/GenAI/Audio/02-Advanced/02-8-Expressive-TTS.ipynbMyIA.AI.Notebooks/GenAI/Audio/03-Orchestration/03-2-Audio-Pipeline-Orchestration.ipynbMyIA.AI.Notebooks/GenAI/Audio/04-Applications/04-1-Educational-Audio-Content.ipynbMyIA.AI.Notebooks/GenAI/Texte/— agents lecture livre, chunking, function calling, RAGÉthique
Cas d'usage
cc @jsboige
Clarifications vérifiées (2026-08-30 — tri ROO-1, réfutations Vibe)
git grep -i "qwen omni|qwen_omni|qwen2.5-omni"= 0 hit). Le service Qwen audio existant estdocker-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-optimizedetShriramnag/Shiv-AI-Voice-Cloning: 0 occurrence dans le dépôt (git grepvide). Ce sont des candidats externes à benchmarker (greenfield) — aucun scaffolding existant. L'existant XTTS = le notebookMyIA.AI.Notebooks/GenAI/Audio/02-Advanced/02-2-XTTS-Voice-Cloning.ipynb(présent, vérifié) et le service Dockertts-fishaudiopour s2-pro.demucs-api,tts-api) mais Kokoro est un TTS, pas un outil de mastering.