Teilen über


Synthetisieren von Sprache aus Text

Referenzdokumentation | Paket (NuGet) | Zusätzliche Beispiele auf GitHub

In dieser Schrittanleitung werden gängige Entwurfsmuster für die Sprachsynthese vorgestellt.

Weitere Informationen zu den folgenden Bereichen finden Sie unter Was ist Sprachsynthese?.

  • Abrufen von Antworten als In-Memory-Datenströme
  • Anpassen der Abtast- und Bitrate der Ausgabe
  • Übermitteln von Syntheseanforderungen mithilfe der Markupsprache für Sprachsynthese (Speech Synthesis Markup Language, SSML)
  • Verwenden neuronaler Stimmen
  • Abonnieren von Ereignissen und ergebnisbezogenes Handeln

Auswählen von Synthesesprache und Stimme

Das Feature für die Sprachsynthese im Speech-Dienst unterstützt mehr als 400 Stimmen und über 140 Sprachen und Varianten. Sie können die vollständige Liste abrufen oder sie im Stimmkatalog ausprobieren.

Geben Sie die Sprache oder Stimme von SpeechConfig entsprechend Ihres Eingabetexts an, und verwenden Sie die festgelegte Stimme. Der folgende Codeschnipsel zeigt, wie dieses Verfahren funktioniert:

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 neuronalen Stimmen sind mehrsprachig und können in ihrer eigenen Sprache und in englischer Sprache sprechen. Wenn der Eingabetext auf Englisch beispielsweise „I'm excited to try text to speech“ lautet und Sie es-ES-ElviraNeural auswählen, wird der Text in englischer Sprache mit einem spanischen Akzent gesprochen.

Wenn die Stimme nicht die Sprache des Eingabetexts spricht, wird keine synthetisierte Audioausgabe vom Speech-Dienst erstellt. Eine vollständige Liste der unterstützten neuronalen Stimmen finden Sie unter Sprach- und Stimmunterstützung für den Speech-Dienst.

Hinweis

Die Standardstimme ist die erste Stimme, die pro Gebietsschema von der Stimmlisten-API zurückgegeben wird.

Die Stimme, die spricht, wird wie folgt nach ihrer Priorität bestimmt:

  • Wenn Sie weder SpeechSynthesisVoiceName noch SpeechSynthesisLanguage festlegen, spricht die Standardstimme für en-US.
  • Wenn Sie nur SpeechSynthesisLanguage festlegen, spricht die Standardstimme für das angegebene Gebietsschema.
  • Wenn sowohl SpeechSynthesisVoiceName als auch SpeechSynthesisLanguage festgelegt sind, wird die Einstellung SpeechSynthesisLanguage ignoriert. Die Stimme, die Sie mithilfe von SpeechSynthesisVoiceName angeben, spricht.
  • Wenn das Stimmelement über Speech Synthesis Markup Language (SSML) festgelegt wird, werden die Einstellungen SpeechSynthesisVoiceName und SpeechSynthesisLanguage ignoriert.

Zusammenfassend kann die Reihenfolge der Priorität wie folgt beschrieben werden:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Ergebnis
Die Standardstimme für en-US spricht.
Die Standardstimme für das angegebene Gebietsschema spricht.
Die Stimme, die Sie mithilfe von SpeechSynthesisVoiceName angeben, spricht.
Die Stimme, die Sie mithilfe von SSML angeben, spricht.

Synthetisieren von Sprache in eine Datei

Erstellen Sie ein SpeechSynthesizer-Objekt. Das in den folgenden Codeschnipseln gezeigte Objekt führt die Konvertierungen von Text in Sprache und Ausgaben an Lautsprecher, in Dateien oder andere Ausgabestreams aus. SpeechSynthesizer akzeptiert folgende Parameter:

  • Das SpeechConfig-Objekt, das Sie im vorherigen Schritt erstellt haben
  • Ein AudioConfig-Objekt, das angibt, wie Ausgabeergebnisse verarbeitet werden sollen
  1. Erstellen Sie eine AudioConfig-Instanz, um die Ausgabe mithilfe der Funktion FromWavFileOutput() automatisch in eine WAV-Datei zu schreiben. Instanziieren Sie sie mit einer using-Anweisung.

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

    Eine using-Anweisung in diesem Kontext gibt automatisch nicht verwaltete Ressourcen frei und führt dazu, dass das Objekt nach der Freigabe nicht mehr zum Geltungsbereich gehört.

  2. Instanziieren Sie mit einer weiteren using-Anweisung eine SpeechSynthesizer-Instanz. Übergeben Sie die speechConfig- und audioConfig-Objekte als Parameter. Um Sprache zu synthetisieren und in eine Datei zu schreiben, führen Sie SpeakTextAsync() mit einer Textzeichenfolge aus.

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

Wenn Sie das Programm ausführen, wird eine synthetisierte WAV-Datei erstellt, die an den von Ihnen angegebenen Speicherort geschrieben wird. Dieses Ergebnis ist ein gutes Beispiel für die einfachste Verwendungsmöglichkeit. Als Nächstes können Sie die Ausgabe anpassen und die Ausgabeantwort als In-Memory-Datenstrom für benutzerdefinierte Szenarios verarbeiten.

Synthetisieren der Lautsprecherausgabe

Zum Ausgeben von synthetisierter Sprache auf dem aktuell aktiven Ausgabegerät wie einem Lautsprecher lassen Sie den Parameter AudioConfig weg, wenn Sie die SpeechSynthesizer-Instanz erstellen. Hier sehen Sie ein Beispiel:

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

Abrufen eines Ergebnisses als In-Memory-Datenstrom

Sie können die resultierenden Audiodaten als einen In-Memory-Datenstrom verwenden, statt sie direkt in eine Datei zu schreiben. Mit einem In-Memory-Datenstrom können Sie benutzerdefiniertes Verhalten erstellen:

  • Abstrahieren des resultierenden Bytearrays als durchsuchbaren Datenstrom für benutzerdefinierte Downstreamdienste
  • Integrieren des Ergebnisses in andere APIs oder Dienste
  • Ändern Sie die Audiodaten, schreiben Sie benutzerdefinierte WAV-Header, und erledigen Sie zugehörige Aufgaben.

Sie können diese Änderung am vorherigen Beispiel vornehmen. Entfernen Sie zunächst den AudioConfig-Block, da Sie das Ausgabeverhalten ab jetzt manuell verwalten, um eine bessere Kontrolle zu erzielen. Übergeben Sie im SpeechSynthesizer-Konstruktor null für AudioConfig.

Hinweis

Wenn Sie null für AudioConfig übergeben, anstatt den Parameter wie im obigen Beispiel für die Lautsprecherausgabe wegzulassen, werden die Audiodaten nicht standardmäßig auf dem derzeit aktiven Ausgabegerät wiedergegeben.

Speichern Sie das Ergebnis in einer SpeechSynthesisResult-Variablen. Die AudioData-Eigenschaft enthält eine byte []-Instanz für die Ausgabedaten. Sie können diese byte []-Instanz manuell nutzen oder die AudioDataStream-Klasse verwenden, um den In-Memory-Datenstrom zu verwalten.

In diesem Beispiel verwenden Sie die statische Funktion AudioDataStream.FromResult(), um einen Datenstrom aus dem Ergebnis abzurufen:

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

Nun können Sie mit dem resultierenden stream-Objekt ein beliebiges benutzerdefiniertes Verhalten implementieren.

Anpassen des Audioformats

Sie können die Attribute der Audioausgabe anpassen, z. B.:

  • Audiodateityp
  • Samplingrate
  • Bittiefe

Zum Ändern des Audioformats wenden Sie die Funktion SetSpeechSynthesisOutputFormat() auf das Objekt SpeechConfig an. Diese Funktion erwartet eine enum-Instanz vom Typ SpeechSynthesisOutputFormat. Verwenden Sie enum, um das Ausgabeformat auszuwählen. Informationen zu den verfügbaren Formaten finden Sie in der Liste der Audioformate.

Abhängig von Ihren Anforderungen stehen Ihnen verschiedene Optionen für unterschiedliche Dateitypen zur Verfügung. Rohformate wie Raw24Khz16BitMonoPcm enthalten gemäß Definition keine Audioheader. Verwenden Sie Rohformate nur in den folgenden Situationen:

  • Sie wissen, dass Ihre Downstreamimplementierung einen unformatierten Bitstream decodieren kann.
  • Sie planen, Header basierend auf Faktoren wie Bittiefe, Abtastrate und Anzahl von Kanälen manuell zu erstellen.

In diesem Beispiel wird das High-Fidelity-RIFF-Format Riff24Khz16BitMonoPcm angegeben, indem SpeechSynthesisOutputFormat für das SpeechConfig-Objekt festgelegt wird. Ähnlich wie im Beispiel im vorherigen Abschnitt nutzen Sie AudioDataStream, um einen In-Memory-Datenstrom des Ergebnisses abzurufen, den Sie anschließend in eine Datei schreiben.

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

Wenn Sie das Programm ausführen, schreibt es eine WAV-Datei in den angegebenen Pfad.

Verwenden von SSML zum Anpassen von Sprachmerkmalen

Mit SSML können Sie die Tonhöhe, Aussprache, Sprechgeschwindigkeit, Lautstärke und andere Aspekte der Ausgabe der Sprachsynthese optimieren, indem Sie Ihre Anforderungen per XML-Schema übermitteln. Dieser Abschnitt enthält ein Beispiel für das Ändern der Stimme. Weitere Informationen finden Sie unter Übersicht über Speech Synthesis Markup Language.

Wenn Sie SSML für die Anpassung nutzen möchten, nehmen Sie eine geringfügige Änderung vor, um die Stimme zu wechseln.

  1. Erstellen Sie im Stammverzeichnis des Projekts eine neue XML-Datei für die SSML-Konfiguration.

    <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 diesem Beispiel ist die Datei ssml.xml. Das Stammelement ist immer <speak>. Indem Sie den Text in einem <voice>-Element umschließen, können Sie die Stimme mit dem name-Parameter ändern. Eine vollständige Liste der unterstützten neuronalen Stimmen finden Sie unter Unterstützte Sprachen.

  2. Ändern Sie die Anforderung der Sprachsynthese so, dass darin auf Ihre XML-Datei verwiesen wird. Die Anforderung bleibt größtenteils unverändert, aber Sie verwenden nun SpeakSsmlAsync() anstelle von SpeakTextAsync(). Diese Funktion erwartet eine XML-Zeichenfolge. Laden Sie zunächst mithilfe von File.ReadAllText() Ihre SSML-Konfiguration als Zeichenfolge. Ab diesem Punkt stimmt das resultierende Objekt genau mit den Objekten in den vorherigen Beispielen überein.

    Hinweis

    Wenn Sie Visual Studio verwenden, findet Ihre Buildkonfiguration die XML-Datei wahrscheinlich nicht standardmäßig. Klicken Sie mit der rechten Maustaste auf die XML-Datei, und wählen Sie Eigenschaften aus. Ändern Sie Buildaktion in Inhalt. Ändern Sie die Einstellung In Ausgabeverzeichnis kopieren in Immer kopieren.

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

Hinweis

Wenn Sie die Stimme ohne SSML ändern möchten, können Sie die Eigenschaft für SpeechConfig mithilfe von SpeechConfig.SpeechSynthesisVoiceName = "en-US-AvaMultilingualNeural"; festlegen.

Abonnieren von Synthesizerereignissen

Sie sollten mehr über die Sprachsyntheseverarbeitung und die Ergebnisse erfahren. Beispielsweise möchten Sie vielleicht wissen, wann der Synthesizer beginnt und anhält, oder Sie möchten wissen, welche anderen Ereignisse während der Synthese auftreten.

Wenn Sie den SpeechSynthesizer für die Sprachsynthese verwenden, können Sie die Ereignisse in dieser Tabelle abonnieren:

Ereignis BESCHREIBUNG Anwendungsfall
BookmarkReached Signalisiert, dass eine Textmarke erreicht wurde. Zum Auslösen eines Textmarke-erreicht-Ereignisses ist im SSML ein bookmark-Element erforderlich. Dieses Ereignis meldet die verstrichene Audioausgabezeit zwischen dem Beginn der Synthese und dem bookmark-Element. Die Eigenschaft Text des Ereignisses ist der Zeichenfolgenwert, den Sie im Attribut mark der Textmarke festlegen. Die bookmark-Elemente werden nicht ausgesprochen. Sie können das bookmark-Element verwenden, um benutzerdefinierte Marker in SSML einzufügen, um den Offset der einzelnen Marker im Audiostream abzurufen. Das bookmark-Element kann verwendet werden, um auf eine bestimmte Position in der Text- oder Tagsequenz zu verweisen.
SynthesisCanceled Zeigt an, dass die Sprachsynthese abgebrochen wurde. Sie können bestätigen, wann die Synthese abgebrochen wird.
SynthesisCompleted Zeigt an, dass die Sprachsynthese vollständig ist. Sie können bestätigen, wenn die Synthese abgeschlossen wurde.
SynthesisStarted Zeigt an, dass die Sprachsynthese begonnen hat. Sie können bestätigen, wenn die Synthese begonnen hat.
Synthesizing Zeigt an, dass die Sprachsynthese fortgesetzt wird. Dieses Ereignis wird jedes Mal ausgelöst, wenn das SDK einen Audioabschnitt vom Speech-Dienst empfängt. Sie können bestätigen, wenn die Synthese aktuell ausgeführt wird.
VisemeReceived Zeigt an, dass ein Visemereignis empfangen wurde. Viseme (Mundbilder) werden häufig verwendet, um die wichtigsten Gesichtsausdrücke beim Sprechen darzustellen. Sie umfassen u. a. die Position der Lippen, des Kiefers und der Zunge beim Erzeugen eines bestimmten Phonems. Sie können Viseme (Mundbilder) anwenden, um das Gesicht einer Figur zu animieren, wenn die Audiodatei abgespielt wird.
WordBoundary Zeigt an, dass eine Wortgrenze empfangen wurde. Dieses Ereignis wird am Anfang jedes neuen gesprochenen Worts, beim Erreichen von Satzzeichen und am Satzanfang ausgelöst. Das Ereignis meldet den Zeitoffset des aktuellen Worts (in Ticks) vom Anfang der Audioausgabe. Dieses Ereignis meldet außerdem die Zeichenposition im Eingabetext (oder SSML) unmittelbar vor dem Wort, das als Nächstes gesprochen wird. Dieses Ereignis wird häufig verwendet, um die relativen Positionen von Text und den entsprechenden Audiodaten abzurufen. Es kann sinnvoll sein, Informationen zu einem neuen Wort zu empfangen und dann auf der Grundlage des Timings Aktionen auszuführen. Sie können z. B. Informationen abrufen, die Sie bei der Entscheidung unterstützen, wann und wie lange Wörter beim Sprechen hervorgehoben werden sollen.

Hinweis

Ereignisse werden ausgelöst, wenn die ausgegebenen Audiodaten verfügbar werden, was schneller passiert als die Wiedergabe über ein Ausgabegerät. Der Aufrufer muss das Streaming ordnungsgemäß und in Echtzeit synchronisieren.

Dieses Beispiel zeigt, wie Ereignisse für die Sprachsynthese abonniert werden.

Wichtig

Wenn Sie einen API-Schlüssel verwenden, speichern Sie ihn an einer anderen Stelle sicher, z. B. in Azure Key Vault. Fügen Sie den API-Schlüssel nicht direkt in Ihren Code ein, und machen Sie ihn nicht öffentlich zugänglich.

Weitere Informationen zur Sicherheit von KI Services finden Sie unter Authentifizieren von Anforderungen an Azure KI Services.

Sie können die Anweisungen im Schnellstart befolgen, aber den Inhalt dieser Program.cs-Datei durch den folgenden C#-Code ersetzen:

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

Weitere Beispiele zur Sprachsynthese finden Sie auf GitHub.

Verwenden Sie einen benutzerdefinierten Endpunkt

Der benutzerdefinierte Endpunkt verfügt über dieselben Funktionen wie der Standardendpunkt für Sprachsynthese-API-Anforderungen.

Ein Unterschied besteht darin, dass die EndpointId angegeben werden muss, wenn Ihre benutzerdefinierte Stimme über das Speech SDK verwendet werden soll. Sie können mit dem Sprachsynthese-Schnellstart beginnen und dann den Code mit EndpointId und SpeechSynthesisVoiceNameaktualisieren.

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

Zum Verwenden einer benutzerdefinierten Stimme mithilfe von Speech Synthesis Markup Language (SSML) geben Sie den Modellnamen als Stimmnamen an. In diesem Beispiel wird die Stimme YourCustomVoiceName verwendet.

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

Ausführen und Verwenden eines Containers

Speech-Container bieten websocketbasierte Abfrageendpunkt-APIs, auf die über das Speech SDK und die Speech-CLI zugegriffen wird. Standardmäßig verwenden das Speech SDK und die Speech-CLI den öffentlichen Speech-Dienst. Um den Container verwenden zu können, müssen Sie die Initialisierungsmethode ändern. Verwenden Sie eine Containerhost-URL anstelle von Schlüssel und Region.

Weitere Informationen zu Containern finden Sie unter Installieren und Ausführen von Speech-Containern mit Docker.

Referenzdokumentation | Paket (NuGet) | Zusätzliche Beispiele auf GitHub

In dieser Schrittanleitung werden gängige Entwurfsmuster für die Sprachsynthese vorgestellt.

Weitere Informationen zu den folgenden Bereichen finden Sie unter Was ist Sprachsynthese?.

  • Abrufen von Antworten als In-Memory-Datenströme
  • Anpassen der Abtast- und Bitrate der Ausgabe
  • Übermitteln von Syntheseanforderungen mithilfe der Markupsprache für Sprachsynthese (Speech Synthesis Markup Language, SSML)
  • Verwenden neuronaler Stimmen
  • Abonnieren von Ereignissen und ergebnisbezogenes Handeln

Auswählen von Synthesesprache und Stimme

Das Feature für die Sprachsynthese im Speech-Dienst unterstützt mehr als 400 Stimmen und über 140 Sprachen und Varianten. Weitere Informationen finden Sie in der vollständigen Liste der unterstützten regionalen Sprachen für die Sprachsynthese. Sie können sie auch im Stimmkatalog ausprobieren.

Geben Sie die Sprache oder Stimme der SpeechConfig-Klasse entsprechend Ihres Eingabetexts an, und verwenden Sie die festgelegte Stimme. Der folgende Codeschnipsel zeigt, wie dieses Verfahren funktioniert:

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

Alle neuronalen Stimmen sind mehrsprachig und können in ihrer eigenen Sprache und in englischer Sprache sprechen. Wenn der Eingabetext auf Englisch beispielsweise „I'm excited to try text to speech“ lautet und Sie es-ES-ElviraNeural auswählen, wird der Text in englischer Sprache mit einem spanischen Akzent gesprochen.

Wenn die Stimme nicht die Sprache des Eingabetexts spricht, wird keine synthetisierte Audioausgabe vom Speech-Dienst erstellt. Eine vollständige Liste der unterstützten neuronalen Stimmen finden Sie unter Sprach- und Stimmunterstützung für den Speech-Dienst.

Hinweis

Die Standardstimme ist die erste Stimme, die pro Gebietsschema von der Stimmlisten-API zurückgegeben wird.

Die Stimme, die spricht, wird wie folgt nach ihrer Priorität bestimmt:

  • Wenn Sie weder SpeechSynthesisVoiceName noch SpeechSynthesisLanguage festlegen, spricht die Standardstimme für en-US.
  • Wenn Sie nur SpeechSynthesisLanguage festlegen, spricht die Standardstimme für das angegebene Gebietsschema.
  • Wenn sowohl SpeechSynthesisVoiceName als auch SpeechSynthesisLanguage festgelegt sind, wird die Einstellung SpeechSynthesisLanguage ignoriert. Die Stimme, die Sie mithilfe von SpeechSynthesisVoiceName angeben, spricht.
  • Wenn das Stimmelement über Speech Synthesis Markup Language (SSML) festgelegt wird, werden die Einstellungen SpeechSynthesisVoiceName und SpeechSynthesisLanguage ignoriert.

Zusammenfassend kann die Reihenfolge der Priorität wie folgt beschrieben werden:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Ergebnis
Die Standardstimme für en-US spricht.
Die Standardstimme für das angegebene Gebietsschema spricht.
Die Stimme, die Sie mithilfe von SpeechSynthesisVoiceName angeben, spricht.
Die Stimme, die Sie mithilfe von SSML angeben, spricht.

Synthetisieren von Sprache in eine Datei

Erstellen Sie ein SpeechSynthesizer-Objekt. Das in den folgenden Codeschnipseln gezeigte Objekt führt die Konvertierungen von Text in Sprache und Ausgaben an Lautsprecher, in Dateien oder andere Ausgabestreams aus. SpeechSynthesizer akzeptiert folgende Parameter:

  • Das SpeechConfig-Objekt, das Sie im vorherigen Schritt erstellt haben
  • Ein AudioConfig-Objekt, das angibt, wie Ausgabeergebnisse verarbeitet werden sollen
  1. Erstellen Sie eine AudioConfig-Instanz, um die Ausgabe mithilfe der Funktion FromWavFileOutput() automatisch in eine WAV-Datei zu schreiben:

    void synthesizeSpeech()
    {
        auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
        auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav");
    }
    
  2. Instanziieren Sie eine SpeechSynthesizer-Instanz. Übergeben Sie die speechConfig- und audioConfig-Objekte als Parameter. Um Sprache zu synthetisieren und in eine Datei zu schreiben, führen Sie SpeakTextAsync() mit einer Textzeichenfolge aus.

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

Wenn Sie das Programm ausführen, wird eine synthetisierte WAV-Datei erstellt, die an den von Ihnen angegebenen Speicherort geschrieben wird. Dieses Ergebnis ist ein gutes Beispiel für die einfachste Verwendungsmöglichkeit. Als Nächstes können Sie die Ausgabe anpassen und die Ausgabeantwort als In-Memory-Datenstrom für benutzerdefinierte Szenarios verarbeiten.

Synthetisieren der Lautsprecherausgabe

Zum Ausgeben von synthetisierter Sprache auf dem aktuell aktiven Ausgabegerät wie einem Lautsprecher lassen Sie den Parameter AudioConfig weg, wenn Sie die SpeechSynthesizer-Instanz erstellen. Ein Beispiel:

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

Abrufen eines Ergebnisses als In-Memory-Datenstrom

Sie können die resultierenden Audiodaten als einen In-Memory-Datenstrom verwenden, statt sie direkt in eine Datei zu schreiben. Mit einem In-Memory-Datenstrom können Sie benutzerdefiniertes Verhalten erstellen:

  • Abstrahieren des resultierenden Bytearrays als durchsuchbaren Datenstrom für benutzerdefinierte Downstreamdienste
  • Integrieren des Ergebnisses in andere APIs oder Dienste
  • Ändern Sie die Audiodaten, schreiben Sie benutzerdefinierte WAV-Header, und erledigen Sie zugehörige Aufgaben.

Sie können diese Änderung am vorherigen Beispiel vornehmen. Entfernen Sie zunächst den AudioConfig-Block, da Sie das Ausgabeverhalten ab jetzt manuell verwalten, um eine bessere Kontrolle zu erzielen. Übergeben Sie im SpeechSynthesizer-Konstruktor NULL für AudioConfig.

Hinweis

Wenn Sie NULL für AudioConfig übergeben, anstatt den Parameter wie im obigen Beispiel für die Lautsprecherausgabe wegzulassen, werden die Audiodaten nicht standardmäßig auf dem derzeit aktiven Ausgabegerät wiedergegeben.

Speichern Sie das Ergebnis in einer SpeechSynthesisResult-Variablen. Der GetAudioData-Getter gibt eine byte []-Instanz für die Ausgabedaten zurück. Sie können diese byte []-Instanz manuell nutzen oder die AudioDataStream-Klasse verwenden, um den In-Memory-Datenstrom zu verwalten.

In diesem Beispiel verwenden Sie die statische Funktion AudioDataStream.FromResult(), um einen Datenstrom aus dem Ergebnis abzurufen:

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

Nun können Sie mit dem resultierenden stream-Objekt ein beliebiges benutzerdefiniertes Verhalten implementieren.

Anpassen des Audioformats

Sie können die Attribute der Audioausgabe anpassen, z. B.:

  • Audiodateityp
  • Samplingrate
  • Bittiefe

Zum Ändern des Audioformats wenden Sie die Funktion SetSpeechSynthesisOutputFormat() auf das Objekt SpeechConfig an. Diese Funktion erwartet eine enum-Instanz vom Typ SpeechSynthesisOutputFormat. Verwenden Sie enum, um das Ausgabeformat auszuwählen. Informationen zu den verfügbaren Formaten finden Sie in der Liste der Audioformate.

Abhängig von Ihren Anforderungen stehen Ihnen verschiedene Optionen für unterschiedliche Dateitypen zur Verfügung. Rohformate wie Raw24Khz16BitMonoPcm enthalten gemäß Definition keine Audioheader. Verwenden Sie Rohformate nur in den folgenden Situationen:

  • Sie wissen, dass Ihre Downstreamimplementierung einen unformatierten Bitstream decodieren kann.
  • Sie planen, Header basierend auf Faktoren wie Bittiefe, Abtastrate und Anzahl von Kanälen manuell zu erstellen.

In diesem Beispiel wird das High-Fidelity-RIFF-Format Riff24Khz16BitMonoPcm angegeben, indem SpeechSynthesisOutputFormat für das SpeechConfig-Objekt festgelegt wird. Ähnlich wie im Beispiel im vorherigen Abschnitt nutzen Sie AudioDataStream, um einen InMemory-Datenstrom des Ergebnisses zu erhalten, das Sie anschließend in eine Datei schreiben.

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

Wenn Sie das Programm ausführen, schreibt es eine WAV-Datei in den angegebenen Pfad.

Verwenden von SSML zum Anpassen von Sprachmerkmalen

Mit SSML können Sie die Tonhöhe, Aussprache, Sprechgeschwindigkeit, Lautstärke und andere Aspekte der Ausgabe der Sprachsynthese optimieren, indem Sie Ihre Anforderungen per XML-Schema übermitteln. Dieser Abschnitt enthält ein Beispiel für das Ändern der Stimme. Weitere Informationen finden Sie unter Übersicht über Speech Synthesis Markup Language.

Wenn Sie SSML für die Anpassung nutzen möchten, nehmen Sie eine geringfügige Änderung vor, um die Stimme zu wechseln.

  1. Erstellen Sie im Stammverzeichnis des Projekts eine neue XML-Datei für die SSML-Konfiguration.

    <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 diesem Beispiel ist die Datei ssml.xml. Das Stammelement ist immer <speak>. Indem Sie den Text in einem <voice>-Element umschließen, können Sie die Stimme mit dem name-Parameter ändern. Eine vollständige Liste der unterstützten neuronalen Stimmen finden Sie unter Unterstützte Sprachen.

  2. Ändern Sie die Anforderung der Sprachsynthese so, dass darin auf Ihre XML-Datei verwiesen wird. Die Anforderung ist größtenteils identisch. Anstatt die SpeakTextAsync()-Funktion zu verwenden, verwenden Sie SpeakSsmlAsync(). Diese Funktion erwartet eine XML-Zeichenfolge. Laden Sie zunächst Ihre SSML-Konfiguration als Zeichenfolge. Ab diesem Punkt stimmt das resultierende Objekt genau mit den Objekten in den vorherigen Beispielen überein.

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

Hinweis

Wenn Sie die Stimme ohne SSML ändern möchten, können Sie die Eigenschaft für SpeechConfig mithilfe von SpeechConfig.SetSpeechSynthesisVoiceName("en-US-AndrewMultilingualNeural") festlegen.

Abonnieren von Synthesizerereignissen

Sie sollten mehr über die Sprachsyntheseverarbeitung und die Ergebnisse erfahren. Beispielsweise möchten Sie vielleicht wissen, wann der Synthesizer beginnt und anhält, oder Sie möchten wissen, welche anderen Ereignisse während der Synthese auftreten.

Wenn Sie den SpeechSynthesizer für die Sprachsynthese verwenden, können Sie die Ereignisse in dieser Tabelle abonnieren:

Ereignis BESCHREIBUNG Anwendungsfall
BookmarkReached Signalisiert, dass eine Textmarke erreicht wurde. Zum Auslösen eines Textmarke-erreicht-Ereignisses ist im SSML ein bookmark-Element erforderlich. Dieses Ereignis meldet die verstrichene Audioausgabezeit zwischen dem Beginn der Synthese und dem bookmark-Element. Die Eigenschaft Text des Ereignisses ist der Zeichenfolgenwert, den Sie im Attribut mark der Textmarke festlegen. Die bookmark-Elemente werden nicht ausgesprochen. Sie können das bookmark-Element verwenden, um benutzerdefinierte Marker in SSML einzufügen, um den Offset der einzelnen Marker im Audiostream abzurufen. Das bookmark-Element kann verwendet werden, um auf eine bestimmte Position in der Text- oder Tagsequenz zu verweisen.
SynthesisCanceled Zeigt an, dass die Sprachsynthese abgebrochen wurde. Sie können bestätigen, wann die Synthese abgebrochen wird.
SynthesisCompleted Zeigt an, dass die Sprachsynthese vollständig ist. Sie können bestätigen, wenn die Synthese abgeschlossen wurde.
SynthesisStarted Zeigt an, dass die Sprachsynthese begonnen hat. Sie können bestätigen, wenn die Synthese begonnen hat.
Synthesizing Zeigt an, dass die Sprachsynthese fortgesetzt wird. Dieses Ereignis wird jedes Mal ausgelöst, wenn das SDK einen Audioabschnitt vom Speech-Dienst empfängt. Sie können bestätigen, wenn die Synthese aktuell ausgeführt wird.
VisemeReceived Zeigt an, dass ein Visemereignis empfangen wurde. Viseme (Mundbilder) werden häufig verwendet, um die wichtigsten Gesichtsausdrücke beim Sprechen darzustellen. Sie umfassen u. a. die Position der Lippen, des Kiefers und der Zunge beim Erzeugen eines bestimmten Phonems. Sie können Viseme (Mundbilder) anwenden, um das Gesicht einer Figur zu animieren, wenn die Audiodatei abgespielt wird.
WordBoundary Zeigt an, dass eine Wortgrenze empfangen wurde. Dieses Ereignis wird am Anfang jedes neuen gesprochenen Worts, beim Erreichen von Satzzeichen und am Satzanfang ausgelöst. Das Ereignis meldet den Zeitoffset des aktuellen Worts (in Ticks) vom Anfang der Audioausgabe. Dieses Ereignis meldet außerdem die Zeichenposition im Eingabetext (oder SSML) unmittelbar vor dem Wort, das als Nächstes gesprochen wird. Dieses Ereignis wird häufig verwendet, um die relativen Positionen von Text und den entsprechenden Audiodaten abzurufen. Es kann sinnvoll sein, Informationen zu einem neuen Wort zu empfangen und dann auf der Grundlage des Timings Aktionen auszuführen. Sie können z. B. Informationen abrufen, die Sie bei der Entscheidung unterstützen, wann und wie lange Wörter beim Sprechen hervorgehoben werden sollen.

Hinweis

Ereignisse werden ausgelöst, wenn die ausgegebenen Audiodaten verfügbar werden, was schneller passiert als die Wiedergabe über ein Ausgabegerät. Der Aufrufer muss das Streaming ordnungsgemäß und in Echtzeit synchronisieren.

Dieses Beispiel zeigt, wie Ereignisse für die Sprachsynthese abonniert werden.

Wichtig

Wenn Sie einen API-Schlüssel verwenden, speichern Sie ihn an einer anderen Stelle sicher, z. B. in Azure Key Vault. Fügen Sie den API-Schlüssel nicht direkt in Ihren Code ein, und machen Sie ihn nicht öffentlich zugänglich.

Weitere Informationen zur Sicherheit von KI Services finden Sie unter Authentifizieren von Anforderungen an Azure KI Services.

Sie können die Anweisungen im Schnellstart befolgen, aber den Inhalt dieser main.cpp-Datei durch den folgenden Code ersetzen:

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

Weitere Beispiele zur Sprachsynthese finden Sie auf GitHub.

Verwenden Sie einen benutzerdefinierten Endpunkt

Der benutzerdefinierte Endpunkt verfügt über dieselben Funktionen wie der Standardendpunkt für Sprachsynthese-Anforderungen.

Ein Unterschied besteht darin, dass die EndpointId angegeben werden muss, wenn Ihre benutzerdefinierte Stimme über das Speech SDK verwendet werden soll. Sie können mit dem Sprachsynthese-Schnellstart beginnen und dann den Code mit EndpointId und SpeechSynthesisVoiceNameaktualisieren.

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

Zum Verwenden einer benutzerdefinierten Stimme mithilfe von Speech Synthesis Markup Language (SSML) geben Sie den Modellnamen als Stimmnamen an. In diesem Beispiel wird die Stimme YourCustomVoiceName verwendet.

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

Ausführen und Verwenden eines Containers

Speech-Container bieten websocketbasierte Abfrageendpunkt-APIs, auf die über das Speech SDK und die Speech-CLI zugegriffen wird. Standardmäßig verwenden das Speech SDK und die Speech-CLI den öffentlichen Speech-Dienst. Um den Container verwenden zu können, müssen Sie die Initialisierungsmethode ändern. Verwenden Sie eine Containerhost-URL anstelle von Schlüssel und Region.

Weitere Informationen zu Containern finden Sie unter Installieren und Ausführen von Speech-Containern mit Docker.

Referenzdokumentation | Paket (Go) | Zusätzliche Beispiele auf GitHub

In dieser Schrittanleitung werden gängige Entwurfsmuster für die Sprachsynthese vorgestellt.

Weitere Informationen zu den folgenden Bereichen finden Sie unter Was ist Sprachsynthese?.

  • Abrufen von Antworten als In-Memory-Datenströme
  • Anpassen der Abtast- und Bitrate der Ausgabe
  • Übermitteln von Syntheseanforderungen mithilfe der Markupsprache für Sprachsynthese (Speech Synthesis Markup Language, SSML)
  • Verwenden neuronaler Stimmen
  • Abonnieren von Ereignissen und ergebnisbezogenes Handeln

Voraussetzungen

Installieren des Speech SDK

Zuallererst müssen Sie das Speech SDK für Go installieren.

Sprachsynthese über Lautsprecher

Verwenden Sie das folgende Codebeispiel, um die Sprachsynthese über Ihr standardmäßiges Audioausgabegerät durchzuführen. Ersetzen Sie die Variablen subscription und region durch Ihren Schlüssel für die Spracheingabe und durch Ihren Standort/Ihre Region. Wenn Sie das Skript ausführen, wird Ihr Eingabetext über den Standardlautsprecher gesprochen.

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

Führen Sie die folgenden Befehle aus, um eine Datei namens go.mod zu erstellen, die mit auf GitHub gehosteten Komponenten verknüpft ist:

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

Erstellen Sie nun den Code, und führen Sie ihn aus:

go build
go run quickstart

Ausführliche Informationen zu den Klassen finden Sie in der Referenzdokumentation zu SpeechConfig und SpeechSynthesizer.

Sprachsynthese über In-Memory-Datenstrom

Sie können die resultierenden Audiodaten als einen In-Memory-Datenstrom verwenden, statt sie direkt in eine Datei zu schreiben. Mit einem In-Memory-Datenstrom können Sie benutzerdefiniertes Verhalten erstellen:

  • Abstrahieren des resultierenden Bytearrays als durchsuchbaren Datenstrom für benutzerdefinierte Downstreamdienste
  • Integrieren des Ergebnisses in andere APIs oder Dienste
  • Ändern Sie die Audiodaten, schreiben Sie benutzerdefinierte WAV-Header, und erledigen Sie zugehörige Aufgaben.

Sie können diese Änderung am vorherigen Beispiel vornehmen. Entfernen Sie den AudioConfig-Block, da Sie das Ausgabeverhalten ab jetzt manuell verwalten, um eine bessere Kontrolle zu erzielen. Übergeben Sie anschließend im SpeechSynthesizer-Konstruktor nil für AudioConfig.

Hinweis

Wenn Sie nil für AudioConfig übergeben, anstatt den Parameter wie im obigen Beispiel für die Lautsprecherausgabe wegzulassen, werden die Audiodaten nicht standardmäßig auf dem derzeit aktiven Ausgabegerät wiedergegeben.

Speichern Sie das Ergebnis in einer SpeechSynthesisResult-Variablen. Die AudioData-Eigenschaft gibt eine []byte-Instanz für die Ausgabedaten zurück. Sie können diese []byte-Instanz manuell nutzen oder die AudioDataStream-Klasse verwenden, um den In-Memory-Datenstrom zu verwalten. In diesem Beispiel verwenden Sie die statische Funktion NewAudioDataStreamFromSpeechSynthesisResult(), um einen Datenstrom aus dem Ergebnis abzurufen.

Ersetzen Sie die Variablen subscription und region durch Ihren Schlüssel für die Spracheingabe und durch Ihren Standort bzw. Ihre Region:

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

Führen Sie die folgenden Befehle aus, um eine Datei namens go.mod zu erstellen, die mit auf GitHub gehosteten Komponenten verknüpft ist:

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

Erstellen Sie nun den Code, und führen Sie ihn aus:

go build
go run quickstart

Ausführliche Informationen zu den Klassen finden Sie in der Referenzdokumentation zu SpeechConfig und SpeechSynthesizer.

Auswählen von Synthesesprache und Stimme

Das Feature für die Sprachsynthese im Speech-Dienst unterstützt mehr als 400 Stimmen und über 140 Sprachen und Varianten. Sie können die vollständige Liste abrufen oder sie im Stimmkatalog ausprobieren.

Geben Sie die Sprache oder Stimme von SpeechConfig entsprechend Ihres Eingabetexts an, und verwenden Sie die festgelegte Stimme:

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 neuronalen Stimmen sind mehrsprachig und können in ihrer eigenen Sprache und in englischer Sprache sprechen. Wenn der Eingabetext auf Englisch beispielsweise „I'm excited to try text to speech“ lautet und Sie es-ES-ElviraNeural auswählen, wird der Text in englischer Sprache mit einem spanischen Akzent gesprochen.

Wenn die Stimme nicht die Sprache des Eingabetexts spricht, wird keine synthetisierte Audioausgabe vom Speech-Dienst erstellt. Eine vollständige Liste der unterstützten neuronalen Stimmen finden Sie unter Sprach- und Stimmunterstützung für den Speech-Dienst.

Hinweis

Die Standardstimme ist die erste Stimme, die pro Gebietsschema von der Stimmlisten-API zurückgegeben wird.

Die Stimme, die spricht, wird wie folgt nach ihrer Priorität bestimmt:

  • Wenn Sie weder SpeechSynthesisVoiceName noch SpeechSynthesisLanguage festlegen, spricht die Standardstimme für en-US.
  • Wenn Sie nur SpeechSynthesisLanguage festlegen, spricht die Standardstimme für das angegebene Gebietsschema.
  • Wenn sowohl SpeechSynthesisVoiceName als auch SpeechSynthesisLanguage festgelegt sind, wird die Einstellung SpeechSynthesisLanguage ignoriert. Die Stimme, die Sie mithilfe von SpeechSynthesisVoiceName angeben, spricht.
  • Wenn das Stimmelement über Speech Synthesis Markup Language (SSML) festgelegt wird, werden die Einstellungen SpeechSynthesisVoiceName und SpeechSynthesisLanguage ignoriert.

Zusammenfassend kann die Reihenfolge der Priorität wie folgt beschrieben werden:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Ergebnis
Die Standardstimme für en-US spricht.
Die Standardstimme für das angegebene Gebietsschema spricht.
Die Stimme, die Sie mithilfe von SpeechSynthesisVoiceName angeben, spricht.
Die Stimme, die Sie mithilfe von SSML angeben, spricht.

Verwenden von SSML zum Anpassen von Sprachmerkmalen

Mit der Markupsprache für Sprachsynthese (Speech Synthesis Markup Language, SSML) können Sie die Tonhöhe, Aussprache, Sprechgeschwindigkeit, Lautstärke und weitere Aspekte der Ausgabe der Sprachsynthese optimieren, indem Sie Ihre Anforderungen per XML-Schema übermitteln. Dieser Abschnitt enthält ein Beispiel für das Ändern der Stimme. Weitere Informationen finden Sie unter Übersicht über Speech Synthesis Markup Language.

Wenn Sie SSML für die Anpassung nutzen möchten, nehmen Sie eine geringfügige Änderung vor, um die Stimme zu wechseln.

Erstellen Sie zuerst im Stammverzeichnis des Projekts eine neue XML-Datei für die SSML-Konfiguration. In diesem Beispiel lautet er ssml.xml. Das Stammelement ist immer <speak>. Indem Sie den Text in einem <voice>-Element umschließen, können Sie die Stimme mit dem name-Parameter ändern. Eine vollständige Liste der unterstützten neuronalen Stimmen finden Sie unter Unterstützte Sprachen.

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

Als Nächstes müssen Sie die Anforderung der Sprachsynthese so ändern, dass darin auf Ihre XML-Datei verwiesen wird. Die Anforderung bleibt größtenteils unverändert, aber Sie verwenden nun SpeakSsmlAsync() anstelle von SpeakTextAsync(). Diese Funktion erwartet eine XML-Zeichenfolge. Daher laden Sie zunächst Ihre SSML-Konfiguration als Zeichenfolge. Ab diesem Punkt stimmt das resultierende Objekt genau mit den Objekten in den vorherigen Beispielen überein.

Hinweis

Wenn Sie die Stimme ohne SSML festlegen möchten, können Sie die Eigenschaft für SpeechConfig mithilfe von speechConfig.SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural") festlegen.

Abonnieren von Synthesizerereignissen

Sie sollten mehr über die Sprachsyntheseverarbeitung und die Ergebnisse erfahren. Beispielsweise möchten Sie vielleicht wissen, wann der Synthesizer beginnt und anhält, oder Sie möchten wissen, welche anderen Ereignisse während der Synthese auftreten.

Wenn Sie den SpeechSynthesizer für die Sprachsynthese verwenden, können Sie die Ereignisse in dieser Tabelle abonnieren:

Ereignis BESCHREIBUNG Anwendungsfall
BookmarkReached Signalisiert, dass eine Textmarke erreicht wurde. Zum Auslösen eines Textmarke-erreicht-Ereignisses ist im SSML ein bookmark-Element erforderlich. Dieses Ereignis meldet die verstrichene Audioausgabezeit zwischen dem Beginn der Synthese und dem bookmark-Element. Die Eigenschaft Text des Ereignisses ist der Zeichenfolgenwert, den Sie im Attribut mark der Textmarke festlegen. Die bookmark-Elemente werden nicht ausgesprochen. Sie können das bookmark-Element verwenden, um benutzerdefinierte Marker in SSML einzufügen, um den Offset der einzelnen Marker im Audiostream abzurufen. Das bookmark-Element kann verwendet werden, um auf eine bestimmte Position in der Text- oder Tagsequenz zu verweisen.
SynthesisCanceled Zeigt an, dass die Sprachsynthese abgebrochen wurde. Sie können bestätigen, wann die Synthese abgebrochen wird.
SynthesisCompleted Zeigt an, dass die Sprachsynthese vollständig ist. Sie können bestätigen, wenn die Synthese abgeschlossen wurde.
SynthesisStarted Zeigt an, dass die Sprachsynthese begonnen hat. Sie können bestätigen, wenn die Synthese begonnen hat.
Synthesizing Zeigt an, dass die Sprachsynthese fortgesetzt wird. Dieses Ereignis wird jedes Mal ausgelöst, wenn das SDK einen Audioabschnitt vom Speech-Dienst empfängt. Sie können bestätigen, wenn die Synthese aktuell ausgeführt wird.
VisemeReceived Zeigt an, dass ein Visemereignis empfangen wurde. Viseme (Mundbilder) werden häufig verwendet, um die wichtigsten Gesichtsausdrücke beim Sprechen darzustellen. Sie umfassen u. a. die Position der Lippen, des Kiefers und der Zunge beim Erzeugen eines bestimmten Phonems. Sie können Viseme (Mundbilder) anwenden, um das Gesicht einer Figur zu animieren, wenn die Audiodatei abgespielt wird.
WordBoundary Zeigt an, dass eine Wortgrenze empfangen wurde. Dieses Ereignis wird am Anfang jedes neuen gesprochenen Worts, beim Erreichen von Satzzeichen und am Satzanfang ausgelöst. Das Ereignis meldet den Zeitoffset des aktuellen Worts (in Ticks) vom Anfang der Audioausgabe. Dieses Ereignis meldet außerdem die Zeichenposition im Eingabetext (oder SSML) unmittelbar vor dem Wort, das als Nächstes gesprochen wird. Dieses Ereignis wird häufig verwendet, um die relativen Positionen von Text und den entsprechenden Audiodaten abzurufen. Es kann sinnvoll sein, Informationen zu einem neuen Wort zu empfangen und dann auf der Grundlage des Timings Aktionen auszuführen. Sie können z. B. Informationen abrufen, die Sie bei der Entscheidung unterstützen, wann und wie lange Wörter beim Sprechen hervorgehoben werden sollen.

Hinweis

Ereignisse werden ausgelöst, wenn die ausgegebenen Audiodaten verfügbar werden, was schneller passiert als die Wiedergabe über ein Ausgabegerät. Der Aufrufer muss das Streaming ordnungsgemäß und in Echtzeit synchronisieren.

Dieses Beispiel zeigt, wie Ereignisse für die Sprachsynthese abonniert werden.

Wichtig

Wenn Sie einen API-Schlüssel verwenden, speichern Sie ihn an einer anderen Stelle sicher, z. B. in Azure Key Vault. Fügen Sie den API-Schlüssel nicht direkt in Ihren Code ein, und machen Sie ihn nicht öffentlich zugänglich.

Weitere Informationen zur Sicherheit von KI Services finden Sie unter Authentifizieren von Anforderungen an Azure KI Services.

Sie können die Anweisungen im Schnellstart befolgen, aber den Inhalt dieser speech-synthesis.go-Datei durch den folgenden Go-Code ersetzen:

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

Weitere Beispiele zur Sprachsynthese finden Sie auf GitHub.

Ausführen und Verwenden eines Containers

Speech-Container bieten websocketbasierte Abfrageendpunkt-APIs, auf die über das Speech SDK und die Speech-CLI zugegriffen wird. Standardmäßig verwenden das Speech SDK und die Speech-CLI den öffentlichen Speech-Dienst. Um den Container verwenden zu können, müssen Sie die Initialisierungsmethode ändern. Verwenden Sie eine Containerhost-URL anstelle von Schlüssel und Region.

Weitere Informationen zu Containern finden Sie unter Installieren und Ausführen von Speech-Containern mit Docker.

Referenzdokumentation | Zusätzliche Beispiele auf GitHub

In dieser Schrittanleitung werden gängige Entwurfsmuster für die Sprachsynthese vorgestellt.

Weitere Informationen zu den folgenden Bereichen finden Sie unter Was ist Sprachsynthese?.

  • Abrufen von Antworten als In-Memory-Datenströme
  • Anpassen der Abtast- und Bitrate der Ausgabe
  • Übermitteln von Syntheseanforderungen mithilfe der Markupsprache für Sprachsynthese (Speech Synthesis Markup Language, SSML)
  • Verwenden neuronaler Stimmen
  • Abonnieren von Ereignissen und ergebnisbezogenes Handeln

Auswählen von Synthesesprache und Stimme

Das Feature für die Sprachsynthese im Speech-Dienst unterstützt mehr als 400 Stimmen und über 140 Sprachen und Varianten. Sie können die vollständige Liste abrufen oder sie im Stimmkatalog ausprobieren.

Geben Sie die Sprache oder Stimme von SpeechConfig entsprechend Ihres Eingabetexts an, und verwenden Sie die festgelegte Stimme. Der folgende Codeschnipsel zeigt, wie dieses Verfahren funktioniert:

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 neuronalen Stimmen sind mehrsprachig und können in ihrer eigenen Sprache und in englischer Sprache sprechen. Wenn der Eingabetext auf Englisch beispielsweise „I'm excited to try text to speech“ lautet und Sie es-ES-ElviraNeural auswählen, wird der Text in englischer Sprache mit einem spanischen Akzent gesprochen.

Wenn die Stimme nicht die Sprache des Eingabetexts spricht, wird keine synthetisierte Audioausgabe vom Speech-Dienst erstellt. Eine vollständige Liste der unterstützten neuronalen Stimmen finden Sie unter Sprach- und Stimmunterstützung für den Speech-Dienst.

Hinweis

Die Standardstimme ist die erste Stimme, die pro Gebietsschema von der Stimmlisten-API zurückgegeben wird.

Die Stimme, die spricht, wird wie folgt nach ihrer Priorität bestimmt:

  • Wenn Sie weder SpeechSynthesisVoiceName noch SpeechSynthesisLanguage festlegen, spricht die Standardstimme für en-US.
  • Wenn Sie nur SpeechSynthesisLanguage festlegen, spricht die Standardstimme für das angegebene Gebietsschema.
  • Wenn sowohl SpeechSynthesisVoiceName als auch SpeechSynthesisLanguage festgelegt sind, wird die Einstellung SpeechSynthesisLanguage ignoriert. Die Stimme, die Sie mithilfe von SpeechSynthesisVoiceName angegeben haben, spricht.
  • Wenn das Stimmelement über Speech Synthesis Markup Language (SSML) festgelegt wird, werden die Einstellungen SpeechSynthesisVoiceName und SpeechSynthesisLanguage ignoriert.

Zusammenfassend kann die Reihenfolge der Priorität wie folgt beschrieben werden:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Ergebnis
Die Standardstimme für en-US spricht.
Die Standardstimme für das angegebene Gebietsschema spricht.
Die Stimme, die Sie mithilfe von SpeechSynthesisVoiceName angeben, spricht.
Die Stimme, die Sie mithilfe von SSML angeben, spricht.

Synthetisieren von Sprache in eine Datei

Erstellen eines SpeechSynthesizer-Objekts Dieses Objekt führt die Konvertierungen von Text in Sprache und Ausgaben an Lautsprecher, in Dateien oder andere Ausgabestreams aus. SpeechSynthesizer akzeptiert folgende Parameter:

  • Das SpeechConfig-Objekt, das Sie im vorherigen Schritt erstellt haben
  • Ein AudioConfig-Objekt, das angibt, wie Ausgabeergebnisse verarbeitet werden sollen
  1. Erstellen Sie eine AudioConfig-Instanz, um die Ausgabe mithilfe der statischen Funktion fromWavFileOutput() automatisch in eine WAV-Datei zu schreiben:

    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav");
    }
    
  2. Instanziieren Sie eine SpeechSynthesizer-Instanz. Übergeben Sie die speechConfig- und audioConfig-Objekte als Parameter. Um Sprache zu synthetisieren und in eine Datei zu schreiben, führen Sie SpeakText() mit einer Textzeichenfolge aus.

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

Wenn Sie das Programm ausführen, wird eine synthetisierte WAV-Datei erstellt, die an den von Ihnen angegebenen Speicherort geschrieben wird. Dieses Ergebnis ist ein gutes Beispiel für die einfachste Verwendungsmöglichkeit. Als Nächstes können Sie die Ausgabe anpassen und die Ausgabeantwort als In-Memory-Datenstrom für benutzerdefinierte Szenarios verarbeiten.

Synthetisieren der Lautsprecherausgabe

Sie sollten mehr über die Sprachsyntheseverarbeitung und die Ergebnisse erfahren. Beispielsweise möchten Sie vielleicht wissen, wann der Synthesizer beginnt und anhält, oder Sie möchten wissen, welche anderen Ereignisse während der Synthese auftreten.

Zum Ausgeben von synthetisierter Sprache an das aktuell aktive Ausgabegerät wie etwa einen Lautsprecher instanziieren Sie AudioConfig mithilfe der statischen Funktion fromDefaultSpeakerOutput(). Hier sehen Sie ein Beispiel:

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

Abrufen eines Ergebnisses als In-Memory-Datenstrom

Sie können die resultierenden Audiodaten als einen In-Memory-Datenstrom verwenden, statt sie direkt in eine Datei zu schreiben. Mit einem In-Memory-Datenstrom können Sie benutzerdefiniertes Verhalten erstellen:

  • Abstrahieren des resultierenden Bytearrays als durchsuchbaren Datenstrom für benutzerdefinierte Downstreamdienste
  • Integrieren des Ergebnisses in andere APIs oder Dienste
  • Ändern Sie die Audiodaten, schreiben Sie benutzerdefinierte WAV-Header, und erledigen Sie zugehörige Aufgaben.

Sie können diese Änderung am vorherigen Beispiel vornehmen. Entfernen Sie zunächst den AudioConfig-Block, da Sie das Ausgabeverhalten ab jetzt manuell verwalten, um eine bessere Kontrolle zu erzielen. Übergeben Sie anschließend im SpeechSynthesizer-Konstruktor null für AudioConfig.

Hinweis

Wenn Sie null für AudioConfig übergeben, anstatt den Parameter wie im obigen Beispiel für die Lautsprecherausgabe wegzulassen, werden die Audiodaten nicht standardmäßig auf dem derzeit aktiven Ausgabegerät wiedergegeben.

Speichern Sie das Ergebnis in einer SpeechSynthesisResult-Variablen. Die Funktion SpeechSynthesisResult.getAudioData() gibt eine byte []-Instanz der Ausgabedaten zurück. Sie können diese byte []-Instanz manuell nutzen oder die AudioDataStream-Klasse verwenden, um den In-Memory-Datenstrom zu verwalten.

In diesem Beispiel verwenden Sie die statische Funktion AudioDataStream.fromResult(), um einen Datenstrom aus dem Ergebnis abzurufen:

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

Nun können Sie mit dem resultierenden stream-Objekt ein beliebiges benutzerdefiniertes Verhalten implementieren.

Anpassen des Audioformats

Sie können die Attribute der Audioausgabe anpassen, z. B.:

  • Audiodateityp
  • Samplingrate
  • Bittiefe

Zum Ändern des Audioformats wenden Sie die Funktion setSpeechSynthesisOutputFormat() auf das Objekt SpeechConfig an. Diese Funktion erwartet eine enum-Instanz vom Typ SpeechSynthesisOutputFormat. Verwenden Sie enum, um das Ausgabeformat auszuwählen. Informationen zu den verfügbaren Formaten finden Sie in der Liste der Audioformate.

Abhängig von Ihren Anforderungen stehen Ihnen verschiedene Optionen für unterschiedliche Dateitypen zur Verfügung. Rohformate wie Raw24Khz16BitMonoPcm enthalten gemäß Definition keine Audioheader. Verwenden Sie Rohformate nur in den folgenden Situationen:

  • Sie wissen, dass Ihre Downstreamimplementierung einen unformatierten Bitstream decodieren kann.
  • Sie planen, Header basierend auf Faktoren wie Bittiefe, Abtastrate und Anzahl von Kanälen manuell zu erstellen.

In diesem Beispiel wird das High-Fidelity-RIFF-Format Riff24Khz16BitMonoPcm angegeben, indem SpeechSynthesisOutputFormat für das SpeechConfig-Objekt festgelegt wird. Ähnlich wie im Beispiel im vorherigen Abschnitt nutzen Sie AudioDataStream, um einen InMemory-Datenstrom des Ergebnisses zu erhalten, das Sie anschließend in eine Datei schreiben.

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

Wenn Sie das Programm ausführen, schreibt es eine WAV-Datei in den angegebenen Pfad.

Verwenden von SSML zum Anpassen von Sprachmerkmalen

Mit SSML können Sie die Tonhöhe, Aussprache, Sprechgeschwindigkeit, Lautstärke und andere Aspekte der Ausgabe der Sprachsynthese optimieren, indem Sie Ihre Anforderungen per XML-Schema übermitteln. Dieser Abschnitt enthält ein Beispiel für das Ändern der Stimme. Weitere Informationen finden Sie im Artikel zur Verwendung von SSML.

Wenn Sie SSML für die Anpassung nutzen möchten, nehmen Sie eine geringfügige Änderung vor, um die Stimme zu wechseln.

  1. Erstellen Sie im Stammverzeichnis des Projekts eine neue XML-Datei für die SSML-Konfiguration.

    <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 diesem Beispiel ist die Datei ssml.xml. Das Stammelement ist immer <speak>. Indem Sie den Text in einem <voice>-Element umschließen, können Sie die Stimme mit dem name-Parameter ändern. Eine vollständige Liste der unterstützten neuronalen Stimmen finden Sie unter Unterstützte Sprachen.

  2. Ändern Sie die Anforderung der Sprachsynthese so, dass darin auf Ihre XML-Datei verwiesen wird. Die Anforderung ist größtenteils identisch. Anstatt die SpeakText()-Funktion zu verwenden, verwenden Sie SpeakSsml(). Diese Funktion erwartet eine XML-Zeichenfolge. Daher erstellen Sie zunächst eine Funktion, um eine XML-Datei zu laden und als Zeichenfolge zurückzugeben:

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

    An diesem Punkt stimmt das resultierende Objekt genau mit den Objekten in den vorherigen Beispielen überein:

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

Hinweis

Wenn Sie die Stimme ohne SSML ändern möchten, können Sie die Eigenschaft für SpeechConfig mithilfe von SpeechConfig.setSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural"); festlegen.

Abonnieren von Synthesizerereignissen

Sie sollten mehr über die Sprachsyntheseverarbeitung und die Ergebnisse erfahren. Beispielsweise möchten Sie vielleicht wissen, wann der Synthesizer beginnt und anhält, oder Sie möchten wissen, welche anderen Ereignisse während der Synthese auftreten.

Wenn Sie den SpeechSynthesizer für die Sprachsynthese verwenden, können Sie die Ereignisse in dieser Tabelle abonnieren:

Ereignis BESCHREIBUNG Anwendungsfall
BookmarkReached Signalisiert, dass eine Textmarke erreicht wurde. Zum Auslösen eines Textmarke-erreicht-Ereignisses ist im SSML ein bookmark-Element erforderlich. Dieses Ereignis meldet die verstrichene Audioausgabezeit zwischen dem Beginn der Synthese und dem bookmark-Element. Die Eigenschaft Text des Ereignisses ist der Zeichenfolgenwert, den Sie im Attribut mark der Textmarke festlegen. Die bookmark-Elemente werden nicht ausgesprochen. Sie können das bookmark-Element verwenden, um benutzerdefinierte Marker in SSML einzufügen, um den Offset der einzelnen Marker im Audiostream abzurufen. Das bookmark-Element kann verwendet werden, um auf eine bestimmte Position in der Text- oder Tagsequenz zu verweisen.
SynthesisCanceled Zeigt an, dass die Sprachsynthese abgebrochen wurde. Sie können bestätigen, wann die Synthese abgebrochen wird.
SynthesisCompleted Zeigt an, dass die Sprachsynthese vollständig ist. Sie können bestätigen, wenn die Synthese abgeschlossen wurde.
SynthesisStarted Zeigt an, dass die Sprachsynthese begonnen hat. Sie können bestätigen, wenn die Synthese begonnen hat.
Synthesizing Zeigt an, dass die Sprachsynthese fortgesetzt wird. Dieses Ereignis wird jedes Mal ausgelöst, wenn das SDK einen Audioabschnitt vom Speech-Dienst empfängt. Sie können bestätigen, wenn die Synthese aktuell ausgeführt wird.
VisemeReceived Zeigt an, dass ein Visemereignis empfangen wurde. Viseme (Mundbilder) werden häufig verwendet, um die wichtigsten Gesichtsausdrücke beim Sprechen darzustellen. Sie umfassen u. a. die Position der Lippen, des Kiefers und der Zunge beim Erzeugen eines bestimmten Phonems. Sie können Viseme (Mundbilder) anwenden, um das Gesicht einer Figur zu animieren, wenn die Audiodatei abgespielt wird.
WordBoundary Zeigt an, dass eine Wortgrenze empfangen wurde. Dieses Ereignis wird am Anfang jedes neuen gesprochenen Worts, beim Erreichen von Satzzeichen und am Satzanfang ausgelöst. Das Ereignis meldet den Zeitoffset des aktuellen Worts (in Ticks) vom Anfang der Audioausgabe. Dieses Ereignis meldet außerdem die Zeichenposition im Eingabetext (oder SSML) unmittelbar vor dem Wort, das als Nächstes gesprochen wird. Dieses Ereignis wird häufig verwendet, um die relativen Positionen von Text und den entsprechenden Audiodaten abzurufen. Es kann sinnvoll sein, Informationen zu einem neuen Wort zu empfangen und dann auf der Grundlage des Timings Aktionen auszuführen. Sie können z. B. Informationen abrufen, die Sie bei der Entscheidung unterstützen, wann und wie lange Wörter beim Sprechen hervorgehoben werden sollen.

Hinweis

Ereignisse werden ausgelöst, wenn die ausgegebenen Audiodaten verfügbar werden, was schneller passiert als die Wiedergabe über ein Ausgabegerät. Der Aufrufer muss das Streaming ordnungsgemäß und in Echtzeit synchronisieren.

Dieses Beispiel zeigt, wie Ereignisse für die Sprachsynthese abonniert werden.

Wichtig

Wenn Sie einen API-Schlüssel verwenden, speichern Sie ihn an einer anderen Stelle sicher, z. B. in Azure Key Vault. Fügen Sie den API-Schlüssel nicht direkt in Ihren Code ein, und machen Sie ihn nicht öffentlich zugänglich.

Weitere Informationen zur Sicherheit von KI Services finden Sie unter Authentifizieren von Anforderungen an Azure KI Services.

Sie können die Anweisungen im Schnellstart befolgen, aber den Inhalt dieser SpeechSynthesis.java-Datei durch den folgenden Java-Code ersetzen:

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

Weitere Beispiele zur Sprachsynthese finden Sie auf GitHub.

Verwenden Sie einen benutzerdefinierten Endpunkt

Der benutzerdefinierte Endpunkt verfügt über dieselben Funktionen wie der Standardendpunkt für Sprachsynthese-Anforderungen.

Ein Unterschied besteht darin, dass die EndpointId angegeben werden muss, wenn Ihre benutzerdefinierte Stimme über das Speech SDK verwendet werden soll. Sie können mit dem Sprachsynthese-Schnellstart beginnen und dann den Code mit EndpointId und SpeechSynthesisVoiceNameaktualisieren.

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

Zum Verwenden einer benutzerdefinierten Stimme mithilfe von Speech Synthesis Markup Language (SSML) geben Sie den Modellnamen als Stimmnamen an. In diesem Beispiel wird die Stimme YourCustomVoiceName verwendet.

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

Ausführen und Verwenden eines Containers

Speech-Container bieten websocketbasierte Abfrageendpunkt-APIs, auf die über das Speech SDK und die Speech-CLI zugegriffen wird. Standardmäßig verwenden das Speech SDK und die Speech-CLI den öffentlichen Speech-Dienst. Um den Container verwenden zu können, müssen Sie die Initialisierungsmethode ändern. Verwenden Sie eine Containerhost-URL anstelle von Schlüssel und Region.

Weitere Informationen zu Containern finden Sie unter Installieren und Ausführen von Speech-Containern mit Docker.

Referenzdokumentation | Paket (npm) | Zusätzliche Beispiele auf GitHub | Quellcode der Bibliothek

In dieser Schrittanleitung werden gängige Entwurfsmuster für die Sprachsynthese vorgestellt.

Weitere Informationen zu den folgenden Bereichen finden Sie unter Was ist Sprachsynthese?.

  • Abrufen von Antworten als In-Memory-Datenströme
  • Anpassen der Abtast- und Bitrate der Ausgabe
  • Übermitteln von Syntheseanforderungen mithilfe der Markupsprache für Sprachsynthese (Speech Synthesis Markup Language, SSML)
  • Verwenden neuronaler Stimmen
  • Abonnieren von Ereignissen und ergebnisbezogenes Handeln

Auswählen von Synthesesprache und Stimme

Das Feature für die Sprachsynthese im Speech-Dienst unterstützt mehr als 400 Stimmen und über 140 Sprachen und Varianten. Sie können die vollständige Liste abrufen oder sie im Stimmkatalog ausprobieren.

Geben Sie die Sprache oder Stimme von SpeechConfig entsprechend Ihres Eingabetexts an, und verwenden Sie die festgelegte Stimme:

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 neuronalen Stimmen sind mehrsprachig und können in ihrer eigenen Sprache und in englischer Sprache sprechen. Wenn der Eingabetext auf Englisch beispielsweise „I'm excited to try text to speech“ lautet und Sie es-ES-ElviraNeural auswählen, wird der Text in englischer Sprache mit einem spanischen Akzent gesprochen.

Wenn die Stimme nicht die Sprache des Eingabetexts spricht, wird keine synthetisierte Audioausgabe vom Speech-Dienst erstellt. Eine vollständige Liste der unterstützten neuronalen Stimmen finden Sie unter Sprach- und Stimmunterstützung für den Speech-Dienst.

Hinweis

Die Standardstimme ist die erste Stimme, die pro Gebietsschema von der Stimmlisten-API zurückgegeben wird.

Die Stimme, die spricht, wird wie folgt nach ihrer Priorität bestimmt:

  • Wenn Sie weder SpeechSynthesisVoiceName noch SpeechSynthesisLanguage festlegen, spricht die Standardstimme für en-US.
  • Wenn Sie nur SpeechSynthesisLanguage festlegen, spricht die Standardstimme für das angegebene Gebietsschema.
  • Wenn sowohl SpeechSynthesisVoiceName als auch SpeechSynthesisLanguage festgelegt sind, wird die Einstellung SpeechSynthesisLanguage ignoriert. Die Stimme, die Sie mithilfe von SpeechSynthesisVoiceName angeben, spricht.
  • Wenn das Stimmelement über Speech Synthesis Markup Language (SSML) festgelegt wird, werden die Einstellungen SpeechSynthesisVoiceName und SpeechSynthesisLanguage ignoriert.

Zusammenfassend kann die Reihenfolge der Priorität wie folgt beschrieben werden:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Ergebnis
Die Standardstimme für en-US spricht.
Die Standardstimme für das angegebene Gebietsschema spricht.
Die Stimme, die Sie mithilfe von SpeechSynthesisVoiceName angeben, spricht.
Die Stimme, die Sie mithilfe von SSML angeben, spricht.

Synthetisieren von Text in Sprache

Zum Ausgeben von synthetisierter Sprache an das aktuell aktive Ausgabegerät wie etwa einen Lautsprecher instanziieren Sie AudioConfig mithilfe der statischen Funktion fromDefaultSpeakerOutput(). Ein Beispiel:

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

Wenn Sie das Programm ausführen, werden synthetisierte Audiodaten über den Lautsprecher wiedergegeben. Dieses Ergebnis ist ein gutes Beispiel für die einfachste Verwendungsmöglichkeit. Als Nächstes können Sie die Ausgabe anpassen und die Ausgabeantwort als In-Memory-Datenstrom für benutzerdefinierte Szenarios verarbeiten.

Abrufen eines Ergebnisses als In-Memory-Datenstrom

Sie können die resultierenden Audiodaten als einen In-Memory-Datenstrom verwenden, statt sie direkt in eine Datei zu schreiben. Mit einem In-Memory-Datenstrom können Sie benutzerdefiniertes Verhalten erstellen:

  • Abstrahieren des resultierenden Bytearrays als durchsuchbaren Datenstrom für benutzerdefinierte Downstreamdienste
  • Integrieren des Ergebnisses in andere APIs oder Dienste
  • Ändern der Audiodaten, Schreiben benutzerdefinierter .wav-Header und Ausführen zugehöriger Aufgaben

Sie können diese Änderung am vorherigen Beispiel vornehmen. Entfernen Sie den AudioConfig-Block, da Sie das Ausgabeverhalten ab jetzt manuell verwalten, um eine bessere Kontrolle zu erzielen. Übergeben Sie anschließend im SpeechSynthesizer-Konstruktor null für AudioConfig.

Hinweis

Wenn Sie null für AudioConfig übergeben, anstatt den Parameter wie im obigen Beispiel für die Lautsprecherausgabe wegzulassen, werden die Audiodaten nicht standardmäßig auf dem derzeit aktiven Ausgabegerät wiedergegeben.

Speichern Sie das Ergebnis in einer SpeechSynthesisResult-Variablen. Die SpeechSynthesisResult.audioData-Eigenschaft gibt einen ArrayBuffer-Wert der Ausgabedaten zurück, den Standard-Browserstreamtyp. Konvertieren Sie ArrayBuffer für serverseitigen Code in einen Pufferstream.

Der folgende Code funktioniert für die Clientseite:

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

Sie können mit dem resultierenden ArrayBuffer-Objekt ein beliebiges benutzerdefiniertes Verhalten implementieren. ArrayBuffer ist ein gängiger Typ, der in einem Browser empfangen und in diesem Format wiedergegeben wird.

Wenn Sie in serverbasiertem Code mit den Daten als Stream arbeiten müssen, müssen Sie das ArrayBuffer-Objekt in einen Stream konvertieren:

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

Anpassen des Audioformats

Sie können die Attribute der Audioausgabe anpassen, z. B.:

  • Audiodateityp
  • Samplingrate
  • Bittiefe

Zum Ändern des Audioformats wenden Sie die Eigenschaft speechSynthesisOutputFormat auf das Objekt SpeechConfig an. Diese Eigenschaft erwartet eine enum-Instanz vom Typ SpeechSynthesisOutputFormat. Verwenden Sie enum, um das Ausgabeformat auszuwählen. Informationen zu den verfügbaren Formaten finden Sie in der Liste der Audioformate.

Abhängig von Ihren Anforderungen stehen Ihnen verschiedene Optionen für unterschiedliche Dateitypen zur Verfügung. Rohformate wie Raw24Khz16BitMonoPcm enthalten gemäß Definition keine Audioheader. Verwenden Sie Rohformate nur in den folgenden Situationen:

  • Sie wissen, dass Ihre Downstreamimplementierung einen unformatierten Bitstream decodieren kann.
  • Sie planen, Header basierend auf Faktoren wie Bittiefe, Abtastrate und Anzahl von Kanälen manuell zu erstellen.

In diesem Beispiel wird das High-Fidelity-RIFF-Format Riff24Khz16BitMonoPcm angegeben, indem speechSynthesisOutputFormat für das SpeechConfig-Objekt festgelegt wird. Rufen Sie die ArrayBuffer-Audiodaten ähnlich wie im Beispiel im vorherigen Abschnitt ab, und interagieren Sie damit.

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

Verwenden von SSML zum Anpassen von Sprachmerkmalen

Mit SSML können Sie die Tonhöhe, Aussprache, Sprechgeschwindigkeit, Lautstärke und andere Aspekte der Ausgabe der Sprachsynthese optimieren, indem Sie Ihre Anforderungen per XML-Schema übermitteln. Dieser Abschnitt enthält ein Beispiel für das Ändern der Stimme. Weitere Informationen finden Sie unter Übersicht über Speech Synthesis Markup Language.

Wenn Sie SSML für die Anpassung nutzen möchten, nehmen Sie eine geringfügige Änderung vor, um die Stimme zu wechseln.

  1. Erstellen Sie im Stammverzeichnis des Projekts eine neue XML-Datei für die SSML-Konfiguration.

    <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 diesem Beispiel wird ssml.xml verwendet. Das Stammelement ist immer <speak>. Indem Sie den Text in einem <voice>-Element umschließen, können Sie die Stimme mit dem name-Parameter ändern. Eine vollständige Liste der unterstützten neuronalen Stimmen finden Sie unter Unterstützte Sprachen.

  2. Ändern Sie die Anforderung der Sprachsynthese so, dass darin auf Ihre XML-Datei verwiesen wird. Die Anforderung bleibt größtenteils unverändert, aber Sie verwenden nun speakSsmlAsync() anstelle von speakTextAsync(). Diese Funktion erwartet eine XML-Zeichenfolge. Erstellen Sie eine Funktion, um eine XML-Datei zu laden und als Zeichenfolge zurückzugeben:

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

    Weitere Informationen zu readFileSync finden Sie unter Node.js-Dateisystem.

    Das resultierende Objekt stimmt genau mit den Objekten in den vorherigen Beispielen überein:

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

Hinweis

Wenn Sie die Stimme ohne SSML ändern möchten, können Sie die Eigenschaft für SpeechConfig mithilfe von SpeechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural"; festlegen.

Abonnieren von Synthesizerereignissen

Sie sollten mehr über die Sprachsyntheseverarbeitung und die Ergebnisse erfahren. Beispielsweise möchten Sie vielleicht wissen, wann der Synthesizer beginnt und anhält, oder Sie möchten wissen, welche anderen Ereignisse während der Synthese auftreten.

Wenn Sie den SpeechSynthesizer für die Sprachsynthese verwenden, können Sie die Ereignisse in dieser Tabelle abonnieren:

Ereignis BESCHREIBUNG Anwendungsfall
BookmarkReached Signalisiert, dass eine Textmarke erreicht wurde. Zum Auslösen eines Textmarke-erreicht-Ereignisses ist im SSML ein bookmark-Element erforderlich. Dieses Ereignis meldet die verstrichene Audioausgabezeit zwischen dem Beginn der Synthese und dem bookmark-Element. Die Eigenschaft Text des Ereignisses ist der Zeichenfolgenwert, den Sie im Attribut mark der Textmarke festlegen. Die bookmark-Elemente werden nicht ausgesprochen. Sie können das bookmark-Element verwenden, um benutzerdefinierte Marker in SSML einzufügen, um den Offset der einzelnen Marker im Audiostream abzurufen. Das bookmark-Element kann verwendet werden, um auf eine bestimmte Position in der Text- oder Tagsequenz zu verweisen.
SynthesisCanceled Zeigt an, dass die Sprachsynthese abgebrochen wurde. Sie können bestätigen, wann die Synthese abgebrochen wird.
SynthesisCompleted Zeigt an, dass die Sprachsynthese vollständig ist. Sie können bestätigen, wenn die Synthese abgeschlossen wurde.
SynthesisStarted Zeigt an, dass die Sprachsynthese begonnen hat. Sie können bestätigen, wenn die Synthese begonnen hat.
Synthesizing Zeigt an, dass die Sprachsynthese fortgesetzt wird. Dieses Ereignis wird jedes Mal ausgelöst, wenn das SDK einen Audioabschnitt vom Speech-Dienst empfängt. Sie können bestätigen, wenn die Synthese aktuell ausgeführt wird.
VisemeReceived Zeigt an, dass ein Visemereignis empfangen wurde. Viseme (Mundbilder) werden häufig verwendet, um die wichtigsten Gesichtsausdrücke beim Sprechen darzustellen. Sie umfassen u. a. die Position der Lippen, des Kiefers und der Zunge beim Erzeugen eines bestimmten Phonems. Sie können Viseme (Mundbilder) anwenden, um das Gesicht einer Figur zu animieren, wenn die Audiodatei abgespielt wird.
WordBoundary Zeigt an, dass eine Wortgrenze empfangen wurde. Dieses Ereignis wird am Anfang jedes neuen gesprochenen Worts, beim Erreichen von Satzzeichen und am Satzanfang ausgelöst. Das Ereignis meldet den Zeitoffset des aktuellen Worts (in Ticks) vom Anfang der Audioausgabe. Dieses Ereignis meldet außerdem die Zeichenposition im Eingabetext (oder SSML) unmittelbar vor dem Wort, das als Nächstes gesprochen wird. Dieses Ereignis wird häufig verwendet, um die relativen Positionen von Text und den entsprechenden Audiodaten abzurufen. Es kann sinnvoll sein, Informationen zu einem neuen Wort zu empfangen und dann auf der Grundlage des Timings Aktionen auszuführen. Sie können z. B. Informationen abrufen, die Sie bei der Entscheidung unterstützen, wann und wie lange Wörter beim Sprechen hervorgehoben werden sollen.

Hinweis

Ereignisse werden ausgelöst, wenn die ausgegebenen Audiodaten verfügbar werden, was schneller passiert als die Wiedergabe über ein Ausgabegerät. Der Aufrufer muss das Streaming ordnungsgemäß und in Echtzeit synchronisieren.

Dieses Beispiel zeigt, wie Ereignisse für die Sprachsynthese abonniert werden.

Wichtig

Wenn Sie einen API-Schlüssel verwenden, speichern Sie ihn an einer anderen Stelle sicher, z. B. in Azure Key Vault. Fügen Sie den API-Schlüssel nicht direkt in Ihren Code ein, und machen Sie ihn nicht öffentlich zugänglich.

Weitere Informationen zur Sicherheit von KI Services finden Sie unter Authentifizieren von Anforderungen an Azure KI Services.

Sie können die Anweisungen im Schnellstart befolgen, aber den Inhalt dieser SpeechSynthesis.js-Datei durch den folgenden JavaScript-Code ersetzen.

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

Weitere Beispiele zur Sprachsynthese finden Sie auf GitHub.

Ausführen und Verwenden eines Containers

Speech-Container bieten websocketbasierte Abfrageendpunkt-APIs, auf die über das Speech SDK und die Speech-CLI zugegriffen wird. Standardmäßig verwenden das Speech SDK und die Speech-CLI den öffentlichen Speech-Dienst. Um den Container verwenden zu können, müssen Sie die Initialisierungsmethode ändern. Verwenden Sie eine Containerhost-URL anstelle von Schlüssel und Region.

Weitere Informationen zu Containern finden Sie unter Installieren und Ausführen von Speech-Containern mit Docker.

Referenzdokumentation | Paket (Download) | Zusätzliche Beispiele auf GitHub

In dieser Schrittanleitung werden gängige Entwurfsmuster für die Sprachsynthese vorgestellt.

Weitere Informationen zu den folgenden Bereichen finden Sie unter Was ist Sprachsynthese?.

  • Abrufen von Antworten als In-Memory-Datenströme
  • Anpassen der Abtast- und Bitrate der Ausgabe
  • Übermitteln von Syntheseanforderungen mithilfe der Markupsprache für Sprachsynthese (Speech Synthesis Markup Language, SSML)
  • Verwenden neuronaler Stimmen
  • Abonnieren von Ereignissen und ergebnisbezogenes Handeln

Voraussetzungen

Installieren des Speech SDK und der Beispiele

Das Repository Azure-Samples/cognitive-services-speech-sdk enthält Beispiele in Objective-C für iOS und Mac. Wählen Sie einen Link aus, um Installationsanweisungen für die einzelnen Beispiele anzuzeigen:

Verwenden Sie einen benutzerdefinierten Endpunkt

Der benutzerdefinierte Endpunkt verfügt über dieselben Funktionen wie der Standardendpunkt für Sprachsynthese-Anforderungen.

Ein Unterschied besteht darin, dass die EndpointId angegeben werden muss, wenn Ihre benutzerdefinierte Stimme über das Speech SDK verwendet werden soll. Sie können mit dem Sprachsynthese-Schnellstart beginnen und dann den Code mit EndpointId und SpeechSynthesisVoiceNameaktualisieren.

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

Zum Verwenden einer benutzerdefinierten Stimme mithilfe von Speech Synthesis Markup Language (SSML) geben Sie den Modellnamen als Stimmnamen an. In diesem Beispiel wird die Stimme YourCustomVoiceName verwendet.

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

Ausführen und Verwenden eines Containers

Speech-Container bieten websocketbasierte Abfrageendpunkt-APIs, auf die über das Speech SDK und die Speech-CLI zugegriffen wird. Standardmäßig verwenden das Speech SDK und die Speech-CLI den öffentlichen Speech-Dienst. Um den Container verwenden zu können, müssen Sie die Initialisierungsmethode ändern. Verwenden Sie eine Containerhost-URL anstelle von Schlüssel und Region.

Weitere Informationen zu Containern finden Sie unter Installieren und Ausführen von Speech-Containern mit Docker.

Referenzdokumentation | Paket (Download) | Zusätzliche Beispiele auf GitHub

In dieser Schrittanleitung werden gängige Entwurfsmuster für die Sprachsynthese vorgestellt.

Weitere Informationen zu den folgenden Bereichen finden Sie unter Was ist Sprachsynthese?.

  • Abrufen von Antworten als In-Memory-Datenströme
  • Anpassen der Abtast- und Bitrate der Ausgabe
  • Übermitteln von Syntheseanforderungen mithilfe der Markupsprache für Sprachsynthese (Speech Synthesis Markup Language, SSML)
  • Verwenden neuronaler Stimmen
  • Abonnieren von Ereignissen und ergebnisbezogenes Handeln

Voraussetzungen

Installieren des Speech SDK und der Beispiele

Das Repository Azure-Samples/cognitive-services-speech-sdk enthält Beispiele in Swift für iOS und Mac. Wählen Sie einen Link aus, um Installationsanweisungen für die einzelnen Beispiele anzuzeigen:

Ausführen und Verwenden eines Containers

Speech-Container bieten websocketbasierte Abfrageendpunkt-APIs, auf die über das Speech SDK und die Speech-CLI zugegriffen wird. Standardmäßig verwenden das Speech SDK und die Speech-CLI den öffentlichen Speech-Dienst. Um den Container verwenden zu können, müssen Sie die Initialisierungsmethode ändern. Verwenden Sie eine Containerhost-URL anstelle von Schlüssel und Region.

Weitere Informationen zu Containern finden Sie unter Installieren und Ausführen von Speech-Containern mit Docker.

Referenzdokumentation | Paket (PyPi) | Zusätzliche Beispiele auf GitHub

In dieser Schrittanleitung werden gängige Entwurfsmuster für die Sprachsynthese vorgestellt.

Weitere Informationen zu den folgenden Bereichen finden Sie unter Was ist Sprachsynthese?.

  • Abrufen von Antworten als In-Memory-Datenströme
  • Anpassen der Abtast- und Bitrate der Ausgabe
  • Übermitteln von Syntheseanforderungen mithilfe der Markupsprache für Sprachsynthese (Speech Synthesis Markup Language, SSML)
  • Verwenden neuronaler Stimmen
  • Abonnieren von Ereignissen und ergebnisbezogenes Handeln

Auswählen von Synthesesprache und Stimme

Das Feature für die Sprachsynthese im Speech-Dienst unterstützt mehr als 400 Stimmen und über 140 Sprachen und Varianten. Sie können die vollständige Liste abrufen oder sie im Stimmkatalog ausprobieren.

Geben Sie die Sprache oder Stimme von SpeechConfig entsprechend Ihres Eingabetexts an, und verwenden Sie die festgelegte Stimme:

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

Alle neuronalen Stimmen sind mehrsprachig und können in ihrer eigenen Sprache und in englischer Sprache sprechen. Wenn der Eingabetext auf Englisch beispielsweise „I'm excited to try text to speech“ lautet und Sie es-ES-ElviraNeural auswählen, wird der Text in englischer Sprache mit einem spanischen Akzent gesprochen.

Wenn die Stimme nicht die Sprache des Eingabetexts spricht, wird keine synthetisierte Audioausgabe vom Speech-Dienst erstellt. Eine vollständige Liste der unterstützten neuronalen Stimmen finden Sie unter Sprach- und Stimmunterstützung für den Speech-Dienst.

Hinweis

Die Standardstimme ist die erste Stimme, die pro Gebietsschema von der Stimmlisten-API zurückgegeben wird.

Die Stimme, die spricht, wird wie folgt nach ihrer Priorität bestimmt:

  • Wenn Sie weder SpeechSynthesisVoiceName noch SpeechSynthesisLanguage festlegen, spricht die Standardstimme für en-US.
  • Wenn Sie nur SpeechSynthesisLanguage festlegen, spricht die Standardstimme für das angegebene Gebietsschema.
  • Wenn sowohl SpeechSynthesisVoiceName als auch SpeechSynthesisLanguage festgelegt sind, wird die Einstellung SpeechSynthesisLanguage ignoriert. Die Stimme, die Sie mithilfe von SpeechSynthesisVoiceName angeben, spricht.
  • Wenn das Stimmelement über Speech Synthesis Markup Language (SSML) festgelegt wird, werden die Einstellungen SpeechSynthesisVoiceName und SpeechSynthesisLanguage ignoriert.

Zusammenfassend kann die Reihenfolge der Priorität wie folgt beschrieben werden:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Ergebnis
Die Standardstimme für en-US spricht.
Die Standardstimme für das angegebene Gebietsschema spricht.
Die Stimme, die Sie mithilfe von SpeechSynthesisVoiceName angeben, spricht.
Die Stimme, die Sie mithilfe von SSML angeben, spricht.

Synthetisieren von Sprache in eine Datei

Erstellen Sie ein SpeechSynthesizer-Objekt. Dieses Objekt führt die Konvertierungen von Text in Sprache und Ausgaben an Lautsprecher, in Dateien oder andere Ausgabestreams aus. SpeechSynthesizer akzeptiert folgende Parameter:

  • Das SpeechConfig-Objekt, das Sie im vorherigen Schritt erstellt haben
  • Ein AudioOutputConfig-Objekt, das angibt, wie Ausgabeergebnisse verarbeitet werden sollen
  1. Erstellen Sie eine AudioOutputConfig-Instanz, um die Ausgabe mithilfe des Konstruktorparameters filename automatisch in eine WAV-Datei zu schreiben:

    audio_config = speechsdk.audio.AudioOutputConfig(filename="path/to/write/file.wav")
    
  2. Instanziieren Sie SpeechSynthesizer, indem Sie die speech_config- und audio_config-Objekte als Parameter übergeben. Um Sprache zu synthetisieren und in eine Datei zu schreiben, führen Sie speak_text_async() mit einer Textzeichenfolge aus.

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

Wenn Sie das Programm ausführen, wird eine synthetisierte WAV-Datei erstellt, die an den von Ihnen angegebenen Speicherort geschrieben wird. Dieses Ergebnis ist ein gutes Beispiel für die einfachste Verwendungsmöglichkeit. Als Nächstes können Sie die Ausgabe anpassen und die Ausgabeantwort als In-Memory-Datenstrom für benutzerdefinierte Szenarios verarbeiten.

Synthetisieren der Lautsprecherausgabe

Zum Ausgeben von synthetisierter Sprache auf dem aktuell aktiven Ausgabegerät wie einem Lautsprecher legen Sie den Parameter use_default_speaker fest, wenn Sie die AudioOutputConfig-Instanz erstellen. Ein Beispiel:

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

Abrufen eines Ergebnisses als In-Memory-Datenstrom

Sie können die resultierenden Audiodaten als einen In-Memory-Datenstrom verwenden, statt sie direkt in eine Datei zu schreiben. Mit einem In-Memory-Datenstrom können Sie benutzerdefiniertes Verhalten erstellen:

  • Abstrahieren des resultierenden Bytearrays als durchsuchbaren Datenstrom für benutzerdefinierte Downstreamdienste
  • Integrieren des Ergebnisses in andere APIs oder Dienste
  • Ändern Sie die Audiodaten, schreiben Sie benutzerdefinierte WAV-Header, und erledigen Sie zugehörige Aufgaben.

Sie können diese Änderung am vorherigen Beispiel vornehmen. Entfernen Sie zunächst AudioConfig, da Sie das Ausgabeverhalten ab jetzt manuell verwalten, um eine bessere Kontrolle zu erzielen. Übergeben Sie im SpeechSynthesizer-Konstruktor None für AudioConfig.

Hinweis

Wenn Sie None für AudioConfig übergeben, anstatt den Parameter wie im obigen Beispiel für die Lautsprecherausgabe wegzulassen, werden die Audiodaten nicht standardmäßig auf dem derzeit aktiven Ausgabegerät wiedergegeben.

Speichern Sie das Ergebnis in einer SpeechSynthesisResult-Variablen. Die audio_data-Eigenschaft enthält ein bytes-Objekt der Ausgabedaten. Sie können dieses Objekt manuell nutzen oder die AudioDataStream-Klasse verwenden, um den InMemory-Datenstrom zu verwalten.

In diesem Beispiel verwenden Sie den Konstruktor AudioDataStream, um einen Datenstrom aus dem Ergebnis abzurufen:

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

Nun können Sie mit dem resultierenden stream-Objekt ein beliebiges benutzerdefiniertes Verhalten implementieren.

Anpassen des Audioformats

Sie können die Attribute der Audioausgabe anpassen, z. B.:

  • Audiodateityp
  • Samplingrate
  • Bittiefe

Zum Ändern des Audioformats wenden Sie die Funktion set_speech_synthesis_output_format() auf das Objekt SpeechConfig an. Diese Funktion erwartet eine enum-Instanz vom Typ SpeechSynthesisOutputFormat. Verwenden Sie enum, um das Ausgabeformat auszuwählen. Informationen zu den verfügbaren Formaten finden Sie in der Liste der Audioformate.

Abhängig von Ihren Anforderungen stehen Ihnen verschiedene Optionen für unterschiedliche Dateitypen zur Verfügung. Rohformate wie Raw24Khz16BitMonoPcm enthalten gemäß Definition keine Audioheader. Verwenden Sie Rohformate nur in den folgenden Situationen:

  • Sie wissen, dass Ihre Downstreamimplementierung einen unformatierten Bitstream decodieren kann.
  • Sie planen, Header basierend auf Faktoren wie Bittiefe, Abtastrate und Anzahl von Kanälen manuell zu erstellen.

In diesem Beispiel wird das High-Fidelity-RIFF-Format Riff24Khz16BitMonoPcm angegeben, indem SpeechSynthesisOutputFormat für das SpeechConfig-Objekt festgelegt wird. Ähnlich wie im Beispiel im vorherigen Abschnitt nutzen Sie AudioDataStream, um einen InMemory-Datenstrom des Ergebnisses zu erhalten, das Sie anschließend in eine Datei schreiben.

speech_config.set_speech_synthesis_output_format(speechsdk.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm)
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)

speech_synthesis_result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
stream = speechsdk.AudioDataStream(speech_synthesis_result)
stream.save_to_wav_file("path/to/write/file.wav")

Wenn Sie das Programm ausführen, schreibt es eine WAV-Datei in den angegebenen Pfad.

Verwenden von SSML zum Anpassen von Sprachmerkmalen

Mit SSML können Sie die Tonhöhe, Aussprache, Sprechgeschwindigkeit, Lautstärke und andere Aspekte der Ausgabe der Sprachsynthese optimieren, indem Sie Ihre Anforderungen per XML-Schema übermitteln. Dieser Abschnitt enthält ein Beispiel für das Ändern der Stimme. Weitere Informationen finden Sie unter Übersicht über Speech Synthesis Markup Language.

Wenn Sie SSML für die Anpassung nutzen möchten, nehmen Sie eine geringfügige Änderung vor, um die Stimme zu wechseln.

  1. Erstellen Sie im Stammverzeichnis des Projekts eine neue XML-Datei für die SSML-Konfiguration.

    <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 diesem Beispiel ist die Datei ssml.xml. Das Stammelement ist immer <speak>. Indem Sie den Text in einem <voice>-Element umschließen, können Sie die Stimme mit dem name-Parameter ändern. Eine vollständige Liste der unterstützten neuronalen Stimmen finden Sie unter Unterstützte Sprachen.

  2. Ändern Sie die Anforderung der Sprachsynthese so, dass darin auf Ihre XML-Datei verwiesen wird. Die Anforderung ist größtenteils identisch. Anstatt die speak_text_async()-Funktion zu verwenden, verwenden Sie speak_ssml_async(). Diese Funktion erwartet eine XML-Zeichenfolge. Lesen Sie zunächst Ihre SSML-Konfiguration als Zeichenfolge. Ab diesem Punkt stimmt das resultierende Objekt genau mit den Objekten in den vorherigen Beispielen überein.

    Hinweis

    Wenn ssml_string am Anfang der Zeichenfolge  enthält, müssen Sie das BOM-Format entfernen, andernfalls gibt der Dienst einen Fehler zurück. Hierzu müssen Sie den Parameter encoding wie folgt festlegen: open("ssml.xml", "r", encoding="utf-8-sig").

    speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)
    
    ssml_string = open("ssml.xml", "r").read()
    speech_synthesis_result = speech_synthesizer.speak_ssml_async(ssml_string).get()
    
    stream = speechsdk.AudioDataStream(speech_synthesis_result)
    stream.save_to_wav_file("path/to/write/file.wav")
    

Hinweis

Wenn Sie die Stimme ohne SSML ändern möchten, können Sie die Eigenschaft für SpeechConfig mithilfe von speech_config.speech_synthesis_voice_name = "en-US-AvaMultilingualNeural" festlegen.

Abonnieren von Synthesizerereignissen

Sie sollten mehr über die Sprachsyntheseverarbeitung und die Ergebnisse erfahren. Beispielsweise möchten Sie vielleicht wissen, wann der Synthesizer beginnt und anhält, oder Sie möchten wissen, welche anderen Ereignisse während der Synthese auftreten.

Wenn Sie den SpeechSynthesizer für die Sprachsynthese verwenden, können Sie die Ereignisse in dieser Tabelle abonnieren:

Ereignis BESCHREIBUNG Anwendungsfall
BookmarkReached Signalisiert, dass eine Textmarke erreicht wurde. Zum Auslösen eines Textmarke-erreicht-Ereignisses ist im SSML ein bookmark-Element erforderlich. Dieses Ereignis meldet die verstrichene Audioausgabezeit zwischen dem Beginn der Synthese und dem bookmark-Element. Die Eigenschaft Text des Ereignisses ist der Zeichenfolgenwert, den Sie im Attribut mark der Textmarke festlegen. Die bookmark-Elemente werden nicht ausgesprochen. Sie können das bookmark-Element verwenden, um benutzerdefinierte Marker in SSML einzufügen, um den Offset der einzelnen Marker im Audiostream abzurufen. Das bookmark-Element kann verwendet werden, um auf eine bestimmte Position in der Text- oder Tagsequenz zu verweisen.
SynthesisCanceled Zeigt an, dass die Sprachsynthese abgebrochen wurde. Sie können bestätigen, wann die Synthese abgebrochen wird.
SynthesisCompleted Zeigt an, dass die Sprachsynthese vollständig ist. Sie können bestätigen, wenn die Synthese abgeschlossen wurde.
SynthesisStarted Zeigt an, dass die Sprachsynthese begonnen hat. Sie können bestätigen, wenn die Synthese begonnen hat.
Synthesizing Zeigt an, dass die Sprachsynthese fortgesetzt wird. Dieses Ereignis wird jedes Mal ausgelöst, wenn das SDK einen Audioabschnitt vom Speech-Dienst empfängt. Sie können bestätigen, wenn die Synthese aktuell ausgeführt wird.
VisemeReceived Zeigt an, dass ein Visemereignis empfangen wurde. Viseme (Mundbilder) werden häufig verwendet, um die wichtigsten Gesichtsausdrücke beim Sprechen darzustellen. Sie umfassen u. a. die Position der Lippen, des Kiefers und der Zunge beim Erzeugen eines bestimmten Phonems. Sie können Viseme (Mundbilder) anwenden, um das Gesicht einer Figur zu animieren, wenn die Audiodatei abgespielt wird.
WordBoundary Zeigt an, dass eine Wortgrenze empfangen wurde. Dieses Ereignis wird am Anfang jedes neuen gesprochenen Worts, beim Erreichen von Satzzeichen und am Satzanfang ausgelöst. Das Ereignis meldet den Zeitoffset des aktuellen Worts (in Ticks) vom Anfang der Audioausgabe. Dieses Ereignis meldet außerdem die Zeichenposition im Eingabetext (oder SSML) unmittelbar vor dem Wort, das als Nächstes gesprochen wird. Dieses Ereignis wird häufig verwendet, um die relativen Positionen von Text und den entsprechenden Audiodaten abzurufen. Es kann sinnvoll sein, Informationen zu einem neuen Wort zu empfangen und dann auf der Grundlage des Timings Aktionen auszuführen. Sie können z. B. Informationen abrufen, die Sie bei der Entscheidung unterstützen, wann und wie lange Wörter beim Sprechen hervorgehoben werden sollen.

Hinweis

Ereignisse werden ausgelöst, wenn die ausgegebenen Audiodaten verfügbar werden, was schneller passiert als die Wiedergabe über ein Ausgabegerät. Der Aufrufer muss das Streaming ordnungsgemäß und in Echtzeit synchronisieren.

Dieses Beispiel zeigt, wie Ereignisse für die Sprachsynthese abonniert werden.

Wichtig

Wenn Sie einen API-Schlüssel verwenden, speichern Sie ihn an einer anderen Stelle sicher, z. B. in Azure Key Vault. Fügen Sie den API-Schlüssel nicht direkt in Ihren Code ein, und machen Sie ihn nicht öffentlich zugänglich.

Weitere Informationen zur Sicherheit von KI Services finden Sie unter Authentifizieren von Anforderungen an Azure KI Services.

Sie können die Anweisungen im Schnellstart befolgen, aber den Inhalt dieser speech-synthesis.py-Datei durch den folgenden Python-Code ersetzen:

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

Weitere Beispiele zur Sprachsynthese finden Sie auf GitHub.

Verwenden Sie einen benutzerdefinierten Endpunkt

Der benutzerdefinierte Endpunkt verfügt über dieselben Funktionen wie der Standardendpunkt für Sprachsynthese-Anforderungen.

Ein Unterschied besteht darin, dass die endpoint_id angegeben werden muss, wenn Ihre benutzerdefinierte Stimme über das Speech SDK verwendet werden soll. Sie können mit dem Sprachsynthese-Schnellstart beginnen und dann den Code mit endpoint_id und speech_synthesis_voice_nameaktualisieren.

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"

Zum Verwenden einer benutzerdefinierten Stimme mithilfe von Speech Synthesis Markup Language (SSML) geben Sie den Modellnamen als Stimmnamen an. In diesem Beispiel wird die Stimme YourCustomVoiceName verwendet.

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

Ausführen und Verwenden eines Containers

Speech-Container bieten websocketbasierte Abfrageendpunkt-APIs, auf die über das Speech SDK und die Speech-CLI zugegriffen wird. Standardmäßig verwenden das Speech SDK und die Speech-CLI den öffentlichen Speech-Dienst. Um den Container verwenden zu können, müssen Sie die Initialisierungsmethode ändern. Verwenden Sie eine Containerhost-URL anstelle von Schlüssel und Region.

Weitere Informationen zu Containern finden Sie unter Installieren und Ausführen von Speech-Containern mit Docker.

REST-API-Referenz zur Spracherkennung | REST-API-Referenz zur Spracherkennung für kurze Audiodaten | Zusätzliche Beispiele auf GitHub

In dieser Schrittanleitung werden gängige Entwurfsmuster für die Sprachsynthese vorgestellt.

Weitere Informationen zu den folgenden Bereichen finden Sie unter Was ist Sprachsynthese?.

  • Abrufen von Antworten als In-Memory-Datenströme
  • Anpassen der Abtast- und Bitrate der Ausgabe
  • Übermitteln von Syntheseanforderungen mithilfe der Markupsprache für Sprachsynthese (Speech Synthesis Markup Language, SSML)
  • Verwenden neuronaler Stimmen
  • Abonnieren von Ereignissen und ergebnisbezogenes Handeln

Voraussetzungen

Konvertieren von Text in Sprache

Führen Sie an der Eingabeaufforderung den folgenden Befehl aus. Fügen Sie diese Werte in den Befehl ein:

  • Ihr Speech-Ressourcenschlüssel
  • Ihre Speech-Ressourcenregion

Sie können ggf. auch die folgenden Werte ändern:

  • Headerwert X-Microsoft-OutputFormat, mit dem das Format der Audioausgabe gesteuert wird. Eine Liste mit den unterstützten Formaten für die Audioausgabe finden Sie in der Referenz zur Sprachsynthese-REST-API.
  • Die Stimme für die Ausgabe. Informationen zum Abrufen einer Liste der für Ihren Speech-Dienstendpunkt verfügbaren Stimmen finden Sie bei der Voice List-API.
  • Die Ausgabedatei. In diesem Beispiel leiten wir die Antwort des Servers an eine Datei mit dem Namen output.mp3 weiter.
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 dieser Schrittanleitung werden gängige Entwurfsmuster für die Sprachsynthese vorgestellt.

Weitere Informationen zu den folgenden Bereichen finden Sie unter Was ist Sprachsynthese?.

  • Abrufen von Antworten als In-Memory-Datenströme
  • Anpassen der Abtast- und Bitrate der Ausgabe
  • Übermitteln von Syntheseanforderungen mithilfe der Markupsprache für Sprachsynthese (Speech Synthesis Markup Language, SSML)
  • Verwenden neuronaler Stimmen
  • Abonnieren von Ereignissen und ergebnisbezogenes Handeln

Voraussetzungen

Herunterladen und installieren

Befolgen Sie diese Schritte und lesen Sie die Schnellstartanleitung für Speech CLI, um weitere Anforderungen für Ihre Plattform zu erfahren.

  1. Führen Sie den folgenden .NET CLI-Befehl aus, um die Speech CLI zu installieren:

    dotnet tool install --global Microsoft.CognitiveServices.Speech.CLI
    
  2. Führen Sie die folgenden Befehle aus, um Ihren Speech-Ressourcenschlüssel und Ihre Region zu konfigurieren. Ersetzen Sie SUBSCRIPTION-KEY durch den Schlüssel Ihrer Speech-Ressource und REGION durch die Region Ihrer Speech-Ressource.

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

Synthetisieren von Sprache über einen Lautsprecher

Sie sind jetzt bereit, die Speech-Befehlszeilenschnittstelle auszuführen, um aus Text Sprache zu synthetisieren.

  • Navigieren Sie in einem Konsolenfenster zu dem Verzeichnis, das die Binärdatei der Speech-CLI enthält. Führen Sie dann den folgenden Befehl aus:

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

Die Speech-CLI gibt natürlichsprachliches Englisch über den Lautsprecher des Computers aus.

Synthetisieren von Sprache in eine Datei

  • Führen Sie den folgenden Befehl aus, um die Ausgabe über den Lautsprecher in eine WAV-Datei zu ändern:

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

Die Speech-CLI gibt natürlichsprachliches Englisch in die Audiodatei greetings.wav aus.

Ausführen und Verwenden eines Containers

Speech-Container bieten websocketbasierte Abfrageendpunkt-APIs, auf die über das Speech SDK und die Speech-CLI zugegriffen wird. Standardmäßig verwenden das Speech SDK und die Speech-CLI den öffentlichen Speech-Dienst. Um den Container verwenden zu können, müssen Sie die Initialisierungsmethode ändern. Verwenden Sie eine Containerhost-URL anstelle von Schlüssel und Region.

Weitere Informationen zu Containern finden Sie unter Installieren und Ausführen von Speech-Containern mit Docker.

Nächste Schritte