Come sintetizzare la voce dal testo

Pacchetto della documentazione di riferimento | (NuGet) | Esempi aggiuntivi 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?

  • Ottenere risposte come flussi in memoria.
  • Personalizzazione della frequenza dei campioni di output e della velocità in bit.
  • Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
  • Uso delle voci neurali.
  • Sottoscrizione di eventi e azione 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 provarli nella Raccolta voci.

Specificare la lingua o la voce di per trovare la corrispondenza con il testo di SpeechConfig input e usare la voce specificata. Il frammento di codice seguente 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 fluente nella propria lingua e inglese. Ad esempio, se il testo di input in inglese è "Sono entusiasta di provare la sintesi vocale" e si seleziona es-ES-ElviraNeural, il testo viene parlato in inglese con un accento spagnolo.

Se la voce non parla la lingua del testo di input, il servizio Voce non crea audio sintetizzato. Per un elenco completo delle voci neurali supportate, vedere Supporto linguistico e vocale per il servizio Voce.

Nota

La voce predefinita è la prima voce restituita per impostazioni locali dall'API Elenco voci.

La voce che parla viene determinata in ordine di priorità come indicato di seguito:

  • Se non si imposta SpeechSynthesisVoiceName o SpeechSynthesisLanguage, la voce predefinita per en-US parla.
  • Se si imposta SpeechSynthesisLanguagesolo , la voce predefinita per le impostazioni locali specificate parla.
  • SpeechSynthesisVoiceNameSpeechSynthesisLanguage Se e sono impostati, l'impostazione SpeechSynthesisLanguage viene ignorata. La voce specificata tramite SpeechSynthesisVoiceName parla.
  • Se l'elemento vocale viene impostato tramite Speech Synthesis Markup Language (SSML), le SpeechSynthesisVoiceName impostazioni e SpeechSynthesisLanguage vengono ignorate.

Sintetizzare la voce in un file

Creare un oggetto SpeechSynthesizer . Questo oggetto illustrato nei frammenti di codice seguenti esegue il testo alle conversioni vocali e agli output in 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.
  1. Creare un'istanza AudioConfig di per scrivere automaticamente l'output in un file .wav usando la FromWavFileOutput() funzione . Crea un'istanza con un'istruzione using .

    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.

  2. Creare un'istanza SpeechSynthesizer di con un'altra using istruzione. Passare l'oggetto speechConfig e l'oggetto audioConfig come parametri. Per sintetizzare la voce e scrivere in un file, eseguire SpeakTextAsync() 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. Successivamente, è possibile personalizzare l'output e gestire la 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 AudioConfig parametro 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 altre API o servizi.
  • Modificare i dati audio, scrivere intestazioni di .wav personalizzate ed eseguire attività correlate.

È possibile apportare questa modifica all'esempio precedente. Prima di tutto, rimuovere il blocco, perché il comportamento di output viene gestito manualmente da questo punto in poi per aumentare il AudioConfig controllo. Passare null per AudioConfig nel SpeechSynthesizer costruttore.

Nota

Passando null per AudioConfig, anziché ometterlo come nell'esempio di output dell'altoparlante precedente, non riproduce l'audio per impostazione predefinita nel dispositivo di output attivo corrente.

Salvare il risultato in una variabile SpeechSynthesisResult . La AudioData proprietà contiene un'istanza byte [] per i dati di output. È possibile usare questa byte [] istanza manualmente oppure è possibile usare la classe AudioDataStream per gestire il flusso in memoria.

In questo esempio si usa la AudioDataStream.FromResult() funzione statica 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 risultante stream .

Personalizzare il formato audio

È possibile personalizzare gli attributi di output audio, tra cui:

  • Tipo di file audio
  • Frequenza di campionamento
  • Profondità bit

Per cambiare il formato audio, usare la funzione SetSpeechSynthesisOutputFormat() nell'oggetto SpeechConfig. Questa funzione prevede un'istanza enum di tipo SpeechSynthesisOutputFormat. enum Usare per selezionare il formato di output. Per i formati disponibili, vedi 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.

In questo esempio viene specificato il formato Riff24Khz16BitMonoPcm RIFF ad alta fedeltà impostando SpeechSynthesisOutputFormat sull'oggetto SpeechConfig . Analogamente all'esempio nella sezione precedente, si usa 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 passo, la pronuncia, la frequenza di pronuncia, il volume e altri aspetti dell'output di sintesi vocale inviando le richieste da uno schema XML. Questa sezione illustra un esempio di modifica della voce. Per altre informazioni, vedere Cenni preliminari sul linguaggio di markup di sintesi vocale.

Per iniziare a usare SSML per la personalizzazione, apportare una modifica secondaria che cambia la voce.

  1. Creare un nuovo file XML per la configurazione SSML nella directory del progetto radice.

    <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 il file è ssml.xml. L'elemento radice è sempre <speak>. Il wrapping del testo in un <voice> elemento consente di modificare la voce usando il name parametro . Per l'elenco completo delle voci neurali supportate, vedere Lingue supportate.

  2. Modificare la richiesta di sintesi vocale per fare 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. Prima di tutto, caricare la configurazione SSML come stringa usando File.ReadAllText(). Da questo punto, 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 scegliere Proprietà. Modificare l'azione di compilazione in Contenuto. Modificare Copia nella directory di output in 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:

Evento Descrizione Caso d'uso
BookmarkReached Segnala che è stato raggiunto un segnalibro. Per attivare un evento raggiunto da un segnalibro, è necessario un bookmark elemento in 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 del mark segnalibro. Gli bookmark elementi 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 viene annullata.
SynthesisCompleted Segnala che la sintesi vocale è completa. È possibile confermare quando la sintesi è completa.
SynthesisStarted Segnala che la sintesi vocale è iniziata. È possibile confermare all'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 viseme. Visemes viene spesso usato 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. Puoi usare visemes 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. È possibile seguire le istruzioni nella guida introduttiva, ma sostituire il contenuto di tale 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

L'endpoint personalizzato è funzionalmente identico all'endpoint standard usato per le richieste di sintesi vocale.

Una differenza è che è EndpointId necessario specificare per usare la voce personalizzata tramite Speech SDK. È possibile iniziare con la guida introduttiva al riconoscimento 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. In questo esempio viene usata la YourCustomVoiceName voce .

<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 voce forniscono API 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, Speech 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 anziché una chiave e un'area.

Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori voce con Docker.

Pacchetto della documentazione di riferimento | (NuGet) | Esempi aggiuntivi 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?

  • Ottenere risposte come flussi in memoria.
  • Personalizzazione della frequenza dei campioni di output e della velocità in bit.
  • Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
  • Uso delle voci neurali.
  • Sottoscrizione di eventi e azione 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 del testo supportato per le impostazioni locali di riconoscimento vocale o provarle in Raccolta voci.

Specificare la lingua o la voce della classe SpeechConfig in modo che corrisponda al testo di input e usare la voce specificata. Il frammento di codice seguente 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 fluente nella propria lingua e inglese. Ad esempio, se il testo di input in inglese è , "Sono entusiasta di provare il testo per la sintesi vocale" e si seleziona es-ES-ElviraNeural, il testo viene parlato in inglese con un accento spagnolo.

Se la voce non parla la lingua del testo di input, il servizio Voce non crea audio sintetizzato. Per un elenco completo delle voci neurali supportate, vedere Supporto linguistico e vocale per il servizio Voce.

Nota

La voce predefinita è la prima voce restituita per impostazioni locali dall'API Elenco voci.

La voce che parla viene determinata in ordine di priorità come indicato di seguito:

  • Se non si imposta SpeechSynthesisVoiceName o SpeechSynthesisLanguage, la voce predefinita per en-US parla.
  • Se si imposta SpeechSynthesisLanguagesolo , la voce predefinita per le impostazioni locali specificate parla.
  • SpeechSynthesisVoiceNameSpeechSynthesisLanguage Se e sono impostati, l'impostazione SpeechSynthesisLanguage viene ignorata. La voce specificata tramite SpeechSynthesisVoiceName parla.
  • Se l'elemento vocale viene impostato tramite Speech Synthesis Markup Language (SSML), le SpeechSynthesisVoiceName impostazioni e SpeechSynthesisLanguage vengono ignorate.

Sintetizzare la voce in un file

Creare un oggetto SpeechSynthesizer . Questo oggetto illustrato nei frammenti di codice seguenti esegue il testo alle conversioni vocali e agli output in 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.
  1. Creare un'istanza AudioConfig per scrivere automaticamente l'output in un file .wav usando la FromWavFileOutput() funzione :

    void synthesizeSpeech()
    {
        auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
        auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav");
    }
    
  2. Creare un'istanza SpeechSynthesizer di . Passare l'oggetto speechConfig e l'oggetto audioConfig come parametri. Per sintetizzare la voce e scrivere in un file, eseguire SpeakTextAsync() 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. Successivamente, è possibile personalizzare l'output e gestire la 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 AudioConfig parametro quando si crea l'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 altre API o servizi.
  • Modificare i dati audio, scrivere intestazioni di .wav personalizzate ed eseguire attività correlate.

È possibile apportare questa modifica all'esempio precedente. Prima di tutto, rimuovere il blocco, perché il comportamento di output viene gestito manualmente da questo punto in poi per aumentare il AudioConfig controllo. Passare NULL per AudioConfig nel SpeechSynthesizer costruttore.

Nota

Passando NULL per AudioConfig, anziché ometterlo come nell'esempio di output dell'altoparlante precedente, non riproduce l'audio per impostazione predefinita nel dispositivo di output attivo corrente.

Salvare il risultato in una variabile SpeechSynthesisResult . Il GetAudioData getter restituisce un'istanza byte [] per i dati di output. È possibile usare questa byte [] istanza manualmente oppure è possibile usare la classe AudioDataStream per gestire il flusso in memoria.

In questo esempio usare la AudioDataStream.FromResult() funzione statica 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 risultante stream .

Personalizzare il formato audio

È possibile personalizzare gli attributi di output audio, tra cui:

  • Tipo di file audio
  • Frequenza di campionamento
  • Profondità bit

Per modificare il formato audio, usare la SetSpeechSynthesisOutputFormat() funzione sull'oggetto SpeechConfig . Questa funzione prevede un'istanza enum di tipo SpeechSynthesisOutputFormat. enum Usare per selezionare il formato di output. Per i formati disponibili, vedi 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.

In questo esempio viene specificato il formato Riff24Khz16BitMonoPcm RIFF ad alta fedeltà impostando SpeechSynthesisOutputFormat sull'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 passo, la pronuncia, la frequenza di pronuncia, il volume e altri aspetti dell'output di sintesi vocale inviando le richieste da uno schema XML. Questa sezione illustra un esempio di modifica della voce. Per altre informazioni, vedere Cenni preliminari sul linguaggio di markup di sintesi vocale.

Per iniziare a usare SSML per la personalizzazione, apportare una modifica secondaria che cambia la voce.

  1. Creare un nuovo file XML per la configurazione SSML nella directory del progetto radice.

    <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 il file è ssml.xml. L'elemento radice è sempre <speak>. Il wrapping del testo in un <voice> elemento consente di modificare la voce usando il name parametro . Per l'elenco completo delle voci neurali supportate, vedere Lingue supportate.

  2. Modificare la richiesta di sintesi vocale per fare riferimento al file XML. La richiesta è principalmente la stessa. Anziché usare la SpeakTextAsync() funzione , si usa SpeakSsmlAsync(). Questa funzione prevede una stringa XML. Prima di tutto, caricare la configurazione SSML come stringa. Da questo punto, 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:

Evento Descrizione Caso d'uso
BookmarkReached Segnala che è stato raggiunto un segnalibro. Per attivare un evento raggiunto da un segnalibro, è necessario un bookmark elemento in 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 del mark segnalibro. Gli bookmark elementi 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 viene annullata.
SynthesisCompleted Segnala che la sintesi vocale è completa. È possibile confermare quando la sintesi è completa.
SynthesisStarted Segnala che la sintesi vocale è iniziata. È possibile confermare all'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 viseme. Visemes viene spesso usato 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. Puoi usare visemes 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. È possibile seguire le istruzioni della guida introduttiva, ma sostituire il contenuto di tale 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

L'endpoint personalizzato è funzionalmente identico all'endpoint standard usato per le richieste di sintesi vocale.

Una differenza è che è EndpointId necessario specificare per usare la voce personalizzata tramite Speech SDK. È possibile iniziare con la guida introduttiva al riconoscimento 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. In questo esempio viene usata la YourCustomVoiceName voce .

<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 voce forniscono API 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, Speech 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 anziché una chiave e un'area.

Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori voce con Docker.

Pacchetto della documentazione di riferimento | (Go) | Esempi aggiuntivi 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?

  • Ottenere risposte come flussi in memoria.
  • Personalizzazione della frequenza dei campioni di output e della velocità in bit.
  • Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
  • Uso delle voci neurali.
  • Sottoscrizione di eventi e azione sui risultati.

Prerequisiti

Installare Speech SDK

Prima di poter eseguire qualsiasi operazione, è necessario installare Speech SDK per Go.

Sintesi vocale in voce

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 comunica 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 collega i componenti ospitati in GitHub:

go mod init quickstart
go get github.com/Microsoft/cognitive-services-speech-sdk-go

A questo momento compilare ed eseguire il codice:

go build
go run quickstart

Per informazioni dettagliate sulle classi, vedere la SpeechConfig documentazione di riferimento 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 altre API o servizi.
  • Modificare i dati audio, scrivere intestazioni di .wav personalizzate ed eseguire attività correlate.

È possibile apportare questa modifica all'esempio precedente. Rimuovere il AudioConfig blocco, perché il comportamento di output viene gestito manualmente da questo punto in poi per aumentare il controllo. nil Passare quindi per AudioConfig nel SpeechSynthesizer costruttore.

Nota

Passando nil per AudioConfig, anziché ometterlo come hai fatto nell'esempio di output dell'altoparlante precedente, non riproduce l'audio per impostazione predefinita nel dispositivo di output attivo corrente.

Salvare il risultato in una SpeechSynthesisResult variabile. La AudioData proprietà restituisce un'istanza []byte per i dati di output. È possibile usare questa []byte istanza manualmente oppure è possibile usare la AudioDataStream classe per gestire il flusso in memoria. In questo esempio si usa la NewAudioDataStreamFromSpeechSynthesisResult() funzione statica 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 collega i componenti ospitati in GitHub:

go mod init quickstart
go get github.com/Microsoft/cognitive-services-speech-sdk-go

A questo momento compilare ed eseguire il codice:

go build
go run quickstart

Per informazioni dettagliate sulle classi, vedere la SpeechConfig documentazione di riferimento 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 provarli nella Raccolta voci.

Specificare la lingua o la voce di in modo che corrisponda al testo di SpeechConfig input e usare 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 fluente nella propria lingua e inglese. Ad esempio, se il testo di input in inglese è , "Sono entusiasta di provare il testo per la sintesi vocale" e si seleziona es-ES-ElviraNeural, il testo viene parlato in inglese con un accento spagnolo.

Se la voce non parla la lingua del testo di input, il servizio Voce non crea audio sintetizzato. Per un elenco completo delle voci neurali supportate, vedere Supporto linguistico e vocale per il servizio Voce.

Nota

La voce predefinita è la prima voce restituita per impostazioni locali dall'API Elenco voci.

La voce che parla viene determinata in ordine di priorità come indicato di seguito:

  • Se non si imposta SpeechSynthesisVoiceName o SpeechSynthesisLanguage, la voce predefinita per en-US parla.
  • Se si imposta SpeechSynthesisLanguagesolo , la voce predefinita per le impostazioni locali specificate parla.
  • SpeechSynthesisVoiceNameSpeechSynthesisLanguage Se e sono impostati, l'impostazione SpeechSynthesisLanguage viene ignorata. La voce specificata tramite SpeechSynthesisVoiceName parla.
  • Se l'elemento vocale viene impostato tramite Speech Synthesis Markup Language (SSML), le SpeechSynthesisVoiceName impostazioni e SpeechSynthesisLanguage vengono ignorate.

Usare SSML per personalizzare le caratteristiche vocali

È possibile usare Speech Synthesis Markup Language (SSML) per ottimizzare la presentazione, la pronuncia, la frequenza di pronuncia, il volume e altro ancora nell'output di sintesi vocale inviando le richieste da uno schema XML. Questa sezione illustra un esempio di modifica della voce. Per altre informazioni, vedere Cenni preliminari sul linguaggio di markup di sintesi vocale.

Per iniziare a usare SSML per la personalizzazione, apportare una modifica secondaria che cambia la voce.

Creare prima di tutto un nuovo file XML per la configurazione SSML nella directory del progetto radice. In questo esempio è ssml.xml. L'elemento radice è sempre <speak>. Il wrapping del testo in un <voice> elemento consente di modificare la voce usando il name parametro . Per l'elenco completo delle voci neurali supportate, vedere Lingue supportate.

<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 si carica la configurazione SSML come stringa. Da questo punto, 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:

Evento Descrizione Caso d'uso
BookmarkReached Segnala che è stato raggiunto un segnalibro. Per attivare un evento raggiunto da un segnalibro, è necessario un bookmark elemento in 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 del mark segnalibro. Gli bookmark elementi 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 viene annullata.
SynthesisCompleted Segnala che la sintesi vocale è completa. È possibile confermare quando la sintesi è completa.
SynthesisStarted Segnala che la sintesi vocale è iniziata. È possibile confermare all'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 viseme. Visemes viene spesso usato 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. Puoi usare visemes 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. È possibile seguire le istruzioni nella guida introduttiva, ma sostituire il contenuto del speech-synthesis.go file 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 voce forniscono API 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, Speech 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 anziché una chiave e un'area.

Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori voce con Docker.

Documentazione di riferimento | Esempi aggiuntivi su 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?

  • Ottenere risposte come flussi in memoria.
  • Personalizzazione della frequenza dei campioni di output e della velocità in bit.
  • Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
  • Uso delle voci neurali.
  • Sottoscrizione di eventi e azione 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 provarli nella Raccolta voci.

Specificare la lingua o la voce di SpeechConfig in modo che corrisponda al testo di input e usare la voce specificata. Il frammento di codice seguente 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 fluente nella propria lingua e inglese. Ad esempio, se il testo di input in inglese è , "Sono entusiasta di provare il testo per la sintesi vocale" e si seleziona es-ES-ElviraNeural, il testo viene parlato in inglese con un accento spagnolo.

Se la voce non parla la lingua del testo di input, il servizio Voce non crea audio sintetizzato. Per un elenco completo delle voci neurali supportate, vedere Supporto linguistico e vocale per il servizio Voce.

Nota

La voce predefinita è la prima voce restituita per impostazioni locali dall'API Elenco voci.

La voce che parla viene determinata in ordine di priorità come indicato di seguito:

  • Se non si imposta SpeechSynthesisVoiceName o SpeechSynthesisLanguage, la voce predefinita per en-US parla.
  • Se si imposta SpeechSynthesisLanguagesolo , la voce predefinita per le impostazioni locali specificate parla.
  • SpeechSynthesisVoiceNameSpeechSynthesisLanguage Se e sono impostati, l'impostazione SpeechSynthesisLanguage viene ignorata. La voce specificata tramite SpeechSynthesisVoiceName parla.
  • Se l'elemento vocale viene impostato tramite Speech Synthesis Markup Language (SSML), le SpeechSynthesisVoiceName impostazioni e SpeechSynthesisLanguage vengono ignorate.

Sintetizzare la voce in un file

Creare un oggetto SpeechSynthesizer. Questo oggetto esegue il testo alle conversioni vocali e agli output in 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.
  1. Creare un'istanza AudioConfig di per scrivere automaticamente l'output in un file .wav usando la fromWavFileOutput() funzione statica:

    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav");
    }
    
  2. Creare un'istanza SpeechSynthesizer di . Passare l'oggetto speechConfig e l'oggetto audioConfig come parametri. Per sintetizzare la voce e scrivere in un file, eseguire SpeakText() 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. Successivamente, è possibile personalizzare l'output e gestire la 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 AudioConfig un'istanza usando la fromDefaultSpeakerOutput() funzione statica. 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 altre API o servizi.
  • Modificare i dati audio, scrivere intestazioni di .wav personalizzate ed eseguire attività correlate.

È possibile apportare questa modifica all'esempio precedente. Prima di tutto, rimuovere il blocco, perché il comportamento di output viene gestito manualmente da questo punto in poi per aumentare il AudioConfig controllo. null Passare quindi per AudioConfig nel SpeechSynthesizer costruttore.

Nota

Passando null per AudioConfig, anziché ometterlo come hai fatto nell'esempio di output dell'altoparlante precedente, non riproduce l'audio per impostazione predefinita nel dispositivo di output attivo corrente.

Salvare il risultato in una SpeechSynthesisResult variabile. La SpeechSynthesisResult.getAudioData() funzione restituisce un'istanza byte [] dei dati di output. È possibile usare questa byte [] istanza manualmente oppure è possibile usare la AudioDataStream classe per gestire il flusso in memoria.

In questo esempio usare la AudioDataStream.fromResult() funzione statica 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 risultante stream .

Personalizzare il formato audio

È possibile personalizzare gli attributi di output audio, tra cui:

  • Tipo di file audio
  • Frequenza di campionamento
  • Profondità bit

Per cambiare il formato audio, usare la funzione setSpeechSynthesisOutputFormat() nell'oggetto SpeechConfig. Questa funzione prevede un'istanza enum di tipo SpeechSynthesisOutputFormat. enum Usare per selezionare il formato di output. Per i formati disponibili, vedi 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.

In questo esempio viene specificato il formato Riff24Khz16BitMonoPcm RIFF ad alta fedeltà impostando SpeechSynthesisOutputFormat sull'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 passo, la pronuncia, la frequenza di pronuncia, il volume e altri aspetti dell'output di sintesi vocale inviando le richieste da uno schema XML. Questa sezione illustra un esempio di modifica della voce. Per altre informazioni, vedere l'articolo procedure SSML.

Per iniziare a usare SSML per la personalizzazione, apportare una modifica secondaria che cambia la voce.

  1. Creare un nuovo file XML per la configurazione SSML nella directory del progetto radice.

    <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 il file è ssml.xml. L'elemento radice è sempre <speak>. Il wrapping del testo in un <voice> elemento consente di modificare la voce usando il name parametro . Per l'elenco completo delle voci neurali supportate, vedere Lingue supportate.

  2. Modificare la richiesta di sintesi vocale per fare riferimento al file XML. La richiesta è principalmente la stessa. Anziché usare la SpeakText() funzione , si usa SpeakSsml(). Questa funzione prevede una stringa XML, quindi creare prima una funzione per caricare un file XML e restituirla 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 risultato è 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:

Evento Descrizione Caso d'uso
BookmarkReached Segnala che è stato raggiunto un segnalibro. Per attivare un evento raggiunto da un segnalibro, è necessario un bookmark elemento in 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 del mark segnalibro. Gli bookmark elementi 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 viene annullata.
SynthesisCompleted Segnala che la sintesi vocale è completa. È possibile confermare quando la sintesi è completa.
SynthesisStarted Segnala che la sintesi vocale è iniziata. È possibile confermare all'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 viseme. Visemes viene spesso usato 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. Puoi usare visemes 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. È possibile seguire le istruzioni nella guida introduttiva, ma sostituire il contenuto di tale 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

L'endpoint personalizzato è funzionalmente identico all'endpoint standard usato per le richieste di sintesi vocale.

Una differenza è che è EndpointId necessario specificare per usare la voce personalizzata tramite Speech SDK. È possibile iniziare con la guida introduttiva al riconoscimento 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. In questo esempio viene usata la YourCustomVoiceName voce .

<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 voce forniscono API 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, Speech 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 anziché una chiave e un'area.

Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori voce con Docker.

Pacchetto della documentazione di riferimento | (npm) | Esempi aggiuntivi nel codice sorgente della libreria 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?

  • Ottenere risposte come flussi in memoria.
  • Personalizzazione della frequenza dei campioni di output e della velocità in bit.
  • Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
  • Uso delle voci neurali.
  • Sottoscrizione di eventi e azione 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 provarli nella Raccolta voci.

Specificare la lingua o la voce di in modo che corrisponda al testo di SpeechConfig input e usare 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 fluente nella propria lingua e inglese. Ad esempio, se il testo di input in inglese è , "Sono entusiasta di provare il testo per la sintesi vocale" e si seleziona es-ES-ElviraNeural, il testo viene parlato in inglese con un accento spagnolo.

Se la voce non parla la lingua del testo di input, il servizio Voce non crea audio sintetizzato. Per un elenco completo delle voci neurali supportate, vedere Supporto linguistico e vocale per il servizio Voce.

Nota

La voce predefinita è la prima voce restituita per impostazioni locali dall'API Elenco voci.

La voce che parla viene determinata in ordine di priorità come indicato di seguito:

  • Se non si imposta SpeechSynthesisVoiceName o SpeechSynthesisLanguage, la voce predefinita per en-US parla.
  • Se si imposta SpeechSynthesisLanguagesolo , la voce predefinita per le impostazioni locali specificate parla.
  • SpeechSynthesisVoiceNameSpeechSynthesisLanguage Se e sono impostati, l'impostazione SpeechSynthesisLanguage viene ignorata. La voce specificata tramite SpeechSynthesisVoiceName parla.
  • Se l'elemento vocale viene impostato tramite Speech Synthesis Markup Language (SSML), le SpeechSynthesisVoiceName impostazioni e SpeechSynthesisLanguage vengono ignorate.

Eseguire la sintesi vocale

Per eseguire l'output vocale sintetizzato nel dispositivo di output attivo corrente, ad esempio un altoparlante, creare AudioConfig un'istanza usando la fromDefaultSpeakerOutput() funzione statica. 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, l'audio sintetizzato viene riprodotto dall'altoparlante. Questo risultato è un buon esempio dell'utilizzo più semplice. Successivamente, è possibile personalizzare l'output e gestire la 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 altre API o servizi.
  • Modificare i dati audio, scrivere intestazioni personalizzate .wav ed eseguire attività correlate.

È possibile apportare questa modifica all'esempio precedente. Rimuovere il AudioConfig blocco, perché il comportamento di output viene gestito manualmente da questo punto in poi per aumentare il controllo. null Passare quindi per AudioConfig nel SpeechSynthesizer costruttore.

Nota

Passando null per AudioConfig, anziché ometterlo come hai fatto nell'esempio di output dell'altoparlante precedente, non riproduce l'audio per impostazione predefinita nel dispositivo di output attivo corrente.

Salvare il risultato in una variabile SpeechSynthesisResult . La SpeechSynthesisResult.audioData proprietà restituisce un ArrayBuffer valore dei dati di output, il tipo di flusso del browser predefinito. Per il codice lato server, eseguire la conversione 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 risultante ArrayBuffer . 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à bit

Per modificare il formato audio, utilizzare la speechSynthesisOutputFormat proprietà sull'oggetto SpeechConfig . Questa proprietà prevede un'istanza enum di tipo SpeechSynthesisOutputFormat. enum Usare per selezionare il formato di output. Per i formati disponibili, vedi 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.

In questo esempio viene specificato il formato Riff24Khz16BitMonoPcm RIFF ad alta fedeltà impostando speechSynthesisOutputFormat sull'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 passo, la pronuncia, la frequenza di pronuncia, il volume e altri aspetti dell'output di sintesi vocale inviando le richieste da uno schema XML. Questa sezione illustra un esempio di modifica della voce. Per altre informazioni, vedere Cenni preliminari sul linguaggio di markup di sintesi vocale.

Per iniziare a usare SSML per la personalizzazione, apportare una modifica secondaria che cambia la voce.

  1. Creare un nuovo file XML per la configurazione SSML nella directory del progetto radice.

    <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 <voice> elemento consente di modificare la voce usando il name parametro . Per l'elenco completo delle voci neurali supportate, vedere Lingue supportate.

  2. Modificare la richiesta di sintesi vocale per fare 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. 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:

Evento Descrizione Caso d'uso
BookmarkReached Segnala che è stato raggiunto un segnalibro. Per attivare un evento raggiunto da un segnalibro, è necessario un bookmark elemento in 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 del mark segnalibro. Gli bookmark elementi 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 viene annullata.
SynthesisCompleted Segnala che la sintesi vocale è completa. È possibile confermare quando la sintesi è completa.
SynthesisStarted Segnala che la sintesi vocale è iniziata. È possibile confermare all'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 viseme. Visemes viene spesso usato 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. Puoi usare visemes 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. È possibile seguire le istruzioni nella guida introduttiva, ma sostituire il contenuto di tale file SpeechSynthesis.js con il codice JavaScript 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 voce forniscono API 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, Speech 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 anziché una chiave e un'area.

Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori voce con Docker.

Pacchetto della documentazione di riferimento | (download) | Esempi aggiuntivi 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?

  • Ottenere risposte come flussi in memoria.
  • Personalizzazione della frequenza dei campioni di output e della velocità in bit.
  • Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
  • Uso delle voci neurali.
  • Sottoscrizione di eventi e azione sui risultati.

Prerequisiti

Installare Speech SDK ed 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:

Usare un endpoint personalizzato

L'endpoint personalizzato è funzionalmente identico all'endpoint standard usato per le richieste di sintesi vocale.

Una differenza è che è EndpointId necessario specificare per usare la voce personalizzata tramite Speech SDK. È possibile iniziare con la guida introduttiva al riconoscimento 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. In questo esempio viene usata la YourCustomVoiceName voce .

<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 voce forniscono API 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, Speech 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 anziché una chiave e un'area.

Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori voce con Docker.

Pacchetto della documentazione di riferimento | (download) | Esempi aggiuntivi 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?

  • Ottenere risposte come flussi in memoria.
  • Personalizzazione della frequenza dei campioni di output e della velocità in bit.
  • Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
  • Uso delle voci neurali.
  • Sottoscrizione di eventi e azione sui risultati.

Prerequisiti

Installare Speech SDK ed 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 voce forniscono API 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, Speech 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 anziché una chiave e un'area.

Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori voce con Docker.

Pacchetto della documentazione di riferimento | (PyPi) | Esempi aggiuntivi 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?

  • Ottenere risposte come flussi in memoria.
  • Personalizzazione della frequenza dei campioni di output e della velocità in bit.
  • Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
  • Uso delle voci neurali.
  • Sottoscrizione di eventi e azione 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 provarli nella Raccolta voci.

Specificare la lingua o la voce di in modo che corrisponda al testo di SpeechConfig input e usare 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 fluente nella propria lingua e inglese. Ad esempio, se il testo di input in inglese è , "Sono entusiasta di provare il testo per la sintesi vocale" e si seleziona es-ES-ElviraNeural, il testo viene parlato in inglese con un accento spagnolo.

Se la voce non parla la lingua del testo di input, il servizio Voce non crea audio sintetizzato. Per un elenco completo delle voci neurali supportate, vedere Supporto linguistico e vocale per il servizio Voce.

Nota

La voce predefinita è la prima voce restituita per impostazioni locali dall'API Elenco voci.

La voce che parla viene determinata in ordine di priorità come indicato di seguito:

  • Se non si imposta SpeechSynthesisVoiceName o SpeechSynthesisLanguage, la voce predefinita per en-US parla.
  • Se si imposta SpeechSynthesisLanguagesolo , la voce predefinita per le impostazioni locali specificate parla.
  • SpeechSynthesisVoiceNameSpeechSynthesisLanguage Se e sono impostati, l'impostazione SpeechSynthesisLanguage viene ignorata. La voce specificata tramite SpeechSynthesisVoiceName parla.
  • Se l'elemento vocale viene impostato tramite Speech Synthesis Markup Language (SSML), le SpeechSynthesisVoiceName impostazioni e SpeechSynthesisLanguage vengono ignorate.

Sintetizzare la voce in un file

Creare un oggetto SpeechSynthesizer . Questo oggetto esegue il testo alle conversioni vocali e agli output in 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.
  1. Creare un'istanza AudioOutputConfig di per scrivere automaticamente l'output in un file .wav usando il parametro del filename costruttore:

    audio_config = speechsdk.audio.AudioOutputConfig(filename="path/to/write/file.wav")
    
  2. SpeechSynthesizer Creare un'istanza passando speech_config l'oggetto e l'oggetto audio_config come parametri. Per sintetizzare la voce e scrivere in un file, eseguire speak_text_async() con una stringa di testo.

    speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)
    speech_synthesizer.speak_text_async("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. Successivamente, è possibile personalizzare l'output e gestire la 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, impostare il use_default_speaker parametro quando si crea l'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 altre API o servizi.
  • Modificare i dati audio, scrivere intestazioni di .wav personalizzate ed eseguire attività correlate.

È possibile apportare questa modifica all'esempio precedente. Prima di tutto, rimuovere AudioConfig, perché il comportamento di output viene gestito manualmente da questo punto in poi per aumentare il controllo. Passare None per AudioConfig nel SpeechSynthesizer costruttore.

Nota

Passando None per AudioConfig, anziché ometterlo come hai fatto nell'esempio di output dell'altoparlante precedente, non riproduce l'audio per impostazione predefinita nel dispositivo di output attivo corrente.

Salvare il risultato in una SpeechSynthesisResult variabile. 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 usare il AudioDataStream costruttore per ottenere un flusso dal risultato:

speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)
result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
stream = AudioDataStream(result)

A questo punto, è possibile implementare qualsiasi comportamento personalizzato usando l'oggetto risultante stream .

Personalizzare il formato audio

È possibile personalizzare gli attributi di output audio, tra cui:

  • Tipo di file audio
  • Frequenza di campionamento
  • Profondità bit

Per modificare il formato audio, usare la set_speech_synthesis_output_format() funzione sull'oggetto SpeechConfig . Questa funzione prevede un'istanza enum di tipo SpeechSynthesisOutputFormat. enum Usare per selezionare il formato di output. Per i formati disponibili, vedi 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.

In questo esempio viene specificato il formato Riff24Khz16BitMonoPcm RIFF ad alta fedeltà impostando SpeechSynthesisOutputFormat sull'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)

result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
stream = speechsdk.AudioDataStream(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 passo, la pronuncia, la frequenza di pronuncia, il volume e altri aspetti dell'output di sintesi vocale inviando le richieste da uno schema XML. Questa sezione illustra un esempio di modifica della voce. Per altre informazioni, vedere Cenni preliminari sul linguaggio di markup di sintesi vocale.

Per iniziare a usare SSML per la personalizzazione, apportare una modifica secondaria che cambia la voce.

  1. Creare un nuovo file XML per la configurazione SSML nella directory del progetto radice.

    <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 il file è ssml.xml. L'elemento radice è sempre <speak>. Il wrapping del testo in un <voice> elemento consente di modificare la voce usando il name parametro . Per l'elenco completo delle voci neurali supportate, vedere Lingue supportate.

  2. Modificare la richiesta di sintesi vocale per fare riferimento al file XML. La richiesta è principalmente la stessa. Anziché usare la speak_text_async() funzione , usare speak_ssml_async(). Questa funzione prevede una stringa XML. Leggere prima di tutto la configurazione di SSML come stringa. Da questo punto, 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 parametro encoding 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()
    result = speech_synthesizer.speak_ssml_async(ssml_string).get()
    
    stream = speechsdk.AudioDataStream(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:

Evento Descrizione Caso d'uso
BookmarkReached Segnala che è stato raggiunto un segnalibro. Per attivare un evento raggiunto da un segnalibro, è necessario un bookmark elemento in 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 del mark segnalibro. Gli bookmark elementi 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 viene annullata.
SynthesisCompleted Segnala che la sintesi vocale è completa. È possibile confermare quando la sintesi è completa.
SynthesisStarted Segnala che la sintesi vocale è iniziata. È possibile confermare all'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 viseme. Visemes viene spesso usato 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. Puoi usare visemes 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. È 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

L'endpoint personalizzato è funzionalmente identico all'endpoint standard usato per le richieste di sintesi vocale.

Una differenza è che è endpoint_id necessario specificare per usare la voce personalizzata tramite Speech SDK. È possibile iniziare con la guida introduttiva al riconoscimento 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. In questo esempio viene usata la YourCustomVoiceName voce .

<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 voce forniscono API 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, Speech 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 anziché una chiave e un'area.

Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori voce con Docker.

Informazioni di riferimento | sull'API REST Riconoscimento vocale in testo per brevi riferimenti | audio Esempi aggiuntivi 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?

  • Ottenere risposte come flussi in memoria.
  • Personalizzazione della frequenza dei campioni di output e della velocità in bit.
  • Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
  • Uso delle voci neurali.
  • Sottoscrizione di eventi e azione sui risultati.

Prerequisiti

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. È possibile trovare un elenco dei formati di output audio supportati nelle informazioni di riferimento sull'API REST 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?

  • Ottenere risposte come flussi in memoria.
  • Personalizzazione della frequenza dei campioni di output e della velocità in bit.
  • Invio di richieste di sintesi tramite Speech Synthesis Markup Language (SSML).
  • Uso delle voci neurali.
  • Sottoscrizione di eventi e azione sui risultati.

Prerequisiti

Scaricare e installare

Seguire questa procedura e vedere la guida introduttiva all'interfaccia della riga di comando di Voce per altri requisiti per la piattaforma.

  1. 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
    
  2. Eseguire i comandi seguenti per configurare la chiave e l'area della risorsa Voce. Sostituire SUBSCRIPTION-KEY con la chiave della risorsa Voce e sostituire REGION 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 di Voce produce una lingua naturale in inglese tramite l'altoparlante del computer.

Sintetizzare la voce in un file

  • Eseguire il comando seguente per modificare l'output dell'altoparlante in un file .wav :

    spx synthesize --text "I'm excited to try text to speech" --audio output greetings.wav
    

L'interfaccia della riga di comando di Voce produce una lingua naturale in inglese nel file audio greetings.wav .

Eseguire e usare un contenitore

I contenitori voce forniscono API 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, Speech 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 anziché una chiave e un'area.

Per altre informazioni sui contenitori, vedere Installare ed eseguire contenitori voce con Docker.

Passaggi successivi