Come sintetizzare la voce dal testo
Documentazione di riferimento | Pacchetto (NuGet) | Ulteriori esempi in GitHub
In questa guida pratica vengono illustrati i modelli di progettazione comuni per eseguire la sintesi vocale.
Per altre informazioni sulle aree seguenti, vedere Che cos'è la sintesi vocale?
- Recupero di risposte come flussi in memoria.
- Personalizzazione della frequenza di campionamento e della velocità in bit dell'output.
- Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
- Uso di voci neurali.
- Sottoscrizione di eventi e azioni sui risultati.
Selezionare il linguaggio di sintesi e la voce
La funzionalità sintesi vocale nel servizio Voce supporta più di 400 voci e più di 140 lingue e varianti. È possibile ottenere l'elenco completo o provarle nella Raccolta voci.
Specificare la lingua o la voce di SpeechConfig
perché corrispondano al testo di input e usino la voce specificata. Il seguente frammento di codice illustra il funzionamento di questa tecnica:
static async Task SynthesizeAudioAsync()
{
var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
// Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
speechConfig.SpeechSynthesisLanguage = "en-US";
speechConfig.SpeechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
}
Tutte le voci neurali sono multilingue e parlano fluentemente sia la propria lingua che l’inglese. Ad esempio, se il testo di input in inglese è "I'm excited to try text to speech" e si imposta es-ES-ElviraNeural
, il testo viene pronunciato in inglese con un accento spagnolo.
Se la voce non parla la lingua del testo di input, il servizio cognitivo di Azure per la voce non creerà audio sintetizzato. Per un elenco completo delle voci neurali supportate, consultare Lingue e voci supportate per il servizio cognitivo di Azure per la voce.
Nota
La voce predefinita è la prima voce restituita per impostazioni locali dall'API dell'elenco voci.
La voce che parla viene determinata in ordine di priorità come indicato di seguito:
- Se non si imposta
SpeechSynthesisVoiceName
oSpeechSynthesisLanguage
, a parlare sarà la voce predefinita peren-US
. - Se si imposta solo
SpeechSynthesisLanguage
, a parlare sarà la voce predefinita per impostazioni locali specificate. - Se
SpeechSynthesisVoiceName
eSpeechSynthesisLanguage
sono entrambi impostati, l'impostazioneSpeechSynthesisLanguage
verrà ignorata. La voce specificata tramiteSpeechSynthesisVoiceName
sarà quella a parlare. - Se l'elemento voce viene impostato tramite Speech Synthesis Markup Language (SSML), le impostazioni
SpeechSynthesisVoiceName
eSpeechSynthesisLanguage
verranno ignorate.
In sintesi, l'ordine di priorità può essere descritto come segue:
SpeechSynthesisVoiceName |
SpeechSynthesisLanguage |
SSML | Risultato |
---|---|---|---|
✗ | ✗ | ✗ | La voce predefinita per en-US sarà quella a parlare |
✗ | ✔ | ✗ | La voce predefinita per le impostazioni locali specificate sarà quella a parlare. |
✔ | ✔ | ✗ | La voce specificata tramite SpeechSynthesisVoiceName sarà quella a parlare. |
✔ | ✔ | ✔ | La voce specificata tramite SSML sarà quella a parlare. |
Sintetizzare la voce in un file
Creare un oggetto SpeechSynthesizer. Questo oggetto, mostrato nei seguenti frammenti di codice, esegue le conversioni di sintesi vocale e invia l’output ad altoparlanti, file o altri flussi di output. SpeechSynthesizer
accetta come parametri:
- L’oggetto SpeechConfig creato nel passaggio precedente
- Un oggetto AudioConfig che specifica la modalità di gestione dei risultati di output
Creare un'istanza
AudioConfig
per scrivere automaticamente l'output in un file .wav usando la funzioneFromWavFileOutput()
: Creare un'istanza con un'istruzioneusing
.static async Task SynthesizeAudioAsync() { var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion"); using var audioConfig = AudioConfig.FromWavFileOutput("path/to/write/file.wav"); }
Un'istruzione
using
in questo contesto elimina automaticamente le risorse non gestite e fa in modo che l'oggetto esca dall'ambito dopo l'eliminazione.Creare un'istanza di
SpeechSynthesizer
con un'altra istruzioneusing
. Passare l'oggettospeechConfig
e l'oggettoaudioConfig
come parametri. Per sintetizzare il parlato e scrivere in un file, eseguireSpeakTextAsync()
con una stringa di testo.
static async Task SynthesizeAudioAsync()
{
var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
using var audioConfig = AudioConfig.FromWavFileOutput("path/to/write/file.wav");
using var speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
}
Quando si esegue il programma, viene creato un file sintetizzato .wav, scritto nel percorso specificato. Questo risultato è un buon esempio dell'utilizzo più semplice. Si esamini quindi la personalizzazione dell'output e la gestione della risposta di output come flusso in memoria per l'uso di scenari personalizzati.
Sintetizzare l'output dell'altoparlante
Per eseguire l'output vocale sintetizzato nel dispositivo di output attivo corrente, ad esempio un altoparlante, omettere il parametro AudioConfig
durante la creazione dell'istanza SpeechSynthesizer
. Ecco un esempio:
static async Task SynthesizeAudioAsync()
{
var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
using var speechSynthesizer = new SpeechSynthesizer(speechConfig);
await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
}
Ottenere un risultato come flusso in memoria
È possibile usare i dati audio risultanti come flusso in memoria anziché scrivere direttamente in un file. Con il flusso in memoria è possibile creare un comportamento personalizzato:
- Astrarre la matrice di byte risultante come flusso ricercabile per i servizi downstream personalizzati.
- Integrare il risultato con altri servizi o API.
- Modificare i dati audio, scrivere intestazioni di .wav personalizzate ed eseguire attività correlate.
È possibile apportare questa modifica all'esempio precedente. Prima rimuovere il blocco AudioConfig
, poiché da questo punto in poi il comportamento di output viene gestito manualmente per un maggior controllo. Passare null
per AudioConfig
nel costruttore SpeechSynthesizer
.
Nota
Se si passa null
per AudioConfig
, invece di ometterlo come nel precedente esempio di output nell'altoparlante, l'audio non viene riprodotto per impostazione predefinita nel dispositivo di output attivo corrente.
Salvare il risultato in una variabile SpeechSynthesisResult. La proprietà AudioData
contiene un'istanza byte []
per i dati di output. Questo oggetto byte []
può essere gestito manualmente oppure è possibile usare la classe AudioDataStream per gestire il flusso in memoria.
In questo esempio si usa la funzione statica AudioDataStream.FromResult()
per ottenere un flusso dal risultato:
static async Task SynthesizeAudioAsync()
{
var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
using var speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
var result = await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
using var stream = AudioDataStream.FromResult(result);
}
A questo punto, è possibile implementare qualsiasi comportamento personalizzato usando l'oggetto stream
risultante.
Personalizzare il formato audio
È possibile personalizzare gli attributi di output audio, tra cui:
- Tipo di file audio
- Frequenza di campionamento
- Profondità di bit
Per cambiare il formato audio, usare la funzione SetSpeechSynthesisOutputFormat()
nell'oggetto SpeechConfig
. Questa funzione prevede un'istanza di enum
di tipo SpeechSynthesisOutputFormat. Usare il enum
per selezionare il formato di output. Per i formati disponili, vedere l’elenco dei formati audio.
Sono disponibili varie opzioni per tipi di file diversi a seconda dei requisiti. Per definizione, i formati non elaborati come Raw24Khz16BitMonoPcm
non includono intestazioni audio. Usare i formati non elaborati solo in una di queste situazioni:
- Si sa che l'implementazione downstream può decodificare un flusso di bit non elaborato.
- Si prevede di compilare manualmente le intestazioni in base a fattori quali profondità bit, frequenza di campionamento e numero di canali.
Questo esempio specifica un formato RIFF ad alta fedeltà Riff24Khz16BitMonoPcm
impostando SpeechSynthesisOutputFormat
nell'oggetto SpeechConfig
. Analogamente all'esempio della sezione precedente, è possibile usare AudioDataStream per ottenere un flusso in memoria del risultato e quindi scriverlo in un file.
static async Task SynthesizeAudioAsync()
{
var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
speechConfig.SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm);
using var speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
var result = await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
using var stream = AudioDataStream.FromResult(result);
await stream.SaveToWaveFileAsync("path/to/write/file.wav");
}
Quando si esegue il programma, scrive un file .wav nel percorso specificato.
Usare SSML per personalizzare le caratteristiche vocali
È possibile usare SSML per ottimizzare il tono, la pronuncia, la velocità del parlato, il volume e altri aspetti nell'output della sintesi vocale inviando le richieste da uno schema XML. Questa sezione illustra un esempio di modifica della voce. Per altre informazioni, vedere Panoramica di Speech Synthesis Markup Language.
Per iniziare a usare SSML per la personalizzazione, è necessario apportare una piccola modifica che cambia la voce.
Creare prima di tutto un nuovo file XML per la configurazione di SSML nella directory radice del progetto.
<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US"> <voice name="en-US-AvaMultilingualNeural"> When you're on the freeway, it's a good idea to use a GPS. </voice> </speak>
In questo esempio, file è ssml.xml. L'elemento radice è sempre
<speak>
. Il wrapping del testo in un elemento<voice>
consente di modificare la voce usando il parametroname
. Per l'elenco completo delle voci neurali supportate, vedere Supporto linguistico.Cambiare la richiesta di sintesi vocale in modo che faccia riferimento al file XML. La richiesta è essenzialmente la stessa, ma invece di usare la funzione
SpeakTextAsync()
si usaSpeakSsmlAsync()
. Questa funzione prevede una stringa XML. Prima di tutto, caricare la configurazione di SSML come stringa usandoFile.ReadAllText()
. Da qui, l'oggetto risultato è esattamente lo stesso degli esempi precedenti.Nota
Se si usa Visual Studio, la configurazione di compilazione probabilmente non troverà il file XML per impostazione predefinita. Fare clic con il pulsante destro del mouse sul file XML e selezionare Proprietà. Impostare Azione di compilazione su Contenuto Impostare Copia nella directory di output su Copia sempre.
public static async Task SynthesizeAudioAsync() { var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion"); using var speechSynthesizer = new SpeechSynthesizer(speechConfig, null); var ssml = File.ReadAllText("./ssml.xml"); var result = await speechSynthesizer.SpeakSsmlAsync(ssml); using var stream = AudioDataStream.FromResult(result); await stream.SaveToWaveFileAsync("path/to/write/file.wav"); }
Nota
Per modificare la voce senza usare SSML, è possibile impostare la proprietà su SpeechConfig
tramite SpeechConfig.SpeechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
.
Sottoscrivere eventi di sintetizzatore
È possibile ottenere altre informazioni dettagliate sull'elaborazione del testo e sui risultati del riconoscimento vocale. Ad esempio, è possibile sapere quando il sintetizzatore inizia e si arresta oppure si potrebbe voler conoscere altri eventi rilevati durante la sintesi.
Quando si usa SpeechSynthesizer per la sintesi vocale, è possibile sottoscrivere gli eventi in questa tabella:
Event | Descrizione | Caso d'uso |
---|---|---|
BookmarkReached |
Segnala che è stato raggiunto un segnalibro. Per attivare un evento raggiunto da un segnalibro, è necessario un elemento bookmark nel SSML. Questo evento segnala il tempo trascorso dell'audio di output tra l'inizio della sintesi e l'elemento bookmark . La proprietà dell'evento Text è il valore stringa impostato nell'attributo mark del segnalibro. Gli elementi bookmark non vengono pronunciati. |
È possibile usare l'elemento bookmark per inserire marcatori personalizzati in SSML per ottenere l'offset di ogni marcatore nel flusso audio. L'elemento bookmark può essere usato per fare riferimento a una posizione specifica nella sequenza di testo o tag. |
SynthesisCanceled |
Segnala che la sintesi vocale è stata annullata. | È possibile confermare quando la sintesi è annullata. |
SynthesisCompleted |
Segnala che la sintesi vocale è stata completata. | È possibile confermare quando la sintesi è stata completata. |
SynthesisStarted |
Segnala che la sintesi vocale è stata completata. | È possibile confermare l'avvio della sintesi. |
Synthesizing |
Segnala che la sintesi vocale è in corso. Questo evento viene generato ogni volta che l'SDK riceve un blocco audio dal servizio Voce. | È possibile confermare quando la sintesi è in corso. |
VisemeReceived |
Segnala che è stato ricevuto un evento visema. | I Visemi vengono spesso usati per rappresentare le posizioni chiave nel parlato osservato. Le pose chiave includono la posizione delle labbra, della mascella e della lingua nella produzione di un particolare fonema. È possibile usare visemi per animare il viso di un personaggio durante la riproduzione dell'audio vocale. |
WordBoundary |
Segnala che è stato ricevuto un limite di parola. Questo evento viene generato all'inizio di ogni nuova parola pronunciata, punteggiatura e frase. L'evento segnala l'offset di tempo della parola corrente, in tick, dall'inizio dell'audio di output. Questo evento segnala anche la posizione del carattere nel testo di input o SSML immediatamente prima della parola che sta per essere pronunciata. | Questo evento viene comunemente usato per ottenere posizioni relative del testo e dell'audio corrispondente. Potrebbe essere necessario conoscere una nuova parola e quindi intervenire in base alla tempistica. Ad esempio, è possibile ottenere informazioni che consentono di decidere quando e per quanto tempo evidenziare le parole quando vengono pronunciate. |
Nota
Gli eventi vengono generati man mano che i dati audio di output diventano disponibili, che è più veloce della riproduzione in un dispositivo di output. Il chiamante deve sincronizzare in modo appropriato lo streaming e il tempo reale.
Ecco un esempio che illustra come sottoscrivere eventi per la sintesi vocale.
Importante
Se si usa una chiave API, archiviarla in modo sicuro in un'altra posizione, ad esempio in Azure Key Vault. Non includere la chiave API direttamente nel codice e non esporla mai pubblicamente.
Per altre informazioni sulla sicurezza dei servizi di intelligenza artificiale, vedere Autenticare le richieste a Servizi di Azure AI.
È possibile seguire le istruzioni nella guida introduttiva, ma sostituire il contenuto del file Program.cs con il codice C# seguente:
using Microsoft.CognitiveServices.Speech;
class Program
{
// This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
static string speechKey = Environment.GetEnvironmentVariable("SPEECH_KEY");
static string speechRegion = Environment.GetEnvironmentVariable("SPEECH_REGION");
async static Task Main(string[] args)
{
var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);
var speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
var ssml = @$"<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
<voice name='{speechSynthesisVoiceName}'>
<mstts:viseme type='redlips_front'/>
The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.
</voice>
</speak>";
// Required for sentence-level WordBoundary events
speechConfig.SetProperty(PropertyId.SpeechServiceResponse_RequestSentenceBoundary, "true");
using (var speechSynthesizer = new SpeechSynthesizer(speechConfig))
{
// Subscribe to events
speechSynthesizer.BookmarkReached += (s, e) =>
{
Console.WriteLine($"BookmarkReached event:" +
$"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" +
$"\r\n\tText: \"{e.Text}\".");
};
speechSynthesizer.SynthesisCanceled += (s, e) =>
{
Console.WriteLine("SynthesisCanceled event");
};
speechSynthesizer.SynthesisCompleted += (s, e) =>
{
Console.WriteLine($"SynthesisCompleted event:" +
$"\r\n\tAudioData: {e.Result.AudioData.Length} bytes" +
$"\r\n\tAudioDuration: {e.Result.AudioDuration}");
};
speechSynthesizer.SynthesisStarted += (s, e) =>
{
Console.WriteLine("SynthesisStarted event");
};
speechSynthesizer.Synthesizing += (s, e) =>
{
Console.WriteLine($"Synthesizing event:" +
$"\r\n\tAudioData: {e.Result.AudioData.Length} bytes");
};
speechSynthesizer.VisemeReceived += (s, e) =>
{
Console.WriteLine($"VisemeReceived event:" +
$"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" +
$"\r\n\tVisemeId: {e.VisemeId}");
};
speechSynthesizer.WordBoundary += (s, e) =>
{
Console.WriteLine($"WordBoundary event:" +
// Word, Punctuation, or Sentence
$"\r\n\tBoundaryType: {e.BoundaryType}" +
$"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" +
$"\r\n\tDuration: {e.Duration}" +
$"\r\n\tText: \"{e.Text}\"" +
$"\r\n\tTextOffset: {e.TextOffset}" +
$"\r\n\tWordLength: {e.WordLength}");
};
// Synthesize the SSML
Console.WriteLine($"SSML to synthesize: \r\n{ssml}");
var speechSynthesisResult = await speechSynthesizer.SpeakSsmlAsync(ssml);
// Output the results
switch (speechSynthesisResult.Reason)
{
case ResultReason.SynthesizingAudioCompleted:
Console.WriteLine("SynthesizingAudioCompleted result");
break;
case ResultReason.Canceled:
var cancellation = SpeechSynthesisCancellationDetails.FromResult(speechSynthesisResult);
Console.WriteLine($"CANCELED: Reason={cancellation.Reason}");
if (cancellation.Reason == CancellationReason.Error)
{
Console.WriteLine($"CANCELED: ErrorCode={cancellation.ErrorCode}");
Console.WriteLine($"CANCELED: ErrorDetails=[{cancellation.ErrorDetails}]");
Console.WriteLine($"CANCELED: Did you set the speech resource key and region values?");
}
break;
default:
break;
}
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
È possibile trovare altri esempi di testo per il riconoscimento vocale in GitHub.
Usare un endpoint personalizzato
Dal punto di vista funzionale, l'endpoint personalizzato è identico all'endpoint standard usato per le richieste di sintesi vocale.
Una differenza è che EndpointId
deve essere specificato per usare la voce personalizzata tramite Speech SDK. È possibile iniziare con l‘avvio rapido della sintesi vocale e quindi aggiornare il codice con EndpointId
e SpeechSynthesisVoiceName
.
var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);
speechConfig.SpeechSynthesisVoiceName = "YourCustomVoiceName";
speechConfig.EndpointId = "YourEndpointId";
Per usare una voce personalizzata tramite Speech Synthesis Markup Language (SSML), specificare il nome del modello come nome della voce. Questo esempio usa la voce YourCustomVoiceName
.
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
<voice name="YourCustomVoiceName">
This is the text that is spoken.
</voice>
</speak>
Eseguire e usare un contenitore
I contenitori del servizio Voce forniscono API di endpoint di query basate su WebSocket a cui si accede tramite Speech SDK e l'interfaccia della riga di comando di Voce. Per impostazione predefinita, l'SDK e l'interfaccia della riga di comando di Voce usano il servizio Voce pubblico. Per usare il contenitore, è necessario modificare il metodo di inizializzazione. Usare un URL host del contenitore invece di chiave e area.
Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori di Voce con Docker.
Documentazione di riferimento | Pacchetto (NuGet) | Ulteriori esempi in GitHub
In questa guida pratica vengono illustrati i modelli di progettazione comuni per eseguire la sintesi vocale.
Per altre informazioni sulle aree seguenti, vedere Che cos'è la sintesi vocale?
- Recupero di risposte come flussi in memoria.
- Personalizzazione della frequenza di campionamento e della velocità in bit dell'output.
- Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
- Uso di voci neurali.
- Sottoscrizione di eventi e azioni sui risultati.
Selezionare il linguaggio di sintesi e la voce
La funzionalità sintesi vocale nel servizio Voce supporta più di 400 voci e più di 140 lingue e varianti. Fare riferimento all'elenco completo delle impostazioni locali di riconoscimento vocale supportate o provarle in Raccolta voci.
Specificare la lingua o la voce della classe SpeechConfig perché corrispondano al testo di input e usino la voce specificata. Il seguente frammento di codice illustra il funzionamento di questa tecnica:
void synthesizeSpeech()
{
auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
// Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
speechConfig->SetSpeechSynthesisLanguage("en-US");
speechConfig->SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");
}
Tutte le voci neurali sono multilingue e parlano fluentemente sia la propria lingua che l’inglese. Ad esempio, se il testo di input in inglese è "I'm excited to try text to speech" e si imposta es-ES-ElviraNeural
, il testo viene pronunciato in inglese con un accento spagnolo.
Se la voce non parla la lingua del testo di input, il servizio cognitivo di Azure per la voce non creerà audio sintetizzato. Per un elenco completo delle voci neurali supportate, consultare Lingue e voci supportate per il servizio cognitivo di Azure per la voce.
Nota
La voce predefinita è la prima voce restituita per impostazioni locali dall'API dell'elenco voci.
La voce che parla viene determinata in ordine di priorità come indicato di seguito:
- Se non si imposta
SpeechSynthesisVoiceName
oSpeechSynthesisLanguage
, a parlare sarà la voce predefinita peren-US
. - Se si imposta solo
SpeechSynthesisLanguage
, a parlare sarà la voce predefinita per impostazioni locali specificate. - Se
SpeechSynthesisVoiceName
eSpeechSynthesisLanguage
sono entrambi impostati, l'impostazioneSpeechSynthesisLanguage
verrà ignorata. La voce specificata tramiteSpeechSynthesisVoiceName
sarà quella a parlare. - Se l'elemento voce viene impostato tramite Speech Synthesis Markup Language (SSML), le impostazioni
SpeechSynthesisVoiceName
eSpeechSynthesisLanguage
verranno ignorate.
In sintesi, l'ordine di priorità può essere descritto come segue:
SpeechSynthesisVoiceName |
SpeechSynthesisLanguage |
SSML | Risultato |
---|---|---|---|
✗ | ✗ | ✗ | La voce predefinita per en-US sarà quella a parlare |
✗ | ✔ | ✗ | La voce predefinita per le impostazioni locali specificate sarà quella a parlare. |
✔ | ✔ | ✗ | La voce specificata tramite SpeechSynthesisVoiceName sarà quella a parlare. |
✔ | ✔ | ✔ | La voce specificata tramite SSML sarà quella a parlare. |
Sintetizzare la voce in un file
Creare un oggetto SpeechSynthesizer. Questo oggetto, mostrato nei seguenti frammenti di codice, esegue le conversioni di sintesi vocale e invia l’output ad altoparlanti, file o altri flussi di output. SpeechSynthesizer
accetta come parametri:
- L’oggetto SpeechConfig creato nel passaggio precedente
- Un oggetto AudioConfig che specifica la modalità di gestione dei risultati di output
Creare un'istanza
AudioConfig
per scrivere automaticamente l'output in un file .wav usando la funzioneFromWavFileOutput()
:void synthesizeSpeech() { auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion"); auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav"); }
Creare un'istanza di
SpeechSynthesizer
. Passare l'oggettospeechConfig
e l'oggettoaudioConfig
come parametri. Per sintetizzare il parlato e scrivere in un file, eseguireSpeakTextAsync()
con una stringa di testo.void synthesizeSpeech() { auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion"); auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav"); auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig, audioConfig); auto result = speechSynthesizer->SpeakTextAsync("A simple test to write to a file.").get(); }
Quando si esegue il programma, viene creato un file sintetizzato .wav, scritto nel percorso specificato. Questo risultato è un buon esempio dell'utilizzo più semplice. Si esamini quindi la personalizzazione dell'output e la gestione della risposta di output come flusso in memoria per l'uso di scenari personalizzati.
Sintetizzare l'output dell'altoparlante
Per eseguire l'output vocale sintetizzato nel dispositivo di output attivo corrente, ad esempio un altoparlante, omettere il parametro AudioConfig
durante la creazione dell'istanza SpeechSynthesizer
. Ecco un esempio:
void synthesizeSpeech()
{
auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
auto result = speechSynthesizer->SpeakTextAsync("I'm excited to try text to speech").get();
}
Ottenere un risultato come flusso in memoria
È possibile usare i dati audio risultanti come flusso in memoria anziché scrivere direttamente in un file. Con il flusso in memoria è possibile creare un comportamento personalizzato:
- Astrarre la matrice di byte risultante come flusso ricercabile per i servizi downstream personalizzati.
- Integrare il risultato con altri servizi o API.
- Modificare i dati audio, scrivere intestazioni di .wav personalizzate ed eseguire attività correlate.
È possibile apportare questa modifica all'esempio precedente. Prima rimuovere il blocco AudioConfig
, poiché da questo punto in poi il comportamento di output viene gestito manualmente per un maggior controllo. Passare NULL
per AudioConfig
nel costruttore SpeechSynthesizer
.
Nota
Se si passa NULL
per AudioConfig
, invece di ometterlo come nel precedente esempio di output nell'altoparlante, l'audio non viene riprodotto per impostazione predefinita nel dispositivo di output attivo corrente.
Salvare il risultato in una variabile SpeechSynthesisResult. Il getter GetAudioData
restituisce un'istanza byte []
per i dati di output. Questo oggetto byte []
può essere gestito manualmente oppure è possibile usare la classe AudioDataStream per gestire il flusso in memoria.
In questo esempio si usa la funzione statica AudioDataStream.FromResult()
per ottenere un flusso dal risultato.
void synthesizeSpeech()
{
auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
auto result = speechSynthesizer->SpeakTextAsync("Getting the response as an in-memory stream.").get();
auto stream = AudioDataStream::FromResult(result);
}
A questo punto, è possibile implementare qualsiasi comportamento personalizzato usando l'oggetto stream
risultante.
Personalizzare il formato audio
È possibile personalizzare gli attributi di output audio, tra cui:
- Tipo di file audio
- Frequenza di campionamento
- Profondità di bit
Per cambiare il formato audio, usare la funzione SetSpeechSynthesisOutputFormat()
nell'oggetto SpeechConfig
. Questa funzione prevede un'istanza di enum
di tipo SpeechSynthesisOutputFormat. Usare il enum
per selezionare il formato di output. Per i formati disponili, vedere l’elenco dei formati audio.
Sono disponibili varie opzioni per tipi di file diversi a seconda dei requisiti. Per definizione, i formati non elaborati come Raw24Khz16BitMonoPcm
non includono intestazioni audio. Usare i formati non elaborati solo in una di queste situazioni:
- Si sa che l'implementazione downstream può decodificare un flusso di bit non elaborato.
- Si prevede di compilare manualmente le intestazioni in base a fattori quali profondità bit, frequenza di campionamento e numero di canali.
Questo esempio specifica un formato RIFF ad alta fedeltà Riff24Khz16BitMonoPcm
impostando SpeechSynthesisOutputFormat
nell'oggetto SpeechConfig
. Analogamente all'esempio della sezione precedente, è possibile usare AudioDataStream
per ottenere un flusso in memoria del risultato e quindi scriverlo in un file.
void synthesizeSpeech()
{
auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
speechConfig->SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat::Riff24Khz16BitMonoPcm);
auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
auto result = speechSynthesizer->SpeakTextAsync("A simple test to write to a file.").get();
auto stream = AudioDataStream::FromResult(result);
stream->SaveToWavFileAsync("path/to/write/file.wav").get();
}
Quando si esegue il programma, scrive un file .wav nel percorso specificato.
Usare SSML per personalizzare le caratteristiche vocali
È possibile usare SSML per ottimizzare il tono, la pronuncia, la velocità del parlato, il volume e altri aspetti nell'output della sintesi vocale inviando le richieste da uno schema XML. Questa sezione illustra un esempio di modifica della voce. Per altre informazioni, vedere Panoramica di Speech Synthesis Markup Language.
Per iniziare a usare SSML per la personalizzazione, è necessario apportare una piccola modifica che cambia la voce.
Creare prima di tutto un nuovo file XML per la configurazione di SSML nella directory radice del progetto.
<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US"> <voice name="en-US-AvaMultilingualNeural"> When you're on the freeway, it's a good idea to use a GPS. </voice> </speak>
In questo esempio, file è ssml.xml. L'elemento radice è sempre
<speak>
. Il wrapping del testo in un elemento<voice>
consente di modificare la voce usando il parametroname
. Per l'elenco completo delle voci neurali supportate, vedere Supporto linguistico.Cambiare la richiesta di sintesi vocale in modo che faccia riferimento al file XML. La richiesta è principalmente la stessa. Anziché usare la funzione
SpeakTextAsync()
, si usaSpeakSsmlAsync()
. Questa funzione prevede una stringa XML. Prima di tutto, caricare la configurazione di SSML come stringa. Da qui, l'oggetto risultato è esattamente lo stesso degli esempi precedenti.void synthesizeSpeech() { auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion"); auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig); std::ifstream file("./ssml.xml"); std::string ssml, line; while (std::getline(file, line)) { ssml += line; ssml.push_back('\n'); } auto result = speechSynthesizer->SpeakSsmlAsync(ssml).get(); auto stream = AudioDataStream::FromResult(result); stream->SaveToWavFileAsync("path/to/write/file.wav").get(); }
Nota
Per modificare la voce senza usare SSML, è possibile impostare la proprietà su SpeechConfig
tramite SpeechConfig.SetSpeechSynthesisVoiceName("en-US-AndrewMultilingualNeural")
.
Sottoscrivere eventi di sintetizzatore
È possibile ottenere altre informazioni dettagliate sull'elaborazione del testo e sui risultati del riconoscimento vocale. Ad esempio, è possibile sapere quando il sintetizzatore inizia e si arresta oppure si potrebbe voler conoscere altri eventi rilevati durante la sintesi.
Quando si usa SpeechSynthesizer per la sintesi vocale, è possibile sottoscrivere gli eventi in questa tabella:
Event | Descrizione | Caso d'uso |
---|---|---|
BookmarkReached |
Segnala che è stato raggiunto un segnalibro. Per attivare un evento raggiunto da un segnalibro, è necessario un elemento bookmark nel SSML. Questo evento segnala il tempo trascorso dell'audio di output tra l'inizio della sintesi e l'elemento bookmark . La proprietà dell'evento Text è il valore stringa impostato nell'attributo mark del segnalibro. Gli elementi bookmark non vengono pronunciati. |
È possibile usare l'elemento bookmark per inserire marcatori personalizzati in SSML per ottenere l'offset di ogni marcatore nel flusso audio. L'elemento bookmark può essere usato per fare riferimento a una posizione specifica nella sequenza di testo o tag. |
SynthesisCanceled |
Segnala che la sintesi vocale è stata annullata. | È possibile confermare quando la sintesi è annullata. |
SynthesisCompleted |
Segnala che la sintesi vocale è stata completata. | È possibile confermare quando la sintesi è stata completata. |
SynthesisStarted |
Segnala che la sintesi vocale è stata completata. | È possibile confermare l'avvio della sintesi. |
Synthesizing |
Segnala che la sintesi vocale è in corso. Questo evento viene generato ogni volta che l'SDK riceve un blocco audio dal servizio Voce. | È possibile confermare quando la sintesi è in corso. |
VisemeReceived |
Segnala che è stato ricevuto un evento visema. | I Visemi vengono spesso usati per rappresentare le posizioni chiave nel parlato osservato. Le pose chiave includono la posizione delle labbra, della mascella e della lingua nella produzione di un particolare fonema. È possibile usare visemi per animare il viso di un personaggio durante la riproduzione dell'audio vocale. |
WordBoundary |
Segnala che è stato ricevuto un limite di parola. Questo evento viene generato all'inizio di ogni nuova parola pronunciata, punteggiatura e frase. L'evento segnala l'offset di tempo della parola corrente, in tick, dall'inizio dell'audio di output. Questo evento segnala anche la posizione del carattere nel testo di input o SSML immediatamente prima della parola che sta per essere pronunciata. | Questo evento viene comunemente usato per ottenere posizioni relative del testo e dell'audio corrispondente. Potrebbe essere necessario conoscere una nuova parola e quindi intervenire in base alla tempistica. Ad esempio, è possibile ottenere informazioni che consentono di decidere quando e per quanto tempo evidenziare le parole quando vengono pronunciate. |
Nota
Gli eventi vengono generati man mano che i dati audio di output diventano disponibili, che è più veloce della riproduzione in un dispositivo di output. Il chiamante deve sincronizzare in modo appropriato lo streaming e il tempo reale.
Ecco un esempio che illustra come sottoscrivere eventi per la sintesi vocale.
Importante
Se si usa una chiave API, archiviarla in modo sicuro in un'altra posizione, ad esempio in Azure Key Vault. Non includere la chiave API direttamente nel codice e non esporla mai pubblicamente.
Per altre informazioni sulla sicurezza dei servizi di intelligenza artificiale, vedere Autenticare le richieste a Servizi di Azure AI.
È possibile seguire le istruzioni nella guida introduttiva, ma sostituire il contenuto del file main.cpp con il codice seguente:
#include <iostream>
#include <stdlib.h>
#include <speechapi_cxx.h>
using namespace Microsoft::CognitiveServices::Speech;
using namespace Microsoft::CognitiveServices::Speech::Audio;
std::string getEnvironmentVariable(const char* name);
int main()
{
// This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
auto speechKey = getEnvironmentVariable("SPEECH_KEY");
auto speechRegion = getEnvironmentVariable("SPEECH_REGION");
if ((size(speechKey) == 0) || (size(speechRegion) == 0)) {
std::cout << "Please set both SPEECH_KEY and SPEECH_REGION environment variables." << std::endl;
return -1;
}
auto speechConfig = SpeechConfig::FromSubscription(speechKey, speechRegion);
// Required for WordBoundary event sentences.
speechConfig->SetProperty(PropertyId::SpeechServiceResponse_RequestSentenceBoundary, "true");
const auto ssml = R"(<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
<voice name = 'en-US-AvaMultilingualNeural'>
<mstts:viseme type = 'redlips_front' />
The rainbow has seven colors : <bookmark mark = 'colors_list_begin' />Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark = 'colors_list_end' />.
</voice>
</speak>)";
auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
// Subscribe to events
speechSynthesizer->BookmarkReached += [](const SpeechSynthesisBookmarkEventArgs& e)
{
std::cout << "Bookmark reached. "
<< "\r\n\tAudioOffset: " << round(e.AudioOffset / 10000) << "ms"
<< "\r\n\tText: " << e.Text << std::endl;
};
speechSynthesizer->SynthesisCanceled += [](const SpeechSynthesisEventArgs& e)
{
std::cout << "SynthesisCanceled event" << std::endl;
};
speechSynthesizer->SynthesisCompleted += [](const SpeechSynthesisEventArgs& e)
{
auto audioDuration = std::chrono::duration_cast<std::chrono::milliseconds>(e.Result->AudioDuration).count();
std::cout << "SynthesisCompleted event:"
<< "\r\n\tAudioData: " << e.Result->GetAudioData()->size() << "bytes"
<< "\r\n\tAudioDuration: " << audioDuration << std::endl;
};
speechSynthesizer->SynthesisStarted += [](const SpeechSynthesisEventArgs& e)
{
std::cout << "SynthesisStarted event" << std::endl;
};
speechSynthesizer->Synthesizing += [](const SpeechSynthesisEventArgs& e)
{
std::cout << "Synthesizing event:"
<< "\r\n\tAudioData: " << e.Result->GetAudioData()->size() << "bytes" << std::endl;
};
speechSynthesizer->VisemeReceived += [](const SpeechSynthesisVisemeEventArgs& e)
{
std::cout << "VisemeReceived event:"
<< "\r\n\tAudioOffset: " << round(e.AudioOffset / 10000) << "ms"
<< "\r\n\tVisemeId: " << e.VisemeId << std::endl;
};
speechSynthesizer->WordBoundary += [](const SpeechSynthesisWordBoundaryEventArgs& e)
{
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(e.Duration).count();
auto boundaryType = "";
switch (e.BoundaryType) {
case SpeechSynthesisBoundaryType::Punctuation:
boundaryType = "Punctuation";
break;
case SpeechSynthesisBoundaryType::Sentence:
boundaryType = "Sentence";
break;
case SpeechSynthesisBoundaryType::Word:
boundaryType = "Word";
break;
}
std::cout << "WordBoundary event:"
// Word, Punctuation, or Sentence
<< "\r\n\tBoundaryType: " << boundaryType
<< "\r\n\tAudioOffset: " << round(e.AudioOffset / 10000) << "ms"
<< "\r\n\tDuration: " << duration
<< "\r\n\tText: \"" << e.Text << "\""
<< "\r\n\tTextOffset: " << e.TextOffset
<< "\r\n\tWordLength: " << e.WordLength << std::endl;
};
auto result = speechSynthesizer->SpeakSsmlAsync(ssml).get();
// Checks result.
if (result->Reason == ResultReason::SynthesizingAudioCompleted)
{
std::cout << "SynthesizingAudioCompleted result" << std::endl;
}
else if (result->Reason == ResultReason::Canceled)
{
auto cancellation = SpeechSynthesisCancellationDetails::FromResult(result);
std::cout << "CANCELED: Reason=" << (int)cancellation->Reason << std::endl;
if (cancellation->Reason == CancellationReason::Error)
{
std::cout << "CANCELED: ErrorCode=" << (int)cancellation->ErrorCode << std::endl;
std::cout << "CANCELED: ErrorDetails=[" << cancellation->ErrorDetails << "]" << std::endl;
std::cout << "CANCELED: Did you set the speech resource key and region values?" << std::endl;
}
}
std::cout << "Press enter to exit..." << std::endl;
std::cin.get();
}
std::string getEnvironmentVariable(const char* name)
{
#if defined(_MSC_VER)
size_t requiredSize = 0;
(void)getenv_s(&requiredSize, nullptr, 0, name);
if (requiredSize == 0)
{
return "";
}
auto buffer = std::make_unique<char[]>(requiredSize);
(void)getenv_s(&requiredSize, buffer.get(), requiredSize, name);
return buffer.get();
#else
auto value = getenv(name);
return value ? value : "";
#endif
}
È possibile trovare altri esempi di testo per il riconoscimento vocale in GitHub.
Usare un endpoint personalizzato
Dal punto di vista funzionale, l'endpoint personalizzato è identico all'endpoint standard usato per le richieste di sintesi vocale.
Una differenza è che EndpointId
deve essere specificato per usare la voce personalizzata tramite Speech SDK. È possibile iniziare con l‘avvio rapido della sintesi vocale e quindi aggiornare il codice con EndpointId
e SpeechSynthesisVoiceName
.
auto speechConfig = SpeechConfig::FromSubscription(speechKey, speechRegion);
speechConfig->SetSpeechSynthesisVoiceName("YourCustomVoiceName");
speechConfig->SetEndpointId("YourEndpointId");
Per usare una voce personalizzata tramite Speech Synthesis Markup Language (SSML), specificare il nome del modello come nome della voce. Questo esempio usa la voce YourCustomVoiceName
.
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
<voice name="YourCustomVoiceName">
This is the text that is spoken.
</voice>
</speak>
Eseguire e usare un contenitore
I contenitori del servizio Voce forniscono API di endpoint di query basate su WebSocket a cui si accede tramite Speech SDK e l'interfaccia della riga di comando di Voce. Per impostazione predefinita, l'SDK e l'interfaccia della riga di comando di Voce usano il servizio Voce pubblico. Per usare il contenitore, è necessario modificare il metodo di inizializzazione. Usare un URL host del contenitore invece di chiave e area.
Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori di Voce con Docker.
Documentazione di riferimento | Pacchetto (Go) | Ulteriori esempi in GitHub
In questa guida pratica vengono illustrati i modelli di progettazione comuni per eseguire la sintesi vocale.
Per altre informazioni sulle aree seguenti, vedere Che cos'è la sintesi vocale?
- Recupero di risposte come flussi in memoria.
- Personalizzazione della frequenza di campionamento e della velocità in bit dell'output.
- Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
- Uso di voci neurali.
- Sottoscrizione di eventi e azioni sui risultati.
Prerequisiti
- Una sottoscrizione di Azure. È possibile crearne uno gratuitamente.
- Creare una risorsa Voce nel portale di Azure.
- Ottenere la chiave e l'area della risorsa Voce. Dopo aver distribuito la risorsa Voce, selezionare Vai alla risorsa per visualizzare e gestire le chiavi.
Installare Speech SDK
Prima di poter eseguire qualsiasi operazione, è necessario installare Speech SDK per Go.
Sintesi vocale all’altoparlante
Usare l'esempio di codice seguente per eseguire la sintesi vocale nel dispositivo di output audio predefinito. Sostituire le variabili subscription
e region
con la chiave vocale e la posizione/area. L'esecuzione dello script pronuncia il testo di input all'altoparlante predefinito.
package main
import (
"bufio"
"fmt"
"os"
"strings"
"time"
"github.com/Microsoft/cognitive-services-speech-sdk-go/audio"
"github.com/Microsoft/cognitive-services-speech-sdk-go/common"
"github.com/Microsoft/cognitive-services-speech-sdk-go/speech"
)
func synthesizeStartedHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("Synthesis started.")
}
func synthesizingHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Printf("Synthesizing, audio chunk size %d.\n", len(event.Result.AudioData))
}
func synthesizedHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Printf("Synthesized, audio length %d.\n", len(event.Result.AudioData))
}
func cancelledHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("Received a cancellation.")
}
func main() {
subscription := "YourSpeechKey"
region := "YourSpeechRegion"
audioConfig, err := audio.NewAudioConfigFromDefaultSpeakerOutput()
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer audioConfig.Close()
speechConfig, err := speech.NewSpeechConfigFromSubscription(subscription, region)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechConfig.Close()
speechSynthesizer, err := speech.NewSpeechSynthesizerFromConfig(speechConfig, audioConfig)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechSynthesizer.Close()
speechSynthesizer.SynthesisStarted(synthesizeStartedHandler)
speechSynthesizer.Synthesizing(synthesizingHandler)
speechSynthesizer.SynthesisCompleted(synthesizedHandler)
speechSynthesizer.SynthesisCanceled(cancelledHandler)
for {
fmt.Printf("Enter some text that you want to speak, or enter empty text to exit.\n> ")
text, _ := bufio.NewReader(os.Stdin).ReadString('\n')
text = strings.TrimSuffix(text, "\n")
if len(text) == 0 {
break
}
task := speechSynthesizer.SpeakTextAsync(text)
var outcome speech.SpeechSynthesisOutcome
select {
case outcome = <-task:
case <-time.After(60 * time.Second):
fmt.Println("Timed out")
return
}
defer outcome.Close()
if outcome.Error != nil {
fmt.Println("Got an error: ", outcome.Error)
return
}
if outcome.Result.Reason == common.SynthesizingAudioCompleted {
fmt.Printf("Speech synthesized to speaker for text [%s].\n", text)
} else {
cancellation, _ := speech.NewCancellationDetailsFromSpeechSynthesisResult(outcome.Result)
fmt.Printf("CANCELED: Reason=%d.\n", cancellation.Reason)
if cancellation.Reason == common.Error {
fmt.Printf("CANCELED: ErrorCode=%d\nCANCELED: ErrorDetails=[%s]\nCANCELED: Did you set the speech resource key and region values?\n",
cancellation.ErrorCode,
cancellation.ErrorDetails)
}
}
}
}
Eseguire i comandi seguenti per creare un file go.mod che si collega ai componenti ospitati in GitHub:
go mod init quickstart
go get github.com/Microsoft/cognitive-services-speech-sdk-go
Ora compilare ed eseguire il codice:
go build
go run quickstart
Per informazioni dettagliate sulle classi, vedere la documentazione di riferimento SpeechConfig
e SpeechSynthesizer
.
Sintesi vocale nel flusso in memoria
È possibile usare i dati audio risultanti come flusso in memoria anziché scrivere direttamente in un file. Con il flusso in memoria è possibile creare un comportamento personalizzato:
- Astrarre la matrice di byte risultante come flusso ricercabile per i servizi downstream personalizzati.
- Integrare il risultato con altri servizi o API.
- Modificare i dati audio, scrivere intestazioni di .wav personalizzate ed eseguire attività correlate.
È possibile apportare questa modifica all'esempio precedente. Rimuovere il blocco AudioConfig
, poiché da questo punto in poi il comportamento di output viene gestito manualmente per un maggior controllo. Passare quindi nil
per AudioConfig
nel costruttore SpeechSynthesizer
.
Nota
Se si passa nil
per AudioConfig
, invece di ometterlo come nel precedente esempio di output nell'altoparlante, l'audio non verrà riprodotto per impostazione predefinita nel dispositivo di output attivo corrente.
Salvare il risultato in una variabile SpeechSynthesisResult
. La proprietà AudioData
restituisce un'istanza []byte
per i dati di output. Questo oggetto []byte
può essere gestito manualmente oppure è possibile usare la classe AudioDataStream
per gestire il flusso in memoria.
In questo esempio si usa la funzione statica NewAudioDataStreamFromSpeechSynthesisResult()
per ottenere un flusso dal risultato.
Sostituire le variabili subscription
e region
con la chiave vocale e la posizione/area:
package main
import (
"bufio"
"fmt"
"io"
"os"
"strings"
"time"
"github.com/Microsoft/cognitive-services-speech-sdk-go/speech"
)
func synthesizeStartedHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("Synthesis started.")
}
func synthesizingHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Printf("Synthesizing, audio chunk size %d.\n", len(event.Result.AudioData))
}
func synthesizedHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Printf("Synthesized, audio length %d.\n", len(event.Result.AudioData))
}
func cancelledHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("Received a cancellation.")
}
func main() {
subscription := "YourSpeechKey"
region := "YourSpeechRegion"
speechConfig, err := speech.NewSpeechConfigFromSubscription(subscription, region)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechConfig.Close()
speechSynthesizer, err := speech.NewSpeechSynthesizerFromConfig(speechConfig, nil)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechSynthesizer.Close()
speechSynthesizer.SynthesisStarted(synthesizeStartedHandler)
speechSynthesizer.Synthesizing(synthesizingHandler)
speechSynthesizer.SynthesisCompleted(synthesizedHandler)
speechSynthesizer.SynthesisCanceled(cancelledHandler)
for {
fmt.Printf("Enter some text that you want to speak, or enter empty text to exit.\n> ")
text, _ := bufio.NewReader(os.Stdin).ReadString('\n')
text = strings.TrimSuffix(text, "\n")
if len(text) == 0 {
break
}
// StartSpeakingTextAsync sends the result to channel when the synthesis starts.
task := speechSynthesizer.StartSpeakingTextAsync(text)
var outcome speech.SpeechSynthesisOutcome
select {
case outcome = <-task:
case <-time.After(60 * time.Second):
fmt.Println("Timed out")
return
}
defer outcome.Close()
if outcome.Error != nil {
fmt.Println("Got an error: ", outcome.Error)
return
}
// In most cases, we want to streaming receive the audio to lower the latency.
// We can use AudioDataStream to do so.
stream, err := speech.NewAudioDataStreamFromSpeechSynthesisResult(outcome.Result)
defer stream.Close()
if err != nil {
fmt.Println("Got an error: ", err)
return
}
var all_audio []byte
audio_chunk := make([]byte, 2048)
for {
n, err := stream.Read(audio_chunk)
if err == io.EOF {
break
}
all_audio = append(all_audio, audio_chunk[:n]...)
}
fmt.Printf("Read [%d] bytes from audio data stream.\n", len(all_audio))
}
}
Eseguire i comandi seguenti per creare un file go.mod che si collega ai componenti ospitati in GitHub:
go mod init quickstart
go get github.com/Microsoft/cognitive-services-speech-sdk-go
Ora compilare ed eseguire il codice:
go build
go run quickstart
Per informazioni dettagliate sulle classi, vedere la documentazione di riferimento SpeechConfig
e SpeechSynthesizer
.
Selezionare il linguaggio di sintesi e la voce
La funzionalità sintesi vocale nel servizio Voce supporta più di 400 voci e più di 140 lingue e varianti. È possibile ottenere l'elenco completo o provarle nella Raccolta voci.
Specificare la lingua o la voce di SpeechConfig
perché corrispondano al testo di input e usino la voce specificata:
speechConfig, err := speech.NewSpeechConfigFromSubscription(key, region)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechConfig.Close()
speechConfig.SetSpeechSynthesisLanguage("en-US")
speechConfig.SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural")
Tutte le voci neurali sono multilingue e parlano fluentemente sia la propria lingua che l’inglese. Ad esempio, se il testo di input in inglese è "I'm excited to try text to speech" e si imposta es-ES-ElviraNeural
, il testo viene pronunciato in inglese con un accento spagnolo.
Se la voce non parla la lingua del testo di input, il servizio cognitivo di Azure per la voce non creerà audio sintetizzato. Per un elenco completo delle voci neurali supportate, consultare Lingue e voci supportate per il servizio cognitivo di Azure per la voce.
Nota
La voce predefinita è la prima voce restituita per impostazioni locali dall'API dell'elenco voci.
La voce che parla viene determinata in ordine di priorità come indicato di seguito:
- Se non si imposta
SpeechSynthesisVoiceName
oSpeechSynthesisLanguage
, a parlare sarà la voce predefinita peren-US
. - Se si imposta solo
SpeechSynthesisLanguage
, a parlare sarà la voce predefinita per impostazioni locali specificate. - Se
SpeechSynthesisVoiceName
eSpeechSynthesisLanguage
sono entrambi impostati, l'impostazioneSpeechSynthesisLanguage
verrà ignorata. La voce specificata tramiteSpeechSynthesisVoiceName
sarà quella a parlare. - Se l'elemento voce viene impostato tramite Speech Synthesis Markup Language (SSML), le impostazioni
SpeechSynthesisVoiceName
eSpeechSynthesisLanguage
verranno ignorate.
In sintesi, l'ordine di priorità può essere descritto come segue:
SpeechSynthesisVoiceName |
SpeechSynthesisLanguage |
SSML | Risultato |
---|---|---|---|
✗ | ✗ | ✗ | La voce predefinita per en-US sarà quella a parlare |
✗ | ✔ | ✗ | La voce predefinita per le impostazioni locali specificate sarà quella a parlare. |
✔ | ✔ | ✗ | La voce specificata tramite SpeechSynthesisVoiceName sarà quella a parlare. |
✔ | ✔ | ✔ | La voce specificata tramite SSML sarà quella a parlare. |
Usare SSML per personalizzare le caratteristiche vocali
È possibile usare il linguaggio SSML (Speech Synthesis Markup Language) per ottimizzare il tono, la pronuncia, la velocità del parlato, il volume e altro ancora dell'output della sintesi vocale inviando le richieste da XML Schema. Questa sezione illustra un esempio di modifica della voce. Per altre informazioni, vedere Panoramica di Speech Synthesis Markup Language.
Per iniziare a usare SSML per la personalizzazione, è necessario apportare una piccola modifica che cambia la voce.
Creare prima di tutto un nuovo file XML per la configurazione di SSML nella directory radice del progetto. In questo esempio è ssml.xml
. L'elemento radice è sempre <speak>
. Il wrapping del testo in un elemento <voice>
consente di modificare la voce usando il parametro name
. Per l'elenco completo delle voci neurali supportate, vedere Supporto linguistico.
<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
<voice name="en-US-AvaMultilingualNeural">
When you're on the freeway, it's a good idea to use a GPS.
</voice>
</speak>
Successivamente, è necessario cambiare la richiesta di sintesi vocale in modo che faccia riferimento al file XML. La richiesta è essenzialmente la stessa, ma invece di usare la funzione SpeakTextAsync()
si usa SpeakSsmlAsync()
. Questa funzione prevede una stringa XML, quindi è prima di tutto necessario caricare la configurazione di SSML come stringa usando. Da qui, l'oggetto risultato è esattamente lo stesso degli esempi precedenti.
Nota
Per impostare la voce senza usare SSML, è possibile impostare la proprietà su SpeechConfig
tramite speechConfig.SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural")
.
Sottoscrivere eventi di sintetizzatore
È possibile ottenere altre informazioni dettagliate sull'elaborazione del testo e sui risultati del riconoscimento vocale. Ad esempio, è possibile sapere quando il sintetizzatore inizia e si arresta oppure si potrebbe voler conoscere altri eventi rilevati durante la sintesi.
Quando si usa SpeechSynthesizer per la sintesi vocale, è possibile sottoscrivere gli eventi in questa tabella:
Event | Descrizione | Caso d'uso |
---|---|---|
BookmarkReached |
Segnala che è stato raggiunto un segnalibro. Per attivare un evento raggiunto da un segnalibro, è necessario un elemento bookmark nel SSML. Questo evento segnala il tempo trascorso dell'audio di output tra l'inizio della sintesi e l'elemento bookmark . La proprietà dell'evento Text è il valore stringa impostato nell'attributo mark del segnalibro. Gli elementi bookmark non vengono pronunciati. |
È possibile usare l'elemento bookmark per inserire marcatori personalizzati in SSML per ottenere l'offset di ogni marcatore nel flusso audio. L'elemento bookmark può essere usato per fare riferimento a una posizione specifica nella sequenza di testo o tag. |
SynthesisCanceled |
Segnala che la sintesi vocale è stata annullata. | È possibile confermare quando la sintesi è annullata. |
SynthesisCompleted |
Segnala che la sintesi vocale è stata completata. | È possibile confermare quando la sintesi è stata completata. |
SynthesisStarted |
Segnala che la sintesi vocale è stata completata. | È possibile confermare l'avvio della sintesi. |
Synthesizing |
Segnala che la sintesi vocale è in corso. Questo evento viene generato ogni volta che l'SDK riceve un blocco audio dal servizio Voce. | È possibile confermare quando la sintesi è in corso. |
VisemeReceived |
Segnala che è stato ricevuto un evento visema. | I Visemi vengono spesso usati per rappresentare le posizioni chiave nel parlato osservato. Le pose chiave includono la posizione delle labbra, della mascella e della lingua nella produzione di un particolare fonema. È possibile usare visemi per animare il viso di un personaggio durante la riproduzione dell'audio vocale. |
WordBoundary |
Segnala che è stato ricevuto un limite di parola. Questo evento viene generato all'inizio di ogni nuova parola pronunciata, punteggiatura e frase. L'evento segnala l'offset di tempo della parola corrente, in tick, dall'inizio dell'audio di output. Questo evento segnala anche la posizione del carattere nel testo di input o SSML immediatamente prima della parola che sta per essere pronunciata. | Questo evento viene comunemente usato per ottenere posizioni relative del testo e dell'audio corrispondente. Potrebbe essere necessario conoscere una nuova parola e quindi intervenire in base alla tempistica. Ad esempio, è possibile ottenere informazioni che consentono di decidere quando e per quanto tempo evidenziare le parole quando vengono pronunciate. |
Nota
Gli eventi vengono generati man mano che i dati audio di output diventano disponibili, che è più veloce della riproduzione in un dispositivo di output. Il chiamante deve sincronizzare in modo appropriato lo streaming e il tempo reale.
Ecco un esempio che illustra come sottoscrivere eventi per la sintesi vocale.
Importante
Se si usa una chiave API, archiviarla in modo sicuro in un'altra posizione, ad esempio in Azure Key Vault. Non includere la chiave API direttamente nel codice e non esporla mai pubblicamente.
Per altre informazioni sulla sicurezza dei servizi di intelligenza artificiale, vedere Autenticare le richieste a Servizi di Azure AI.
È possibile seguire le istruzioni nella guida introduttiva, ma sostituire il contenuto del file speech-synthesis.go
con il codice Go seguente:
package main
import (
"fmt"
"os"
"time"
"github.com/Microsoft/cognitive-services-speech-sdk-go/audio"
"github.com/Microsoft/cognitive-services-speech-sdk-go/common"
"github.com/Microsoft/cognitive-services-speech-sdk-go/speech"
)
func bookmarkReachedHandler(event speech.SpeechSynthesisBookmarkEventArgs) {
defer event.Close()
fmt.Println("BookmarkReached event")
}
func synthesisCanceledHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("SynthesisCanceled event")
}
func synthesisCompletedHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("SynthesisCompleted event")
fmt.Printf("\tAudioData: %d bytes\n", len(event.Result.AudioData))
fmt.Printf("\tAudioDuration: %d\n", event.Result.AudioDuration)
}
func synthesisStartedHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("SynthesisStarted event")
}
func synthesizingHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("Synthesizing event")
fmt.Printf("\tAudioData %d bytes\n", len(event.Result.AudioData))
}
func visemeReceivedHandler(event speech.SpeechSynthesisVisemeEventArgs) {
defer event.Close()
fmt.Println("VisemeReceived event")
fmt.Printf("\tAudioOffset: %dms\n", (event.AudioOffset+5000)/10000)
fmt.Printf("\tVisemeID %d\n", event.VisemeID)
}
func wordBoundaryHandler(event speech.SpeechSynthesisWordBoundaryEventArgs) {
defer event.Close()
boundaryType := ""
switch event.BoundaryType {
case 0:
boundaryType = "Word"
case 1:
boundaryType = "Punctuation"
case 2:
boundaryType = "Sentence"
}
fmt.Println("WordBoundary event")
fmt.Printf("\tBoundaryType %v\n", boundaryType)
fmt.Printf("\tAudioOffset: %dms\n", (event.AudioOffset+5000)/10000)
fmt.Printf("\tDuration %d\n", event.Duration)
fmt.Printf("\tText %s\n", event.Text)
fmt.Printf("\tTextOffset %d\n", event.TextOffset)
fmt.Printf("\tWordLength %d\n", event.WordLength)
}
func main() {
// This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
speechKey := os.Getenv("SPEECH_KEY")
speechRegion := os.Getenv("SPEECH_REGION")
audioConfig, err := audio.NewAudioConfigFromDefaultSpeakerOutput()
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer audioConfig.Close()
speechConfig, err := speech.NewSpeechConfigFromSubscription(speechKey, speechRegion)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechConfig.Close()
// Required for WordBoundary event sentences.
speechConfig.SetProperty(common.SpeechServiceResponseRequestSentenceBoundary, "true")
speechSynthesizer, err := speech.NewSpeechSynthesizerFromConfig(speechConfig, audioConfig)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechSynthesizer.Close()
speechSynthesizer.BookmarkReached(bookmarkReachedHandler)
speechSynthesizer.SynthesisCanceled(synthesisCanceledHandler)
speechSynthesizer.SynthesisCompleted(synthesisCompletedHandler)
speechSynthesizer.SynthesisStarted(synthesisStartedHandler)
speechSynthesizer.Synthesizing(synthesizingHandler)
speechSynthesizer.VisemeReceived(visemeReceivedHandler)
speechSynthesizer.WordBoundary(wordBoundaryHandler)
speechSynthesisVoiceName := "en-US-AvaMultilingualNeural"
ssml := fmt.Sprintf(`<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
<voice name='%s'>
<mstts:viseme type='redlips_front'/>
The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.
</voice>
</speak>`, speechSynthesisVoiceName)
// Synthesize the SSML
fmt.Printf("SSML to synthesize: \n\t%s\n", ssml)
task := speechSynthesizer.SpeakSsmlAsync(ssml)
var outcome speech.SpeechSynthesisOutcome
select {
case outcome = <-task:
case <-time.After(60 * time.Second):
fmt.Println("Timed out")
return
}
defer outcome.Close()
if outcome.Error != nil {
fmt.Println("Got an error: ", outcome.Error)
return
}
if outcome.Result.Reason == common.SynthesizingAudioCompleted {
fmt.Println("SynthesizingAudioCompleted result")
} else {
cancellation, _ := speech.NewCancellationDetailsFromSpeechSynthesisResult(outcome.Result)
fmt.Printf("CANCELED: Reason=%d.\n", cancellation.Reason)
if cancellation.Reason == common.Error {
fmt.Printf("CANCELED: ErrorCode=%d\nCANCELED: ErrorDetails=[%s]\nCANCELED: Did you set the speech resource key and region values?\n",
cancellation.ErrorCode,
cancellation.ErrorDetails)
}
}
}
È possibile trovare altri esempi di testo per il riconoscimento vocale in GitHub.
Eseguire e usare un contenitore
I contenitori del servizio Voce forniscono API di endpoint di query basate su WebSocket a cui si accede tramite Speech SDK e l'interfaccia della riga di comando di Voce. Per impostazione predefinita, l'SDK e l'interfaccia della riga di comando di Voce usano il servizio Voce pubblico. Per usare il contenitore, è necessario modificare il metodo di inizializzazione. Usare un URL host del contenitore invece di chiave e area.
Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori di Voce con Docker.
Documentazione di riferimento | Ulteriori esempi in GitHub
In questa guida pratica vengono illustrati i modelli di progettazione comuni per eseguire la sintesi vocale.
Per altre informazioni sulle aree seguenti, vedere Che cos'è la sintesi vocale?
- Recupero di risposte come flussi in memoria.
- Personalizzazione della frequenza di campionamento e della velocità in bit dell'output.
- Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
- Uso di voci neurali.
- Sottoscrizione di eventi e azioni sui risultati.
Selezionare il linguaggio di sintesi e la voce
La funzionalità sintesi vocale nel servizio Voce supporta più di 400 voci e più di 140 lingue e varianti. È possibile ottenere l'elenco completo o provarle nella Raccolta voci.
Specificare la lingua o la voce SpeechConfig perché corrispondano al testo di input e usino la voce specificata. Il seguente frammento di codice illustra il funzionamento di questa tecnica:
public static void main(String[] args) {
SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
// Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
speechConfig.setSpeechSynthesisLanguage("en-US");
speechConfig.setSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");
}
Tutte le voci neurali sono multilingue e parlano fluentemente sia la propria lingua che l’inglese. Ad esempio, se il testo di input in inglese è "I'm excited to try text to speech" e si imposta es-ES-ElviraNeural
, il testo viene pronunciato in inglese con un accento spagnolo.
Se la voce non parla la lingua del testo di input, il servizio cognitivo di Azure per la voce non creerà audio sintetizzato. Per un elenco completo delle voci neurali supportate, consultare Lingue e voci supportate per il servizio cognitivo di Azure per la voce.
Nota
La voce predefinita è la prima voce restituita per impostazioni locali dall'API dell'elenco voci.
La voce che parla viene determinata in ordine di priorità come indicato di seguito:
- Se non si imposta
SpeechSynthesisVoiceName
oSpeechSynthesisLanguage
, a parlare sarà la voce predefinita peren-US
. - Se si imposta solo
SpeechSynthesisLanguage
, a parlare sarà la voce predefinita per impostazioni locali specificate. - Se
SpeechSynthesisVoiceName
eSpeechSynthesisLanguage
sono entrambi impostati, l'impostazioneSpeechSynthesisLanguage
verrà ignorata. La voce specificata tramiteSpeechSynthesisVoiceName
sarà quella a parlare. - Se l'elemento voce viene impostato tramite Speech Synthesis Markup Language (SSML), le impostazioni
SpeechSynthesisVoiceName
eSpeechSynthesisLanguage
verranno ignorate.
In sintesi, l'ordine di priorità può essere descritto come segue:
SpeechSynthesisVoiceName |
SpeechSynthesisLanguage |
SSML | Risultato |
---|---|---|---|
✗ | ✗ | ✗ | La voce predefinita per en-US sarà quella a parlare |
✗ | ✔ | ✗ | La voce predefinita per le impostazioni locali specificate sarà quella a parlare. |
✔ | ✔ | ✗ | La voce specificata tramite SpeechSynthesisVoiceName sarà quella a parlare. |
✔ | ✔ | ✔ | La voce specificata tramite SSML sarà quella a parlare. |
Sintetizzare la voce in un file
Creare un oggetto SpeechSynthesizer
. Questo oggetto esegue le conversioni di sintesi vocale e invia l’output ad altoparlanti, file o altri flussi di output. SpeechSynthesizer
accetta come parametri:
- Oggetto
SpeechConfig
creato nel passaggio precedente. - Oggetto
AudioConfig
che specifica la modalità di gestione dei risultati di output.
Creare un'istanza
AudioConfig
per scrivere automaticamente l'output in un file .wav usando la funzione staticafromWavFileOutput()
:public static void main(String[] args) { SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion"); AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav"); }
Creare un'istanza di
SpeechSynthesizer
. Passare l'oggettospeechConfig
e l'oggettoaudioConfig
come parametri. Per sintetizzare il parlato e scrivere in un file, eseguireSpeakText()
con una stringa di testo.public static void main(String[] args) { SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion"); AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav"); SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig); speechSynthesizer.SpeakText("I'm excited to try text to speech"); }
Quando si esegue il programma, viene creato un file sintetizzato .wav, scritto nel percorso specificato. Questo risultato è un buon esempio dell'utilizzo più semplice. Si esamini quindi la personalizzazione dell'output e la gestione della risposta di output come flusso in memoria per l'uso di scenari personalizzati.
Sintetizzare l'output dell'altoparlante
È possibile ottenere altre informazioni dettagliate sull'elaborazione del testo e sui risultati del riconoscimento vocale. Ad esempio, è possibile sapere quando il sintetizzatore inizia e si arresta oppure si potrebbe voler conoscere altri eventi rilevati durante la sintesi.
Per eseguire l'output vocale sintetizzato nel dispositivo di output attivo corrente, ad esempio un altoparlante, creare un'istanza AudioConfig
usando la funzione statica fromDefaultSpeakerOutput()
. Ecco un esempio:
public static void main(String[] args) {
SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
AudioConfig audioConfig = AudioConfig.fromDefaultSpeakerOutput();
SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
speechSynthesizer.SpeakText("I'm excited to try text to speech");
}
Ottenere un risultato come flusso in memoria
È possibile usare i dati audio risultanti come flusso in memoria anziché scrivere direttamente in un file. Con il flusso in memoria è possibile creare un comportamento personalizzato:
- Astrarre la matrice di byte risultante come flusso ricercabile per i servizi downstream personalizzati.
- Integrare il risultato con altri servizi o API.
- Modificare i dati audio, scrivere intestazioni di .wav personalizzate ed eseguire attività correlate.
È possibile apportare questa modifica all'esempio precedente. Prima rimuovere il blocco AudioConfig
, poiché da questo punto in poi il comportamento di output viene gestito manualmente per un maggior controllo. Passare quindi null
per AudioConfig
nel costruttore SpeechSynthesizer
.
Nota
Se si passa null
per AudioConfig
, invece di ometterlo come nel precedente esempio di output nell'altoparlante, l'audio non viene riprodotto per impostazione predefinita nel dispositivo di output attivo corrente.
Salvare il risultato in una variabile SpeechSynthesisResult
. La funzione SpeechSynthesisResult.getAudioData()
restituisce un'istanza byte []
dei dati di output. Questo oggetto byte []
può essere gestito manualmente oppure è possibile usare la classe AudioDataStream
per gestire il flusso in memoria.
In questo esempio si usa la funzione statica AudioDataStream.fromResult()
per ottenere un flusso dal risultato.
public static void main(String[] args) {
SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
SpeechSynthesisResult result = speechSynthesizer.SpeakText("I'm excited to try text to speech");
AudioDataStream stream = AudioDataStream.fromResult(result);
System.out.print(stream.getStatus());
}
A questo punto, è possibile implementare qualsiasi comportamento personalizzato usando l'oggetto stream
risultante.
Personalizzare il formato audio
È possibile personalizzare gli attributi di output audio, tra cui:
- Tipo di file audio
- Frequenza di campionamento
- Profondità di bit
Per cambiare il formato audio, usare la funzione setSpeechSynthesisOutputFormat()
nell'oggetto SpeechConfig
. Questa funzione prevede un'istanza di enum
di tipo SpeechSynthesisOutputFormat. Usare il enum
per selezionare il formato di output. Per i formati disponili, vedere l’elenco dei formati audio.
Sono disponibili varie opzioni per tipi di file diversi a seconda dei requisiti. Per definizione, i formati non elaborati come Raw24Khz16BitMonoPcm
non includono intestazioni audio. Usare i formati non elaborati solo in una di queste situazioni:
- Si sa che l'implementazione downstream può decodificare un flusso di bit non elaborato.
- Si prevede di compilare manualmente le intestazioni in base a fattori quali profondità bit, frequenza di campionamento e numero di canali.
Questo esempio specifica un formato RIFF ad alta fedeltà Riff24Khz16BitMonoPcm
impostando SpeechSynthesisOutputFormat
nell'oggetto SpeechConfig
. Analogamente all'esempio della sezione precedente, è possibile usare AudioDataStream
per ottenere un flusso in memoria del risultato e quindi scriverlo in un file.
public static void main(String[] args) {
SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
// set the output format
speechConfig.setSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm);
SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
SpeechSynthesisResult result = speechSynthesizer.SpeakText("I'm excited to try text to speech");
AudioDataStream stream = AudioDataStream.fromResult(result);
stream.saveToWavFile("path/to/write/file.wav");
}
Quando si esegue il programma, scrive un file .wav nel percorso specificato.
Usare SSML per personalizzare le caratteristiche vocali
È possibile usare SSML per ottimizzare il tono, la pronuncia, la velocità del parlato, il volume e altri aspetti nell'output della sintesi vocale inviando le richieste da uno schema XML. Questa sezione illustra un esempio di modifica della voce. Per altre informazioni, vedere l'articolo Procedura SSML:
Per iniziare a usare SSML per la personalizzazione, è necessario apportare una piccola modifica che cambia la voce.
Creare prima di tutto un nuovo file XML per la configurazione di SSML nella directory radice del progetto.
<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US"> <voice name="en-US-AvaMultilingualNeural"> When you're on the freeway, it's a good idea to use a GPS. </voice> </speak>
In questo esempio, file è ssml.xml. L'elemento radice è sempre
<speak>
. Il wrapping del testo in un elemento<voice>
consente di modificare la voce usando il parametroname
. Per l'elenco completo delle voci neurali supportate, vedere Supporto linguistico.Cambiare la richiesta di sintesi vocale in modo che faccia riferimento al file XML. La richiesta è principalmente la stessa. Anziché usare la funzione
SpeakText()
, si usaSpeakSsml()
. Questa funzione prevede una stringa XML, quindi creare prima di tutto una funzione per caricare un file XML e restituirlo come stringa:private static String xmlToString(String filePath) { File file = new File(filePath); StringBuilder fileContents = new StringBuilder((int)file.length()); try (Scanner scanner = new Scanner(file)) { while(scanner.hasNextLine()) { fileContents.append(scanner.nextLine() + System.lineSeparator()); } return fileContents.toString().trim(); } catch (FileNotFoundException ex) { return "File not found."; } }
A questo punto, l'oggetto risultante è esattamente lo stesso degli esempi precedenti:
public static void main(String[] args) { SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion"); SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, null); String ssml = xmlToString("ssml.xml"); SpeechSynthesisResult result = speechSynthesizer.SpeakSsml(ssml); AudioDataStream stream = AudioDataStream.fromResult(result); stream.saveToWavFile("path/to/write/file.wav"); }
Nota
Per modificare la voce senza usare SSML, impostare la proprietà su SpeechConfig
tramite SpeechConfig.setSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");
.
Sottoscrivere eventi di sintetizzatore
È possibile ottenere altre informazioni dettagliate sull'elaborazione del testo e sui risultati del riconoscimento vocale. Ad esempio, è possibile sapere quando il sintetizzatore inizia e si arresta oppure si potrebbe voler conoscere altri eventi rilevati durante la sintesi.
Quando si usa SpeechSynthesizer per la sintesi vocale, è possibile sottoscrivere gli eventi in questa tabella:
Event | Descrizione | Caso d'uso |
---|---|---|
BookmarkReached |
Segnala che è stato raggiunto un segnalibro. Per attivare un evento raggiunto da un segnalibro, è necessario un elemento bookmark nel SSML. Questo evento segnala il tempo trascorso dell'audio di output tra l'inizio della sintesi e l'elemento bookmark . La proprietà dell'evento Text è il valore stringa impostato nell'attributo mark del segnalibro. Gli elementi bookmark non vengono pronunciati. |
È possibile usare l'elemento bookmark per inserire marcatori personalizzati in SSML per ottenere l'offset di ogni marcatore nel flusso audio. L'elemento bookmark può essere usato per fare riferimento a una posizione specifica nella sequenza di testo o tag. |
SynthesisCanceled |
Segnala che la sintesi vocale è stata annullata. | È possibile confermare quando la sintesi è annullata. |
SynthesisCompleted |
Segnala che la sintesi vocale è stata completata. | È possibile confermare quando la sintesi è stata completata. |
SynthesisStarted |
Segnala che la sintesi vocale è stata completata. | È possibile confermare l'avvio della sintesi. |
Synthesizing |
Segnala che la sintesi vocale è in corso. Questo evento viene generato ogni volta che l'SDK riceve un blocco audio dal servizio Voce. | È possibile confermare quando la sintesi è in corso. |
VisemeReceived |
Segnala che è stato ricevuto un evento visema. | I Visemi vengono spesso usati per rappresentare le posizioni chiave nel parlato osservato. Le pose chiave includono la posizione delle labbra, della mascella e della lingua nella produzione di un particolare fonema. È possibile usare visemi per animare il viso di un personaggio durante la riproduzione dell'audio vocale. |
WordBoundary |
Segnala che è stato ricevuto un limite di parola. Questo evento viene generato all'inizio di ogni nuova parola pronunciata, punteggiatura e frase. L'evento segnala l'offset di tempo della parola corrente, in tick, dall'inizio dell'audio di output. Questo evento segnala anche la posizione del carattere nel testo di input o SSML immediatamente prima della parola che sta per essere pronunciata. | Questo evento viene comunemente usato per ottenere posizioni relative del testo e dell'audio corrispondente. Potrebbe essere necessario conoscere una nuova parola e quindi intervenire in base alla tempistica. Ad esempio, è possibile ottenere informazioni che consentono di decidere quando e per quanto tempo evidenziare le parole quando vengono pronunciate. |
Nota
Gli eventi vengono generati man mano che i dati audio di output diventano disponibili, che è più veloce della riproduzione in un dispositivo di output. Il chiamante deve sincronizzare in modo appropriato lo streaming e il tempo reale.
Ecco un esempio che illustra come sottoscrivere eventi per la sintesi vocale.
Importante
Se si usa una chiave API, archiviarla in modo sicuro in un'altra posizione, ad esempio in Azure Key Vault. Non includere la chiave API direttamente nel codice e non esporla mai pubblicamente.
Per altre informazioni sulla sicurezza dei servizi di intelligenza artificiale, vedere Autenticare le richieste a Servizi di Azure AI.
È possibile seguire le istruzioni nella guida introduttiva, ma sostituire il contenuto del file SpeechSynthesis.java con il codice Java seguente.
import com.microsoft.cognitiveservices.speech.*;
import com.microsoft.cognitiveservices.speech.audio.*;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
public class SpeechSynthesis {
// This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
private static String speechKey = System.getenv("SPEECH_KEY");
private static String speechRegion = System.getenv("SPEECH_REGION");
public static void main(String[] args) throws InterruptedException, ExecutionException {
SpeechConfig speechConfig = SpeechConfig.fromSubscription(speechKey, speechRegion);
// Required for WordBoundary event sentences.
speechConfig.setProperty(PropertyId.SpeechServiceResponse_RequestSentenceBoundary, "true");
String speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
String ssml = String.format("<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>"
.concat(String.format("<voice name='%s'>", speechSynthesisVoiceName))
.concat("<mstts:viseme type='redlips_front'/>")
.concat("The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.")
.concat("</voice>")
.concat("</speak>"));
SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig);
{
// Subscribe to events
speechSynthesizer.BookmarkReached.addEventListener((o, e) -> {
System.out.println("BookmarkReached event:");
System.out.println("\tAudioOffset: " + ((e.getAudioOffset() + 5000) / 10000) + "ms");
System.out.println("\tText: " + e.getText());
});
speechSynthesizer.SynthesisCanceled.addEventListener((o, e) -> {
System.out.println("SynthesisCanceled event");
});
speechSynthesizer.SynthesisCompleted.addEventListener((o, e) -> {
SpeechSynthesisResult result = e.getResult();
byte[] audioData = result.getAudioData();
System.out.println("SynthesisCompleted event:");
System.out.println("\tAudioData: " + audioData.length + " bytes");
System.out.println("\tAudioDuration: " + result.getAudioDuration());
result.close();
});
speechSynthesizer.SynthesisStarted.addEventListener((o, e) -> {
System.out.println("SynthesisStarted event");
});
speechSynthesizer.Synthesizing.addEventListener((o, e) -> {
SpeechSynthesisResult result = e.getResult();
byte[] audioData = result.getAudioData();
System.out.println("Synthesizing event:");
System.out.println("\tAudioData: " + audioData.length + " bytes");
result.close();
});
speechSynthesizer.VisemeReceived.addEventListener((o, e) -> {
System.out.println("VisemeReceived event:");
System.out.println("\tAudioOffset: " + ((e.getAudioOffset() + 5000) / 10000) + "ms");
System.out.println("\tVisemeId: " + e.getVisemeId());
});
speechSynthesizer.WordBoundary.addEventListener((o, e) -> {
System.out.println("WordBoundary event:");
System.out.println("\tBoundaryType: " + e.getBoundaryType());
System.out.println("\tAudioOffset: " + ((e.getAudioOffset() + 5000) / 10000) + "ms");
System.out.println("\tDuration: " + e.getDuration());
System.out.println("\tText: " + e.getText());
System.out.println("\tTextOffset: " + e.getTextOffset());
System.out.println("\tWordLength: " + e.getWordLength());
});
// Synthesize the SSML
System.out.println("SSML to synthesize:");
System.out.println(ssml);
SpeechSynthesisResult speechSynthesisResult = speechSynthesizer.SpeakSsmlAsync(ssml).get();
if (speechSynthesisResult.getReason() == ResultReason.SynthesizingAudioCompleted) {
System.out.println("SynthesizingAudioCompleted result");
}
else if (speechSynthesisResult.getReason() == ResultReason.Canceled) {
SpeechSynthesisCancellationDetails cancellation = SpeechSynthesisCancellationDetails.fromResult(speechSynthesisResult);
System.out.println("CANCELED: Reason=" + cancellation.getReason());
if (cancellation.getReason() == CancellationReason.Error) {
System.out.println("CANCELED: ErrorCode=" + cancellation.getErrorCode());
System.out.println("CANCELED: ErrorDetails=" + cancellation.getErrorDetails());
System.out.println("CANCELED: Did you set the speech resource key and region values?");
}
}
}
speechSynthesizer.close();
System.exit(0);
}
}
È possibile trovare altri esempi di testo per il riconoscimento vocale in GitHub.
Usare un endpoint personalizzato
Dal punto di vista funzionale, l'endpoint personalizzato è identico all'endpoint standard usato per le richieste di sintesi vocale.
Una differenza è che EndpointId
deve essere specificato per usare la voce personalizzata tramite Speech SDK. È possibile iniziare con l‘avvio rapido della sintesi vocale e quindi aggiornare il codice con EndpointId
e SpeechSynthesisVoiceName
.
SpeechConfig speechConfig = SpeechConfig.fromSubscription(speechKey, speechRegion);
speechConfig.setSpeechSynthesisVoiceName("YourCustomVoiceName");
speechConfig.setEndpointId("YourEndpointId");
Per usare una voce personalizzata tramite Speech Synthesis Markup Language (SSML), specificare il nome del modello come nome della voce. Questo esempio usa la voce YourCustomVoiceName
.
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
<voice name="YourCustomVoiceName">
This is the text that is spoken.
</voice>
</speak>
Eseguire e usare un contenitore
I contenitori del servizio Voce forniscono API di endpoint di query basate su WebSocket a cui si accede tramite Speech SDK e l'interfaccia della riga di comando di Voce. Per impostazione predefinita, l'SDK e l'interfaccia della riga di comando di Voce usano il servizio Voce pubblico. Per usare il contenitore, è necessario modificare il metodo di inizializzazione. Usare un URL host del contenitore invece di chiave e area.
Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori di Voce con Docker.
Documentazione di riferimento | Pacchetto (npm) | Ulteriori esempi in GitHub | Codice sorgente della libreria
In questa guida pratica vengono illustrati i modelli di progettazione comuni per eseguire la sintesi vocale.
Per altre informazioni sulle aree seguenti, vedere Che cos'è la sintesi vocale?
- Recupero di risposte come flussi in memoria.
- Personalizzazione della frequenza di campionamento e della velocità in bit dell'output.
- Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
- Uso di voci neurali.
- Sottoscrizione di eventi e azioni sui risultati.
Selezionare il linguaggio di sintesi e la voce
La funzionalità sintesi vocale nel servizio Voce supporta più di 400 voci e più di 140 lingue e varianti. È possibile ottenere l'elenco completo o provarle nella Raccolta voci.
Specificare la lingua o la voce di SpeechConfig
perché corrispondano al testo di input e usino la voce specificata:
function synthesizeSpeech() {
const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
// Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
speechConfig.speechSynthesisLanguage = "en-US";
speechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
}
synthesizeSpeech();
Tutte le voci neurali sono multilingue e parlano fluentemente sia la propria lingua che l’inglese. Ad esempio, se il testo di input in inglese è "I'm excited to try text to speech" e si imposta es-ES-ElviraNeural
, il testo viene pronunciato in inglese con un accento spagnolo.
Se la voce non parla la lingua del testo di input, il servizio cognitivo di Azure per la voce non creerà audio sintetizzato. Per un elenco completo delle voci neurali supportate, consultare Lingue e voci supportate per il servizio cognitivo di Azure per la voce.
Nota
La voce predefinita è la prima voce restituita per impostazioni locali dall'API dell'elenco voci.
La voce che parla viene determinata in ordine di priorità come indicato di seguito:
- Se non si imposta
SpeechSynthesisVoiceName
oSpeechSynthesisLanguage
, a parlare sarà la voce predefinita peren-US
. - Se si imposta solo
SpeechSynthesisLanguage
, a parlare sarà la voce predefinita per impostazioni locali specificate. - Se
SpeechSynthesisVoiceName
eSpeechSynthesisLanguage
sono entrambi impostati, l'impostazioneSpeechSynthesisLanguage
verrà ignorata. La voce specificata tramiteSpeechSynthesisVoiceName
sarà quella a parlare. - Se l'elemento voce viene impostato tramite Speech Synthesis Markup Language (SSML), le impostazioni
SpeechSynthesisVoiceName
eSpeechSynthesisLanguage
verranno ignorate.
In sintesi, l'ordine di priorità può essere descritto come segue:
SpeechSynthesisVoiceName |
SpeechSynthesisLanguage |
SSML | Risultato |
---|---|---|---|
✗ | ✗ | ✗ | La voce predefinita per en-US sarà quella a parlare |
✗ | ✔ | ✗ | La voce predefinita per le impostazioni locali specificate sarà quella a parlare. |
✔ | ✔ | ✗ | La voce specificata tramite SpeechSynthesisVoiceName sarà quella a parlare. |
✔ | ✔ | ✔ | La voce specificata tramite SSML sarà quella a parlare. |
Eseguire la sintesi vocale
Per eseguire l'output vocale sintetizzato nel dispositivo di output attivo corrente, ad esempio un altoparlante, creare un'istanza AudioConfig
usando la funzione statica fromDefaultSpeakerOutput()
. Ecco un esempio:
function synthesizeSpeech() {
const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
const audioConfig = sdk.AudioConfig.fromDefaultSpeakerOutput();
const speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
speechSynthesizer.speakTextAsync(
"I'm excited to try text to speech",
result => {
if (result) {
speechSynthesizer.close();
return result.audioData;
}
},
error => {
console.log(error);
speechSynthesizer.close();
});
}
Quando si esegue il programma, un audio sintetizzato viene riprodotto dall'altoparlante. Questo risultato è un buon esempio dell'utilizzo più semplice. Si esamini quindi la personalizzazione dell'output e la gestione della risposta di output come flusso in memoria per l'uso di scenari personalizzati.
Ottenere un risultato come flusso in memoria
È possibile usare i dati audio risultanti come flusso in memoria anziché scrivere direttamente in un file. Con il flusso in memoria è possibile creare un comportamento personalizzato:
- Astrarre la matrice di byte risultante come flusso ricercabile per i servizi downstream personalizzati.
- Integrare il risultato con altri servizi o API.
- Modificare i dati audio, scrivere intestazioni
.wav
personalizzate ed eseguire attività correlate.
È possibile apportare questa modifica all'esempio precedente. Rimuovere il blocco AudioConfig
, poiché da questo punto in poi il comportamento di output viene gestito manualmente per un maggior controllo. Passare quindi null
per AudioConfig
nel costruttore SpeechSynthesizer
.
Nota
Se si passa null
per AudioConfig
, invece di ometterlo come nel precedente esempio di output nell'altoparlante, l'audio non viene riprodotto per impostazione predefinita nel dispositivo di output attivo corrente.
Salvare il risultato in una variabile SpeechSynthesisResult. La proprietà SpeechSynthesisResult.audioData
restituisce un valore ArrayBuffer
dei dati di output, il tipo di flusso del browser predefinito. Per il codice lato server, eseguire la conversione di ArrayBuffer
in un flusso di buffer.
Il codice seguente funziona per il lato client:
function synthesizeSpeech() {
const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig);
speechSynthesizer.speakTextAsync(
"I'm excited to try text to speech",
result => {
speechSynthesizer.close();
return result.audioData;
},
error => {
console.log(error);
speechSynthesizer.close();
});
}
È possibile implementare qualsiasi comportamento personalizzato usando l'oggetto ArrayBuffer
risultante. ArrayBuffer
è un tipo comune da ricevere in un browser e riprodurre da questo formato.
Per qualsiasi codice basato su server, se è necessario usare i dati come flusso, è necessario convertire l'oggetto ArrayBuffer
in un flusso:
function synthesizeSpeech() {
const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig);
speechSynthesizer.speakTextAsync(
"I'm excited to try text to speech",
result => {
const { audioData } = result;
speechSynthesizer.close();
// convert arrayBuffer to stream
// return stream
const bufferStream = new PassThrough();
bufferStream.end(Buffer.from(audioData));
return bufferStream;
},
error => {
console.log(error);
speechSynthesizer.close();
});
}
Personalizzare il formato audio
È possibile personalizzare gli attributi di output audio, tra cui:
- Tipo di file audio
- Frequenza di campionamento
- Profondità di bit
Per cambiare il formato audio, usare la proprietà speechSynthesisOutputFormat
nell'oggetto SpeechConfig
. Questa proprietà prevede un'istanza di enum
di tipo SpeechSynthesisOutputFormat. Usare il enum
per selezionare il formato di output. Per i formati disponili, vedere l’elenco dei formati audio.
Sono disponibili varie opzioni per tipi di file diversi a seconda dei requisiti. Per definizione, i formati non elaborati come Raw24Khz16BitMonoPcm
non includono intestazioni audio. Usare i formati non elaborati solo in una di queste situazioni:
- Si sa che l'implementazione downstream può decodificare un flusso di bit non elaborato.
- Si prevede di compilare manualmente le intestazioni in base a fattori quali profondità bit, frequenza di campionamento e numero di canali.
Questo esempio specifica un formato RIFF ad alta fedeltà Riff24Khz16BitMonoPcm
impostando speechSynthesisOutputFormat
nell'oggetto SpeechConfig
. Analogamente all'esempio riportato nella sezione precedente, ottenere i dati audio di ArrayBuffer
e interagirvi.
function synthesizeSpeech() {
const speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
// Set the output format
speechConfig.speechSynthesisOutputFormat = sdk.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm;
const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig, null);
speechSynthesizer.speakTextAsync(
"I'm excited to try text to speech",
result => {
// Interact with the audio ArrayBuffer data
const audioData = result.audioData;
console.log(`Audio data byte size: ${audioData.byteLength}.`)
speechSynthesizer.close();
},
error => {
console.log(error);
speechSynthesizer.close();
});
}
Usare SSML per personalizzare le caratteristiche vocali
È possibile usare SSML per ottimizzare il tono, la pronuncia, la velocità del parlato, il volume e altri aspetti nell'output della sintesi vocale inviando le richieste da uno schema XML. Questa sezione illustra un esempio di modifica della voce. Per altre informazioni, vedere Panoramica di Speech Synthesis Markup Language.
Per iniziare a usare SSML per la personalizzazione, è necessario apportare una piccola modifica che cambia la voce.
Creare prima di tutto un nuovo file XML per la configurazione di SSML nella directory radice del progetto.
<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US"> <voice name="en-US-AvaMultilingualNeural"> When you're on the freeway, it's a good idea to use a GPS. </voice> </speak>
In questo esempio, è ssml.xml. L'elemento radice è sempre
<speak>
. Il wrapping del testo in un elemento<voice>
consente di modificare la voce usando il parametroname
. Per l'elenco completo delle voci neurali supportate, vedere Supporto linguistico.Cambiare la richiesta di sintesi vocale in modo che faccia riferimento al file XML. La richiesta è essenzialmente la stessa, ma invece di usare la funzione
speakTextAsync()
si usaspeakSsmlAsync()
. Questa funzione prevede una stringa XML. Creare una funzione per caricare un file XML e restituirla come stringa:function xmlToString(filePath) { const xml = readFileSync(filePath, "utf8"); return xml; }
Per altre informazioni su
readFileSync
, vedere File system Node.js.L’oggetto risultato è esattamente lo stesso degli esempi precedenti.
function synthesizeSpeech() { const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion"); const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig, null); const ssml = xmlToString("ssml.xml"); speechSynthesizer.speakSsmlAsync( ssml, result => { if (result.errorDetails) { console.error(result.errorDetails); } else { console.log(JSON.stringify(result)); } speechSynthesizer.close(); }, error => { console.log(error); speechSynthesizer.close(); }); }
Nota
Per modificare la voce senza usare SSML, è possibile impostare la proprietà su SpeechConfig
tramite SpeechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
.
Sottoscrivere eventi di sintetizzatore
È possibile ottenere altre informazioni dettagliate sull'elaborazione del testo e sui risultati del riconoscimento vocale. Ad esempio, è possibile sapere quando il sintetizzatore inizia e si arresta oppure si potrebbe voler conoscere altri eventi rilevati durante la sintesi.
Quando si usa SpeechSynthesizer per la sintesi vocale, è possibile sottoscrivere gli eventi in questa tabella:
Event | Descrizione | Caso d'uso |
---|---|---|
BookmarkReached |
Segnala che è stato raggiunto un segnalibro. Per attivare un evento raggiunto da un segnalibro, è necessario un elemento bookmark nel SSML. Questo evento segnala il tempo trascorso dell'audio di output tra l'inizio della sintesi e l'elemento bookmark . La proprietà dell'evento Text è il valore stringa impostato nell'attributo mark del segnalibro. Gli elementi bookmark non vengono pronunciati. |
È possibile usare l'elemento bookmark per inserire marcatori personalizzati in SSML per ottenere l'offset di ogni marcatore nel flusso audio. L'elemento bookmark può essere usato per fare riferimento a una posizione specifica nella sequenza di testo o tag. |
SynthesisCanceled |
Segnala che la sintesi vocale è stata annullata. | È possibile confermare quando la sintesi è annullata. |
SynthesisCompleted |
Segnala che la sintesi vocale è stata completata. | È possibile confermare quando la sintesi è stata completata. |
SynthesisStarted |
Segnala che la sintesi vocale è stata completata. | È possibile confermare l'avvio della sintesi. |
Synthesizing |
Segnala che la sintesi vocale è in corso. Questo evento viene generato ogni volta che l'SDK riceve un blocco audio dal servizio Voce. | È possibile confermare quando la sintesi è in corso. |
VisemeReceived |
Segnala che è stato ricevuto un evento visema. | I Visemi vengono spesso usati per rappresentare le posizioni chiave nel parlato osservato. Le pose chiave includono la posizione delle labbra, della mascella e della lingua nella produzione di un particolare fonema. È possibile usare visemi per animare il viso di un personaggio durante la riproduzione dell'audio vocale. |
WordBoundary |
Segnala che è stato ricevuto un limite di parola. Questo evento viene generato all'inizio di ogni nuova parola pronunciata, punteggiatura e frase. L'evento segnala l'offset di tempo della parola corrente, in tick, dall'inizio dell'audio di output. Questo evento segnala anche la posizione del carattere nel testo di input o SSML immediatamente prima della parola che sta per essere pronunciata. | Questo evento viene comunemente usato per ottenere posizioni relative del testo e dell'audio corrispondente. Potrebbe essere necessario conoscere una nuova parola e quindi intervenire in base alla tempistica. Ad esempio, è possibile ottenere informazioni che consentono di decidere quando e per quanto tempo evidenziare le parole quando vengono pronunciate. |
Nota
Gli eventi vengono generati man mano che i dati audio di output diventano disponibili, che è più veloce della riproduzione in un dispositivo di output. Il chiamante deve sincronizzare in modo appropriato lo streaming e il tempo reale.
Ecco un esempio che illustra come sottoscrivere eventi per la sintesi vocale.
Importante
Se si usa una chiave API, archiviarla in modo sicuro in un'altra posizione, ad esempio in Azure Key Vault. Non includere la chiave API direttamente nel codice e non esporla mai pubblicamente.
Per altre informazioni sulla sicurezza dei servizi di intelligenza artificiale, vedere Autenticare le richieste a Servizi di Azure AI.
È possibile seguire le istruzioni nella guida introduttiva, ma sostituire il contenuto del file SpeechSynthesis.js con il codice Java seguente.
(function() {
"use strict";
var sdk = require("microsoft-cognitiveservices-speech-sdk");
var audioFile = "YourAudioFile.wav";
// This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
const speechConfig = sdk.SpeechConfig.fromSubscription(process.env.SPEECH_KEY, process.env.SPEECH_REGION);
const audioConfig = sdk.AudioConfig.fromAudioFileOutput(audioFile);
var speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
var ssml = `<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'> \r\n \
<voice name='${speechSynthesisVoiceName}'> \r\n \
<mstts:viseme type='redlips_front'/> \r\n \
The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>. \r\n \
</voice> \r\n \
</speak>`;
// Required for WordBoundary event sentences.
speechConfig.setProperty(sdk.PropertyId.SpeechServiceResponse_RequestSentenceBoundary, "true");
// Create the speech speechSynthesizer.
var speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig, audioConfig);
speechSynthesizer.bookmarkReached = function (s, e) {
var str = `BookmarkReached event: \
\r\n\tAudioOffset: ${(e.audioOffset + 5000) / 10000}ms \
\r\n\tText: \"${e.text}\".`;
console.log(str);
};
speechSynthesizer.synthesisCanceled = function (s, e) {
console.log("SynthesisCanceled event");
};
speechSynthesizer.synthesisCompleted = function (s, e) {
var str = `SynthesisCompleted event: \
\r\n\tAudioData: ${e.result.audioData.byteLength} bytes \
\r\n\tAudioDuration: ${e.result.audioDuration}`;
console.log(str);
};
speechSynthesizer.synthesisStarted = function (s, e) {
console.log("SynthesisStarted event");
};
speechSynthesizer.synthesizing = function (s, e) {
var str = `Synthesizing event: \
\r\n\tAudioData: ${e.result.audioData.byteLength} bytes`;
console.log(str);
};
speechSynthesizer.visemeReceived = function(s, e) {
var str = `VisemeReceived event: \
\r\n\tAudioOffset: ${(e.audioOffset + 5000) / 10000}ms \
\r\n\tVisemeId: ${e.visemeId}`;
console.log(str);
};
speechSynthesizer.wordBoundary = function (s, e) {
// Word, Punctuation, or Sentence
var str = `WordBoundary event: \
\r\n\tBoundaryType: ${e.boundaryType} \
\r\n\tAudioOffset: ${(e.audioOffset + 5000) / 10000}ms \
\r\n\tDuration: ${e.duration} \
\r\n\tText: \"${e.text}\" \
\r\n\tTextOffset: ${e.textOffset} \
\r\n\tWordLength: ${e.wordLength}`;
console.log(str);
};
// Synthesize the SSML
console.log(`SSML to synthesize: \r\n ${ssml}`)
console.log(`Synthesize to: ${audioFile}`);
speechSynthesizer.speakSsmlAsync(ssml,
function (result) {
if (result.reason === sdk.ResultReason.SynthesizingAudioCompleted) {
console.log("SynthesizingAudioCompleted result");
} else {
console.error("Speech synthesis canceled, " + result.errorDetails +
"\nDid you set the speech resource key and region values?");
}
speechSynthesizer.close();
speechSynthesizer = null;
},
function (err) {
console.trace("err - " + err);
speechSynthesizer.close();
speechSynthesizer = null;
});
}());
È possibile trovare altri esempi di testo per il riconoscimento vocale in GitHub.
Eseguire e usare un contenitore
I contenitori del servizio Voce forniscono API di endpoint di query basate su WebSocket a cui si accede tramite Speech SDK e l'interfaccia della riga di comando di Voce. Per impostazione predefinita, l'SDK e l'interfaccia della riga di comando di Voce usano il servizio Voce pubblico. Per usare il contenitore, è necessario modificare il metodo di inizializzazione. Usare un URL host del contenitore invece di chiave e area.
Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori di Voce con Docker.
Documentazione di riferimento | Pacchetto (download) | Ulteriori esempi in GitHub
In questa guida pratica vengono illustrati i modelli di progettazione comuni per eseguire la sintesi vocale.
Per altre informazioni sulle aree seguenti, vedere Che cos'è la sintesi vocale?
- Recupero di risposte come flussi in memoria.
- Personalizzazione della frequenza di campionamento e della velocità in bit dell'output.
- Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
- Uso di voci neurali.
- Sottoscrizione di eventi e azioni sui risultati.
Prerequisiti
- Una sottoscrizione di Azure. È possibile crearne uno gratuitamente.
- Creare una risorsa Voce nel portale di Azure.
- Ottenere la chiave e l'area della risorsa Voce. Dopo aver distribuito la risorsa Voce, selezionare Vai alla risorsa per visualizzare e gestire le chiavi.
Installare Speech SDK e gli esempi
Il repository Azure-Samples/cognitive-services-speech-sdk contiene esempi scritti in Objective-C per iOS e Mac. Selezionare un collegamento per visualizzare le istruzioni di installazione per ogni esempio:
- Sintesi vocale in Objective-C in macOS
- Sintesi vocale in Objective-C in iOS
- Esempi aggiuntivi per Objective-C in iOS
Usare un endpoint personalizzato
Dal punto di vista funzionale, l'endpoint personalizzato è identico all'endpoint standard usato per le richieste di sintesi vocale.
Una differenza è che EndpointId
deve essere specificato per usare la voce personalizzata tramite Speech SDK. È possibile iniziare con l‘avvio rapido della sintesi vocale e quindi aggiornare il codice con EndpointId
e SpeechSynthesisVoiceName
.
SPXSpeechConfiguration *speechConfig = [[SPXSpeechConfiguration alloc] initWithSubscription:speechKey region:speechRegion];
speechConfig.speechSynthesisVoiceName = @"YourCustomVoiceName";
speechConfig.EndpointId = @"YourEndpointId";
Per usare una voce personalizzata tramite Speech Synthesis Markup Language (SSML), specificare il nome del modello come nome della voce. Questo esempio usa la voce YourCustomVoiceName
.
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
<voice name="YourCustomVoiceName">
This is the text that is spoken.
</voice>
</speak>
Eseguire e usare un contenitore
I contenitori del servizio Voce forniscono API di endpoint di query basate su WebSocket a cui si accede tramite Speech SDK e l'interfaccia della riga di comando di Voce. Per impostazione predefinita, l'SDK e l'interfaccia della riga di comando di Voce usano il servizio Voce pubblico. Per usare il contenitore, è necessario modificare il metodo di inizializzazione. Usare un URL host del contenitore invece di chiave e area.
Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori di Voce con Docker.
Documentazione di riferimento | Pacchetto (download) | Ulteriori esempi in GitHub
In questa guida pratica vengono illustrati i modelli di progettazione comuni per eseguire la sintesi vocale.
Per altre informazioni sulle aree seguenti, vedere Che cos'è la sintesi vocale?
- Recupero di risposte come flussi in memoria.
- Personalizzazione della frequenza di campionamento e della velocità in bit dell'output.
- Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
- Uso di voci neurali.
- Sottoscrizione di eventi e azioni sui risultati.
Prerequisiti
- Una sottoscrizione di Azure. È possibile crearne uno gratuitamente.
- Creare una risorsa Voce nel portale di Azure.
- Ottenere la chiave e l'area della risorsa Voce. Dopo aver distribuito la risorsa Voce, selezionare Vai alla risorsa per visualizzare e gestire le chiavi.
Installare Speech SDK e gli esempi
Il repository Azure-Samples/cognitive-services-speech-sdk contiene esempi scritti in Swift per iOS e Mac. Selezionare un collegamento per visualizzare le istruzioni di installazione per ogni esempio:
Eseguire e usare un contenitore
I contenitori del servizio Voce forniscono API di endpoint di query basate su WebSocket a cui si accede tramite Speech SDK e l'interfaccia della riga di comando di Voce. Per impostazione predefinita, l'SDK e l'interfaccia della riga di comando di Voce usano il servizio Voce pubblico. Per usare il contenitore, è necessario modificare il metodo di inizializzazione. Usare un URL host del contenitore invece di chiave e area.
Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori di Voce con Docker.
Documentazione di riferimento | Pacchetto (PyPi) | Ulteriori esempi in GitHub
In questa guida pratica vengono illustrati i modelli di progettazione comuni per eseguire la sintesi vocale.
Per altre informazioni sulle aree seguenti, vedere Che cos'è la sintesi vocale?
- Recupero di risposte come flussi in memoria.
- Personalizzazione della frequenza di campionamento e della velocità in bit dell'output.
- Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
- Uso di voci neurali.
- Sottoscrizione di eventi e azioni sui risultati.
Selezionare il linguaggio di sintesi e la voce
La funzionalità sintesi vocale nel servizio Voce supporta più di 400 voci e più di 140 lingue e varianti. È possibile ottenere l'elenco completo o provarle nella Raccolta voci.
Specificare la lingua o la voce di SpeechConfig
perché corrispondano al testo di input e usino la voce specificata:
# Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
speech_config.speech_synthesis_language = "en-US"
speech_config.speech_synthesis_voice_name ="en-US-AvaMultilingualNeural"
Tutte le voci neurali sono multilingue e parlano fluentemente sia la propria lingua che l’inglese. Ad esempio, se il testo di input in inglese è "I'm excited to try text to speech" e si imposta es-ES-ElviraNeural
, il testo viene pronunciato in inglese con un accento spagnolo.
Se la voce non parla la lingua del testo di input, il servizio cognitivo di Azure per la voce non creerà audio sintetizzato. Per un elenco completo delle voci neurali supportate, consultare Lingue e voci supportate per il servizio cognitivo di Azure per la voce.
Nota
La voce predefinita è la prima voce restituita per impostazioni locali dall'API dell'elenco voci.
La voce che parla viene determinata in ordine di priorità come indicato di seguito:
- Se non si imposta
SpeechSynthesisVoiceName
oSpeechSynthesisLanguage
, a parlare sarà la voce predefinita peren-US
. - Se si imposta solo
SpeechSynthesisLanguage
, a parlare sarà la voce predefinita per impostazioni locali specificate. - Se
SpeechSynthesisVoiceName
eSpeechSynthesisLanguage
sono entrambi impostati, l'impostazioneSpeechSynthesisLanguage
verrà ignorata. La voce specificata tramiteSpeechSynthesisVoiceName
sarà quella a parlare. - Se l'elemento voce viene impostato tramite Speech Synthesis Markup Language (SSML), le impostazioni
SpeechSynthesisVoiceName
eSpeechSynthesisLanguage
verranno ignorate.
In sintesi, l'ordine di priorità può essere descritto come segue:
SpeechSynthesisVoiceName |
SpeechSynthesisLanguage |
SSML | Risultato |
---|---|---|---|
✗ | ✗ | ✗ | La voce predefinita per en-US sarà quella a parlare |
✗ | ✔ | ✗ | La voce predefinita per le impostazioni locali specificate sarà quella a parlare. |
✔ | ✔ | ✗ | La voce specificata tramite SpeechSynthesisVoiceName sarà quella a parlare. |
✔ | ✔ | ✔ | La voce specificata tramite SSML sarà quella a parlare. |
Sintetizzare la voce in un file
Creare un oggetto SpeechSynthesizer. Questo oggetto esegue le conversioni di sintesi vocale e invia l’output ad altoparlanti, file o altri flussi di output. SpeechSynthesizer
accetta come parametri:
- Oggetto
SpeechConfig
creato nel passaggio precedente. - Oggetto
AudioOutputConfig
che specifica la modalità di gestione dei risultati di output.
Creare un'istanza
AudioOutputConfig
per scrivere automaticamente l'output in un file .wav usando il parametro del costruttorefilename
:audio_config = speechsdk.audio.AudioOutputConfig(filename="path/to/write/file.wav")
Creare un'istanza di
SpeechSynthesizer
passando l'oggettospeech_config
e l'oggettoaudio_config
come parametri. Per sintetizzare il parlato e scrivere in un file, eseguirespeak_text_async()
con una stringa di testo.speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config) speech_synthesis_result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
Quando si esegue il programma, viene creato un file sintetizzato .wav, scritto nel percorso specificato. Questo risultato è un buon esempio dell'utilizzo più semplice. Si esamini quindi la personalizzazione dell'output e la gestione della risposta di output come flusso in memoria per l'uso di scenari personalizzati.
Sintetizzare l'output dell'altoparlante
Per eseguire l'output vocale sintetizzato nel dispositivo di output attivo corrente, ad esempio un altoparlante, configurare il parametro use_default_speaker
durante la creazione dell'istanza AudioOutputConfig
. Ecco un esempio:
audio_config = speechsdk.audio.AudioOutputConfig(use_default_speaker=True)
Ottenere un risultato come flusso in memoria
È possibile usare i dati audio risultanti come flusso in memoria anziché scrivere direttamente in un file. Con il flusso in memoria è possibile creare un comportamento personalizzato:
- Astrarre la matrice di byte risultante come flusso ricercabile per i servizi downstream personalizzati.
- Integrare il risultato con altri servizi o API.
- Modificare i dati audio, scrivere intestazioni di .wav personalizzate ed eseguire attività correlate.
È possibile apportare questa modifica all'esempio precedente. Rimuovere prima di tutto AudioConfig
, perché il comportamento di output viene gestito manualmente da questo punto in poi per un maggior controllo. Passare None
per AudioConfig
nel costruttore SpeechSynthesizer
.
Nota
Se si passa None
per AudioConfig
, invece di ometterlo come nel precedente esempio di output nell'altoparlante, l'audio non viene riprodotto per impostazione predefinita nel dispositivo di output attivo corrente.
Salvare il risultato in una variabile SpeechSynthesisResult
. La proprietà audio_data
contiene un oggetto bytes
dei dati di output. Questo oggetto può essere gestito manualmente oppure è possibile usare la classe AudioDataStream
per gestire il flusso in memoria.
In questo esempio si usa il costruttore AudioDataStream
per ottenere un flusso dal risultato.
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)
speech_synthesis_result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
stream = speechsdk.AudioDataStream(speech_synthesis_result)
A questo punto, è possibile implementare qualsiasi comportamento personalizzato usando l'oggetto stream
risultante.
Personalizzare il formato audio
È possibile personalizzare gli attributi di output audio, tra cui:
- Tipo di file audio
- Frequenza di campionamento
- Profondità di bit
Per cambiare il formato audio, usare la funzione set_speech_synthesis_output_format()
nell'oggetto SpeechConfig
. Questa funzione prevede un'istanza di enum
di tipo SpeechSynthesisOutputFormat. Usare il enum
per selezionare il formato di output. Per i formati disponili, vedere l’elenco dei formati audio.
Sono disponibili varie opzioni per tipi di file diversi a seconda dei requisiti. Per definizione, i formati non elaborati come Raw24Khz16BitMonoPcm
non includono intestazioni audio. Usare i formati non elaborati solo in una di queste situazioni:
- Si sa che l'implementazione downstream può decodificare un flusso di bit non elaborato.
- Si prevede di compilare manualmente le intestazioni in base a fattori quali profondità bit, frequenza di campionamento e numero di canali.
Questo esempio specifica un formato RIFF ad alta fedeltà Riff24Khz16BitMonoPcm
impostando SpeechSynthesisOutputFormat
nell'oggetto SpeechConfig
. Analogamente all'esempio della sezione precedente, è possibile usare AudioDataStream
per ottenere un flusso in memoria del risultato e quindi scriverlo in un file.
speech_config.set_speech_synthesis_output_format(speechsdk.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm)
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)
speech_synthesis_result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
stream = speechsdk.AudioDataStream(speech_synthesis_result)
stream.save_to_wav_file("path/to/write/file.wav")
Quando si esegue il programma, scrive un file .wav nel percorso specificato.
Usare SSML per personalizzare le caratteristiche vocali
È possibile usare SSML per ottimizzare il tono, la pronuncia, la velocità del parlato, il volume e altri aspetti nell'output della sintesi vocale inviando le richieste da uno schema XML. Questa sezione illustra un esempio di modifica della voce. Per altre informazioni, vedere Panoramica di Speech Synthesis Markup Language.
Per iniziare a usare SSML per la personalizzazione, è necessario apportare una piccola modifica che cambia la voce.
Creare prima di tutto un nuovo file XML per la configurazione di SSML nella directory radice del progetto.
<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US"> <voice name="en-US-AvaMultilingualNeural"> When you're on the freeway, it's a good idea to use a GPS. </voice> </speak>
In questo esempio, file è ssml.xml. L'elemento radice è sempre
<speak>
. Il wrapping del testo in un elemento<voice>
consente di modificare la voce usando il parametroname
. Per l'elenco completo delle voci neurali supportate, vedere Supporto linguistico.Cambiare la richiesta di sintesi vocale in modo che faccia riferimento al file XML. La richiesta è principalmente la stessa. Anziché usare la funzione
speak_text_async()
, si usaspeak_ssml_async()
. Questa funzione prevede una stringa XML. Prima di tutto, leggere la configurazione di SSML come stringa. Da qui, l'oggetto risultato è esattamente lo stesso degli esempi precedenti.Nota
Se
ssml_string
contiene
all'inizio della stringa, è necessario rimuovere il formato BOM, in caso contrario il servizio restituirà un errore. A questo scopo, impostare il parametroencoding
come segue:open("ssml.xml", "r", encoding="utf-8-sig")
.speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None) ssml_string = open("ssml.xml", "r").read() speech_synthesis_result = speech_synthesizer.speak_ssml_async(ssml_string).get() stream = speechsdk.AudioDataStream(speech_synthesis_result) stream.save_to_wav_file("path/to/write/file.wav")
Nota
Per modificare la voce senza usare SSML, è possibile impostare la proprietà su SpeechConfig
tramite speech_config.speech_synthesis_voice_name = "en-US-AvaMultilingualNeural"
.
Sottoscrivere eventi di sintetizzatore
È possibile ottenere altre informazioni dettagliate sull'elaborazione del testo e sui risultati del riconoscimento vocale. Ad esempio, è possibile sapere quando il sintetizzatore inizia e si arresta oppure si potrebbe voler conoscere altri eventi rilevati durante la sintesi.
Quando si usa SpeechSynthesizer per la sintesi vocale, è possibile sottoscrivere gli eventi in questa tabella:
Event | Descrizione | Caso d'uso |
---|---|---|
BookmarkReached |
Segnala che è stato raggiunto un segnalibro. Per attivare un evento raggiunto da un segnalibro, è necessario un elemento bookmark nel SSML. Questo evento segnala il tempo trascorso dell'audio di output tra l'inizio della sintesi e l'elemento bookmark . La proprietà dell'evento Text è il valore stringa impostato nell'attributo mark del segnalibro. Gli elementi bookmark non vengono pronunciati. |
È possibile usare l'elemento bookmark per inserire marcatori personalizzati in SSML per ottenere l'offset di ogni marcatore nel flusso audio. L'elemento bookmark può essere usato per fare riferimento a una posizione specifica nella sequenza di testo o tag. |
SynthesisCanceled |
Segnala che la sintesi vocale è stata annullata. | È possibile confermare quando la sintesi è annullata. |
SynthesisCompleted |
Segnala che la sintesi vocale è stata completata. | È possibile confermare quando la sintesi è stata completata. |
SynthesisStarted |
Segnala che la sintesi vocale è stata completata. | È possibile confermare l'avvio della sintesi. |
Synthesizing |
Segnala che la sintesi vocale è in corso. Questo evento viene generato ogni volta che l'SDK riceve un blocco audio dal servizio Voce. | È possibile confermare quando la sintesi è in corso. |
VisemeReceived |
Segnala che è stato ricevuto un evento visema. | I Visemi vengono spesso usati per rappresentare le posizioni chiave nel parlato osservato. Le pose chiave includono la posizione delle labbra, della mascella e della lingua nella produzione di un particolare fonema. È possibile usare visemi per animare il viso di un personaggio durante la riproduzione dell'audio vocale. |
WordBoundary |
Segnala che è stato ricevuto un limite di parola. Questo evento viene generato all'inizio di ogni nuova parola pronunciata, punteggiatura e frase. L'evento segnala l'offset di tempo della parola corrente, in tick, dall'inizio dell'audio di output. Questo evento segnala anche la posizione del carattere nel testo di input o SSML immediatamente prima della parola che sta per essere pronunciata. | Questo evento viene comunemente usato per ottenere posizioni relative del testo e dell'audio corrispondente. Potrebbe essere necessario conoscere una nuova parola e quindi intervenire in base alla tempistica. Ad esempio, è possibile ottenere informazioni che consentono di decidere quando e per quanto tempo evidenziare le parole quando vengono pronunciate. |
Nota
Gli eventi vengono generati man mano che i dati audio di output diventano disponibili, che è più veloce della riproduzione in un dispositivo di output. Il chiamante deve sincronizzare in modo appropriato lo streaming e il tempo reale.
Ecco un esempio che illustra come sottoscrivere eventi per la sintesi vocale.
Importante
Se si usa una chiave API, archiviarla in modo sicuro in un'altra posizione, ad esempio in Azure Key Vault. Non includere la chiave API direttamente nel codice e non esporla mai pubblicamente.
Per altre informazioni sulla sicurezza dei servizi di intelligenza artificiale, vedere Autenticare le richieste a Servizi di Azure AI.
È possibile seguire le istruzioni nella guida introduttiva, ma sostituire il contenuto di tale file speech-synthesis.py con il codice Python seguente.
import os
import azure.cognitiveservices.speech as speechsdk
def speech_synthesizer_bookmark_reached_cb(evt: speechsdk.SessionEventArgs):
print('BookmarkReached event:')
print('\tAudioOffset: {}ms'.format((evt.audio_offset + 5000) / 10000))
print('\tText: {}'.format(evt.text))
def speech_synthesizer_synthesis_canceled_cb(evt: speechsdk.SessionEventArgs):
print('SynthesisCanceled event')
def speech_synthesizer_synthesis_completed_cb(evt: speechsdk.SessionEventArgs):
print('SynthesisCompleted event:')
print('\tAudioData: {} bytes'.format(len(evt.result.audio_data)))
print('\tAudioDuration: {}'.format(evt.result.audio_duration))
def speech_synthesizer_synthesis_started_cb(evt: speechsdk.SessionEventArgs):
print('SynthesisStarted event')
def speech_synthesizer_synthesizing_cb(evt: speechsdk.SessionEventArgs):
print('Synthesizing event:')
print('\tAudioData: {} bytes'.format(len(evt.result.audio_data)))
def speech_synthesizer_viseme_received_cb(evt: speechsdk.SessionEventArgs):
print('VisemeReceived event:')
print('\tAudioOffset: {}ms'.format((evt.audio_offset + 5000) / 10000))
print('\tVisemeId: {}'.format(evt.viseme_id))
def speech_synthesizer_word_boundary_cb(evt: speechsdk.SessionEventArgs):
print('WordBoundary event:')
print('\tBoundaryType: {}'.format(evt.boundary_type))
print('\tAudioOffset: {}ms'.format((evt.audio_offset + 5000) / 10000))
print('\tDuration: {}'.format(evt.duration))
print('\tText: {}'.format(evt.text))
print('\tTextOffset: {}'.format(evt.text_offset))
print('\tWordLength: {}'.format(evt.word_length))
# This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
speech_config = speechsdk.SpeechConfig(subscription=os.environ.get('SPEECH_KEY'), region=os.environ.get('SPEECH_REGION'))
# Required for WordBoundary event sentences.
speech_config.set_property(property_id=speechsdk.PropertyId.SpeechServiceResponse_RequestSentenceBoundary, value='true')
audio_config = speechsdk.audio.AudioOutputConfig(use_default_speaker=True)
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)
# Subscribe to events
speech_synthesizer.bookmark_reached.connect(speech_synthesizer_bookmark_reached_cb)
speech_synthesizer.synthesis_canceled.connect(speech_synthesizer_synthesis_canceled_cb)
speech_synthesizer.synthesis_completed.connect(speech_synthesizer_synthesis_completed_cb)
speech_synthesizer.synthesis_started.connect(speech_synthesizer_synthesis_started_cb)
speech_synthesizer.synthesizing.connect(speech_synthesizer_synthesizing_cb)
speech_synthesizer.viseme_received.connect(speech_synthesizer_viseme_received_cb)
speech_synthesizer.synthesis_word_boundary.connect(speech_synthesizer_word_boundary_cb)
# The language of the voice that speaks.
speech_synthesis_voice_name='en-US-AvaMultilingualNeural'
ssml = """<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
<voice name='{}'>
<mstts:viseme type='redlips_front'/>
The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.
</voice>
</speak>""".format(speech_synthesis_voice_name)
# Synthesize the SSML
print("SSML to synthesize: \r\n{}".format(ssml))
speech_synthesis_result = speech_synthesizer.speak_ssml_async(ssml).get()
if speech_synthesis_result.reason == speechsdk.ResultReason.SynthesizingAudioCompleted:
print("SynthesizingAudioCompleted result")
elif speech_synthesis_result.reason == speechsdk.ResultReason.Canceled:
cancellation_details = speech_synthesis_result.cancellation_details
print("Speech synthesis canceled: {}".format(cancellation_details.reason))
if cancellation_details.reason == speechsdk.CancellationReason.Error:
if cancellation_details.error_details:
print("Error details: {}".format(cancellation_details.error_details))
print("Did you set the speech resource key and region values?")
È possibile trovare altri esempi di testo per il riconoscimento vocale in GitHub.
Usare un endpoint personalizzato
Dal punto di vista funzionale, l'endpoint personalizzato è identico all'endpoint standard usato per le richieste di sintesi vocale.
Una differenza è che endpoint_id
deve essere specificato per usare la voce personalizzata tramite Speech SDK. È possibile iniziare con l‘avvio rapido della sintesi vocale e quindi aggiornare il codice con endpoint_id
e speech_synthesis_voice_name
.
speech_config = speechsdk.SpeechConfig(subscription=os.environ.get('SPEECH_KEY'), region=os.environ.get('SPEECH_REGION'))
speech_config.endpoint_id = "YourEndpointId"
speech_config.speech_synthesis_voice_name = "YourCustomVoiceName"
Per usare una voce personalizzata tramite Speech Synthesis Markup Language (SSML), specificare il nome del modello come nome della voce. Questo esempio usa la voce YourCustomVoiceName
.
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
<voice name="YourCustomVoiceName">
This is the text that is spoken.
</voice>
</speak>
Eseguire e usare un contenitore
I contenitori del servizio Voce forniscono API di endpoint di query basate su WebSocket a cui si accede tramite Speech SDK e l'interfaccia della riga di comando di Voce. Per impostazione predefinita, l'SDK e l'interfaccia della riga di comando di Voce usano il servizio Voce pubblico. Per usare il contenitore, è necessario modificare il metodo di inizializzazione. Usare un URL host del contenitore invece di chiave e area.
Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori di Voce con Docker.
Informazioni di riferimento sull'API REST di riconoscimento vocale | Informazioni di riferimento sull'API REST di riconoscimento vocale per audio brevi | Ulteriori esempi in GitHub
In questa guida pratica vengono illustrati i modelli di progettazione comuni per eseguire la sintesi vocale.
Per altre informazioni sulle aree seguenti, vedere Che cos'è la sintesi vocale?
- Recupero di risposte come flussi in memoria.
- Personalizzazione della frequenza di campionamento e della velocità in bit dell'output.
- Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
- Uso di voci neurali.
- Sottoscrizione di eventi e azioni sui risultati.
Prerequisiti
- Una sottoscrizione di Azure. È possibile crearne uno gratuitamente.
- Creare una risorsa Voce nel portale di Azure.
- Ottenere la chiave e l'area della risorsa Voce. Dopo aver distribuito la risorsa Voce, selezionare Vai alla risorsa per visualizzare e gestire le chiavi.
Sintesi vocale
Al prompt dei comandi, eseguire questo comando. Inserire questi valori nel comando:
- Chiave della risorsa Voce
- Area della risorsa Voce
È anche possibile modificare i valori seguenti:
- Il valore dell'intestazione
X-Microsoft-OutputFormat
, che controlla il formato di output audio. Un elenco di formati di output audio supportati è disponibile nelle Informazioni di riferimento sull'API REST di sintesi vocale. - La voce di output. Per ottenere un elenco di voci disponibili per l'endpoint del servizio Voce, vedere l'API Elenco voci.
- File di output. In questo esempio la risposta del server viene indirizzata a un file denominato
output.mp3
.
curl --location --request POST 'https://YOUR_RESOURCE_REGION.tts.speech.microsoft.com/cognitiveservices/v1' \
--header 'Ocp-Apim-Subscription-Key: YOUR_RESOURCE_KEY' \
--header 'Content-Type: application/ssml+xml' \
--header 'X-Microsoft-OutputFormat: audio-16khz-128kbitrate-mono-mp3' \
--header 'User-Agent: curl' \
--data-raw '<speak version='\''1.0'\'' xml:lang='\''en-US'\''>
<voice name='\''en-US-AvaMultilingualNeural'\''>
I am excited to try text to speech
</voice>
</speak>' > output.mp3
In questa guida pratica vengono illustrati i modelli di progettazione comuni per eseguire la sintesi vocale.
Per altre informazioni sulle aree seguenti, vedere Che cos'è la sintesi vocale?
- Recupero di risposte come flussi in memoria.
- Personalizzazione della frequenza di campionamento e della velocità in bit dell'output.
- Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
- Uso di voci neurali.
- Sottoscrizione di eventi e azioni sui risultati.
Prerequisiti
- Una sottoscrizione di Azure. È possibile crearne uno gratuitamente.
- Creare una risorsa Voce nel portale di Azure.
- Ottenere la chiave e l'area della risorsa Voce. Dopo aver distribuito la risorsa Voce, selezionare Vai alla risorsa per visualizzare e gestire le chiavi.
Scaricare e installare
Seguire questi passaggi e vedere la guida di Avvio rapido sull'interfaccia della riga di comando di Voce per altri requisiti della piattaforma.
Eseguire il comando seguente dell'interfaccia della riga di comando di .NET per installare l'interfaccia della riga di comando di Voce:
dotnet tool install --global Microsoft.CognitiveServices.Speech.CLI
Eseguire i comandi seguenti per configurare la chiave e l'area della risorsa Voce. Sostituire
SUBSCRIPTION-KEY
con la chiave della risorsa Voce eREGION
con l'area della risorsa Voce.spx config @key --set SUBSCRIPTION-KEY spx config @region --set REGION
Sintesi vocale in un altoparlante
A questo punto si è pronti per eseguire l'interfaccia della riga di comando per Voce per sintetizzare la sintesi vocale da testo.
In una finestra della console passare alla directory che contiene il file binario dell'interfaccia della riga di comando di Voce. Poi eseguire quindi il comando seguente.
spx synthesize --text "I'm excited to try text to speech"
L'interfaccia della riga di comando per Voce produce il linguaggio naturale in inglese attraverso l’altoparlante del computer.
Sintetizzare la voce in un file
Eseguire il comando seguente per sostituire l'output del relatore con un file .wav:
spx synthesize --text "I'm excited to try text to speech" --audio output greetings.wav
L'interfaccia della riga di comando per Voce produce il linguaggio naturale in inglese attraverso il file audio greetings.wav.
Eseguire e usare un contenitore
I contenitori del servizio Voce forniscono API di endpoint di query basate su WebSocket a cui si accede tramite Speech SDK e l'interfaccia della riga di comando di Voce. Per impostazione predefinita, l'SDK e l'interfaccia della riga di comando di Voce usano il servizio Voce pubblico. Per usare il contenitore, è necessario modificare il metodo di inizializzazione. Usare un URL host del contenitore invece di chiave e area.
Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori di Voce con Docker.