Share via


Spraaksynthese van tekst

Referentiedocumentatiepakket (NuGet) | Aanvullende voorbeelden op GitHub |

In deze handleiding leert u algemene ontwerppatronen voor het uitvoeren van tekst-naar-spraaksynthese.

Zie Wat is tekst naar spraak voor meer informatie over de volgende gebieden ?

  • Antwoorden krijgen als in-memory streams.
  • Voorbeeldsnelheid en bitsnelheid van uitvoer aanpassen.
  • Syntheseaanvragen verzenden met behulp van Speech Synthesis Markup Language (SSML).
  • Neurale stemmen gebruiken.
  • Abonneren op gebeurtenissen en reageren op resultaten.

Synthesetaal en spraak selecteren

De functie tekst-naar-spraak in de Speech-service ondersteunt meer dan 400 stemmen en meer dan 140 talen en varianten. U kunt de volledige lijst ophalen of ze uitproberen in de spraakgalerie.

Geef de taal of stem op van SpeechConfig uw invoertekst en gebruik de opgegeven stem. In het volgende codefragment ziet u hoe deze techniek werkt:

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";
}

Alle neurale stemmen zijn meertalige en vloeiende taal en Engels. Als de invoertekst in het Engels bijvoorbeeld 'Ik ben enthousiast om tekst naar spraak te proberen' is en u selecteert es-ES-ElviraNeural, wordt de tekst in het Engels gesproken met een Spaans accent.

Als de stem de taal van de invoertekst niet spreekt, maakt de Speech-service geen gesynthetiseerde audio. Zie Taal- en spraakondersteuning voor de Speech-service voor een volledige lijst met ondersteunde neurale stemmen.

Notitie

De standaardstem is de eerste stem die per landinstelling wordt geretourneerd vanuit de Voice List-API.

De stem die spreekt, wordt als volgt bepaald in volgorde van prioriteit:

  • Als u dit niet instelt SpeechSynthesisVoiceName of SpeechSynthesisLanguage, wordt de standaardstem voor en-US gesproken tekst gebruikt.
  • Als u alleen instelt SpeechSynthesisLanguage, spreekt de standaardstem voor de opgegeven landinstelling.
  • Als beide SpeechSynthesisVoiceName zijn SpeechSynthesisLanguage ingesteld, wordt de SpeechSynthesisLanguage instelling genegeerd. De stem die u opgeeft met behulp van SpeechSynthesisVoiceName spreekt.
  • Als het spraakelement is ingesteld met behulp van Speech Synthesis Markup Language (SSML), worden de SpeechSynthesisVoiceName en SpeechSynthesisLanguage instellingen genegeerd.

Spraak synthetiseren naar een bestand

Maak een SpeechSynthesizer-object . Dit object dat wordt weergegeven in de volgende codefragmenten voert tekst uit naar spraakconversies en uitvoer naar luidsprekers, bestanden of andere uitvoerstromen. SpeechSynthesizer accepteert als parameters:

  1. Maak een AudioConfig exemplaar om de uitvoer automatisch naar een .wav-bestand te schrijven met behulp van de FromWavFileOutput() functie. Instantieer het met een using instructie.

    static async Task SynthesizeAudioAsync()
    {
        var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
        using var audioConfig = AudioConfig.FromWavFileOutput("path/to/write/file.wav");
    }
    

    Met een using-instructie in deze context worden niet-beheerde resources automatisch verwijderd en wordt het object na verwijdering buiten gebruik gesteld.

  2. Instantieer een SpeechSynthesizer exemplaar met een andere using instructie. Geef uw speechConfig object en het audioConfig object door als parameters. Als u spraak wilt omzetten en naar een bestand wilt schrijven, voert u deze uit SpeakTextAsync() met een tekenreeks tekst.

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");
}

Wanneer u het programma uitvoert, wordt er een gesynthetiseerd .wav-bestand gemaakt, dat wordt geschreven naar de locatie die u opgeeft. Dit resultaat is een goed voorbeeld van het meest eenvoudige gebruik. Vervolgens kunt u de uitvoer aanpassen en het uitvoerantwoord verwerken als een stroom in het geheugen voor het werken met aangepaste scenario's.

Synthetiseren naar de uitvoer van de luidspreker

Als u gesynthetiseerde spraak wilt uitvoeren naar het huidige actieve uitvoerapparaat zoals een luidspreker, laat u de AudioConfig parameter weg wanneer u het SpeechSynthesizer exemplaar maakt. Hier volgt een voorbeeld:

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");
}

Een resultaat ophalen als een stroom in het geheugen

U kunt de resulterende audiogegevens gebruiken als een in-memory stream in plaats van rechtstreeks naar een bestand te schrijven. Met een in-memory stream kunt u aangepast gedrag bouwen:

  • Abstract de resulterende bytematrix als een zoekbare stroom voor aangepaste downstreamservices.
  • Integreer het resultaat met andere API's of services.
  • Wijzig de audiogegevens, schrijf aangepaste .wav headers en voer gerelateerde taken uit.

U kunt deze wijziging aanbrengen in het vorige voorbeeld. Verwijder eerst het AudioConfig blok, omdat u het uitvoergedrag vanaf dit punt handmatig beheert voor meer controle. Geef null deze door AudioConfig in de SpeechSynthesizer constructor.

Notitie

Het doorgeven null voor AudioConfig, in plaats van deze weg te laten zoals in het vorige voorbeeld van de luidsprekeruitvoer, speelt de audio niet standaard af op het huidige actieve uitvoerapparaat.

Sla het resultaat op in een SpeechSynthesisResult-variabele . De AudioData eigenschap bevat een byte [] exemplaar voor de uitvoergegevens. U kunt met dit byte [] exemplaar handmatig werken of u kunt de Klasse AudioDataStream gebruiken om de stroom in het geheugen te beheren.

In dit voorbeeld gebruikt u de AudioDataStream.FromResult() statische functie om een stroom op te halen uit het resultaat:

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);
}

Op dit moment kunt u elk aangepast gedrag implementeren met behulp van het resulterende stream object.

Audio-indeling aanpassen

U kunt kenmerken voor audio-uitvoer aanpassen, waaronder:

  • Audiobestandstype
  • Samplefrequentie
  • Bitdiepte

Als u de audio-indeling wilt wijzigen, gebruikt u de functie SetSpeechSynthesisOutputFormat() op het SpeechConfig-object. Deze functie verwacht een exemplaar van het enum type SpeechSynthesisOutputFormat. Gebruik de enum optie om de uitvoerindeling te selecteren. Zie de lijst met audio-indelingen voor beschikbare indelingen.

Er zijn verschillende opties voor verschillende bestandstypen, afhankelijk van uw vereisten. Onbewerkte indelingen Raw24Khz16BitMonoPcm bevatten standaard geen audioheaders. Gebruik onbewerkte indelingen alleen in een van deze situaties:

  • U weet dat uw downstream-implementatie een onbewerkte bitstream kan decoderen.
  • U bent van plan om handmatig headers te bouwen op basis van factoren zoals bitdiepte, samplefrequentie en aantal kanalen.

In dit voorbeeld wordt de RIFF-indeling Riff24Khz16BitMonoPcm met hoge kwaliteit opgegeven door het object in te SpeechConfig stellenSpeechSynthesisOutputFormat. Net als in het voorbeeld in de vorige sectie gebruikt u AudioDataStream om een stroom in het geheugen van het resultaat op te halen en vervolgens naar een bestand te schrijven.

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");
}

Wanneer u het programma uitvoert, wordt er een .wav-bestand naar het opgegeven pad geschreven.

SSML gebruiken om spraakkenmerken aan te passen

U kunt SSML gebruiken om de toonhoogte, uitspraak, spreeksnelheid, volume en andere aspecten in de tekst naar spraakuitvoer af te stemmen door uw aanvragen vanuit een XML-schema in te dienen. In deze sectie ziet u een voorbeeld van het wijzigen van de stem. Zie het overzicht van Speech Synthesis Markup Language voor meer informatie.

Als u SSML wilt gaan gebruiken voor aanpassing, moet u een kleine wijziging aanbrengen waarmee de stem wordt gewijzigd.

  1. Maak een nieuw XML-bestand voor de SSML-configuratie in de hoofdprojectmap.

    <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 dit voorbeeld wordt het bestand ssml.xml. Het hoofdelement is altijd <speak>. Als u de tekst in een <voice> element terugloopt, kunt u de stem wijzigen met behulp van de name parameter. Zie Ondersteunde talen voor de volledige lijst met ondersteunde neurale stemmen.

  2. Wijzig de aanvraag voor spraaksynthese om te verwijzen naar uw XML-bestand. De aanvraag is doorgaans hetzelfde, maar in plaats van de functie SpeakTextAsync() gebruikt u SpeakSsmlAsync(). Deze functie verwacht een XML-tekenreeks. Laad eerst uw SSML-configuratie als een tekenreeks met behulp van File.ReadAllText(). Vanaf dit punt is het resultaatobject precies hetzelfde als eerdere voorbeelden.

    Notitie

    Als u Visual Studio gebruikt, vindt uw buildconfiguratie waarschijnlijk niet standaard uw XML-bestand. Klik met de rechtermuisknop op het XML-bestand en selecteer Eigenschappen. Bouwactie wijzigen in inhoud. Wijzig Kopiëren naar Uitvoermap om altijd te kopiëren.

    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");
    }
    

Notitie

Als u de stem wilt wijzigen zonder SSML te gebruiken, kunt u de eigenschap SpeechConfig instellen met behulp van SpeechConfig.SpeechSynthesisVoiceName = "en-US-AvaMultilingualNeural";.

Abonneren op synthesizer-evenementen

Mogelijk wilt u meer inzichten over de tekst naar spraakverwerking en resultaten. U wilt bijvoorbeeld weten wanneer de synthesizer start en stopt, of misschien wilt u weten over andere gebeurtenissen die tijdens de synthese zijn aangetroffen.

Tijdens het gebruik van speechSynthesizer voor tekst-naar-spraak kunt u zich abonneren op de gebeurtenissen in deze tabel:

Gebeurtenis Beschrijving Gebruiksscenario
BookmarkReached Signalen dat een bladwijzer is bereikt. Voor het activeren van een gebeurtenis die een bladwijzer heeft bereikt, is een bookmark element vereist in de SSML. Deze gebeurtenis rapporteert de verstreken tijd van de uitvoeraudio tussen het begin van de synthese en het bookmark element. De eigenschap van Text de gebeurtenis is de tekenreekswaarde die u hebt ingesteld in het kenmerk van mark de bladwijzer. De bookmark elementen worden niet gesproken. U kunt het bookmark element gebruiken om aangepaste markeringen in SSML in te voegen om de verschuiving van elke markering in de audiostream op te halen. Het bookmark element kan worden gebruikt om te verwijzen naar een specifieke locatie in de tekst- of tagvolgorde.
SynthesisCanceled Signalen dat de spraaksynthese is geannuleerd. U kunt bevestigen wanneer synthese wordt geannuleerd.
SynthesisCompleted Signalen dat spraaksynthese is voltooid. U kunt bevestigen wanneer de synthese is voltooid.
SynthesisStarted Signalen dat spraaksynthese is gestart. U kunt bevestigen wanneer de synthese is gestart.
Synthesizing Signalen dat spraaksynthese gaande is. Deze gebeurtenis wordt geactiveerd telkens wanneer de SDK een audiosegment van de Speech-service ontvangt. U kunt controleren wanneer de synthese wordt uitgevoerd.
VisemeReceived Signalen dat er een visemegebeurtenis is ontvangen. Visemes worden vaak gebruikt om de belangrijkste poses in geobserveerde spraak te vertegenwoordigen. Belangrijke poses zijn onder andere de positie van de lippen, de kaak en de tong bij het produceren van een bepaald telefoonme. U kunt visemes gebruiken om het gezicht van een teken te animeren terwijl spraakaudio wordt afgespeeld.
WordBoundary Signalen dat een woordgrens is ontvangen. Deze gebeurtenis wordt aan het begin van elk nieuw gesproken woord, leesteken en zin gegenereerd. De gebeurtenis rapporteert de tijdsverschil van het huidige woord, in tikken, vanaf het begin van de uitvoeraudio. Deze gebeurtenis rapporteert ook de tekenpositie in de invoertekst of SSML direct voordat het woord wordt gesproken. Deze gebeurtenis wordt vaak gebruikt om relatieve posities van de tekst en bijbehorende audio te verkrijgen. Misschien wilt u meer weten over een nieuw woord en vervolgens actie ondernemen op basis van de timing. U kunt bijvoorbeeld informatie krijgen waarmee u kunt bepalen wanneer en hoe lang woorden moeten worden gemarkeerd terwijl ze worden gesproken.

Notitie

Gebeurtenissen worden gegenereerd wanneer de uitvoeraudiogegevens beschikbaar komen, wat sneller is dan afspelen op een uitvoerapparaat. De beller moet streaming en realtime synchroniseren.

Hier volgt een voorbeeld waarin wordt getoond hoe u zich kunt abonneren op gebeurtenissen voor spraaksynthese. U kunt de instructies in de quickstart volgen, maar de inhoud van dat Program.cs bestand vervangen door de volgende C#-code:

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();
    }
}

U vindt meer tekst naar spraakvoorbeelden op GitHub.

Een aangepast eindpunt gebruiken

Het aangepaste eindpunt is functioneel identiek aan het standaardeindpunt dat wordt gebruikt voor tekst-naar-spraakaanvragen.

Een verschil is dat het EndpointId moet worden opgegeven om uw aangepaste stem te gebruiken via de Speech SDK. U kunt beginnen met de snelstartgids voor tekst naar spraak en vervolgens de code bijwerken met de EndpointId en SpeechSynthesisVoiceName.

var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);     
speechConfig.SpeechSynthesisVoiceName = "YourCustomVoiceName";
speechConfig.EndpointId = "YourEndpointId";

Als u een aangepaste stem wilt gebruiken via Speech Synthesis Markup Language (SSML), geeft u de modelnaam op als de spraaknaam. In dit voorbeeld wordt de YourCustomVoiceName stem gebruikt.

<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>

Een container uitvoeren en gebruiken

Spraakcontainers bieden websocket-api's voor query-eindpunten die toegankelijk zijn via de Speech SDK en Speech CLI. De Speech SDK en Speech CLI maken standaard gebruik van de openbare Speech-service. Als u de container wilt gebruiken, moet u de initialisatiemethode wijzigen. Gebruik een containerhost-URL in plaats van sleutel en regio.

Zie Speech-containers installeren en uitvoeren met Docker voor meer informatie over containers.

Referentiedocumentatiepakket (NuGet) | Aanvullende voorbeelden op GitHub |

In deze handleiding leert u algemene ontwerppatronen voor het uitvoeren van tekst-naar-spraaksynthese.

Zie Wat is tekst naar spraak voor meer informatie over de volgende gebieden ?

  • Antwoorden krijgen als in-memory streams.
  • Voorbeeldsnelheid en bitsnelheid van uitvoer aanpassen.
  • Syntheseaanvragen verzenden met behulp van Speech Synthesis Markup Language (SSML).
  • Neurale stemmen gebruiken.
  • Abonneren op gebeurtenissen en reageren op resultaten.

Synthesetaal en spraak selecteren

De functie tekst-naar-spraak in de Speech-service ondersteunt meer dan 400 stemmen en meer dan 140 talen en varianten. Raadpleeg de volledige lijst met ondersteunde tekst naar spraakinstellingen of probeer deze in de spraakgalerie.

Geef de taal of stem van de SpeechConfig-klasse op die overeenkomt met de invoertekst en gebruik de opgegeven stem. In het volgende codefragment ziet u hoe deze techniek werkt:

void synthesizeSpeech()
{
    auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
    // Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
    speechConfig->SetSpeechSynthesisLanguage("en-US"); 
    speechConfig->SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");
}

Alle neurale stemmen zijn meertalige en vloeiende taal en Engels. Als de invoertekst in het Engels bijvoorbeeld 'Ik ben enthousiast om tekst naar spraak te proberen' is en u selecteert es-ES-ElviraNeural, wordt de tekst in het Engels gesproken met een Spaans accent.

Als de stem de taal van de invoertekst niet spreekt, maakt de Speech-service geen gesynthetiseerde audio. Zie Taal- en spraakondersteuning voor de Speech-service voor een volledige lijst met ondersteunde neurale stemmen.

Notitie

De standaardstem is de eerste stem die per landinstelling wordt geretourneerd vanuit de Voice List-API.

De stem die spreekt, wordt als volgt bepaald in volgorde van prioriteit:

  • Als u dit niet instelt SpeechSynthesisVoiceName of SpeechSynthesisLanguage, wordt de standaardstem voor en-US gesproken tekst gebruikt.
  • Als u alleen instelt SpeechSynthesisLanguage, spreekt de standaardstem voor de opgegeven landinstelling.
  • Als beide SpeechSynthesisVoiceName zijn SpeechSynthesisLanguage ingesteld, wordt de SpeechSynthesisLanguage instelling genegeerd. De stem die u opgeeft met behulp van SpeechSynthesisVoiceName spreekt.
  • Als het spraakelement is ingesteld met behulp van Speech Synthesis Markup Language (SSML), worden de SpeechSynthesisVoiceName en SpeechSynthesisLanguage instellingen genegeerd.

Spraak synthetiseren naar een bestand

Maak een SpeechSynthesizer-object . Dit object dat wordt weergegeven in de volgende codefragmenten voert tekst uit naar spraakconversies en uitvoer naar luidsprekers, bestanden of andere uitvoerstromen. SpeechSynthesizer accepteert als parameters:

  1. Maak een AudioConfig exemplaar om de uitvoer automatisch naar een .wav-bestand te schrijven met behulp van de FromWavFileOutput() functie:

    void synthesizeSpeech()
    {
        auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
        auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav");
    }
    
  2. Instantieer een SpeechSynthesizer exemplaar. Geef uw speechConfig object en het audioConfig object door als parameters. Als u spraak wilt omzetten en naar een bestand wilt schrijven, voert u deze uit SpeakTextAsync() met een tekenreeks tekst.

    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();
    }
    

Wanneer u het programma uitvoert, wordt er een gesynthetiseerd .wav-bestand gemaakt, dat wordt geschreven naar de locatie die u opgeeft. Dit resultaat is een goed voorbeeld van het meest eenvoudige gebruik. Vervolgens kunt u de uitvoer aanpassen en het uitvoerantwoord verwerken als een stroom in het geheugen voor het werken met aangepaste scenario's.

Synthetiseren naar de uitvoer van de luidspreker

Als u gesynthetiseerde spraak wilt uitvoeren naar het huidige actieve uitvoerapparaat zoals een luidspreker, laat u de AudioConfig parameter weg wanneer u het SpeechSynthesizer exemplaar maakt. Hier volgt een voorbeeld:

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();
}

Een resultaat ophalen als een stroom in het geheugen

U kunt de resulterende audiogegevens gebruiken als een in-memory stream in plaats van rechtstreeks naar een bestand te schrijven. Met een in-memory stream kunt u aangepast gedrag bouwen:

  • Abstract de resulterende bytematrix als een zoekbare stroom voor aangepaste downstreamservices.
  • Integreer het resultaat met andere API's of services.
  • Wijzig de audiogegevens, schrijf aangepaste .wav headers en voer gerelateerde taken uit.

U kunt deze wijziging aanbrengen in het vorige voorbeeld. Verwijder eerst het AudioConfig blok, omdat u het uitvoergedrag vanaf dit punt handmatig beheert voor meer controle. Geef NULL deze door AudioConfig in de SpeechSynthesizer constructor.

Notitie

Het doorgeven NULL voor AudioConfig, in plaats van deze weg te laten zoals in het vorige voorbeeld van de luidsprekeruitvoer, speelt de audio niet standaard af op het huidige actieve uitvoerapparaat.

Sla het resultaat op in een SpeechSynthesisResult-variabele . De GetAudioData getter retourneert een byte [] exemplaar voor de uitvoergegevens. U kunt met dit byte [] exemplaar handmatig werken of u kunt de Klasse AudioDataStream gebruiken om de stroom in het geheugen te beheren.

In dit voorbeeld gebruikt u de AudioDataStream.FromResult() statische functie om een stroom op te halen uit het resultaat:

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);
}

Op dit moment kunt u elk aangepast gedrag implementeren met behulp van het resulterende stream object.

Audio-indeling aanpassen

U kunt kenmerken voor audio-uitvoer aanpassen, waaronder:

  • Audiobestandstype
  • Samplefrequentie
  • Bitdiepte

Als u de audio-indeling wilt wijzigen, gebruikt u de SetSpeechSynthesisOutputFormat() functie voor het SpeechConfig object. Deze functie verwacht een exemplaar van het enum type SpeechSynthesisOutputFormat. Gebruik de enum optie om de uitvoerindeling te selecteren. Zie de lijst met audio-indelingen voor beschikbare indelingen.

Er zijn verschillende opties voor verschillende bestandstypen, afhankelijk van uw vereisten. Onbewerkte indelingen Raw24Khz16BitMonoPcm bevatten standaard geen audioheaders. Gebruik onbewerkte indelingen alleen in een van deze situaties:

  • U weet dat uw downstream-implementatie een onbewerkte bitstream kan decoderen.
  • U bent van plan om handmatig headers te bouwen op basis van factoren zoals bitdiepte, samplefrequentie en aantal kanalen.

In dit voorbeeld wordt de RIFF-indeling Riff24Khz16BitMonoPcm met hoge kwaliteit opgegeven door het object in te SpeechConfig stellenSpeechSynthesisOutputFormat. Net als in het voorbeeld in de vorige sectie, gebruikt u AudioDataStream om een stroom in het geheugen van het resultaat te verkrijgen en vervolgens naar een bestand te schrijven.

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();
}

Wanneer u het programma uitvoert, wordt er een .wav-bestand naar het opgegeven pad geschreven.

SSML gebruiken om spraakkenmerken aan te passen

U kunt SSML gebruiken om de toonhoogte, uitspraak, spreeksnelheid, volume en andere aspecten in de tekst naar spraakuitvoer af te stemmen door uw aanvragen vanuit een XML-schema in te dienen. In deze sectie ziet u een voorbeeld van het wijzigen van de stem. Zie het overzicht van Speech Synthesis Markup Language voor meer informatie.

Als u SSML wilt gaan gebruiken voor aanpassing, moet u een kleine wijziging aanbrengen waarmee de stem wordt gewijzigd.

  1. Maak een nieuw XML-bestand voor de SSML-configuratie in de hoofdprojectmap.

    <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 dit voorbeeld wordt het bestand ssml.xml. Het hoofdelement is altijd <speak>. Als u de tekst in een <voice> element terugloopt, kunt u de stem wijzigen met behulp van de name parameter. Zie Ondersteunde talen voor de volledige lijst met ondersteunde neurale stemmen.

  2. Wijzig de aanvraag voor spraaksynthese om te verwijzen naar uw XML-bestand. De aanvraag is meestal hetzelfde. In plaats van de SpeakTextAsync() functie te gebruiken, gebruikt SpeakSsmlAsync()u . Deze functie verwacht een XML-tekenreeks. Laad eerst uw SSML-configuratie als een tekenreeks. Vanaf dit punt is het resultaatobject precies hetzelfde als eerdere voorbeelden.

    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();
    }
    

Notitie

Als u de stem wilt wijzigen zonder SSML te gebruiken, kunt u de eigenschap SpeechConfig instellen met behulp van SpeechConfig.SetSpeechSynthesisVoiceName("en-US-AndrewMultilingualNeural").

Abonneren op synthesizer-evenementen

Mogelijk wilt u meer inzichten over de tekst naar spraakverwerking en resultaten. U wilt bijvoorbeeld weten wanneer de synthesizer start en stopt, of misschien wilt u weten over andere gebeurtenissen die tijdens de synthese zijn aangetroffen.

Tijdens het gebruik van speechSynthesizer voor tekst-naar-spraak kunt u zich abonneren op de gebeurtenissen in deze tabel:

Gebeurtenis Beschrijving Gebruiksscenario
BookmarkReached Signalen dat een bladwijzer is bereikt. Voor het activeren van een gebeurtenis die een bladwijzer heeft bereikt, is een bookmark element vereist in de SSML. Deze gebeurtenis rapporteert de verstreken tijd van de uitvoeraudio tussen het begin van de synthese en het bookmark element. De eigenschap van Text de gebeurtenis is de tekenreekswaarde die u hebt ingesteld in het kenmerk van mark de bladwijzer. De bookmark elementen worden niet gesproken. U kunt het bookmark element gebruiken om aangepaste markeringen in SSML in te voegen om de verschuiving van elke markering in de audiostream op te halen. Het bookmark element kan worden gebruikt om te verwijzen naar een specifieke locatie in de tekst- of tagvolgorde.
SynthesisCanceled Signalen dat de spraaksynthese is geannuleerd. U kunt bevestigen wanneer synthese wordt geannuleerd.
SynthesisCompleted Signalen dat spraaksynthese is voltooid. U kunt bevestigen wanneer de synthese is voltooid.
SynthesisStarted Signalen dat spraaksynthese is gestart. U kunt bevestigen wanneer de synthese is gestart.
Synthesizing Signalen dat spraaksynthese gaande is. Deze gebeurtenis wordt geactiveerd telkens wanneer de SDK een audiosegment van de Speech-service ontvangt. U kunt controleren wanneer de synthese wordt uitgevoerd.
VisemeReceived Signalen dat er een visemegebeurtenis is ontvangen. Visemes worden vaak gebruikt om de belangrijkste poses in geobserveerde spraak te vertegenwoordigen. Belangrijke poses zijn onder andere de positie van de lippen, de kaak en de tong bij het produceren van een bepaald telefoonme. U kunt visemes gebruiken om het gezicht van een teken te animeren terwijl spraakaudio wordt afgespeeld.
WordBoundary Signalen dat een woordgrens is ontvangen. Deze gebeurtenis wordt aan het begin van elk nieuw gesproken woord, leesteken en zin gegenereerd. De gebeurtenis rapporteert de tijdsverschil van het huidige woord, in tikken, vanaf het begin van de uitvoeraudio. Deze gebeurtenis rapporteert ook de tekenpositie in de invoertekst of SSML direct voordat het woord wordt gesproken. Deze gebeurtenis wordt vaak gebruikt om relatieve posities van de tekst en bijbehorende audio te verkrijgen. Misschien wilt u meer weten over een nieuw woord en vervolgens actie ondernemen op basis van de timing. U kunt bijvoorbeeld informatie krijgen waarmee u kunt bepalen wanneer en hoe lang woorden moeten worden gemarkeerd terwijl ze worden gesproken.

Notitie

Gebeurtenissen worden gegenereerd wanneer de uitvoeraudiogegevens beschikbaar komen, wat sneller is dan afspelen op een uitvoerapparaat. De beller moet streaming en realtime synchroniseren.

Hier volgt een voorbeeld waarin wordt getoond hoe u zich kunt abonneren op gebeurtenissen voor spraaksynthese. U kunt de instructies in de quickstart volgen, maar de inhoud van dat main.cpp bestand vervangen door de volgende code:

#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
}

U vindt meer tekst naar spraakvoorbeelden op GitHub.

Een aangepast eindpunt gebruiken

Het aangepaste eindpunt is functioneel identiek aan het standaardeindpunt dat wordt gebruikt voor tekst-naar-spraakaanvragen.

Een verschil is dat het EndpointId moet worden opgegeven om uw aangepaste stem te gebruiken via de Speech SDK. U kunt beginnen met de snelstartgids voor tekst naar spraak en vervolgens de code bijwerken met de EndpointId en SpeechSynthesisVoiceName.

auto speechConfig = SpeechConfig::FromSubscription(speechKey, speechRegion);
speechConfig->SetSpeechSynthesisVoiceName("YourCustomVoiceName");
speechConfig->SetEndpointId("YourEndpointId");

Als u een aangepaste stem wilt gebruiken via Speech Synthesis Markup Language (SSML), geeft u de modelnaam op als de spraaknaam. In dit voorbeeld wordt de YourCustomVoiceName stem gebruikt.

<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>

Een container uitvoeren en gebruiken

Spraakcontainers bieden websocket-api's voor query-eindpunten die toegankelijk zijn via de Speech SDK en Speech CLI. De Speech SDK en Speech CLI maken standaard gebruik van de openbare Speech-service. Als u de container wilt gebruiken, moet u de initialisatiemethode wijzigen. Gebruik een containerhost-URL in plaats van sleutel en regio.

Zie Speech-containers installeren en uitvoeren met Docker voor meer informatie over containers.

Referentiedocumentatiepakket (Go) | Aanvullende voorbeelden op GitHub |

In deze handleiding leert u algemene ontwerppatronen voor het uitvoeren van tekst-naar-spraaksynthese.

Zie Wat is tekst naar spraak voor meer informatie over de volgende gebieden ?

  • Antwoorden krijgen als in-memory streams.
  • Voorbeeldsnelheid en bitsnelheid van uitvoer aanpassen.
  • Syntheseaanvragen verzenden met behulp van Speech Synthesis Markup Language (SSML).
  • Neurale stemmen gebruiken.
  • Abonneren op gebeurtenissen en reageren op resultaten.

Vereisten

De Speech-SDK installeren

Voordat u iets kunt doen, moet u de Speech SDK voor Go installeren.

Tekst naar spraak naar spreker

Gebruik het volgende codevoorbeeld om spraaksynthese uit te voeren op uw standaardapparaat voor audio-uitvoer. Vervang de variabelen subscription en region door uw spraaksleutel en locatie/regio. Als u het script uitvoert, wordt de invoertekst voor de standaardluidspreker weergegeven.

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)
            }
        }
    }
}

Voer de volgende opdrachten uit om een go.mod-bestand te maken dat is gekoppeld aan onderdelen die worden gehost op GitHub:

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

Bouw nu de code en voer deze uit:

go build
go run quickstart

Zie de SpeechConfig en SpeechSynthesizer referentiedocumenten voor gedetailleerde informatie over de klassen.

Tekst naar spraak naar in-memory stream

U kunt de resulterende audiogegevens gebruiken als een in-memory stream in plaats van rechtstreeks naar een bestand te schrijven. Met een in-memory stream kunt u aangepast gedrag bouwen:

  • Abstract de resulterende bytematrix als een zoekbare stroom voor aangepaste downstreamservices.
  • Integreer het resultaat met andere API's of services.
  • Wijzig de audiogegevens, schrijf aangepaste .wav headers en voer gerelateerde taken uit.

U kunt deze wijziging aanbrengen in het vorige voorbeeld. Verwijder het AudioConfig blok, omdat u het uitvoergedrag vanaf dit punt handmatig beheert voor een betere controle. Geef nil vervolgens de AudioConfigSpeechSynthesizer constructor door.

Notitie

AudioConfigAls u dit doorgeeftnil, in plaats van deze weg te laten zoals u in het vorige voorbeeld van de luidsprekeruitvoer hebt gedaan, wordt de audio niet standaard afgespeeld op het huidige actieve uitvoerapparaat.

Sla het resultaat op in een SpeechSynthesisResult variabele. De AudioData eigenschap retourneert een []byte exemplaar voor de uitvoergegevens. U kunt met dit []byte exemplaar handmatig werken of u kunt de AudioDataStream klasse gebruiken om de stroom in het geheugen te beheren. In dit voorbeeld gebruikt u de NewAudioDataStreamFromSpeechSynthesisResult() statische functie om een stroom op te halen uit het resultaat.

Vervang de variabelen subscription en region door uw spraaksleutel en locatie/regio:

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))
    }
}

Voer de volgende opdrachten uit om een go.mod-bestand te maken dat is gekoppeld aan onderdelen die worden gehost op GitHub:

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

Bouw nu de code en voer deze uit:

go build
go run quickstart

Zie de SpeechConfig en SpeechSynthesizer referentiedocumenten voor gedetailleerde informatie over de klassen.

Synthesetaal en spraak selecteren

De functie tekst-naar-spraak in de Speech-service ondersteunt meer dan 400 stemmen en meer dan 140 talen en varianten. U kunt de volledige lijst ophalen of ze uitproberen in de spraakgalerie.

Geef de taal of stem op van SpeechConfig uw invoertekst en gebruik de opgegeven stem:

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")

Alle neurale stemmen zijn meertalige en vloeiende taal en Engels. Als de invoertekst in het Engels bijvoorbeeld 'Ik ben enthousiast om tekst naar spraak te proberen' is en u selecteert es-ES-ElviraNeural, wordt de tekst in het Engels gesproken met een Spaans accent.

Als de stem de taal van de invoertekst niet spreekt, maakt de Speech-service geen gesynthetiseerde audio. Zie Taal- en spraakondersteuning voor de Speech-service voor een volledige lijst met ondersteunde neurale stemmen.

Notitie

De standaardstem is de eerste stem die per landinstelling wordt geretourneerd vanuit de Voice List-API.

De stem die spreekt, wordt als volgt bepaald in volgorde van prioriteit:

  • Als u dit niet instelt SpeechSynthesisVoiceName of SpeechSynthesisLanguage, wordt de standaardstem voor en-US gesproken tekst gebruikt.
  • Als u alleen instelt SpeechSynthesisLanguage, spreekt de standaardstem voor de opgegeven landinstelling.
  • Als beide SpeechSynthesisVoiceName zijn SpeechSynthesisLanguage ingesteld, wordt de SpeechSynthesisLanguage instelling genegeerd. De stem die u opgeeft met behulp van SpeechSynthesisVoiceName spreekt.
  • Als het spraakelement is ingesteld met behulp van Speech Synthesis Markup Language (SSML), worden de SpeechSynthesisVoiceName en SpeechSynthesisLanguage instellingen genegeerd.

SSML gebruiken om spraakkenmerken aan te passen

U kunt SSML (Speech Synthesis Markup Language) gebruiken om de toonhoogte, uitspraak, spreeksnelheid, volume en meer in de tekst af te stemmen op spraakuitvoer door uw aanvragen vanuit een XML-schema in te dienen. In deze sectie ziet u een voorbeeld van het wijzigen van de stem. Zie het overzicht van Speech Synthesis Markup Language voor meer informatie.

Als u SSML wilt gaan gebruiken voor aanpassing, moet u een kleine wijziging aanbrengen waarmee de stem wordt gewijzigd.

Maak eerst een nieuw XML-bestand voor de SSML-configuratie in de hoofdprojectmap. In dit voorbeeld is het ssml.xml. Het hoofdelement is altijd <speak>. Als u de tekst in een <voice> element terugloopt, kunt u de stem wijzigen met behulp van de name parameter. Zie Ondersteunde talen voor de volledige lijst met ondersteunde neurale stemmen.

<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>

Vervolgens moet u de aanvraag voor spraaksynthese wijzigen om te verwijzen naar uw XML-bestand. De aanvraag is doorgaans hetzelfde, maar in plaats van de functie SpeakTextAsync() gebruikt u SpeakSsmlAsync(). Deze functie verwacht een XML-tekenreeks, dus u laadt eerst uw SSML-configuratie als een tekenreeks. Vanaf dit punt is het resultaatobject precies hetzelfde als eerdere voorbeelden.

Notitie

Als u de stem wilt instellen zonder SSML te gebruiken, kunt u de eigenschap SpeechConfig instellen met behulp van speechConfig.SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural").

Abonneren op synthesizer-evenementen

Mogelijk wilt u meer inzichten over de tekst naar spraakverwerking en resultaten. U wilt bijvoorbeeld weten wanneer de synthesizer start en stopt, of misschien wilt u weten over andere gebeurtenissen die tijdens de synthese zijn aangetroffen.

Tijdens het gebruik van speechSynthesizer voor tekst-naar-spraak kunt u zich abonneren op de gebeurtenissen in deze tabel:

Gebeurtenis Beschrijving Gebruiksscenario
BookmarkReached Signalen dat een bladwijzer is bereikt. Voor het activeren van een gebeurtenis die een bladwijzer heeft bereikt, is een bookmark element vereist in de SSML. Deze gebeurtenis rapporteert de verstreken tijd van de uitvoeraudio tussen het begin van de synthese en het bookmark element. De eigenschap van Text de gebeurtenis is de tekenreekswaarde die u hebt ingesteld in het kenmerk van mark de bladwijzer. De bookmark elementen worden niet gesproken. U kunt het bookmark element gebruiken om aangepaste markeringen in SSML in te voegen om de verschuiving van elke markering in de audiostream op te halen. Het bookmark element kan worden gebruikt om te verwijzen naar een specifieke locatie in de tekst- of tagvolgorde.
SynthesisCanceled Signalen dat de spraaksynthese is geannuleerd. U kunt bevestigen wanneer synthese wordt geannuleerd.
SynthesisCompleted Signalen dat spraaksynthese is voltooid. U kunt bevestigen wanneer de synthese is voltooid.
SynthesisStarted Signalen dat spraaksynthese is gestart. U kunt bevestigen wanneer de synthese is gestart.
Synthesizing Signalen dat spraaksynthese gaande is. Deze gebeurtenis wordt geactiveerd telkens wanneer de SDK een audiosegment van de Speech-service ontvangt. U kunt controleren wanneer de synthese wordt uitgevoerd.
VisemeReceived Signalen dat er een visemegebeurtenis is ontvangen. Visemes worden vaak gebruikt om de belangrijkste poses in geobserveerde spraak te vertegenwoordigen. Belangrijke poses zijn onder andere de positie van de lippen, de kaak en de tong bij het produceren van een bepaald telefoonme. U kunt visemes gebruiken om het gezicht van een teken te animeren terwijl spraakaudio wordt afgespeeld.
WordBoundary Signalen dat een woordgrens is ontvangen. Deze gebeurtenis wordt aan het begin van elk nieuw gesproken woord, leesteken en zin gegenereerd. De gebeurtenis rapporteert de tijdsverschil van het huidige woord, in tikken, vanaf het begin van de uitvoeraudio. Deze gebeurtenis rapporteert ook de tekenpositie in de invoertekst of SSML direct voordat het woord wordt gesproken. Deze gebeurtenis wordt vaak gebruikt om relatieve posities van de tekst en bijbehorende audio te verkrijgen. Misschien wilt u meer weten over een nieuw woord en vervolgens actie ondernemen op basis van de timing. U kunt bijvoorbeeld informatie krijgen waarmee u kunt bepalen wanneer en hoe lang woorden moeten worden gemarkeerd terwijl ze worden gesproken.

Notitie

Gebeurtenissen worden gegenereerd wanneer de uitvoeraudiogegevens beschikbaar komen, wat sneller is dan afspelen op een uitvoerapparaat. De beller moet streaming en realtime synchroniseren.

Hier volgt een voorbeeld waarin wordt getoond hoe u zich kunt abonneren op gebeurtenissen voor spraaksynthese. U kunt de instructies in de quickstart volgen, maar de inhoud van dat speech-synthesis.go bestand vervangen door de volgende Go-code:

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)
        }
    }
}

U vindt meer tekst naar spraakvoorbeelden op GitHub.

Een container uitvoeren en gebruiken

Spraakcontainers bieden websocket-api's voor query-eindpunten die toegankelijk zijn via de Speech SDK en Speech CLI. De Speech SDK en Speech CLI maken standaard gebruik van de openbare Speech-service. Als u de container wilt gebruiken, moet u de initialisatiemethode wijzigen. Gebruik een containerhost-URL in plaats van sleutel en regio.

Zie Speech-containers installeren en uitvoeren met Docker voor meer informatie over containers.

Referentiedocumentatie | Aanvullende voorbeelden op GitHub

In deze handleiding leert u algemene ontwerppatronen voor het uitvoeren van tekst-naar-spraaksynthese.

Zie Wat is tekst naar spraak voor meer informatie over de volgende gebieden ?

  • Antwoorden krijgen als in-memory streams.
  • Voorbeeldsnelheid en bitsnelheid van uitvoer aanpassen.
  • Syntheseaanvragen verzenden met behulp van Speech Synthesis Markup Language (SSML).
  • Neurale stemmen gebruiken.
  • Abonneren op gebeurtenissen en reageren op resultaten.

Synthesetaal en spraak selecteren

De functie tekst-naar-spraak in de Speech-service ondersteunt meer dan 400 stemmen en meer dan 140 talen en varianten. U kunt de volledige lijst ophalen of ze uitproberen in de spraakgalerie.

Geef de taal of stem van SpeechConfig op die overeenkomt met uw invoertekst en gebruik de opgegeven stem. In het volgende codefragment ziet u hoe deze techniek werkt:

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");
}

Alle neurale stemmen zijn meertalige en vloeiende taal en Engels. Als de invoertekst in het Engels bijvoorbeeld 'Ik ben enthousiast om tekst naar spraak te proberen' is en u selecteert es-ES-ElviraNeural, wordt de tekst in het Engels gesproken met een Spaans accent.

Als de stem de taal van de invoertekst niet spreekt, maakt de Speech-service geen gesynthetiseerde audio. Zie Taal- en spraakondersteuning voor de Speech-service voor een volledige lijst met ondersteunde neurale stemmen.

Notitie

De standaardstem is de eerste stem die per landinstelling wordt geretourneerd vanuit de Voice List-API.

De stem die spreekt, wordt als volgt bepaald in volgorde van prioriteit:

  • Als u dit niet instelt SpeechSynthesisVoiceName of SpeechSynthesisLanguage, wordt de standaardstem voor en-US gesproken tekst gebruikt.
  • Als u alleen instelt SpeechSynthesisLanguage, spreekt de standaardstem voor de opgegeven landinstelling.
  • Als beide SpeechSynthesisVoiceName zijn SpeechSynthesisLanguage ingesteld, wordt de SpeechSynthesisLanguage instelling genegeerd. De stem die u hebt opgegeven met behulp van SpeechSynthesisVoiceName spreekt.
  • Als het spraakelement is ingesteld met behulp van Speech Synthesis Markup Language (SSML), worden de SpeechSynthesisVoiceName en SpeechSynthesisLanguage instellingen genegeerd.

Spraak synthetiseren naar een bestand

Maak een SpeechSynthesizer object. Met dit object wordt tekst uitgevoerd naar spraakconversies en uitvoer naar luidsprekers, bestanden of andere uitvoerstromen. SpeechSynthesizer accepteert als parameters:

  • Het SpeechConfig object dat u in de vorige stap hebt gemaakt.
  • Een AudioConfig object dat aangeeft hoe uitvoerresultaten moeten worden verwerkt.
  1. Maak een AudioConfig exemplaar om de uitvoer automatisch naar een .wav-bestand te schrijven met behulp van de fromWavFileOutput() statische functie:

    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav");
    }
    
  2. Instantieer een SpeechSynthesizer exemplaar. Geef uw speechConfig object en het audioConfig object door als parameters. Als u spraak wilt omzetten en naar een bestand wilt schrijven, voert u deze uit SpeakText() met een tekenreeks tekst.

    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");
    }
    

Wanneer u het programma uitvoert, wordt er een gesynthetiseerd .wav-bestand gemaakt, dat wordt geschreven naar de locatie die u opgeeft. Dit resultaat is een goed voorbeeld van het meest eenvoudige gebruik. Vervolgens kunt u de uitvoer aanpassen en het uitvoerantwoord verwerken als een stroom in het geheugen voor het werken met aangepaste scenario's.

Synthetiseren naar de uitvoer van de luidspreker

Mogelijk wilt u meer inzichten over de tekst naar spraakverwerking en resultaten. U wilt bijvoorbeeld weten wanneer de synthesizer start en stopt, of misschien wilt u weten over andere gebeurtenissen die tijdens de synthese zijn aangetroffen.

Als u gesynthetiseerde spraak wilt uitvoeren naar het huidige actieve uitvoerapparaat zoals een luidspreker, instantiëren AudioConfig met behulp van de fromDefaultSpeakerOutput() statische functie. Hier volgt een voorbeeld:

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");
}

Een resultaat ophalen als een stroom in het geheugen

U kunt de resulterende audiogegevens gebruiken als een in-memory stream in plaats van rechtstreeks naar een bestand te schrijven. Met een in-memory stream kunt u aangepast gedrag bouwen:

  • Abstract de resulterende bytematrix als een zoekbare stroom voor aangepaste downstreamservices.
  • Integreer het resultaat met andere API's of services.
  • Wijzig de audiogegevens, schrijf aangepaste .wav headers en voer gerelateerde taken uit.

U kunt deze wijziging aanbrengen in het vorige voorbeeld. Verwijder eerst het AudioConfig blok, omdat u het uitvoergedrag vanaf dit punt handmatig beheert voor meer controle. Geef null vervolgens de AudioConfigSpeechSynthesizer constructor door.

Notitie

Het doorgeven null van AudioConfig, in plaats van het weglaten zoals u in het vorige voorbeeld van de luidsprekeruitvoer hebt gedaan, speelt de audio niet standaard af op het huidige actieve uitvoerapparaat.

Sla het resultaat op in een SpeechSynthesisResult variabele. De SpeechSynthesisResult.getAudioData() functie retourneert een byte [] exemplaar van de uitvoergegevens. U kunt met dit byte [] exemplaar handmatig werken of u kunt de AudioDataStream klasse gebruiken om de stroom in het geheugen te beheren.

In dit voorbeeld gebruikt u de AudioDataStream.fromResult() statische functie om een stroom op te halen uit het resultaat:

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());
}

Op dit moment kunt u elk aangepast gedrag implementeren met behulp van het resulterende stream object.

Audio-indeling aanpassen

U kunt kenmerken voor audio-uitvoer aanpassen, waaronder:

  • Audiobestandstype
  • Samplefrequentie
  • Bitdiepte

Als u de audio-indeling wilt wijzigen, gebruikt u de functie setSpeechSynthesisOutputFormat() op het SpeechConfig-object. Deze functie verwacht een exemplaar van het enum type SpeechSynthesisOutputFormat. Gebruik de enum optie om de uitvoerindeling te selecteren. Zie de lijst met audio-indelingen voor beschikbare indelingen.

Er zijn verschillende opties voor verschillende bestandstypen, afhankelijk van uw vereisten. Onbewerkte indelingen Raw24Khz16BitMonoPcm bevatten standaard geen audioheaders. Gebruik onbewerkte indelingen alleen in een van deze situaties:

  • U weet dat uw downstream-implementatie een onbewerkte bitstream kan decoderen.
  • U bent van plan om handmatig headers te bouwen op basis van factoren zoals bitdiepte, samplefrequentie en aantal kanalen.

In dit voorbeeld wordt de RIFF-indeling Riff24Khz16BitMonoPcm met hoge kwaliteit opgegeven door het object in te SpeechConfig stellenSpeechSynthesisOutputFormat. Net als in het voorbeeld in de vorige sectie, gebruikt u AudioDataStream om een stroom in het geheugen van het resultaat te verkrijgen en vervolgens naar een bestand te schrijven.

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");
}

Wanneer u het programma uitvoert, wordt er een .wav-bestand naar het opgegeven pad geschreven.

SSML gebruiken om spraakkenmerken aan te passen

U kunt SSML gebruiken om de toonhoogte, uitspraak, spreeksnelheid, volume en andere aspecten in de tekst naar spraakuitvoer af te stemmen door uw aanvragen vanuit een XML-schema in te dienen. In deze sectie ziet u een voorbeeld van het wijzigen van de stem. Zie het SSML-artikel voor meer informatie.

Als u SSML wilt gaan gebruiken voor aanpassing, moet u een kleine wijziging aanbrengen waarmee de stem wordt gewijzigd.

  1. Maak een nieuw XML-bestand voor de SSML-configuratie in de hoofdprojectmap.

    <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 dit voorbeeld wordt het bestand ssml.xml. Het hoofdelement is altijd <speak>. Als u de tekst in een <voice> element terugloopt, kunt u de stem wijzigen met behulp van de name parameter. Zie Ondersteunde talen voor de volledige lijst met ondersteunde neurale stemmen.

  2. Wijzig de aanvraag voor spraaksynthese om te verwijzen naar uw XML-bestand. De aanvraag is meestal hetzelfde. In plaats van de SpeakText() functie te gebruiken, gebruikt SpeakSsml()u . Deze functie verwacht een XML-tekenreeks, dus maak eerst een functie om een XML-bestand te laden en als een tekenreeks te retourneren:

    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.";
        }
    }
    

    Op dit moment is het resultaatobject precies hetzelfde als de vorige voorbeelden:

    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");
    }
    

Notitie

Als u de stem wilt wijzigen zonder SSML te gebruiken, stelt u de eigenschap SpeechConfig in met behulp van SpeechConfig.setSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");.

Abonneren op synthesizer-evenementen

Mogelijk wilt u meer inzichten over de tekst naar spraakverwerking en resultaten. U wilt bijvoorbeeld weten wanneer de synthesizer start en stopt, of misschien wilt u weten over andere gebeurtenissen die tijdens de synthese zijn aangetroffen.

Tijdens het gebruik van speechSynthesizer voor tekst-naar-spraak kunt u zich abonneren op de gebeurtenissen in deze tabel:

Gebeurtenis Beschrijving Gebruiksscenario
BookmarkReached Signalen dat een bladwijzer is bereikt. Voor het activeren van een gebeurtenis die een bladwijzer heeft bereikt, is een bookmark element vereist in de SSML. Deze gebeurtenis rapporteert de verstreken tijd van de uitvoeraudio tussen het begin van de synthese en het bookmark element. De eigenschap van Text de gebeurtenis is de tekenreekswaarde die u hebt ingesteld in het kenmerk van mark de bladwijzer. De bookmark elementen worden niet gesproken. U kunt het bookmark element gebruiken om aangepaste markeringen in SSML in te voegen om de verschuiving van elke markering in de audiostream op te halen. Het bookmark element kan worden gebruikt om te verwijzen naar een specifieke locatie in de tekst- of tagvolgorde.
SynthesisCanceled Signalen dat de spraaksynthese is geannuleerd. U kunt bevestigen wanneer synthese wordt geannuleerd.
SynthesisCompleted Signalen dat spraaksynthese is voltooid. U kunt bevestigen wanneer de synthese is voltooid.
SynthesisStarted Signalen dat spraaksynthese is gestart. U kunt bevestigen wanneer de synthese is gestart.
Synthesizing Signalen dat spraaksynthese gaande is. Deze gebeurtenis wordt geactiveerd telkens wanneer de SDK een audiosegment van de Speech-service ontvangt. U kunt controleren wanneer de synthese wordt uitgevoerd.
VisemeReceived Signalen dat er een visemegebeurtenis is ontvangen. Visemes worden vaak gebruikt om de belangrijkste poses in geobserveerde spraak te vertegenwoordigen. Belangrijke poses zijn onder andere de positie van de lippen, de kaak en de tong bij het produceren van een bepaald telefoonme. U kunt visemes gebruiken om het gezicht van een teken te animeren terwijl spraakaudio wordt afgespeeld.
WordBoundary Signalen dat een woordgrens is ontvangen. Deze gebeurtenis wordt aan het begin van elk nieuw gesproken woord, leesteken en zin gegenereerd. De gebeurtenis rapporteert de tijdsverschil van het huidige woord, in tikken, vanaf het begin van de uitvoeraudio. Deze gebeurtenis rapporteert ook de tekenpositie in de invoertekst of SSML direct voordat het woord wordt gesproken. Deze gebeurtenis wordt vaak gebruikt om relatieve posities van de tekst en bijbehorende audio te verkrijgen. Misschien wilt u meer weten over een nieuw woord en vervolgens actie ondernemen op basis van de timing. U kunt bijvoorbeeld informatie krijgen waarmee u kunt bepalen wanneer en hoe lang woorden moeten worden gemarkeerd terwijl ze worden gesproken.

Notitie

Gebeurtenissen worden gegenereerd wanneer de uitvoeraudiogegevens beschikbaar komen, wat sneller is dan afspelen op een uitvoerapparaat. De beller moet streaming en realtime synchroniseren.

Hier volgt een voorbeeld waarin wordt getoond hoe u zich kunt abonneren op gebeurtenissen voor spraaksynthese. U kunt de instructies in de quickstart volgen, maar de inhoud van dat SpeechSynthesis.java bestand vervangen door de volgende Java-code:

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);
    }
}

U vindt meer tekst naar spraakvoorbeelden op GitHub.

Een aangepast eindpunt gebruiken

Het aangepaste eindpunt is functioneel identiek aan het standaardeindpunt dat wordt gebruikt voor tekst-naar-spraakaanvragen.

Een verschil is dat het EndpointId moet worden opgegeven om uw aangepaste stem te gebruiken via de Speech SDK. U kunt beginnen met de snelstartgids voor tekst naar spraak en vervolgens de code bijwerken met de EndpointId en SpeechSynthesisVoiceName.

SpeechConfig speechConfig = SpeechConfig.fromSubscription(speechKey, speechRegion);
speechConfig.setSpeechSynthesisVoiceName("YourCustomVoiceName");
speechConfig.setEndpointId("YourEndpointId");

Als u een aangepaste stem wilt gebruiken via Speech Synthesis Markup Language (SSML), geeft u de modelnaam op als de spraaknaam. In dit voorbeeld wordt de YourCustomVoiceName stem gebruikt.

<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>

Een container uitvoeren en gebruiken

Spraakcontainers bieden websocket-api's voor query-eindpunten die toegankelijk zijn via de Speech SDK en Speech CLI. De Speech SDK en Speech CLI maken standaard gebruik van de openbare Speech-service. Als u de container wilt gebruiken, moet u de initialisatiemethode wijzigen. Gebruik een containerhost-URL in plaats van sleutel en regio.

Zie Speech-containers installeren en uitvoeren met Docker voor meer informatie over containers.

Referentiedocumentatiepakket (npm) | Aanvullende voorbeelden op GitHub | Library-broncode |

In deze handleiding leert u algemene ontwerppatronen voor het uitvoeren van tekst-naar-spraaksynthese.

Zie Wat is tekst naar spraak voor meer informatie over de volgende gebieden ?

  • Antwoorden krijgen als in-memory streams.
  • Voorbeeldsnelheid en bitsnelheid van uitvoer aanpassen.
  • Syntheseaanvragen verzenden met behulp van Speech Synthesis Markup Language (SSML).
  • Neurale stemmen gebruiken.
  • Abonneren op gebeurtenissen en reageren op resultaten.

Synthesetaal en spraak selecteren

De functie tekst-naar-spraak in de Speech-service ondersteunt meer dan 400 stemmen en meer dan 140 talen en varianten. U kunt de volledige lijst ophalen of ze uitproberen in de spraakgalerie.

Geef de taal of stem op van SpeechConfig uw invoertekst en gebruik de opgegeven stem:

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();

Alle neurale stemmen zijn meertalige en vloeiende taal en Engels. Als de invoertekst in het Engels bijvoorbeeld 'Ik ben enthousiast om tekst naar spraak te proberen' is en u selecteert es-ES-ElviraNeural, wordt de tekst in het Engels gesproken met een Spaans accent.

Als de stem de taal van de invoertekst niet spreekt, maakt de Speech-service geen gesynthetiseerde audio. Zie Taal- en spraakondersteuning voor de Speech-service voor een volledige lijst met ondersteunde neurale stemmen.

Notitie

De standaardstem is de eerste stem die per landinstelling wordt geretourneerd vanuit de Voice List-API.

De stem die spreekt, wordt als volgt bepaald in volgorde van prioriteit:

  • Als u dit niet instelt SpeechSynthesisVoiceName of SpeechSynthesisLanguage, wordt de standaardstem voor en-US gesproken tekst gebruikt.
  • Als u alleen instelt SpeechSynthesisLanguage, spreekt de standaardstem voor de opgegeven landinstelling.
  • Als beide SpeechSynthesisVoiceName zijn SpeechSynthesisLanguage ingesteld, wordt de SpeechSynthesisLanguage instelling genegeerd. De stem die u opgeeft met behulp van SpeechSynthesisVoiceName spreekt.
  • Als het spraakelement is ingesteld met behulp van Speech Synthesis Markup Language (SSML), worden de SpeechSynthesisVoiceName en SpeechSynthesisLanguage instellingen genegeerd.

Tekst omzetten in spraak

Als u gesynthetiseerde spraak wilt uitvoeren naar het huidige actieve uitvoerapparaat zoals een luidspreker, instantiëren AudioConfig met behulp van de fromDefaultSpeakerOutput() statische functie. Hier volgt een voorbeeld:

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();
        });
}

Wanneer u het programma uitvoert, wordt gesynthetiseerde audio afgespeeld vanuit de luidspreker. Dit resultaat is een goed voorbeeld van het meest eenvoudige gebruik. Vervolgens kunt u de uitvoer aanpassen en het uitvoerantwoord verwerken als een in-memory stream voor het werken met aangepaste scenario's.

Een resultaat ophalen als een stroom in het geheugen

U kunt de resulterende audiogegevens gebruiken als een in-memory stream in plaats van rechtstreeks naar een bestand te schrijven. Met een in-memory stream kunt u aangepast gedrag bouwen:

  • Abstract de resulterende bytematrix als een zoekbare stroom voor aangepaste downstreamservices.
  • Integreer het resultaat met andere API's of services.
  • Wijzig de audiogegevens, schrijf aangepaste headers en voer gerelateerde .wav taken uit.

U kunt deze wijziging aanbrengen in het vorige voorbeeld. Verwijder het AudioConfig blok, omdat u het uitvoergedrag vanaf dit punt handmatig beheert voor een betere controle. Geef null vervolgens de AudioConfigSpeechSynthesizer constructor door.

Notitie

Het doorgeven null van AudioConfig, in plaats van het weglaten zoals u in het vorige voorbeeld van de luidsprekeruitvoer hebt gedaan, speelt de audio niet standaard af op het huidige actieve uitvoerapparaat.

Sla het resultaat op in een SpeechSynthesisResult-variabele . De SpeechSynthesisResult.audioData eigenschap retourneert een ArrayBuffer waarde van de uitvoergegevens, het standaardtype browserstream. Voor code aan de serverzijde converteert u ArrayBuffer naar een bufferstroom.

De volgende code werkt voor de clientzijde:

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();
        });
}

U kunt elk aangepast gedrag implementeren met behulp van het resulterende ArrayBuffer object. ArrayBuffer is een veelvoorkomend type dat u in een browser kunt ontvangen en kunt afspelen vanuit deze indeling.

Als u met de gegevens als een stroom wilt werken, moet u het ArrayBuffer object converteren naar een stream als u op een server gebaseerde code wilt gebruiken:

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();
        });
}

Audio-indeling aanpassen

U kunt kenmerken voor audio-uitvoer aanpassen, waaronder:

  • Audiobestandstype
  • Samplefrequentie
  • Bitdiepte

Als u de audio-indeling wilt wijzigen, gebruikt u de speechSynthesisOutputFormat eigenschap van het SpeechConfig object. Deze eigenschap verwacht een enum exemplaar van het type SpeechSynthesisOutputFormat. Gebruik de enum optie om de uitvoerindeling te selecteren. Zie de lijst met audio-indelingen voor beschikbare indelingen.

Er zijn verschillende opties voor verschillende bestandstypen, afhankelijk van uw vereisten. Onbewerkte indelingen Raw24Khz16BitMonoPcm bevatten standaard geen audioheaders. Gebruik onbewerkte indelingen alleen in een van deze situaties:

  • U weet dat uw downstream-implementatie een onbewerkte bitstream kan decoderen.
  • U bent van plan om handmatig headers te bouwen op basis van factoren zoals bitdiepte, samplefrequentie en aantal kanalen.

In dit voorbeeld wordt de RIFF-indeling Riff24Khz16BitMonoPcm met hoge kwaliteit opgegeven door het object in te SpeechConfig stellenspeechSynthesisOutputFormat. Net als in het voorbeeld in de vorige sectie, kunt u de ArrayBuffer-audiogegevens ophalen en ermee werken.

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();
        });
}

SSML gebruiken om spraakkenmerken aan te passen

U kunt SSML gebruiken om de toonhoogte, uitspraak, spreeksnelheid, volume en andere aspecten in de tekst naar spraakuitvoer af te stemmen door uw aanvragen vanuit een XML-schema in te dienen. In deze sectie ziet u een voorbeeld van het wijzigen van de stem. Zie het overzicht van Speech Synthesis Markup Language voor meer informatie.

Als u SSML wilt gaan gebruiken voor aanpassing, moet u een kleine wijziging aanbrengen waarmee de stem wordt gewijzigd.

  1. Maak een nieuw XML-bestand voor de SSML-configuratie in de hoofdprojectmap.

    <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 dit voorbeeld is het ssml.xml. Het hoofdelement is altijd <speak>. Als u de tekst in een <voice> element terugloopt, kunt u de stem wijzigen met behulp van de name parameter. Zie Ondersteunde talen voor de volledige lijst met ondersteunde neurale stemmen.

  2. Wijzig de aanvraag voor spraaksynthese om te verwijzen naar uw XML-bestand. De aanvraag is doorgaans hetzelfde, maar in plaats van de functie speakTextAsync() gebruikt u speakSsmlAsync(). Deze functie verwacht een XML-tekenreeks. Maak een functie om een XML-bestand te laden en als een tekenreeks te retourneren:

    function xmlToString(filePath) {
        const xml = readFileSync(filePath, "utf8");
        return xml;
    }
    

    Zie Node.js-bestandssysteem voor meer informatie over readFileSync.

    Het resultaatobject is precies hetzelfde als de vorige voorbeelden:

    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();
            });
    }
    

Notitie

Als u de stem wilt wijzigen zonder SSML te gebruiken, kunt u de eigenschap SpeechConfig instellen met behulp van SpeechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";.

Abonneren op synthesizer-evenementen

Mogelijk wilt u meer inzichten over de tekst naar spraakverwerking en resultaten. U wilt bijvoorbeeld weten wanneer de synthesizer start en stopt, of misschien wilt u weten over andere gebeurtenissen die tijdens de synthese zijn aangetroffen.

Tijdens het gebruik van speechSynthesizer voor tekst-naar-spraak kunt u zich abonneren op de gebeurtenissen in deze tabel:

Gebeurtenis Beschrijving Gebruiksscenario
BookmarkReached Signalen dat een bladwijzer is bereikt. Voor het activeren van een gebeurtenis die een bladwijzer heeft bereikt, is een bookmark element vereist in de SSML. Deze gebeurtenis rapporteert de verstreken tijd van de uitvoeraudio tussen het begin van de synthese en het bookmark element. De eigenschap van Text de gebeurtenis is de tekenreekswaarde die u hebt ingesteld in het kenmerk van mark de bladwijzer. De bookmark elementen worden niet gesproken. U kunt het bookmark element gebruiken om aangepaste markeringen in SSML in te voegen om de verschuiving van elke markering in de audiostream op te halen. Het bookmark element kan worden gebruikt om te verwijzen naar een specifieke locatie in de tekst- of tagvolgorde.
SynthesisCanceled Signalen dat de spraaksynthese is geannuleerd. U kunt bevestigen wanneer synthese wordt geannuleerd.
SynthesisCompleted Signalen dat spraaksynthese is voltooid. U kunt bevestigen wanneer de synthese is voltooid.
SynthesisStarted Signalen dat spraaksynthese is gestart. U kunt bevestigen wanneer de synthese is gestart.
Synthesizing Signalen dat spraaksynthese gaande is. Deze gebeurtenis wordt geactiveerd telkens wanneer de SDK een audiosegment van de Speech-service ontvangt. U kunt controleren wanneer de synthese wordt uitgevoerd.
VisemeReceived Signalen dat er een visemegebeurtenis is ontvangen. Visemes worden vaak gebruikt om de belangrijkste poses in geobserveerde spraak te vertegenwoordigen. Belangrijke poses zijn onder andere de positie van de lippen, de kaak en de tong bij het produceren van een bepaald telefoonme. U kunt visemes gebruiken om het gezicht van een teken te animeren terwijl spraakaudio wordt afgespeeld.
WordBoundary Signalen dat een woordgrens is ontvangen. Deze gebeurtenis wordt aan het begin van elk nieuw gesproken woord, leesteken en zin gegenereerd. De gebeurtenis rapporteert de tijdsverschil van het huidige woord, in tikken, vanaf het begin van de uitvoeraudio. Deze gebeurtenis rapporteert ook de tekenpositie in de invoertekst of SSML direct voordat het woord wordt gesproken. Deze gebeurtenis wordt vaak gebruikt om relatieve posities van de tekst en bijbehorende audio te verkrijgen. Misschien wilt u meer weten over een nieuw woord en vervolgens actie ondernemen op basis van de timing. U kunt bijvoorbeeld informatie krijgen waarmee u kunt bepalen wanneer en hoe lang woorden moeten worden gemarkeerd terwijl ze worden gesproken.

Notitie

Gebeurtenissen worden gegenereerd wanneer de uitvoeraudiogegevens beschikbaar komen, wat sneller is dan afspelen op een uitvoerapparaat. De beller moet streaming en realtime synchroniseren.

Hier volgt een voorbeeld waarin wordt getoond hoe u zich kunt abonneren op gebeurtenissen voor spraaksynthese. U kunt de instructies in de quickstart volgen, maar de inhoud van dat SpeechSynthesis.js bestand vervangen door de volgende JavaScript-code.

(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;
    });
}());

U vindt meer tekst naar spraakvoorbeelden op GitHub.

Een container uitvoeren en gebruiken

Spraakcontainers bieden websocket-api's voor query-eindpunten die toegankelijk zijn via de Speech SDK en Speech CLI. De Speech SDK en Speech CLI maken standaard gebruik van de openbare Speech-service. Als u de container wilt gebruiken, moet u de initialisatiemethode wijzigen. Gebruik een containerhost-URL in plaats van sleutel en regio.

Zie Speech-containers installeren en uitvoeren met Docker voor meer informatie over containers.

Referentiedocumentatiepakket (downloaden) | Aanvullende voorbeelden op GitHub |

In deze handleiding leert u algemene ontwerppatronen voor het uitvoeren van tekst-naar-spraaksynthese.

Zie Wat is tekst naar spraak voor meer informatie over de volgende gebieden ?

  • Antwoorden krijgen als in-memory streams.
  • Voorbeeldsnelheid en bitsnelheid van uitvoer aanpassen.
  • Syntheseaanvragen verzenden met behulp van Speech Synthesis Markup Language (SSML).
  • Neurale stemmen gebruiken.
  • Abonneren op gebeurtenissen en reageren op resultaten.

Vereisten

De Speech SDK en voorbeelden installeren

De opslagplaats Azure-Samples/cognitive-services-speech-sdk bevat voorbeelden die zijn geschreven in Objective-C voor iOS en Mac. Selecteer een koppeling om de installatie-instructies voor elk voorbeeld te bekijken:

Een aangepast eindpunt gebruiken

Het aangepaste eindpunt is functioneel identiek aan het standaardeindpunt dat wordt gebruikt voor tekst-naar-spraakaanvragen.

Een verschil is dat het EndpointId moet worden opgegeven om uw aangepaste stem te gebruiken via de Speech SDK. U kunt beginnen met de snelstartgids voor tekst naar spraak en vervolgens de code bijwerken met de EndpointId en SpeechSynthesisVoiceName.

SPXSpeechConfiguration *speechConfig = [[SPXSpeechConfiguration alloc] initWithSubscription:speechKey region:speechRegion];
speechConfig.speechSynthesisVoiceName = @"YourCustomVoiceName";
speechConfig.EndpointId = @"YourEndpointId";

Als u een aangepaste stem wilt gebruiken via Speech Synthesis Markup Language (SSML), geeft u de modelnaam op als de spraaknaam. In dit voorbeeld wordt de YourCustomVoiceName stem gebruikt.

<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>

Een container uitvoeren en gebruiken

Spraakcontainers bieden websocket-api's voor query-eindpunten die toegankelijk zijn via de Speech SDK en Speech CLI. De Speech SDK en Speech CLI maken standaard gebruik van de openbare Speech-service. Als u de container wilt gebruiken, moet u de initialisatiemethode wijzigen. Gebruik een containerhost-URL in plaats van sleutel en regio.

Zie Speech-containers installeren en uitvoeren met Docker voor meer informatie over containers.

Referentiedocumentatiepakket (downloaden) | Aanvullende voorbeelden op GitHub |

In deze handleiding leert u algemene ontwerppatronen voor het uitvoeren van tekst-naar-spraaksynthese.

Zie Wat is tekst naar spraak voor meer informatie over de volgende gebieden ?

  • Antwoorden krijgen als in-memory streams.
  • Voorbeeldsnelheid en bitsnelheid van uitvoer aanpassen.
  • Syntheseaanvragen verzenden met behulp van Speech Synthesis Markup Language (SSML).
  • Neurale stemmen gebruiken.
  • Abonneren op gebeurtenissen en reageren op resultaten.

Vereisten

De Speech SDK en voorbeelden installeren

De opslagplaats Azure-Samples/cognitive-services-speech-sdk bevat voorbeelden die zijn geschreven in Swift voor iOS en Mac. Selecteer een koppeling om de installatie-instructies voor elk voorbeeld te bekijken:

Een container uitvoeren en gebruiken

Spraakcontainers bieden websocket-api's voor query-eindpunten die toegankelijk zijn via de Speech SDK en Speech CLI. De Speech SDK en Speech CLI maken standaard gebruik van de openbare Speech-service. Als u de container wilt gebruiken, moet u de initialisatiemethode wijzigen. Gebruik een containerhost-URL in plaats van sleutel en regio.

Zie Speech-containers installeren en uitvoeren met Docker voor meer informatie over containers.

Referentiedocumentatiepakket (PyPi) | Aanvullende voorbeelden op GitHub |

In deze handleiding leert u algemene ontwerppatronen voor het uitvoeren van tekst-naar-spraaksynthese.

Zie Wat is tekst naar spraak voor meer informatie over de volgende gebieden ?

  • Antwoorden krijgen als in-memory streams.
  • Voorbeeldsnelheid en bitsnelheid van uitvoer aanpassen.
  • Syntheseaanvragen verzenden met behulp van Speech Synthesis Markup Language (SSML).
  • Neurale stemmen gebruiken.
  • Abonneren op gebeurtenissen en reageren op resultaten.

Synthesetaal en spraak selecteren

De functie tekst-naar-spraak in de Speech-service ondersteunt meer dan 400 stemmen en meer dan 140 talen en varianten. U kunt de volledige lijst ophalen of ze uitproberen in de spraakgalerie.

Geef de taal of stem op van SpeechConfig uw invoertekst en gebruik de opgegeven stem:

# Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
speech_config.speech_synthesis_language = "en-US" 
speech_config.speech_synthesis_voice_name ="en-US-AvaMultilingualNeural"

Alle neurale stemmen zijn meertalige en vloeiende taal en Engels. Als de invoertekst in het Engels bijvoorbeeld 'Ik ben enthousiast om tekst naar spraak te proberen' is en u selecteert es-ES-ElviraNeural, wordt de tekst in het Engels gesproken met een Spaans accent.

Als de stem de taal van de invoertekst niet spreekt, maakt de Speech-service geen gesynthetiseerde audio. Zie Taal- en spraakondersteuning voor de Speech-service voor een volledige lijst met ondersteunde neurale stemmen.

Notitie

De standaardstem is de eerste stem die per landinstelling wordt geretourneerd vanuit de Voice List-API.

De stem die spreekt, wordt als volgt bepaald in volgorde van prioriteit:

  • Als u dit niet instelt SpeechSynthesisVoiceName of SpeechSynthesisLanguage, wordt de standaardstem voor en-US gesproken tekst gebruikt.
  • Als u alleen instelt SpeechSynthesisLanguage, spreekt de standaardstem voor de opgegeven landinstelling.
  • Als beide SpeechSynthesisVoiceName zijn SpeechSynthesisLanguage ingesteld, wordt de SpeechSynthesisLanguage instelling genegeerd. De stem die u opgeeft met behulp van SpeechSynthesisVoiceName spreekt.
  • Als het spraakelement is ingesteld met behulp van Speech Synthesis Markup Language (SSML), worden de SpeechSynthesisVoiceName en SpeechSynthesisLanguage instellingen genegeerd.

Spraak synthetiseren naar een bestand

Maak een SpeechSynthesizer-object . Met dit object wordt tekst uitgevoerd naar spraakconversies en uitvoer naar luidsprekers, bestanden of andere uitvoerstromen. SpeechSynthesizer accepteert als parameters:

  • Het SpeechConfig object dat u in de vorige stap hebt gemaakt.
  • Een AudioOutputConfig object dat aangeeft hoe uitvoerresultaten moeten worden verwerkt.
  1. Maak een AudioOutputConfig exemplaar om de uitvoer automatisch naar een .wav-bestand te schrijven met behulp van de filename constructorparameter:

    audio_config = speechsdk.audio.AudioOutputConfig(filename="path/to/write/file.wav")
    
  2. Instantieer SpeechSynthesizer door uw speech_config object en het audio_config object als parameters door te geven. Als u spraak wilt omzetten en naar een bestand wilt schrijven, voert u deze uit speak_text_async() met een tekenreeks tekst.

    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")
    

Wanneer u het programma uitvoert, wordt er een gesynthetiseerd .wav-bestand gemaakt, dat wordt geschreven naar de locatie die u opgeeft. Dit resultaat is een goed voorbeeld van het meest eenvoudige gebruik. Vervolgens kunt u de uitvoer aanpassen en het uitvoerantwoord verwerken als een stroom in het geheugen voor het werken met aangepaste scenario's.

Synthetiseren naar de uitvoer van de luidspreker

Als u gesynthetiseerde spraak wilt uitvoeren naar het huidige actieve uitvoerapparaat zoals een luidspreker, stelt u de use_default_speaker parameter in wanneer u het AudioOutputConfig exemplaar maakt. Hier volgt een voorbeeld:

audio_config = speechsdk.audio.AudioOutputConfig(use_default_speaker=True)

Een resultaat ophalen als een stroom in het geheugen

U kunt de resulterende audiogegevens gebruiken als een in-memory stream in plaats van rechtstreeks naar een bestand te schrijven. Met een in-memory stream kunt u aangepast gedrag bouwen:

  • Abstract de resulterende bytematrix als een zoekbare stroom voor aangepaste downstreamservices.
  • Integreer het resultaat met andere API's of services.
  • Wijzig de audiogegevens, schrijf aangepaste .wav headers en voer gerelateerde taken uit.

U kunt deze wijziging aanbrengen in het vorige voorbeeld. Verwijder AudioConfigeerst, omdat u vanaf dit moment het uitvoergedrag handmatig beheert voor meer controle. Geef None deze door AudioConfig in de SpeechSynthesizer constructor.

Notitie

Het doorgeven None van AudioConfig, in plaats van het weglaten zoals u in het vorige voorbeeld van de luidsprekeruitvoer hebt gedaan, speelt de audio niet standaard af op het huidige actieve uitvoerapparaat.

Sla het resultaat op in een SpeechSynthesisResult variabele. De eigenschap audio_data bevat een bytes-object van de uitvoergegevens. U kunt handmatig met dit object werken, of u kunt de AudioDataStream-klasse gebruiken om de stroom in het geheugen te beheren.

In dit voorbeeld gebruikt u de AudioDataStream constructor om een stroom op te halen uit het resultaat:

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)

Op dit moment kunt u elk aangepast gedrag implementeren met behulp van het resulterende stream object.

Audio-indeling aanpassen

U kunt kenmerken voor audio-uitvoer aanpassen, waaronder:

  • Audiobestandstype
  • Samplefrequentie
  • Bitdiepte

Als u de audio-indeling wilt wijzigen, gebruikt u de set_speech_synthesis_output_format() functie voor het SpeechConfig object. Deze functie verwacht een exemplaar van het enum type SpeechSynthesisOutputFormat. Gebruik de enum optie om de uitvoerindeling te selecteren. Zie de lijst met audio-indelingen voor beschikbare indelingen.

Er zijn verschillende opties voor verschillende bestandstypen, afhankelijk van uw vereisten. Onbewerkte indelingen Raw24Khz16BitMonoPcm bevatten standaard geen audioheaders. Gebruik onbewerkte indelingen alleen in een van deze situaties:

  • U weet dat uw downstream-implementatie een onbewerkte bitstream kan decoderen.
  • U bent van plan om handmatig headers te bouwen op basis van factoren zoals bitdiepte, samplefrequentie en aantal kanalen.

In dit voorbeeld wordt de RIFF-indeling Riff24Khz16BitMonoPcm met hoge kwaliteit opgegeven door het object in te SpeechConfig stellenSpeechSynthesisOutputFormat. Net als in het voorbeeld in de vorige sectie, gebruikt u AudioDataStream om een stroom in het geheugen van het resultaat te verkrijgen en vervolgens naar een bestand te schrijven.

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")

Wanneer u het programma uitvoert, wordt er een .wav-bestand naar het opgegeven pad geschreven.

SSML gebruiken om spraakkenmerken aan te passen

U kunt SSML gebruiken om de toonhoogte, uitspraak, spreeksnelheid, volume en andere aspecten in de tekst naar spraakuitvoer af te stemmen door uw aanvragen vanuit een XML-schema in te dienen. In deze sectie ziet u een voorbeeld van het wijzigen van de stem. Zie het overzicht van Speech Synthesis Markup Language voor meer informatie.

Als u SSML wilt gaan gebruiken voor aanpassing, moet u een kleine wijziging aanbrengen waarmee de stem wordt gewijzigd.

  1. Maak een nieuw XML-bestand voor de SSML-configuratie in de hoofdprojectmap.

    <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 dit voorbeeld wordt het bestand ssml.xml. Het hoofdelement is altijd <speak>. Als u de tekst in een <voice> element terugloopt, kunt u de stem wijzigen met behulp van de name parameter. Zie Ondersteunde talen voor de volledige lijst met ondersteunde neurale stemmen.

  2. Wijzig de aanvraag voor spraaksynthese om te verwijzen naar uw XML-bestand. De aanvraag is meestal hetzelfde. Gebruik in plaats van de speak_text_async() functie speak_ssml_async(). Deze functie verwacht een XML-tekenreeks. Lees eerst uw SSML-configuratie als een tekenreeks. Vanaf dit punt is het resultaatobject precies hetzelfde als eerdere voorbeelden.

    Notitie

    Als uw ssml_string aan het begin van de tekenreeks  bevat, moet u de BOM-indeling verwijderen, anders wordt er een foutbericht weergegeven. U doet dit door de parameter encoding als volgt in te stellen: 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")
    

Notitie

Als u de stem wilt wijzigen zonder SSML te gebruiken, kunt u de eigenschap SpeechConfig instellen met behulp van speech_config.speech_synthesis_voice_name = "en-US-AvaMultilingualNeural".

Abonneren op synthesizer-evenementen

Mogelijk wilt u meer inzichten over de tekst naar spraakverwerking en resultaten. U wilt bijvoorbeeld weten wanneer de synthesizer start en stopt, of misschien wilt u weten over andere gebeurtenissen die tijdens de synthese zijn aangetroffen.

Tijdens het gebruik van speechSynthesizer voor tekst-naar-spraak kunt u zich abonneren op de gebeurtenissen in deze tabel:

Gebeurtenis Beschrijving Gebruiksscenario
BookmarkReached Signalen dat een bladwijzer is bereikt. Voor het activeren van een gebeurtenis die een bladwijzer heeft bereikt, is een bookmark element vereist in de SSML. Deze gebeurtenis rapporteert de verstreken tijd van de uitvoeraudio tussen het begin van de synthese en het bookmark element. De eigenschap van Text de gebeurtenis is de tekenreekswaarde die u hebt ingesteld in het kenmerk van mark de bladwijzer. De bookmark elementen worden niet gesproken. U kunt het bookmark element gebruiken om aangepaste markeringen in SSML in te voegen om de verschuiving van elke markering in de audiostream op te halen. Het bookmark element kan worden gebruikt om te verwijzen naar een specifieke locatie in de tekst- of tagvolgorde.
SynthesisCanceled Signalen dat de spraaksynthese is geannuleerd. U kunt bevestigen wanneer synthese wordt geannuleerd.
SynthesisCompleted Signalen dat spraaksynthese is voltooid. U kunt bevestigen wanneer de synthese is voltooid.
SynthesisStarted Signalen dat spraaksynthese is gestart. U kunt bevestigen wanneer de synthese is gestart.
Synthesizing Signalen dat spraaksynthese gaande is. Deze gebeurtenis wordt geactiveerd telkens wanneer de SDK een audiosegment van de Speech-service ontvangt. U kunt controleren wanneer de synthese wordt uitgevoerd.
VisemeReceived Signalen dat er een visemegebeurtenis is ontvangen. Visemes worden vaak gebruikt om de belangrijkste poses in geobserveerde spraak te vertegenwoordigen. Belangrijke poses zijn onder andere de positie van de lippen, de kaak en de tong bij het produceren van een bepaald telefoonme. U kunt visemes gebruiken om het gezicht van een teken te animeren terwijl spraakaudio wordt afgespeeld.
WordBoundary Signalen dat een woordgrens is ontvangen. Deze gebeurtenis wordt aan het begin van elk nieuw gesproken woord, leesteken en zin gegenereerd. De gebeurtenis rapporteert de tijdsverschil van het huidige woord, in tikken, vanaf het begin van de uitvoeraudio. Deze gebeurtenis rapporteert ook de tekenpositie in de invoertekst of SSML direct voordat het woord wordt gesproken. Deze gebeurtenis wordt vaak gebruikt om relatieve posities van de tekst en bijbehorende audio te verkrijgen. Misschien wilt u meer weten over een nieuw woord en vervolgens actie ondernemen op basis van de timing. U kunt bijvoorbeeld informatie krijgen waarmee u kunt bepalen wanneer en hoe lang woorden moeten worden gemarkeerd terwijl ze worden gesproken.

Notitie

Gebeurtenissen worden gegenereerd wanneer de uitvoeraudiogegevens beschikbaar komen, wat sneller is dan afspelen op een uitvoerapparaat. De beller moet streaming en realtime synchroniseren.

Hier volgt een voorbeeld waarin wordt getoond hoe u zich kunt abonneren op gebeurtenissen voor spraaksynthese. U kunt de instructies in de quickstart volgen, maar de inhoud van dat speech-synthesis.py bestand vervangen door de volgende Python-code:

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?")

U vindt meer tekst naar spraakvoorbeelden op GitHub.

Een aangepast eindpunt gebruiken

Het aangepaste eindpunt is functioneel identiek aan het standaardeindpunt dat wordt gebruikt voor tekst-naar-spraakaanvragen.

Een verschil is dat het endpoint_id moet worden opgegeven om uw aangepaste stem te gebruiken via de Speech SDK. U kunt beginnen met de snelstartgids voor tekst naar spraak en vervolgens de code bijwerken met de endpoint_id en 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"

Als u een aangepaste stem wilt gebruiken via Speech Synthesis Markup Language (SSML), geeft u de modelnaam op als de spraaknaam. In dit voorbeeld wordt de YourCustomVoiceName stem gebruikt.

<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>

Een container uitvoeren en gebruiken

Spraakcontainers bieden websocket-api's voor query-eindpunten die toegankelijk zijn via de Speech SDK en Speech CLI. De Speech SDK en Speech CLI maken standaard gebruik van de openbare Speech-service. Als u de container wilt gebruiken, moet u de initialisatiemethode wijzigen. Gebruik een containerhost-URL in plaats van sleutel en regio.

Zie Speech-containers installeren en uitvoeren met Docker voor meer informatie over containers.

Spraak-naar-tekst-REST API-verwijzing Speech naar text REST API voor korte audioverwijzing | Aanvullende voorbeelden op GitHub |

In deze handleiding leert u algemene ontwerppatronen voor het uitvoeren van tekst-naar-spraaksynthese.

Zie Wat is tekst naar spraak voor meer informatie over de volgende gebieden ?

  • Antwoorden krijgen als in-memory streams.
  • Voorbeeldsnelheid en bitsnelheid van uitvoer aanpassen.
  • Syntheseaanvragen verzenden met behulp van Speech Synthesis Markup Language (SSML).
  • Neurale stemmen gebruiken.
  • Abonneren op gebeurtenissen en reageren op resultaten.

Vereisten

Tekst naar spraak converteren

Voer de volgende opdracht uit bij een opdrachtprompt: Voeg deze waarden in de opdracht in:

  • Uw spraakresourcesleutel
  • Uw spraakresourceregio

U kunt ook de volgende waarden wijzigen:

  • De waarde van de X-Microsoft-OutputFormat-header, waarmee de indeling van de audio-uitvoer wordt bepaald. U vindt een lijst met ondersteunde audio-uitvoerindelingen in de tekst-naar-spraak-REST API-verwijzing.
  • De stem voor de uitvoer. Zie de Spraaklijst-API voor een lijst met stemmen die beschikbaar zijn voor uw Speech-service-eindpunt.
  • Het uitvoerbestand. In dit voorbeeld wordt het antwoord van de server naar het bestand output.mp3 gestuurd.
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 deze handleiding leert u algemene ontwerppatronen voor het uitvoeren van tekst-naar-spraaksynthese.

Zie Wat is tekst naar spraak voor meer informatie over de volgende gebieden ?

  • Antwoorden krijgen als in-memory streams.
  • Voorbeeldsnelheid en bitsnelheid van uitvoer aanpassen.
  • Syntheseaanvragen verzenden met behulp van Speech Synthesis Markup Language (SSML).
  • Neurale stemmen gebruiken.
  • Abonneren op gebeurtenissen en reageren op resultaten.

Vereisten

Downloaden en installeren van

Volg deze stappen en bekijk de quickstart voor Speech CLI voor andere vereisten voor uw platform.

  1. Voer de volgende .NET CLI-opdracht uit om de Speech CLI te installeren:

    dotnet tool install --global Microsoft.CognitiveServices.Speech.CLI
    
  2. Voer de volgende opdrachten uit om uw Spraak-resourcesleutel en -regio te configureren. Vervang door SUBSCRIPTION-KEY uw Spraak-resourcesleutel en vervang deze door REGION de spraakresourceregio.

    spx config @key --set SUBSCRIPTION-KEY
    spx config @region --set REGION
    

Spraaksynthese naar een luidspreker

Nu bent u klaar om de Speech CLI uit te voeren om tekst om te zetten in spraak.

  • Ga in een consolevenster naar de map met het binaire Speech CLI-bestand. Voer vervolgens de volgende opdracht uit:

    spx synthesize --text "I'm excited to try text to speech"
    

De Speech CLI produceert natuurlijke taal in het Engels via de computer spreker.

Spraak synthetiseren naar een bestand

  • Voer de volgende opdracht uit om de uitvoer van uw luidspreker te wijzigen in een .wav-bestand :

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

De Speech CLI produceert natuurlijke taal in het Engels naar het greetings.wav audiobestand.

Een container uitvoeren en gebruiken

Spraakcontainers bieden websocket-api's voor query-eindpunten die toegankelijk zijn via de Speech SDK en Speech CLI. De Speech SDK en Speech CLI maken standaard gebruik van de openbare Speech-service. Als u de container wilt gebruiken, moet u de initialisatiemethode wijzigen. Gebruik een containerhost-URL in plaats van sleutel en regio.

Zie Speech-containers installeren en uitvoeren met Docker voor meer informatie over containers.

Volgende stappen