Per trasformare testo in parlato in JavaScript, crea una SpeechSynthesisUtterance e passala a window.speechSynthesis.speak(). Il browser gestisce la riproduzione. Non servono una chiave API, un server o un pacchetto JavaScript.
Funziona bene per un prototipo o un controllo di lettura ad alta voce in cui le voci del dispositivo sono accettabili. Se sviluppi un agente vocale che richiede la stessa voce su dispositivi diversi o audio in streaming verso una telefonata, usa invece un’API di sintesi vocale ospitata. SpeechSynthesis del browser e l’API di Cartesia sono modi distinti di generare parlato.
Come funziona la sintesi vocale del browser
window.speechSynthesis è il controller della Web Speech API per il parlato sintetizzato. Un’utterance contiene testo e impostazioni di una richiesta. Chiamare speak() aggiunge l’utterance a una coda; non restituisce un file audio.1
Il browser espone le voci disponibili sul dispositivo tramite getVoices(). L’elenco può caricarsi dopo l’esecuzione dello script, quindi leggilo subito e aggiornalo quando si attiva voiceschanged.2 Non inserire nel codice il nome di una voce del tuo portatile aspettandoti di trovarla anche sul telefono di un cliente.
1. Salva una demo di sintesi vocale funzionante
Salva il codice seguente come speech.html e aprilo in un browser. Inserisci una frase breve, scegli una voce se il browser ne elenca una e premi Speak. Usa testo di esempio non sensibile: alcune voci impiegano servizi vocali remoti.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 demo limita l’input a 500 caratteri per mantenere breve il primo test. È un limite della demo, non della Web Speech API. Prova passaggi più lunghi separatamente su ogni browser supportato.
2. Verifica selezione della voce e riproduzione
Il selettore mostra nome e lingua di ogni voce disponibile. Scegli una voce corrispondente alla lingua del testo: impostare utterance.lang non traduce le parole.
Speak viene eseguito al clic sul pulsante, non al caricamento della pagina. Questo dà il controllo all’ascoltatore ed evita di affidarsi alla riproduzione automatica. Premere di nuovo Speak annulla la richiesta corrente prima di avviarne un’altra, anziché accodare clic ripetuti. Stop chiama cancel(), che rimuove le utterance in coda e interrompe il parlato corrente.4
Il controllo currentUtterance impedisce a un callback tardivo di una richiesta annullata di sovrascrivere lo stato di una più recente. Se adatti il codice in un componente, rimuovi il listener voiceschanged quando il componente viene smontato. Annulla la riproduzione allo smontaggio solo se quel componente controlla la coda vocale della pagina.
3. Risolvi parlato assente o incoerente
| Sintomo | Cosa verificare |
|---|---|
| Il selettore mostra solo Browser default | Attendi voiceschanged. Se l’elenco resta vuoto, controlla supporto del browser e voci installate. La demo può comunque richiedere una voce predefinita. |
| Nessun suono dopo aver premuto Speak | Controlla volume e uscita audio, prova una frase breve nella lingua corrispondente e leggi il messaggio di stato per eventuali errori di sintesi. |
| Una voce esiste su desktop ma non su mobile | Gli elenchi dipendono dal dispositivo. Mantieni un’opzione predefinita e prova sui sistemi operativi effettivamente supportati. |
| Clic ripetuti causano parlato ritardato | speak() accoda le richieste. Annulla prima quella vecchia se il nuovo testo deve sostituirla. |
| Il parlato non funziona senza internet | La voce scelta può usare un servizio remoto. Esamina voice.localService e prova offline anziché presumere una sintesi locale. |
Per una funzione di lettura ad alta voce, lascia visibile il testo originale e rendi Stop accessibile da tastiera. Non avviare automaticamente il parlato e non trattarlo come un sostituto del supporto agli screen reader.
Quando usare un’API TTS ospitata
Scegli il parlato del browser quando bastano le voci disponibili all’ascoltatore e serve solo riproduzione sul suo dispositivo. Scegli un’API ospitata quando l’applicazione richiede byte audio generati, un’identità vocale gestita dal fornitore o audio inviato fuori dal browser.
| Requisito | SpeechSynthesis del browser | API TTS ospitata come Cartesia |
|---|---|---|
| Credenziali | Nessuna chiave API applicativa | Credenziali API e account con accesso all’utilizzo |
| Selezione della voce | Elenco del browser e del sistema operativo | Catalogo del fornitore o voce personalizzata autorizzata |
| Destinazione audio | Riproduzione nel browser | L’applicazione riceve audio da riprodurre, conservare o trasportare |
| Comportamento offline | Dipende da voce e dispositivo | Le richieste API di Cartesia richiedono una connessione di rete |
| Gestione del testo | Locale o remota, secondo la voce | Il testo viene inviato al fornitore; verifica i requisiti sui dati prima dell’integrazione |
Per la sintesi vocale di Cartesia, chiama l’API dal backend. Conserva lì la chiave API, non in un file HTML pubblico o in un bundle client. Un’applicazione browser può inviare testo al backend autenticato, che applica limiti di input e restituisce audio al client. Limita la frequenza delle richieste a quell’endpoint per evitare che i visitatori consumino crediti API senza limiti.
Inizia generando un file WAV con l’SDK Python di Cartesia. La guida verifica il percorso di generazione ospitata; non è un lettore browser in streaming. Per un’applicazione conversazionale servono anche buffering di riproduzione e gestione delle interruzioni. Confronta questo lavoro con Cartesia Managed Agents prima di costruire l’intera pipeline dell’agente vocale.
Riferimenti correlati
Note a piè di pagina
-
MDN, SpeechSynthesis. ↩
-
MDN, SpeechSynthesis.getVoices(). ↩
-
MDN, SpeechSynthesis.cancel(). ↩