Pour convertir du texte en parole en JavaScript, créez un SpeechSynthesisUtterance et transmettez-le à window.speechSynthesis.speak(). Le navigateur gère la lecture. Vous n’avez besoin ni de clé API, ni de serveur, ni de paquet JavaScript.
Cela convient à un prototype ou à une commande de lecture à voix haute si les voix de l’appareil suffisent. Pour un agent qui doit conserver la même voix sur tous les appareils ou diffuser l’audio dans un appel, préférez une API de synthèse vocale hébergée. SpeechSynthesis et l’API Cartesia sont deux méthodes distinctes.
Fonctionnement de la synthèse du navigateur
window.speechSynthesis est le contrôleur de parole synthétique de la Web Speech API. Un énoncé contient le texte et les réglages d’une requête. speak() l’ajoute à une file d’attente sans renvoyer de fichier audio.1
Le navigateur expose les voix de l’appareil via getVoices(). La liste peut se charger après votre script : lisez-la immédiatement, puis actualisez-la à l’événement voiceschanged.2 Ne codez pas en dur une voix de votre ordinateur en supposant qu’elle existe sur le téléphone d’un client.
1. Enregistrer une démonstration fonctionnelle
Enregistrez le code suivant dans speech.html et ouvrez-le dans un navigateur. Saisissez une phrase courte, choisissez une voix si une liste apparaît, puis appuyez sur Speak. Utilisez du texte non sensible : certaines voix passent par des services distants.3
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>JavaScript text-to-speech demo</title>
</head>
<body>
<h1>Read text aloud</h1>
<p>
<label for="text">Text to speak</label><br />
<textarea id="text" rows="4" cols="30" maxlength="500">
Hello from your browser.</textarea
>
</p>
<p>
<label for="voice">Voice</label>
<select id="voice"></select>
</p>
<button id="speak" type="button">Speak</button>
<button id="stop" type="button">Stop</button>
<p id="status" role="status" aria-live="polite">Ready.</p>
<script>
const text = document.querySelector("#text");
const voiceSelect = document.querySelector("#voice");
const speakButton = document.querySelector("#speak");
const stopButton = document.querySelector("#stop");
const status = document.querySelector("#status");
let voices = [];
let currentUtterance = null;
if (
!("speechSynthesis" in window) ||
!("SpeechSynthesisUtterance" in window)
) {
status.textContent = "This browser does not support speech synthesis.";
speakButton.disabled = true;
stopButton.disabled = true;
} else {
const synth = window.speechSynthesis;
function loadVoices() {
const previousVoice = voiceSelect.value;
voices = synth.getVoices();
voiceSelect.replaceChildren(new Option("Browser default", ""));
for (const voice of voices) {
voiceSelect.add(
new Option(`${voice.name} (${voice.lang})`, voice.voiceURI),
);
}
if (voices.some((voice) => voice.voiceURI === previousVoice)) {
voiceSelect.value = previousVoice;
}
}
loadVoices();
synth.addEventListener("voiceschanged", loadVoices);
speakButton.addEventListener("click", () => {
const transcript = text.value.trim();
if (!transcript) {
status.textContent = "Enter some text first.";
return;
}
// Ignore callbacks from the utterance being replaced.
currentUtterance = null;
synth.cancel();
const utterance = new SpeechSynthesisUtterance(transcript);
const voice = voices.find(
(item) => item.voiceURI === voiceSelect.value,
);
if (voice) {
utterance.voice = voice;
utterance.lang = voice.lang;
} else {
utterance.lang = document.documentElement.lang;
}
utterance.rate = 1;
currentUtterance = utterance;
status.textContent = "Starting speech...";
utterance.onstart = () => {
if (currentUtterance === utterance)
status.textContent = "Speaking...";
};
utterance.onend = () => {
if (currentUtterance !== utterance) return;
currentUtterance = null;
status.textContent = "Finished.";
};
utterance.onerror = (event) => {
if (currentUtterance !== utterance) return;
currentUtterance = null;
status.textContent = `Speech failed: ${event.error}`;
};
synth.speak(utterance);
});
stopButton.addEventListener("click", () => {
currentUtterance = null;
synth.cancel();
status.textContent = "Stopped.";
});
}
</script>
</body>
</html>
La démonstration limite le texte à 500 caractères pour garder le premier test court. C’est sa propre limite, pas celle de la Web Speech API. Testez séparément les passages longs sur chaque navigateur pris en charge.
2. Vérifier le choix de voix et la lecture
Le sélecteur affiche le nom et la langue des voix disponibles. Choisissez celle qui correspond au texte : définir utterance.lang ne traduit pas les mots.
Speak s’exécute après un clic plutôt qu’au chargement. L’auditeur garde ainsi le contrôle et vous ne dépendez pas de la lecture automatique. Un nouveau clic annule la requête en cours avant d’en lancer une autre, au lieu d’accumuler les clics dans la file. Stop appelle cancel(), qui vide les énoncés en attente et arrête la parole en cours.4
La vérification de currentUtterance empêche le rappel tardif d’une requête annulée de remplacer l’état d’une requête plus récente. Si vous adaptez le code en composant, retirez l’écouteur voiceschanged au démontage. N’annulez la lecture à ce moment que si ce composant possède la file vocale de la page.
3. Résoudre les problèmes de silence ou d’incohérence
| Symptôme | Vérifications |
|---|---|
| Le sélecteur n’affiche que Browser default | Attendez voiceschanged. Si la liste reste vide, vérifiez le navigateur et les voix système installées. La démonstration peut encore demander une voix par défaut. |
| Aucun son après Speak | Vérifiez volume et sortie audio, essayez une phrase courte dans la bonne langue et lisez le message d’état pour repérer une erreur. |
| Une voix existe sur ordinateur mais pas sur mobile | Les listes dépendent de l’appareil. Gardez un choix par défaut et testez les systèmes réellement pris en charge. |
| Des clics répétés retardent la parole | speak() met les requêtes en attente. Annulez l’ancienne si le nouveau texte doit la remplacer. |
| La parole échoue sans Internet | La voix choisie peut dépendre d’un service distant. Examinez voice.localService et testez hors ligne au lieu de supposer une synthèse locale. |
Pour une lecture à voix haute, gardez le texte original visible et rendez Stop accessible au clavier. Ne démarrez pas automatiquement et ne traitez pas la synthèse comme un remplacement de la compatibilité avec les lecteurs d’écran.
Quand utiliser une API TTS hébergée
Choisissez la synthèse du navigateur si les voix disponibles suffisent et si la lecture reste sur cet appareil. Choisissez une API hébergée pour obtenir des octets audio, une identité vocale gérée par le fournisseur ou une diffusion hors navigateur.
| Besoin | SpeechSynthesis du navigateur | API TTS hébergée comme Cartesia |
|---|---|---|
| Identifiants | Pas de clé API applicative | Identifiants API et compte autorisé |
| Choix des voix | Liste du navigateur et du système | Bibliothèque du fournisseur ou voix personnalisée autorisée |
| Destination audio | Lecture dans le navigateur | Audio reçu par l’application pour lecture, stockage ou transport |
| Hors ligne | Dépend de la voix et de l’appareil | Les requêtes API Cartesia nécessitent le réseau |
| Traitement du texte | Local ou distant selon la voix | Texte envoyé au fournisseur ; vérifiez les exigences de données avant intégration |
Pour la synthèse vocale Cartesia, appelez l’API depuis votre serveur. Gardez-y la clé, hors d’un fichier HTML public ou d’un bundle client. Le navigateur peut envoyer le texte à votre serveur authentifié, qui applique les limites d’entrée et renvoie l’audio. Limitez le débit de ce point de terminaison pour empêcher une consommation illimitée de vos crédits.
Commencez par générer un WAV avec le SDK Python Cartesia. Ce guide teste la génération hébergée ; ce n’est pas un lecteur de navigateur en continu. Une application conversationnelle demande aussi mémoire tampon et gestion des interruptions. Comparez ce travail à Cartesia Managed Agents avant de construire toute la chaîne vous-même.
Références associées
- Compatibilité des navigateurs et référence API SpeechSynthesis
- Cartesia Sonic
- Tarifs de l’API Cartesia
Notes de bas de page
-
MDN, SpeechSynthesis. ↩
-
MDN, SpeechSynthesis.getVoices(). ↩
-
MDN, SpeechSynthesis.cancel(). ↩