Creation de Contenu Audio Educatif

Module : 04-Audio-Applications
Niveau : Applications
Technologies : OpenAI TTS, Kokoro TTS, Whisper, GPT (LLM), pydub
VRAM estimee : ~10 GB
Duree estimee : 50 minutes

Objectifs d’Apprentissage

Prerequis

  • Notebooks Foundation (01-1 a 01-5) completes
  • Cle API OpenAI configuree (OPENAI_API_KEY dans .env)
  • pydub installe (manipulation audio)
  • Comprehension de base du TTS et du STT

Navigation : Index | << Précédent | Suivant >>

# Parametres Papermill - JAMAIS modifier ce commentaire

# Configuration notebook
notebook_mode = "interactive"        # "interactive" ou "batch"
skip_widgets = False               # True pour mode batch MCP
debug_level = "INFO"

# Parametres contenu educatif
tts_model = "tts-1"               # "tts-1" ou "tts-1-hd"
narrator_voice = "nova"            # Voix principale de narration
secondary_voice = "onyx"           # Voix secondaire (exemples, citations)
llm_model = "gpt-4o-mini"         # Modele LLM pour generation de scripts
target_languages = ["fr", "en"]    # Langues cibles
accessibility_speed = 0.85         # Vitesse reduite pour accessibilite

# Configuration sauvegarde
generate_audio = True
save_audio_files = True
# Parameters
BATCH_MODE = True
skip_widgets = True

L’environnement de travail est configure avec les paramètres Papermill. La cellule suivante charge les bibliotheques Python necessaires : gestion des fichiers audio, appels API et utilitaires de traitement.

# Setup environnement et imports
import os
import sys
import json
import time
from pathlib import Path
from datetime import datetime
from typing import Dict, List, Any, Optional
from io import BytesIO
import logging

from IPython.display import Audio, display, HTML

# Resolution GENAI_ROOT
GENAI_ROOT = Path.cwd()
while GENAI_ROOT.name != 'GenAI' and len(GENAI_ROOT.parts) > 1:
    GENAI_ROOT = GENAI_ROOT.parent

HELPERS_PATH = GENAI_ROOT / 'shared' / 'helpers'
if HELPERS_PATH.exists():
    sys.path.insert(0, str(HELPERS_PATH.parent))
    try:
        from helpers.audio_helpers import (
            play_audio_bytes, display_audio_bundle, synthesize_openai, transcribe_openai,
            get_audio_info, estimate_audio_duration
        )
        print("Helpers audio importes")
    except ImportError as e:
        print(f"Helpers audio non disponibles - mode autonome : {e}")

# Repertoire de sortie
OUTPUT_DIR = GENAI_ROOT / 'outputs' / 'audio' / 'educational'
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)

# Configuration logging
logging.basicConfig(level=getattr(logging, debug_level))
logger = logging.getLogger('educational_audio')

print(f"Creation de Contenu Audio Educatif")
print(f"Date : {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"Mode : {notebook_mode}, TTS : {tts_model}")
print(f"Voix narrateur : {narrator_voice}, Voix secondaire : {secondary_voice}")
print(f"Sortie : {OUTPUT_DIR.relative_to(GENAI_ROOT)}")
Helpers audio importes
Creation de Contenu Audio Educatif
Date : 2026-08-16 01:49:49
Mode : interactive, TTS : tts-1
Voix narrateur : nova, Voix secondaire : onyx
Sortie : outputs\audio\educational

Les modules Python sont importes. Cette cellule charge les cles API depuis le fichier .env en remontant l’arborescence de repertoires pour s’adapter aux différents contextes d’exécution (local, Papermill, CI).

# Chargement robuste de la configuration .env (Pattern A - Papermill-safe)
from dotenv import load_dotenv
import os
from pathlib import Path

current_path = Path.cwd()
genai_path = None

# Remonter jusqu'au dossier GenAI
while len(current_path.parts) > 1:
    if current_path.name == "GenAI":
        genai_path = current_path
        break
    current_path = current_path.parent

if genai_path:
    env_path = genai_path / ".env"
    if env_path.exists():
        load_dotenv(env_path)
        print(f".env charge depuis: {env_path.name}")

# Configuration API OpenAI
openai_key = os.environ.get('OPENAI_API_KEY', '')
openai_available = bool(openai_key and not openai_key.startswith('sk-or-'))

if openai_available:
    print("OPENAI_API_KEY valide - API disponible")
    from openai import OpenAI
    client = OpenAI(api_key=openai_key)
else:
    print("OPENAI_API_KEY non disponible ou invalide (cle OpenRouter)")
    openai_key = "dummy_key_for_validation"
    client = None
.env charge depuis: .env
OPENAI_API_KEY valide - API disponible

Pipeline complet de creation de contenu audio educatif

Ce notebook explore la creation de contenus audio pedagogiques en utilisant les technologies de l’IA : LLM pour la generation de scripts, TTS (Text-to-Speech) pour la narration, et STT (Speech-to-Text) pour la validation qualite.

Cas d’usage pedagogiques :

Scénario Description Technologies
Cours audio pour MOOC Modules narres accessibles offline LLM + TTS multi-voix
Contenu multilingue Cours traduits en plusieurs langues Traduction LLM + TTS multilingue
Accessibilite MALV Adaptation pour publics a besoins spécifiques TTS vitesse reduite + enonciation claire
Podcasts educatifs Contenu audio structuré et engageant Multi-voix + assemblage pydub
Validation qualite Verification fidelite narration Round-trip TTS->STT

Architecture du pipeline :

Texte de cours (ecrit)
         ↓
    [LLM] GPT-4o-mini
   (Adaptation ecrit→oral)
         ↓
  Script narre avec marqueurs
  [NARRATEUR], [EXPERT], [PAUSE]
         ↓
    [Parsing] Python
   (Extraction segments par voix)
         ↓
   [TTS] OpenAI tts-1
 (Synthese audio multi-voix)
         ↓
  [Assemblage] pydub
 (Concatenation + normalisation)
         ↓
   [Validation] Whisper
  (Round-trip STT)
         ↓
  Cours audio final (.mp3)

Nous allons implementer ce pipeline étape par étape, en testant différentes configurations (multi-voix, multilingue, accessibilite) pour evaluer leur impact pedagogique.


Section 1 : Generation de scripts de narration via LLM

La première étape d’un contenu audio educatif consiste a transformer un texte brut de cours en un script de narration naturel. Un LLM adapte le contenu technique en discours oral fluide :

Étape Description Outil
Texte source Contenu pedagogique brut –
Reformulation Adaptation pour la narration orale GPT-4o-mini
Structuration Decoupage en sections narrees GPT-4o-mini
Attribution voix Assignation des voix par section Configuration

Le LLM recoit le texte de cours et genere un script avec des indications de voix, pauses et intonation.

# Generation de scripts de narration a partir de texte de cours
print("GENERATION DE SCRIPTS DE NARRATION")
print("=" * 50)

# Texte de cours source (exemple : introduction a l'IA)
course_text = """
L'intelligence artificielle (IA) est un domaine de l'informatique qui vise
a creer des systemes capables de realiser des taches necessitant normalement
l'intelligence humaine. Ces taches incluent la reconnaissance vocale,
la prise de decision, la traduction et la generation de contenu.

Le machine learning (apprentissage automatique) est une sous-branche de l'IA
qui permet aux machines d'apprendre a partir de donnees sans etre explicitement
programmees. Les reseaux de neurones profonds (deep learning) sont une technique
de machine learning inspiree du cerveau humain.
""".strip()

# Prompt pour le LLM : transformer en script de narration
narration_prompt = f"""
Transforme ce texte de cours en un script de narration audio educatif.
Le script doit :
- Etre naturel a l'oral (phrases courtes, transitions fluides)
- Inclure des marqueurs [PAUSE] pour les pauses naturelles
- Indiquer les changements de voix avec [NARRATEUR] et [EXPERT]
- Ajouter une introduction accueillante et une conclusion

Texte source :
{course_text}

Genere uniquement le script, sans commentaires.
"""

narration_script = ""
if generate_audio:
    start_time = time.time()
    response = client.chat.completions.create(
        model=llm_model,
        messages=[{"role": "user", "content": narration_prompt}],
        temperature=0.7,
        max_tokens=1000
    )
    narration_script = response.choices[0].message.content
    gen_time = time.time() - start_time

    print(f"Script genere en {gen_time:.1f}s")
    print(f"Tokens utilises : {response.usage.total_tokens}")
    print(f"\n--- Script de narration ---")
    print(narration_script)
    print(f"--- Fin du script ---")
    print(f"\nLongueur : {len(narration_script)} caracteres")
    print(f"Duree estimee : {estimate_audio_duration(narration_script):.0f}s")
else:
    print("Generation desactivee (generate_audio=False)")
GENERATION DE SCRIPTS DE NARRATION
==================================================
Script genere en 5.4s
Tokens utilises : 609

--- Script de narration ---
[NARRATEUR] Bonjour et bienvenue dans cet épisode consacré à l'intelligence artificielle, ou IA. [PAUSE] Aujourd'hui, nous allons explorer ce domaine fascinant de l'informatique. [PAUSE] Prêt ? C'est parti !

[NARRATEUR] L'intelligence artificielle vise à créer des systèmes capables d'accomplir des tâches qui nécessitent normalement l'intelligence humaine. [PAUSE] Ces tâches incluent, par exemple, la reconnaissance vocale, [PAUSE] la prise de décision, [PAUSE] la traduction et même la génération de contenu. [PAUSE] Intéressant, n'est-ce pas ?

[EXPERT] En effet, l'IA est omniprésente dans notre quotidien. [PAUSE] Mais pour mieux comprendre, il est essentiel de se pencher sur une de ses sous-branches : le machine learning, ou apprentissage automatique. [PAUSE] Cette technique permet aux machines d'apprendre à partir de données, sans être explicitement programmées. [PAUSE] C'est ce qui les rend si puissantes.

[NARRATEUR] Exactement ! [PAUSE] Et pour aller encore plus loin, nous avons le deep learning, ou apprentissage profond. [PAUSE] C'est une technique inspirée du fonctionnement du cerveau humain. [PAUSE] Les réseaux de neurones profonds imitent la façon dont nous apprenons, [PAUSE] ce qui permet aux machines de résoudre des problèmes complexes.

[NARRATEUR] Voilà un aperçu de l'intelligence artificielle et de ses sous-disciplines. [PAUSE] C'est un domaine en constante évolution, [PAUSE] qui transforme notre monde de manière incroyable. [PAUSE] Merci de nous avoir écoutés aujourd'hui ! [PAUSE] À très bientôt pour de nouvelles découvertes !
--- Fin du script ---

Longueur : 1566 caracteres
Duree estimee : 89s

Interpretation : Generation de scripts par LLM

Aspect Valeur observee Analyse pedagogique
Temps de generation runtime machine-dep : ~8 secondes Rapide, permet itérations et affinements
Tokens utilises 599 (input + output) Economique pour GPT-4o-mini
Longueur script 1516 caractères ~2x le texte source (adaptation ecrit->oral)
Duree estimee ~80 secondes Format micro-module ideal
Structure Alternance NARRATEUR/EXPERT Decoupage pedagogique coherent

Points cles : 1. Le LLM adapte naturellement le registre ecrit vers l’oral (phrases plus courtes, transitions) 2. Les marqueurs [PAUSE] indiquent les rythmes naturels de la parole 3. La structure multi-voix emerge spontanement du prompt pedagogique 4. Temperature 0.7 = equilibre entre fidelite au contenu et creativité orale

Note technique : Pour des contenus plus longs, decouper en sections de 200-300 mots et generer des scripts separes avec des contextes différents (introduction, développement, conclusion).


Section 1 : Generation de scripts de narration via LLM

La première étape d’un contenu audio educatif consiste a transformer un texte brut de cours en un script de narration naturel. Un LLM (Large Language Model) comme GPT-4o-mini adapte le contenu technique en discours oral fluide.

Pipeline de transformation :

Texte source (cours) -> LLM (GPT-4o-mini) -> Script narre avec marqueurs -> Parsing -> Segments par voix

Marqueurs generes par le LLM :

Marqueur Signification Utilisation
[NARRATEUR] Voix principale Introduction, transitions, conclusion
[EXPERT] Voix d’autorite Definitions, concepts techniques
[PAUSE] Silence naturel Respiration, emphasis, transitions

Le LLM recoit le texte de cours et un prompt pedagogique specifiant le format de sortie, puis genere un script avec des indications de voix, pauses et intonation.


Exercice : Prompt engineering pour scripts de narration

Duree estimee : 15-20 minutes

Objectif

Créer un prompt système optimise pour generer des scripts de narration educative adaptes a différents publics (debutants, experts, enfants).

Contexte

Le script de narration est la base du pipeline audio. La qualite du prompt LLM determine directement la qualite du script genere. Un bon prompt precise le format de sortie, les marqueurs de voix et le registre de langue attendu.

Instructions

  1. Analyser le prompt narration_prompt utilise dans la cellule précédente
  2. Créer une fonction qui genere des scripts adaptes a un niveau de public
  3. Tester avec un même texte source pour 2 niveaux différents
  4. Comparer les scripts obtenus (longueur, structure, vocabulaire)

Indices : - # Étape 1 : Définir les paramètres de niveau (vocabulaire simple vs technique) - # Étape 2 : Construire un prompt dynamique en fonction du niveau - # Étape 3 : Appeler le LLM avec le prompt personnalise - # Indice : Utiliser les paramètres temperature et max_tokens pour ajuster la creativite - # Indice : Un prompt “debutant” doit demander des phrases courtes et des analogies

# TODO: Creer un generateur de scripts adapte au niveau du public
def generate_adaptive_script(source_text: str, target_audience: str = "debutant",
                              llm_client=None, model: str = "gpt-4o-mini") -> str:
    """
    Genere un script de narration adapte au niveau du public cible.
    
    Args:
        source_text: Texte de cours source
        target_audience: "debutant", "intermediaire" ou "expert"
        llm_client: Client OpenAI initialise
        model: Modele LLM a utiliser
    
    Returns:
        Script avec marqueurs [NARRATEUR], [EXPERT], [PAUSE]
    """
    # Etape 1 : Definir les instructions par niveau
    # Indice: Un debutant a besoin d'analogies, un expert de termes techniques
    audience_instructions = None  # TODO etudiant : construire le prompt
    
    # Etape 2 : Construire le prompt complet
    # Indice: Inclure le texte source et les consignes de format
    full_prompt = None  # TODO etudiant
    
    # Etape 3 : Appeler le LLM
    # Indice: adapter temperature selon le niveau (plus creatif pour debutant)
    generated_script = None  # TODO etudiant : appeler llm_client.chat.completions.create()
    
    return generated_script if generated_script else ""

# Test avec le texte de cours du notebook
test_levels = ["debutant", "expert"]
for level in test_levels:
    print(f"\n--- Niveau : {level} ---")
    # script = generate_adaptive_script(course_text, level, client, llm_model)
    # print(f"Script genere ({len(script)} chars) :")
    # print(script[:200] + "...")
    print(f"Exercice a completer pour le niveau {level}")

--- Niveau : debutant ---
Exercice a completer pour le niveau debutant

--- Niveau : expert ---
Exercice a completer pour le niveau expert

Section 2 : Narration multi-voix

Un contenu educatif beneficie de plusieurs voix pour distinguer les rôles :

Rôle Voix suggeree Utilisation
Narrateur principal nova Explications, transitions
Expert / Citations onyx Definitions, concepts cles
Exemples echo Illustrations pratiques

Nous allons parser le script genere, identifier les segments par voix, et generer chaque segment avec la voix appropriee.

# Narration multi-voix : parser et generer par segments
print("NARRATION MULTI-VOIX")
print("=" * 50)

import re

# Mapping des roles vers les voix OpenAI
voice_mapping = {
    "NARRATEUR": narrator_voice,
    "EXPERT": secondary_voice,
    "DEFAULT": narrator_voice
}

def parse_narration_script(script: str) -> List[Dict[str, str]]:
    """Parse un script avec marqueurs [ROLE] en segments."""
    segments = []
    current_role = "DEFAULT"
    current_text = []

    for line in script.split('\n'):
        line = line.strip()
        if not line:
            continue

        # Detection marqueur de role
        role_match = re.match(r'\[(NARRATEUR|EXPERT)\]', line)
        if role_match:
            # Sauvegarder le segment precedent
            if current_text:
                text = ' '.join(current_text).strip()
                text = re.sub(r'\[PAUSE\]', '...', text)
                if text:
                    segments.append({"role": current_role, "text": text})
            current_role = role_match.group(1)
            # Texte apres le marqueur
            remaining = line[role_match.end():].strip()
            current_text = [remaining] if remaining else []
        else:
            current_text.append(line)

    # Dernier segment
    if current_text:
        text = ' '.join(current_text).strip()
        text = re.sub(r'\[PAUSE\]', '...', text)
        if text:
            segments.append({"role": current_role, "text": text})

    return segments

# Parser le script
if narration_script:
    segments = parse_narration_script(narration_script)
else:
    # Script de demonstration si la generation a ete sautee
    segments = [
        {"role": "NARRATEUR", "text": "Bienvenue dans ce cours sur l'intelligence artificielle."},
        {"role": "EXPERT", "text": "L'intelligence artificielle est un domaine qui vise a creer des systemes intelligents."},
        {"role": "NARRATEUR", "text": "Voyons maintenant le machine learning, une sous-branche fondamentale."},
        {"role": "EXPERT", "text": "Le machine learning permet aux machines d'apprendre a partir de donnees."}
    ]

print(f"Segments identifies : {len(segments)}")
print(f"\nDetail des segments :")
for i, seg in enumerate(segments):
    voice = voice_mapping.get(seg['role'], narrator_voice)
    print(f"  [{i+1}] {seg['role']:12s} -> voix '{voice}' | {seg['text'][:60]}...")

# Generer chaque segment avec la voix appropriee
audio_segments = []

if generate_audio:
    print(f"\nGeneration audio par segment :")
    total_start = time.time()

    for i, seg in enumerate(segments):
        voice = voice_mapping.get(seg['role'], narrator_voice)
        start_time = time.time()

        response = client.audio.speech.create(
            model=tts_model,
            voice=voice,
            input=seg['text'],
            response_format="mp3",
            speed=1.0
        )

        audio_data = response.content
        gen_time = time.time() - start_time

        audio_segments.append({
            "role": seg['role'],
            "voice": voice,
            "audio": audio_data,
            "size_kb": len(audio_data) / 1024,
            "time": gen_time
        })

        print(f"  Segment {i+1}/{len(segments)} : {voice} | {gen_time:.1f}s | {len(audio_data)/1024:.1f} KB")

    total_time = time.time() - total_start
    print(f"\nTotal : {len(audio_segments)} segments en {total_time:.1f}s")
    print(f"Taille totale : {sum(s['size_kb'] for s in audio_segments):.1f} KB")

    # Ecouter le premier segment
    if audio_segments:
        print(f"\nEcoute du premier segment ({audio_segments[0]['role']}, voix {audio_segments[0]['voice']}) :")
        display_audio_bundle(audio_segments[0]['audio'])
else:
    print("Generation desactivee")
NARRATION MULTI-VOIX
==================================================
Segments identifies : 5

Detail des segments :
  [1] NARRATEUR    -> voix 'nova' | Bonjour et bienvenue dans cet épisode consacré à l'intellige...
  [2] NARRATEUR    -> voix 'nova' | L'intelligence artificielle vise à créer des systèmes capabl...
  [3] EXPERT       -> voix 'onyx' | En effet, l'IA est omniprésente dans notre quotidien. ... Ma...
  [4] NARRATEUR    -> voix 'nova' | Exactement ! ... Et pour aller encore plus loin, nous avons ...
  [5] NARRATEUR    -> voix 'nova' | Voilà un aperçu de l'intelligence artificielle et de ses sou...

Generation audio par segment :
  Segment 1/5 : nova | 3.3s | 178.1 KB
  Segment 2/5 : nova | 2.5s | 283.9 KB
  Segment 3/5 : onyx | 4.2s | 337.9 KB
  Segment 4/5 : nova | 2.0s | 306.8 KB
  Segment 5/5 : nova | 2.0s | 257.6 KB

Total : 5 segments en 13.9s
Taille totale : 1364.2 KB

Ecoute du premier segment (NARRATEUR, voix nova) :

Interpretation : Narration multi-voix

Aspect Valeur observee Analyse pedagogique
Segments generes 5 segments (4 narrateur, 1 expert) Equilibre narrateur/expert = 4:1, demonstration courte
Voix utilisees nova (narrateur), onyx (expert) Differentiation claire, ton adapte au rôle
Temps generation runtime machine-dep : ~20 secondes pour 5 segments (observe 19.7s) Performance adequate pour production batch
Taille totale 1.6 MB (observe 1623.8 KB) Compact pour ~20 secondes d’audio

Points cles : 1. La multi-voix ameliore l’engagement en variant le timbre et le rythme 2. Les marqueurs [NARRATEUR] et [EXPERT] structurent le contenu de facon automatique 3. Les pauses [PAUSE] converties en ellipses (…) créent un rythme naturel 4. La distinction voix feminine (nova) vs voix masculine (onyx) aide a suivre les changements de rôle

Bon a savoir : Pour les contenus plus complexes, vous pouvez ajouter d’autres rôles (EXEMPLE, DEFINITION, CONCLUSION) avec des voix distinctes (echo, shimmer, fable).

En complement — benefice pedagogique : la multi-voix rend le contenu plus dynamique qu’un narrateur unique, en maintenant l’attention de l’auditeur sur les changements de role.


Section 2 : Narration multi-voix

Un contenu educatif beneficie de plusieurs voix pour distinguer les rôles et maintenir l’engagement de l’auditeur. Cette technique, commune dans les documentaires et podcasts educatifs, s’applique également aux cours audio generes par IA.

Rôles typiques dans un cours audio :

Rôle Voix suggeree Fonction pedagogique
Narrateur principal nova (F) ou alloy (N) Explications, transitions, fil conducteur
Expert / Citations onyx (M) ou fable (N) Definitions techniques, concepts cles, autorite
Exemples / Illustrations echo (F) ou shimmer (F) Cas pratiques, analogies, ton plus leger

Nous allons parser le script genere par le LLM pour identifier les segments par rôle (marqueurs [NARRATEUR], [EXPERT]), puis generer chaque segment avec la voix OpenAI appropriee.

Section 3 : Contenu multilingue

L’API OpenAI TTS gere nativement de nombreuses langues. Pour créer du contenu multilingue, deux approches :

Approche Description Avantage
Traduction LLM + TTS Traduire via GPT, puis synthetiser Contrôle total du texte
TTS direct multilingue Fournir le texte dans la langue cible Plus simple, qualite variable

Nous utilisons la première approche pour garantir la qualite pedagogique du contenu traduit.

# Contenu multilingue : traduction + narration
print("CONTENU MULTILINGUE")
print("=" * 50)

# Texte source en francais
source_text_fr = (
    "L'apprentissage automatique permet aux ordinateurs d'apprendre "
    "a partir d'exemples. Au lieu de programmer chaque regle manuellement, "
    "on fournit des donnees et l'algorithme decouvre les patterns par lui-meme."
)

lang_configs = {
    "fr": {"name": "Francais", "voice": "nova", "text": source_text_fr},
    "en": {"name": "English", "voice": "alloy", "text": None}  # A traduire
}

multilingual_results = {}

if generate_audio:
    # Etape 1 : Traduction vers l'anglais via LLM
    print("Etape 1 : Traduction via LLM")
    translation_response = client.chat.completions.create(
        model=llm_model,
        messages=[{
            "role": "user",
            "content": f"Traduis ce texte educatif en anglais, en gardant le ton pedagogique :\n\n{source_text_fr}"
        }],
        temperature=0.3
    )
    lang_configs["en"]["text"] = translation_response.choices[0].message.content

    for lang_code, config in lang_configs.items():
        print(f"\n--- {config['name']} ({lang_code}) ---")
        print(f"Texte : {config['text'][:80]}...")

        start_time = time.time()
        response = client.audio.speech.create(
            model=tts_model,
            voice=config['voice'],
            input=config['text'],
            response_format="mp3"
        )
        audio_data = response.content
        gen_time = time.time() - start_time

        multilingual_results[lang_code] = {
            "audio": audio_data,
            "text": config['text'],
            "voice": config['voice'],
            "size_kb": len(audio_data) / 1024,
            "time": gen_time
        }

        print(f"Voix : {config['voice']} | {gen_time:.1f}s | {len(audio_data)/1024:.1f} KB")
        display_audio_bundle(audio_data)

        if save_audio_files:
            filepath = OUTPUT_DIR / f"multilingual_{lang_code}.mp3"
            with open(filepath, 'wb') as f:
                f.write(audio_data)
            print(f"Sauvegarde : {filepath.name}")

    # Comparaison
    print(f"\nComparaison multilingue :")
    print(f"{'Langue':<12} {'Voix':<10} {'Taille (KB)':<12} {'Temps (s)':<10}")
    print("-" * 44)
    for lang, data in multilingual_results.items():
        print(f"{lang:<12} {data['voice']:<10} {data['size_kb']:<12.1f} {data['time']:<10.1f}")
else:
    print("Generation desactivee")
CONTENU MULTILINGUE
==================================================
Etape 1 : Traduction via LLM

--- Francais (fr) ---
Texte : L'apprentissage automatique permet aux ordinateurs d'apprendre a partir d'exempl...
Voix : nova | 2.2s | 195.8 KB
Sauvegarde : multilingual_fr.mp3

--- English (en) ---
Texte : Machine learning enables computers to learn from examples. Instead of manually p...
Voix : alloy | 1.6s | 160.9 KB
Sauvegarde : multilingual_en.mp3

Comparaison multilingue :
Langue       Voix       Taille (KB)  Temps (s) 
--------------------------------------------
fr           nova       195.8        2.2       
en           alloy      160.9        1.6       

Interpretation : Contenu multilingue

Langue Voix Taille fichier Qualite perçue
Francais (nova) F = voix feminine 253 KB Excellente, ton pedagogique naturel
Anglais (alloy) N = voix neutre 201 KB Excellente, native pour le modèle

Points cles : 1. L’API OpenAI TTS gere nativement de nombreuses langues avec une qualite constante 2. La traduction LLM (GPT-4o-mini) preserve le ton pedagogique et la structure 3. La différence de taille fichier (~20%) s’explique par la densite linguistique (anglais plus concis) 4. Pour des productions multilingues, créer d’abord le script dans la langue source, puis traduire avec des prompts de contexte pedagogique

Note technique : Pour les langues moins supportees (arabe, hindi, etc.), tester avec un locuteur natif avant production large echelle.


Section 3 : Contenu multilingue

L’API OpenAI TTS supporte plus de 50 langues, ce qui permet de créer du contenu educatif multilingue sans changer d’outil. Deux approches sont possibles :

Approche Méthode Avantages Inconvenients
Traduction LLM + TTS Traduire via GPT, puis synthetiser Contrôle total, preservation du ton pedagogique, adaptation culturelle Deux étapes (plus lent)
TTS direct multilingue Fournir texte traduit, synthetiser direct Plus simple, une seule étape Qualite depend de la traduction source

Nous utilisons la première approche (traduction LLM) pour garantir que le contenu reste pedagogique et naturel dans chaque langue cible. Le prompt de traduction inclut le contexte “educatif” pour preserver le ton.

Section 4 : Accessibilite audio

Un contenu educatif accessible doit prendre en compte différents profils d’apprenants :

Paramètre Valeur standard Valeur accessible Impact
Vitesse 1.0x 0.85x Meilleure comprehension
Pauses Courtes Allongees Temps de reflexion
Voix Au choix Claire, posee Intelligibilite
Repetitions Aucune Concepts cles repetes Memorisation
# Accessibilite : vitesse reduite et enonciation claire
print("ACCESSIBILITE AUDIO")
print("=" * 50)

accessibility_text = (
    "Un reseau de neurones est compose de couches de neurones artificiels. "
    "Chaque neurone recoit des entrees, les multiplie par des poids, "
    "et applique une fonction d'activation. "
    "Retenez bien : entrees, poids, activation. "
    "C'est le fonctionnement fondamental de tout reseau de neurones."
)

speed_configs = [
    {"label": "Standard (1.0x)", "speed": 1.0},
    {"label": f"Accessible ({accessibility_speed}x)", "speed": accessibility_speed},
    {"label": "Lent (0.7x)", "speed": 0.7}
]

accessibility_results = []

if generate_audio:
    for config in speed_configs:
        print(f"\n--- {config['label']} ---")
        start_time = time.time()

        response = client.audio.speech.create(
            model=tts_model,
            voice=narrator_voice,
            input=accessibility_text,
            response_format="mp3",
            speed=config['speed']
        )

        audio_data = response.content
        gen_time = time.time() - start_time

        accessibility_results.append({
            "label": config['label'],
            "speed": config['speed'],
            "audio": audio_data,
            "size_kb": len(audio_data) / 1024,
            "time": gen_time
        })

        print(f"Taille : {len(audio_data)/1024:.1f} KB | Temps : {gen_time:.1f}s")
        display_audio_bundle(audio_data)

    # Comparaison
    print(f"\nComparaison des vitesses :")
    print(f"{'Mode':<25} {'Vitesse':<10} {'Taille (KB)':<12}")
    print("-" * 47)
    for r in accessibility_results:
        print(f"{r['label']:<25} {r['speed']:<10} {r['size_kb']:<12.1f}")

    print(f"\nLa version accessible est ~{accessibility_results[1]['size_kb']/accessibility_results[0]['size_kb']*100:.0f}% de la taille standard")
else:
    print("Generation desactivee")
ACCESSIBILITE AUDIO
==================================================

--- Standard (1.0x) ---
Taille : 268.5 KB | Temps : 1.6s

--- Accessible (0.85x) ---
Taille : 312.0 KB | Temps : 2.4s

--- Lent (0.7x) ---
Taille : 384.8 KB | Temps : 2.9s

Comparaison des vitesses :
Mode                      Vitesse    Taille (KB) 
-----------------------------------------------
Standard (1.0x)           1.0        268.5       
Accessible (0.85x)        0.85       312.0       
Lent (0.7x)               0.7        384.8       

La version accessible est ~116% de la taille standard

Interpretation : Paramètres d’accessibilite

Vitesse Taille fichier Impact pedagogique
1.0x (standard) 338 KB Rythme normal, adapté aux apprenants familiers
0.85x (accessible) 396 KB (+17%) Meilleure comprehension, temps de reflexion
0.7x (lent) 478 KB (+41%) Pour contenus complexes ou public non expert

Points cles : 1. La vitesse reduite (0.85x) est recommandee pour l’accessibilite cognitive 2. L’augmentation de taille (~17%) est acceptable pour le gain pedagogique 3. Les pauses implicites (vitesse reduite) aident a la memorisation 4. Pour les publics MALV (Malentendants, Aveugles, Low Vision, troubles cognitifs), privilegier 0.85x

Bon a savoir : L’API OpenAI TTS supporte des vitesses de 0.25 a 4.0, mais 0.7-1.0 est la plage optimale pour la voix naturelle.


Section 4 : Accessibilite audio

Un contenu educatif accessible doit prendre en compte différents profils d’apprenants. Les paramètres d’accessibilite audio visent a rendre le contenu comprehensible par le plus grand nombre :

Profil Besoin Adaptation audio
Apprenants non experts Temps d’assimilation Vitesse reduite (0.85x)
Public MALV cognitif Traitement séquentiel Pauses allongees, reformulations
Malentendants Clarte d’enonciation Voix posee, vitesse stable
Non-natifs Exposition progressive Vitesse 0.85x, articulation claire

Nous allons tester l’impact de la vitesse sur la qualite perçue et la taille du fichier audio.

Section 5 : Assemblage d’un cours narrate complet

L’assemblage final combine tous les segments audio en un fichier unique avec pydub. Le processus :

  1. Charger chaque segment audio genere
  2. Ajouter des silences entre les sections (transition naturelle)
  3. Concatener dans l’ordre du script
  4. Normaliser le volume global
  5. Exporter en format final
# Assemblage du cours narrate complet
print("ASSEMBLAGE DU COURS NARRATE")
print("=" * 50)

# Verifier la disponibilite de pydub/ffmpeg
skip_assembly = False
try:
    from pydub import AudioSegment
    from pydub.silence import detect_nonsilent
    # Tester l'acces a ffmpeg
    test_segment = AudioSegment.silent(duration=100)
    del test_segment
except (ImportError, FileNotFoundError, OSError) as e:
    print(f"ATTENTION: pydub/ffmpeg non disponible - assemblage saute")
    print(f"  Raison: {type(e).__name__}: {str(e)[:100]}")
    print(f"  Solution: installez ffmpeg ou utilisez un environnement avec ffmpeg dans PATH")
    skip_assembly = True
    audio_segments_assembled = None

if not skip_assembly and generate_audio and audio_segments:
    try:
        # Silence entre les segments (ms)
        inter_segment_silence = 800   # Entre segments du meme role
        inter_section_silence = 1500  # Entre sections (changement de role)

        # Construire le fichier final
        final_audio = AudioSegment.silent(duration=500)  # Silence initial
        prev_role = None

        for i, seg in enumerate(audio_segments):
            # Charger le segment
            segment_audio = AudioSegment.from_mp3(BytesIO(seg['audio']))

            # Ajouter silence adapte
            if prev_role is not None:
                silence_ms = inter_section_silence if seg['role'] != prev_role else inter_segment_silence
                final_audio += AudioSegment.silent(duration=silence_ms)

            final_audio += segment_audio
            prev_role = seg['role']
            print(f"  Segment {i+1} : {seg['role']:12s} ({len(segment_audio)/1000:.1f}s)")

        # Silence final
        final_audio += AudioSegment.silent(duration=500)

        # Normalisation du volume
        target_dBFS = -20.0
        change_in_dBFS = target_dBFS - final_audio.dBFS
        final_audio = final_audio.apply_gain(change_in_dBFS)

        print(f"\nCours assemble :")
        print(f"  Duree totale : {len(final_audio)/1000:.1f}s")
        print(f"  Volume normalise : {final_audio.dBFS:.1f} dBFS")
        print(f"  Segments : {len(audio_segments)}")

        # Sauvegarde
        if save_audio_files:
            output_path = OUTPUT_DIR / "cours_complet_assemble.mp3"
            final_audio.export(str(output_path), format="mp3", bitrate="192k")
            print(f"  Sauvegarde : {output_path.name} ({output_path.stat().st_size/1024:.1f} KB)")

        # Ecouter le resultat
        final_bytes = BytesIO()
        final_audio.export(final_bytes, format="mp3")
        print(f"\nEcoute du cours complet :")
        display_audio_bundle(final_bytes.getvalue())
        
        audio_segments_assembled = final_audio
        
    except Exception as e:
        print(f"Erreur lors de l'assemblage: {type(e).__name__}: {str(e)[:200]}")
        print("L'assemblage a ete saute, mais les segments individuels restent disponibles.")
        audio_segments_assembled = None
else:
    if skip_assembly:
        print("Assemblage non disponible (ffmpeg requis)")
    else:
        print("Assemblage ignore (pas de segments audio disponibles)")
ASSEMBLAGE DU COURS NARRATE
==================================================
  Segment 1 : NARRATEUR    (11.4s)
  Segment 2 : NARRATEUR    (18.2s)
  Segment 3 : EXPERT       (21.6s)
  Segment 4 : NARRATEUR    (19.6s)
  Segment 5 : NARRATEUR    (16.5s)

Cours assemble :
  Duree totale : 92.9s
  Volume normalise : -20.0 dBFS
  Segments : 5
  Sauvegarde : cours_complet_assemble.mp3 (1816.4 KB)

Ecoute du cours complet :

Interpretation : Assemblage du cours complet

Aspect Valeur observee Signification pedagogique
Duree totale ~90 secondes Format ideal pour un micro-module
Silences entre segments 800-1500ms Pauses naturelles pour la comprehension
Normalisation volume -20 dBFS Volume confortable, ecoute prolongee possible
Segments 5 segments Decoupage pedagogique efficace

Points cles : 1. L’assemblage avec pydub permet de créer un flux continu et naturel 2. Les silences variables (800ms vs 1500ms) marquent les changements de rôle 3. La normalisation du volume evite les sauts de loudness entre segments 4. Le format MP3 192kbps offre un bon compromis qualite/taille

Note technique : Pour des cours plus longs, decouper en chapitres de 3-5 minutes chacun avec des titres intermediaires.

En complement — dependance outil : pydub utilise ffmpeg en arriere-plan ; assurez-vous que ffmpeg est installe dans votre environnement avant l’assemblage.


Section 5 : Assemblage d’un cours narre complet

L’assemblage final combine tous les segments audio en un fichier unique avec pydub. Le processus suit 5 étapes :

  1. Charger chaque segment audio genere (format MP3 depuis BytesIO)
  2. Ajouter des silences entre les segments (800ms intra-rôle, 1500ms inter-rôle)
  3. Concatener dans l’ordre du script narre
  4. Normaliser le volume global a -20 dBFS
  5. Exporter en format final (MP3 192kbps)

Cette approche créé une expérience d’ecoute fluide et professionnelle.

Section 6 : Verification qualite par round-trip STT

Pour valider que la narration est fidele au texte source, nous effectuons un round-trip :

Texte source -> TTS -> Audio -> STT -> Texte transcrit -> Comparaison

La similarite entre le texte source et le texte retranscrit mesure la fidelite du pipeline.

# Verification qualite par round-trip STT
print("VERIFICATION QUALITE - ROUND-TRIP STT")
print("=" * 50)

from difflib import SequenceMatcher

roundtrip_text = (
    "Le deep learning utilise des reseaux de neurones profonds "
    "pour apprendre des representations hierarchiques des donnees."
)

if generate_audio:
    # Etape 1 : TTS
    print("Etape 1 : Generation TTS")
    tts_response = client.audio.speech.create(
        model=tts_model,
        voice=narrator_voice,
        input=roundtrip_text,
        response_format="mp3"
    )
    tts_audio = tts_response.content
    print(f"  Audio genere : {len(tts_audio)/1024:.1f} KB")

    # Sauvegarder temporairement pour Whisper
    temp_path = OUTPUT_DIR / "roundtrip_temp.mp3"
    with open(temp_path, 'wb') as f:
        f.write(tts_audio)

    # Etape 2 : STT
    print("Etape 2 : Transcription STT")
    with open(temp_path, 'rb') as audio_file:
        transcript = client.audio.transcriptions.create(
            model="whisper-1",
            file=audio_file,
            language="fr"
        )
    transcribed_text = transcript.text
    print(f"  Texte transcrit : {transcribed_text}")

    # Etape 3 : Comparaison
    print("\nEtape 3 : Comparaison")
    similarity = SequenceMatcher(None,
                                 roundtrip_text.lower(),
                                 transcribed_text.lower()).ratio()

    print(f"  Texte original  : {roundtrip_text}")
    print(f"  Texte transcrit : {transcribed_text}")
    print(f"  Similarite      : {similarity*100:.1f}%")

    if similarity >= 0.9:
        print(f"  Verdict : EXCELLENT - Narration fidele")
    elif similarity >= 0.75:
        print(f"  Verdict : BON - Quelques differences mineures")
    else:
        print(f"  Verdict : A VERIFIER - Differences significatives")

    # Nettoyage
    if temp_path.exists():
        temp_path.unlink()
else:
    print("Verification desactivee")
VERIFICATION QUALITE - ROUND-TRIP STT
==================================================
Etape 1 : Generation TTS
  Audio genere : 112.9 KB
Etape 2 : Transcription STT
  Texte transcrit : Les Deep Learning utilisent des réseaux de neurones profonds pour apprendre des représentations hiérarchiques des données.

Etape 3 : Comparaison
  Texte original  : Le deep learning utilise des reseaux de neurones profonds pour apprendre des representations hierarchiques des donnees.
  Texte transcrit : Les Deep Learning utilisent des réseaux de neurones profonds pour apprendre des représentations hiérarchiques des données.
  Similarite      : 95.4%
  Verdict : EXCELLENT - Narration fidele

Exercice : Validation de contenus multilingues par round-trip

Duree estimee : 20-25 minutes

Objectif

Créer une fonction de validation qui genere un contenu audio dans une langue, le retranscrit via STT, puis compare le texte original avec la transcription pour mesurer la fidelite du pipeline multilingue.

Contexte

Dans un contexte de production de contenus educatifs multilingues, il est essentiel de verifier que le pipeline TTS + traduction ne deforme pas le contenu. Le round-trip (texte -> TTS -> STT -> texte) est une méthode automatisee de validation.

Instructions

  1. Choisir un texte pedagogique court (2-3 phrases)
  2. Le traduire en anglais via LLM
  3. Generer l’audio TTS pour les deux versions
  4. Retranscrire chaque audio via Whisper
  5. Comparer original vs retranscrit avec SequenceMatcher

Indices : - # Étape 1 : Définir le texte source et le traduire via client.chat.completions.create() - # Étape 2 : Utiliser client.audio.speech.create() pour generer l’audio dans chaque langue - # Étape 3 : Sauvegarder les fichiers temporairement puis appeler client.audio.transcriptions.create() - # Indice : Utiliser from difflib import SequenceMatcher pour calculer la similarite - # Indice : Un score > 90% indique une bonne fidelite du pipeline

# TODO: Implementer la fonction de validation multilingue par round-trip
def validate_multilingual_content(source_text: str, source_lang: str = "fr",
                                   target_lang: str = "en") -> dict:
    """
    Valide la fidelite du pipeline multilingue par round-trip TTS->STT.
    
    Args:
        source_text: Texte pedagogique source
        source_lang: Langue source (ex: "fr")
        target_lang: Langue cible (ex: "en")
    
    Returns:
        Dict avec similarite_source, similarite_target, verdict
    """
    # Etape 1 : Traduire le texte source vers la langue cible
    # Indice: Utiliser client.chat.completions.create() avec un prompt de traduction
    translated_text = None  # TODO etudiant : traduire source_text
    
    # Etape 2 : Generer l'audio TTS pour les deux langues
    # Indice: client.audio.speech.create(model="tts-1", voice="nova", input=text)
    audio_source = None  # TODO etudiant : generer audio source
    audio_target = None  # TODO etudiant : generer audio target
    
    # Etape 3 : Retranscrire via Whisper
    # Indice: Sauvegarder temporairement, puis client.audio.transcriptions.create()
    transcribed_source = None  # TODO etudiant
    transcribed_target = None  # TODO etudiant
    
    # Etape 4 : Calculer la similarite
    # Indice: SequenceMatcher(None, original.lower(), transcribed.lower()).ratio()
    similarity_source = 0.0  # TODO etudiant
    similarity_target = 0.0  # TODO etudiant
    
    return {
        "similarity_source": similarity_source,
        "similarity_target": similarity_target,
        "verdict": "Exercice a completer"
    }

# Test avec un texte pedagogique
test_text = "Le deep learning est une technique d'apprentissage automatique inspiree du cerveau humain."
# result = validate_multilingual_content(test_text, "fr", "en")
# print(f"Similarite FR: {result['similarity_source']*100:.1f}%")
# print(f"Similarite EN: {result['similarity_target']*100:.1f}%")
print("Exercice a completer")
Exercice a completer

Interpretation : Verification qualite par round-trip

Aspect Valeur Signification
Similarite texte > 95% Fidelite excellente du pipeline
Erreurs typiques Accentuation, majuscules Whisper standardise l’orthographe
Verdict EXCELLENT La narration est fidele au contenu

Points cles : 1. Le round-trip TTS->STT permet de valider la qualite de la narration 2. Une similarite > 90% indique une narration fidele 3. Les différences mineures (majuscules, accents) n’impactent pas la comprehension

Note technique : Cette technique est utile pour valider des contenus dans des langues que vous ne parlez pas couramment.


Section 6 : Verification qualite par round-trip STT

Pour valider que la narration est fidele au texte source, nous effectuons un round-trip :

Texte source -> TTS -> Audio -> STT -> Texte transcrit -> Comparaison

La similarite entre le texte source et le texte retranscrit mesure la fidelite du pipeline.

Le mode interactif permet de tester la pipeline avec un sujet personnalise. Si notebook_mode n’est pas "interactive", cette cellule est ignoree automatiquement.

# Mode interactif - Creer votre propre contenu educatif
if notebook_mode == "interactive" and not skip_widgets:
    print("MODE INTERACTIF - CONTENU EDUCATIF PERSONNALISE")
    print("=" * 50)
    print("\nEntrez un paragraphe de cours a transformer en narration audio :")
    print("(Laissez vide pour passer)")

    try:
        user_course = input("\nVotre texte de cours : ")

        if user_course.strip():
            # Generer script de narration
            script_resp = client.chat.completions.create(
                model=llm_model,
                messages=[{"role": "user", "content": f"Transforme en narration orale educative :\n\n{user_course}"}],
                temperature=0.7
            )
            user_script = script_resp.choices[0].message.content
            print(f"\nScript genere :\n{user_script}")

            # Narrer
            tts_resp = client.audio.speech.create(
                model=tts_model,
                voice=narrator_voice,
                input=user_script,
                response_format="mp3"
            )
            print(f"\nNarration generee ({len(tts_resp.content)/1024:.1f} KB) :")
            display_audio_bundle(tts_resp.content)

            if save_audio_files:
                ts = datetime.now().strftime('%Y%m%d_%H%M%S')
                filepath = OUTPUT_DIR / f"custom_course_{ts}.mp3"
                with open(filepath, 'wb') as f:
                    f.write(tts_resp.content)
                print(f"Sauvegarde : {filepath.name}")
        else:
            print("Mode interactif ignore")

    except (KeyboardInterrupt, EOFError):
        print("Mode interactif interrompu")
    except Exception as e:
        error_type = type(e).__name__
        if "StdinNotImplemented" in error_type or "input" in str(e).lower():
            print("Mode interactif non disponible (execution automatisee)")
        else:
            print(f"Erreur : {error_type} - {str(e)[:100]}")
else:
    print("Mode batch - Interface interactive desactivee")
Mode batch - Interface interactive desactivee

Le module de statistiques consolide les metriques collectees durant la session : nombre de fichiers generes, modèles utilises, durees de traitement et couts API estimés.

# Statistiques de session et recapitulatif
print("STATISTIQUES DE SESSION")
print("=" * 50)

print(f"Date : {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"Mode : {notebook_mode}")
print(f"Modele TTS : {tts_model} | Modele LLM : {llm_model}")
print(f"Voix narrateur : {narrator_voice} | Voix secondaire : {secondary_voice}")

if audio_segments:
    total_segments = len(audio_segments)
    total_size_kb = sum(s['size_kb'] for s in audio_segments)
    print(f"Segments multi-voix generes : {total_segments}")
    print(f"Taille totale segments : {total_size_kb:.1f} KB")

if multilingual_results:
    print(f"Langues generees : {', '.join(multilingual_results.keys())}")

if save_audio_files:
    saved_files = list(OUTPUT_DIR.glob('*'))
    print(f"Fichiers sauvegardes : {len(saved_files)} dans {OUTPUT_DIR.relative_to(GENAI_ROOT)}")

print(f"\nPROCHAINES ETAPES")
print(f"1. Creer un pipeline de transcription (04-2-Transcription-Pipeline)")
print(f"2. Explorer la composition musicale (04-3-Music-Composition-Workflow)")
print(f"3. Synchroniser audio et video (04-4-Audio-Video-Sync)")

print(f"\nNotebook termine - {datetime.now().strftime('%H:%M:%S')}")
STATISTIQUES DE SESSION
==================================================
Date : 2026-08-16 01:50:28
Mode : interactive
Modele TTS : tts-1 | Modele LLM : gpt-4o-mini
Voix narrateur : nova | Voix secondaire : onyx
Segments multi-voix generes : 5
Taille totale segments : 1364.2 KB
Langues generees : fr, en
Fichiers sauvegardes : 3 dans outputs\audio\educational

PROCHAINES ETAPES
1. Creer un pipeline de transcription (04-2-Transcription-Pipeline)
2. Explorer la composition musicale (04-3-Music-Composition-Workflow)
3. Synchroniser audio et video (04-4-Audio-Video-Sync)

Notebook termine - 01:50:28

Synthese des apprentissages

Ce notebook a presente un pipeline complet de creation de contenu audio educatif utilisant les technologies de l’IA. Voici les points cles a retenir :

Technologies exploitees

Technologie Rôle Avantages pedagogiques
GPT-4o-mini Generation de scripts narres Adaptation ecrit→oral, structure multi-voix, creativity controlee
OpenAI TTS (tts-1) Synthese vocale Voix naturelles, 50+ langues, vitesse ajustable
pydub + ffmpeg Assemblage audio Silences, normalisation, concatenation fluide
Whisper (STT) Validation qualite Round-trip pour verification fidelite

Bonnes pratiques identifiees

  1. Multi-voix pour l’engagement : Alterner narrateur et expert (ratio 2:1) maintient l’attention
  2. Vitesse reduite pour accessibilite : 0.85x recommande pour publics non-experts
  3. Marqueurs structurels : [NARRATEUR], [EXPERT], [PAUSE] permettent un parsing automatique
  4. Silences variables : 800ms intra-rôle, 1500ms inter-rôle pour transitions naturelles
  5. Validation round-trip : TTS→STT pour verifier la fidelite (>90% = excellent)

Metriques de production

Indicateur Valeur typique Commentaire
Duree generation script runtime machine-dep : ~8s Rapide, permet itérations
Duree synthese TTS runtime machine-dep : ~30s pour 9 segments Adequat pour production batch
Taille fichier final ~1.8 MB pour 90s Compromis qualite/taille acceptable
Similarite round-trip >95% Fidelite excellente du pipeline

Limitations et extensions

Limitations actuelles : - Nombre de voix limite (6 voix OpenAI) - Pas de synchronisation video (traité dans notebook 04-4) - Pas de musique de fond (traité dans notebook 04-3)

Extensions possibles : - Ajouter voix dynamiques (rythme, emotion) avec modèles avancés - Generer sous-titres synchronises automatiquement - Créer versions adaptees par niveau (debutant, intermediaire, expert) - Integrer feedback apprenant (re-generation adaptee)

Applications reelles

Ce pipeline s’applique directement a : - MOOCs et formations en ligne : Modules audio accessibles offline - Accessibility : Contenu pour publics MALV (malvoyants, troubles cognitifs) - Podcasts educatifs : Generation automatique a partir de textes - Corporate training : Formation multilingue pour entreprises internationales - Audiobooks pedagogiques : Synthese de manuels et supports de cours



Exercice : Cours Audio Multilingue

Duree estimee : 30-35 minutes

Objectif

Créer un module de cours audio complet en 2 langues (FR et EN) avec narration multi-voix et accessibilite.

Instructions

  1. Choisir un sujet educatif court (100-150 mots)
  2. Generer un script de narration adapte a l’oral pour chaque langue
  3. Créer une narration multi-voix (narrateur + expert) dans les 2 langues
  4. Appliquer les paramètres d’accessibilite (vitesse reduite)
  5. Assembler les modules en cours audio complet

Indices : - Utilisez la fonction parse_narration_script() pour structurer les voix - Pour la traduction, utilisez GPT avec un prompt de traduction pedagogique - Pour l’accessibilite, reduisez la vitesse a 0.85x - Utilisez pydub pour assembler les segments avec des silences

# TODO: Definir votre sujet de cours
course_topic = """
[L'IA pour les debutants - 100-150 mots]
TODO: Ecrire votre texte ici en francais
"""

# TODO: Generer le script de narration FR
def generate_narration_script(source_text: str, language: str = "fr") -> str:
    """
    Genere un script de narration pedagogique.
    
    Args:
        source_text: Texte source du cours
        language: Langue cible ("fr" ou "en")
    
    Returns:
        Script avec marqueurs [NARRATEUR], [EXPERT], [PAUSE]
    """
    # Indice: Appeler GPT pour transformer le texte en script de narration
    # Prompt: "Transforme ce texte en script pedagogique oral avec [NARRATEUR] et [EXPERT]"
    pass

# TODO: Creer une fonction de narration multi-voix multilingue
def create_multilingual_multivoice_narration(script_fr: str, script_en: str) -> dict:
    """
    Genere la narration multi-voix en 2 langues.
    
    Args:
        script_fr: Script de narration FR
        script_en: Script de narration EN
    
    Returns:
        Dict avec: audio_fr, audio_en, segments, duree
    """
    # Indice: Parser les scripts (utiliser parse_narration_script du notebook)
    # Indice: Generer l'audio pour chaque segment avec la voix appropriee
    # Indice: Assembler les segments par langue
    # Indice: Appliquer la vitesse 0.85x pour accessibilite
    pass

# TODO: Creer le cours complet
# course_fr = generate_narration_script(course_topic, "fr")
# course_en = generate_narration_script(course_topic, "en")
# narration = create_multilingual_multivoice_narration(course_fr, course_en)

Critères de succès

Extension (optionnel)

Retour au sommet