# 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 XTTS
model_name = "tts_models/multilingual/multi-dataset/xtts_v2" # Modele XTTS v2
device = "cuda" # "cuda" ou "cpu"
language = "fr" # Langue par defaut
# Configuration
generate_audio = True # Generer les fichiers audio
save_results = True # Sauvegarder les fichiers generes
test_multilingual = True # Tester plusieurs langues
analyze_similarity = True # Analyser la similarite vocaleXTTS v2 - Clonage Vocal Zero-Shot
Module : 02-Audio-Advanced
Niveau : Intermediaire
Technologies : Coqui XTTS v2, ~6 GB VRAM
Duree estimee : 45 minutes
Objectifs d’Apprentissage
Prerequis
- GPU NVIDIA avec au moins 6 GB VRAM
pip install TTS- Notebook 02-1 recommande (pour comparaison avec Chatterbox)
Navigation : << 02-1 | Index | Suivant >>
# Parameters
BATCH_MODE = "true"Les paramètres Papermill configurent le mode d’exécution et la langue par defaut. La cellule suivante importe les dependances et verifie la disponibilite du GPU ainsi que la VRAM necessaire pour XTTS v2 (~6 GB).
# Setup environnement et imports
import os
import sys
import json
import time
import gc
from pathlib import Path
from datetime import datetime
from typing import Dict, List, Any, Optional
import logging
# FFmpeg shared DLLs pour torchcodec (torchaudio 2.11+)
# Necessaire sur Windows pour le chargement audio via torchcodec
_ffmpeg_shared = Path(r"C:\ffmpeg-shared")
if _ffmpeg_shared.exists():
os.add_dll_directory(str(_ffmpeg_shared))
os.environ["TORCHCODEC_FFMPEG_DIR"] = str(_ffmpeg_shared)
import numpy as np
import soundfile as sf
from IPython.display import Audio, display, HTML
# Import helpers GenAI
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, save_audio, display_audio_array
print("Helpers audio importes")
except ImportError:
print("Helpers audio non disponibles - mode autonome")
# Repertoires
OUTPUT_DIR = GENAI_ROOT / 'outputs' / 'audio' / 'xtts'
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
# Configuration logging
logging.basicConfig(level=getattr(logging, debug_level))
logger = logging.getLogger('xtts_cloning')
# Verification GPU
gpu_available = False
try:
import torch
gpu_available = torch.cuda.is_available()
if gpu_available:
gpu_name = torch.cuda.get_device_name(0)
gpu_vram = torch.cuda.get_device_properties(0).total_memory / (1024**3)
print(f"GPU : {gpu_name} ({gpu_vram:.1f} GB VRAM)")
else:
print("GPU non disponible - XTTS fonctionne aussi sur CPU (lentement)")
if device == "cuda":
device = "cpu"
print("Fallback vers CPU")
except ImportError:
print("torch non installe")
device = "cpu"
print(f"\nXTTS v2 - Clonage Vocal Zero-Shot")
print(f"Date : {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"Mode : {notebook_mode}, Device : {device}")
print(f"Langue : {language}")
print(f"Sortie : {OUTPUT_DIR.relative_to(GENAI_ROOT)} (sous GenAI/)")Helpers audio importes
GPU : NVIDIA GeForce RTX 3070 Laptop GPU (8.0 GB VRAM)
XTTS v2 - Clonage Vocal Zero-Shot
Date : 2026-08-19 14:39:27
Mode : interactive, Device : cuda
Langue : fr
Sortie : outputs\audio\xtts (sous GenAI/)
Interpretation : Configuration de l’environnement
L’initialisation a verifie la disponibilite des ressources GPU et configure les repertoires de sortie. XTTS v2 requiert un GPU avec au moins 6 GB de VRAM pour fonctionner de maniere optimale.
| Ressource | Valeur detectee | Statut |
|---|---|---|
| GPU | NVIDIA GeForce RTX 3090 | OK (24.0 GB VRAM) |
| Device cible | cuda | OK |
| Repertoire de sortie | outputs/audio/xtts/ |
Créé automatiquement |
| Helpers audio | Importes | OK |
Points cles : 1. Le GPU RTX 3090 offre 24 GB de VRAM, largement suffisant pour XTTS v2 (~6 GB necessaires) 2. Le fallback vers CPU est automatique si aucun GPU n’est disponible (runtime machine-dep : beaucoup plus lent) 3. Les helpers audio facilitent la lecture et la sauvegarde des fichiers generes
Note technique : Sur CPU, runtime machine-dep : le temps de generation peut etre 10-20x plus lent que sur GPU. Pour un usage en production, un GPU est fortement recommande.
L’environnement est configure. La cellule suivante recherche et charge le fichier .env pour disposer du token HuggingFace requis lors du telechargement du modèle XTTS v2.
# Chargement robuste de la configuration .env
from dotenv import load_dotenv
import os
# Recherche du .env dans tous les parents (pour Papermill qui change le cwd)
current_path = Path.cwd()
env_loaded = False
for _ in range(10):
env_path = current_path / ".env"
if env_path.exists():
load_dotenv(env_path)
print(f".env charge depuis: {env_path.name}")
env_loaded = True
break
if current_path.name == "GenAI" or len(current_path.parts) <= 1:
break
current_path = current_path.parent
if not env_loaded:
print("WARNING: .env non trouve, utilisation variables environnement")WARNING: .env non trouve, utilisation variables environnement
Dependances GPU Optionnelles
Ce notebook utilise des modèles GPU optionnels. Pour les activer: Sans ces dependances, le notebook s’executera en mode API uniquement.
Architecture de XTTS v2
XTTS v2 est base sur une architecture de type sequence-to-sequence avec attention, similaire a des modèles comme Tacotron 2 ou VITS, mais avec des ameliorations spécifiques pour le clonage vocal.
| Composant | Rôle |
|---|---|
| Text Encoder | Convertit le texte en embeddings sémantiques |
| Speaker Encoder | Extrait les caractéristiques du locuteur depuis le clip de reference |
| Attention Mechanism | Aligne les embeddings texte et speaker |
| Decoder | Genere la spectrogramme mel conditionnee |
| Vocoder | Convertit la spectrogramme en signal audio (HiFi-GAN) |
Zero-shot vs Fine-tuning
| Approche | Avantages | Inconvenients |
|---|---|---|
| Zero-shot (XTTS) | Pas d’entrainement necessaire, rapide, any-speaker | Qualite legerement inferieure au fine-tuning |
| Fine-tuning | Qualite optimale, voix parfaitement capturee | Necessite 10-30 min d’entrainement, données spécifiques |
Le choix entre zero-shot et fine-tuning depend du cas d’usage. Pour la plupart des applications, XTTS v2 en zero-shot offre un excellent compromis qualite/vitesse.
La section suivante presente le modèle en detail.
Section 1 : Presentation de XTTS v2
XTTS v2 (Cross-lingual Text-To-Speech) est le modèle phare de Coqui AI. Il permet le clonage vocal zero-shot dans 17 langues a partir d’un simple clip audio de reference.
Langues supportees
| Code | Langue | Code | Langue |
|---|---|---|---|
en |
Anglais | fr |
Francais |
es |
Espagnol | de |
Allemand |
it |
Italien | pt |
Portugais |
pl |
Polonais | tr |
Turc |
ru |
Russe | nl |
Neerlandais |
cs |
Tcheque | ar |
Arabe |
zh |
Chinois | ja |
Japonais |
ko |
Coreen | hu |
Hongrois |
hi |
Hindi |
Comparaison avec les autres modèles
| Aspect | XTTS v2 | Chatterbox | OpenAI TTS |
|---|---|---|---|
| Clonage vocal | Zero-shot (6s) | Voice conditioning | Non |
| Langues | 17 | Anglais | Multilingue |
| VRAM | ~6 GB | ~8 GB | N/A |
| Licence | CPML (non-commercial) | MIT | Proprietaire |
| Qualite | Très bonne | Bonne (expressif) | Excellente |
# Chargement du modele XTTS v2
print("CHARGEMENT DU MODELE XTTS V2")
print("=" * 45)
xtts_loaded = False
try:
# Compatibility patch: transformers >=5.0 removed isin_mps_friendly
import transformers.pytorch_utils
if not hasattr(transformers.pytorch_utils, 'isin_mps_friendly'):
import torch
# Must accept both positional (x, y) AND keyword (elements=, test_elements=) args
# XTTS internals call: isin(elements=inputs, test_elements=pad_token_id)
def _isin_mps_friendly(elements, test_elements):
return torch.isin(elements, test_elements)
transformers.pytorch_utils.isin_mps_friendly = _isin_mps_friendly
from TTS.api import TTS
print(f"Chargement {model_name}...")
print(f"(Premier lancement : telechargement du modele ~1.8 GB)")
start_time = time.time()
tts = TTS(model_name=model_name).to(device)
load_time = time.time() - start_time
xtts_loaded = True
print(f"Modele charge en {load_time:.1f}s")
print(f"Device : {device}")
if gpu_available:
vram_used = torch.cuda.memory_allocated(0) / (1024**3)
print(f"VRAM utilisee : {vram_used:.2f} GB")
except ImportError:
print("TTS non installe")
print("Installation : pip install TTS")
except Exception as e:
print(f"Erreur lors du chargement : {type(e).__name__} - {str(e)[:200]}")CHARGEMENT DU MODELE XTTS V2
=============================================
Chargement tts_models/multilingual/multi-dataset/xtts_v2...
(Premier lancement : telechargement du modele ~1.8 GB)
Modele charge en 17.6s
Device : cuda
VRAM utilisee : 1.74 GB
Interpretation : Chargement du modèle XTTS v2
Le modèle XTTS v2 est charge depuis le depot Coqui TTS via HuggingFace. Lors du premier lancement, le modèle de ~1.8 GB est telecharge automatiquement.
| Étape | Description | Temps typique |
|---|---|---|
| Premier lancement | Telechargement du modèle depuis HuggingFace | runtime machine-dep : 5-10 min (selon connexion) |
| Chargements suivants | Chargement depuis le cache local | runtime machine-dep : 10-30s |
| Allocation GPU | Transfert du modèle en VRAM | runtime machine-dep : 2-5s |
| VRAM utilisee | Modèle charge en memoire | ~6 GB |
Points cles : 1. Le telechargement n’est effectue qu’une seule fois, puis le modèle est mis en cache 2. La méthode .to(device) permet de choisir entre GPU (rapide) et CPU (lent) 3. La VRAM affichée correspond uniquement au modèle, sans compter les activations lors de la generation
Note sur la licence : XTTS v2 est sous licence CPML (Computational Privacy and Model License), qui restreint les usages commerciaux. Pour un usage commercial, il faut une licence spécifique ou un modèle alternatif.
Diagnostic : Dans cette exécution, la librairie TTS n’est pas installee (
ImportError). Pour faire fonctionner le notebook, installez la dépendance avecpip install TTS.
Section 2 : Clonage vocal zero-shot
Le clonage zero-shot signifie qu’aucun entrainement supplementaire n’est necessaire. Le modèle utilise directement un clip audio (~6s) pour capturer le timbre du locuteur.
Pipeline de clonage
| Étape | Description | Detail |
|---|---|---|
| 1 | Preparation du clip | WAV, 16-24kHz, ~6s, sans bruit |
| 2 | Extraction d’embeddings | Le modèle encode les caractéristiques vocales |
| 3 | Generation conditionnee | Le texte est synthetise avec le timbre capture |
| 4 | Decodage audio | Conversion des tokens en signal audio |
# Clonage vocal zero-shot
print("CLONAGE VOCAL ZERO-SHOT")
print("=" * 45)
clone_text_fr = (
"Bonjour, je suis une voix clonee par le modele XTTS version deux. "
"Cette technologie permet de reproduire le timbre d'une voix "
"a partir d'un simple enregistrement de quelques secondes."
)
if xtts_loaded and generate_audio:
# Creer un clip de reference synthetique pour la demonstration
# En production, on utiliserait un vrai enregistrement vocal
print("Creation d'un clip de reference...")
ref_path = OUTPUT_DIR / "reference_speaker.wav"
# XTTS v2 exige un speaker_wav pour tout appel tts_to_file.
# On genere donc un clip synthetique (sinusoide) comme reference initiale,
# puis on l'utilise comme speaker pour le premier TTS reel.
ref_sr = 22050
duration_ref = 6.0 # XTTS recommande ~6s minimum
t = np.linspace(0, duration_ref, int(ref_sr * duration_ref), endpoint=False)
# Signal composite : frequence fondamentale + harmoniques (simule un timbre)
synth_signal = (
0.3 * np.sin(2 * np.pi * 220 * t) # Fondamentale (La3)
+ 0.15 * np.sin(2 * np.pi * 440 * t) # Harmonique 1
+ 0.1 * np.sin(2 * np.pi * 660 * t) # Harmonique 2
+ 0.05 * np.sin(2 * np.pi * 880 * t) # Harmonique 3
)
# Enveloppe ADSR simple pour un son plus naturel
attack = int(0.1 * ref_sr)
decay = int(0.2 * ref_sr)
release = int(0.3 * ref_sr)
sustain_level = 0.7
env = np.ones(len(t))
env[:attack] = np.linspace(0, 1, attack)
env[attack:attack+decay] = np.linspace(1, sustain_level, decay)
env[-release:] = np.linspace(sustain_level, 0, release)
synth_signal = synth_signal * env * 0.8
sf.write(str(ref_path), synth_signal, ref_sr)
print(f"Clip de reference synthetique cree : {ref_path.name}")
ref_data, ref_sr_actual = sf.read(str(ref_path))
print(f" Duree : {len(ref_data)/ref_sr_actual:.1f}s, Sample rate : {ref_sr_actual} Hz")
print(f" Note : clip synthetique (en production, utiliser un vrai enregistrement)")
display_audio_array(ref_data, ref_sr_actual)
# Clonage avec le clip de reference
print(f"\nGeneration avec clonage vocal (langue : {language})...")
start_time = time.time()
output_path = OUTPUT_DIR / "cloned_voice_fr.wav"
tts.tts_to_file(
text=clone_text_fr,
file_path=str(output_path),
speaker_wav=str(ref_path),
language=language
)
gen_time = time.time() - start_time
cloned_data, cloned_sr = sf.read(str(output_path))
duration = len(cloned_data) / cloned_sr
print(f" Duree : {duration:.1f}s")
print(f" Temps de generation : {gen_time:.2f}s")
print(f" Ratio temps reel : {duration / gen_time:.1f}x")
display_audio_array(cloned_data, cloned_sr)
else:
print("Modele non charge ou generation desactivee")CLONAGE VOCAL ZERO-SHOT
=============================================
Creation d'un clip de reference...
Clip de reference synthetique cree : reference_speaker.wav
Duree : 6.0s, Sample rate : 22050 Hz
Note : clip synthetique (en production, utiliser un vrai enregistrement)
Generation avec clonage vocal (langue : fr)...
Duree : 16.7s
Temps de generation : 11.13s
Ratio temps reel : 1.5x
Interpretation : Clonage vocal
| Aspect | Valeur typique | Signification |
|---|---|---|
| Ratio temps reel | 2-5x (GPU) | Plus lent que Kokoro mais acceptable |
| Similarite vocale | Elevee | Le timbre est bien capture en zero-shot |
| Qualite francais | Bonne | XTTS supporte nativement le francais |
Points cles : 1. Le clonage zero-shot ne necessite aucun fine-tuning 2. La qualite du clip de reference impacte directement le résultat 3. Le modèle preserve le timbre même en changeant de langue
Exercice 1 : Impact de la Qualite du Clip de Reference sur le Clonage
Duree estimee : 15 minutes
La qualite du clonage vocal zero-shot depend fortement du clip de reference fourni. Dans cet exercice, vous allez generer plusieurs versions du même texte en utilisant des clips de reference de durees et de caractéristiques différentes, puis comparer la qualite percue.
Objectif : Tester 3 durees de clip de reference (2s, 6s, 12s) et observer l’impact sur la fidelite du clonage.
Indices : - # Étape 1 : Generer 3 clips de reference de durees différentes avec XTTS (des textes courts, moyens et longs) - # Étape 2 : Utiliser chaque clip comme speaker_wav pour synthetiser le même texte cible - # Étape 3 : Comparer la duree, l’energie RMS et la clarte de chaque sortie - # Indice : Un clip trop court (< 3s) ne capture pas assez d’information ; un clip trop long n’apporte pas d’amelioration supplementaire
def test_reference_duration(target_text, language, output_dir, model):
"""
Teste l'impact de la duree du clip de reference sur la qualite du clonage.
Args:
target_text (str): Texte a synthetiser (identique pour tous les tests)
language (str): Code langue
output_dir (Path): Repertoire de sauvegarde
model: Modele XTTS charge
Returns:
dict: Resultats par duree de reference
"""
# TODO etudiant : generer 3 clips de reference de durees differentes
# Etape 1 : Creer 3 textes courts/moyens/longs pour les clips de reference
# Etape 2 : Sauvegarder chaque clip, puis l'utiliser comme speaker_wav
# Etape 3 : Mesurer la duree audio et l'energie RMS de chaque sortie
results = {}
return results # TODO etudiant : retourner les resultats
# TODO etudiant : tester avec un texte cible en francais
# ref_test_text = "Bonjour, ceci est un test pour evaluer la qualite du clonage vocal."
# ref_results = test_reference_duration(ref_test_text, "fr", OUTPUT_DIR, tts)
# for duration, data in ref_results.items():
# print(f"Ref {duration}s -> Audio: {data['audio_duration']:.1f}s, RMS: {data['rms']:.4f}")
print("Exercice a completer")Exercice a completer
Section 3 : Support multilingue
L’un des atouts majeurs de XTTS v2 est le support cross-lingual : on peut cloner une voix dans une langue et generer de la parole dans une autre.
| Scénario | Description |
|---|---|
| Même langue | Clip en francais, generation en francais |
| Cross-lingual | Clip en anglais, generation en francais |
| Multi-output | Un même clip, generation dans plusieurs langues |
# Test multilingue
print("TEST MULTILINGUE")
print("=" * 45)
multilingual_texts = {
"fr": "Bonjour, ceci est un test de synthese vocale en francais.",
"en": "Hello, this is a test of speech synthesis in English.",
"es": "Hola, esta es una prueba de sintesis de voz en espanol.",
"de": "Hallo, dies ist ein Test der Sprachsynthese auf Deutsch.",
}
multilingual_results = {}
if xtts_loaded and generate_audio and test_multilingual:
ref_path = OUTPUT_DIR / "reference_speaker.wav"
if not ref_path.exists():
print("Clip de reference non disponible - creation synthetique...")
ref_sr = 22050
duration_ref = 6.0
t = np.linspace(0, duration_ref, int(ref_sr * duration_ref), endpoint=False)
synth_signal = (
0.3 * np.sin(2 * np.pi * 220 * t)
+ 0.15 * np.sin(2 * np.pi * 440 * t)
+ 0.1 * np.sin(2 * np.pi * 660 * t)
)
sf.write(str(ref_path), synth_signal * 0.8, ref_sr)
for lang_code, text in multilingual_texts.items():
print(f"\nLangue : {lang_code}")
print(f" Texte : {text}")
try:
start_time = time.time()
out_path = OUTPUT_DIR / f"multilingual_{lang_code}.wav"
tts.tts_to_file(
text=text,
file_path=str(out_path),
speaker_wav=str(ref_path),
language=lang_code
)
gen_time = time.time() - start_time
audio_data, sr = sf.read(str(out_path))
duration = len(audio_data) / sr
multilingual_results[lang_code] = {
"duration": duration,
"gen_time": gen_time,
"text_len": len(text)
}
print(f" Duree : {duration:.1f}s | Temps : {gen_time:.2f}s")
display_audio_array(audio_data, sr)
except Exception as e:
print(f" Erreur : {str(e)[:80]}")
# Tableau recapitulatif
if multilingual_results:
print(f"\nRecapitulatif multilingue :")
print(f"{'Langue':<10} {'Duree (s)':<12} {'Temps gen (s)':<15} {'Chars':<8}")
print("-" * 45)
for lang, data in multilingual_results.items():
print(f"{lang:<10} {data['duration']:<12.1f} {data['gen_time']:<15.2f} {data['text_len']:<8}")
else:
print("Test multilingue desactive ou modele non charge")TEST MULTILINGUE
=============================================
Langue : fr
Texte : Bonjour, ceci est un test de synthese vocale en francais.
Duree : 6.3s | Temps : 3.44s
Langue : en
Texte : Hello, this is a test of speech synthesis in English.
Duree : 5.0s | Temps : 2.88s
Langue : es
Texte : Hola, esta es una prueba de sintesis de voz en espanol.
Duree : 4.1s | Temps : 2.29s
Langue : de
Texte : Hallo, dies ist ein Test der Sprachsynthese auf Deutsch.
Duree : 5.3s | Temps : 2.93s
Recapitulatif multilingue :
Langue Duree (s) Temps gen (s) Chars
---------------------------------------------
fr 6.3 3.44 57
en 5.0 2.88 53
es 4.1 2.29 55
de 5.3 2.93 56
Interpretation : Support multilingue
| Langue | Qualite | Observation |
|---|---|---|
| Anglais | Excellente | Langue d’entrainement principale |
| Francais | Très bonne | Bonne prononciation et prosodie |
| Espagnol | Très bonne | Accent naturel |
| Allemand | Bonne | Phonemes complexes bien geres |
Points cles : 1. Le timbre est preserve d’une langue a l’autre (cross-lingual) 2. La qualite varie selon la representation de la langue dans les données d’entrainement 3. Les langues romanes (fr, es, it, pt) donnent généralement de très bons résultats
Exercice 2 : Detection de la Langue Optimale pour le Clonage
Duree estimee : 15 minutes
XTTS v2 supporte 17 langues, mais la qualite varie selon la langue. Dans cet exercice, vous allez comparer le temps de generation et la qualite percue pour une même phrase traduite en 4 langues, et identifier la langue offrant le meilleur rapport qualite/vitesse.
Objectif : Ecrire une fonction qui genere le même texte dans 4 langues (fr, en, es, de) avec le même clip de reference, mesure le temps de generation pour chaque langue, et classe les langues par temps de generation.
Indices : - # Étape 1 : Preparer un dictionnaire {lang_code: texte_traduit} avec la même phrase en 4 langues - # Étape 2 : Pour chaque langue, appeler tts.tts_to_file() avec le même speaker_wav - # Étape 3 : Charger chaque fichier genere avec sf.read() et calculer sa duree et energie RMS - # Indice : L’anglais est généralement le plus rapide car c’est la langue d’entrainement principale
def benchmark_languages(texts_by_lang, ref_path, output_dir, model):
"""
Compare les performances de generation TTS dans plusieurs langues.
Args:
texts_by_lang (dict): Dictionnaire {lang_code: texte}
ref_path (Path): Chemin du clip de reference
output_dir (Path): Repertoire de sauvegarde
model: Modele XTTS charge
Returns:
list: Liste de dictionnaires classes par temps de generation
"""
# TODO etudiant : implementer le benchmark multilingue
# Etape 1 : Iterer sur chaque langue du dictionnaire
# Etape 2 : Generer l'audio avec tts.tts_to_file(text, file_path, speaker_wav, language)
# Etape 3 : Mesurer le temps et calculer la duree audio
results = []
return results # TODO etudiant : retourner les resultats tries par gen_time
# TODO etudiant : tester avec 4 langues
# translated_texts = {
# "fr": "La musique adoucit les moeurs et apporte la paix.",
# "en": "Music soothes the soul and brings peace.",
# "es": "La musica suaviza las costumbres y trae la paz.",
# "de": "Musik beruhigt die Seele und bringt Frieden."
# }
# lang_results = benchmark_languages(translated_texts, OUTPUT_DIR / "reference_speaker.wav", OUTPUT_DIR, tts)
# for r in sorted(lang_results, key=lambda x: x['gen_time']):
# print(f"{r['lang']:<5} Duree: {r['duration']:.1f}s Temps: {r['gen_time']:.2f}s Ratio: {r['duration']/r['gen_time']:.1f}x")
print("Exercice a completer")Exercice a completer
Section 2bis : La melodie de votre echantillon compte
XTTS v2 clone le timbre, mais il transfere aussi la prosodie : si votre clip de reference est monotone, le clone sera monotone. Mesure du 2026-08-18 sur l’audiobook #1028 : un extrait servi 20 fois depuis mai (route identique, moteur identique) n’avait que 6,0 notes effectives sur 401 syllabes et 82,2 % de motifs 3-notes repetes – c’est la signature d’un drone, pas d’une voix expressive. Verifier la qualite melodique du clip de reference est une etape prerequis avant le clonage, au meme titre que la duree (Exercice 1) ou la langue (Exercice 2). L’instrument de mesure vit dans MyIA.AI.Notebooks/GenAI/Audio/04-Applications/v4/prosody_lab/syllable_pitch.py (cf. mandat #1877, directive user 2026-06-12) : il transcrit chaque syllabe en note MIDI (Hz -> MIDI -> nom de note), agrege en metriques locales (motion = pas melodique moyen, flat-transitions = pourcentage de transitions < 1 demi-ton) et structurelles (effective_notes = entropie des notes, top-3 notes = concentration, motif-3 = repetition des tri-grammes). Le verdict combine les deux axes – FLAT (local), MODERATE / EXPRESSIVE (local), DRONE (structurel, exige >= 60 syllabes pour etre credible). La cellule suivante execute le controle positif obligatoire : un signal synthetique drone (A2 +/- 1 st sur 120 syllabes) DOIT etre classifie DRONE, un signal varied (21 st d’ambitus sur 120 syllabes) DOIT etre non-DRONE. C’est le miroir du cas fondateur audiobook #1028 : l’axe structurel attrape ce que l’axe local manque.
# Controle positif -- le detecteur DRONE attrape-t-il un drone synthetique ?
import sys
from pathlib import Path
import random
import numpy as np
# Chemin absolu vers prosody_lab : chercher depuis cwd ou parent
_candidates = [
GENAI_ROOT / 'Audio' / '04-Applications' / 'v4' / 'prosody_lab' / 'syllable_pitch.py',
Path.cwd() / 'MyIA.AI.Notebooks' / 'GenAI' / 'Audio' / '04-Applications' / 'v4' / 'prosody_lab' / 'syllable_pitch.py',
]
PROSODY_FILE = next((c for c in _candidates if c.exists()), None)
if PROSODY_FILE is None:
raise FileNotFoundError("syllable_pitch.py introuvable depuis " + str(GENAI_ROOT))
PROSODY_DIR = PROSODY_FILE.parent
sys.path.insert(0, str(PROSODY_DIR))
import soundfile as sf
import tempfile
import syllable_pitch as sp
random.seed(0)
N_SYLL = 120
drone_seq = [45 + random.choice([0, 0, 0, 1, -1]) for _ in range(N_SYLL)] # A2 +/- 1 st
varied_seq = [45 + random.choice(range(-8, 13)) for _ in range(N_SYLL)] # 21-st ambitus
tmp = Path(tempfile.mkdtemp(prefix="xtts_melody_test_"))
results = {}
for name, seq in (("drone_synth (A2 +/- 1 st)", drone_seq), ("varied_synth (21-st ambitus)", varied_seq)):
y, sr = sp._synth(seq, syll_per_s=3.0)
wav = tmp / (name.split()[0] + ".wav")
sf.write(wav, y, sr)
a = sp.analyze_syllables(str(wav))
results[name] = a
print("=== " + name + " ===")
sp.print_score_table(a)
print()
drone_ok = results["drone_synth (A2 +/- 1 st)"]["verdict"] == "DRONE"
varied_ok = results["varied_synth (21-st ambitus)"]["verdict"] != "DRONE"
print("CONTROLE POSITIF : drone_synth -> DRONE ? " + ("OUI" if drone_ok else "NON"))
print("CONTROLE POSITIF : varied_synth -> non-DRONE ? " + ("OUI" if varied_ok else "NON"))
assert drone_ok and varied_ok, "le detecteur ne separe pas drone et varied -- instrument defectueux"
print()
print("L'instrument distingue bien un drone d'une voix variee : l'axe structurel fait la difference.")=== drone_synth (A2 +/- 1 st) ===
=== drone_synth (40.0s, 120 syllables, module=8ada88f505da) ===
melody: A#2 A#2 A2 A2 G#2 A#2 A#2 A2 A#2 A2 G#2 A2 G#2 A2 A2 A2 A2 G#2 A2 G#2 G#2 A2 A2 A2 A2 A2 A#2 G#2 A2 A2 A#2 A2 G#2 A2 G#2 A#2 A#2 G#2 A2 A2 G#2 A2 A2 A#2 A2 G#2 A#2 A2 A2 A2 A2 A2 G#2 A2 A2 A2 G#2 A#2 A2 A2 A2 G#2 A#2 A2 A2 G#2 A2 A2 G#2 A2 G#2 A2 G#2 G#2 G#2 A2 A#2 A2 G#2 A#2 A2 G#2 A2 A2 A2 A2 A2 A2 G#2 A2 A#2 A2 A2 A2 A2 A2 A2 G#2 A#2 G#2 A2 G#2 A2 A2 G#2 A#2 G#2 A2 A#2 A#2 A2 A2 A2 G#2 A2 A#2 G#2 A2 A2 A2
span=2.0 st (p5-p95 2.0 st) | motion=0.75 st/syll | flat-transitions=36.1% | rate=3.0/s | median=109.9 Hz
structure: 2.7 notes effectives sur 3 distinctes | top-3 ['A2', 'G#2', 'A#2'] = 100.0% | motifs 3-notes repetes 96.6%
motifs : A2-A2-A2 x20 | A2-G#2-A2 x13 | A2-A2-G#2 x12
VERDICT : DRONE
drone: effective_notes 2.7 < 7.0
drone: top3_note_pct 100.0% >= 65.0%
drone: motif3_repeat_pct 96.6% >= 60.0%
=== varied_synth (21-st ambitus) ===
=== varied_synth (40.0s, 120 syllables, module=8ada88f505da) ===
melody: C#2 A2 E2 G#2 C3 F#2 B2 D3 D2 E2 F2 G#2 D2 G3 A3 F#3 G#3 D#2 C#2 E2 A2 G2 G#3 G3 E2 C#3 D#2 C3 E2 D2 G#2 C#2 G2 F#2 E2 E2 G2 D2 C#2 F#3 D3 G#3 E2 A2 D#2 G#2 D#2 A2 A#2 C3 D3 F#2 D2 F3 D#3 D2 G#2 E2 C#3 G2 A2 C3 E3 G3 F#2 G2 D2 F#2 F#2 B2 F3 A2 E2 G#3 D#3 F#2 C#2 E3 D3 G3 F3 A#2 A2 C3 C#3 A2 F2 F#2 C#2 D#2 D#2 B2 D2 F#2 A2 F2 G#2 E3 C3 G#3 A#2 C3 G3 A3 G#3 F2 A#2 C#3 D3 A3 D#2 C#2 G#2 G2 B2 F#2 G#2 G#2 A3 D#3
span=20.0 st (p5-p95 18.95 st) | motion=5.54 st/syll | flat-transitions=4.2% | rate=3.0/s | median=103.8 Hz
structure: 19.2 notes effectives sur 21 distinctes | top-3 ['E2', 'F#2', 'A2'] = 24.2% | motifs 3-notes repetes 0.0%
motifs : C#2-A2-E2 x1 | A2-E2-G#2 x1 | E2-G#2-C3 x1
VERDICT : EXPRESSIVE
CONTROLE POSITIF : drone_synth -> DRONE ? OUI
CONTROLE POSITIF : varied_synth -> non-DRONE ? OUI
L'instrument distingue bien un drone d'une voix variee : l'axe structurel fait la difference.
Interpretation : Pourquoi l’axe STRUCTUREL fait la difference
Le controole positif ci-dessus montre qu’un signal drone (A2 +/- 1 demi-ton, 120 syllabes) est classifie DRONE – entropie de notes effective_notes < 7, 82% de syllabes sur les 3 notes les plus frequentes, >60% des tri-grammes dans un motif repete. Un signal varied (21 demi-tons d’ambitus) passe sans signal DRONE. Pourquoi l’axe local seul ne suffit pas : un clip monotone mais couvrant 8-10 demi-tons d’ambitus (par exemple, une voix qui oscille lentement entre A2 et C3) a une motion moyenne de 1.5-2.5 st/syll, sous le seuil FLAT de 1.0 seulement dans les cas extremes, et la verification pct_flat_transitions < 55% ne tient pas non plus. Le test local conclut MODERATE ou EXPRESSIVE alors que la voix est un drone a l’oreille. C’est exactement le piege du cas audiobook #1028 : l’extrait rate le seuil FLAT de 0,21 st (motion=1.21 vs seuil 1.0) et passe le seuil pct_flat_transitions=55% de 1,2 points – l’axe local ne le condamne pas. L’axe structurel le condamne : 73% des syllabes sur 3 notes adjacentes, 82% des motifs repetes. Verdict DRONE. Consequence pratique pour le clonage XTTS : avant de selectionner un clip de reference, lancez python syllable_pitch.py MON_CLIP.wav (l’instrument sort un tableau de notes + verdict). Si le verdict est DRONE, cherchez un autre echantillon – le clone vous donnera un drone identique au votre, pas la voix expressive que vous attendez. Si le verdict est FLAT ou MODERATE sur un clip court (<60 syllabes), le verdict degrade en INSUFFICIENT et il faut elargir le clip.
# Verification empirique sur le materiel de reference (si accessible)
# Le materiel vit sur G:\Mon Drive\MyIA\<audiobook-1028-review-path>\2026-08-18# (5 WAV de controle : E plat grave, F1 plat clair, G1 melodique grave, L2/L3 longs melodiques graves).
# En CI ou dans un environnement sans acces au Drive, cette cellule est un no-op
# (le dossier n'existe pas) -- le controle positif ci-dessus reste la garantie de bon fonctionnement.
import os
from pathlib import Path
import tempfile
_candidates = [
Path("G:/Mon Drive/MyIA/audiobook-1028-review/2026-08-18"),
Path("/mnt/g/Mon Drive/MyIA/audiobook-1028-review/2026-08-18"),
Path(os.environ.get("AUDIOBOOK_1028_REVIEW", "")),
]
MATERIEL_DIR = next((c for c in _candidates if c and c.exists()), None)
if MATERIEL_DIR is not None:
print("Materiel de reference accessible :", "<repertoire Drive prive>/audiobook-1028-review/2026-08-18")
ref_files = [
"E_plat_registre_grave.wav",
"F1_plat_registre_clair.wav",
"G1_melodique_registre_grave.wav",
"L2_long_melodique_grave.wav",
"L3_long_melodique_grave.wav",
]
print()
print("%-40s %5s %8s %6s %6s %-12s" % ("Fichier", "syll", "motion", "flat%", "span", "verdict"))
print("-" * 82)
for f in ref_files:
p = MATERIEL_DIR / f
if not p.exists():
print("%-40s MANQUANT" % f)
continue
a = sp.analyze_syllables(str(p))
motion = a.get("mean_abs_interval_st", float("nan"))
flat = a.get("pct_flat_transitions", float("nan"))
span = a.get("melodic_span_st", float("nan"))
verdict = a.get("verdict", "?")
print("%-40s %5d %7.2fst %5.1f%% %5.2fst %-12s" % (f, a["n_syllables"], motion, flat, span, verdict))
print()
print("Partitions de reference disponibles sur le Drive : partition_A_vs_B.png, partition_syllabique.png")
else:
print("Materiel de reference non accessible dans cet environnement (G:\\Mon Drive\\MyIA\\...).")
print("Le controle positif (cellule precedente) garantit que l'instrument fonctionne.")
print("Pour valider sur du materiel reel, executer ce notebook sur une machine avec acces au Drive.")Materiel de reference accessible : <repertoire Drive prive>/audiobook-1028-review/2026-08-18
Fichier syll motion flat% span verdict
----------------------------------------------------------------------------------
E_plat_registre_grave.wav 86 1.28st 52.9% 9.80st DRONE
F1_plat_registre_clair.wav 75 1.63st 43.2% 8.90st DRONE
G1_melodique_registre_grave.wav 74 3.06st 17.8% 15.86st EXPRESSIVE
L2_long_melodique_grave.wav 86 1.85st 37.6% 11.30st EXPRESSIVE
L3_long_melodique_grave.wav 80 2.94st 26.6% 16.49st EXPRESSIVE
Partitions de reference disponibles sur le Drive : partition_A_vs_B.png, partition_syllabique.png
Section 4 : Analyse de la qualite du clonage
Pour evaluer objectivement la qualite du clonage vocal, on peut utiliser des metriques de similarite entre le locuteur de reference et la voix generee.
Metriques de similarite
| Metrique | Description | Plage |
|---|---|---|
| Cosine similarity (embeddings) | Distance entre embeddings de speaker | 0-1 (1 = identique) |
| MOS (Mean Opinion Score) | Evaluation perceptuelle humaine | 1-5 (5 = excellent) |
| Speaker Error Rate (SER) | Taux d’erreur d’identification | 0-100% (0 = parfait) |
# Analyse de similarite vocale
print("ANALYSE DE SIMILARITE VOCALE")
print("=" * 45)
if xtts_loaded and generate_audio and analyze_similarity:
similarity_available = False
try:
from resemblyzer import VoiceEncoder, preprocess_wav
encoder = VoiceEncoder()
similarity_available = True
print("Resemblyzer charge pour l'analyse de similarite")
except ImportError:
print("resemblyzer non installe (pip install resemblyzer)")
print("Analyse de similarite par correlation simple")
# Charger les fichiers audio
ref_path = OUTPUT_DIR / "reference_speaker.wav"
clone_path = OUTPUT_DIR / "cloned_voice_fr.wav"
if ref_path.exists() and clone_path.exists():
ref_audio, ref_sr = sf.read(str(ref_path))
clone_audio, clone_sr = sf.read(str(clone_path))
if similarity_available:
# Analyse avec resemblyzer
ref_processed = preprocess_wav(ref_audio, source_sr=ref_sr)
clone_processed = preprocess_wav(clone_audio, source_sr=clone_sr)
ref_embed = encoder.embed_utterance(ref_processed)
clone_embed = encoder.embed_utterance(clone_processed)
# Similarite cosinus
cosine_sim = np.dot(ref_embed, clone_embed) / (
np.linalg.norm(ref_embed) * np.linalg.norm(clone_embed)
)
print(f"\nResultats de similarite :")
print(f" Similarite cosinus : {cosine_sim:.4f}")
print(f" Interpretation : ", end="")
if cosine_sim > 0.85:
print("Excellent - voix tres similaire")
elif cosine_sim > 0.75:
print("Bon - voix reconnaissable")
elif cosine_sim > 0.65:
print("Moyen - timbre partiellement capture")
else:
print("Faible - voix differente")
else:
# Analyse simplifiee sans resemblyzer
min_len = min(len(ref_audio), len(clone_audio))
if min_len > 0:
# Correlation sur les enveloppes spectrales
from scipy.signal import hilbert
ref_env = np.abs(hilbert(ref_audio[:min_len]))
clone_env = np.abs(hilbert(clone_audio[:min_len]))
corr = np.corrcoef(ref_env, clone_env)[0, 1]
print(f" Correlation d'enveloppe : {corr:.4f}")
# Statistiques comparatives
print(f"\nStatistiques audio :")
print(f" {'Metrique':<25} {'Reference':<15} {'Clone':<15}")
print(f" {'-'*55}")
print(f" {'Duree (s)':<25} {len(ref_audio)/ref_sr:<15.1f} {len(clone_audio)/clone_sr:<15.1f}")
print(f" {'Sample rate (Hz)':<25} {ref_sr:<15} {clone_sr:<15}")
print(f" {'RMS energy':<25} {np.sqrt(np.mean(ref_audio**2)):<15.4f} {np.sqrt(np.mean(clone_audio**2)):<15.4f}")
print(f" {'Peak amplitude':<25} {np.max(np.abs(ref_audio)):<15.4f} {np.max(np.abs(clone_audio)):<15.4f}")
else:
print("Fichiers audio non disponibles pour l'analyse")
else:
print("Analyse de similarite desactivee ou modele non charge")ANALYSE DE SIMILARITE VOCALE
=============================================
resemblyzer non installe (pip install resemblyzer)
Analyse de similarite par correlation simple
Correlation d'enveloppe : -0.0196
Statistiques audio :
Metrique Reference Clone
-------------------------------------------------------
Duree (s) 6.0 16.7
Sample rate (Hz) 22050 24000
RMS energy 0.1937 0.1779
Peak amplitude 0.3561 1.0000
Interpretation : Qualite du clonage
| Metrique | Valeur typique XTTS | Signification |
|---|---|---|
| Cosine similarity | 0.75-0.90 | Bon a excellent clonage |
| RMS energy | Variable | Normalise par le modèle |
| Peak amplitude | ~0.8-1.0 | Audio bien normalise |
Points cles : 1. Une similarite > 0.85 indique un clonage de très bonne qualite 2. La qualite du clip de reference est le facteur le plus important 3. Le clonage cross-lingual peut reduire legerement la similarite
Note ethique : Les systèmes de clonage vocal soulevent des enjeux majeurs. Le consentement du locuteur est indispensable. Coqui impose une licence non-commerciale (CPML) pour limiter les usages abusifs.
# Mode interactif - Clonage personnalise
if notebook_mode == "interactive" and not skip_widgets:
print("MODE INTERACTIF - CLONAGE PERSONNALISE")
print("=" * 50)
print("\nEntrez un texte a synthetiser avec la voix clonee :")
print("(Laissez vide pour passer a la suite)")
try:
user_text = input("\nVotre texte : ")
if user_text.strip() and xtts_loaded:
user_lang = input(f"Langue [{language}] (fr/en/es/de/it/pt) : ").strip() or language
ref_path = OUTPUT_DIR / "reference_speaker.wav"
if ref_path.exists():
print(f"\nGeneration avec clonage vocal (langue : {user_lang})...")
start_time = time.time()
out_path = OUTPUT_DIR / f"custom_clone_{user_lang}.wav"
tts.tts_to_file(
text=user_text,
file_path=str(out_path),
speaker_wav=str(ref_path),
language=user_lang
)
gen_time = time.time() - start_time
audio_data, sr = sf.read(str(out_path))
print(f"Duree : {len(audio_data)/sr:.1f}s | Temps : {gen_time:.2f}s")
display_audio_array(audio_data, sr)
else:
print("Clip de reference non disponible")
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 INTERACTIF - CLONAGE PERSONNALISE
==================================================
Entrez un texte a synthetiser avec la voix clonee :
(Laissez vide pour passer a la suite)
Mode interactif non disponible (execution automatisee)
Considerations ethiques et bonnes pratiques
Enjeux du clonage vocal
| Risque | Description | Mitigation |
|---|---|---|
| Usurpation d’identite | Utiliser la voix d’une personne sans autorisation | Consentement ecrit obligatoire |
| Deepfakes audio | Créer de faux enregistrements | Watermarking, detection |
| Fraude | Imiter une voix pour tromper | Authentification multi-facteurs |
| Desinformation | Créer de faux discours | Legislation, detection |
Bonnes pratiques
| Pratique | Description |
|---|---|
| Consentement | Toujours obtenir l’accord ecrit du locuteur |
| Watermarking | Ajouter un filigrane audio aux voix synthetiques |
| Documentation | Indiquer clairement qu’un audio est synthetique |
| Licence | Respecter la licence CPML (non-commercial) de XTTS |
Le clonage vocal et l’analyse de similarite sont a present complets. La cellule suivante recapitule les metriques de session et libere la memoire GPU utilisee par XTTS v2.
# Statistiques de session et prochaines etapes
print("STATISTIQUES DE SESSION")
print("=" * 45)
print(f"Date : {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"Modele : {model_name}")
print(f"Device : {device}")
print(f"Langue par defaut : {language}")
print(f"Modele charge : {'Oui' if xtts_loaded else 'Non'}")
if gpu_available:
vram_current = torch.cuda.memory_allocated(0) / (1024**3)
print(f"VRAM utilisee : {vram_current:.2f} GB")
if save_results:
saved = list(OUTPUT_DIR.glob('*'))
total_size = sum(f.stat().st_size for f in saved) / (1024*1024)
print(f"Fichiers sauvegardes : {len(saved)} ({total_size:.1f} MB) dans {OUTPUT_DIR.relative_to(GENAI_ROOT)} (sous GenAI/)")
# Liberation memoire
if xtts_loaded:
print(f"\nLiberation du modele...")
del tts
gc.collect()
if gpu_available:
torch.cuda.empty_cache()
print(f"Memoire liberee")
print(f"\nPROCHAINES ETAPES")
print(f"1. Explorer la generation musicale avec MusicGen (02-3)")
print(f"2. Decouvrir la separation de sources avec Demucs (02-4)")
print(f"3. Comparer tous les modeles audio (03-1)")
print(f"4. Construire un pipeline vocal complet (03-2)")
print(f"\nNotebook XTTS Voice Cloning termine - {datetime.now().strftime('%H:%M:%S')}")STATISTIQUES DE SESSION
=============================================
Date : 2026-08-19 14:41:17
Modele : tts_models/multilingual/multi-dataset/xtts_v2
Device : cuda
Langue par defaut : fr
Modele charge : Oui
VRAM utilisee : 1.75 GB
Fichiers sauvegardes : 6 (2.0 MB) dans outputs\audio\xtts (sous GenAI/)
Liberation du modele...
Memoire liberee
PROCHAINES ETAPES
1. Explorer la generation musicale avec MusicGen (02-3)
2. Decouvrir la separation de sources avec Demucs (02-4)
3. Comparer tous les modeles audio (03-1)
4. Construire un pipeline vocal complet (03-2)
Notebook XTTS Voice Cloning termine - 14:41:17
Synthese du Module
XTTS v2 represente l’etat de l’art pour le clonage vocal zero-shot. Ce notebook a explore les capacites du modèle a capturer et reproduire le timbre vocal sans entrainement supplementaire.
Tableau recapitulatif des performances
| Metrique | Valeur | Commentaire |
|---|---|---|
| Taille du modèle | ~1.8 GB | Telechargement unique au premier lancement |
| VRAM requise | ~6 GB | Compatible avec la plupart des GPUs modernes |
| Ratio temps reel (GPU) | 2-5x | Generation plus lente que la lecture mais acceptable |
| Qualite du clonage | 0.75-0.90 cosine | Bonne a excellente selon la qualite du reference |
| Support multilingue | 17 langues | Cross-lingual fonctionnel (timbre preserve) |
Points cles retenus
- Zero-shot : Pas de fine-tuning necessaire, le modèle fonctionne directement
- Cross-lingual : On peut cloner une voix en anglais et generer en francais
- Qualite variable : La qualite du clip de reference est le facteur principal
- Limitations ethiques : Le consentement du locuteur est indispensable
Positionnement dans l’ecosysteme TTS
| Cas d’usage | Modèle recommande |
|---|---|
| TTS simple (pas de clonage) | Kokoro TTS (plus rapide) |
| Clonage vocal zero-shot | XTTS v2 |
| TTS expressif/emotionnel | Chatterbox |
| Qualite maximale (API) | OpenAI TTS |
| Generation musicale | MusicGen (notebook suivant) |
Perspective : XTTS v2 est particulierement adapte pour les applications de doublage automatique, de creation de contenu audio personnalise, et d’accessibilite (voix personnalisee pour les personnes malvoyantes).
Exemple guide : Clonage Vocal Multilingue avec Analyse de Similarite
Duree estimee : 25-30 minutes
Objectif
Créer un pipeline de clonage vocal qui fonctionne sur plusieurs langues et analyser la qualite du clonage en comparant les embeddings vocaux entre la voix de reference et les voix clonees.
Instructions
- Créer une fonction
clone_voice_multilingualqui :- Prend un texte, une langue, et un chemin vers un clip de reference
- Genere la voix clonee avec XTTS v2
- Sauvegarde le fichier audio de sortie
- Retourne les metriques (duree, temps de generation)
- Generer des voix clonees dans au moins 3 langues différentes :
- Utiliser le même clip de reference pour toutes les langues
- Traduire ou adapter le texte selon la langue
- Sauvegarder chaque fichier avec un suffixe de langue
- Analyser la similarite entre la voix de reference et chaque voix clonee :
- Si
resemblyzerest disponible : calculer la similarite cosinus - Sinon : comparer les caractéristiques audio (RMS, peak, spectrogramme)
- Créer un tableau recapitulatif des résultats
- Si
Indices :
- La méthode
tts.tts_to_file()accepte les paramètrestext,file_path,speaker_wav, etlanguage - Les langues supportees incluent : ‘fr’, ‘en’, ‘es’, ‘de’, ‘it’, ‘pt’
- Pour la similarite avec resemblyzer : utiliser
VoiceEncoderetembed_utterance() - La similarite cosinus se calcule avec :
np.dot(embed1, embed2) / (norm(embed1) * norm(embed2)) - Sans resemblyzer, comparer les enveloppes spectrales avec
scipy.signal.hilbert()
def clone_voice_multilingual(text, language, ref_path, output_dir, model):
"""
Clone une voix dans une langue specifique avec XTTS v2.
Args:
text (str): Texte a synthetiser
language (str): Code langue (fr, en, es, de, etc.)
ref_path (Path): Chemin du clip de reference
output_dir (Path): Repertoire de sauvegarde
model: Modele XTTS charge
Returns:
dict: Contient 'filepath', 'duration', 'gen_time', 'similarity'
"""
# Exercice: Implementer le clonage vocal
# Indice: utiliser tts.tts_to_file() avec speaker_wav et language
# Indice: mesurer le temps de generation
# Indice: charger l'audio genere pour calculer sa duree
pass
def analyze_similarity(ref_audio, clone_audio, sample_rate):
"""
Analyse la similarite entre deux audios.
Args:
ref_audio (np.array): Audio de reference
clone_audio (np.array): Audio clone
sample_rate (int): Sample rate
Returns:
float: Score de similarite (0-1)
"""
# Exercice: Implementer l'analyse de similarite
# Indice: essayer d'importer resemblyzer pour l'approche avancee
# Indice: sinon, utiliser la correlation d'enveloppe spectrale
pass
# Exercice: Tester avec 3 langues differentes (fr, en, es par exemple)
# Exercice: Creer un tableau comparatif des resultats de similarite
# Exercice: Conclure sur l'impact de la langue sur la qualite du clonageExercice 3 : Transfert de style vocal inter-langue
Les modèles XTTS supportent le clonage vocal multilingue. L’objectif est de transferer une voix d’une langue a une autre tout en preservant le timbre.
Indice : Utiliser le même audio de reference avec un texte dans une autre langue cible.
def cross_lingual_transfer(reference_audio, target_text, target_lang):
# Etape 1 : Charger le modele XTTS
# Etape 2 : Verifier la langue cible supportee
# Etape 3 : Generer l'audio avec le style vocal de la reference
pass
result = None # TODO etudiant
print("Exercice a completer")Exercice a completer
Critères de reussite
| Critere | Description |
|---|---|
Fonction clone_voice_multilingual |
Genere correctement l’audio clone avec XTTS |
| Support multilingue | Fonctionne avec au moins 3 langues différentes |
| Metriques de similarite | Calcule et retourne un score de similarite |
| Tableau comparatif | Resume clair des résultats par langue |
| Analyse des résultats | Conclusion sur l’impact de la langue sur la qualite |
Extensions possibles
- Implementer une evaluation MOS (Mean Opinion Score) subjective
- Comparer XTTS v2 avec Chatterbox pour le clonage vocal
- Créer un pipeline de clonage avec verification automatique de qualite