Lire ou écrire ne me pose pas trop de problèmes, mais dès qu’il s’agit de parler, je me rends compte que ma prononciation n’est pas toujours claire.
ChatGPT est super pour le texte, mais les modèles génératifs actuels ne savent pas évaluer la prononciation.
Alors je me suis demandé : et si je construisais moi-même un petit coach ?
Un outil qui :
C’est ce que je vais détailler ici, tout en expliquant simplement les briques IA derrière : embeddings, distances, DTW, phonèmes, visèmes.
Un mot parlé n’est pas une suite de lettres, mais une onde sonore qui varie dans le temps :
Même deux personnes qui prononcent exactement le même mot n’auront jamais deux courbes identiques.
La question centrale devient donc : comment comparer deux audios qui ne s’alignent pas parfaitement ?
Voici un aperçu de l’architecture que j’ai mise en place :
N’ayez pas peur, on va expliquer tous ces concepts pas à pas.
Un ordinateur ne comprend pas les sons. Il ne manipule que des vecteurs de nombres.
[0.2, -0.7, 1.1]
.Avec Wav2Vec2, chaque tranche d’audio de quelques millisecondes est encodée en 768 nombres décrivant le timbre, l’énergie, l’articulation, etc.
processor = Wav2Vec2Processor.from_pretrained("facebook/wav2vec2-large-960h")
def extract_embeddings(audio_waveform, sampling_rate=16000):
inputs = processor(audio_waveform, sampling_rate=sampling_rate,
return_tensors="pt", padding=True)
input_values = inputs.input_values.squeeze(0)
with torch.no_grad():
features = model(input_values).last_hidden_state
return features.squeeze(0).numpy()
En résumé :
Une fois deux vecteurs extraits, il faut mesurer leur proximité.
L’outil de base : la distance euclidienne.
Exemple simple entre [1,2]
et [4,6]
:
√((4-1)² + (6-2)²) = 5
Avec les embeddings audio, c’est le même principe mais dans un espace à 768 dimensions.
from fastdtw import fastdtw
from scipy.spatial.distance import euclidean
def compare_pronunciation(expected, actual):
expected_seq = get_phoneme_embeddings(expected)
actual_seq = get_phoneme_embeddings(actual)
distance, _ = fastdtw(expected_seq, actual_seq, dist=euclidean)
return distance
Problème : un mot peut durer 0,5 seconde chez moi et 0,8 seconde dans la référence.
Si on compare naïvement, ça échoue.
La solution : Dynamic Time Warping (DTW).
Cet algorithme aligne deux séquences de vitesses différentes en “étirant” ou “compressant” le temps pour faire correspondre les parties similaires.
import numpy as np
def align_sequences_dtw(seq1, seq2):
distance, path = fastdtw(seq1, seq2, dist=euclidean)
aligned1, aligned2 = [], []
for i, j in path:
aligned1.append(seq1[i][0])
aligned2.append(seq2[j][0])
return np.array(aligned1), np.array(aligned2)
Résultat : une comparaison robuste, même si le rythme diffère.
Certains sons sont difficiles à distinguer à l’oreille.
Exemple : “think” vs “sink” (différence subtile entre /θ/ et /s/).
Dans mon prototype, quand un mot est mal prononcé, je peux cliquer dessus et voir une animation de bouche qui montre la bonne articulation.
👉 Apprentissage plus concret : j’entends et je vois ce qu’il faut corriger.
(Documentation Microsoft sur les visèmes)
Soyons honnêtes :
Je n’ai pas réinventé Duolingo. Mais j’ai construit un coach maison qui m’aide à progresser à l’oral.
La force vient de la combinaison :
Un mélange de machine learning, de maths et de pédagogie, au service d’un objectif très concret : mieux parler anglais.
👉 Le code source est disponible sur GitHub.
Vos retours ou contributions sont bienvenus.
© Jean-François Lépine, 2010 - 2025